diff -ur --new-file old/linux/drivers/atm/eni.c new/linux/drivers/atm/eni.c --- old/linux/drivers/atm/eni.c Fri Dec 20 21:56:26 1996 +++ new/linux/drivers/atm/eni.c Fri Dec 20 21:56:53 1996 @@ -921,13 +921,6 @@ static enum enq_res do_tx(struct sk_buff *skb) { - /* @@@ - * This static var may break with multiple adapters if multiple - * instances of do_tx (for different cards) are active concurrently. - * Moving it to eni_dev may cause a performance drop, so I'm avoiding - * that for now. - */ - static unsigned long dma[TX_DMA_BUF*2]; struct atm_vcc *vcc; struct eni_dev *eni_dev; struct eni_vcc *eni_vcc; @@ -997,25 +990,25 @@ } /* prepare DMA queue entries */ j = 0; - dma[j++] = (((tx->tx_pos+TX_DESCR_SIZE) & (tx->words-1)) << + eni_dev->dma[j++] = (((tx->tx_pos+TX_DESCR_SIZE) & (tx->words-1)) << MID_DMA_COUNT_SHIFT) | (tx->index << MID_DMA_CHAN_SHIFT) | MID_DT_JK; j++; if (!skb->atm.iovcnt) if (aal5) - put_dma(tx->index,dma,&j,(unsigned long) skb->data, - skb->len); - else put_dma(tx->index,dma,&j,(unsigned long) skb->data+4, - skb->len-4); + put_dma(tx->index,eni_dev->dma,&j, + (unsigned long) skb->data,skb->len); + else put_dma(tx->index,eni_dev->dma,&j, + (unsigned long) skb->data+4,skb->len-4); else { DPRINTK("doing direct send\n"); for (i = 0; i < skb->atm.iovcnt; i++) - put_dma(tx->index,dma,&j,(unsigned long) + put_dma(tx->index,eni_dev->dma,&j,(unsigned long) ((struct iovec *) skb->data)[i].iov_base, ((struct iovec *) skb->data)[i].iov_len); } /* JK for AAL5 trailer - AAL0 doesn't need it, but who cares ... */ - dma[j++] = (((tx->tx_pos+size) & (tx->words-1)) << + eni_dev->dma[j++] = (((tx->tx_pos+size) & (tx->words-1)) << MID_DMA_COUNT_SHIFT) | (tx->index << MID_DMA_CHAN_SHIFT) | MID_DMA_END | MID_DT_JK; j++; @@ -1034,8 +1027,8 @@ skb->len; j = j >> 1; for (i = 0; i < j; i++) { - eni_dev->tx_dma[dma_wr*2] = dma[i*2]; - eni_dev->tx_dma[dma_wr*2+1] = dma[i*2+1]; + eni_dev->tx_dma[dma_wr*2] = eni_dev->dma[i*2]; + eni_dev->tx_dma[dma_wr*2+1] = eni_dev->dma[i*2+1]; dma_wr = (dma_wr+1) & (NR_DMA_TX-1); } skb->atm.pos = tx->tx_pos; diff -ur --new-file old/linux/drivers/atm/eni.h new/linux/drivers/atm/eni.h --- old/linux/drivers/atm/eni.h Fri Dec 20 21:56:26 1996 +++ new/linux/drivers/atm/eni.h Fri Dec 20 21:56:53 1996 @@ -80,6 +80,7 @@ struct sk_buff_head tx_queue; /* PDUs currently being TX DMAed*/ struct wait_queue *tx_wait; /* for close */ int tx_bw; /* remaining bandwidth */ + unsigned long dma[TX_DMA_BUF*2]; /* DMA request scratch area */ /*-------------------------------- RX part */ unsigned long serv_read; /* host service read index */ struct atm_vcc *fast,*last_fast;/* queues of VCCs with pending PDUs */ diff -ur --new-file old/linux/drivers/atm/nicstar.c new/linux/drivers/atm/nicstar.c --- old/linux/drivers/atm/nicstar.c Fri Dec 20 21:56:26 1996 +++ new/linux/drivers/atm/nicstar.c Fri Dec 20 21:56:53 1996 @@ -26,7 +26,7 @@ * */ -static char _modversion[] = "@(#) nicstar.c, $Id: nicstar.c,v 1.28 1996/11/12 23:17:53 swdaniel Exp $"; +static char _modversion[] = "@(#) nicstar.c, $Id: nicstar.c,v 1.31 1996/11/25 21:05:54 swdaniel Exp $"; #include <linux/fs.h> #include <asm/system.h> @@ -138,7 +138,7 @@ if (error) return error; vcc->vpi = vpi; vcc->vci = vci; - vcc->dev_data = &(node->vci_map[vci]); + vcc->dev_data = &(node->vci_map[(vpi << NUM_VCI_BITS) | vci]); vcc->flags |= ATM_VF_ADDR; #if NICSTAR_CBR @@ -147,7 +147,7 @@ #else if (vcc->txtp.class == ATM_CBR) { #endif - printk("Opening CBR connection on vpci %d.%d\n",vpi,vci); + PRINTK("Opening CBR connection on vpci %d.%d\n",vpi,vci); alloc_tx(node,vcc); } #endif @@ -168,7 +168,7 @@ printk ("nicstar%d: invalid AAL %d on open",node->index,vcc->aal); return -EINVAL; } - open_rx_connection(node, vci, status); + open_rx_connection(node, (vpi << NUM_VCI_BITS) | vci, status); } vcc->flags |= ATM_VF_PARTIAL; @@ -195,7 +195,7 @@ #else if (vcc->rxtp.class != ATM_NONE) { #endif - close_rx_connection(node, vcc->vci); + close_rx_connection(node, (vcc->vpi << NUM_VCI_BITS) | vcc->vci); vcc->flags &= ~ATM_VF_PARTIAL; mapval->rx = 0; } @@ -270,7 +270,8 @@ nicstar_scq *scq; u32 rate; #ifdef NICSTAR_FASTXMIT - int len, len_buf; + int len; + int len_buf = 0; #else nicstar_tbd tbd2, tbd3; #endif @@ -316,7 +317,7 @@ skb->atm.vcc = vcc; - vci = vcc->vci; + vci = (vcc->vpi << NUM_VCI_BITS) | vcc->vci; #ifndef ATM_013 if (vcc->qos.txtp.traffic_class == ATM_CBR) { #else @@ -362,6 +363,7 @@ len = (((skb->len + 8 + 47) / 48) * 48); pad = len - skb->len; PRINTK ("new len %d skb len %ld skb end %x skb tail %x\n",len,skb->len,(u32)skb->end,(u32)skb->tail); + if (!(node->rev_C3)) { /* SAR supports mod 4 buffer sizes */ len_buf = (((skb->len + 3) / 4) * 4); if (pad == 0) { @@ -380,7 +382,7 @@ tbd1.buf_addr = (u32)skb->data; tbd1.ctl_len = skb->len; - tbd1.cell_hdr = (vcc->vci << 4); + tbd1.cell_hdr = (vcc->vpi << 20) | (vcc->vci << 4); scq->scq_shadow[sindex].skb = skb; if (!(node->rev_C3) && (pad != 0)) { @@ -388,7 +390,7 @@ tbd1.status = TBD_AAL5 | TBD_ENDPDU | rate | (len - len_buf); tbd1.buf_addr = (u32)node->tmp_cell; tbd1.ctl_len = skb->len; - tbd1.cell_hdr = (vcc->vci << 4); + tbd1.cell_hdr = (vcc->vpi << 20) | (vcc->vci << 4); push_scq_entry(node, scq, &tbd1, 1); } else { @@ -413,7 +415,7 @@ tbd1.status = 0x08810000 | (((skb->len - (40 - pad))/sizeof(u32)) << 2); tbd1.buf_addr = (u32)skb->data; tbd1.ctl_len = skb->len; - tbd1.cell_hdr = (vcc->vci << 4); + tbd1.cell_hdr = (vcc->vpi << 20) | (vcc->vci << 4); node->scq->scq_shadow[sindex].skb = skb; push_scq_entry(node, node->scq, &tbd1, 0); @@ -421,7 +423,7 @@ tbd2.status = 0x48810030; tbd2.buf_addr = (u32)(node->scq->scq_shadow[sindex].cell); tbd2.ctl_len = skb->len; - tbd2.cell_hdr = (vcc->vci << 4); + tbd2.cell_hdr = (vcc->vpi << 20) | (vcc->vci << 4); push_scq_entry(node, node->scq, &tbd2, 1); @@ -435,7 +437,7 @@ tbd1.status = 0x08810000 | (((skb->len - (48 - pad))/sizeof(u32)) << 2); tbd1.buf_addr = (u32)skb->data; tbd1.ctl_len = skb->len; - tbd1.cell_hdr = (vcc->vci << 4); + tbd1.cell_hdr = (vcc->vpi << 20) | (vcc->vci << 4); node->scq->scq_shadow[sindex].skb = skb; push_scq_entry(node, node->scq, &tbd1, 0); @@ -443,14 +445,14 @@ tbd2.status = 0x08810030; tbd2.buf_addr = (u32)(node->scq->scq_shadow[sindex].cell); tbd2.ctl_len = skb->len; - tbd2.cell_hdr = (vcc->vci << 4); + tbd2.cell_hdr = (vcc->vpi << 20) | (vcc->vci << 4); push_scq_entry(node, node->scq, &tbd2, 0); tbd3.status = 0x48810030; tbd3.buf_addr = (u32)(node->tmp_cell); tbd3.ctl_len = skb->len; - tbd3.cell_hdr = (vcc->vci << 4); + tbd3.cell_hdr = (vcc->vpi << 20) | (vcc->vci << 4); push_scq_entry(node, node->scq, &tbd3, 1); } @@ -464,7 +466,7 @@ tbd1.status = 0x48810030; tbd1.buf_addr = (u32)(node->scq->scq_shadow[sindex].cell); tbd1.ctl_len = skb->len; - tbd1.cell_hdr = (vcc->vci << 4); + tbd1.cell_hdr = (vcc->vpi << 20) | (vcc->vci << 4); node->scq->scq_shadow[sindex].skb = skb; push_scq_entry(node, node->scq, &tbd1, 1); @@ -480,7 +482,7 @@ tbd1.status = 0x08810030; tbd1.buf_addr = (u32)(node->scq->scq_shadow[sindex].cell); tbd1.ctl_len = skb->len; - tbd1.cell_hdr = (vcc->vci << 4); + tbd1.cell_hdr = (vcc->vpi << 20) | (vcc->vci << 4); node->scq->scq_shadow[sindex].skb = skb; push_scq_entry(node, node->scq, &tbd1, 0); @@ -488,7 +490,7 @@ tbd2.status = 0x48810030; tbd2.buf_addr = (u32)(node->tmp_cell); tbd2.ctl_len = skb->len; - tbd2.cell_hdr = (vcc->vci << 4); + tbd2.cell_hdr = (vcc->vpi << 20) | (vcc->vci << 4); push_scq_entry(node, node->scq, &tbd2, 1); @@ -677,7 +679,7 @@ node->dev->esi[5] = '\110'; node->dev->dev_data = node; - node->dev->ci_range.vpi_bits = 0; + node->dev->ci_range.vpi_bits = NUM_VPI_BITS; node->dev->ci_range.vci_bits = NUM_VCI_BITS; } @@ -1083,12 +1085,12 @@ #if NICSTAR_RCQ /* Turn on everything */ - writel(0x21801c38 | 0x200 | 0x800, node->membase+CFG); + writel(0x21801c38 | CFG_VPIVCI | 0x200 | 0x800, node->membase+CFG); /* | 0x800 turns on raw cell interrupts */ /* | 0x200 for raw cell receive */ /* | 0x8000 to receive cells that don't map via RCT (not there/closed) */ #else - writel(0x21801c38, node->membase+CFG); /* Turn on everything */ + writel(0x21801c38 | CFG_VPIVCI, node->membase+CFG); /* Turn on everything */ #endif while(CMD_BUSY(node)); @@ -1205,18 +1207,18 @@ wake_up_interruptible(&node->scq->scqfull_waitq); } #else - id = (node->tx_statq_next->status & 0xf0000000) >> 16; + id = (node->tx_statq_next->status & 0xc0000000) >> 16; switch (id) { case (SCQFULL_MAGIC >> 16): scq = node->scq; break; #if NICSTAR_CBR case (CBRSCQFULL_MAGIC_CLOSE >> 16): - scq = node->vci_map[(node->tx_statq_next->status & 0x0fff0000)>>16].scq; + scq = node->vci_map[(node->tx_statq_next->status & 0x3fff0000)>>16].scq; scq->closing = 1; break; case (CBRSCQFULL_MAGIC >> 16): - scq = node->vci_map[(node->tx_statq_next->status & 0x0fff0000)>>16].scq; + scq = node->vci_map[(node->tx_statq_next->status & 0x3fff0000)>>16].scq; break; #endif default: @@ -1500,16 +1502,16 @@ nicstar_vcimap *mapval; PRINTK ("Reserving vci %d\n",(u32) *vci); - /* We accept VPI 0 and VCI 0-4095. */ + /* Default, accept VPI 0 and VCI 0-4095. */ if (*vpi == ATM_VPI_UNSPEC || *vci == ATM_VCI_UNSPEC) return -EINVAL; if (*vpi == ATM_VPI_ANY) *vpi = 0; - if (*vpi != 0) return -EINVAL; + if (*vpi >= NUM_VPI) return -EINVAL; if (*vci == ATM_VCI_ANY) { /* Find lowest VCI */ #ifndef ATM_013 - for (*vci = ATM_NOT_RSV_VCI; *vci < NUM_VCI; (*vci)++) { + for (*vci = (*vpi) * NUM_VCI + ATM_NOT_RSV_VCI; *vci < (*vpi + 1) * NUM_VCI; (*vci)++) { mapval = &(node->vci_map[*vci]); if (vcc->qos.rxtp.traffic_class != ATM_NONE && mapval->rx) continue; if (vcc->qos.txtp.traffic_class != ATM_NONE && mapval->tx) continue; @@ -1536,7 +1538,7 @@ } else { /* Use this particular VCI */ if (*vci >= NUM_VCI) return -EINVAL; - mapval = &(node->vci_map[*vci]); + mapval = &(node->vci_map[(*vpi << NUM_VCI_BITS) | *vci]); #ifndef ATM_013 if (vcc->qos.rxtp.traffic_class != ATM_NONE && mapval->rx) return -EADDRINUSE; if (vcc->qos.txtp.traffic_class != ATM_NONE && mapval->tx) return -EADDRINUSE; @@ -1598,20 +1600,21 @@ unsigned short aal5_len; unsigned short aal0_len; u32 *aal0_ptr; + u32 vpi, vci; + + vpi = (entry->vpi_vci & 0x00ff0000) >> 16; + vci = entry->vpi_vci & 0xffff; - if ((entry->vpi_vci & 0x00ff0000) || - ((entry->vpi_vci & 0xffff) > NUM_VCI)) { + if ((vpi >= NUM_VPI) || (vci >= NUM_VCI)) { printk("nicstar%d: SDU received for out of range VC %d.%d.\n", - node->index, - entry->vpi_vci >> 16, - entry->vpi_vci & 0xffff); + node->index, vpi, vci); return; } - mapval = &(node->vci_map[entry->vpi_vci]); + mapval = &(node->vci_map[(vpi << NUM_VCI_BITS) | vci]); if (!mapval->rx) { - printk("nicstar%d: SDU received on inactive VC 0.%d.\n", - node->index, entry->vpi_vci); + printk("nicstar%d: SDU received on inactive VC %d.%d.\n", + node->index, vpi, vci); } vcc = mapval->rx_vcc; @@ -1771,7 +1774,7 @@ int spacing; int vci; - vci = vcc->vci; + vci = (vcc->vpi << NUM_VCI_BITS) | vcc->vci; create_scq(&((node->vci_map[vci]).scq),CBRSCQ_SIZE); (node->vci_map[vci].scq)->id = CBRSCQFULL_MAGIC | (vci << 16); PRINTK ("nicstar%d: Allocating CBR SCQ at %x\n",node->index,(u32) ((node->vci_map[vci]).scq)); diff -ur --new-file old/linux/drivers/atm/nicstar.h new/linux/drivers/atm/nicstar.h --- old/linux/drivers/atm/nicstar.h Fri Dec 20 21:56:26 1996 +++ new/linux/drivers/atm/nicstar.h Fri Dec 20 21:56:53 1996 @@ -19,6 +19,23 @@ * * M. Welsh, 6 July 1996 * + * + * Configuration notes: + * Driver can be configured by defining/undefining + * the configuration options below. + * Supported VPI/VCI range can be adjusted; search for + * CFG_VPIVCI for more info. + * A 128k x 32 SRAM board might require adjusting some constants + * below; see IDT 77201 NICStAR User's Manual + * + * If you want to use a different size for the small free buffers, + * be sure to set SM_BUFSZ to the actual buffer size + 4 + * + * I'm not convinced that the CBR support is "accurate"; if you want + * to find out what's wrong, feel free. + * + * S. Daniel, Nov. 25, 1996 + * */ #ifndef _LINUX_NICSTAR_H @@ -31,6 +48,15 @@ #define NICSTAR_DEV_MAJOR 35 +/* misc configuration options */ +#define NICSTAR_FASTXMIT 1 /* Lies about buffer lengths to speed xmit + possibly insecure (see nicstar.c) */ +#define NICSTAR_CBR 1 /* Constant bit rate support */ +#undef NICSTAR_RCQ /* Raw cell queue support; just prints out raw cells */ +#define NICSTAR_PARANOID 1 /* adds some extra checks */ +#undef TEST_LOOPBACK /* enables PHY-level loopback */ +#undef ATM_013 + /* Kernel definitions ******************************************************/ #ifdef __KERNEL__ @@ -86,15 +112,6 @@ VPM = 0x50 }; -/* misc configuration options (experimental) */ -#define NICSTAR_FASTXMIT 1 -#define NICSTAR_CBR 1 /* Constant bit rate support */ -#undef NICSTAR_RCQ /* Raw cell queue support */ -#define NICSTAR_PARANOID 1 /* adds some extra checks */ -#undef TEST_LOOPBACK /* enables PHY-level loopback */ -#undef ATM_013 - - /* SRAM locations */ #define NICSTAR_VBR_SCD0 (0x1e7f4) #define NICSTAR_VBR_SCD1 (0x1e7e8) @@ -152,9 +169,13 @@ #define CBRSCQ_SIZE (1024) /* space to reserve for each */ #define CBRSCQ_ENTRIES (CBRSCQ_SIZE / TBD_SIZE) /* # entries in a CBR SCQ */ #ifdef NICSTAR_CBR -#define SCQFULL_MAGIC (0xf0000000) -#define CBRSCQFULL_MAGIC (0xc0000000) -#define CBRSCQFULL_MAGIC_CLOSE (0xe0000000) +/* magic #s must be non-zero; restrict to high two bits to support + largest possible receive table (8 VPI bits, 6 VCI bits) + Magic #s must be non-zero to distinguish them from the timestamp + overflow */ +#define SCQFULL_MAGIC (0xc0000000) +#define CBRSCQFULL_MAGIC (0x80000000) +#define CBRSCQFULL_MAGIC_CLOSE (0x40000000) #else #define SCQFULL_MAGIC (0xfeed0000) #endif @@ -208,8 +229,27 @@ #endif } nicstar_vcimap; -#define NUM_VCI (4096) /* Size of Rx conn table, indexed by VCI only */ -#define NUM_VCI_BITS (12) /* Num sig bits */ +/* Valid combinations for VPI/VCI: + 4k table, no VPI, 12b VCI (set CFG_VPIVCI to 0x00000) + 4k table, 1b VPI, 11b VCI (set CFG_VPIVCI to 0x40000) + 4k table, 2b VPI, 10b VCI (set CFG_VPIVCI to 0x80000) + 4k table, 8b VPI, 4b VCI (set CFG_VPIVCI to 0xc0000) + *** below only for boards with 128k x 32b SRAM *** + 8k table, no VPI, 13b VCI (set CFG_VPIVCI to 0x10000) + 8k table, 1b VPI, 12b VCI (set CFG_VPIVCI to 0x50000) + 8k table, 2b VPI, 11b VCI (set CFG_VPIVCI to 0x90000) + 8k table, 8b VPI, 5b VCI (set CFG_VPIVCI to 0xd0000) + 16k table, no VPI, 14b VCI (set CFG_VPIVCI to 0x20000) + 16k table, 1b VPI, 13b VCI (set CFG_VPIVCI to 0x60000) + 16k table, 2b VPI, 12b VCI (set CFG_VPIVCI to 0xa0000) + 16k table, 8b VPI, 6b VCI (set CFG_VPIVCI to 0xe0000) + You will need to define each of the below to match the desired config + */ +#define CFG_VPIVCI 0x40000 +#define NUM_VCI (2048) /* Size of Rx conn table, indexed by VCI only */ +#define NUM_VCI_BITS (11) /* Num sig bits */ +#define NUM_VPI (2) /* Only VPI 0 currently defined */ +#define NUM_VPI_BITS (1) /* Number of bits required for above */ typedef struct nicstar_buf_list { caddr_t buf_addr; @@ -255,7 +295,7 @@ caddr_t scq_orig; struct atm_dev *dev; - nicstar_vcimap vci_map[NUM_VCI]; + nicstar_vcimap vci_map[NUM_VPI * NUM_VCI]; unsigned char tmp_cell[48]; } nicstar_dev, *nicstar_devp; diff -ur --new-file old/linux/net/atm/atmarp.c new/linux/net/atm/atmarp.c --- old/linux/net/atm/atmarp.c Fri Dec 20 21:56:26 1996 +++ new/linux/net/atm/atmarp.c Fri Dec 20 21:56:54 1996 @@ -171,19 +171,22 @@ unsigned long expire; idle_timer.expires = UINT_MAX; - for (itf = clip_devs; itf; itf = PRIV(itf)->next) - for (entry = &PRIV(itf)->table; *entry; - entry = &(*entry)->next) + for (itf = clip_devs; itf; itf = PRIV(itf)->next) { + entry = &PRIV(itf)->table; + while (*entry) { if ((*entry)->idle_timeout) { expire = (*entry)->last_use+(*entry)-> idle_timeout; if (expire < jiffies) { time_out_entry(entry); - if (!*entry) break; + continue; } else if (expire < idle_timer.expires) idle_timer.expires = expire; } + entry = &(*entry)->next; + } + } if (idle_timer.expires < jiffies+CLIP_CHECK_INTERVAL*HZ) idle_timer.expires = jiffies+CLIP_CHECK_INTERVAL*HZ; del_timer(&idle_timer); diff -ur --new-file old/linux/net/atm/lec.c new/linux/net/atm/lec.c --- old/linux/net/atm/lec.c Fri Dec 20 21:56:27 1996 +++ new/linux/net/atm/lec.c Fri Dec 20 21:56:54 1996 @@ -119,8 +119,9 @@ /* Put le header to place */ lec_h = (struct lecdatahdr_8023*)skb->data; + /* lec_h->le_header = htons(priv->lecid); - + */ #if DUMP_PACKETS > 0 printk("%s: send datalen:%ld lecid:%4.4x\n", dev->name, skb->len, priv->lecid); @@ -235,7 +236,6 @@ /* Destination addr */ if (daddr) { memcpy(hdr->h_dest, daddr, dev->addr_len); - hdr->le_header = 0; return dev->hard_header_len; } return -dev->hard_header_len; @@ -493,6 +493,7 @@ struct device *dev = (struct device *)vcc->proto_data; struct lec_priv *priv = (struct lec_priv *)dev->priv; struct lecdatahdr_8023 *hdr; + unsigned char *rawp; #if DUMP_PACKETS >0 int i=0; char buf[300]; @@ -556,6 +557,10 @@ else skb->protocol = htons(ETH_P_802_2); skb->h.raw = skb_pull(skb, LEC_HEADER_LEN); + rawp = skb->data; + /* Magic hack for IPX ... */ + if (*(unsigned short*)rawp == 0xFFFF) + skb->protocol = htons(ETH_P_802_3); netif_rx(skb); priv->stats.rx_packets++; }