📄 tms380tr.c
字号:
int i, loop_cnt, retry_cnt; /* Normalize: byte order low/high, word order high/low! (only IPB!) */ tp->ipb.SCB_Addr = SWAPW(((char *)&tp->scb - (char *)tp) + tp->dmabuffer); tp->ipb.SSB_Addr = SWAPW(((char *)&tp->ssb - (char *)tp) + tp->dmabuffer); if(tms380tr_debug > 3) { printk(KERN_DEBUG "%s: buffer (real): %lx\n", dev->name, (long) &tp->scb); printk(KERN_DEBUG "%s: buffer (virt): %lx\n", dev->name, (long) ((char *)&tp->scb - (char *)tp) + (long) tp->dmabuffer); printk(KERN_DEBUG "%s: buffer (DMA) : %lx\n", dev->name, (long) tp->dmabuffer); printk(KERN_DEBUG "%s: buffer (tp) : %lx\n", dev->name, (long) tp); } /* Maximum: three initialization retries */ retry_cnt = INIT_MAX_RETRIES; do { retry_cnt--; /* Transfer initialization block */ SIFWRITEW(0x0001, SIFADX); /* To address 0001:0A00 of adapter RAM */ SIFWRITEW(0x0A00, SIFADD); /* Write 11 words to adapter RAM */ for(i = 0; i < 11; i++) SIFWRITEW(ipb_ptr[i], SIFINC); /* Execute SCB adapter command */ tms380tr_exec_sifcmd(dev, CMD_EXECUTE); loop_cnt = INIT_MAX_LOOPCNT; /* Maximum: 11 seconds */ /* While remaining retries, no error and not completed */ do { Status = 0; loop_cnt--; tms380tr_wait(HALF_SECOND); /* Mask interesting status bits */ Status = SIFREADW(SIFSTS); Status &= STS_MASK; } while(((Status &(STS_INITIALIZE | STS_ERROR | STS_TEST)) != 0) && ((Status & STS_ERROR) == 0) && (loop_cnt != 0)); if((Status & (STS_INITIALIZE | STS_ERROR | STS_TEST)) == 0) { /* Initialization completed without error */ i = 0; do { /* Test if contents of SCB is valid */ if(SCB_Test[i] != *(cb_ptr + i)) { printk(KERN_INFO "%s: DMA failed\n", dev->name); /* DMA data error: wrong data in SCB */ return (-1); } i++; } while(i < 6); i = 0; do { /* Test if contents of SSB is valid */ if(SSB_Test[i] != *(sb_ptr + i)) /* DMA data error: wrong data in SSB */ return (-1); i++; } while (i < 8); return (1); /* Adapter successfully initialized */ } else { if((Status & STS_ERROR) != 0) { /* Initialization error occurred */ Status = SIFREADW(SIFSTS); Status &= STS_ERROR_MASK; /* ShowInitialisationErrorCode(Status); */ printk(KERN_INFO "%s: Status error: %d\n", dev->name, Status); return (-1); /* Unrecoverable error */ } else { if(retry_cnt > 0) { /* Reset adapter and try init again */ tms380tr_exec_sifcmd(dev, EXEC_SOFT_RESET); tms380tr_wait(HALF_SECOND); } } } } while(retry_cnt > 0); printk(KERN_INFO "%s: Retry exceeded\n", dev->name); return (-1);}/* * Check for outstanding commands in command queue and tries to execute * command immediately. Corresponding command flag in command queue is cleared. */static void tms380tr_chk_outstanding_cmds(struct net_device *dev){ struct net_local *tp = netdev_priv(dev); unsigned long Addr = 0; if(tp->CMDqueue == 0) return; /* No command execution */ /* If SCB in use: no command */ if(tp->ScbInUse == 1) return; /* Check if adapter is opened, avoiding COMMAND_REJECT * interrupt by the adapter! */ if(tp->AdapterOpenFlag == 0) { if(tp->CMDqueue & OC_OPEN) { /* Execute OPEN command */ tp->CMDqueue ^= OC_OPEN; Addr = htonl(((char *)&tp->ocpl - (char *)tp) + tp->dmabuffer); tp->scb.Parm[0] = LOWORD(Addr); tp->scb.Parm[1] = HIWORD(Addr); tp->scb.CMD = OPEN; } else /* No OPEN command queued, but adapter closed. Note: * We'll try to re-open the adapter in DriverPoll() */ return; /* No adapter command issued */ } else { /* Adapter is open; evaluate command queue: try to execute * outstanding commands (depending on priority!) CLOSE * command queued */ if(tp->CMDqueue & OC_CLOSE) { tp->CMDqueue ^= OC_CLOSE; tp->AdapterOpenFlag = 0; tp->scb.Parm[0] = 0; /* Parm[0], Parm[1] are ignored */ tp->scb.Parm[1] = 0; /* but should be set to zero! */ tp->scb.CMD = CLOSE; if(!tp->HaltInProgress) tp->CMDqueue |= OC_OPEN; /* re-open adapter */ else tp->CMDqueue = 0; /* no more commands */ } else { if(tp->CMDqueue & OC_RECEIVE) { tp->CMDqueue ^= OC_RECEIVE; Addr = htonl(((char *)tp->RplHead - (char *)tp) + tp->dmabuffer); tp->scb.Parm[0] = LOWORD(Addr); tp->scb.Parm[1] = HIWORD(Addr); tp->scb.CMD = RECEIVE; } else { if(tp->CMDqueue & OC_TRANSMIT_HALT) { /* NOTE: TRANSMIT.HALT must be checked * before TRANSMIT. */ tp->CMDqueue ^= OC_TRANSMIT_HALT; tp->scb.CMD = TRANSMIT_HALT; /* Parm[0] and Parm[1] are ignored * but should be set to zero! */ tp->scb.Parm[0] = 0; tp->scb.Parm[1] = 0; } else { if(tp->CMDqueue & OC_TRANSMIT) { /* NOTE: TRANSMIT must be * checked after TRANSMIT.HALT */ if(tp->TransmitCommandActive) { if(!tp->TransmitHaltScheduled) { tp->TransmitHaltScheduled = 1; tms380tr_exec_cmd(dev, OC_TRANSMIT_HALT) ; } tp->TransmitCommandActive = 0; return; } tp->CMDqueue ^= OC_TRANSMIT; tms380tr_cancel_tx_queue(tp); Addr = htonl(((char *)tp->TplBusy - (char *)tp) + tp->dmabuffer); tp->scb.Parm[0] = LOWORD(Addr); tp->scb.Parm[1] = HIWORD(Addr); tp->scb.CMD = TRANSMIT; tp->TransmitCommandActive = 1; } else { if(tp->CMDqueue & OC_MODIFY_OPEN_PARMS) { tp->CMDqueue ^= OC_MODIFY_OPEN_PARMS; tp->scb.Parm[0] = tp->ocpl.OPENOptions; /* new OPEN options*/ tp->scb.Parm[0] |= ENABLE_FULL_DUPLEX_SELECTION; tp->scb.Parm[1] = 0; /* is ignored but should be zero */ tp->scb.CMD = MODIFY_OPEN_PARMS; } else { if(tp->CMDqueue & OC_SET_FUNCT_ADDR) { tp->CMDqueue ^= OC_SET_FUNCT_ADDR; tp->scb.Parm[0] = LOWORD(tp->ocpl.FunctAddr); tp->scb.Parm[1] = HIWORD(tp->ocpl.FunctAddr); tp->scb.CMD = SET_FUNCT_ADDR; } else { if(tp->CMDqueue & OC_SET_GROUP_ADDR) { tp->CMDqueue ^= OC_SET_GROUP_ADDR; tp->scb.Parm[0] = LOWORD(tp->ocpl.GroupAddr); tp->scb.Parm[1] = HIWORD(tp->ocpl.GroupAddr); tp->scb.CMD = SET_GROUP_ADDR; } else { if(tp->CMDqueue & OC_READ_ERROR_LOG) { tp->CMDqueue ^= OC_READ_ERROR_LOG; Addr = htonl(((char *)&tp->errorlogtable - (char *)tp) + tp->dmabuffer); tp->scb.Parm[0] = LOWORD(Addr); tp->scb.Parm[1] = HIWORD(Addr); tp->scb.CMD = READ_ERROR_LOG; } else { printk(KERN_WARNING "CheckForOutstandingCommand: unknown Command\n"); tp->CMDqueue = 0; return; } } } } } } } } } tp->ScbInUse = 1; /* Set semaphore: SCB in use. */ /* Execute SCB and generate IRQ when done. */ tms380tr_exec_sifcmd(dev, CMD_EXECUTE | CMD_SCB_REQUEST); return;}/* * IRQ conditions: signal loss on the ring, transmit or receive of beacon * frames (disabled if bit 1 of OPEN option is set); report error MAC * frame transmit (disabled if bit 2 of OPEN option is set); open or short * circuit fault on the lobe is detected; remove MAC frame received; * error counter overflow (255); opened adapter is the only station in ring. * After some of the IRQs the adapter is closed! */static void tms380tr_ring_status_irq(struct net_device *dev){ struct net_local *tp = netdev_priv(dev); tp->CurrentRingStatus = be16_to_cpu((unsigned short)tp->ssb.Parm[0]); /* First: fill up statistics */ if(tp->ssb.Parm[0] & SIGNAL_LOSS) { printk(KERN_INFO "%s: Signal Loss\n", dev->name); tp->MacStat.line_errors++; } /* Adapter is closed, but initialized */ if(tp->ssb.Parm[0] & LOBE_WIRE_FAULT) { printk(KERN_INFO "%s: Lobe Wire Fault, Reopen Adapter\n", dev->name); tp->MacStat.line_errors++; } if(tp->ssb.Parm[0] & RING_RECOVERY) printk(KERN_INFO "%s: Ring Recovery\n", dev->name); /* Counter overflow: read error log */ if(tp->ssb.Parm[0] & COUNTER_OVERFLOW) { printk(KERN_INFO "%s: Counter Overflow\n", dev->name); tms380tr_exec_cmd(dev, OC_READ_ERROR_LOG); } /* Adapter is closed, but initialized */ if(tp->ssb.Parm[0] & REMOVE_RECEIVED) printk(KERN_INFO "%s: Remove Received, Reopen Adapter\n", dev->name); /* Adapter is closed, but initialized */ if(tp->ssb.Parm[0] & AUTO_REMOVAL_ERROR) printk(KERN_INFO "%s: Auto Removal Error, Reopen Adapter\n", dev->name); if(tp->ssb.Parm[0] & HARD_ERROR) printk(KERN_INFO "%s: Hard Error\n", dev->name); if(tp->ssb.Parm[0] & SOFT_ERROR) printk(KERN_INFO "%s: Soft Error\n", dev->name); if(tp->ssb.Parm[0] & TRANSMIT_BEACON) printk(KERN_INFO "%s: Transmit Beacon\n", dev->name); if(tp->ssb.Parm[0] & SINGLE_STATION) printk(KERN_INFO "%s: Single Station\n", dev->name); /* Check if adapter has been closed */ if(tp->ssb.Parm[0] & ADAPTER_CLOSED) { printk(KERN_INFO "%s: Adapter closed (Reopening)," "CurrentRingStat %x\n", dev->name, tp->CurrentRingStatus); tp->AdapterOpenFlag = 0; tms380tr_open_adapter(dev); } return;}/* * Issued if adapter has encountered an unrecoverable hardware * or software error. */static void tms380tr_chk_irq(struct net_device *dev){ int i; unsigned short AdapterCheckBlock[4]; struct net_local *tp = netdev_priv(dev); tp->AdapterOpenFlag = 0; /* Adapter closed now */ /* Page number of adapter memory */ SIFWRITEW(0x0001, SIFADX); /* Address offset */ SIFWRITEW(CHECKADDR, SIFADR); /* Reading 8 byte adapter check block. */ for(i = 0; i < 4; i++) AdapterCheckBlock[i] = SIFREADW(SIFINC); if(tms380tr_debug > 3) { printk(KERN_DEBUG "%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(KERN_INFO "%s: Illegal operation code in firmware\n", dev->name); /* Parm[0-3]: adapter internal register R13-R15 */ break; case PARITY_ERRORS: printk(KERN_INFO "%s: Adapter internal bus parity error\n", dev->name); /* Parm[0-3]: adapter internal register R13-R15 */ break; case RAM_DATA_ERROR: printk(KERN_INFO "%s: RAM data error\n", dev->name); /* Parm[0-1]: MSW/LSW address of RAM location. */ break; case RAM_PARITY_ERROR: printk(KERN_INFO "%s: RAM parity error\n", dev->name); /* Parm[0-1]: MSW/LSW address of RAM location. */ break; case RING_UNDERRUN: printk(KERN_INFO "%s: Internal DMA underrun detected\n", dev->name); break; case INVALID_IRQ: printk(KERN_INFO "%s: Unrecognized interrupt detected\n", dev->name); /* Parm[0-3]: adapter internal register R13-R15 */ break; case INVALID_ERROR_IRQ: printk(KERN_INFO "%s: Unrecognized error interrupt detected\n", dev->name); /* Parm[0-3]: adapter internal register R13-R15 */ break; case INVALID_XOP: printk(KERN_INFO "%s: Unrecognized XOP request detected\n", dev->name);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -