📄 sktr.c
字号:
if(sktr_debug > 3) { printk("%s: AdapterCheckBlock: ", dev->name); for (i = 0; i < 4; i++) printk("%04X", AdapterCheckBlock[i]); printk("\n"); } switch(AdapterCheckBlock[0]) { case DIO_PARITY: printk(KERN_INFO "%s: DIO parity error\n", dev->name); break; case DMA_READ_ABORT: printk(KERN_INFO "%s DMA read operation aborted:\n", dev->name); switch (AdapterCheckBlock[1]) { case 0: printk(KERN_INFO "Timeout\n"); printk(KERN_INFO "Address: %04X %04X\n", AdapterCheckBlock[2], AdapterCheckBlock[3]); break; case 1: printk(KERN_INFO "Parity error\n"); printk(KERN_INFO "Address: %04X %04X\n", AdapterCheckBlock[2], AdapterCheckBlock[3]); break; case 2: printk(KERN_INFO "Bus error\n"); printk(KERN_INFO "Address: %04X %04X\n", AdapterCheckBlock[2], AdapterCheckBlock[3]); break; default: printk(KERN_INFO "Unknown error.\n"); break; } break; case DMA_WRITE_ABORT: printk(KERN_INFO "%s: DMA write operation aborted: \n", dev->name); switch (AdapterCheckBlock[1]) { case 0: printk(KERN_INFO "Timeout\n"); printk(KERN_INFO "Address: %04X %04X\n", AdapterCheckBlock[2], AdapterCheckBlock[3]); break; case 1: printk(KERN_INFO "Parity error\n"); printk(KERN_INFO "Address: %04X %04X\n", AdapterCheckBlock[2], AdapterCheckBlock[3]); break; case 2: printk(KERN_INFO "Bus error\n"); printk(KERN_INFO "Address: %04X %04X\n", AdapterCheckBlock[2], AdapterCheckBlock[3]); break; default: printk(KERN_INFO "Unknown error.\n"); break; } break; case ILLEGAL_OP_CODE: printk("%s: Illegal operation code in firmware\n", dev->name); /* Parm[0-3]: adapter internal register R13-R15 */ break; case PARITY_ERRORS: printk("%s: Adapter internal bus parity error\n", dev->name); /* Parm[0-3]: adapter internal register R13-R15 */ break; case RAM_DATA_ERROR: printk("%s: RAM data error\n", dev->name); /* Parm[0-1]: MSW/LSW address of RAM location. */ break; case RAM_PARITY_ERROR: printk("%s: RAM parity error\n", dev->name); /* Parm[0-1]: MSW/LSW address of RAM location. */ break; case RING_UNDERRUN: printk("%s: Internal DMA underrun detected\n", dev->name); break; case INVALID_IRQ: printk("%s: Unrecognized interrupt detected\n", dev->name); /* Parm[0-3]: adapter internal register R13-R15 */ break; case INVALID_ERROR_IRQ: printk("%s: Unrecognized error interrupt detected\n", dev->name); /* Parm[0-3]: adapter internal register R13-R15 */ break; case INVALID_XOP: printk("%s: Unrecognized XOP request detected\n", dev->name); /* Parm[0-3]: adapter internal register R13-R15 */ break; default: printk("%s: Unknown status", dev->name); break; } if(sktr_chipset_init(dev) == 1) { /* Restart of firmware successful */ tp->AdapterOpenFlag = 1; } return;}/* * Internal adapter pointer to RAM data are copied from adapter into * host system. */static void sktr_read_ptr(struct device *dev){ struct net_local *tp = (struct net_local *)dev->priv; unsigned short adapterram; sktr_read_ram(dev, (unsigned char *)&tp->intptrs.BurnedInAddrPtr, ADAPTER_INT_PTRS, 16); sktr_read_ram(dev, (unsigned char *)&adapterram, (unsigned short)SWAPB(tp->intptrs.AdapterRAMPtr), 2); printk(KERN_INFO "%s: Adapter RAM size: %d K\n", dev->name, SWAPB(adapterram)); return;}/* * Reads a number of bytes from adapter to system memory. */static void sktr_read_ram(struct device *dev, unsigned char *Data, unsigned short Address, int Length){ int i; unsigned short old_sifadx, old_sifadr, InWord; unsigned short ioaddr = dev->base_addr; /* Save the current values */ old_sifadx = inw(ioaddr + SIFADX); old_sifadr = inw(ioaddr + SIFADR); /* Page number of adapter memory */ outw(0x0001, ioaddr + SIFADX); /* Address offset in adapter RAM */ outw(Address, ioaddr + SIFADR); /* Copy len byte from adapter memory to system data area. */ i = 0; for(;;) { InWord = inw(ioaddr + SIFINC); *(Data + i) = HIBYTE(InWord); /* Write first byte */ if(++i == Length) /* All is done break */ break; *(Data + i) = LOBYTE(InWord); /* Write second byte */ if (++i == Length) /* All is done break */ break; } /* Restore original values */ outw(old_sifadx, ioaddr + SIFADX); outw(old_sifadr, ioaddr + SIFADR); return;}/* * Reads MAC address from adapter ROM. */static void sktr_read_addr(struct device *dev, unsigned char *Address){ int i, In; unsigned short ioaddr = dev->base_addr; /* Address: 0000:0000 */ outw(0, ioaddr + SIFADX); outw(0, ioaddr + SIFADR); /* Read six byte MAC address data */ for(i = 0; i < 6; i++) { In = inw(ioaddr + SIFINC); *(Address + i) = (unsigned char)(In >> 8); } return;}/* * Cancel all queued packets in the transmission queue. */static void sktr_cancel_tx_queue(struct net_local* tp){ TPL *tpl; struct sk_buff *skb; /* * NOTE: There must not be an active TRANSMIT command pending, when * this function is called. */ if(tp->TransmitCommandActive) return; for(;;) { tpl = tp->TplBusy; if(!tpl->BusyFlag) break; /* "Remove" TPL from busy list. */ tp->TplBusy = tpl->NextTPLPtr; sktr_write_tpl_status(tpl, 0); /* Clear VALID bit */ tpl->BusyFlag = 0; /* "free" TPL */ printk(KERN_INFO "Cancel tx (%08lXh).\n", (unsigned long)tpl); dev_kfree_skb(tpl->Skb); } for(;;) { skb = skb_dequeue(&tp->SendSkbQueue); if(skb == NULL) break; tp->QueueSkb++; dev_kfree_skb(skb); } return;}/* * This function is called whenever a transmit interrupt is generated by the * adapter. For a command complete interrupt, it is checked if we have to * issue a new transmit command or not. */static void sktr_tx_status_irq(struct device *dev){ struct net_local *tp = (struct net_local *)dev->priv; unsigned char HighByte, HighAc, LowAc; TPL *tpl; /* NOTE: At this point the SSB from TRANSMIT STATUS is no longer * available, because the CLEAR SSB command has already been issued. * * Process all complete transmissions. */ for(;;) { tpl = tp->TplBusy; if(!tpl->BusyFlag || (tpl->Status & (TX_VALID | TX_FRAME_COMPLETE)) != TX_FRAME_COMPLETE) { break; } /* "Remove" TPL from busy list. */ tp->TplBusy = tpl->NextTPLPtr ; if(sktr_debug > 3) sktr_dump(tpl->MData, SWAPB(tpl->FrameSize)); /* Check the transmit status field only for directed frames*/ if(DIRECTED_FRAME(tpl) && (tpl->Status & TX_ERROR) == 0) { HighByte = GET_TRANSMIT_STATUS_HIGH_BYTE(tpl->Status); HighAc = GET_FRAME_STATUS_HIGH_AC(HighByte); LowAc = GET_FRAME_STATUS_LOW_AC(HighByte); if((HighAc != LowAc) || (HighAc == AC_NOT_RECOGNIZED)) { printk(KERN_INFO "%s: (DA=%08lX not recognized)", dev->name, *(unsigned long *)&tpl->MData[2+2]); } else { if(sktr_debug > 3) printk("%s: Directed frame tx'd\n", dev->name); } } else { if(!DIRECTED_FRAME(tpl)) { if(sktr_debug > 3) printk("%s: Broadcast frame tx'd\n", dev->name); } } tp->MacStat.tx_packets++; dev_kfree_skb(tpl->Skb); tpl->BusyFlag = 0; /* "free" TPL */ } dev->tbusy = 0; if(tp->QueueSkb < MAX_TX_QUEUE) sktr_hardware_send_packet(dev, tp); return;}/* * Called if a frame receive interrupt is generated by the adapter. * Check if the frame is valid and indicate it to system. */static void sktr_rcv_status_irq(struct device *dev){ struct net_local *tp = (struct net_local *)dev->priv; unsigned char *ReceiveDataPtr; struct sk_buff *skb; unsigned int Length, Length2; RPL *rpl; RPL *SaveHead; /* NOTE: At this point the SSB from RECEIVE STATUS is no longer * available, because the CLEAR SSB command has already been issued. * * Process all complete receives. */ for(;;) { rpl = tp->RplHead; if(rpl->Status & RX_VALID) break; /* RPL still in use by adapter */ /* Forward RPLHead pointer to next list. */ SaveHead = tp->RplHead; tp->RplHead = rpl->NextRPLPtr; /* Get the frame size (Byte swap for Intel). * Do this early (see workaround comment below) */ Length = (unsigned short)SWAPB(rpl->FrameSize); /* Check if the Frame_Start, Frame_End and * Frame_Complete bits are set. */ if((rpl->Status & VALID_SINGLE_BUFFER_FRAME) == VALID_SINGLE_BUFFER_FRAME) { ReceiveDataPtr = rpl->MData; /* Workaround for delayed write of FrameSize on ISA * (FrameSize is false but valid-bit is reset) * Frame size is set to zero when the RPL is freed. * Length2 is there because there have also been * cases where the FrameSize was partially written */ Length2 = (unsigned short)SWAPB(rpl->FrameSize); if(Length == 0 || Length != Length2) { tp->RplHead = SaveHead; break; /* Return to sktr_interrupt */ } /* Drop frames sent by myself */ if(sktr_chk_frame(dev, rpl->MData)) { printk(KERN_INFO "%s: Received my own frame\n", dev->name); if(rpl->Skb != NULL) dev_kfree_skb(rpl->Skb); } else { sktr_update_rcv_stats(tp,ReceiveDataPtr,Length); if(sktr_debug > 3) printk("%s: Packet Length %04X (%d)\n", dev->name, Length, Length); /* Indicate the received frame to system the * adapter does the Source-Routing padding for * us. See: OpenOptions in sktr_init_opb() */ skb = rpl->Skb; if(rpl->SkbStat == SKB_UNAVAILABLE) { /* Try again to allocate skb */ skb = dev_alloc_skb(tp->MaxPacketSize); if(skb == NULL) { /* Update Stats ?? */ } else { skb->dev = dev; skb_put(skb, tp->MaxPacketSize); rpl->SkbStat = SKB_DATA_COPY; ReceiveDataPtr = rpl->MData; } } if(rpl->SkbStat == SKB_DATA_COPY || rpl->SkbStat == SKB_DMA_DIRECT) { if(rpl->SkbStat == SKB_DATA_COPY) { memmove(skb->data, ReceiveDataPtr, Length); } /* Deliver frame to system */ rpl->Skb = NULL; skb_trim(skb,Length); skb->protocol = tr_type_trans(skb,dev); netif_rx(skb); } } } else /* Invalid frame */ { if(rpl->Skb != NULL) dev_kfree_skb(rpl->Skb); /* Skip list. */ if(rpl->Status & RX_START_FRAME) /* Frame start bit is set -> overflow. */ tp->MacStat.rx_errors++; } /* Allocate new skb for rpl */ rpl->Skb = dev_alloc_skb(tp->MaxPacketSize); /* skb == NULL ? then use local buffer */ if(rpl->Skb == NULL) { rpl->SkbStat = SKB_UNAVAILABLE; rpl->FragList[0].DataAddr = htonl(virt_to_bus(tp->LocalRxBuffers[rpl->RPLIndex])); rpl->MData = tp->LocalRxBuffers[rpl->RPLIndex]; } else /* skb != NULL */ { rpl->Skb->dev = dev; skb_put(rpl->Skb, tp->MaxPacketSize); /* Data unreachable for DMA ? then use local buffer */ if(virt_to_bus(rpl->Skb->data) + tp->MaxPacketSize > ISA_MAX_ADDRESS) { rpl->SkbStat = SKB_DATA_COPY; rpl->FragList[0].DataAddr = htonl(virt_to_bus(tp->LocalRxBuffers[rpl->RPLIndex])); rpl->MData = tp->LocalRxBuffers[rpl->RPLIndex]; } else { /* DMA directly in skb->data */ rpl->SkbStat = SKB_DMA_DIRECT; rpl->FragList[0].DataAddr = htonl(virt_to_bus(rpl->Skb->data)); rpl->MData = rpl->Skb->data; } } rpl->FragList[0].DataCount = SWAPB(tp->MaxPacketSize); rpl->FrameSize = 0; /* Pass the last RPL back to the adapter */ tp->RplTail->FrameSize = 0; /* Reset the CSTAT field in the list. */ sktr_write_rpl_status(tp->RplTail, RX_VALID | RX_FRAME_IRQ); /* Current RPL becomes last one in list. */ tp->RplTail = tp->RplTail->NextRPLPtr; /* Inform adapter about RPL valid. */ sktr_exec_sifcmd(dev, CMD_RX_VALID); } return;}/* * This function should be used whenever the status of any RPL must be * modified by the driver, because the compile
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -