00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 FILE_LICENCE ( GPL2_OR_LATER );
00047
00048
00049 #include "etherboot.h"
00050
00051 #include "nic.h"
00052 #include <gpxe/isapnp.h>
00053 #include <gpxe/isa.h>
00054 #include <gpxe/ethernet.h>
00055
00056 static void t3c515_wait(unsigned int nticks)
00057 {
00058 unsigned int to = currticks() + nticks;
00059 while (currticks() < to)
00060 ;
00061 }
00062
00063
00064 #define HZ 100
00065 static int if_port;
00066 static struct corkscrew_private *vp;
00067
00068 #define CORKSCREW 1
00069
00070
00071
00072
00073
00074
00075 #define AUTOMEDIA 1
00076
00077
00078
00079
00080
00081 #define VORTEX_BUS_MASTER
00082
00083
00084
00085 #define TX_RING_SIZE 16
00086 #define RX_RING_SIZE 16
00087 #define PKT_BUF_SZ 1536
00088
00089
00090
00091 #define DRIVER_DEBUG 1
00092
00093
00094
00095
00096
00097 #define CORKSCREW_ID 10
00098
00099 #define EL3WINDOW(win_num) \
00100 outw(SelectWindow + (win_num), nic->ioaddr + EL3_CMD)
00101 #define EL3_CMD 0x0e
00102 #define EL3_STATUS 0x0e
00103 #define RX_BYTES_MASK (unsigned short) (0x07ff)
00104
00105 enum corkscrew_cmd {
00106 TotalReset = 0 << 11, SelectWindow = 1 << 11, StartCoax = 2 << 11,
00107 RxDisable = 3 << 11, RxEnable = 4 << 11, RxReset = 5 << 11,
00108 UpStall = 6 << 11, UpUnstall = (6 << 11) + 1,
00109 DownStall = (6 << 11) + 2, DownUnstall = (6 << 11) + 3,
00110 RxDiscard = 8 << 11, TxEnable = 9 << 11, TxDisable =
00111 10 << 11, TxReset = 11 << 11,
00112 FakeIntr = 12 << 11, AckIntr = 13 << 11, SetIntrEnb = 14 << 11,
00113 SetStatusEnb = 15 << 11, SetRxFilter = 16 << 11, SetRxThreshold =
00114 17 << 11,
00115 SetTxThreshold = 18 << 11, SetTxStart = 19 << 11,
00116 StartDMAUp = 20 << 11, StartDMADown = (20 << 11) + 1, StatsEnable =
00117 21 << 11,
00118 StatsDisable = 22 << 11, StopCoax = 23 << 11,
00119 };
00120
00121
00122 enum RxFilter {
00123 RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8
00124 };
00125
00126
00127 enum corkscrew_status {
00128 IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004,
00129 TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020,
00130 IntReq = 0x0040, StatsFull = 0x0080,
00131 DMADone = 1 << 8, DownComplete = 1 << 9, UpComplete = 1 << 10,
00132 DMAInProgress = 1 << 11,
00133 CmdInProgress = 1 << 12,
00134 };
00135
00136
00137
00138 enum Window1 {
00139 TX_FIFO = 0x10, RX_FIFO = 0x10, RxErrors = 0x14,
00140 RxStatus = 0x18, Timer = 0x1A, TxStatus = 0x1B,
00141 TxFree = 0x1C,
00142 };
00143 enum Window0 {
00144 Wn0IRQ = 0x08,
00145 #if defined(CORKSCREW)
00146 Wn0EepromCmd = 0x200A,
00147 Wn0EepromData = 0x200C,
00148 #else
00149 Wn0EepromCmd = 10,
00150 Wn0EepromData = 12,
00151 #endif
00152 };
00153 enum Win0_EEPROM_bits {
00154 EEPROM_Read = 0x80, EEPROM_WRITE = 0x40, EEPROM_ERASE = 0xC0,
00155 EEPROM_EWENB = 0x30,
00156 EEPROM_EWDIS = 0x00,
00157 };
00158
00159 enum Window3 {
00160 Wn3_Config = 0, Wn3_MAC_Ctrl = 6, Wn3_Options = 8,
00161 };
00162 union wn3_config {
00163 int i;
00164 struct w3_config_fields {
00165 unsigned int ram_size:3, ram_width:1, ram_speed:2,
00166 rom_size:2;
00167 int pad8:8;
00168 unsigned int ram_split:2, pad18:2, xcvr:3, pad21:1,
00169 autoselect:1;
00170 int pad24:7;
00171 } u;
00172 };
00173
00174 enum Window4 {
00175 Wn4_NetDiag = 6, Wn4_Media = 10,
00176 };
00177 enum Win4_Media_bits {
00178 Media_SQE = 0x0008,
00179 Media_10TP = 0x00C0,
00180 Media_Lnk = 0x0080,
00181 Media_LnkBeat = 0x0800,
00182 };
00183 enum Window7 {
00184 Wn7_MasterAddr = 0, Wn7_MasterLen = 6, Wn7_MasterStatus = 12,
00185 };
00186
00187
00188 enum MasterCtrl {
00189 PktStatus = 0x400, DownListPtr = 0x404, FragAddr = 0x408, FragLen =
00190 0x40c,
00191 TxFreeThreshold = 0x40f, UpPktStatus = 0x410, UpListPtr = 0x418,
00192 };
00193
00194
00195
00196
00197 struct boom_rx_desc {
00198 u32 next;
00199 s32 status;
00200 u32 addr;
00201 s32 length;
00202 };
00203
00204
00205 enum rx_desc_status {
00206 RxDComplete = 0x00008000, RxDError = 0x4000,
00207
00208 };
00209
00210 struct boom_tx_desc {
00211 u32 next;
00212 s32 status;
00213 u32 addr;
00214 s32 length;
00215 };
00216
00217 struct corkscrew_private {
00218 const char *product_name;
00219 struct net_device *next_module;
00220
00221 struct boom_rx_desc rx_ring[RX_RING_SIZE];
00222 struct boom_tx_desc tx_ring[TX_RING_SIZE];
00223
00224 struct sk_buff *rx_skbuff[RX_RING_SIZE];
00225 struct sk_buff *tx_skbuff[TX_RING_SIZE];
00226 unsigned int cur_rx, cur_tx;
00227 unsigned int dirty_rx, dirty_tx;
00228 struct sk_buff *tx_skb;
00229 int capabilities;
00230 int options;
00231 int last_rx_packets;
00232 unsigned int available_media:8,
00233 media_override:3,
00234 default_media:3,
00235 full_duplex:1, autoselect:1, bus_master:1,
00236 full_bus_master_tx:1, full_bus_master_rx:1,
00237 tx_full:1;
00238 };
00239
00240
00241
00242
00243 enum xcvr_types {
00244 XCVR_10baseT =
00245 0, XCVR_AUI, XCVR_10baseTOnly, XCVR_10base2, XCVR_100baseTx,
00246 XCVR_100baseFx, XCVR_MII = 6, XCVR_Default = 8,
00247 };
00248
00249 static struct media_table {
00250 char *name;
00251 unsigned int media_bits:16,
00252 mask:8,
00253 next:8;
00254 short wait;
00255 } media_tbl[] = {
00256 {
00257 "10baseT", Media_10TP, 0x08, XCVR_10base2, (14 * HZ) / 10}
00258 , {
00259 "10Mbs AUI", Media_SQE, 0x20, XCVR_Default, (1 * HZ) / 10}
00260 , {
00261 "undefined", 0, 0x80, XCVR_10baseT, 10000}
00262 , {
00263 "10base2", 0, 0x10, XCVR_AUI, (1 * HZ) / 10}
00264 , {
00265 "100baseTX", Media_Lnk, 0x02, XCVR_100baseFx,
00266 (14 * HZ) / 10}
00267 , {
00268 "100baseFX", Media_Lnk, 0x04, XCVR_MII, (14 * HZ) / 10}
00269 , {
00270 "MII", 0, 0x40, XCVR_10baseT, 3 * HZ}
00271 , {
00272 "undefined", 0, 0x01, XCVR_10baseT, 10000}
00273 , {
00274 "Default", 0, 0xFF, XCVR_10baseT, 10000}
00275 ,};
00276
00277
00278 static int corkscrew_found_device(int ioaddr, int irq, int product_index,
00279 int options, struct nic *nic);
00280 static int corkscrew_probe1(int ioaddr, int irq, int product_index,
00281 struct nic *nic);
00282
00283
00284
00285 static int options = -1;
00286
00287
00288
00289
00290
00291
00292 static void t515_reset(struct nic *nic)
00293 {
00294 union wn3_config config;
00295 int i;
00296
00297
00298 EL3WINDOW(3);
00299 if (vp->full_duplex)
00300 outb(0x20, nic->ioaddr + Wn3_MAC_Ctrl);
00301 config.i = inl(nic->ioaddr + Wn3_Config);
00302
00303 if (vp->media_override != 7) {
00304 DBG ( "Media override to transceiver %d (%s).\n",
00305 vp->media_override,
00306 media_tbl[vp->media_override].name);
00307 if_port = vp->media_override;
00308 } else if (vp->autoselect) {
00309
00310 if_port = 4;
00311 while (!(vp->available_media & media_tbl[if_port].mask))
00312 if_port = media_tbl[if_port].next;
00313
00314 DBG ( "Initial media type %s.\n",
00315 media_tbl[if_port].name);
00316 } else
00317 if_port = vp->default_media;
00318
00319 config.u.xcvr = if_port;
00320 outl(config.i, nic->ioaddr + Wn3_Config);
00321
00322 DBG ( "corkscrew_open() InternalConfig 0x%hX.\n",
00323 config.i);
00324
00325 outw(TxReset, nic->ioaddr + EL3_CMD);
00326 for (i = 20; i >= 0; i--)
00327 if (!(inw(nic->ioaddr + EL3_STATUS) & CmdInProgress))
00328 break;
00329
00330 outw(RxReset, nic->ioaddr + EL3_CMD);
00331
00332 for (i = 20; i >= 0; i--)
00333 if (!(inw(nic->ioaddr + EL3_STATUS) & CmdInProgress))
00334 break;
00335
00336 outw(SetStatusEnb | 0x00, nic->ioaddr + EL3_CMD);
00337
00338 #ifdef debug_3c515
00339 EL3WINDOW(4);
00340 DBG ( "FIXME: fix print for irq, not 9" );
00341 DBG ( "corkscrew_open() irq %d media status 0x%hX.\n",
00342 9, inw(nic->ioaddr + Wn4_Media) );
00343 #endif
00344
00345
00346 EL3WINDOW(2);
00347 for (i = 0; i < 6; i++)
00348 outb(nic->node_addr[i], nic->ioaddr + i);
00349 for (; i < 12; i += 2)
00350 outw(0, nic->ioaddr + i);
00351
00352 if (if_port == 3)
00353
00354 outw(StartCoax, nic->ioaddr + EL3_CMD);
00355 EL3WINDOW(4);
00356 outw((inw(nic->ioaddr + Wn4_Media) & ~(Media_10TP | Media_SQE)) |
00357 media_tbl[if_port].media_bits, nic->ioaddr + Wn4_Media);
00358
00359
00360
00361 EL3WINDOW(6);
00362 for (i = 0; i < 10; i++)
00363 inb(nic->ioaddr + i);
00364 inw(nic->ioaddr + 10);
00365 inw(nic->ioaddr + 12);
00366
00367 EL3WINDOW(4);
00368 inb(nic->ioaddr + 12);
00369
00370 outw(0x0040, nic->ioaddr + Wn4_NetDiag);
00371
00372
00373 EL3WINDOW(7);
00374
00375
00376
00377
00378 if (vp->full_bus_master_rx) {
00379 printf("FIXME: Is this if necessary");
00380 vp->cur_rx = vp->dirty_rx = 0;
00381 DBG ( " Filling in the Rx ring.\n" );
00382 for (i = 0; i < RX_RING_SIZE; i++) {
00383 printf("FIXME: Is this if necessary");
00384 }
00385 }
00386 if (vp->full_bus_master_tx) {
00387 vp->cur_tx = vp->dirty_tx = 0;
00388 outb(PKT_BUF_SZ >> 8, nic->ioaddr + TxFreeThreshold);
00389
00390 for (i = 0; i < TX_RING_SIZE; i++)
00391 vp->tx_skbuff[i] = 0;
00392 outl(0, nic->ioaddr + DownListPtr);
00393 }
00394
00395 outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm,
00396 nic->ioaddr + EL3_CMD);
00397
00398 outw(RxEnable, nic->ioaddr + EL3_CMD);
00399 outw(TxEnable, nic->ioaddr + EL3_CMD);
00400
00401 outw(SetStatusEnb | AdapterFailure | IntReq | StatsFull |
00402 (vp->full_bus_master_tx ? DownComplete : TxAvailable) |
00403 (vp->full_bus_master_rx ? UpComplete : RxComplete) |
00404 (vp->bus_master ? DMADone : 0), nic->ioaddr + EL3_CMD);
00405
00406 outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
00407 nic->ioaddr + EL3_CMD);
00408 outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull
00409 | (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete,
00410 nic->ioaddr + EL3_CMD);
00411
00412 }
00413
00414
00415
00416
00417 static int t515_poll(struct nic *nic, int retrieve)
00418 {
00419 short status, cst;
00420 register short rx_fifo;
00421
00422 cst = inw(nic->ioaddr + EL3_STATUS);
00423
00424 if ((cst & RxComplete) == 0) {
00425
00426 outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
00427 nic->ioaddr + EL3_CMD);
00428 outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete |
00429 StatsFull | (vp->
00430 bus_master ? DMADone : 0) | UpComplete |
00431 DownComplete, nic->ioaddr + EL3_CMD);
00432 return 0;
00433 }
00434 status = inw(nic->ioaddr + RxStatus);
00435
00436 if (status & RxDError) {
00437 printf("RxDError\n");
00438 outw(RxDiscard, nic->ioaddr + EL3_CMD);
00439 return 0;
00440 }
00441
00442 rx_fifo = status & RX_BYTES_MASK;
00443 if (rx_fifo == 0)
00444 return 0;
00445
00446 if ( ! retrieve ) return 1;
00447
00448 DBG ( "[l=%d", rx_fifo );
00449 insw(nic->ioaddr + RX_FIFO, nic->packet, rx_fifo / 2);
00450 if (rx_fifo & 1)
00451 nic->packet[rx_fifo - 1] = inb(nic->ioaddr + RX_FIFO);
00452 nic->packetlen = rx_fifo;
00453
00454 while (1) {
00455 status = inw(nic->ioaddr + RxStatus);
00456 DBG ( "0x%hX*", status );
00457 rx_fifo = status & RX_BYTES_MASK;
00458
00459 if (rx_fifo > 0) {
00460 insw(nic->ioaddr + RX_FIFO, nic->packet + nic->packetlen,
00461 rx_fifo / 2);
00462 if (rx_fifo & 1)
00463 nic->packet[nic->packetlen + rx_fifo - 1] =
00464 inb(nic->ioaddr + RX_FIFO);
00465 nic->packetlen += rx_fifo;
00466 DBG ( "+%d", rx_fifo );
00467 }
00468 if ((status & RxComplete) == 0) {
00469 DBG ( "=%d", nic->packetlen );
00470 break;
00471 }
00472 udelay(1000);
00473 }
00474
00475
00476 outw(RxDiscard, nic->ioaddr + EL3_CMD);
00477 while (inw(nic->ioaddr + EL3_STATUS) & CmdInProgress);
00478 #ifdef debug_3c515
00479 {
00480 unsigned short type = 0;
00481 type = (nic->packet[12] << 8) | nic->packet[13];
00482 if (nic->packet[0] + nic->packet[1] + nic->packet[2] +
00483 nic->packet[3] + nic->packet[4] + nic->packet[5] ==
00484 0xFF * ETH_ALEN)
00485 DBG ( ",t=0x%hX,b]", type );
00486 else
00487 DBG ( ",t=0x%hX]", type );
00488 }
00489 #endif
00490
00491 return 1;
00492 }
00493
00494
00495
00496
00497 static char padmap[] = {
00498 0, 3, 2, 1
00499 };
00500
00501
00502
00503 static void t515_transmit(struct nic *nic, const char *d,
00504 unsigned int t,
00505 unsigned int s,
00506 const char *p)
00507 {
00508 register int len;
00509 int pad;
00510 int status;
00511
00512 DBG ( "{l=%d,t=0x%hX}", s + ETH_HLEN, t );
00513
00514
00515 t = htons(t);
00516
00517 len = s + ETH_HLEN;
00518 pad = padmap[len & 3];
00519
00520
00521
00522
00523
00524
00525
00526 if (len + pad > ETH_FRAME_LEN) {
00527 return;
00528 }
00529
00530 while ((status = inb(nic->ioaddr + TxStatus)) & TxComplete) {
00531
00532 outw(TxReset, nic->ioaddr + EL3_CMD);
00533 outw(TxEnable, nic->ioaddr + EL3_CMD);
00534
00535
00536 outb(0x0, nic->ioaddr + TxStatus);
00537 }
00538
00539 while (inw(nic->ioaddr + TxFree) < len + pad + 4) {
00540
00541 }
00542
00543 outw(len, nic->ioaddr + TX_FIFO);
00544 outw(0x0, nic->ioaddr + TX_FIFO);
00545
00546
00547 outsw(nic->ioaddr + TX_FIFO, d, ETH_ALEN / 2);
00548 outsw(nic->ioaddr + TX_FIFO, nic->node_addr, ETH_ALEN / 2);
00549 outw(t, nic->ioaddr + TX_FIFO);
00550 outsw(nic->ioaddr + TX_FIFO, p, s / 2);
00551
00552 if (s & 1)
00553 outb(*(p + s - 1), nic->ioaddr + TX_FIFO);
00554
00555 while (pad--)
00556 outb(0, nic->ioaddr + TX_FIFO);
00557
00558
00559 while ((inw(nic->ioaddr + EL3_STATUS) & CmdInProgress) != 0);
00560 }
00561
00562
00563
00564
00565 static void t515_disable ( struct nic *nic,
00566 struct isapnp_device *isapnp ) {
00567
00568 t515_reset(nic);
00569
00570
00571
00572
00573
00574
00575 outw(RxDisable, nic->ioaddr + EL3_CMD);
00576 outw(TxDisable, nic->ioaddr + EL3_CMD);
00577
00578 if (if_port == XCVR_10base2)
00579
00580 outw(StopCoax, nic->ioaddr + EL3_CMD);
00581
00582
00583 outw(SetIntrEnb | 0x0000, nic->ioaddr + EL3_CMD);
00584
00585 deactivate_isapnp_device ( isapnp );
00586 return;
00587 }
00588
00589 static void t515_irq(struct nic *nic __unused, irq_action_t action __unused)
00590 {
00591 switch ( action ) {
00592 case DISABLE :
00593 break;
00594 case ENABLE :
00595 break;
00596 case FORCE :
00597 break;
00598 }
00599 }
00600
00601 static struct nic_operations t515_operations = {
00602 .connect = dummy_connect,
00603 .poll = t515_poll,
00604 .transmit = t515_transmit,
00605 .irq = t515_irq,
00606
00607 };
00608
00609
00610
00611
00612
00613 static int t515_probe ( struct nic *nic, struct isapnp_device *isapnp ) {
00614
00615
00616
00617 nic->ioaddr = isapnp->ioaddr;
00618 nic->irqno = isapnp->irqno;
00619 activate_isapnp_device ( isapnp );
00620
00621
00622 if ((unsigned)(inw(nic->ioaddr + 0x2002) & 0x1f0)
00623 != (nic->ioaddr & 0x1f0)) {
00624 DBG ( "3c515 ioaddr mismatch\n" );
00625 return 0;
00626 }
00627
00628
00629 {
00630 int timer;
00631 outw(EEPROM_Read + 7, nic->ioaddr + Wn0EepromCmd);
00632
00633 for (timer = 4; timer >= 0; timer--) {
00634 t3c515_wait(1);
00635 if ((inw(nic->ioaddr + Wn0EepromCmd) & 0x0200) == 0)
00636 break;
00637 }
00638 if (inw(nic->ioaddr + Wn0EepromData) != 0x6d50) {
00639 DBG ( "3c515 read incorrect vendor ID from EEPROM" );
00640 return 0;
00641 }
00642
00643 }
00644 DBG ( "3c515 Resource configuration register 0x%X, DCR 0x%hX.\n",
00645 inl(nic->ioaddr + 0x2002), inw(nic->ioaddr + 0x2000) );
00646 corkscrew_found_device(nic->ioaddr, nic->irqno, CORKSCREW_ID,
00647 options, nic);
00648
00649 t515_reset(nic);
00650 nic->nic_op = &t515_operations;
00651 return 1;
00652 }
00653
00654 static int
00655 corkscrew_found_device(int ioaddr, int irq,
00656 int product_index, int options, struct nic *nic)
00657 {
00658
00659 vp->product_name = "3c515";
00660 vp->options = options;
00661 if (options >= 0) {
00662 vp->media_override =
00663 ((options & 7) == 2) ? 0 : options & 7;
00664 vp->full_duplex = (options & 8) ? 1 : 0;
00665 vp->bus_master = (options & 16) ? 1 : 0;
00666 } else {
00667 vp->media_override = 7;
00668 vp->full_duplex = 0;
00669 vp->bus_master = 0;
00670 }
00671
00672 corkscrew_probe1(ioaddr, irq, product_index, nic);
00673 return 0;
00674 }
00675
00676 static int
00677 corkscrew_probe1(int ioaddr, int irq, int product_index __unused,
00678 struct nic *nic)
00679 {
00680 unsigned int eeprom[0x40], checksum = 0;
00681 int i;
00682
00683 printf("3Com %s at 0x%hX, ", vp->product_name, ioaddr);
00684
00685
00686 EL3WINDOW(0);
00687 for (i = 0; i < 0x18; i++) {
00688 short *phys_addr = (short *) nic->node_addr;
00689 int timer;
00690 outw(EEPROM_Read + i, ioaddr + Wn0EepromCmd);
00691
00692 for (timer = 4; timer >= 0; timer--) {
00693 t3c515_wait(1);
00694 if ((inw(ioaddr + Wn0EepromCmd) & 0x0200) == 0)
00695 break;
00696 }
00697 eeprom[i] = inw(ioaddr + Wn0EepromData);
00698 DBG ( "Value %d: %hX ", i, eeprom[i] );
00699 checksum ^= eeprom[i];
00700 if (i < 3)
00701 phys_addr[i] = htons(eeprom[i]);
00702 }
00703 checksum = (checksum ^ (checksum >> 8)) & 0xff;
00704 if (checksum != 0x00)
00705 printf(" ***INVALID CHECKSUM 0x%hX*** ", checksum);
00706
00707 DBG ( "%s", eth_ntoa ( nic->node_addr ) );
00708
00709 if (eeprom[16] == 0x11c7) {
00710
00711 }
00712 printf(", IRQ %d\n", irq);
00713
00714 if ( (irq <= 0 || irq > 15) ) {
00715 DBG (" *** Warning: this IRQ is unlikely to work! ***\n" );
00716 }
00717
00718 {
00719 char *ram_split[] = { "5:3", "3:1", "1:1", "3:5" };
00720 union wn3_config config;
00721 EL3WINDOW(3);
00722 vp->available_media = inw(ioaddr + Wn3_Options);
00723 config.i = inl(ioaddr + Wn3_Config);
00724 DBG ( " Internal config register is %4.4x, "
00725 "transceivers 0x%hX.\n",
00726 config.i, inw(ioaddr + Wn3_Options) );
00727 printf
00728 (" %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n",
00729 8 << config.u.ram_size,
00730 config.u.ram_width ? "word" : "byte",
00731 ram_split[config.u.ram_split],
00732 config.u.autoselect ? "autoselect/" : "",
00733 media_tbl[config.u.xcvr].name);
00734 if_port = config.u.xcvr;
00735 vp->default_media = config.u.xcvr;
00736 vp->autoselect = config.u.autoselect;
00737 }
00738 if (vp->media_override != 7) {
00739 printf(" Media override to transceiver type %d (%s).\n",
00740 vp->media_override,
00741 media_tbl[vp->media_override].name);
00742 if_port = vp->media_override;
00743 }
00744
00745 vp->capabilities = eeprom[16];
00746 vp->full_bus_master_tx = (vp->capabilities & 0x20) ? 1 : 0;
00747
00748
00749 vp->full_bus_master_rx = (vp->capabilities & 0x20) ? 1 : 0;
00750
00751 return 0;
00752 }
00753
00754 static struct isapnp_device_id t515_adapters[] = {
00755 { "3c515 (ISAPnP)", ISAPNP_VENDOR('T','C','M'), 0x5051 },
00756 };
00757
00758 ISAPNP_DRIVER ( t515_driver, t515_adapters );
00759
00760 DRIVER ( "3c515", nic_driver, isapnp_driver, t515_driver,
00761 t515_probe, t515_disable );
00762
00763 ISA_ROM ( "3c515", "3c515 Fast EtherLink ISAPnP" );