3c509.c File Reference

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <gpxe/io.h>
#include <unistd.h>
#include <gpxe/device.h>
#include <gpxe/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:
rootdev 3c509 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().

00408                                                            {
00409         struct t509_device *t509;
00410         struct t509_device *tmp;
00411 
00412         list_for_each_entry_safe ( t509, tmp, &rootdev->dev.children,
00413                                    dev.siblings ) {
00414                 t509_remove ( t509 );
00415                 list_del ( &t509->dev.siblings );
00416                 free ( t509 );
00417         }
00418 }

static void t509_set_drvdata ( struct t509_device t509,
void *  priv 
) [inline, static]

Set 3c509 driver-private data.

Parameters:
t509 3c509 device
priv Private data

Definition at line 61 of file 3c509.c.

References t509_device::priv.

Referenced by legacy_t509_set_drvdata().

00061                                                                              {
00062         t509->priv = priv;
00063 }

static void* t509_get_drvdata ( struct t509_device t509  )  [inline, static]

Get 3c509 driver-private data.

Parameters:
t509 3c509 device
Return values:
priv Private data

Definition at line 71 of file 3c509.c.

References t509_device::priv.

Referenced by legacy_t509_get_drvdata().

00071                                                                    {
00072         return t509->priv;
00073 }

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().

00080                                              {
00081         outb ( 0x00, t509_id_port );
00082 }

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().

00084                                                       {
00085         outb ( 0x00, t509_id_port );
00086 }

static void t509_global_reset ( void   )  [inline, static]

Definition at line 88 of file 3c509.c.

References outb, and t509_id_port.

00088                                               {
00089         outb ( 0xc0, t509_id_port );
00090 }

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().

00092                                            {
00093         outb ( 0xd0, t509_id_port );
00094 }

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().

00096                                                 {
00097         outb ( 0xd0 | tag, t509_id_port );
00098 }

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().

00100                                                    {
00101         outb ( 0xd8 | tag, t509_id_port );
00102 }

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().

00104                                                      {
00105         outb ( 0xe0 | ( ioaddr >> 4 ), t509_id_port );
00106 }

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().

00108                                                                      {
00109         outb ( GLOBAL_RESET, ioaddr + EP_COMMAND );
00110 }

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().

00112                                                             {
00113         outb ( 0x80 | offset, t509_id_port );
00114 }

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().

00120                                              {
00121 
00122         for ( t509_id_port = EP_ID_PORT_START ;
00123               t509_id_port < EP_ID_PORT_END ;
00124               t509_id_port += EP_ID_PORT_INC ) {
00125                 t509_set_id_port ();
00126                 /* See if anything's listening */
00127                 outb ( 0xff, t509_id_port );
00128                 if ( inb ( t509_id_port ) & 0x01 ) {
00129                         /* Found a suitable port */
00130                         DBG ( "T509 using ID port at %04x\n", t509_id_port );
00131                         return 0;
00132                 }
00133         }
00134         /* No id port available */
00135         DBG ( "T509 found no available ID port\n" );
00136         return -ENOENT;
00137 }

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().

00143                                            {
00144         unsigned short lrs_state, i;
00145 
00146         t509_set_id_port ();
00147         /* Reset IDS on cards */
00148         t509_wait_for_id_sequence ();
00149         lrs_state = 0xff;
00150         for ( i = 0; i < 255; i++ ) {
00151                 outb ( lrs_state, t509_id_port );
00152                 lrs_state <<= 1;
00153                 lrs_state = lrs_state & 0x100 ? lrs_state ^ 0xcf : lrs_state;
00154         }
00155 }

static uint16_t t509_id_read_eeprom ( int  offset  )  [static]

Definition at line 169 of file 3c509.c.

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

Referenced by t509_isolate(), and t509bus_probe().

00169                                                    {
00170         int i, data = 0;
00171 
00172         t509_load_eeprom_word ( offset );
00173         /* Do we really need this wait? Won't be noticeable anyway */
00174         udelay(10000);
00175 
00176         for ( i = 0; i < 16; i++ ) {
00177                 data = ( data << 1 ) | ( inw ( t509_id_port ) & 1 );
00178         }
00179         return data;
00180 }

static int t509_isolate ( void   )  [static]

Definition at line 186 of file 3c509.c.

References DBG, EEPROM_MFG_ID, MFG_ID, 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().

00186                                  {
00187         unsigned int i;
00188         uint16_t contend[3];
00189         int rc;
00190 
00191         /* Find a suitable ID port */
00192         if ( ( rc = t509_find_id_port() ) != 0 )
00193                 return rc;
00194 
00195         while ( 1 ) {
00196 
00197                 /* All cards are in ID_WAIT state each time we go
00198                  * through this loop.
00199                  */
00200 
00201                 /* Send the ID sequence */
00202                 t509_send_id_sequence();
00203 
00204                 /* First time through, reset all tags.  On subsequent
00205                  * iterations, kill off any already-tagged cards
00206                  */
00207                 if ( t509_max_tag == 0 ) {
00208                         t509_reset_tag();
00209                 } else {
00210                         t509_select_tag ( 0 );
00211                 }
00212         
00213                 /* Read the manufacturer ID, to see if there are any
00214                  * more cards
00215                  */
00216                 if ( t509_id_read_eeprom ( EEPROM_MFG_ID ) != MFG_ID ) {
00217                         DBG ( "T509 saw %s signs of life\n",
00218                               t509_max_tag ? "no further" : "no" );
00219                         break;
00220                 }
00221 
00222                 /* Perform contention selection on the MAC address */
00223                 for ( i = 0 ; i < 3 ; i++ ) {
00224                         contend[i] = t509_id_read_eeprom ( i );
00225                 }
00226 
00227                 /* Only one device will still be left alive.  Tag it. */
00228                 ++t509_max_tag;
00229                 DBG ( "T509 found card %04x%04x%04x, assigning tag %02x\n",
00230                       contend[0], contend[1], contend[2], t509_max_tag );
00231                 t509_set_tag ( t509_max_tag );
00232 
00233                 /* Return all cards back to ID_WAIT state */
00234                 t509_wait_for_id_sequence();
00235         }
00236 
00237         DBG ( "T509 found %d cards using ID port %04x\n",
00238               t509_max_tag, t509_id_port );
00239         return 0;
00240 }

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().

00250                                                                      {
00251         t509_send_id_sequence ();
00252         t509_select_tag ( t509->tag );
00253         t509_activate ( t509->ioaddr );
00254         DBG ( "T509 activated device %02x at ioaddr %04x\n",
00255               t509->tag, t509->ioaddr );
00256 }

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().

00265                                                                        {
00266         t509_deactivate_and_reset_tag ( t509->ioaddr );
00267         udelay ( 1000 );
00268         t509_send_id_sequence ();
00269         t509_select_tag ( 0 );
00270         t509_set_tag ( t509->tag );
00271         t509_wait_for_id_sequence ();
00272         DBG ( "T509 deactivated device at %04x and re-tagged as %02x\n",
00273               t509->ioaddr, t509->tag );
00274 }

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, nic::ioaddr, ISA_PROD_ID, ISA_PROD_ID_MASK, PROD_ID, and t5x9_probe().

Referenced by t509_probe().

00280                                                               {
00281         struct t509_device *t509 = hwdev;
00282 
00283         /* We could change t509->ioaddr if we wanted to */
00284         activate_t509_device ( t509 );
00285         nic->ioaddr = t509->ioaddr;
00286 
00287         /* Hand off to generic t5x9 probe routine */
00288         return t5x9_probe ( nic, ISA_PROD_ID ( PROD_ID ), ISA_PROD_ID_MASK );
00289 }

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().

00291                                                                  {
00292         struct t509_device *t509 = hwdev;
00293 
00294         t5x9_disable ( nic );
00295         deactivate_t509_device ( t509 );
00296 }

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().

00298                                                                        {
00299         t509_set_drvdata ( hwdev, priv );
00300 }

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().

00302                                                              {
00303         return t509_get_drvdata ( hwdev );
00304 }

static int t509_probe ( struct t509_device t509  )  [static]

Probe a 3c509 device.

Parameters:
t509 3c509 device
Return values:
rc Return 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().

00315                                                    {
00316         DBG ( "Adding 3c509 device %02x (I/O %04x)\n",
00317               t509->tag, t509->ioaddr );
00318         return legacy_probe ( t509, legacy_t509_set_drvdata, &t509->dev,
00319                               legacy_t509_probe, legacy_t509_disable );
00320 }

static void t509_remove ( struct t509_device t509  )  [static]

Remove a 3c509 device.

Parameters:
t509 3c509 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().

00327                                                      {
00328         legacy_remove ( t509, legacy_t509_get_drvdata, legacy_t509_disable );
00329         DBG ( "Removed 3c509 device %02x\n", t509->tag );
00330 }

static int t509bus_probe ( struct root_device rootdev  )  [static]

Probe 3c509 root bus.

Parameters:
rootdev 3c509 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, root_device::dev, t509_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, 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, and device_description::vendor.

00340                                                          {
00341         struct t509_device *t509 = NULL;
00342         unsigned int tag;
00343         unsigned int iobase;
00344         int rc;
00345 
00346         /* Perform isolation and tagging */
00347         if ( ( rc = t509_isolate() ) != 0 )
00348                 return rc;
00349 
00350         for ( tag = 1 ; tag <= t509_max_tag ; tag++ ) {
00351                 /* Allocate struct t509_device */
00352                 if ( ! t509 )
00353                         t509 = malloc ( sizeof ( *t509 ) );
00354                 if ( ! t509 ) {
00355                         rc = -ENOMEM;
00356                         goto err;
00357                 }
00358                 memset ( t509, 0, sizeof ( *t509 ) );
00359                 t509->tag = tag;
00360 
00361                 /* Send the ID sequence */
00362                 t509_send_id_sequence ();
00363 
00364                 /* Select the specified tag */
00365                 t509_select_tag ( t509->tag );
00366 
00367                 /* Read the default I/O address */
00368                 iobase = t509_id_read_eeprom ( EEPROM_ADDR_CFG );
00369                 t509->ioaddr = 0x200 + ( ( iobase & 0x1f ) << 4 );
00370 
00371                 /* Send card back to ID_WAIT */
00372                 t509_wait_for_id_sequence();
00373 
00374                 /* Add to device hierarchy */
00375                 snprintf ( t509->dev.name, sizeof ( t509->dev.name ),
00376                            "t509%02x", tag );
00377                 t509->dev.desc.bus_type = BUS_TYPE_ISA;
00378                 t509->dev.desc.vendor = MFG_ID;
00379                 t509->dev.desc.device = PROD_ID;
00380                 t509->dev.parent = &rootdev->dev;
00381                 list_add ( &t509->dev.siblings, &rootdev->dev.children );
00382                 INIT_LIST_HEAD ( &t509->dev.children );
00383                         
00384                 /* Look for a driver */
00385                 if ( t509_probe ( t509 ) == 0 ) {
00386                         /* t509dev registered, we can drop our ref */
00387                         t509 = NULL;
00388                 } else {
00389                         /* Not registered; re-use struct */
00390                         list_del ( &t509->dev.siblings );
00391                 }
00392         }
00393 
00394         free ( t509 );
00395         return 0;
00396 
00397  err:
00398         free ( t509 );
00399         t509bus_remove ( rootdev );
00400         return rc;
00401 }

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.


Generated on Tue Apr 6 20:01:18 2010 for gPXE by  doxygen 1.5.7.1