📄 tlan.c
字号:
nic->transmit = tlan_transmit; return 1;#else nic->disable = tlan_disable; nic->poll = tlan_poll; nic->transmit = tlan_transmit; return nic;#endif}/*********************************************************************************************************************************************************** ThunderLAN Driver Eeprom routines The Compaq Netelligent 10 and 10/100 cards use a Microchip 24C02A EEPROM. These functions are based on information in Microchip's data sheet. I don't know how well this functions will work with other EEPROMs.***********************************************************************************************************************************************************/ /*************************************************************** * TLan_EeSendStart * * Returns: * Nothing * Parms: * io_base The IO port base address for the * TLAN device with the EEPROM to * use. * * This function sends a start cycle to an EEPROM attached * to a TLAN chip. * **************************************************************/void TLan_EeSendStart(u16 io_base){ u16 sio; outw(TLAN_NET_SIO, io_base + TLAN_DIO_ADR); sio = io_base + TLAN_DIO_DATA + TLAN_NET_SIO; TLan_SetBit(TLAN_NET_SIO_ECLOK, sio); TLan_SetBit(TLAN_NET_SIO_EDATA, sio); TLan_SetBit(TLAN_NET_SIO_ETXEN, sio); TLan_ClearBit(TLAN_NET_SIO_EDATA, sio); TLan_ClearBit(TLAN_NET_SIO_ECLOK, sio);} /* TLan_EeSendStart */ /*************************************************************** * TLan_EeSendByte * * Returns: * If the correct ack was received, 0, otherwise 1 * Parms: io_base The IO port base address for the * TLAN device with the EEPROM to * use. * data The 8 bits of information to * send to the EEPROM. * stop If TLAN_EEPROM_STOP is passed, a * stop cycle is sent after the * byte is sent after the ack is * read. * * This function sends a byte on the serial EEPROM line, * driving the clock to send each bit. The function then * reverses transmission direction and reads an acknowledge * bit. * **************************************************************/int TLan_EeSendByte(u16 io_base, u8 data, int stop){ int err; u8 place; u16 sio; outw(TLAN_NET_SIO, io_base + TLAN_DIO_ADR); sio = io_base + TLAN_DIO_DATA + TLAN_NET_SIO; /* Assume clock is low, tx is enabled; */ for (place = 0x80; place != 0; place >>= 1) { if (place & data) TLan_SetBit(TLAN_NET_SIO_EDATA, sio); else TLan_ClearBit(TLAN_NET_SIO_EDATA, sio); TLan_SetBit(TLAN_NET_SIO_ECLOK, sio); TLan_ClearBit(TLAN_NET_SIO_ECLOK, sio); } TLan_ClearBit(TLAN_NET_SIO_ETXEN, sio); TLan_SetBit(TLAN_NET_SIO_ECLOK, sio); err = TLan_GetBit(TLAN_NET_SIO_EDATA, sio); TLan_ClearBit(TLAN_NET_SIO_ECLOK, sio); TLan_SetBit(TLAN_NET_SIO_ETXEN, sio); if ((!err) && stop) { TLan_ClearBit(TLAN_NET_SIO_EDATA, sio); /* STOP, raise data while clock is high */ TLan_SetBit(TLAN_NET_SIO_ECLOK, sio); TLan_SetBit(TLAN_NET_SIO_EDATA, sio); } return (err);} /* TLan_EeSendByte */ /*************************************************************** * TLan_EeReceiveByte * * Returns: * Nothing * Parms: * io_base The IO port base address for the * TLAN device with the EEPROM to * use. * data An address to a char to hold the * data sent from the EEPROM. * stop If TLAN_EEPROM_STOP is passed, a * stop cycle is sent after the * byte is received, and no ack is * sent. * * This function receives 8 bits of data from the EEPROM * over the serial link. It then sends and ack bit, or no * ack and a stop bit. This function is used to retrieve * data after the address of a byte in the EEPROM has been * sent. * **************************************************************/void TLan_EeReceiveByte(u16 io_base, u8 * data, int stop){ u8 place; u16 sio; outw(TLAN_NET_SIO, io_base + TLAN_DIO_ADR); sio = io_base + TLAN_DIO_DATA + TLAN_NET_SIO; *data = 0; /* Assume clock is low, tx is enabled; */ TLan_ClearBit(TLAN_NET_SIO_ETXEN, sio); for (place = 0x80; place; place >>= 1) { TLan_SetBit(TLAN_NET_SIO_ECLOK, sio); if (TLan_GetBit(TLAN_NET_SIO_EDATA, sio)) *data |= place; TLan_ClearBit(TLAN_NET_SIO_ECLOK, sio); } TLan_SetBit(TLAN_NET_SIO_ETXEN, sio); if (!stop) { TLan_ClearBit(TLAN_NET_SIO_EDATA, sio); /* Ack = 0 */ TLan_SetBit(TLAN_NET_SIO_ECLOK, sio); TLan_ClearBit(TLAN_NET_SIO_ECLOK, sio); } else { TLan_SetBit(TLAN_NET_SIO_EDATA, sio); /* No ack = 1 (?) */ TLan_SetBit(TLAN_NET_SIO_ECLOK, sio); TLan_ClearBit(TLAN_NET_SIO_ECLOK, sio); TLan_ClearBit(TLAN_NET_SIO_EDATA, sio); /* STOP, raise data while clock is high */ TLan_SetBit(TLAN_NET_SIO_ECLOK, sio); TLan_SetBit(TLAN_NET_SIO_EDATA, sio); }} /* TLan_EeReceiveByte */ /*************************************************************** * TLan_EeReadByte * * Returns: * No error = 0, else, the stage at which the error * occurred. * Parms: * io_base The IO port base address for the * TLAN device with the EEPROM to * use. * ee_addr The address of the byte in the * EEPROM whose contents are to be * retrieved. * data An address to a char to hold the * data obtained from the EEPROM. * * This function reads a byte of information from an byte * cell in the EEPROM. * **************************************************************/int TLan_EeReadByte(u16 io_base, u8 ee_addr, u8 * data){ int err; int ret = 0; TLan_EeSendStart(io_base); err = TLan_EeSendByte(io_base, 0xA0, TLAN_EEPROM_ACK); if (err) { ret = 1; goto fail; } err = TLan_EeSendByte(io_base, ee_addr, TLAN_EEPROM_ACK); if (err) { ret = 2; goto fail; } TLan_EeSendStart(io_base); err = TLan_EeSendByte(io_base, 0xA1, TLAN_EEPROM_ACK); if (err) { ret = 3; goto fail; } TLan_EeReceiveByte(io_base, data, TLAN_EEPROM_STOP); fail: return ret;} /* TLan_EeReadByte *//*********************************************************************************************************************************************************** ThunderLAN Driver MII Routines These routines are based on the information in Chap. 2 of the "ThunderLAN Programmer's Guide", pp. 15-24.***********************************************************************************************************************************************************/ /*************************************************************** * TLan_MiiReadReg * * Returns: * 0 if ack received ok * 1 otherwise. * * Parms: * dev The device structure containing * The io address and interrupt count * for this device. * phy The address of the PHY to be queried. * reg The register whose contents are to be * retreived. * val A pointer to a variable to store the * retrieved value. * * This function uses the TLAN's MII bus to retreive the contents * of a given register on a PHY. It sends the appropriate info * and then reads the 16-bit register value from the MII bus via * the TLAN SIO register. * **************************************************************/int TLan_MiiReadReg(struct nic *nic __unused, u16 phy, u16 reg, u16 * val){ u8 nack; u16 sio, tmp; u32 i; int err; int minten; err = FALSE; outw(TLAN_NET_SIO, BASE + TLAN_DIO_ADR); sio = BASE + TLAN_DIO_DATA + TLAN_NET_SIO; TLan_MiiSync(BASE); minten = TLan_GetBit(TLAN_NET_SIO_MINTEN, sio); if (minten) TLan_ClearBit(TLAN_NET_SIO_MINTEN, sio); TLan_MiiSendData(BASE, 0x1, 2); /* Start ( 01b ) */ TLan_MiiSendData(BASE, 0x2, 2); /* Read ( 10b ) */ TLan_MiiSendData(BASE, phy, 5); /* Device # */ TLan_MiiSendData(BASE, reg, 5); /* Register # */ TLan_ClearBit(TLAN_NET_SIO_MTXEN, sio); /* Change direction */ TLan_ClearBit(TLAN_NET_SIO_MCLK, sio); /* Clock Idle bit */ TLan_SetBit(TLAN_NET_SIO_MCLK, sio); TLan_ClearBit(TLAN_NET_SIO_MCLK, sio); /* Wait 300ns */ nack = TLan_GetBit(TLAN_NET_SIO_MDATA, sio); /* Check for ACK */ TLan_SetBit(TLAN_NET_SIO_MCLK, sio); /* Finish ACK */ if (nack) { /* No ACK, so fake it */ for (i = 0; i < 16; i++) { TLan_ClearBit(TLAN_NET_SIO_MCLK, sio); TLan_SetBit(TLAN_NET_SIO_MCLK, sio); } tmp = 0xffff; err = TRUE; } else { /* ACK, so read data */ for (tmp = 0, i = 0x8000; i; i >>= 1) { TLan_ClearBit(TLAN_NET_SIO_MCLK, sio); if (TLan_GetBit(TLAN_NET_SIO_MDATA, sio)) tmp |= i; TLan_SetBit(TLAN_NET_SIO_MCLK, sio); } } TLan_ClearBit(TLAN_NET_SIO_MCLK, sio); /* Idle cycle */ TLan_SetBit(TLAN_NET_SIO_MCLK, sio); if (minten) TLan_SetBit(TLAN_NET_SIO_MINTEN, sio); *val = tmp; return err;} /* TLan_MiiReadReg */ /*************************************************************** * TLan_MiiSendData * * Returns: * Nothing * Parms: * base_port The base IO port of the adapter in * question. * dev The address of the PHY to be queried. * data The value to be placed on the MII bus. * num_bits The number of bits in data that are to * be placed on the MII bus. * * This function sends on sequence of bits on the MII * configuration bus. * **************************************************************/void TLan_MiiSendData(u16 base_port, u32 data, unsigned num_bits){ u16 sio; u32 i; if (num_bits == 0) return; outw(TLAN_NET_SIO, base_port + TLAN_DIO_ADR); sio = base_port + TLAN_DIO_DATA + TLAN_NET_SIO; TLan_SetBit(TLAN_NET_SIO_MTXEN, sio); for (i = (0x1 << (num_bits - 1)); i; i >>= 1) { TLan_ClearBit(TLAN_NET_SIO_MCLK, sio); (void) TLan_GetBit(TLAN_NET_SIO_MCLK, sio); if (data & i) TLan_SetBit(TLAN_NET_SIO_MDATA, sio); else TLan_ClearBit(TLAN_NET_SIO_MDATA, sio); TLan_SetBit(TLAN_NET_SIO_MCLK, sio); (void) TLan_GetBit(TLAN_NET_SIO_MCLK, sio); }} /* TLan_MiiSendData */ /*************************************************************** * TLan_MiiSync * * Returns: * Nothing * Parms: * base_port The base IO port of the adapter in * question. * * This functions syncs all PHYs in terms of the MII configuration * bus. * **************************************************************/void TLan_MiiSync(u16 base_port){ int i; u16 sio; outw(TLAN_NET_SIO, base_port + TLAN_DIO_ADR); sio = base_port + TLAN_DIO_DATA + TLAN_NET_SIO; TLan_ClearBit(TLAN_NET_SIO_MTXEN, sio); for (i = 0; i < 32; i++) { TLan_ClearBit(TLAN_NET_SIO_MCLK, sio); TLan_SetBit(TLAN_NET_SIO_MCLK, sio); }} /* TLan_MiiSync */ /*************************************************************** * TLan_MiiWriteReg * * Returns: * Nothing * Parms: * dev The device structure for the device * to write to. * phy The address of the PHY to be written to. * reg The register whose contents are to be * written. * val The value to be written to the register. * * This function uses the TLAN's MII bus to write the contents of a * given register on a PHY. It sends the appropriate info and then * writes the 16-bit register value from the MII configuration bus * via the TLAN SIO register. * **************************************************************/void TLan_MiiWriteReg(struct nic *nic __unused, u16 phy, u16 reg, u16 val){ u16 sio; int minten; outw(TLAN_NET_SIO, BASE + TLAN_DIO_ADR); sio = BASE + TLAN_DIO_DATA + TLAN_NET_SIO; TLan_MiiSync(BASE); minten = TLan_GetBit(TLAN_NET_SIO_MINTEN, sio); if (minten) TLan_ClearBit(TLAN_NET_SIO_MINTEN, sio); TLan_MiiSendData(BASE, 0x1, 2); /* Start ( 01b ) */ TLan_MiiSendData(BASE, 0x1, 2); /* Write ( 01b ) */ TLan_MiiSendData(BASE, phy, 5); /* Device # */ TLan_MiiSendData(BASE, reg, 5); /* Register # */ TLan_MiiSendData(BASE, 0x2, 2); /* Send ACK */ TLan_MiiSendData(BASE, val, 16); /* Send Data */ TLan_ClearBit(TLAN_NET_SIO_MCLK, sio); /* Idle cycle */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -