patch-2.3.35 linux/drivers/net/myri_sbus.c
Next file: linux/drivers/net/myri_sbus.h
Previous file: linux/drivers/net/irda/w83977af_ir.c
Back to the patch index
Back to the overall index
- Lines: 970
- Date:
Mon Dec 20 22:06:42 1999
- Orig file:
v2.3.34/linux/drivers/net/myri_sbus.c
- Orig date:
Thu Nov 11 20:11:41 1999
diff -u --recursive --new-file v2.3.34/linux/drivers/net/myri_sbus.c linux/drivers/net/myri_sbus.c
@@ -1,10 +1,10 @@
/* myri_sbus.h: MyriCOM MyriNET SBUS card driver.
*
- * Copyright (C) 1996 David S. Miller ([email protected])
+ * Copyright (C) 1996, 1999 David S. Miller ([email protected])
*/
static char *version =
- "myri_sbus.c:v1.0 10/Dec/96 David S. Miller ([email protected])\n";
+ "myri_sbus.c:v1.9 12/Sep/99 David S. Miller ([email protected])\n";
#include <linux/module.h>
@@ -92,73 +92,79 @@
static struct myri_eth *root_myri_dev = NULL;
#endif
-static inline void myri_reset_off(struct lanai_regs *lp, struct myri_control *cregs)
+static void myri_reset_off(unsigned long lp, unsigned long cregs)
{
- lp->eimask = 0; /* Clear IRQ mask. */
- cregs->ctrl = CONTROL_ROFF; /* Turn RESET function off. */
+ /* Clear IRQ mask. */
+ sbus_writel(0, lp + LANAI_EIMASK);
+
+ /* Turn RESET function off. */
+ sbus_writel(CONTROL_ROFF, cregs + MYRICTRL_CTRL);
}
-static inline void myri_reset_on(struct myri_control *cregs)
+static void myri_reset_on(unsigned long cregs)
{
- cregs->ctrl = CONTROL_RON; /* Enable RESET function. */
- cregs->ctrl = CONTROL_DIRQ; /* Disable IRQ's. */
+ /* Enable RESET function. */
+ sbus_writel(CONTROL_RON, cregs + MYRICTRL_CTRL);
+
+ /* Disable IRQ's. */
+ sbus_writel(CONTROL_DIRQ, cregs + MYRICTRL_CTRL);
}
-static inline void myri_disable_irq(struct lanai_regs *lp, struct myri_control *cregs)
+static void myri_disable_irq(unsigned long lp, unsigned long cregs)
{
- cregs->ctrl = CONTROL_DIRQ;
- lp->eimask = 0;
- lp->istat = ISTAT_HOST;
+ sbus_writel(CONTROL_DIRQ, cregs + MYRICTRL_CTRL);
+ sbus_writel(0, lp + LANAI_EIMASK);
+ sbus_writel(ISTAT_HOST, lp + LANAI_ISTAT);
}
-static inline void myri_enable_irq(struct lanai_regs *lp, struct myri_control *cregs)
+static void myri_enable_irq(unsigned long lp, unsigned long cregs)
{
- cregs->ctrl = CONTROL_EIRQ;
- lp->eimask = ISTAT_HOST;
+ sbus_writel(CONTROL_EIRQ, cregs + MYRICTRL_CTRL);
+ sbus_writel(ISTAT_HOST, lp + LANAI_EIMASK);
}
static inline void bang_the_chip(struct myri_eth *mp)
{
struct myri_shmem *shmem = mp->shmem;
- struct myri_control *cregs = mp->cregs;
+ unsigned long cregs = mp->cregs;
- shmem->send = 1;
- cregs->ctrl = CONTROL_WON;
+ sbus_writel(1, &shmem->send);
+ sbus_writel(CONTROL_WON, cregs + MYRICTRL_CTRL);
}
-static inline int myri_do_handshake(struct myri_eth *mp)
+static int myri_do_handshake(struct myri_eth *mp)
{
struct myri_shmem *shmem = mp->shmem;
- struct myri_control *cregs = mp->cregs;
+ unsigned long cregs = mp->cregs;
struct myri_channel *chan = &shmem->channel;
int tick = 0;
DET(("myri_do_handshake: "));
- if(chan->state == STATE_READY) {
+ if (sbus_readl(&chan->state) == STATE_READY) {
DET(("Already STATE_READY, failed.\n"));
return -1; /* We're hosed... */
}
myri_disable_irq(mp->lregs, cregs);
- while(tick++ <= 25) {
- unsigned int softstate;
+ while (tick++ <= 25) {
+ u32 softstate;
/* Wake it up. */
DET(("shakedown, CONTROL_WON, "));
- shmem->shakedown = 1;
- cregs->ctrl = CONTROL_WON;
+ sbus_writel(1, &shmem->shakedown);
+ sbus_writel(CONTROL_WON, cregs + MYRICTRL_CTRL);
- softstate = chan->state;
+ softstate = sbus_readl(&chan->state);
DET(("chanstate[%08x] ", softstate));
- if(softstate == STATE_READY) {
+ if (softstate == STATE_READY) {
DET(("wakeup successful, "));
break;
}
- if(softstate != STATE_WFN) {
+ if (softstate != STATE_WFN) {
DET(("not WFN setting that, "));
- chan->state = STATE_WFN;
+ sbus_writel(STATE_WFN, &chan->state);
}
udelay(20);
@@ -166,7 +172,7 @@
myri_enable_irq(mp->lregs, cregs);
- if(tick > 25) {
+ if (tick > 25) {
DET(("25 ticks we lose, failure.\n"));
return -1;
}
@@ -174,9 +180,9 @@
return 0;
}
-static inline int myri_load_lanai(struct myri_eth *mp)
+static int myri_load_lanai(struct myri_eth *mp)
{
- struct net_device *dev = mp->dev;
+ struct net_device *dev = mp->dev;
struct myri_shmem *shmem = mp->shmem;
unsigned char *rptr;
int i;
@@ -185,28 +191,30 @@
myri_reset_on(mp->cregs);
rptr = (unsigned char *) mp->lanai;
- for(i = 0; i < mp->eeprom.ramsz; i++)
- rptr[i] = 0;
+ for (i = 0; i < mp->eeprom.ramsz; i++)
+ sbus_writeb(0, &rptr[i]);
- if(mp->eeprom.cpuvers >= CPUVERS_3_0)
- mp->lregs->cval = mp->eeprom.cval;
+ if (mp->eeprom.cpuvers >= CPUVERS_3_0)
+ sbus_writel(mp->eeprom.cval, mp->lregs + LANAI_CVAL);
/* Load executable code. */
- for(i = 0; i < sizeof(lanai4_code); i++)
- rptr[(lanai4_code_off * 2) + i] = lanai4_code[i];
+ for (i = 0; i < sizeof(lanai4_code); i++)
+ sbus_writeb(lanai4_code[i], &rptr[(lanai4_code_off * 2) + i]);
/* Load data segment. */
- for(i = 0; i < sizeof(lanai4_data); i++)
- rptr[(lanai4_data_off * 2) + i] = lanai4_data[i];
+ for (i = 0; i < sizeof(lanai4_data); i++)
+ sbus_writeb(lanai4_data[i], &rptr[(lanai4_data_off * 2) + i]);
/* Set device address. */
- shmem->addr[0] = shmem->addr[1] = 0;
- for(i = 0; i < 6; i++)
- shmem->addr[i + 2] = dev->dev_addr[i];
+ sbus_writeb(0, &shmem->addr[0]);
+ sbus_writeb(0, &shmem->addr[1]);
+ for (i = 0; i < 6; i++)
+ sbus_writeb(dev->dev_addr[i],
+ &shmem->addr[i + 2]);
/* Set SBUS bursts and interrupt mask. */
- shmem->burst = ((mp->myri_bursts & 0xf8) >> 3);
- shmem->imask = SHMEM_IMASK_RX;
+ sbus_writel(((mp->myri_bursts & 0xf8) >> 3), &shmem->burst);
+ sbus_writel(SHMEM_IMASK_RX, &shmem->imask);
/* Release the LANAI. */
myri_disable_irq(mp->lregs, mp->cregs);
@@ -214,22 +222,22 @@
myri_disable_irq(mp->lregs, mp->cregs);
/* Wait for the reset to complete. */
- for(i = 0; i < 5000; i++) {
- if(shmem->channel.state != STATE_READY)
+ for (i = 0; i < 5000; i++) {
+ if (sbus_readl(&shmem->channel.state) != STATE_READY)
break;
else
udelay(10);
}
- if(i == 5000)
- printk("myricom: Chip would not reset after firmware load.\n");
+ if (i == 5000)
+ printk(KERN_ERR "myricom: Chip would not reset after firmware load.\n");
i = myri_do_handshake(mp);
- if(i)
- printk("myricom: Handshake with LANAI failed.\n");
+ if (i)
+ printk(KERN_ERR "myricom: Handshake with LANAI failed.\n");
- if(mp->eeprom.cpuvers == CPUVERS_4_0)
- mp->lregs->vers = 0;
+ if (mp->eeprom.cpuvers == CPUVERS_4_0)
+ sbus_writel(0, mp->lregs + LANAI_VERS);
return i;
}
@@ -240,17 +248,31 @@
struct recvq *rq = mp->rq;
int i;
- rq->tail = rq->head = 0;
- for(i = 0; i < (RX_RING_SIZE+1); i++) {
- if(mp->rx_skbs[i] != NULL) {
+ sbus_writel(0, &rq->tail);
+ sbus_writel(0, &rq->head);
+ for (i = 0; i < (RX_RING_SIZE+1); i++) {
+ if (mp->rx_skbs[i] != NULL) {
+ struct myri_rxd *rxd = &rq->myri_rxd[i];
+ u32 dma_addr;
+
+ dma_addr = sbus_readl(&rxd->myri_scatters[0].addr);
+ sbus_unmap_single(mp->myri_sdev, dma_addr, RX_ALLOC_SIZE);
dev_kfree_skb(mp->rx_skbs[i]);
mp->rx_skbs[i] = NULL;
}
}
- mp->tx_old = sq->tail = sq->head = 0;
- for(i = 0; i < TX_RING_SIZE; i++) {
- if(mp->tx_skbs[i] != NULL) {
+ mp->tx_old = 0;
+ sbus_writel(0, &sq->tail);
+ sbus_writel(0, &sq->head);
+ for (i = 0; i < TX_RING_SIZE; i++) {
+ if (mp->tx_skbs[i] != NULL) {
+ struct sk_buff *skb = mp->tx_skbs[i];
+ struct myri_txd *txd = &sq->myri_txd[i];
+ u32 dma_addr;
+
+ dma_addr = sbus_readl(&txd->myri_gathers[0].addr);
+ sbus_unmap_single(mp->myri_sdev, dma_addr, (skb->len + 3) & ~3);
dev_kfree_skb(mp->tx_skbs[i]);
mp->tx_skbs[i] = NULL;
}
@@ -265,25 +287,28 @@
int gfp_flags = GFP_KERNEL;
int i;
- if(from_irq || in_interrupt())
+ if (from_irq || in_interrupt())
gfp_flags = GFP_ATOMIC;
myri_clean_rings(mp);
- for(i = 0; i < RX_RING_SIZE; i++) {
+ for (i = 0; i < RX_RING_SIZE; i++) {
struct sk_buff *skb = myri_alloc_skb(RX_ALLOC_SIZE, gfp_flags);
+ u32 dma_addr;
- if(!skb)
+ if (!skb)
continue;
mp->rx_skbs[i] = skb;
skb->dev = dev;
skb_put(skb, RX_ALLOC_SIZE);
- rxd[i].myri_scatters[0].addr = sbus_dvma_addr(skb->data);
- rxd[i].myri_scatters[0].len = RX_ALLOC_SIZE;
- rxd[i].ctx = i;
- rxd[i].num_sg = 1;
+
+ dma_addr = sbus_map_single(mp->myri_sdev, skb->data, RX_ALLOC_SIZE);
+ sbus_writel(dma_addr, &rxd[i].myri_scatters[0].addr);
+ sbus_writel(RX_ALLOC_SIZE, &rxd[i].myri_scatters[0].len);
+ sbus_writel(i, &rxd[i].ctx);
+ sbus_writel(1, &rxd[i].num_sg);
}
- rq->head = 0;
- rq->tail = RX_RING_SIZE;
+ sbus_writel(0, &rq->head);
+ sbus_writel(RX_RING_SIZE, &rq->tail);
}
static int myri_init(struct myri_eth *mp, int from_irq)
@@ -323,19 +348,22 @@
}
#endif
-static inline void myri_tx(struct myri_eth *mp, struct net_device *dev)
+static void myri_tx(struct myri_eth *mp, struct net_device *dev)
{
struct sendq *sq = mp->sq;
int entry = mp->tx_old;
- int limit = sq->head;
+ int limit = sbus_readl(&sq->head);
DTX(("entry[%d] limit[%d] ", entry, limit));
- if(entry == limit)
+ if (entry == limit)
return;
- while(entry != limit) {
+ while (entry != limit) {
struct sk_buff *skb = mp->tx_skbs[entry];
+ u32 dma_addr;
DTX(("SKB[%d] ", entry));
+ dma_addr = sbus_readl(&sq->myri_txd[entry].myri_gathers[0].addr);
+ sbus_unmap_single(mp->myri_sdev, dma_addr, skb->len);
dev_kfree_skb(skb);
mp->tx_skbs[entry] = NULL;
mp->enet_stats.tx_packets++;
@@ -361,17 +389,17 @@
DHDR(("myri_type_trans: "));
dump_ehdr(eth);
#endif
- if(*eth->h_dest & 1) {
- if(memcmp(eth->h_dest, dev->broadcast, ETH_ALEN)==0)
+ if (*eth->h_dest & 1) {
+ if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN)==0)
skb->pkt_type = PACKET_BROADCAST;
else
skb->pkt_type = PACKET_MULTICAST;
- } else if(dev->flags & (IFF_PROMISC|IFF_ALLMULTI)) {
- if(memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN))
+ } else if (dev->flags & (IFF_PROMISC|IFF_ALLMULTI)) {
+ if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN))
skb->pkt_type = PACKET_OTHERHOST;
}
- if(ntohs(eth->h_proto) >= 1536)
+ if (ntohs(eth->h_proto) >= 1536)
return eth->h_proto;
rawp = skb->data;
@@ -388,36 +416,39 @@
return htons(ETH_P_802_2);
}
-static inline void myri_rx(struct myri_eth *mp, struct net_device *dev)
+static void myri_rx(struct myri_eth *mp, struct net_device *dev)
{
struct recvq *rq = mp->rq;
struct recvq *rqa = mp->rqack;
- int entry = rqa->head;
- int limit = rqa->tail;
+ int entry = sbus_readl(&rqa->head);
+ int limit = sbus_readl(&rqa->tail);
int drops;
DRX(("entry[%d] limit[%d] ", entry, limit));
- if(entry == limit)
+ if (entry == limit)
return;
drops = 0;
DRX(("\n"));
- while(entry != limit) {
+ while (entry != limit) {
struct myri_rxd *rxdack = &rqa->myri_rxd[entry];
- unsigned int csum = rxdack->csum;
- int len = rxdack->myri_scatters[0].len;
- int index = rxdack->ctx;
+ u32 csum = sbus_readl(&rxdack->csum);
+ int len = sbus_readl(&rxdack->myri_scatters[0].len);
+ int index = sbus_readl(&rxdack->ctx);
struct myri_rxd *rxd = &rq->myri_rxd[rq->tail];
struct sk_buff *skb = mp->rx_skbs[index];
/* Ack it. */
- rqa->head = NEXT_RX(entry);
+ sbus_writel(NEXT_RX(entry), &rqa->head);
/* Check for errors. */
DRX(("rxd[%d]: %p len[%d] csum[%08x] ", entry, rxd, len, csum));
- if((len < (ETH_HLEN + MYRI_PAD_LEN)) || (skb->data[0] != MYRI_PAD_LEN)) {
+ sbus_dma_sync_single(mp->myri_sdev,
+ sbus_readl(&rxd->myri_scatters[0].addr),
+ RX_ALLOC_SIZE);
+ if (len < (ETH_HLEN + MYRI_PAD_LEN) || (skb->data[0] != MYRI_PAD_LEN)) {
DRX(("ERROR["));
mp->enet_stats.rx_errors++;
- if(len < (ETH_HLEN + MYRI_PAD_LEN)) {
+ if (len < (ETH_HLEN + MYRI_PAD_LEN)) {
DRX(("BAD_LENGTH] "));
mp->enet_stats.rx_length_errors++;
} else {
@@ -430,37 +461,38 @@
drops++;
DRX(("DROP "));
mp->enet_stats.rx_dropped++;
- rxd->myri_scatters[0].addr = sbus_dvma_addr(skb->data);
- rxd->myri_scatters[0].len = RX_ALLOC_SIZE;
- rxd->ctx = index;
- rxd->num_sg = 1;
- rq->tail = NEXT_RX(rq->tail);
+ sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len);
+ sbus_writel(index, &rxd->ctx);
+ sbus_writel(1, &rxd->num_sg);
+ sbus_writel(NEXT_RX(sbus_readl(&rq->tail)), &rq->tail);
goto next;
}
-#ifdef NEED_DMA_SYNCHRONIZATION
- mmu_sync_dma(sbus_dvma_addr(skb->data),
- skb->len, mp->myri_sbus_dev->my_bus);
-#endif
-
DRX(("len[%d] ", len));
- if(len > RX_COPY_THRESHOLD) {
+ if (len > RX_COPY_THRESHOLD) {
struct sk_buff *new_skb;
+ u32 dma_addr;
DRX(("BIGBUFF "));
new_skb = myri_alloc_skb(RX_ALLOC_SIZE, GFP_ATOMIC);
- if(!new_skb) {
+ if (new_skb == NULL) {
DRX(("skb_alloc(FAILED) "));
goto drop_it;
}
+ sbus_unmap_single(mp->myri_sdev,
+ sbus_readl(&rxd->myri_scatters[0].addr),
+ RX_ALLOC_SIZE);
mp->rx_skbs[index] = new_skb;
new_skb->dev = dev;
skb_put(new_skb, RX_ALLOC_SIZE);
- rxd->myri_scatters[0].addr = sbus_dvma_addr(new_skb->data);
- rxd->myri_scatters[0].len = RX_ALLOC_SIZE;
- rxd->ctx = index;
- rxd->num_sg = 1;
- rq->tail = NEXT_RX(rq->tail);
+ dma_addr = sbus_map_single(mp->myri_sdev,
+ new_skb->data,
+ RX_ALLOC_SIZE);
+ sbus_writel(dma_addr, &rxd->myri_scatters[0].addr);
+ sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len);
+ sbus_writel(index, &rxd->ctx);
+ sbus_writel(1, &rxd->num_sg);
+ sbus_writel(NEXT_RX(sbus_readl(&rq->tail)), &rq->tail);
/* Trim the original skb for the netif. */
DRX(("trim(%d) ", len));
@@ -469,10 +501,11 @@
struct sk_buff *copy_skb = dev_alloc_skb(len);
DRX(("SMALLBUFF "));
- if(!copy_skb) {
+ if (copy_skb == NULL) {
DRX(("dev_alloc_skb(FAILED) "));
goto drop_it;
}
+ /* DMA sync already done above. */
copy_skb->dev = dev;
DRX(("resv_and_put "));
skb_put(copy_skb, len);
@@ -480,11 +513,10 @@
/* Reuse original ring buffer. */
DRX(("reuse "));
- rxd->myri_scatters[0].addr = sbus_dvma_addr(skb->data);
- rxd->myri_scatters[0].len = RX_ALLOC_SIZE;
- rxd->ctx = index;
- rxd->num_sg = 1;
- rq->tail = NEXT_RX(rq->tail);
+ sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len);
+ sbus_writel(index, &rxd->ctx);
+ sbus_writel(1, &rxd->num_sg);
+ sbus_writel(NEXT_RX(sbus_readl(&rq->tail)), &rq->tail);
skb = copy_skb;
}
@@ -508,28 +540,28 @@
{
struct net_device *dev = (struct net_device *) dev_id;
struct myri_eth *mp = (struct myri_eth *) dev->priv;
- struct lanai_regs *lregs = mp->lregs;
+ unsigned long lregs = mp->lregs;
struct myri_channel *chan = &mp->shmem->channel;
- unsigned int status;
+ u32 status;
- status = lregs->istat;
+ status = sbus_readl(lregs + LANAI_ISTAT);
DIRQ(("myri_interrupt: status[%08x] ", status));
- if(status & ISTAT_HOST) {
- unsigned int softstate;
+ if (status & ISTAT_HOST) {
+ u32 softstate;
DIRQ(("IRQ_DISAB "));
myri_disable_irq(lregs, mp->cregs);
dev->interrupt = 1;
- softstate = chan->state;
+ softstate = sbus_readl(&chan->state);
DIRQ(("state[%08x] ", softstate));
- if(softstate != STATE_READY) {
+ if (softstate != STATE_READY) {
DIRQ(("myri_not_so_happy "));
myri_is_not_so_happy(mp);
}
DIRQ(("\nmyri_rx: "));
myri_rx(mp, dev);
DIRQ(("\nistat=ISTAT_HOST "));
- lregs->istat = ISTAT_HOST;
+ sbus_writel(ISTAT_HOST, lregs + LANAI_ISTAT);
dev->interrupt = 0;
DIRQ(("IRQ_ENAB "));
myri_enable_irq(lregs, mp->cregs);
@@ -557,25 +589,25 @@
struct myri_eth *mp = (struct myri_eth *) dev->priv;
struct sendq *sq = mp->sq;
struct myri_txd *txd;
- unsigned char *srcptr;
unsigned long flags;
unsigned int head, tail;
int len, entry;
+ u32 dma_addr;
DTX(("myri_start_xmit: "));
myri_tx(mp, dev);
- if(dev->tbusy) {
+ if (dev->tbusy) {
int tickssofar = jiffies - dev->trans_start;
DTX(("tbusy tickssofar[%d] ", tickssofar));
- if(tickssofar < 40) {
+ if (tickssofar < 40) {
DTX(("returning 1\n"));
return 1;
} else {
DTX(("resetting, return 0\n"));
- printk("%s: transmit timed out, resetting\n", dev->name);
+ printk(KERN_ERR "%s: transmit timed out, resetting\n", dev->name);
mp->enet_stats.tx_errors++;
myri_init(mp, in_interrupt());
dev->tbusy = 0;
@@ -584,23 +616,17 @@
}
}
- if(test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
+ if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
DTX(("tbusy, maybe a race? returning 1\n"));
printk("%s: Transmitter access conflict.\n", dev->name);
return 1;
}
-
-#ifdef NEED_DMA_SYNCHRONIZATION
- mmu_sync_dma(sbus_dvma_addr(skb->data),
- skb->len, mp->myri_sbus_dev->my_bus);
-#endif
-
/* This is just to prevent multiple PIO reads for TX_BUFFS_AVAIL. */
- head = sq->head;
- tail = sq->tail;
+ head = sbus_readl(&sq->head);
+ tail = sbus_readl(&sq->tail);
- if(!TX_BUFFS_AVAIL(head, tail)) {
+ if (!TX_BUFFS_AVAIL(head, tail)) {
DTX(("no buffs available, returning 1\n"));
return 1;
}
@@ -614,34 +640,39 @@
/* XXX Maybe this can go as well. */
len = skb->len;
- if(len & 3) {
+ if (len & 3) {
DTX(("len&3 "));
len = (len + 4) & (~3);
}
- entry = sq->tail;
+ entry = sbus_readl(&sq->tail);
txd = &sq->myri_txd[entry];
mp->tx_skbs[entry] = skb;
- txd->myri_gathers[0].addr = sbus_dvma_addr(skb->data);
- txd->myri_gathers[0].len = len;
- txd->num_sg = 1;
- txd->chan = KERNEL_CHANNEL;
- txd->len = len;
- txd->csum_off = ((unsigned int)-1);
- txd->csum_field = 0;
-
- srcptr = (((unsigned char *) skb->data) + MYRI_PAD_LEN);
- if(srcptr[0] & 0x1) {
- txd->addr[0] = txd->addr[1] = txd->addr[2] = txd->addr[3] = 0xffff;
+ /* Must do this before we sbus map it. */
+ if (skb->data[MYRI_PAD_LEN] & 0x1) {
+ sbus_writew(0xffff, &txd->addr[0]);
+ sbus_writew(0xffff, &txd->addr[1]);
+ sbus_writew(0xffff, &txd->addr[2]);
+ sbus_writew(0xffff, &txd->addr[3]);
} else {
- txd->addr[0] = 0;
- txd->addr[1] = (srcptr[0] << 8) | srcptr[1];
- txd->addr[2] = (srcptr[2] << 8) | srcptr[3];
- txd->addr[3] = (srcptr[4] << 8) | srcptr[5];
- }
- sq->tail = NEXT_TX(entry);
+ sbus_writew(0xffff, &txd->addr[0]);
+ sbus_writew((skb->data[0] << 8) | skb->data[1], &txd->addr[1]);
+ sbus_writew((skb->data[2] << 8) | skb->data[3], &txd->addr[2]);
+ sbus_writew((skb->data[4] << 8) | skb->data[5], &txd->addr[3]);
+ }
+
+ dma_addr = sbus_map_single(mp->myri_sdev, skb->data, len);
+ sbus_writel(dma_addr, &txd->myri_gathers[0].addr);
+ sbus_writel(len, &txd->myri_gathers[0].len);
+ sbus_writel(1, &txd->num_sg);
+ sbus_writel(KERNEL_CHANNEL, &txd->chan);
+ sbus_writel(len, &txd->len);
+ sbus_writel((u32)-1, &txd->csum_off);
+ sbus_writel(0, &txd->csum_field);
+
+ sbus_writel(NEXT_TX(entry), &sq->tail);
DTX(("BangTheChip "));
bang_the_chip(mp);
@@ -659,8 +690,8 @@
static int myri_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
void *daddr, void *saddr, unsigned len)
{
- struct ethhdr *eth = (struct ethhdr *)skb_push(skb,ETH_HLEN);
- unsigned char *pad = (unsigned char *)skb_push(skb,MYRI_PAD_LEN);
+ struct ethhdr *eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
+ unsigned char *pad = (unsigned char *) skb_push(skb, MYRI_PAD_LEN);
#ifdef DEBUG_HEADER
DHDR(("myri_header: pad[%02x,%02x] ", pad[0], pad[1]));
@@ -674,13 +705,13 @@
/* Set the protocol type. For a packet of type ETH_P_802_3 we put the length
* in here instead. It is up to the 802.2 layer to carry protocol information.
*/
- if(type != ETH_P_802_3)
+ if (type != ETH_P_802_3)
eth->h_proto = htons(type);
else
eth->h_proto = htons(len);
/* Set the source hardware address. */
- if(saddr)
+ if (saddr)
memcpy(eth->h_source, saddr, dev->addr_len);
else
memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
@@ -688,12 +719,12 @@
/* Anyway, the loopback-device should never use this function... */
if (dev->flags & IFF_LOOPBACK) {
int i;
- for(i = 0; i < dev->addr_len; i++)
+ for (i = 0; i < dev->addr_len; i++)
eth->h_dest[i] = 0;
return(dev->hard_header_len);
}
- if(daddr) {
+ if (daddr) {
memcpy(eth->h_dest, daddr, dev->addr_len);
return dev->hard_header_len;
}
@@ -706,8 +737,8 @@
*/
static int myri_rebuild_header(struct sk_buff *skb)
{
- unsigned char *pad = (unsigned char *)skb->data;
- struct ethhdr *eth = (struct ethhdr *)(pad + MYRI_PAD_LEN);
+ unsigned char *pad = (unsigned char *) skb->data;
+ struct ethhdr *eth = (struct ethhdr *) (pad + MYRI_PAD_LEN);
struct net_device *dev = skb->dev;
#ifdef DEBUG_HEADER
@@ -742,8 +773,8 @@
int myri_header_cache(struct neighbour *neigh, struct hh_cache *hh)
{
unsigned short type = hh->hh_type;
- unsigned char *pad = (unsigned char *)hh->hh_data;
- struct ethhdr *eth = (struct ethhdr *)(pad + MYRI_PAD_LEN);
+ unsigned char *pad = (unsigned char *) hh->hh_data;
+ struct ethhdr *eth = (struct ethhdr *) (pad + MYRI_PAD_LEN);
struct net_device *dev = neigh->dev;
if (type == __constant_htons(ETH_P_802_3))
@@ -862,37 +893,36 @@
}
#endif
-static inline int myri_ether_init(struct net_device *dev, struct linux_sbus_device *sdev, int num)
+static int __init myri_ether_init(struct net_device *dev, struct sbus_dev *sdev, int num)
{
static unsigned version_printed = 0;
struct myri_eth *mp;
- unsigned char prop_buf[32];
+ unsigned char prop_buf[32];
int i;
DET(("myri_ether_init(%p,%p,%d):\n", dev, sdev, num));
dev = init_etherdev(0, sizeof(struct myri_eth));
- if(version_printed++ == 0)
+ if (version_printed++ == 0)
printk(version);
printk("%s: MyriCOM MyriNET Ethernet ", dev->name);
- dev->base_addr = (long) sdev;
mp = (struct myri_eth *) dev->priv;
- mp->myri_sbus_dev = sdev;
+ mp->myri_sdev = sdev;
/* Clean out skb arrays. */
- for(i = 0; i < (RX_RING_SIZE + 1); i++)
+ for (i = 0; i < (RX_RING_SIZE + 1); i++)
mp->rx_skbs[i] = NULL;
- for(i = 0; i < TX_RING_SIZE; i++)
+ for (i = 0; i < TX_RING_SIZE; i++)
mp->tx_skbs[i] = NULL;
/* First check for EEPROM information. */
i = prom_getproperty(sdev->prom_node, "myrinet-eeprom-info",
(char *)&mp->eeprom, sizeof(struct myri_eeprom));
DET(("prom_getprop(myrinet-eeprom-info) returns %d\n", i));
- if(i == 0 || i == -1) {
+ if (i == 0 || i == -1) {
/* No eeprom property, must cook up the values ourselves. */
DET(("No EEPROM: "));
mp->eeprom.bus_type = BUS_TYPE_SBUS;
@@ -901,38 +931,38 @@
mp->eeprom.ramsz = prom_getintdefault(sdev->prom_node,"sram_size",0);
DET(("cpuvers[%d] cval[%d] ramsz[%d]\n", mp->eeprom.cpuvers,
mp->eeprom.cval, mp->eeprom.ramsz));
- if(mp->eeprom.cpuvers == 0) {
+ if (mp->eeprom.cpuvers == 0) {
DET(("EEPROM: cpuvers was zero, setting to %04x\n",CPUVERS_2_3));
mp->eeprom.cpuvers = CPUVERS_2_3;
}
- if(mp->eeprom.cpuvers < CPUVERS_3_0) {
+ if (mp->eeprom.cpuvers < CPUVERS_3_0) {
DET(("EEPROM: cpuvers < CPUVERS_3_0, clockval set to zero.\n"));
mp->eeprom.cval = 0;
}
- if(mp->eeprom.ramsz == 0) {
+ if (mp->eeprom.ramsz == 0) {
DET(("EEPROM: ramsz == 0, setting to 128k\n"));
mp->eeprom.ramsz = (128 * 1024);
}
i = prom_getproperty(sdev->prom_node, "myrinet-board-id",
&prop_buf[0], 10);
DET(("EEPROM: prom_getprop(myrinet-board-id) returns %d\n", i));
- if((i != 0) && (i != -1))
+ if ((i != 0) && (i != -1))
memcpy(&mp->eeprom.id[0], &prop_buf[0], 6);
else
set_boardid_from_idprom(mp, num);
i = prom_getproperty(sdev->prom_node, "fpga_version",
&mp->eeprom.fvers[0], 32);
DET(("EEPROM: prom_getprop(fpga_version) returns %d\n", i));
- if(i == 0 || i == -1)
+ if (i == 0 || i == -1)
memset(&mp->eeprom.fvers[0], 0, 32);
- if(mp->eeprom.cpuvers == CPUVERS_4_1) {
+ if (mp->eeprom.cpuvers == CPUVERS_4_1) {
DET(("EEPROM: cpuvers CPUVERS_4_1, "));
- if(mp->eeprom.ramsz == (128 * 1024)) {
+ if (mp->eeprom.ramsz == (128 * 1024)) {
DET(("ramsize 128k, setting to 256k, "));
mp->eeprom.ramsz = (256 * 1024);
}
- if((mp->eeprom.cval==0x40414041)||(mp->eeprom.cval==0x90449044)){
+ if ((mp->eeprom.cval==0x40414041)||(mp->eeprom.cval==0x90449044)){
DET(("changing cval from %08x to %08x ",
mp->eeprom.cval, 0x50e450e4));
mp->eeprom.cval = 0x50e450e4;
@@ -944,7 +974,7 @@
dump_eeprom(mp);
#endif
- for(i = 0; i < 6; i++)
+ for (i = 0; i < 6; i++)
printk("%2.2x%c",
dev->dev_addr[i] = mp->eeprom.id[i],
i == 5 ? ' ' : ':');
@@ -953,45 +983,36 @@
determine_reg_space_size(mp);
/* Map in the MyriCOM register/localram set. */
- prom_apply_sbus_ranges(sdev->my_bus, &sdev->reg_addrs[0],
- sdev->num_registers, sdev);
- if(mp->eeprom.cpuvers < CPUVERS_4_0) {
+ if (mp->eeprom.cpuvers < CPUVERS_4_0) {
/* XXX Makes no sense, if control reg is non-existant this
* XXX driver cannot function at all... maybe pre-4.0 is
* XXX only a valid version for PCI cards? Ask feldy...
*/
DET(("Mapping regs for cpuvers < CPUVERS_4_0\n"));
- mp->regs = (struct myri_regs *)
- sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0,
- mp->reg_size, "MyriCOM Regs",
- sdev->reg_addrs[0].which_io, 0);
- if(!mp->regs) {
+ mp->regs = sbus_ioremap(&sdev->resource[0], 0,
+ mp->reg_size, "MyriCOM Regs");
+ if (!mp->regs) {
printk("MyriCOM: Cannot map MyriCOM registers.\n");
return ENODEV;
}
- mp->lanai = (unsigned short *) (((unsigned long)mp->regs) + (256*1024));
+ mp->lanai = (unsigned short *) (mp->regs + (256 * 1024));
mp->lanai3 = (unsigned int *) mp->lanai;
- mp->lregs = (struct lanai_regs *) &mp->lanai[0x10000];
+ mp->lregs = (unsigned long) &mp->lanai[0x10000];
} else {
DET(("Mapping regs for cpuvers >= CPUVERS_4_0\n"));
- mp->cregs = (struct myri_control *)
- sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0,
- PAGE_SIZE, "MyriCOM Control Regs",
- sdev->reg_addrs[0].which_io, 0);
- mp->lregs = (struct lanai_regs *)
- sparc_alloc_io(sdev->reg_addrs[0].phys_addr + (256 * 1024),
- 0, PAGE_SIZE, "MyriCOM LANAI Regs",
- sdev->reg_addrs[0].which_io, 0);
+ mp->cregs = sbus_ioremap(&sdev->resource[0], 0,
+ PAGE_SIZE, "MyriCOM Control Regs");
+ mp->lregs = sbus_ioremap(&sdev->resource[0], (256 * 1024),
+ PAGE_SIZE, "MyriCOM LANAI Regs");
mp->lanai = (unsigned short *)
- sparc_alloc_io(sdev->reg_addrs[0].phys_addr + (512 * 1024),
- 0, mp->eeprom.ramsz, "MyriCOM SRAM",
- sdev->reg_addrs[0].which_io, 0);
+ sbus_ioremap(&sdev->resource[0], (512 * 1024),
+ mp->eeprom.ramsz, "MyriCOM SRAM");
mp->lanai3 = (unsigned int *) mp->lanai;
}
- DET(("Registers mapped: cregs[%p] lregs[%p] lanai[%p] lanai3[%p]\n",
+ DET(("Registers mapped: cregs[%lx] lregs[%lx] lanai[%p] lanai3[%p]\n",
mp->cregs, mp->lregs, mp->lanai, mp->lanai3));
- if(mp->eeprom.cpuvers >= CPUVERS_4_0)
+ if (mp->eeprom.cpuvers >= CPUVERS_4_0)
mp->shmem_base = 0xf000;
else
mp->shmem_base = 0x8000;
@@ -1017,22 +1038,22 @@
myri_reset_on(mp->cregs);
/* Get the supported DVMA burst sizes from our SBUS. */
- mp->myri_bursts = prom_getintdefault(mp->myri_sbus_dev->my_bus->prom_node,
+ mp->myri_bursts = prom_getintdefault(mp->myri_sdev->bus->prom_node,
"burst-sizes", 0x00);
-#if 1 /* XXX Until sun4m SBUS burst workaround is written. */
- if(sparc_cpu_model == sun4m)
+ if (!sbus_can_burst64(sdev))
mp->myri_bursts &= ~(DMA_BURST64);
-#endif
+
DET(("MYRI bursts %02x\n", mp->myri_bursts));
/* Encode SBUS interrupt level in second control register. */
i = prom_getint(sdev->prom_node, "interrupts");
- if(i == 0)
+ if (i == 0)
i = 4;
DET(("prom_getint(interrupts)==%d, irqlvl set to %04x\n",
i, (1 << i)));
- mp->cregs->irqlvl = (1 << i);
+
+ sbus_writel((1 << i), mp->cregs + MYRICTRL_IRQLVL);
mp->dev = dev;
dev->open = &myri_open;
@@ -1041,12 +1062,11 @@
dev->get_stats = &myri_get_stats;
dev->set_multicast_list = &myri_set_multicast;
dev->irq = sdev->irqs[0];
- dev->dma = 0;
/* Register interrupt handler now. */
DET(("Requesting MYRIcom IRQ line.\n"));
- if(request_irq(dev->irq, &myri_interrupt,
- SA_SHIRQ, "MyriCOM Ethernet", (void *) dev)) {
+ if (request_irq(dev->irq, &myri_interrupt,
+ SA_SHIRQ, "MyriCOM Ethernet", (void *) dev)) {
printk("MyriCOM: Cannot register interrupt handler.\n");
return ENODEV;
}
@@ -1074,31 +1094,42 @@
return 0;
}
+static int __init myri_sbus_match(struct sbus_dev *sdev)
+{
+ char *name = sdev->prom_name;
+
+ if (!strcmp(name, "MYRICOM,mlanai") ||
+ !strcmp(name, "myri"))
+ return 1;
+
+ return 0;
+}
+
int __init myri_sbus_probe(void)
{
struct net_device *dev = NULL;
- struct linux_sbus *bus;
- struct linux_sbus_device *sdev = 0;
+ struct sbus_bus *bus;
+ struct sbus_dev *sdev = 0;
static int called = 0;
int cards = 0, v;
- if(called)
+ if (called)
return ENODEV;
called++;
for_each_sbus(bus) {
for_each_sbusdev(sdev, bus) {
- if(cards) dev = NULL;
- if(!strcmp(sdev->prom_name, "MYRICOM,mlanai") ||
- !strcmp(sdev->prom_name, "myri")) {
+ if (cards)
+ dev = NULL;
+ if (myri_sbus_match(sdev)) {
cards++;
DET(("Found myricom myrinet as %s\n", sdev->prom_name));
- if((v = myri_ether_init(dev, sdev, (cards - 1))))
+ if ((v = myri_ether_init(dev, sdev, (cards - 1))))
return v;
}
}
}
- if(!cards)
+ if (!cards)
return ENODEV;
return 0;
}
@@ -1115,15 +1146,13 @@
void
cleanup_module(void)
{
- struct myri_eth *mp;
-
/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
while (root_myri_dev) {
- mp = root_myri_dev->next_module;
+ struct myri_eth *next = root_myri_dev->next_module;
unregister_netdev(root_myri_dev->dev);
kfree(root_myri_dev->dev);
- root_myri_dev = mp;
+ root_myri_dev = next;
}
}
FUNET's LINUX-ADM group, [email protected]
TCL-scripts by Sam Shen (who was at: [email protected])