#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 | |
| FILE_LICENCE | ( | BSD2 | ) |
| static void t509bus_remove | ( | struct root_device * | rootdev | ) | [static] |
Remove 3c509 root bus.
| 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.
| t509 | 3c509 device | |
| priv | Private data |
Definition at line 61 of file 3c509.c.
References t509_device::priv.
Referenced by legacy_t509_set_drvdata().
| static void* t509_get_drvdata | ( | struct t509_device * | t509 | ) | [inline, static] |
Get 3c509 driver-private data.
| t509 | 3c509 device |
| 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.
| t509 | 3c509 device |
| rc | Return status code |
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.
| 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.
| rootdev | 3c509 bus root device |
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" | ||||
| ) |
unsigned int t509_id_port = 0 [static] |
Definition at line 36 of file 3c509.c.
Referenced by t509_activate(), t509_find_id_port(), t509_global_reset(), t509_id_read_eeprom(), t509_isolate(), t509_load_eeprom_word(), t509_reset_tag(), t509_select_tag(), t509_send_id_sequence(), t509_set_id_port(), t509_set_tag(), and t509_wait_for_id_sequence().
unsigned int t509_max_tag = 0 [static] |
struct root_driver t509_root_driver [static] |
| struct root_device t509_root_device __root_device |
1.5.7.1