diff -ur --new-file old/linux/arch/sparc/config.in new/linux/arch/sparc/config.in --- old/linux/arch/sparc/config.in Thu Jan 14 19:29:28 1999 +++ new/linux/arch/sparc/config.in Thu Jun 3 00:42:16 1999 @@ -170,6 +170,9 @@ # bool 'FDDI driver support' CONFIG_FDDI # if [ "$CONFIG_FDDI" = "y" ]; then # fi + if [ "$CONFIG_ATM" = "y" ]; then + source drivers/atm/Config.in + fi fi endmenu fi diff -ur --new-file old/linux/drivers/atm/Config.in new/linux/drivers/atm/Config.in --- old/linux/drivers/atm/Config.in Thu Jun 3 00:40:49 1999 +++ new/linux/drivers/atm/Config.in Thu Jun 3 00:42:17 1999 @@ -31,6 +31,9 @@ # bool ' Enable extended debugging' CONFIG_ATM_TNETA1570_DEBUG n # fi tristate 'IDT 77201 (NICStAR)' CONFIG_ATM_NICSTAR + if [ "$CONFIG_ATM_NICSTAR" != "n" ]; then + bool ' Use suni PHY driver' CONFIG_ATM_NICSTAR_USE_SUNI + fi tristate 'Madge Ambassador (Collage PCI 155 Server)' CONFIG_ATM_AMBASSADOR if [ "$CONFIG_ATM_AMBASSADOR" != "n" ]; then bool ' Enable debugging messages' CONFIG_ATM_AMBASSADOR_DEBUG diff -ur --new-file old/linux/drivers/atm/Makefile new/linux/drivers/atm/Makefile --- old/linux/drivers/atm/Makefile Thu Jun 3 00:40:49 1999 +++ new/linux/drivers/atm/Makefile Thu Jun 3 00:42:17 1999 @@ -38,9 +38,15 @@ ifeq ($(CONFIG_ATM_NICSTAR),y) L_OBJS += nicstar.o + ifeq ($(CONFIG_ATM_NICSTAR_USE_SUNI),y) + LX_OBJS += suni.o + endif else ifeq ($(CONFIG_ATM_NICSTAR),m) M_OBJS += nicstar.o + ifeq ($(CONFIG_ATM_NICSTAR_USE_SUNI),y) + MX_OBJS += suni.o + endif endif endif diff -ur --new-file old/linux/drivers/atm/eni.c new/linux/drivers/atm/eni.c --- old/linux/drivers/atm/eni.c Thu Jun 3 00:40:49 1999 +++ new/linux/drivers/atm/eni.c Thu Jun 3 00:42:17 1999 @@ -30,6 +30,11 @@ #include "suni.h" #include "eni.h" +#ifndef __i386__ +#ifndef ioremap_nocache +#define ioremap_nocache(X,Y) ioremap(X,Y) +#endif +#endif /* * TODO: @@ -91,7 +96,8 @@ */ #define NULLCHECK(x) \ - if ((unsigned long) (x) < 0x30) printk(KERN_CRIT #x "==0x%x\n", (int) (x)) + if ((unsigned long) (x) < 0x30) \ + printk(KERN_CRIT #x "==0x%lx\n",(unsigned long) (x)) /* * Very extensive activity logging. Greatly improves bug detection speed but @@ -152,6 +158,10 @@ static u32 *zeroes = NULL; /* aligned "magic" zeroes */ +/* Read/write registers on card */ +#define eni_in(r) readl(eni_dev->reg+(r)*4) +#define eni_out(v,r) writel((v),eni_dev->reg+(r)*4) + /*-------------------------------- utilities --------------------------------*/ @@ -179,12 +189,12 @@ printk(KERN_NOTICE "TX buffers\n"); for (i = 0; i < NR_CHAN; i++) if (eni_dev->tx[i].send) - printk(KERN_NOTICE " TX %d @ 0x%p: %ld\n",i, + printk(KERN_NOTICE " TX %d @ 0x%lx: %ld\n",i, eni_dev->tx[i].send,eni_dev->tx[i].words*4); printk(KERN_NOTICE "RX buffers\n"); for (i = 0; i < 1024; i++) if (eni_dev->rx_map[i] && ENI_VCC(eni_dev->rx_map[i])->rx) - printk(KERN_NOTICE " RX %d @ 0x%p: %ld\n",i, + printk(KERN_NOTICE " RX %d @ 0x%lx: %ld\n",i, ENI_VCC(eni_dev->rx_map[i])->recv, ENI_VCC(eni_dev->rx_map[i])->words*4); printk(KERN_NOTICE "----\n"); @@ -255,8 +265,7 @@ *size = 1 << order; eni_put_free(eni_dev,start+*size,(1 << best_order)-*size); DPRINTK("%ld bytes (order %d) at 0x%lx\n",*size,order,start); - for (i = (*size >> 2)-1; i >= 0; i--) /* never leak data */ - ((unsigned long *) start)[i] = 0; + memset_io(start,0,*size); /* never leak data */ /*dump_mem(eni_dev);*/ return start; } @@ -305,12 +314,14 @@ static void rx_ident_err(struct atm_vcc *vcc) { struct atm_dev *dev; + struct eni_dev *eni_dev; struct eni_vcc *eni_vcc; dev = vcc->dev; + eni_dev = ENI_DEV(dev); /* immediately halt adapter */ - writel(readl(ENI_DEV(dev)->reg+MID_MC_S) & ~(MID_DMA_ENABLE | - MID_TX_ENABLE | MID_RX_ENABLE),ENI_DEV(dev)->reg+MID_MC_S); + eni_out(eni_in(MID_MC_S) & + ~(MID_DMA_ENABLE | MID_TX_ENABLE | MID_RX_ENABLE),MID_MC_S); /* dump useful information */ eni_vcc = ENI_VCC(vcc); printk(KERN_ALERT DEV_LABEL "(itf %d): driver error - RX ident " @@ -319,7 +330,7 @@ eni_vcc->rxing,eni_vcc->words); printk(KERN_ALERT " host descr 0x%lx, rx pos 0x%lx, descr value " "0x%x\n",eni_vcc->descr,eni_vcc->rx_pos, - readl(eni_vcc->recv+eni_vcc->descr)); + (unsigned) readl(eni_vcc->recv+eni_vcc->descr*4)); printk(KERN_ALERT " last 0x%p, servicing %d\n",eni_vcc->last, eni_vcc->servicing); EVENT("---dump ends here---\n",0,0); @@ -441,8 +452,8 @@ } dma[j-2] |= MID_DMA_END; j = j >> 1; - dma_wr = readl(eni_dev->reg+MID_DMA_WR_RX); - dma_rd = readl(eni_dev->reg+MID_DMA_RD_RX); + dma_wr = eni_in(MID_DMA_WR_RX); + dma_rd = eni_in(MID_DMA_RD_RX); /* * Can I move the dma_wr pointer by 2j+1 positions without overwriting * data that hasn't been read (position of dma_rd) yet ? @@ -454,8 +465,8 @@ return -1; } for (i = 0; i < j; i++) { - writel(dma[i*2],eni_dev->rx_dma+dma_wr*2); - writel(dma[i*2+1],eni_dev->rx_dma+dma_wr*2+1); + writel(dma[i*2],eni_dev->rx_dma+dma_wr*8); + writel(dma[i*2+1],eni_dev->rx_dma+dma_wr*8+4); dma_wr = (dma_wr+1) & (NR_DMA_RX-1); } if (skb) { @@ -465,7 +476,7 @@ rx_enqueued++; } eni_vcc->descr = here; - writel(dma_wr,eni_dev->reg+MID_DMA_WR_RX); + eni_out(dma_wr,MID_DMA_WR_RX); return 0; } @@ -497,7 +508,7 @@ DPRINTK(">rx_aal0\n"); eni_vcc = ENI_VCC(vcc); - descr = readl(eni_vcc->recv+eni_vcc->descr); + descr = readl(eni_vcc->recv+eni_vcc->descr*4); if ((descr & MID_RED_IDEN) != (MID_RED_RX_ID << MID_RED_SHIFT)) { rx_ident_err(vcc); return 1; @@ -539,7 +550,7 @@ EVENT("rx_aal5\n",0,0); DPRINTK(">rx_aal5\n"); eni_vcc = ENI_VCC(vcc); - descr = readl(eni_vcc->recv+eni_vcc->descr); + descr = readl(eni_vcc->recv+eni_vcc->descr*4); if ((descr & MID_RED_IDEN) != (MID_RED_RX_ID << MID_RED_SHIFT)) { rx_ident_err(vcc); return 1; @@ -570,8 +581,9 @@ else { size = (descr & MID_RED_COUNT)*(ATM_CELL_PAYLOAD >> 2); DPRINTK("size=%ld\n",size); - length = readl(eni_vcc->recv+((eni_vcc->descr+size-1) & - (eni_vcc->words-1))) & 0xffff; /* -trailer(2)+header(1) */ + length = readl(eni_vcc->recv+(((eni_vcc->descr+size-1) & + (eni_vcc->words-1)))*4) & 0xffff; + /* -trailer(2)+header(1) */ if (length && length <= (size << 2)-8 && length <= ATM_MAX_AAL5_PDU) eff = (length+3) >> 2; else { /* ^ trailer length (8) */ @@ -608,19 +620,18 @@ static inline int rx_vcc(struct atm_vcc *vcc) { - u32 *vci_dsc; + unsigned long vci_dsc,tmp; struct eni_vcc *eni_vcc; - unsigned long tmp; eni_vcc = ENI_VCC(vcc); - vci_dsc = ENI_DEV(vcc->dev)->vci+vcc->vci*4; + vci_dsc = ENI_DEV(vcc->dev)->vci+vcc->vci*16; EVENT("rx_vcc(1)\n",0,0); - while (eni_vcc->descr != (tmp = (readl(vci_dsc+1) & MID_VCI_DESCR) >> + while (eni_vcc->descr != (tmp = (readl(vci_dsc+4) & MID_VCI_DESCR) >> MID_VCI_DESCR_SHIFT)) { EVENT("rx_vcc(2: host dsc=0x%lx, nic dsc=0x%lx)\n", eni_vcc->descr,tmp); DPRINTK("CB_DESCR %ld REG_DESCR %d\n",ENI_VCC(vcc)->descr, - ((readl(vci_dsc+1) & MID_VCI_DESCR) >> + (((unsigned) readl(vci_dsc+4) & MID_VCI_DESCR) >> MID_VCI_DESCR_SHIFT)); if (ENI_VCC(vcc)->rx(vcc)) return 1; } @@ -632,12 +643,12 @@ * follows. So we have to loop again to be sure. */ EVENT("rx_vcc(3)\n",0,0); - while (ENI_VCC(vcc)->descr != (tmp = (readl(vci_dsc+1) & MID_VCI_DESCR) + while (ENI_VCC(vcc)->descr != (tmp = (readl(vci_dsc+4) & MID_VCI_DESCR) >> MID_VCI_DESCR_SHIFT)) { EVENT("rx_vcc(4: host dsc=0x%lx, nic dsc=0x%lx)\n", eni_vcc->descr,tmp); DPRINTK("CB_DESCR %ld REG_DESCR %d\n",ENI_VCC(vcc)->descr, - ((readl(vci_dsc+1) & MID_VCI_DESCR) >> + (((unsigned) readl(vci_dsc+4) & MID_VCI_DESCR) >> MID_VCI_DESCR_SHIFT)); if (ENI_VCC(vcc)->rx(vcc)) return 1; } @@ -676,8 +687,8 @@ DPRINTK(">get_service\n"); eni_dev = ENI_DEV(dev); - while (readl(eni_dev->reg+MID_SERV_WRITE) != eni_dev->serv_read) { - vci = readl(eni_dev->service+eni_dev->serv_read); + while (eni_in(MID_SERV_WRITE) != eni_dev->serv_read) { + vci = readl(eni_dev->service+eni_dev->serv_read*4); eni_dev->serv_read = (eni_dev->serv_read+1) & (NR_SERVICE-1); vcc = eni_dev->rx_map[vci & 1023]; if (!vcc) { @@ -718,7 +729,7 @@ struct eni_vcc *eni_vcc; struct atm_vcc *vcc; struct sk_buff *skb; - u32 *vci_dsc; + unsigned long vci_dsc; int first; eni_dev = ENI_DEV(dev); @@ -739,9 +750,9 @@ vcc = ATM_SKB(skb)->vcc; eni_vcc = ENI_VCC(vcc); first = 0; - vci_dsc = eni_dev->vci+(vcc->vci << 2); + vci_dsc = eni_dev->vci+vcc->vci*16; if (!EEPMOK(eni_vcc->rx_pos,ENI_PRV_SIZE(skb), - (readl(vci_dsc+1) & MID_VCI_READ) >> MID_VCI_READ_SHIFT, + (readl(vci_dsc+4) & MID_VCI_READ) >> MID_VCI_READ_SHIFT, eni_vcc->words)) { EVENT("requeuing\n",0,0); skb_queue_head(&eni_dev->rx_queue,skb); @@ -780,8 +791,8 @@ if (size > MID_MAX_BUF_SIZE && vcc->qos.rxtp.max_sdu <= MID_MAX_BUF_SIZE) size = MID_MAX_BUF_SIZE; - eni_vcc->recv = (u32 *) eni_alloc_mem(eni_dev,&size); - DPRINTK("rx at 0x%p\n",eni_vcc->recv); + eni_vcc->recv = eni_alloc_mem(eni_dev,&size); + DPRINTK("rx at 0x%lx\n",eni_vcc->recv); eni_vcc->words = size >> 2; if (!eni_vcc->recv) return -ENOBUFS; eni_vcc->rx = vcc->qos.aal == ATM_AAL5 ? rx_aal5 : rx_aal0; @@ -796,7 +807,7 @@ static int open_rx_second(struct atm_vcc *vcc) { - u32 *here; + unsigned long here; struct eni_dev *eni_dev; struct eni_vcc *eni_vcc; unsigned long size; @@ -807,19 +818,19 @@ eni_vcc = ENI_VCC(vcc); if (!eni_vcc->rx) return 0; /* set up VCI descriptor */ - here = eni_dev->vci+(vcc->vci << 2); - DPRINTK("loc 0x%x\n",eni_vcc->recv-eni_dev->ram); + here = eni_dev->vci+vcc->vci*16; + DPRINTK("loc 0x%x\n",(unsigned) (eni_vcc->recv-eni_dev->ram)/4); size = eni_vcc->words >> 8; for (order = -1; size; order++) size >>= 1; - writel(0,here+1); /* descr, read = 0 */ - writel(0,here+2); /* write, state, count = 0 */ + writel(0,here+4); /* descr, read = 0 */ + writel(0,here+8); /* write, state, count = 0 */ if (eni_dev->rx_map[vcc->vci]) printk(KERN_CRIT DEV_LABEL "(itf %d): BUG - VCI %d already " "in use\n",vcc->dev->number,vcc->vci); eni_dev->rx_map[vcc->vci] = vcc; /* now it counts */ writel(((vcc->qos.aal != ATM_AAL5 ? MID_MODE_RAW : MID_MODE_AAL5) << MID_VCI_MODE_SHIFT) | MID_VCI_PTI_MODE | - (((eni_vcc->recv-eni_dev->ram) >> MID_LOC_SKIP) << + (((eni_vcc->recv-eni_dev->ram) >> (MID_LOC_SKIP+2)) << MID_VCI_LOCATION_SHIFT) | (order << MID_VCI_SIZE_SHIFT),here); return 0; } @@ -827,17 +838,16 @@ static void close_rx(struct atm_vcc *vcc) { - u32 *here; + unsigned long here,flags; struct eni_dev *eni_dev; struct eni_vcc *eni_vcc; - unsigned long flags; u32 tmp; eni_vcc = ENI_VCC(vcc); if (!eni_vcc->rx) return; eni_dev = ENI_DEV(vcc->dev); if (vcc->vpi != ATM_VPI_UNSPEC && vcc->vci != ATM_VCI_UNSPEC) { - here = eni_dev->vci+(vcc->vci << 2); + here = eni_dev->vci+vcc->vci*16; /* block receiver */ writel((readl(here) & ~MID_VCI_MODE) | (MID_MODE_TRASH << MID_VCI_MODE_SHIFT),here); @@ -859,8 +869,9 @@ eni_vcc->rxing); sleep_on(&eni_dev->rx_wait); } - while (eni_vcc->rx_pos != (tmp = eni_dev->vci[vcc->vci*4+1] & - MID_VCI_READ) >> MID_VCI_READ_SHIFT) { + while (eni_vcc->rx_pos != (tmp = + readl(eni_dev->vci+vcc->vci*16+4) & MID_VCI_READ)>> + MID_VCI_READ_SHIFT) { EVENT("drain discard (host 0x%lx, nic 0x%lx)\n", eni_vcc->rx_pos,tmp); printk(KERN_INFO "draining RX: host 0x%lx, nic 0x%x\n", @@ -869,8 +880,7 @@ } restore_flags(flags); } - eni_free_mem(eni_dev,(unsigned long) eni_vcc->recv, - eni_vcc->words << 2); + eni_free_mem(eni_dev,eni_vcc->recv,eni_vcc->words << 2); eni_vcc->rx = NULL; } @@ -892,8 +902,8 @@ eni_dev->slow = eni_dev->last_slow = NULL; eni_dev->rx_wait = NULL; skb_queue_head_init(&eni_dev->rx_queue); - eni_dev->serv_read = readl(eni_dev->reg+MID_SERV_WRITE); - writel(0,eni_dev->reg+MID_DMA_WR_RX); + eni_dev->serv_read = eni_in(MID_SERV_WRITE); + eni_out(0,MID_DMA_WR_RX); return 0; } @@ -1057,14 +1067,14 @@ * the manual calls "too close". */ if (!NEPMOK(tx->tx_pos,size+TX_GAP, - readl(eni_dev->reg+MID_TX_RDPTR(tx->index)),tx->words)) { - DPRINTK(DEV_LABEL "(itf %d): TX full (size %ld)\n", + eni_in(MID_TX_RDPTR(tx->index)),tx->words)) { + DPRINTK(DEV_LABEL "(itf %d): TX full (size %d)\n", vcc->dev->number,size); return enq_next; } /* check DMA */ - dma_wr = readl(eni_dev->reg+MID_DMA_WR_TX); - dma_rd = readl(eni_dev->reg+MID_DMA_RD_TX); + dma_wr = eni_in(MID_DMA_WR_TX); + dma_rd = eni_in(MID_DMA_RD_TX); dma_size = 3; /* JK for descriptor and final fill, plus final size mis-alignment fix */ DPRINTK("iovcnt = %d\n",ATM_SKB(skb)->iovcnt); @@ -1074,7 +1084,7 @@ printk(KERN_CRIT DEV_LABEL "(itf %d): needs %d DMA entries " "(got only %d)\n",vcc->dev->number,dma_size,TX_DMA_BUF); } - DPRINTK("dma_wr is %ld, tx_pos is %ld\n",dma_wr,tx->tx_pos); + DPRINTK("dma_wr is %d, tx_pos is %ld\n",dma_wr,tx->tx_pos); if (dma_wr != dma_rd && ((dma_rd+NR_DMA_TX-dma_wr) & (NR_DMA_TX-1)) < dma_size) { printk(KERN_WARNING DEV_LABEL "(itf %d): TX DMA full\n", @@ -1110,30 +1120,31 @@ j++; DPRINTK("DMA at end: %d\n",j); /* store frame */ - tx->send[tx->tx_pos] = (MID_SEG_TX_ID << MID_SEG_ID_SHIFT) | + writel((MID_SEG_TX_ID << MID_SEG_ID_SHIFT) | (aal5 ? MID_SEG_AAL5 : 0) | (tx->prescaler << MID_SEG_PR_SHIFT) | (tx->resolution << MID_SEG_RATE_SHIFT) | - (size/(ATM_CELL_PAYLOAD/4)); -/*printk("dsc = 0x%08lx\n",tx->send[tx->tx_pos]);*/ - tx->send[(tx->tx_pos+1) & (tx->words-1)] = (vcc->vci << - MID_SEG_VCI_SHIFT) | (aal5 ? 0 : (skb->data[3] & 0xf)) | - (ATM_SKB(skb)->atm_options & ATM_ATMOPT_CLP ? MID_SEG_CLP : 0); - DPRINTK("size: %ld, len:%d\n",size,skb->len); + (size/(ATM_CELL_PAYLOAD/4)),tx->send+tx->tx_pos*4); +/*printk("dsc = 0x%08lx\n",(unsigned long) readl(tx->send+tx->tx_pos*4));*/ + writel((vcc->vci << MID_SEG_VCI_SHIFT) | + (aal5 ? 0 : (skb->data[3] & 0xf)) | + (ATM_SKB(skb)->atm_options & ATM_ATMOPT_CLP ? MID_SEG_CLP : 0), + tx->send+((tx->tx_pos+1) & (tx->words-1))*4); + DPRINTK("size: %d, len:%d\n",size,skb->len); if (aal5) - tx->send[(tx->tx_pos+size-AAL5_TRAILER) & (tx->words-1)] = - skb->len; + writel(skb->len,tx->send+ + ((tx->tx_pos+size-AAL5_TRAILER) & (tx->words-1))*4); j = j >> 1; for (i = 0; i < j; i++) { - writel(eni_dev->dma[i*2],eni_dev->tx_dma+dma_wr*2); - writel(eni_dev->dma[i*2+1],eni_dev->tx_dma+dma_wr*2+1); + writel(eni_dev->dma[i*2],eni_dev->tx_dma+dma_wr*8); + writel(eni_dev->dma[i*2+1],eni_dev->tx_dma+dma_wr*8+4); dma_wr = (dma_wr+1) & (NR_DMA_TX-1); } ENI_PRV_POS(skb) = tx->tx_pos; ENI_PRV_SIZE(skb) = size; ENI_VCC(vcc)->txing += size; tx->tx_pos = (tx->tx_pos+size) & (tx->words-1); - DPRINTK("dma_wr set to %ld, tx_pos is now %ld\n",dma_wr,tx->tx_pos); - writel(dma_wr,eni_dev->reg+MID_DMA_WR_TX); + DPRINTK("dma_wr set to %d, tx_pos is now %ld\n",dma_wr,tx->tx_pos); + eni_out(dma_wr,MID_DMA_WR_TX); skb_queue_tail(&eni_dev->tx_queue,skb); queued++; return enq_ok; @@ -1181,9 +1192,9 @@ tx = ENI_VCC(vcc)->tx; NULLCHECK(ENI_VCC(vcc)->tx); DPRINTK("dequeue_tx: next 0x%lx curr 0x%x\n",ENI_PRV_POS(skb), - readl(eni_dev->reg+MID_TX_DESCRSTART(tx->index))); + (unsigned) eni_in(MID_TX_DESCRSTART(tx->index))); if (ENI_VCC(vcc)->txing < tx->words && ENI_PRV_POS(skb) == - readl(eni_dev->reg+MID_TX_DESCRSTART(tx->index))) { + eni_in(MID_TX_DESCRSTART(tx->index))) { skb_queue_head(&eni_dev->tx_queue,skb); break; } @@ -1286,14 +1297,14 @@ } DPRINTK("got chan %d\n",tx->index); tx->reserved = tx->shaping = 0; - tx->send = (u32 *) mem; + tx->send = mem; tx->words = size >> 2; skb_queue_head_init(&tx->backlog); for (order = 0; size > (1 << (order+10)); order++); - writel((order << MID_SIZE_SHIFT) | - ((tx->send-eni_dev->ram) >> MID_LOC_SKIP), - eni_dev->reg+MID_TX_PLACE(tx->index)); - tx->tx_pos = readl(eni_dev->reg+MID_TX_DESCRSTART(tx->index)) & + eni_out((order << MID_SIZE_SHIFT) | + ((tx->send-eni_dev->ram) >> (MID_LOC_SKIP+2)), + MID_TX_PLACE(tx->index)); + tx->tx_pos = eni_in(MID_TX_DESCRSTART(tx->index)) & MID_DESCR_START; } error = comp_tx(eni_dev,&rate,tx->reserved,&pre,&res,unlimited); @@ -1308,7 +1319,7 @@ error = -EINVAL; if (error) { if (new_tx) { - tx->send = NULL; + tx->send = 0; eni_free_mem(eni_dev,mem,size); } return error; @@ -1367,8 +1378,8 @@ * Looping a few times in here is probably far cheaper than keeping * track of TX completions all the time, so let's poll a bit ... */ - while (readl(eni_dev->reg+MID_TX_RDPTR(eni_vcc->tx->index)) != - readl(eni_dev->reg+MID_TX_DESCRSTART(eni_vcc->tx->index))) + while (eni_in(MID_TX_RDPTR(eni_vcc->tx->index)) != + eni_in(MID_TX_DESCRSTART(eni_vcc->tx->index))) schedule(); restore_flags(flags); #if 0 @@ -1376,9 +1387,8 @@ printk(KERN_CRIT DEV_LABEL "SKBs in BACKLOG !!!\n"); #endif if (eni_vcc->tx != eni_dev->ubr) { - eni_free_mem(eni_dev,(unsigned long) eni_vcc->tx->send, - eni_vcc->tx->words << 2); - eni_vcc->tx->send = NULL; + eni_free_mem(eni_dev,eni_vcc->tx->send,eni_vcc->tx->words << 2); + eni_vcc->tx->send = 0; eni_dev->tx_bw += eni_vcc->tx->reserved; } eni_vcc->tx = NULL; @@ -1396,9 +1406,9 @@ eni_dev->tx_wait = NULL; eni_dev->ubr = NULL; skb_queue_head_init(&eni_dev->tx_queue); - writel(0,eni_dev->reg+MID_DMA_WR_TX); + eni_out(0,MID_DMA_WR_TX); for (i = 0; i < NR_CHAN; i++) { - eni_dev->tx[i].send = NULL; + eni_dev->tx[i].send = 0; eni_dev->tx[i].index = i; } return 0; @@ -1431,7 +1441,7 @@ eni_dev = ENI_DEV(dev); if (reason & MID_STAT_OVFL) { EVENT("stat overflow\n",0,0); - eni_dev->lost += readl(eni_dev->reg+MID_STAT) & MID_OVFL_TRASH; + eni_dev->lost += eni_in(MID_STAT) & MID_OVFL_TRASH; } if (reason & MID_SUNI_INT) { EVENT("SUNI int\n",0,0); @@ -1473,7 +1483,7 @@ DPRINTK(">eni_int\n"); dev = dev_id; eni_dev = ENI_DEV(dev); - while ((reason = readl(eni_dev->reg+MID_ISA))) { + while ((reason = eni_in(MID_ISA))) { DPRINTK(DEV_LABEL ": int 0x%lx\n",reason); if (reason & MID_RX_DMA_COMPLETE) { EVENT("INT: RX DMA complete, starting dequeue_rx\n", @@ -1632,15 +1642,11 @@ __initfunc(static int get_esi_fpga(struct atm_dev *dev,unsigned long base)) { - struct eni_dev *eni_dev; - struct midway_eprom *eprom; + unsigned long mac_base; int i; - eprom = (struct midway_eprom *) (base+EPROM_SIZE-sizeof(struct - midway_eprom)); - eni_dev = ENI_DEV(dev); - for (i = 0; i < ESI_LEN; i++) - dev->esi[i] = readl(&eprom->mac+((i & ~3) | (3-(i & 3)))); + mac_base = base+EPROM_SIZE-sizeof(struct midway_eprom); + for (i = 0; i < ESI_LEN; i++) dev->esi[i] = readb(mac_base+(i^3)); return 0; } @@ -1691,17 +1697,16 @@ if (readl(&eprom->magic) != ENI155_MAGIC) { printk("\n"); printk(KERN_ERR KERN_ERR DEV_LABEL "(itf %d): bad " - "magic - expected 0x%X, got 0x%X\n",dev->number, - ENI155_MAGIC,readl(&eprom->magic)); + "magic - expected 0x%x, got 0x%x\n",dev->number, + ENI155_MAGIC,(unsigned) readl(&eprom->magic)); return -EINVAL; } } - eni_dev->phy = (u32 *) (base+PHY_BASE); - eni_dev->reg = (u32 *) (base+REG_BASE); - eni_dev->ram = (u32 *) (base+RAM_BASE); - last = (MAP_MAX_SIZE-RAM_BASE)/4; - for (i = last-RAM_INCREMENT; i >= 0; - i -= RAM_INCREMENT) { + eni_dev->phy = base+PHY_BASE; + eni_dev->reg = base+REG_BASE; + eni_dev->ram = base+RAM_BASE; + last = MAP_MAX_SIZE-RAM_BASE; + for (i = last-RAM_INCREMENT; i >= 0; i -= RAM_INCREMENT) { writel(0x55555555,eni_dev->ram+i); if (readl(eni_dev->ram+i) != 0x55555555) last = i; else { @@ -1712,15 +1717,15 @@ } for (i = 0; i < last; i += RAM_INCREMENT) if (readl(eni_dev->ram+i) != i) break; - eni_dev->mem = i << 2; + eni_dev->mem = i; memset_io(eni_dev->ram,0,eni_dev->mem); /* TODO: should shrink allocation now */ printk("mem=%dkB (",eni_dev->mem >> 10); /* TODO: check for non-SUNI, check for TAXI ? */ - if (!(readl(eni_dev->reg+MID_RES_ID_MCON) & 0x200) != !eni_dev->asic) { + if (!(eni_in(MID_RES_ID_MCON) & 0x200) != !eni_dev->asic) { printk(")\n"); - printk(KERN_ERR DEV_LABEL "(itf %d): ERROR - wrong id 0x%0x\n", - dev->number,readl(eni_dev->reg+MID_RES_ID_MCON)); + printk(KERN_ERR DEV_LABEL "(itf %d): ERROR - wrong id 0x%x\n", + dev->number,(unsigned) eni_in(MID_RES_ID_MCON)); return -EINVAL; } error = eni_dev->asic ? get_esi_asic(dev) : get_esi_fpga(dev,base); @@ -1729,8 +1734,8 @@ printk("%s%02X",i ? "-" : "",dev->esi[i]); printk(")\n"); printk(KERN_NOTICE DEV_LABEL "(itf %d): %s,%s\n",dev->number, - readl(eni_dev->reg+MID_RES_ID_MCON) & 0x200 ? "ASIC" : "FPGA", - media_name[readl(eni_dev->reg+MID_RES_ID_MCON) & DAUGTHER_ID]); + eni_in(MID_RES_ID_MCON) & 0x200 ? "ASIC" : "FPGA", + media_name[eni_in(MID_RES_ID_MCON) & DAUGTHER_ID]); return suni_init(dev); } @@ -1738,8 +1743,7 @@ __initfunc(static int eni_start(struct atm_dev *dev)) { struct eni_dev *eni_dev; - u32 *buf; - unsigned long buffer_mem; + unsigned long buf,buffer_mem; int error; DPRINTK(">eni_start\n"); @@ -1765,16 +1769,15 @@ } /* determine addresses of internal tables */ eni_dev->vci = eni_dev->ram; - eni_dev->rx_dma = eni_dev->ram+NR_VCI*4; - eni_dev->tx_dma = eni_dev->rx_dma+NR_DMA_RX*2; - eni_dev->service = eni_dev->tx_dma+NR_DMA_TX*2; - buf = eni_dev->service+NR_SERVICE; - DPRINTK("vci 0x%p,rx 0x%p, tx 0x%p,srv 0x%p,buf 0x%p\n", - eni_dev->vci,eni_dev->rx_dma,eni_dev->tx_dma,eni_dev->service, - buf); + eni_dev->rx_dma = eni_dev->ram+NR_VCI*16; + eni_dev->tx_dma = eni_dev->rx_dma+NR_DMA_RX*8; + eni_dev->service = eni_dev->tx_dma+NR_DMA_TX*8; + buf = eni_dev->service+NR_SERVICE*4; + DPRINTK("vci 0x%lx,rx 0x%lx, tx 0x%lx,srv 0x%lx,buf 0x%lx\n", + eni_dev->vci,eni_dev->rx_dma,eni_dev->tx_dma, + eni_dev->service,buf); /* initialize memory management */ - buffer_mem = eni_dev->mem-((unsigned long) buf- - (unsigned long) eni_dev->ram); + buffer_mem = eni_dev->mem-(buf-eni_dev->ram); eni_dev->free_list_size = buffer_mem/MID_MIN_BUF_SIZE/2; eni_dev->free_list = (struct eni_free *) kmalloc( sizeof(struct eni_free)*(eni_dev->free_list_size+1),GFP_KERNEL); @@ -1784,7 +1787,7 @@ return -ENOMEM; } eni_dev->free_len = 0; - eni_put_free(eni_dev,(unsigned long) buf,buffer_mem); + eni_put_free(eni_dev,buf,buffer_mem); memset_io(eni_dev->vci,0,16*NR_VCI); /* clear VCI table */ /* * byte_addr free (k) @@ -1795,18 +1798,18 @@ * 0x00007000 484 buffers * 0x00080000 0 end (512kB) */ - writel(0xffffffff,eni_dev->reg+MID_IE); + eni_out(0xffffffff,MID_IE); error = start_tx(dev); if (error) return error; error = start_rx(dev); if (error) return error; error = dev->phy->start(dev); if (error) return error; - writel(readl(eni_dev->reg+MID_MC_S) | (1 << MID_INT_SEL_SHIFT) | + eni_out(eni_in(MID_MC_S) | (1 << MID_INT_SEL_SHIFT) | MID_TX_LOCK_MODE | MID_DMA_ENABLE | MID_TX_ENABLE | MID_RX_ENABLE, - eni_dev->reg+MID_MC_S); + MID_MC_S); /* Tonga uses SBus INTReq1 */ - (void) readl(eni_dev->reg+MID_ISA); /* clear Midway interrupts */ + (void) eni_in(MID_ISA); /* clear Midway interrupts */ return 0; } @@ -1942,13 +1945,13 @@ cli(); for (skb = eni_dev->tx_queue.next; skb != (struct sk_buff *) &eni_dev->tx_queue; skb = skb->next) { - u32 *dsc; + unsigned long dsc; if (ATM_SKB(skb)->vcc != vcc) continue; - dsc = tx->send+ENI_PRV_POS(skb); - *dsc = (*dsc & ~(MID_SEG_RATE | MID_SEG_PR)) | + dsc = tx->send+ENI_PRV_POS(skb)*4; + writel((readl(dsc) & ~(MID_SEG_RATE | MID_SEG_PR)) | (tx->prescaler << MID_SEG_PR_SHIFT) | - (tx->resolution << MID_SEG_RATE_SHIFT); + (tx->resolution << MID_SEG_RATE_SHIFT), dsc); } restore_flags(flags); return 0; @@ -2055,14 +2058,14 @@ static void eni_phy_put(struct atm_dev *dev,unsigned char value, unsigned long addr) { - writel(value,ENI_DEV(dev)->phy+addr); + writel(value,ENI_DEV(dev)->phy+addr*4); } static unsigned char eni_phy_get(struct atm_dev *dev,unsigned long addr) { - return readl(ENI_DEV(dev)->phy+addr); + return readl(ENI_DEV(dev)->phy+addr*4); } @@ -2127,9 +2130,10 @@ if (!tx->send) continue; if (--left) continue; - return sprintf(page,"tx[%d]: 0x%06x-0x%06lx (%6ld bytes), " - "rsv %d cps, shp %d cps%s\n",i,(tx->send-eni_dev->ram)*4, - (tx->send-eni_dev->ram+tx->words)*4-1,tx->words*4, + return sprintf(page,"tx[%d]: 0x%06lx-0x%06lx (%6ld bytes), " + "rsv %d cps, shp %d cps%s\n",i, + tx->send-eni_dev->ram, + tx->send-eni_dev->ram+tx->words*4-1,tx->words*4, tx->reserved,tx->shaping, tx == eni_dev->ubr ? " (UBR)" : ""); } @@ -2140,9 +2144,10 @@ if (--left) continue; length = sprintf(page,"vcc %4d: ",vcc->vci); if (eni_vcc->rx) { - length += sprintf(page+length,"0x%06x-0x%06lx " - "(%6ld bytes)",(eni_vcc->recv-eni_dev->ram)*4, - (eni_vcc->recv-eni_dev->ram+eni_vcc->words)*4-1, + length += sprintf(page+length,"0x%06lx-0x%06lx " + "(%6ld bytes)", + eni_vcc->recv-eni_dev->ram, + eni_vcc->recv-eni_dev->ram+eni_vcc->words*4-1, eni_vcc->words*4); if (eni_vcc->tx) length += sprintf(page+length,", "); } @@ -2157,7 +2162,7 @@ unsigned long offset; if (--left) continue; - offset = (unsigned long) eni_dev->ram+eni_dev->base_diff; + offset = eni_dev->ram+eni_dev->base_diff; return sprintf(page,"free 0x%06lx-0x%06lx (%6d bytes)\n", fe->start-offset,fe->start-offset+(1 << fe->order)-1, 1 << fe->order); diff -ur --new-file old/linux/drivers/atm/eni.h new/linux/drivers/atm/eni.h --- old/linux/drivers/atm/eni.h Thu Jun 3 00:40:49 1999 +++ new/linux/drivers/atm/eni.h Thu Jun 3 00:42:17 1999 @@ -31,7 +31,7 @@ }; struct eni_tx { - u32 *send; /* base, NULL if unused */ + unsigned long send; /* base, 0 if unused */ int prescaler; /* shaping prescaler */ int resolution; /* shaping divider */ unsigned long tx_pos; /* current TX write position */ @@ -44,7 +44,7 @@ struct eni_vcc { int (*rx)(struct atm_vcc *vcc); /* RX function, NULL if none */ - u32 *recv; /* receive buffer */ + unsigned long recv; /* receive buffer */ unsigned long words; /* its size in words */ unsigned long descr; /* next descriptor (RX) */ unsigned long rx_pos; /* current RX descriptor pos */ @@ -61,13 +61,13 @@ struct eni_dev { /*-------------------------------- base pointers into Midway address space */ - u32 *phy; /* PHY interface chip registers */ - u32 *reg; /* register base */ - u32 *ram; /* RAM base */ - u32 *vci; /* VCI table */ - u32 *rx_dma; /* RX DMA queue */ - u32 *tx_dma; /* TX DMA queue */ - u32 *service; /* service list */ + unsigned long phy; /* PHY interface chip registers */ + unsigned long reg; /* register base */ + unsigned long ram; /* RAM base */ + unsigned long vci; /* VCI table */ + unsigned long rx_dma; /* RX DMA queue */ + unsigned long tx_dma; /* TX DMA queue */ + unsigned long service; /* service list */ /*-------------------------------- TX part */ struct eni_tx tx[NR_CHAN]; /* TX channels */ struct eni_tx *ubr; /* UBR channel */ diff -ur --new-file old/linux/drivers/atm/midway.h new/linux/drivers/atm/midway.h --- old/linux/drivers/atm/midway.h Thu Jun 3 00:40:49 1999 +++ new/linux/drivers/atm/midway.h Thu Jun 3 00:42:17 1999 @@ -1,6 +1,6 @@ /* drivers/atm/midway.h - Efficient Networks Midway (SAR) description */ -/* Written 1995 by Werner Almesberger, EPFL LRC */ +/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */ #ifndef DRIVERS_ATM_MIDWAY_H @@ -21,7 +21,7 @@ #define PHY_BASE 0x00020000 /* offset of PHY register are */ #define REG_BASE 0x00040000 /* offset of Midway register area */ #define RAM_BASE 0x00200000 /* offset of RAM area */ -#define RAM_INCREMENT 0x00008000 /* probe for RAM every 128kB (32 kw) */ +#define RAM_INCREMENT 0x00020000 /* probe for RAM every 128kB */ #define MID_VCI_BASE RAM_BASE #define MID_DMA_RX_BASE (MID_VCI_BASE+NR_VCI*16) @@ -161,8 +161,8 @@ struct midway_eprom { unsigned char mac[MAC_LEN],inv_mac[MAC_LEN]; unsigned char pad[36]; - unsigned long serial,inv_serial; - unsigned long magic,inv_magic; + u32 serial,inv_serial; + u32 magic,inv_magic; }; diff -ur --new-file old/linux/drivers/atm/nicstar.c new/linux/drivers/atm/nicstar.c --- old/linux/drivers/atm/nicstar.c Thu Jun 3 00:40:49 1999 +++ new/linux/drivers/atm/nicstar.c Thu Jun 3 00:42:18 1999 @@ -2,7 +2,7 @@ * * nicstar.c * - * Device driver supporting CBR for IDT 77211 "NICStAR" based cards. + * Device driver supporting CBR for IDT 77201/77211 "NICStAR" based cards. * * IMPORTANT: The included file nicstarmac.c was NOT WRITTEN BY ME. * It was taken from the frle-0.22 device driver. @@ -11,16 +11,12 @@ * frle-0.22 device driver. * Some code is based on the nicstar driver by M. Welsh. * - * Author: Rui Prior + * Author: Rui Prior (rprior@inescn.pt) + * PowerPC support by Jay Talbott (jay_talbott@mcg.mot.com) April 1999 * - * URLs: - * NICStAR driver homepage - * http://jaguar.inescn.pt/~rprior/nicstar/nicstar.html * - * IDT 77211 documentation - * http://www.idt.com/product_files/77211.html + * (C) INESC 1999 * - * (C) INESC 1998 * ******************************************************************************/ @@ -45,6 +41,9 @@ #include <asm/uaccess.h> #include "nicstar.h" #include "nicstarmac.h" +#ifdef CONFIG_ATM_NICSTAR_USE_SUNI +#include "suni.h" +#endif /* CONFIG_ATM_NICSTAR_USE_SUNI */ /* Additional code ************************************************************/ @@ -153,6 +152,10 @@ static void ns_poll(unsigned long arg); static int ns_parse_mac(char *mac, unsigned char *esi); static short ns_h2i(char c); +static void ns_phy_put(struct atm_dev *dev, unsigned char value, + unsigned long addr); +static unsigned char ns_phy_get(struct atm_dev *dev, unsigned long addr); + /* Global variables ***********************************************************/ @@ -170,8 +173,8 @@ ns_send, /* send */ NULL, /* sg_send */ NULL, /* send_oam */ - NULL, /* phy_put */ - NULL, /* phy_get */ + ns_phy_put, /* phy_put */ + ns_phy_get, /* phy_get */ NULL, /* feedback */ NULL, /* change_qos */ NULL, /* free_rx_skb */ @@ -452,6 +455,11 @@ card->index = i; card->pcidev = pcidev; card->membase = (u32) (pcidev->base_address[1] & PCI_BASE_ADDRESS_MEM_MASK); +#ifdef __powerpc__ + /* Compensate for different memory map between host CPU and PCI bus. + Shouldn't we use a macro for this? */ + card->membase += KERNELBASE; +#endif /* __powerpc__ */ card->membase = (u32) ioremap(card->membase, NS_IOREMAP_SIZE); if (card->membase == (u32) (NULL)) { @@ -555,7 +563,8 @@ printk("nicstar%d: unknown PHY type (0x%08X).\n", i, data); error = 8; ns_init_card_error(card, error); - return error; } + return error; + } writel(0x00000000, card->membase + GP); /* Determine SRAM size */ @@ -597,7 +606,7 @@ if (request_irq(pcidev->irq, &ns_irq_handler, SA_INTERRUPT | SA_SHIRQ, "nicstar", card) != 0) { - printk("nicstar%d: can't allocate IRQ.\n", i); + printk("nicstar%d: can't allocate IRQ %d.\n", i, pcidev->irq); error = 9; ns_init_card_error(card, error); return error; @@ -848,7 +857,8 @@ NS_CFG_RSQAFIE | NS_CFG_TXEN | NS_CFG_TXIE | - NS_CFG_TSQFIE_OPT, /* Only enabled if ENABLE_TSQFIE */ + NS_CFG_TSQFIE_OPT | /* Only enabled if ENABLE_TSQFIE */ + NS_CFG_PHYIE, card->membase + CFG); /* Register device */ @@ -874,6 +884,18 @@ card->atmdev->ci_range.vci_bits = card->vcibits; card->atmdev->link_rate = card->max_pcr; +#ifdef CONFIG_ATM_NICSTAR_USE_SUNI + if (card->max_pcr == ATM_OC3_PCR) { + suni_init(card->atmdev); +#ifdef MODULE + MOD_INC_USE_COUNT; + /* Can't remove the nicstar driver or the suni driver would oops */ +#endif /* MODULE */ + } +#endif /* CONFIG_ATM_NICSTAR_USE_SUNI */ + if (card->atmdev->phy && card->atmdev->phy->start) + card->atmdev->phy->start(card->atmdev); + num_cards++; return error; @@ -1138,8 +1160,10 @@ { u32 stat_r; ns_dev *card; + struct atm_dev *dev; card = (ns_dev *) dev_id; + dev = card->atmdev; card->intcnt++; PRINTK("nicstar%d: NICStAR generated an interrupt\n", card->index); @@ -1195,7 +1219,10 @@ if (stat_r & NS_STAT_PHYI) { writel(NS_STAT_PHYI, card->membase + STAT); - printk("nicstar%d: PHY interrupt.\n", card->index); + PRINTK("nicstar%d: PHY interrupt.\n", card->index); + if (dev->phy && dev->phy->interrupt) { + dev->phy->interrupt(dev); + } } /* Small Buffer Queue is full */ @@ -1329,7 +1356,7 @@ ns_dev *card; vc_map *vc; int error; - double tmpd; + unsigned long tmpl, modl; int tcr, tcra; /* target cell rate, and absolute value */ int n = 0; /* Number of entries in the TST. Initialized to remove the compiler warning. */ @@ -1398,19 +1425,15 @@ PRINTK("nicstar%d: target cell rate = %d.\n", card->index, vcc->qos.txtp.max_pcr); - tmpd = ((double) tcra) * ((double) NS_TST_NUM_ENTRIES) / - ((double) card->max_pcr); + tmpl = (unsigned long)tcra * (unsigned long)NS_TST_NUM_ENTRIES; + modl = tmpl % card->max_pcr; - n = (int) tmpd; + n = (int)(tmpl / card->max_pcr); if (tcr > 0) { - if (tmpd > (double) n) n++; - } - else if (tcr < 0) - { - if (tmpd < (double) n) n--; + if (modl > 0) n++; } - else /* tcr == 0 */ + else if (tcr == 0) { if ((n = (card->tst_free_entries - NS_TST_RESERVED)) <= 0) { @@ -1427,17 +1450,6 @@ return -EINVAL; } - if (vcc->qos.txtp.max_pcr > 0) - { - tmpd = (double) n * (double) card->max_pcr / - (double) NS_TST_NUM_ENTRIES; - if (tmpd > PCR_TOLERANCE * (double) vcc->qos.txtp.max_pcr) - { - PRINTK("nicstar%d: target cell rate exceeded requested max_pcr.\n", - card->index); - } - } - if (n > (card->tst_free_entries - NS_TST_RESERVED)) { PRINTK("nicstar%d: not enough free CBR bandwidth.\n", card->index); @@ -1677,7 +1689,7 @@ static void fill_tst(ns_dev *card, int n, vc_map *vc) { u32 new_tst; - double c, q; + unsigned long cl; int e, r; u32 data; @@ -1694,32 +1706,30 @@ if (card->tste2vc[e] == NULL) break; } - if (e == NS_TST_NUM_ENTRIES) + if (e == NS_TST_NUM_ENTRIES) { printk("nicstar%d: No free TST entries found. \n", card->index); + return; + } r = n; - c = 1.0; - q = (double) n / (double) NS_TST_NUM_ENTRIES; - + cl = NS_TST_NUM_ENTRIES; data = ns_tste_make(NS_TST_OPCODE_FIXED, vc->cbr_scd); - while (e < NS_TST_NUM_ENTRIES) + while (r > 0) { - if (c >= 1.0 && card->tste2vc[e] == NULL) + if (cl >= NS_TST_NUM_ENTRIES && card->tste2vc[e] == NULL) { card->tste2vc[e] = vc; ns_write_sram(card, new_tst + e, &data, 1); - c -= 1.0; - if (--r == 0) - break; + cl -= NS_TST_NUM_ENTRIES; + r--; } - e++; - c += q; + if (++e == NS_TST_NUM_ENTRIES) { + e = 0; + } + cl += n; } - if (r != 0) - printk("nicstar%d: Not enough free TST entries. CBR lower than requested.\n", - card->index); /* End of fill procedure */ @@ -1780,24 +1790,25 @@ { buflen = (skb->len + 47 + 8) / 48 * 48; /* Multiple of 48 */ flags = NS_TBD_AAL5; - scqe.word_2 = (u32) virt_to_bus(skb->data); - scqe.word_3 = (u32) skb->len; - scqe.word_4 = ((u32) vcc->vpi) << NS_TBD_VPI_SHIFT | - ((u32) vcc->vci) << NS_TBD_VCI_SHIFT; + scqe.word_2 = cpu_to_le32((u32) virt_to_bus(skb->data)); + scqe.word_3 = cpu_to_le32((u32) skb->len); + scqe.word_4 = cpu_to_le32(((u32) vcc->vpi) << NS_TBD_VPI_SHIFT | + ((u32) vcc->vci) << NS_TBD_VCI_SHIFT); flags |= NS_TBD_EOPDU; } else /* (vcc->qos.aal == ATM_AAL0) */ { buflen = ATM_CELL_PAYLOAD; /* i.e., 48 bytes */ flags = NS_TBD_AAL0; - scqe.word_2 = (u32) virt_to_bus(skb->data) + NS_AAL0_HEADER; - scqe.word_3 = 0x00000000; + scqe.word_2 = cpu_to_le32((u32) virt_to_bus(skb->data) + NS_AAL0_HEADER); + scqe.word_3 = cpu_to_le32(0x00000000); if (*skb->data & 0x02) /* Payload type 1 - end of pdu */ flags |= NS_TBD_EOPDU; - scqe.word_4 = *((u32 *) skb->data) & ~NS_TBD_VC_MASK; + scqe.word_4 = cpu_to_le32(*((u32 *) skb->data) & ~NS_TBD_VC_MASK); /* Force the VPI/VCI to be the same as in VCC struct */ - scqe.word_4 |= (((u32) vcc->vpi) << NS_TBD_VPI_SHIFT | - ((u32) vcc->vci) << NS_TBD_VCI_SHIFT) & NS_TBD_VC_MASK; + scqe.word_4 |= cpu_to_le32((((u32) vcc->vpi) << NS_TBD_VPI_SHIFT | + ((u32) vcc->vci) << NS_TBD_VCI_SHIFT) & + NS_TBD_VC_MASK); } if (vcc->qos.txtp.traffic_class == ATM_CBR) @@ -1857,7 +1868,8 @@ XPRINTK("nicstar%d: sending skb at 0x%x (pos %d).\n", card->index, (u32) skb, index); XPRINTK("nicstar%d: TBD written:\n0x%x\n0x%x\n0x%x\n0x%x\n at 0x%x.\n", - card->index, tbd->word_1, tbd->word_2, tbd->word_3, tbd->word_4, + card->index, le32_to_cpu(tbd->word_1), le32_to_cpu(tbd->word_2), + le32_to_cpu(tbd->word_3), le32_to_cpu(tbd->word_4), (u32) scq->next); if (scq->next == scq->last) scq->next = scq->base; @@ -1906,7 +1918,8 @@ index = (int) scqi; scq->skb[index] = NULL; XPRINTK("nicstar%d: TSR written:\n0x%x\n0x%x\n0x%x\n0x%x\n at 0x%x.\n", - card->index, tsr.word_1, tsr.word_2, tsr.word_3, tsr.word_4, + card->index, le32_to_cpu(tsr.word_1), le32_to_cpu(tsr.word_2), + le32_to_cpu(tsr.word_3), le32_to_cpu(tsr.word_4), (u32) scq->next); if (scq->next == scq->last) scq->next = scq->base; @@ -1974,7 +1987,7 @@ ns_tsi_init(card->tsq.next); return; } - scq = card->scd2vc[scdi]->scq; + scq = card->scd2vc[scdi]->scq; } drain_scq(card, scq, ns_tsi_getscqpos(card->tsq.next)); scq->full = 0; @@ -2084,7 +2097,7 @@ card->sbfqc = ns_stat_sfbqc_get(stat); card->lbfqc = ns_stat_lfbqc_get(stat); - skb = (struct sk_buff *) rsqe->buffer_handle; + skb = (struct sk_buff *) le32_to_cpu(rsqe->buffer_handle); vpi = ns_rsqe_vpi(rsqe); vci = ns_rsqe_vci(rsqe); if (vpi >= 1UL << card->vpibits || vci >= 1UL << card->vcibits) @@ -2131,7 +2144,7 @@ break; } /* Rebuild the header */ - *((u32 *) sb->data) = rsqe->word_1 << 4 | + *((u32 *) sb->data) = le32_to_cpu(rsqe->word_1) << 4 | (ns_rsqe_clp(rsqe) ? 0x00000001 : 0x00000000); if (i == 1 && ns_rsqe_eopdu(rsqe)) *((u32 *) sb->data) |= 0x00000002; @@ -2231,10 +2244,10 @@ if (ns_rsqe_eopdu(rsqe)) { - aal5_len = *((unsigned short *) ((u32) skb->data + iov->iov_len - 6)); - /* Swap byte order. Is it just me or the nicstar manual sais this should - already be in little endian format? */ - aal5_len = ((aal5_len & 0x00ff) << 8 | (aal5_len & 0xff00) >> 8); + /* This works correctly regardless of the endianness of the host */ + unsigned char *L1L2 = (unsigned char *)((u32)skb->data + + iov->iov_len - 6); + aal5_len = L1L2[0] << 8 | L1L2[1]; len = (aal5_len == 0x0000) ? 0x10000 : aal5_len; if (ns_rsqe_crcerr(rsqe) || len + 8 > iovb->len || len + (47 + 8) < iovb->len) @@ -2896,8 +2909,14 @@ return 0; default: - if (dev->phy->ioctl == NULL) return -EINVAL; - return dev->phy->ioctl(dev, cmd, arg); + if (dev->phy && dev->phy->ioctl) { + return dev->phy->ioctl(dev, cmd, arg); + } + else { + printk("nicstar%d: %s == NULL \n", card->index, + dev->phy ? "dev->phy->ioctl" : "dev->phy"); + return -EINVAL; + } } } @@ -2951,7 +2970,7 @@ process_tsq(card); process_rsq(card); - writel(card->membase + STAT, stat_w); + writel(stat_w, card->membase + STAT); card->in_poll = 0; restore_flags(flags); } @@ -2996,4 +3015,40 @@ if (c >= 'a' && c <= 'f') return (short) (c - 'a' + 10); return -1; +} + + + +static void ns_phy_put(struct atm_dev *dev, unsigned char value, + unsigned long addr) +{ + ns_dev *card; + unsigned long flags; + + card = dev->dev_data; + save_flags(flags); cli(); + while(CMD_BUSY(card)); + writel((unsigned long) value, card->membase + DR0); + writel(NS_CMD_WRITE_UTILITY | 0x00000200 | (addr & 0x000000FF), + card->membase + CMD); + restore_flags(flags); +} + + + +static unsigned char ns_phy_get(struct atm_dev *dev, unsigned long addr) +{ + ns_dev *card; + unsigned long flags; + unsigned long data; + + card = dev->dev_data; + save_flags(flags); cli(); + while(CMD_BUSY(card)); + writel(NS_CMD_READ_UTILITY | 0x00000200 | (addr & 0x000000FF), + card->membase + CMD); + while(CMD_BUSY(card)); + data = readl(card->membase + DR0) & 0x000000FF; + restore_flags(flags); + return (unsigned char) data; } diff -ur --new-file old/linux/drivers/atm/nicstar.h new/linux/drivers/atm/nicstar.h --- old/linux/drivers/atm/nicstar.h Thu Jun 3 00:40:49 1999 +++ new/linux/drivers/atm/nicstar.h Thu Jun 3 00:42:17 1999 @@ -4,7 +4,8 @@ * * Header file for the nicstar device driver. * - * Author: Rui Prior + * Author: Rui Prior (rprior@inescn.pt) + * PowerPC support by Jay Talbott (jay_talbott@mcg.mot.com) April 1999 * * (C) INESC 1998 * @@ -135,8 +136,10 @@ u32 word_4; } ns_rsqe; -#define ns_rsqe_vpi(ns_rsqep) (((ns_rsqep)->word_1 & 0x00FF0000) >> 16) -#define ns_rsqe_vci(ns_rsqep) ((ns_rsqep)->word_1 & 0x0000FFFF) +#define ns_rsqe_vpi(ns_rsqep) \ + ((le32_to_cpu((ns_rsqep)->word_1) & 0x00FF0000) >> 16) +#define ns_rsqe_vci(ns_rsqep) \ + (le32_to_cpu((ns_rsqep)->word_1) & 0x0000FFFF) #define NS_RSQE_VALID 0x80000000 #define NS_RSQE_NZGFC 0x00004000 @@ -149,16 +152,25 @@ #define NS_RSQE_BUFSIZE_SM 0x00000000 #define NS_RSQE_BUFSIZE_LG 0x00001000 -#define ns_rsqe_valid(ns_rsqep) ((ns_rsqep)->word_4 & NS_RSQE_VALID) -#define ns_rsqe_nzgfc(ns_rsqep) ((ns_rsqep)->word_4 & NS_RSQE_NZGFC) -#define ns_rsqe_eopdu(ns_rsqep) ((ns_rsqep)->word_4 & NS_RSQE_EOPDU) -#define ns_rsqe_bufsize(ns_rsqep) ((ns_rsqep)->word_4 & NS_RSQE_BUFSIZE) -#define ns_rsqe_congestion(ns_rsqep) ((ns_rsqep)->word_4 & NS_RSQE_CONGESTION) -#define ns_rsqe_clp(ns_rsqep) ((ns_rsqep)->word_4 & NS_RSQE_CLP) -#define ns_rsqe_crcerr(ns_rsqep) ((ns_rsqep)->word_4 & NS_RSQE_CRCERR) - -#define ns_rsqe_cellcount(ns_rsqep) ((ns_rsqep)->word_4 & 0x000001FF) -#define ns_rsqe_init(ns_rsqep) ((ns_rsqep)->word_4 = 0x00000000) +#define ns_rsqe_valid(ns_rsqep) \ + (le32_to_cpu((ns_rsqep)->word_4) & NS_RSQE_VALID) +#define ns_rsqe_nzgfc(ns_rsqep) \ + (le32_to_cpu((ns_rsqep)->word_4) & NS_RSQE_NZGFC) +#define ns_rsqe_eopdu(ns_rsqep) \ + (le32_to_cpu((ns_rsqep)->word_4) & NS_RSQE_EOPDU) +#define ns_rsqe_bufsize(ns_rsqep) \ + (le32_to_cpu((ns_rsqep)->word_4) & NS_RSQE_BUFSIZE) +#define ns_rsqe_congestion(ns_rsqep) \ + (le32_to_cpu((ns_rsqep)->word_4) & NS_RSQE_CONGESTION) +#define ns_rsqe_clp(ns_rsqep) \ + (le32_to_cpu((ns_rsqep)->word_4) & NS_RSQE_CLP) +#define ns_rsqe_crcerr(ns_rsqep) \ + (le32_to_cpu((ns_rsqep)->word_4) & NS_RSQE_CRCERR) + +#define ns_rsqe_cellcount(ns_rsqep) \ + (le32_to_cpu((ns_rsqep)->word_4) & 0x000001FF) +#define ns_rsqe_init(ns_rsqep) \ + ((ns_rsqep)->word_4 = cpu_to_le32(0x00000000)) #define NS_RSQ_NUM_ENTRIES (NS_RSQSIZE / 16) #define NS_RSQ_ALIGNMENT NS_RSQSIZE @@ -186,9 +198,12 @@ #define NS_RCQE_SIZE 64 /* bytes */ -#define ns_rcqe_islast(ns_rcqep) ((ns_rcqep)->word_2 != 0x00000000) -#define ns_rcqe_cellheader(ns_rcqep) ((ns_rcqep)->word_1) -#define ns_rcqe_nextbufhandle(ns_rcqep) ((ns_rcqep)->word_2) +#define ns_rcqe_islast(ns_rcqep) \ + (le32_to_cpu((ns_rcqep)->word_2) != 0x00000000) +#define ns_rcqe_cellheader(ns_rcqep) \ + (le32_to_cpu((ns_rcqep)->word_1)) +#define ns_rcqe_nextbufhandle(ns_rcqep) \ + (le32_to_cpu((ns_rcqep)->word_2)) @@ -224,20 +239,27 @@ #define NS_TBD_VPI_SHIFT 20 #define NS_TBD_VCI_SHIFT 4 -#define ns_tbd_mkword_1(flags, m, n, buflen) (flags | m << 23 | n << 16 | buflen) -#define ns_tbd_mkword_1_novbr(flags, buflen) (flags | buflen | 0x00810000) -#define ns_tbd_mkword_3(control, pdulen) (control << 16 | pdulen) -#define ns_tbd_mkword_4(gfc, vpi, vci, pt, clp) (gfc << 28 | vpi << 20 | vci << 4 | pt << 1 | clp)) +#define ns_tbd_mkword_1(flags, m, n, buflen) \ + (cpu_to_le32(flags | m << 23 | n << 16 | buflen)) +#define ns_tbd_mkword_1_novbr(flags, buflen) \ + (cpu_to_le32(flags | buflen | 0x00810000)) +#define ns_tbd_mkword_3(control, pdulen) \ + (cpu_to_le32(control << 16 | pdulen)) +#define ns_tbd_mkword_4(gfc, vpi, vci, pt, clp) \ + (cpu_to_le32(gfc << 28 | vpi << 20 | vci << 4 | pt << 1 | clp))) #define NS_TSR_INTENABLE 0x20000000 #define NS_TSR_SCDISVBR 0xFFFF /* Use as scdi for VBR SCD */ -#define ns_tsr_mkword_1(flags) (NS_SCQE_TYPE_TSR | (flags)) -#define ns_tsr_mkword_2(scdi, scqi) ((scdi) << 16 | 0x00008000 | (scqi)) +#define ns_tsr_mkword_1(flags) \ + (cpu_to_le32(NS_SCQE_TYPE_TSR | (flags))) +#define ns_tsr_mkword_2(scdi, scqi) \ + (cpu_to_le32((scdi) << 16 | 0x00008000 | (scqi))) -#define ns_scqe_is_tsr(ns_scqep) ((ns_scqep)->word_1 & NS_SCQE_TYPE_TSR) +#define ns_scqe_is_tsr(ns_scqep) \ + (le32_to_cpu((ns_scqep)->word_1) & NS_SCQE_TYPE_TSR) #define VBR_SCQ_NUM_ENTRIES 512 #define VBR_SCQSIZE 8192 @@ -266,10 +288,13 @@ #define NS_TSI_EMPTY 0x80000000 #define NS_TSI_TIMESTAMP_MASK 0x00FFFFFF -#define ns_tsi_isempty(ns_tsip) ((ns_tsip)->word_2 & NS_TSI_EMPTY) -#define ns_tsi_gettimestamp(ns_tsip) ((ns_tsip)->word_2 & NS_TSI_TIMESTAMP_MASK) +#define ns_tsi_isempty(ns_tsip) \ + (le32_to_cpu((ns_tsip)->word_2) & NS_TSI_EMPTY) +#define ns_tsi_gettimestamp(ns_tsip) \ + (le32_to_cpu((ns_tsip)->word_2) & NS_TSI_TIMESTAMP_MASK) -#define ns_tsi_init(ns_tsip) ((ns_tsip)->word_2 = NS_TSI_EMPTY) +#define ns_tsi_init(ns_tsip) \ + ((ns_tsip)->word_2 = cpu_to_le32(NS_TSI_EMPTY)) #define NS_TSQSIZE 8192 @@ -279,9 +304,12 @@ #define NS_TSI_SCDISVBR NS_TSR_SCDISVBR -#define ns_tsi_tmrof(ns_tsip) ((ns_tsip)->word_1 == 0x00000000) -#define ns_tsi_getscdindex(ns_tsip) (((ns_tsip)->word_1 & 0xFFFF0000) >> 16) -#define ns_tsi_getscqpos(ns_tsip) ((ns_tsip)->word_1 & 0x00007FFF) +#define ns_tsi_tmrof(ns_tsip) \ + (le32_to_cpu((ns_tsip)->word_1) == 0x00000000) +#define ns_tsi_getscdindex(ns_tsip) \ + ((le32_to_cpu((ns_tsip)->word_1) & 0xFFFF0000) >> 16) +#define ns_tsi_getscqpos(ns_tsip) \ + (le32_to_cpu((ns_tsip)->word_1) & 0x00007FFF) diff -ur --new-file old/linux/include/linux/atm.h new/linux/include/linux/atm.h --- old/linux/include/linux/atm.h Thu Jun 3 00:40:51 1999 +++ new/linux/include/linux/atm.h Thu Jun 3 00:42:18 1999 @@ -1,6 +1,6 @@ /* atm.h - general ATM declarations */ -/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ +/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */ /* @@ -46,7 +46,6 @@ #define ATM_AAL2 2 /* AAL2 (VBR) */ #define ATM_AAL34 3 /* AAL3/4 (data) */ #define ATM_AAL5 5 /* AAL5 (data) */ -#define ATM_SAAL 12 /* signaling AAL */ /* socket option name coding functions */ diff -ur --new-file old/linux/include/linux/atmlec.h new/linux/include/linux/atmlec.h --- old/linux/include/linux/atmlec.h Thu Jun 3 00:40:51 1999 +++ new/linux/include/linux/atmlec.h Thu Jun 3 00:42:18 1999 @@ -18,7 +18,13 @@ #define ATMLEC_MCAST _IO('a',ATMIOC_LANE+2) /* Maximum number of LEC interfaces (tweakable) */ -#define MAX_LEC_ITF 16 +#define MAX_LEC_ITF 48 + +/* From the total of MAX_LEC_ITF, last NUM_TR_DEVS are reserved for Token Ring. + * E.g. if MAX_LEC_ITF = 48 and NUM_TR_DEVS = 8, then lec0-lec39 are for + * Ethernet ELANs and lec40-lec47 are for Token Ring ELANS. + */ +#define NUM_TR_DEVS 8 typedef enum { l_set_mac_addr, l_del_mac_addr, @@ -28,6 +34,7 @@ l_narp_req, /* LANE2 mandates the use of this */ l_config, l_flush_tran_id, l_set_lecid, l_arp_xmt, + l_rdesc_arp_xmt, l_associate_req, l_should_bridge /* should we bridge this MAC? */ } atmlec_msg_type; diff -ur --new-file old/linux/net/802/tr.c new/linux/net/802/tr.c --- old/linux/net/802/tr.c Wed Dec 16 22:35:50 1998 +++ new/linux/net/802/tr.c Thu Jun 3 00:42:21 1999 @@ -51,7 +51,7 @@ struct rif_cache_s { unsigned char addr[TR_ALEN]; - unsigned char iface[5]; + unsigned char iface[10]; __u16 rcf; __u16 rseg[8]; rif_cache next; @@ -354,7 +354,8 @@ } memcpy(&(entry->addr[0]),&(trh->saddr[0]),TR_ALEN); - memcpy(&(entry->iface[0]),dev->name,5); + strncpy(entry->iface,dev->name,sizeof(entry->iface)); + entry->iface[sizeof(entry->iface)-1] = '\0'; entry->next=rif_table[hash]; entry->last_used=jiffies; rif_table[hash]=entry; diff -ur --new-file old/linux/net/atm/common.c new/linux/net/atm/common.c --- old/linux/net/atm/common.c Thu Jun 3 00:40:52 1999 +++ new/linux/net/atm/common.c Thu Jun 3 00:42:21 1999 @@ -275,11 +275,14 @@ if (vpi != ATM_VPI_UNSPEC && vci != ATM_VCI_UNSPEC) vcc->flags &= ~ATM_VF_PARTIAL; else if (vcc->flags & ATM_VF_PARTIAL) return -EINVAL; - printk("atm_connect (TX: cl %d,bw %d-%d,sdu %d; RX: cl %d,bw %d-%d," - "sdu %d,AAL %d)\n",vcc->qos.txtp.traffic_class, - vcc->qos.txtp.min_pcr,vcc->qos.txtp.max_pcr,vcc->qos.txtp.max_sdu, + printk(KERN_DEBUG "atm_connect (TX: cl %d,bw %d-%d,sdu %d; " + "RX: cl %d,bw %d-%d,sdu %d,AAL %s%d)\n", + vcc->qos.txtp.traffic_class,vcc->qos.txtp.min_pcr, + vcc->qos.txtp.max_pcr,vcc->qos.txtp.max_sdu, vcc->qos.rxtp.traffic_class,vcc->qos.rxtp.min_pcr, - vcc->qos.rxtp.max_pcr,vcc->qos.rxtp.max_sdu,vcc->qos.aal); + vcc->qos.rxtp.max_pcr,vcc->qos.rxtp.max_sdu, + vcc->qos.aal == ATM_AAL5 ? "" : vcc->qos.aal == ATM_AAL0 ? "" : + " ??? code ",vcc->qos.aal == ATM_AAL0 ? 0 : vcc->qos.aal); if (!(vcc->flags & ATM_VF_HASQOS)) return -EBADFD; if (vcc->qos.txtp.traffic_class == ATM_ANYCLASS || vcc->qos.rxtp.traffic_class == ATM_ANYCLASS) diff -ur --new-file old/linux/net/atm/lec.c new/linux/net/atm/lec.c --- old/linux/net/atm/lec.c Thu Jun 3 00:40:52 1999 +++ new/linux/net/atm/lec.c Thu Jun 3 00:42:21 1999 @@ -19,6 +19,11 @@ #include <net/dst.h> #include <linux/proc_fs.h> +/* TokenRing if needed */ +#ifdef CONFIG_TR +#include <linux/trdevice.h> +#endif + /* And atm device */ #include <linux/atmdev.h> #include <linux/atmlec.h> @@ -75,7 +80,9 @@ }; /* will be lec0, lec1, lec2 etc. */ -static char myname[] = "lecx"; +static char myname[] = "lecxx"; + +static unsigned char bus_mac[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff}; /* Device structures */ static struct device *dev_lec[MAX_LEC_ITF]; @@ -113,10 +120,7 @@ mesg->content.normal.flag = *(skb->nh.raw + BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET) & TOPOLOGY_CHANGE; priv = (struct lec_priv *)dev->priv; - if (atm_charge(priv->lecd, skb2->truesize) == 0) { - kfree_skb(skb2); - return; - } + atm_force_charge(priv->lecd, skb2->truesize); skb_queue_tail(&priv->lecd->recvq, skb2); wake_up(&priv->lecd->sleep); } @@ -126,6 +130,49 @@ #endif /* CONFIG_BRIDGE */ /* + * Modelled after tr_type_trans + * All multicast and ARE or STE frames go to BUS. + * Non source routed frames go by destination address. + * Last hop source routed frames go by destination address. + * Not last hop source routed frames go by _next_ route descriptor. + * Returns pointer to destination MAC address or fills in rdesc + * and returns NULL. + */ +#ifdef CONFIG_TR +unsigned char *get_tr_dst(unsigned char *packet, unsigned char *rdesc) +{ + struct trh_hdr *trh; + int riflen, num_rdsc; + + trh = (struct trh_hdr *)packet; + if (trh->daddr[0] & (uint8_t)0x80) + return bus_mac; /* multicast */ + + if (trh->saddr[0] & TR_RII) { + riflen = (ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8; + if ((ntohs(trh->rcf) >> 13) != 0) + return bus_mac; /* ARE or STE */ + } + else + return trh->daddr; /* not source routed */ + + if (riflen < 6) + return trh->daddr; /* last hop, source routed */ + + /* riflen is 6 or more, packet has more than one route descriptor */ + num_rdsc = (riflen/2) - 1; + memset(rdesc, 0, ETH_ALEN); + /* offset 4 comes from LAN destination field in LE control frames */ + if (trh->rcf & htons((uint16_t)TR_RCF_DIR_BIT)) + memcpy(&rdesc[4], &trh->rseg[num_rdsc-2], sizeof(uint16_t)); + else + memcpy(&rdesc[4], &trh->rseg[1], sizeof(uint16_t)); + + return NULL; +} +#endif /* CONFIG_TR */ + +/* * Open/initialize the netdevice. This is called (in the current kernel) * sometime after booting when the 'ifconfig' program is run. * @@ -155,7 +202,9 @@ struct lecdatahdr_8023 *lec_h; struct atm_vcc *send_vcc; struct lec_arp_table *entry; - unsigned char *nb; + unsigned char *nb, *dst; + unsigned char rdesc[ETH_ALEN]; /* Token Ring route descriptor */ + int is_rdesc; #if DUMP_PACKETS > 0 char buf[300]; int i=0; @@ -205,7 +254,7 @@ } skb_push(skb, 2); - /* Put le header to place */ + /* Put le header to place, works for TokenRing too */ lec_h = (struct lecdatahdr_8023*)skb->data; lec_h->le_header = htons(priv->lecid); @@ -247,8 +296,19 @@ } /* Send to right vcc */ + is_rdesc = 0; + dst = lec_h->h_dest; +#ifdef CONFIG_TR + if (priv->is_trdev) { + dst = get_tr_dst(skb->data+2, rdesc); + if (dst == NULL) { + dst = rdesc; + is_rdesc = 1; + } + } +#endif entry = NULL; - send_vcc = lec_arp_resolve(priv, lec_h->h_dest, &entry); + send_vcc = lec_arp_resolve(priv, dst, is_rdesc, &entry); DPRINTK("%s:send_vcc:%p vcc_flags:%x, entry:%p\n", dev->name, send_vcc, send_vcc?send_vcc->flags:0, entry); if (!send_vcc || !(send_vcc->flags & ATM_VF_READY)) { @@ -430,10 +490,7 @@ if (skb2 == NULL) break; skb2->len = sizeof(struct atmlec_msg); memcpy(skb2->data, mesg, sizeof(struct atmlec_msg)); - if (atm_charge(priv->lecd, skb2->truesize) == 0) { - kfree_skb(skb2); - break; - } + atm_force_charge(priv->lecd, skb2->truesize); skb_queue_tail(&priv->lecd->recvq, skb2); wake_up(&priv->lecd->sleep); } @@ -540,21 +597,13 @@ if (atm_addr) memcpy(&mesg->content.normal.atm_addr, atm_addr, ATM_ESA_LEN); - if (atm_charge(priv->lecd, skb->truesize) == 0) { - DPRINTK("lec: send_to_lecd, atm_charge()\n"); - kfree_skb(skb); - return -1; - } + atm_force_charge(priv->lecd, skb->truesize); skb_queue_tail(&priv->lecd->recvq, skb); wake_up(&priv->lecd->sleep); if (data != NULL) { DPRINTK("lec: about to send %d bytes of data\n", data->len); - if (atm_charge(priv->lecd, data->truesize) == 0) { - printk("lec: send_to_lecd, atm_charge\n"); - kfree_skb(data); - return -1; - } + atm_force_charge(priv->lecd, data->truesize); skb_queue_tail(&priv->lecd->recvq, data); wake_up(&priv->lecd->sleep); } @@ -574,13 +623,14 @@ static int lec_init(struct device *dev) { - dev->priv = kmalloc(sizeof(struct lec_priv), GFP_KERNEL); - if (!dev->priv) - return -ENOMEM; - - memset(dev->priv,0,sizeof(struct lec_priv)); + struct lec_priv *priv; - ether_setup(dev); + priv = (struct lec_priv *)dev->priv; + if (priv->is_trdev) { +#ifdef CONFIG_TR + init_trdev(dev, 0); +#endif + } else ether_setup(dev); dev->change_mtu = lec_change_mtu; dev->open = lec_open; dev->stop = lec_close; @@ -655,6 +705,10 @@ } skb->dev = dev; skb->data += 2; /* skip lec_id */ +#ifdef CONFIG_TR + if (priv->is_trdev) skb->protocol = tr_type_trans(skb, dev); + else +#endif skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); priv->stats.rx_packets++; @@ -703,8 +757,13 @@ i = 0; else i = arg; +#ifdef CONFIG_TR if (arg >= MAX_LEC_ITF) return -EINVAL; +#else /* Reserve the top NUM_TR_DEVS for TR */ + if (arg >= (MAX_LEC_ITF-NUM_TR_DEVS)) + return -EINVAL; +#endif if (!dev_lec[i]) { dev_lec[i] = (struct device*)kmalloc(sizeof(struct device)+ sizeof(myname)+1, @@ -712,13 +771,23 @@ if (!dev_lec[i]) return -ENOMEM; memset(dev_lec[i],0, sizeof(struct device)+sizeof(myname)+1); + + dev_lec[i]->priv = kmalloc(sizeof(struct lec_priv), GFP_KERNEL); + if (!dev_lec[i]->priv) + return -ENOMEM; + memset(dev_lec[i]->priv,0,sizeof(struct lec_priv)); + priv = (struct lec_priv *)dev_lec[i]->priv; + + if (i >= (MAX_LEC_ITF - NUM_TR_DEVS)) + priv->is_trdev = 1; + dev_lec[i]->name = (char*)(dev_lec[i]+1); sprintf(dev_lec[i]->name, "lec%d",i); dev_lec[i]->init = lec_init; if ((result = register_netdev(dev_lec[i])) !=0) return result; - priv = (struct lec_priv *)dev_lec[i]->priv; - } else { + sprintf(dev_lec[i]->name, "lec%d", i); /* init_trdev globbers device name */ + } else { priv = (struct lec_priv *)dev_lec[i]->priv; if (priv->lecd) return -EADDRINUSE; @@ -777,6 +846,7 @@ { int i; extern struct atm_lane_ops atm_lane_ops; + struct lec_priv *priv; if (MOD_IN_USE) { printk(KERN_NOTICE "lec.c: module in use\n"); @@ -790,7 +860,13 @@ for (i = 0; i < MAX_LEC_ITF; i++) { if (dev_lec[i] != NULL) { - unregister_netdev(dev_lec[i]); + priv = (struct lec_priv *)dev_lec[i]->priv; + if (priv->is_trdev) { +#ifdef CONFIG_TR + unregister_trdev(dev_lec[i]); +#endif + } else + unregister_netdev(dev_lec[i]); kfree(dev_lec[i]->priv); kfree(dev_lec[i]); dev_lec[i] = NULL; @@ -1411,8 +1487,10 @@ DPRINTK("lec_arp_expire_arp\n"); if (entry->status == ESI_ARP_PENDING) { if (entry->no_tries <= entry->priv->max_retry_count) { - send_to_lecd(entry->priv, l_arp_xmt, - entry->mac_addr, NULL, NULL); + if (entry->is_rdesc) + send_to_lecd(entry->priv, l_rdesc_arp_xmt, entry->mac_addr, NULL, NULL); + else + send_to_lecd(entry->priv, l_arp_xmt, entry->mac_addr, NULL, NULL); entry->no_tries++; } entry->timer.expires = jiffies + (1*HZ); @@ -1552,10 +1630,9 @@ * */ struct atm_vcc* -lec_arp_resolve(struct lec_priv *priv, unsigned char *mac_to_find, +lec_arp_resolve(struct lec_priv *priv, unsigned char *mac_to_find, int is_rdesc, struct lec_arp_table **ret_entry) { - unsigned char bus_mac[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff}; struct lec_arp_table *entry; if (mac_to_find[0]&0x01) { @@ -1611,7 +1688,11 @@ entry->status = ESI_ARP_PENDING; entry->no_tries = 1; entry->last_used = entry->timestamp = jiffies; - send_to_lecd(priv, l_arp_xmt, mac_to_find, NULL, NULL); + entry->is_rdesc = is_rdesc; + if (entry->is_rdesc) + send_to_lecd(priv, l_rdesc_arp_xmt, mac_to_find, NULL, NULL); + else + send_to_lecd(priv, l_arp_xmt, mac_to_find, NULL, NULL); entry->timer.expires = jiffies + (1*HZ); entry->timer.function = lec_arp_expire_arp; add_timer(&entry->timer); @@ -1764,7 +1845,6 @@ { struct lec_arp_table *entry; int i, found_entry=0; - unsigned char bus_mac[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff,0xff}; lec_arp_lock(priv); if (ioc_data->receive == 2) { @@ -2042,20 +2122,28 @@ struct lec_arp_table *entry, *prev; struct lecdatahdr_8023 *hdr = (struct lecdatahdr_8023 *)skb->data; unsigned long flags; - + unsigned char *src; +#ifdef CONFIG_TR + struct lecdatahdr_8025 *tr_hdr = (struct lecdatahdr_8025 *)skb->data; + + if (priv->is_trdev) src = tr_hdr->h_source; + else +#endif + src = hdr->h_source; + lec_arp_lock(priv); entry = priv->lec_arp_empty_ones; if (vcc == entry->vcc) { save_flags(flags); cli(); del_timer(&entry->timer); - memcpy(entry->mac_addr, hdr->h_source, ETH_ALEN); + memcpy(entry->mac_addr, src, ETH_ALEN); entry->status = ESI_FORWARD_DIRECT; entry->last_used = jiffies; priv->lec_arp_empty_ones = entry->next; restore_flags(flags); /* We might have got an entry */ - if ((prev=lec_arp_find(priv,hdr->h_source))) { + if ((prev=lec_arp_find(priv,src))) { lec_arp_remove(priv->lec_arp_tables, prev); kfree(prev); } @@ -2077,12 +2165,12 @@ save_flags(flags); cli(); del_timer(&entry->timer); - memcpy(entry->mac_addr, hdr->h_source, ETH_ALEN); + memcpy(entry->mac_addr, src, ETH_ALEN); entry->status = ESI_FORWARD_DIRECT; entry->last_used = jiffies; prev->next = entry->next; restore_flags(flags); - if ((prev = lec_arp_find(priv, hdr->h_source))) { + if ((prev = lec_arp_find(priv, src))) { lec_arp_remove(priv->lec_arp_tables,prev); kfree(prev); } diff -ur --new-file old/linux/net/atm/lec.h new/linux/net/atm/lec.h --- old/linux/net/atm/lec.h Thu Jun 3 00:40:52 1999 +++ new/linux/net/atm/lec.h Thu Jun 3 00:42:21 1999 @@ -26,7 +26,7 @@ unsigned short le_header; unsigned char ac_pad; unsigned char fc; - unsigned char h_dst[ETH_ALEN]; + unsigned char h_dest[ETH_ALEN]; unsigned char h_source[ETH_ALEN]; }; @@ -131,6 +131,7 @@ int itfnum; /* e.g. 2 for lec2, 5 for lec5 */ struct lane2_ops *lane2_ops; /* can be NULL for LANE v1 */ int is_proxy; /* bridge between ATM and Ethernet */ + int is_trdev; /* Device type, 0 = Ethernet, 1 = TokenRing */ }; int lecd_attach(struct atm_vcc *vcc, int arg); diff -ur --new-file old/linux/net/atm/lec_arpc.h new/linux/net/atm/lec_arpc.h --- old/linux/net/atm/lec_arpc.h Thu Jun 3 00:40:53 1999 +++ new/linux/net/atm/lec_arpc.h Thu Jun 3 00:42:21 1999 @@ -14,6 +14,7 @@ struct lec_arp_table *next; /* Linked entry list */ unsigned char atm_addr[ATM_ESA_LEN]; /* Atm address */ unsigned char mac_addr[ETH_ALEN]; /* Mac address */ + int is_rdesc; /* Mac address is a route descriptor */ struct atm_vcc *vcc; /* Vcc this entry is attached */ struct atm_vcc *recv_vcc; /* Vcc we receive data from */ void (*old_push)(struct atm_vcc *vcc,struct sk_buff *skb); @@ -96,6 +97,7 @@ struct atm_vcc *lec_arp_resolve(struct lec_priv *priv, unsigned char *mac_to_addr, + int is_rdesc, struct lec_arp_table **ret_entry); void lec_vcc_added(struct lec_priv *dev, struct atmlec_ioc *ioc_data, struct atm_vcc *vcc, diff -ur --new-file old/linux/net/atm/mpc.c new/linux/net/atm/mpc.c --- old/linux/net/atm/mpc.c Thu Jun 3 00:40:53 1999 +++ new/linux/net/atm/mpc.c Thu Jun 3 00:42:21 1999 @@ -951,12 +951,7 @@ return -ENOMEM; skb_put(skb, sizeof(struct k_message)); memcpy(skb->data, mesg, sizeof(struct k_message)); - if (atm_charge(mpc->mpoad_vcc, skb->truesize) == 0) { - printk("mpoa: msg_to_mpoad: atm_charge failed\n"); - kfree_skb(skb); - return -ENOMEM; - } - + atm_force_charge(mpc->mpoad_vcc, skb->truesize); skb_queue_tail(&mpc->mpoad_vcc->recvq, skb); wake_up(&mpc->mpoad_vcc->sleep); @@ -1215,12 +1210,7 @@ if (entry != NULL) purge_msg->content.eg_info = entry->ctrl_info; - if (atm_charge(vcc, skb->truesize) == 0) { - printk("mpoa: purge_egress_shortcut: atm_charge failed\n"); - kfree_skb(skb); - return; - } - + atm_force_charge(vcc, skb->truesize); skb_queue_tail(&vcc->recvq, skb); wake_up(&vcc->sleep); dprintk("mpoa: purge_egress_shortcut: exiting:\n"); diff -ur --new-file old/linux/net/atm/proc.c new/linux/net/atm/proc.c --- old/linux/net/atm/proc.c Thu Jun 3 00:40:53 1999 +++ new/linux/net/atm/proc.c Thu Jun 3 00:42:21 1999 @@ -245,8 +245,10 @@ { static const char *class_name[] = { "off","UBR","CBR","VBR","ABR" }; static const char *aal_name[] = { - "0", "1", "2", "3/4", /* 0- 3 */ - "???", "5", "???", "???" };/* 4- 7 */ + "---", "1", "2", "3/4", /* 0- 3 */ + "???", "5", "???", "???", /* 4- 7 */ + "???", "???", "???", "???", /* 8-11 */ + "???", "0", "???", "???"}; /* 12-15 */ int off; off = sprintf(buf,"%3d %3d %5d %-3s %7d %-5s %7d %-6s",