/******************************************************************************* * * Linux ThunderLAN Driver * * tlan.c * by James Banks * * (C) 1997-1998 Caldera, Inc. * (C) 1998 James Banks * (C) 1999-2001 Torben Mathiasen * (C) 2002 Samuel Chessman * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. * ** Useful (if not required) reading: * * Texas Instruments, ThunderLAN Programmer's Guide, * TI Literature Number SPWU013A * available in PDF format from www.ti.com * Level One, LXT901 and LXT970 Data Sheets * available in PDF format from www.level1.com * National Semiconductor, DP83840A Data Sheet * available in PDF format from www.national.com * Microchip Technology, 24C01A/02A/04A Data Sheet * available in PDF format from www.microchip.com *
******************************************************************************/
/*************************************************************** * tlan_remove_one * * Returns: * Nothing * Parms: * None * * Goes through the TLanDevices list and frees the device * structs and memory associated with each device (lists * and buffers). It also ureserves the IO port regions * associated with this device. *
**************************************************************/
staticvoid tlan_start(struct net_device *dev)
{
tlan_reset_lists(dev); /* NOTE: It might not be necessary to read the stats before a reset if you don't care what the values are.
*/
tlan_read_and_clear_stats(dev, TLAN_IGNORE);
tlan_reset_adapter(dev);
netif_wake_queue(dev);
}
/* *************************************************************** * tlan_probe1 * * Returns: * 0 on success, error code on error * Parms: * none * * The name is lower case to fit in with all the rest of * the netcard_probe names. This function looks for * another TLan based adapter, setting it up with the * allocated device struct if one is found. * tlan_probe has been ported to the new net API and * now allocates its own device structure. This function * is also used by modules. *
**************************************************************/
staticint tlan_probe1(struct pci_dev *pdev, long ioaddr, int irq, int rev, conststruct pci_device_id *ent)
{
/* This will be used when we get an adapter error from
* within our irq handler */
INIT_WORK(&priv->tlan_tqueue, tlan_tx_timeout_work);
spin_lock_init(&priv->lock);
rc = tlan_init(dev); if (rc) {
pr_err("Could not set up device\n"); goto err_out_free_dev;
}
rc = register_netdev(dev); if (rc) {
pr_err("Could not register device\n"); goto err_out_uninit;
}
tlan_devices_installed++;
boards_found++;
/* pdev is NULL if this is an EISA device */ if (pdev)
tlan_have_pci++; else {
priv->next_device = tlan_eisa_devices;
tlan_eisa_devices = dev;
tlan_have_eisa++;
}
/************************************************************** * tlan_eisa_probe * * Returns: 0 on success, 1 otherwise * * Parms: None * * * This functions probes for EISA devices and calls * TLan_probe1 when one is found. *
*************************************************************/
staticvoid __init tlan_eisa_probe(void)
{ long ioaddr; int irq;
u16 device_id;
if (!EISA_bus) {
TLAN_DBG(TLAN_DEBUG_PROBE, "No EISA bus present\n"); return;
}
/* Loop through all slots of the EISA bus */ for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) {
/*************************************************************** * tlan_init * * Returns: * 0 on success, error code otherwise. * Parms: * dev The structure of the device to be * init'ed. * * This function completes the initialization of the * device structure and driver. It reserves the IO * addresses, allocates memory for the lists and bounce * buffers, retrieves the MAC address from the eeprom * and assignes the device's methods. *
**************************************************************/
staticint tlan_init(struct net_device *dev)
{ int dma_size; int err; int i; struct tlan_priv *priv;
u8 addr[ETH_ALEN];
/*************************************************************** * tlan_open * * Returns: * 0 on success, error code otherwise. * Parms: * dev Structure of device to be opened. * * This routine puts the driver and TLAN adapter in a * state where it is ready to send and receive packets. * It allocates the IRQ, resets and brings the adapter * out of reset, and allows interrupts. It also delays * the startup for autonegotiation or sends a Rx GO * command to the adapter, as appropriate. *
**************************************************************/
/*************************************************************** * tlan_tx_timeout * * Returns: nothing * * Params: * dev structure of device which timed out * during transmit. *
**************************************************************/
/* Ok so we timed out, lets see what we can do about it...*/
tlan_free_lists(dev);
tlan_reset_lists(dev);
tlan_read_and_clear_stats(dev, TLAN_IGNORE);
tlan_reset_adapter(dev);
netif_trans_update(dev); /* prevent tx timeout */
netif_wake_queue(dev);
}
/*************************************************************** * tlan_tx_timeout_work * * Returns: nothing * * Params: * work work item of device which timed out *
**************************************************************/
/*************************************************************** * tlan_start_tx * * Returns: * 0 on success, non-zero on failure. * Parms: * skb A pointer to the sk_buff containing the * frame to be sent. * dev The device to send the data on. * * This function adds a frame to the Tx list to be sent * ASAP. First it verifies that the adapter is ready and * there is room in the queue. Then it sets up the next * available list, copies the frame to the corresponding * buffer. If the adapter Tx channel is idle, it gives * the adapter a Tx Go command on the list, otherwise it * sets the forward address of the previous list to point * to this one. Then it frees the sk_buff. *
**************************************************************/
/*************************************************************** * tlan_handle_interrupt * * Returns: * Nothing * Parms: * irq The line on which the interrupt * occurred. * dev_id A pointer to the device assigned to * this irq line. * * This function handles an interrupt generated by its * assigned TLAN adapter. The function deactivates * interrupts on its adapter, records the type of * interrupt, executes the appropriate subhandler, and * acknowdges the interrupt to the adapter (thus * re-enabling adapter interrupts. *
**************************************************************/
/*************************************************************** * tlan_close * * Returns: * An error code. * Parms: * dev The device structure of the device to * close. * * This function shuts down the adapter. It records any * stats, puts the adapter into reset state, deactivates * its time as needed, and frees the irq it is using. *
**************************************************************/
/*************************************************************** * tlan_get_stats * * Returns: * A pointer to the device's statistics structure. * Parms: * dev The device structure to return the * stats for. * * This function updates the devices statistics by reading * the TLAN chip's onboard registers. Then it returns the * address of the statistics structure. *
**************************************************************/
/* Should only read stats if open ? */
tlan_read_and_clear_stats(dev, TLAN_RECORD);
TLAN_DBG(TLAN_DEBUG_RX, "RECEIVE: %s EOC count = %d\n", dev->name,
priv->rx_eoc_count);
TLAN_DBG(TLAN_DEBUG_TX, "TRANSMIT: %s Busy count = %d\n", dev->name,
priv->tx_busy_count); if (debug & TLAN_DEBUG_GNRL) {
tlan_print_dio(dev->base_addr);
tlan_phy_print(dev);
} if (debug & TLAN_DEBUG_LIST) { for (i = 0; i < TLAN_NUM_RX_LISTS; i++)
tlan_print_list(priv->rx_list + i, "RX", i); for (i = 0; i < TLAN_NUM_TX_LISTS; i++)
tlan_print_list(priv->tx_list + i, "TX", i);
}
return &dev->stats;
}
/*************************************************************** * tlan_set_multicast_list * * Returns: * Nothing * Parms: * dev The device structure to set the * multicast list for. * * This function sets the TLAN adaptor to various receive * modes. If the IFF_PROMISC flag is set, promiscuous * mode is acitviated. Otherwise, promiscuous mode is * turned off. If the IFF_ALLMULTI flag is set, then * the hash table is set to receive all group addresses. * Otherwise, the first three multicast addresses are * stored in AREG_1-3, and the rest are selected via the * hash table, as necessary. *
**************************************************************/
please see chap. 4, "Interrupt Handling" of the "ThunderLAN Programmer's Guide" for more informations on handling interrupts generated by TLAN based adapters.
/*************************************************************** * tlan_handle_tx_eof * * Returns: * 1 * Parms: * dev Device assigned the IRQ that was * raised. * host_int The contents of the HOST_INT * port. * * This function handles Tx EOF interrupts which are raised * by the adapter when it has completed sending the * contents of a buffer. If detemines which list/buffer * was completed and resets it. If the buffer was the last * in the channel (EOC), then the function checks to see if * another buffer is ready to send, and if so, sends a Tx * Go command. Finally, the driver activates/continues the * activity LED. *
**************************************************************/
/*************************************************************** * TLan_HandleStatOverflow * * Returns: * 1 * Parms: * dev Device assigned the IRQ that was * raised. * host_int The contents of the HOST_INT * port. * * This function handles the Statistics Overflow interrupt * which means that one or more of the TLAN statistics * registers has reached 1/2 capacity and needs to be read. *
**************************************************************/
/*************************************************************** * TLan_HandleRxEOF * * Returns: * 1 * Parms: * dev Device assigned the IRQ that was * raised. * host_int The contents of the HOST_INT * port. * * This function handles the Rx EOF interrupt which * indicates a frame has been received by the adapter from * the net and the frame has been transferred to memory. * The function determines the bounce buffer the frame has * been loaded into, creates a new sk_buff big enough to * hold the frame, and sends it to protocol stack. It * then resets the used buffer and appends it to the end * of the list. If the frame was the last in the Rx * channel (EOC), the function restarts the receive channel * by sending an Rx Go command to the adapter. Then it * activates/continues the activity LED. *
**************************************************************/
/*************************************************************** * tlan_handle_dummy * * Returns: * 1 * Parms: * dev Device assigned the IRQ that was * raised. * host_int The contents of the HOST_INT * port. * * This function handles the Dummy interrupt, which is * raised whenever a test interrupt is generated by setting * the Req_Int bit of HOST_CMD to 1. *
**************************************************************/
/*************************************************************** * tlan_handle_tx_eoc * * Returns: * 1 * Parms: * dev Device assigned the IRQ that was * raised. * host_int The contents of the HOST_INT * port. * * This driver is structured to determine EOC occurrences by * reading the CSTAT member of the list structure. Tx EOC * interrupts are disabled via the DIO INTDIS register. * However, TLAN chips before revision 3.0 didn't have this * functionality, so process EOC events if this is the * case. *
**************************************************************/
/*************************************************************** * tlan_handle_status_check * * Returns: * 0 if Adapter check, 1 if Network Status check. * Parms: * dev Device assigned the IRQ that was * raised. * host_int The contents of the HOST_INT * port. * * This function handles Adapter Check/Network Status * interrupts generated by the adapter. It checks the * vector in the HOST_INT register to determine if it is * an Adapter Check interrupt. If so, it resets the * adapter. Otherwise it clears the status registers * and services the PHY. *
**************************************************************/
/*************************************************************** * tlan_handle_rx_eoc * * Returns: * 1 * Parms: * dev Device assigned the IRQ that was * raised. * host_int The contents of the HOST_INT * port. * * This driver is structured to determine EOC occurrences by * reading the CSTAT member of the list structure. Rx EOC * interrupts are disabled via the DIO INTDIS register. * However, TLAN chips before revision 3.0 didn't have this * CSTAT member or a INTDIS register, so if this chip is * pre-3.0, process EOC interrupts normally. *
**************************************************************/
/*************************************************************** * tlan_timer * * Returns: * Nothing * Parms: * data A value given to add timer when * add_timer was called. * * This function handles timed functionality for the * TLAN driver. The two current timer uses are for * delaying for autonegotionation and driving the ACT LED. * - Autonegotiation requires being allowed about * 2 1/2 seconds before attempting to transmit a * packet. It would be a very bad thing to hang * the kernel this long, so the driver doesn't * allow transmission 'til after this time, for * certain PHYs. It would be much nicer if all * PHYs were interrupt-capable like the internal * PHY. * - The ACT LED, which shows adapter activity, is * driven by the driver, and so must be left on * for a short period to power up the LED so it * can be seen. This delay can be changed by * changing the TLAN_TIMER_ACT_DELAY in tlan.h, * if desired. 100 ms produces a slightly * sluggish response. *
**************************************************************/
/*************************************************************** * tlan_reset_lists * * Returns: * Nothing * Parms: * dev The device structure with the list * structures to be reset. * * This routine sets the variables associated with managing * the TLAN lists to their initial values. *
**************************************************************/
for (i = 0; i < TLAN_NUM_TX_LISTS; i++) {
list = priv->tx_list + i;
skb = tlan_get_skb(list); if (skb) {
dma_unmap_single(&priv->pci_dev->dev,
list->buffer[0].address,
max(skb->len, (unsignedint)TLAN_MIN_FRAME_SIZE),
DMA_TO_DEVICE);
dev_kfree_skb_any(skb);
list->buffer[8].address = 0;
list->buffer[9].address = 0;
}
}
for (i = 0; i < TLAN_NUM_RX_LISTS; i++) {
list = priv->rx_list + i;
skb = tlan_get_skb(list); if (skb) {
dma_unmap_single(&priv->pci_dev->dev,
list->buffer[0].address,
TLAN_MAX_FRAME_SIZE, DMA_FROM_DEVICE);
dev_kfree_skb_any(skb);
list->buffer[8].address = 0;
list->buffer[9].address = 0;
}
}
}
/*************************************************************** * tlan_print_dio * * Returns: * Nothing * Parms: * io_base Base IO port of the device of * which to print DIO registers. * * This function prints out all the internal (DIO) * registers of a TLAN chip. *
**************************************************************/
staticvoid tlan_print_dio(u16 io_base)
{
u32 data0, data1; int i;
pr_info("Contents of internal registers for io base 0x%04hx\n",
io_base);
pr_info("Off. +0 +4\n"); for (i = 0; i < 0x4C; i += 8) {
data0 = tlan_dio_read32(io_base, i);
data1 = tlan_dio_read32(io_base, i + 0x4);
pr_info("0x%02x 0x%08x 0x%08x\n", i, data0, data1);
}
}
/*************************************************************** * TLan_PrintList * * Returns: * Nothing * Parms: * list A pointer to the struct tlan_list structure to * be printed. * type A string to designate type of list, * "Rx" or "Tx". * num The index of the list. * * This function prints out the contents of the list * pointed to by the list parameter. *
**************************************************************/
staticvoid tlan_print_list(struct tlan_list *list, char *type, int num)
{ int i;
pr_info("%s List %d at %p\n", type, num, list);
pr_info(" Forward = 0x%08x\n", list->forward);
pr_info(" CSTAT = 0x%04hx\n", list->c_stat);
pr_info(" Frame Size = 0x%04hx\n", list->frame_size); /* for (i = 0; i < 10; i++) { */ for (i = 0; i < 2; i++) {
pr_info(" Buffer[%d].count, addr = 0x%08x, 0x%08x\n",
i, list->buffer[i].count, list->buffer[i].address);
}
}
/*************************************************************** * tlan_read_and_clear_stats * * Returns: * Nothing * Parms: * dev Pointer to device structure of adapter * to which to read stats. * record Flag indicating whether to add * * This functions reads all the internal status registers * of the TLAN chip, which clears them as a side effect. * It then either adds the values to the device's status * struct, or discards them, depending on whether record * is TLAN_RECORD (!=0) or TLAN_IGNORE (==0). *
**************************************************************/
/*************************************************************** * TLan_Reset * * Returns: * 0 * Parms: * dev Pointer to device structure of adapter * to be reset. * * This function resets the adapter and it's physical * device. See Chap. 3, pp. 9-10 of the "ThunderLAN * Programmer's Guide" for details. The routine tries to * implement what is detailed there, though adjustments * have been made. *
**************************************************************/
/* don't power down internal PHY if we're going to use it */ if (priv->phy_num == 0 ||
(priv->adapter->flags & TLAN_ADAPTER_USE_INTERN_10))
data |= TLAN_NET_CFG_PHY_EN;
tlan_dio_write16(dev->base_addr, TLAN_NET_CONFIG, (u16) data);
if (priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY)
tlan_finish_reset(dev); else
tlan_phy_power_down(dev);
/*************************************************************** * tlan_set_mac * * Returns: * Nothing * Parms: * dev Pointer to device structure of adapter * on which to change the AREG. * areg The AREG to set the address in (0 - 3). * mac A pointer to an array of chars. Each * element stores one byte of the address. * IE, it isn't in ascii. * * This function transfers a MAC address to one of the * TLAN AREGs (address registers). The TLAN chip locks * the register on writing to offset 0 and unlocks the * register after writing to offset 5. If NULL is passed * in mac, then the AREG is filled with 0's. *
**************************************************************/
staticvoid tlan_set_mac(struct net_device *dev, int areg, constchar *mac)
{ int i;
areg *= 6;
if (mac != NULL) { for (i = 0; i < 6; i++)
tlan_dio_write8(dev->base_addr,
TLAN_AREG_0 + areg + i, mac[i]);
} else { for (i = 0; i < 6; i++)
tlan_dio_write8(dev->base_addr,
TLAN_AREG_0 + areg + i, 0);
}
/********************************************************************* * __tlan_phy_print * * Returns: * Nothing * Parms: * dev A pointer to the device structure of the * TLAN device having the PHYs to be detailed. * * This function prints the registers a PHY (aka transceiver). *
********************************************************************/
/********************************************************************* * tlan_phy_detect * * Returns: * Nothing * Parms: * dev A pointer to the device structure of the adapter
--> --------------------
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.