iPXE
Data Structures | Functions | Variables
3c509.c File Reference
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ipxe/io.h>
#include <unistd.h>
#include <ipxe/device.h>
#include <ipxe/isa.h>
#include "3c509.h"

Go to the source code of this file.

Data Structures

struct  t509_device
 A 3c509 device. More...

Functions

 FILE_LICENCE (BSD2)
static void t509bus_remove (struct root_device *rootdev)
 Remove 3c509 root bus.
static void t509_set_drvdata (struct t509_device *t509, void *priv)
 Set 3c509 driver-private data.
static void * t509_get_drvdata (struct t509_device *t509)
 Get 3c509 driver-private data.
static void t509_set_id_port (void)
static void t509_wait_for_id_sequence (void)
static void t509_global_reset (void)
static void t509_reset_tag (void)
static void t509_set_tag (uint8_t tag)
static void t509_select_tag (uint8_t tag)
static void t509_activate (uint16_t ioaddr)
static void t509_deactivate_and_reset_tag (uint16_t ioaddr)
static void t509_load_eeprom_word (uint8_t offset)
static int t509_find_id_port (void)
static void t509_send_id_sequence (void)
static uint16_t t509_id_read_eeprom (int offset)
static int t509_isolate (void)
static void activate_t509_device (struct t509_device *t509)
static void deactivate_t509_device (struct t509_device *t509)
static int legacy_t509_probe (struct nic *nic, void *hwdev)
static void legacy_t509_disable (struct nic *nic, void *hwdev)
static void legacy_t509_set_drvdata (void *hwdev, void *priv)
static void * legacy_t509_get_drvdata (void *hwdev)
static int t509_probe (struct t509_device *t509)
 Probe a 3c509 device.
static void t509_remove (struct t509_device *t509)
 Remove a 3c509 device.
static int t509bus_probe (struct root_device *rootdev)
 Probe 3c509 root bus.
 ISA_ROM ("3c509","3c509")

Variables

static unsigned int t509_id_port = 0
static unsigned int t509_max_tag = 0
static struct root_driver t509_root_driver
 3c509 bus root device driver
struct root_device t509_root_device __root_device
 3c509 bus root device

Function Documentation

FILE_LICENCE ( BSD2  )
static void t509bus_remove ( struct root_device rootdev) [static]

Remove 3c509 root bus.

Parameters:
rootdev3c509 bus root device

Definition at line 408 of file 3c509.c.

References device::children, t509_device::dev, root_device::dev, free, list_del, list_for_each_entry_safe, device::siblings, and t509_remove().

Referenced by t509bus_probe().

                                                           {
        struct t509_device *t509;
        struct t509_device *tmp;

        list_for_each_entry_safe ( t509, tmp, &rootdev->dev.children,
                                   dev.siblings ) {
                t509_remove ( t509 );
                list_del ( &t509->dev.siblings );
                free ( t509 );
        }
}
static void t509_set_drvdata ( struct t509_device t509,
void *  priv 
) [inline, static]

Set 3c509 driver-private data.

Parameters:
t5093c509 device
privPrivate data

Definition at line 61 of file 3c509.c.

References t509_device::priv, and priv.

Referenced by legacy_t509_set_drvdata().

                                                                             {
        t509->priv = priv;
}
static void* t509_get_drvdata ( struct t509_device t509) [inline, static]

Get 3c509 driver-private data.

Parameters:
t5093c509 device
Return values:
privPrivate data

Definition at line 71 of file 3c509.c.

References t509_device::priv.

Referenced by legacy_t509_get_drvdata().

                                                                   {
        return t509->priv;
}
static void t509_set_id_port ( void  ) [inline, static]

Definition at line 80 of file 3c509.c.

References outb(), and t509_id_port.

Referenced by t509_find_id_port(), and t509_send_id_sequence().

                                             {
        outb ( 0x00, t509_id_port );
}
static void t509_wait_for_id_sequence ( void  ) [inline, static]

Definition at line 84 of file 3c509.c.

References outb(), and t509_id_port.

Referenced by deactivate_t509_device(), t509_isolate(), t509_send_id_sequence(), and t509bus_probe().

                                                      {
        outb ( 0x00, t509_id_port );
}
static void t509_global_reset ( void  ) [inline, static]

Definition at line 88 of file 3c509.c.

References outb(), and t509_id_port.

                                              {
        outb ( 0xc0, t509_id_port );
}
static void t509_reset_tag ( void  ) [inline, static]

Definition at line 92 of file 3c509.c.

References outb(), and t509_id_port.

Referenced by t509_isolate().

                                           {
        outb ( 0xd0, t509_id_port );
}
static void t509_set_tag ( uint8_t  tag) [inline, static]

Definition at line 96 of file 3c509.c.

References outb(), and t509_id_port.

Referenced by deactivate_t509_device(), and t509_isolate().

                                                {
        outb ( 0xd0 | tag, t509_id_port );
}
static void t509_select_tag ( uint8_t  tag) [inline, static]

Definition at line 100 of file 3c509.c.

References outb(), and t509_id_port.

Referenced by activate_t509_device(), deactivate_t509_device(), t509_isolate(), and t509bus_probe().

                                                   {
        outb ( 0xd8 | tag, t509_id_port );
}
static void t509_activate ( uint16_t  ioaddr) [inline, static]

Definition at line 104 of file 3c509.c.

References outb(), and t509_id_port.

Referenced by activate_t509_device().

                                                     {
        outb ( 0xe0 | ( ioaddr >> 4 ), t509_id_port );
}
static void t509_deactivate_and_reset_tag ( uint16_t  ioaddr) [inline, static]

Definition at line 108 of file 3c509.c.

References EP_COMMAND, GLOBAL_RESET, and outb().

Referenced by deactivate_t509_device().

static void t509_load_eeprom_word ( uint8_t  offset) [inline, static]

Definition at line 112 of file 3c509.c.

References outb(), and t509_id_port.

Referenced by t509_id_read_eeprom().

                                                            {
        outb ( 0x80 | offset, t509_id_port );
}
static int t509_find_id_port ( void  ) [inline, static]

Definition at line 120 of file 3c509.c.

References DBG, ENOENT, EP_ID_PORT_END, EP_ID_PORT_INC, EP_ID_PORT_START, inb(), outb(), t509_id_port, and t509_set_id_port().

Referenced by t509_isolate().

                                             {

        for ( t509_id_port = EP_ID_PORT_START ;
              t509_id_port < EP_ID_PORT_END ;
              t509_id_port += EP_ID_PORT_INC ) {
                t509_set_id_port ();
                /* See if anything's listening */
                outb ( 0xff, t509_id_port );
                if ( inb ( t509_id_port ) & 0x01 ) {
                        /* Found a suitable port */
                        DBG ( "T509 using ID port at %04x\n", t509_id_port );
                        return 0;
                }
        }
        /* No id port available */
        DBG ( "T509 found no available ID port\n" );
        return -ENOENT;
}
static void t509_send_id_sequence ( void  ) [static]

Definition at line 143 of file 3c509.c.

References outb(), t509_id_port, t509_set_id_port(), and t509_wait_for_id_sequence().

Referenced by activate_t509_device(), deactivate_t509_device(), t509_isolate(), and t509bus_probe().

                                           {
        unsigned short lrs_state, i;

        t509_set_id_port ();
        /* Reset IDS on cards */
        t509_wait_for_id_sequence ();
        lrs_state = 0xff;
        for ( i = 0; i < 255; i++ ) {
                outb ( lrs_state, t509_id_port );
                lrs_state <<= 1;
                lrs_state = lrs_state & 0x100 ? lrs_state ^ 0xcf : lrs_state;
        }
}
static uint16_t t509_id_read_eeprom ( int  offset) [static]

Definition at line 169 of file 3c509.c.

References data, inw(), t509_id_port, t509_load_eeprom_word(), and udelay().

Referenced by t509_isolate(), and t509bus_probe().

                                                   {
        int i, data = 0;

        t509_load_eeprom_word ( offset );
        /* Do we really need this wait? Won't be noticeable anyway */
        udelay(10000);

        for ( i = 0; i < 16; i++ ) {
                data = ( data << 1 ) | ( inw ( t509_id_port ) & 1 );
        }
        return data;
}
static int t509_isolate ( void  ) [static]

Definition at line 186 of file 3c509.c.

References DBG, EEPROM_MFG_ID, MFG_ID, rc, t509_find_id_port(), t509_id_port, t509_id_read_eeprom(), t509_max_tag, t509_reset_tag(), t509_select_tag(), t509_send_id_sequence(), t509_set_tag(), and t509_wait_for_id_sequence().

Referenced by t509bus_probe().

                                 {
        unsigned int i;
        uint16_t contend[3];
        int rc;

        /* Find a suitable ID port */
        if ( ( rc = t509_find_id_port() ) != 0 )
                return rc;

        while ( 1 ) {

                /* All cards are in ID_WAIT state each time we go
                 * through this loop.
                 */

                /* Send the ID sequence */
                t509_send_id_sequence();

                /* First time through, reset all tags.  On subsequent
                 * iterations, kill off any already-tagged cards
                 */
                if ( t509_max_tag == 0 ) {
                        t509_reset_tag();
                } else {
                        t509_select_tag ( 0 );
                }
        
                /* Read the manufacturer ID, to see if there are any
                 * more cards
                 */
                if ( t509_id_read_eeprom ( EEPROM_MFG_ID ) != MFG_ID ) {
                        DBG ( "T509 saw %s signs of life\n",
                              t509_max_tag ? "no further" : "no" );
                        break;
                }

                /* Perform contention selection on the MAC address */
                for ( i = 0 ; i < 3 ; i++ ) {
                        contend[i] = t509_id_read_eeprom ( i );
                }

                /* Only one device will still be left alive.  Tag it. */
                ++t509_max_tag;
                DBG ( "T509 found card %04x%04x%04x, assigning tag %02x\n",
                      contend[0], contend[1], contend[2], t509_max_tag );
                t509_set_tag ( t509_max_tag );

                /* Return all cards back to ID_WAIT state */
                t509_wait_for_id_sequence();
        }

        DBG ( "T509 found %d cards using ID port %04x\n",
              t509_max_tag, t509_id_port );
        return 0;
}
static void activate_t509_device ( struct t509_device t509) [inline, static]

Definition at line 250 of file 3c509.c.

References DBG, t509_device::ioaddr, t509_activate(), t509_select_tag(), t509_send_id_sequence(), and t509_device::tag.

Referenced by legacy_t509_probe().

                                                                     {
        t509_send_id_sequence ();
        t509_select_tag ( t509->tag );
        t509_activate ( t509->ioaddr );
        DBG ( "T509 activated device %02x at ioaddr %04x\n",
              t509->tag, t509->ioaddr );
}
static void deactivate_t509_device ( struct t509_device t509) [inline, static]

Definition at line 265 of file 3c509.c.

References DBG, t509_device::ioaddr, t509_deactivate_and_reset_tag(), t509_select_tag(), t509_send_id_sequence(), t509_set_tag(), t509_wait_for_id_sequence(), t509_device::tag, and udelay().

Referenced by legacy_t509_disable().

                                                                       {
        t509_deactivate_and_reset_tag ( t509->ioaddr );
        udelay ( 1000 );
        t509_send_id_sequence ();
        t509_select_tag ( 0 );
        t509_set_tag ( t509->tag );
        t509_wait_for_id_sequence ();
        DBG ( "T509 deactivated device at %04x and re-tagged as %02x\n",
              t509->ioaddr, t509->tag );
}
static int legacy_t509_probe ( struct nic nic,
void *  hwdev 
) [static]

Definition at line 280 of file 3c509.c.

References activate_t509_device(), t509_device::ioaddr, ISA_PROD_ID, ISA_PROD_ID_MASK, PROD_ID, and t5x9_probe().

Referenced by t509_probe().

                                                              {
        struct t509_device *t509 = hwdev;

        /* We could change t509->ioaddr if we wanted to */
        activate_t509_device ( t509 );
        nic->ioaddr = t509->ioaddr;

        /* Hand off to generic t5x9 probe routine */
        return t5x9_probe ( nic, ISA_PROD_ID ( PROD_ID ), ISA_PROD_ID_MASK );
}
static void legacy_t509_disable ( struct nic nic,
void *  hwdev 
) [static]

Definition at line 291 of file 3c509.c.

References deactivate_t509_device(), and t5x9_disable().

Referenced by t509_probe(), and t509_remove().

                                                                 {
        struct t509_device *t509 = hwdev;

        t5x9_disable ( nic );
        deactivate_t509_device ( t509 );
}
static void legacy_t509_set_drvdata ( void *  hwdev,
void *  priv 
) [inline, static]

Definition at line 298 of file 3c509.c.

References t509_set_drvdata().

Referenced by t509_probe().

                                                                       {
        t509_set_drvdata ( hwdev, priv );
}
static void* legacy_t509_get_drvdata ( void *  hwdev) [inline, static]

Definition at line 302 of file 3c509.c.

References t509_get_drvdata().

Referenced by t509_remove().

                                                             {
        return t509_get_drvdata ( hwdev );
}
static int t509_probe ( struct t509_device t509) [static]

Probe a 3c509 device.

Parameters:
t5093c509 device
Return values:
rcReturn status code

Searches for a driver for the 3c509 device. If a driver is found, its probe() routine is called.

Definition at line 315 of file 3c509.c.

References DBG, t509_device::dev, t509_device::ioaddr, legacy_probe(), legacy_t509_disable(), legacy_t509_probe(), legacy_t509_set_drvdata(), and t509_device::tag.

Referenced by t509bus_probe().

                                                   {
        DBG ( "Adding 3c509 device %02x (I/O %04x)\n",
              t509->tag, t509->ioaddr );
        return legacy_probe ( t509, legacy_t509_set_drvdata, &t509->dev,
                              legacy_t509_probe, legacy_t509_disable );
}
static void t509_remove ( struct t509_device t509) [static]

Remove a 3c509 device.

Parameters:
t5093c509 device

Definition at line 327 of file 3c509.c.

References DBG, legacy_remove(), legacy_t509_disable(), legacy_t509_get_drvdata(), and t509_device::tag.

Referenced by t509bus_remove().

                                                     {
        legacy_remove ( t509, legacy_t509_get_drvdata, legacy_t509_disable );
        DBG ( "Removed 3c509 device %02x\n", t509->tag );
}
static int t509bus_probe ( struct root_device rootdev) [static]

Probe 3c509 root bus.

Parameters:
rootdev3c509 bus root device

Scans the 3c509 bus for devices and registers all devices it can find.

Definition at line 340 of file 3c509.c.

References device_description::bus_type, BUS_TYPE_ISA, device::children, device::desc, t509_device::dev, root_device::dev, device_description::device, EEPROM_ADDR_CFG, ENOMEM, free, INIT_LIST_HEAD, t509_device::ioaddr, list_add, list_del, malloc(), memset(), MFG_ID, device::name, NULL, device::parent, PROD_ID, rc, device::siblings, snprintf(), t509_id_read_eeprom(), t509_isolate(), t509_max_tag, t509_probe(), t509_select_tag(), t509_send_id_sequence(), t509_wait_for_id_sequence(), t509bus_remove(), t509_device::tag, tag, and device_description::vendor.

                                                         {
        struct t509_device *t509 = NULL;
        unsigned int tag;
        unsigned int iobase;
        int rc;

        /* Perform isolation and tagging */
        if ( ( rc = t509_isolate() ) != 0 )
                return rc;

        for ( tag = 1 ; tag <= t509_max_tag ; tag++ ) {
                /* Allocate struct t509_device */
                if ( ! t509 )
                        t509 = malloc ( sizeof ( *t509 ) );
                if ( ! t509 ) {
                        rc = -ENOMEM;
                        goto err;
                }
                memset ( t509, 0, sizeof ( *t509 ) );
                t509->tag = tag;

                /* Send the ID sequence */
                t509_send_id_sequence ();

                /* Select the specified tag */
                t509_select_tag ( t509->tag );

                /* Read the default I/O address */
                iobase = t509_id_read_eeprom ( EEPROM_ADDR_CFG );
                t509->ioaddr = 0x200 + ( ( iobase & 0x1f ) << 4 );

                /* Send card back to ID_WAIT */
                t509_wait_for_id_sequence();

                /* Add to device hierarchy */
                snprintf ( t509->dev.name, sizeof ( t509->dev.name ),
                           "t509%02x", tag );
                t509->dev.desc.bus_type = BUS_TYPE_ISA;
                t509->dev.desc.vendor = MFG_ID;
                t509->dev.desc.device = PROD_ID;
                t509->dev.parent = &rootdev->dev;
                list_add ( &t509->dev.siblings, &rootdev->dev.children );
                INIT_LIST_HEAD ( &t509->dev.children );
                        
                /* Look for a driver */
                if ( t509_probe ( t509 ) == 0 ) {
                        /* t509dev registered, we can drop our ref */
                        t509 = NULL;
                } else {
                        /* Not registered; re-use struct */
                        list_del ( &t509->dev.siblings );
                }
        }

        free ( t509 );
        return 0;

 err:
        free ( t509 );
        t509bus_remove ( rootdev );
        return rc;
}
ISA_ROM ( "3c509"  ,
"3c509"   
)

Variable Documentation

unsigned int t509_id_port = 0 [static]
unsigned int t509_max_tag = 0 [static]

Definition at line 37 of file 3c509.c.

Referenced by t509_isolate(), and t509bus_probe().

struct root_driver t509_root_driver [static]
Initial value:
 {
        .probe = t509bus_probe,
        .remove = t509bus_remove,
}

3c509 bus root device driver

Definition at line 421 of file 3c509.c.

struct root_device t509_root_device __root_device
Initial value:
 {
        .dev = { .name = "3c509" },
        .driver = &t509_root_driver,
}

3c509 bus root device

Definition at line 427 of file 3c509.c.