📄 rcpci45.c
字号:
printk("rc: Waking up adapter...\n"); RCResetLANCard(pDpa->id,0,0,0); } else { pDpa->nexus = 1; } while(post_buffers) { if (post_buffers > MAX_NMBR_POST_BUFFERS_PER_MSG) requested = MAX_NMBR_POST_BUFFERS_PER_MSG; else requested = post_buffers; count = RC_allocate_and_post_buffers(dev, requested); if ( count < requested ) { /* * Check to see if we were able to post any buffers at all. */ if (post_buffers == MAX_NMBR_RCV_BUFFERS) { printk("rc: Error RCopen: not able to allocate any buffers\r\n"); return(-ENOMEM); } printk("rc: Warning RCopen: not able to allocate all requested buffers\r\n"); break; /* we'll try to post more buffers later */ } else post_buffers -= count; } pDpa->numOutRcvBuffers = MAX_NMBR_RCV_BUFFERS - post_buffers; pDpa->shutdown = 0; /* just in case */#ifdef RCDEBUG printk("rc: RCopen: posted %d buffers\n", (uint)pDpa->numOutRcvBuffers);#endif MOD_INC_USE_COUNT; return 0;}static intRC_xmit_packet(struct sk_buff *skb, struct device *dev){ PDPA pDpa = (PDPA) dev->priv; singleTCB tcb; psingleTCB ptcb = &tcb; RC_RETURN status = 0; if (dev->tbusy || pDpa->shutdown || pDpa->reboot) {#ifdef RCDEBUG printk("rc: RC_xmit_packet: tbusy!\n");#endif dev->tbusy = 1; return 1; } if ( skb->len <= 0 ) { printk("RC_xmit_packet: skb->len less than 0!\n"); return 0; } /* * The user is free to reuse the TCB after RCI2OSendPacket() returns, since * the function copies the necessary info into its own private space. Thus, * our TCB can be a local structure. The skb, on the other hand, will be * freed up in our interrupt handler. */ ptcb->bcount = 1; /* * we'll get the context when the adapter interrupts us to tell us that * the transmision is done. At that time, we can free skb. */ ptcb->b.context = (U32)skb; ptcb->b.scount = 1; ptcb->b.size = skb->len; ptcb->b.addr = virt_to_bus((void *)skb->data);#ifdef RCDEBUG printk("rc: RC xmit: skb = 0x%x, pDpa = 0x%x, id = %d, ptcb = 0x%x\n", (uint)skb, (uint)pDpa, (uint)pDpa->id, (uint)ptcb);#endif if ( (status = RCI2OSendPacket(pDpa->id, (U32)NULL, (PRCTCB)ptcb)) != RC_RTN_NO_ERROR) {#ifdef RCDEBUG printk("rc: RC send error 0x%x\n", (uint)status);#endif dev->tbusy = 1; return 1; } else { dev->trans_start = jiffies; // dev->tbusy = 0; } /* * That's it! */ return 0;}/* * RCxmit_callback() * * The transmit callback routine. It's called by RCProcI2OMsgQ() * because the adapter is done with one or more transmit buffers and * it's returning them to us, or we asked the adapter to return the * outstanding transmit buffers by calling RCResetLANCard() with * RC_RESOURCE_RETURN_PEND_TX_BUFFERS flag. * All we need to do is free the buffers. */static void RCxmit_callback(U32 Status, U16 PcktCount, PU32 BufferContext, U16 AdapterID){ struct sk_buff *skb; PDPA pDpa; struct device *dev; pDpa = PCIAdapters[AdapterID]; if (!pDpa) { printk("rc: Fatal error: xmit callback, !pDpa\n"); return; } dev = pDpa->dev; // printk("xmit_callback: Status = 0x%x\n", (uint)Status); if (Status != I2O_REPLY_STATUS_SUCCESS) { printk("rc: xmit_callback: Status = 0x%x\n", (uint)Status); }#ifdef RCDEBUG if (pDpa->shutdown || pDpa->reboot) printk("rc: xmit callback: shutdown||reboot\n");#endif#ifdef RCDEBUG printk("rc: xmit_callback: PcktCount = %d, BC = 0x%x\n", (uint)PcktCount, (uint)BufferContext);#endif while (PcktCount--) { skb = (struct sk_buff *)(BufferContext[0]);#ifdef RCDEBUG printk("rc: skb = 0x%x\n", (uint)skb);#endif BufferContext++;#ifdef LINUX_2_1 dev_kfree_skb (skb);#else dev_kfree_skb (skb, FREE_WRITE);#endif } dev->tbusy = 0;}static voidRCreset_callback(U32 Status, U32 p1, U32 p2, U16 AdapterID){ PDPA pDpa; struct device *dev; pDpa = PCIAdapters[AdapterID]; dev = pDpa->dev;#ifdef RCDEBUG printk("rc: RCreset_callback Status 0x%x\n", (uint)Status);#endif /* * Check to see why we were called. */ if (pDpa->shutdown) { printk("rc: Shutting down interface\n"); pDpa->shutdown = 0; pDpa->reboot = 0; MOD_DEC_USE_COUNT; } else if (pDpa->reboot) { printk("rc: reboot, shutdown adapter\n"); /* * We don't set any of the flags in RCShutdownLANCard() * and we don't pass a callback routine to it. * The adapter will have already initiated the reboot by * the time the function returns. */ RCDisableI2OInterrupts(pDpa->id); RCShutdownLANCard(pDpa->id,0,0,0); printk("rc: scheduling timer...\n"); init_timer(&pDpa->timer); pDpa->timer.expires = RUN_AT((40*HZ)/10); /* 4 sec. */ pDpa->timer.data = (unsigned long)dev; pDpa->timer.function = &rc_timer; /* timer handler */ add_timer(&pDpa->timer); }}static voidRCreboot_callback(U32 Status, U32 p1, U32 p2, U16 AdapterID){ PDPA pDpa; pDpa = PCIAdapters[AdapterID];#ifdef RCDEBUG printk("rc: RCreboot: rcv buffers outstanding = %d\n", (uint)pDpa->numOutRcvBuffers);#endif if (pDpa->shutdown) { printk("rc: skipping reboot sequence -- shutdown already initiated\n"); return; } pDpa->reboot = 1; /* * OK, we reset the adapter and ask it to return all * outstanding transmit buffers as well as the posted * receive buffers. When the adapter is done returning * those buffers, it will call our RCreset_callback() * routine. In that routine, we'll call RCShutdownLANCard() * to tell the adapter that it's OK to start the reboot and * schedule a timer callback routine to execute 3 seconds * later; this routine will reinitialize the adapter at that time. */ RCResetLANCard(pDpa->id, RC_RESOURCE_RETURN_POSTED_RX_BUCKETS | RC_RESOURCE_RETURN_PEND_TX_BUFFERS,0, (PFNCALLBACK)RCreset_callback);}int broadcast_packet(unsigned char * address){ int i; for (i=0; i<6; i++) if (address[i] != 0xff) return 0; return 1;}/* * RCrecv_callback() * * The receive packet callback routine. This is called by * RCProcI2OMsgQ() after the adapter posts buffers which have been * filled (one ethernet packet per buffer). */static voidRCrecv_callback(U32 Status, U8 PktCount, U32 BucketsRemain, PU32 PacketDescBlock, U16 AdapterID){ U32 len, count; PDPA pDpa; struct sk_buff *skb; struct device *dev; singleTCB tcb; psingleTCB ptcb = &tcb; pDpa = PCIAdapters[AdapterID]; dev = pDpa->dev; ptcb->bcount = 1;#ifdef RCDEBUG printk("rc: RCrecv_callback: 0x%x, 0x%x, 0x%x\n", (uint)PktCount, (uint)BucketsRemain, (uint)PacketDescBlock);#endif #ifdef RCDEBUG if ((pDpa->shutdown || pDpa->reboot) && !Status) printk("shutdown||reboot && !Status: PktCount = %d\n",PktCount);#endif if ( (Status != I2O_REPLY_STATUS_SUCCESS) || pDpa->shutdown) { /* * Free whatever buffers the adapter returned, but don't * pass them to the kernel. */ if (!pDpa->shutdown && !pDpa->reboot) printk("rc: RCrecv error: status = 0x%x\n", (uint)Status);#ifdef RCDEBUG else printk("rc: Returning %d buffers, status = 0x%x\n", PktCount, (uint)Status);#endif /* * TO DO: check the nature of the failure and put the adapter in * failed mode if it's a hard failure. Send a reset to the adapter * and free all outstanding memory. */ if (Status == I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER) {#ifdef RCDEBUG printk("RCrecv status ABORT NO DATA TRANSFER\n");#endif } /* check for reset status: I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER */ if (PacketDescBlock) { while(PktCount--) { skb = (struct sk_buff *)PacketDescBlock[0];#ifndef LINUX_2_1 skb->free = 1; skb->lock = 0; #endif#ifdef RCDEBUG printk("free skb 0x%p\n", skb);#endif#ifdef LINUX_2_1 dev_kfree_skb (skb);#else dev_kfree_skb(skb, FREE_READ);#endif pDpa->numOutRcvBuffers--; PacketDescBlock += BD_SIZE; /* point to next context field */ } } return; } else { while(PktCount--) { skb = (struct sk_buff *)PacketDescBlock[0];#ifdef RCDEBUG if (pDpa->shutdown) printk("shutdown: skb=0x%x\n", (uint)skb); printk("skb = 0x%x: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", (uint)skb, (uint)skb->data[0], (uint)skb->data[1], (uint)skb->data[2], (uint)skb->data[3], (uint)skb->data[4], (uint)skb->data[5]);#endif#ifdef PROMISCUOUS_BY_DEFAULT /* early 2.x firmware */ if ( (memcmp(dev->dev_addr, skb->data, 6)) && (!broadcast_packet(skb->data))) { /* * Re-post the buffer to the adapter. Since the adapter usually * return 1 to 2 receive buffers at a time, it's not too inefficient * post one buffer at a time but ... may be that should be * optimized at some point. */ ptcb->b.context = (U32)skb; ptcb->b.scount = 1; ptcb->b.size = MAX_ETHER_SIZE; ptcb->b.addr = virt_to_bus((void *)skb->data); if ( RCPostRecvBuffers(pDpa->id, (PRCTCB)ptcb ) != RC_RTN_NO_ERROR) { printk("rc: RCrecv_callback: post buffer failed!\n");#ifdef LINUX_2_1 dev_kfree_skb (skb);#else skb->free = 1; dev_kfree_skb(skb, FREE_READ);#endif } else { pDpa->numOutRcvBuffers++; } } else#endif /* PROMISCUOUS_BY_DEFAULT */ { len = PacketDescBlock[2]; skb->dev = dev; skb_put( skb, len ); /* adjust length and tail */ skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); /* send the packet to the kernel */ dev->last_rx = jiffies; } pDpa->numOutRcvBuffers--; PacketDescBlock += BD_SIZE; /* point to next context field */ } } /* * Replenish the posted receive buffers. * DO NOT replenish buffers if the driver has already * initiated a reboot or shutdown! */ if (!pDpa->shutdown && !pDpa->reboot) { count = RC_allocate_and_post_buffers(dev, MAX_NMBR_RCV_BUFFERS-pDpa->numOutRcvBuffers); pDpa->numOutRcvBuffers += count; }}/* * RCinterrupt() * * Interrupt handler. * This routine sets up a couple of pointers and calls * RCProcI2OMsgQ(), which in turn process the message and * calls one of our callback functions. */static void RCinterrupt(int irq, void *dev_id, struct pt_regs *regs){ PDPA pDpa; struct device *dev = (struct device *)(dev_id); pDpa = (PDPA) (dev->priv); #ifdef RCDEBUG if (pDpa->shutdown) printk("rc: shutdown: service irq\n"); printk("RC irq: pDpa = 0x%x, dev = 0x%x, id = %d\n", (uint)pDpa, (uint)dev, (uint)pDpa->id); printk("dev = 0x%x\n", (uint)dev);#endif if (dev->interrupt) printk("%s: Re-entering the interrupt handler.\n", dev->name); dev->interrupt = 1; RCProcI2OMsgQ(pDpa->id); dev->interrupt = 0; return;}#define REBOOT_REINIT_RETRY_LIMIT 4static void rc_timer(unsigned long data){ struct device *dev = (struct device *)data; PDPA pDpa = (PDPA) (dev->priv); int init_status; static int retry = 0; int post_buffers = MAX_NMBR_RCV_BUFFERS; int count = 0; int requested = 0; if (pDpa->reboot) { init_status = RCInitI2OMsgLayer(pDpa->id, dev->base_addr, pDpa->PLanApiPA, (PU8)virt_to_bus((void *)pDpa->PLanApiPA), (PFNTXCALLBACK)RCxmit_callback, (PFNRXCALLBACK)RCrecv_callback, (PFNCALLBACK)RCreboot_callback); switch(init_status) { case RC_RTN_NO_ERROR: pDpa->reboot = 0; pDpa->shutdown = 0; /* just in case */ RCReportDriverCapability(pDpa->id, DriverControlWord); RCEnableI2OInterrupts(pDpa->id); if (dev->flags & IFF_UP) { while(post_buffers) { if (post_buffers > MAX_NMBR_POST_BUFFERS_PER_MSG) requested = MAX_NMBR_POST_BUFFERS_PER_MSG; else requested = post_buffers; count = RC_allocate_and_post_buffers(dev, requested); post_buffers -= count;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -