📄 3c509.c
字号:
outw_el3(dep, REG_CmdStatus, CMD_StopIntXcvr); /* milli_delay(5); */ } else if (dep->de_if_port == TP_XCVR) { SetWindow(WNO_Diagnostics); outw_el3(dep, REG_MediaStatus, inw_el3(dep, REG_MediaStatus) & NOT((MediaLBeatEnable | MediaJabberEnable))); /* milli_delay(5); */ } DEBUG(printf("%s: stopping Etherlink ... \n", dep->de_name)); /* Issues a global reset outw_el3(dep, REG_CmdStatus, CMD_GlobalReset); */ sys_irqdisable(&dep->de_hook); /* Disable interrupt */ return;}/*** Name: void el3_interrupt(dpeth_t *dep)** Function: Interrupt handler. Acknwledges transmit interrupts** or unloads receive buffer to memory queue.*/static void el3_interrupt(dpeth_t * dep){ int loop; unsigned short isr; for (loop = 5; loop > 0 && ((isr = inw_el3(dep, REG_CmdStatus)) & (INT_Latch | INT_RxComplete | INT_UpdateStats)); loop -= 1) { if (isr & INT_RxComplete) /* Got a new packet */ el3_rx_complete(dep); if (isr & INT_TxAvailable) { /* Tx has room for big packets */ DEBUG(printf("3c509: got Tx interrupt, Status=0x%04x\n", isr);) dep->de_flags &= NOT(DEF_XMIT_BUSY); outw_el3(dep, REG_CmdStatus, CMD_Acknowledge | INT_TxAvailable); if (dep->de_flags & DEF_SENDING) /* Send pending */ el3_send(dep, TRUE, dep->de_send_s); } if (isr & (INT_AdapterFail | INT_RxEarly | INT_UpdateStats)) { if (isr & INT_UpdateStats) /* Empties statistics */ el3_getstats(dep); if (isr & INT_RxEarly) /* Not really used. Do nothing */ outw_el3(dep, REG_CmdStatus, CMD_Acknowledge | (INT_RxEarly)); if (isr & INT_AdapterFail) { /* Adapter error. Reset and re-enable receiver */ DEBUG(printf("3c509: got Rx fail interrupt, Status=0x%04x\n", isr);) el3_rx_mode(dep); outw_el3(dep, REG_CmdStatus, CMD_Acknowledge | INT_AdapterFail); } } /* Acknowledge interrupt */ outw_el3(dep, REG_CmdStatus, CMD_Acknowledge | (INT_Latch | INT_Requested)); } return;}/*** Name: unsigned el3_read_eeprom(port_t port, unsigned address);** Function: Reads the EEPROM at specified address*/static unsigned el3_read_eeprom(port_t port, unsigned address){ unsigned int result; int bit; address |= EL3_READ_EEPROM; outb(port, address); milli_delay(5); /* Allows EEPROM reads */ for (result = 0, bit = 16; bit > 0; bit -= 1) { result = (result << 1) | (inb(port) & 0x0001); } return result;}/*** Name: void el3_read_StationAddress(dpeth_t *dep)** Function: Reads station address from board*/static void el3_read_StationAddress(dpeth_t * dep){ unsigned int ix, rc; for (ix = EE_3COM_NODE_ADDR; ix < SA_ADDR_LEN;) { /* Accesses with word No. */ rc = el3_read_eeprom(dep->de_id_port, ix / 2); /* Swaps bytes of word */ dep->de_address.ea_addr[ix++] = (rc >> 8) & 0xFF; dep->de_address.ea_addr[ix++] = rc & 0xFF; } return;}/*** Name: void el3_open(dpeth_t *dep)** Function: Initalizes board hardware and driver data structures.*/static void el3_open(dpeth_t * dep){ unsigned int AddrCfgReg, ResCfgReg; unsigned int ix; el3_read_StationAddress(dep); /* Get ethernet address */ /* Get address and resource configurations */ AddrCfgReg = el3_read_eeprom(dep->de_id_port, EE_ADDR_CFG); ResCfgReg = el3_read_eeprom(dep->de_id_port, EE_RESOURCE_CFG); outb(dep->de_id_port, EL3_ACTIVATE); /* Activate the board */ /* Gets xcvr configuration */ dep->de_if_port = AddrCfgReg & EL3_CONFIG_XCVR_MASK; AddrCfgReg = ((AddrCfgReg & EL3_CONFIG_IOBASE_MASK) << 4) + EL3_IO_BASE_ADDR; if (AddrCfgReg != dep->de_base_port) panic(dep->de_name, "Bad I/O port for Etherlink board", NO_NUM); ResCfgReg >>= 12; dep->de_irq &= NOT(DEI_DEFAULT); /* Strips the default flag */ if (ResCfgReg != dep->de_irq) panic(dep->de_name, "Bad IRQ for Etherlink board", NO_NUM); SetWindow(WNO_Setup); /* Reset transmitter and receiver */ outw_el3(dep, REG_CmdStatus, CMD_TxReset); outw_el3(dep, REG_CmdStatus, CMD_RxReset); /* Enable the adapter */ outb_el3(dep, REG_CfgControl, EL3_EnableAdapter); /* Disable Status bits */ outw_el3(dep, REG_CmdStatus, CMD_SetStatusEnab + 0x00); /* Set "my own" address */ SetWindow(WNO_StationAddress); for (ix = 0; ix < 6; ix += 1) outb_el3(dep, REG_SA0_1 + ix, dep->de_address.ea_addr[ix]); /* Start Transceivers as required */ if (dep->de_if_port == BNC_XCVR) { /* Start internal transceiver for Coaxial cable */ outw_el3(dep, REG_CmdStatus, CMD_StartIntXcvr); milli_delay(5); } else if (dep->de_if_port == TP_XCVR) { /* Start internal transceiver for Twisted pair cable */ SetWindow(WNO_Diagnostics); outw_el3(dep, REG_MediaStatus, inw_el3(dep, REG_MediaStatus) | (MediaLBeatEnable | MediaJabberEnable)); } /* Switch to the statistic window, and clear counts (by reading) */ SetWindow(WNO_Statistics); for (ix = REG_TxCarrierLost; ix <= REG_TxDefer; ix += 1) inb_el3(dep, ix); inw_el3(dep, REG_RxBytes); inw_el3(dep, REG_TxBytes); /* Switch to operating window for normal use */ SetWindow(WNO_Operating); /* Receive individual address & broadcast. (Mofified later by rx_mode) */ outw_el3(dep, REG_CmdStatus, CMD_SetRxFilter | (FilterIndividual | FilterBroadcast)); /* Turn on statistics */ outw_el3(dep, REG_CmdStatus, CMD_StatsEnable); /* Enable transmitter and receiver */ outw_el3(dep, REG_CmdStatus, CMD_TxEnable); outw_el3(dep, REG_CmdStatus, CMD_RxEnable); /* Enable all the status bits */ outw_el3(dep, REG_CmdStatus, CMD_SetStatusEnab | 0xFF); /* Acknowledge all interrupts to clear adapter. Enable interrupts */ outw_el3(dep, REG_CmdStatus, CMD_Acknowledge | 0xFF); outw_el3(dep, REG_CmdStatus, CMD_SetIntMask | (INT_Latch | INT_TxAvailable | INT_RxComplete | INT_UpdateStats)); /* Ready to operate, sets the environment for eth_task */ dep->de_data_port = dep->de_base_port; /* Allocates Rx/Tx buffers */ init_buff(dep, NULL); /* Device specific functions */ dep->de_recvf = el3_recv; dep->de_sendf = el3_send; dep->de_flagsf = el3_rx_mode; dep->de_resetf = el3_reset; dep->de_getstatsf = el3_getstats; dep->de_dumpstatsf = el3_dodump; dep->de_interruptf = el3_interrupt; printf("%s: Etherlink III (%s) at %X:%d, %s port - ", dep->de_name, "3c509", dep->de_base_port, dep->de_irq, IfNamesMsg[dep->de_if_port >> 14]); for (ix = 0; ix < SA_ADDR_LEN; ix += 1) printf("%02X%c", dep->de_address.ea_addr[ix], ix < SA_ADDR_LEN - 1 ? ':' : '\n'); return; /* Done */}/*** Name: unsigned int el3_checksum(port_t port);** Function: Reads EEPROM and computes checksum.*/static unsigned short el3_checksum(port_t port){ unsigned short rc, checksum, address; unsigned char lo, hi; for (checksum = address = 0; address < 15; address += 1) { rc = el3_read_eeprom(port, address); lo = rc & 0xFF; hi = (rc >> 8) & 0xFF; if ((address == EE_PROD_ID && (rc & EE_PROD_ID_MASK) != EL3_PRODUCT_ID) || (address == EE_3COM_CODE && rc != EL3_3COM_CODE)) return address; if (address == EE_ADDR_CFG || address == EE_RESOURCE_CFG || address == EE_SW_CONFIG_INFO) { lo ^= hi; hi = 0; } else { hi ^= lo; lo = 0; } rc = ((unsigned) hi << 8) + lo; checksum ^= rc; } rc = el3_read_eeprom(port, address); return(checksum ^= rc); /* If OK checksum is 0 */}/*** Name: void el3_write_id(port_t port);** Function: Writes the ID sequence to the board.*/static void el3_write_id(port_t port){ int ix, pattern; outb(port, 0); /* Selects the ID port */ outb(port, 0); /* Resets hardware pattern generator */ for (pattern = ix = 0x00FF; ix > 0; ix -= 1) { outb(port, pattern); pattern <<= 1; pattern = (pattern & 0x0100) ? pattern ^ 0xCF : pattern; } return;}/*** Name: int el3_probe(dpeth_t *dep)** Function: Checks for presence of the board.*/PUBLIC int el3_probe(dpeth_t * dep){ port_t id_port; /* Don't ask me what is this for !! */ outb(0x0279, 0x02); /* Select PnP config control register. */ outb(0x0A79, 0x02); /* Return to WaitForKey state. */ /* Tests I/O ports in the 0x1xF range for a valid ID port */ for (id_port = 0x110; id_port < 0x200; id_port += 0x10) { outb(id_port, 0x00); outb(id_port, 0xFF); if (inb(id_port) & 0x01) break; } if (id_port == 0x200) return 0; /* No board responding */ el3_write_id(id_port); outb(id_port, EL3_ID_GLOBAL_RESET); /* Reset the board */ milli_delay(5); /* Technical reference says 162 micro sec. */ el3_write_id(id_port); outb(id_port, EL3_SET_TAG_REGISTER); milli_delay(5); dep->de_id_port = id_port; /* Stores ID port No. */ dep->de_ramsize = /* RAM size is meaningless */ dep->de_offset_page = 0; dep->de_linmem = 0L; /* Access is via I/O port */ /* Device specific functions */ dep->de_initf = el3_open; dep->de_stopf = el3_close; return(el3_checksum(id_port) == 0); /* Etherlink board found/not found */}#endif /* ENABLE_3C509 *//** 3c509.c **/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -