[9] | 1 | /*
|
---|
| 2 | ** File: 3c501.c Jan. 14, 1997
|
---|
| 3 | **
|
---|
| 4 | ** Author: Giovanni Falzoni <gfalzoni@inwind.it>
|
---|
| 5 | **
|
---|
| 6 | ** This file contains specific implementation of the ethernet
|
---|
| 7 | ** device driver for 3Com Etherlink (3c501) boards. This is a
|
---|
| 8 | ** very old board and its performances are very poor for today
|
---|
| 9 | ** network environments.
|
---|
| 10 | **
|
---|
| 11 | ** $Id: 3c501.c,v 1.3 2005/08/05 19:08:43 beng Exp $
|
---|
| 12 | */
|
---|
| 13 |
|
---|
| 14 | #include "drivers.h"
|
---|
| 15 | #include <minix/com.h>
|
---|
| 16 | #include <net/hton.h>
|
---|
| 17 | #include <net/gen/ether.h>
|
---|
| 18 | #include <net/gen/eth_io.h>
|
---|
| 19 | #include "dp.h"
|
---|
| 20 |
|
---|
| 21 | #if (ENABLE_3C501 == 1)
|
---|
| 22 |
|
---|
| 23 | #include "3c501.h"
|
---|
| 24 |
|
---|
| 25 | static unsigned char StationAddress[SA_ADDR_LEN] = {0, 0, 0, 0, 0, 0,};
|
---|
| 26 | static buff_t *TxBuff = NULL;
|
---|
| 27 |
|
---|
| 28 | /*
|
---|
| 29 | ** Name: void el1_getstats(dpeth_t *dep)
|
---|
| 30 | ** Function: Reads statistics counters from board.
|
---|
| 31 | **/
|
---|
| 32 | static void el1_getstats(dpeth_t * dep)
|
---|
| 33 | {
|
---|
| 34 |
|
---|
| 35 | return; /* Nothing to do */
|
---|
| 36 | }
|
---|
| 37 |
|
---|
| 38 | /*
|
---|
| 39 | ** Name: void el1_reset(dpeth_t *dep)
|
---|
| 40 | ** Function: Reset function specific for Etherlink hardware.
|
---|
| 41 | */
|
---|
| 42 | static void el1_reset(dpeth_t * dep)
|
---|
| 43 | {
|
---|
| 44 | int ix;
|
---|
| 45 |
|
---|
| 46 | for (ix = 0; ix < 8; ix += 1) /* Resets the board */
|
---|
| 47 | outb_el1(dep, EL1_CSR, ECSR_RESET);
|
---|
| 48 | outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_SYS);
|
---|
| 49 |
|
---|
| 50 | /* Set Ethernet Address on controller */
|
---|
| 51 | outb_el1(dep, EL1_CSR, ECSR_LOOP); /* Loopback mode */
|
---|
| 52 | for (ix = EL1_ADDRESS; ix < SA_ADDR_LEN; ix += 1)
|
---|
| 53 | outb_el1(dep, ix, StationAddress[ix]);
|
---|
| 54 |
|
---|
| 55 | lock();
|
---|
| 56 | /* Enable DMA/Interrupt, gain control of Buffer */
|
---|
| 57 | outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_SYS);
|
---|
| 58 | /* Clear RX packet area */
|
---|
| 59 | outw_el1(dep, EL1_RECVPTR, 0);
|
---|
| 60 | /* Enable transmit/receive configuration and flush pending interrupts */
|
---|
| 61 | outb_el1(dep, EL1_XMIT, EXSR_IDLE | EXSR_16JAM | EXSR_JAM | EXSR_UNDER);
|
---|
| 62 | outb_el1(dep, EL1_RECV, dep->de_recv_mode);
|
---|
| 63 | inb_el1(dep, EL1_RECV);
|
---|
| 64 | inb_el1(dep, EL1_XMIT);
|
---|
| 65 | dep->de_flags &= NOT(DEF_XMIT_BUSY);
|
---|
| 66 | unlock();
|
---|
| 67 | return; /* Done */
|
---|
| 68 | }
|
---|
| 69 |
|
---|
| 70 | /*
|
---|
| 71 | ** Name: void el1_dumpstats(dpeth_t *dep, int port, vir_bytes size)
|
---|
| 72 | ** Function: Dumps counter on screen (support for console display).
|
---|
| 73 | */
|
---|
| 74 | static void el1_dumpstats(dpeth_t * dep)
|
---|
| 75 | {
|
---|
| 76 |
|
---|
| 77 | return;
|
---|
| 78 | }
|
---|
| 79 |
|
---|
| 80 | /*
|
---|
| 81 | ** Name: void el1_mode_init(dpeth_t *dep)
|
---|
| 82 | ** Function: Initializes receicer mode
|
---|
| 83 | */
|
---|
| 84 | static void el1_mode_init(dpeth_t * dep)
|
---|
| 85 | {
|
---|
| 86 |
|
---|
| 87 | if (dep->de_flags & DEF_BROAD) {
|
---|
| 88 | dep->de_recv_mode = ERSR_BROAD | ERSR_RMASK;
|
---|
| 89 |
|
---|
| 90 | } else if (dep->de_flags & DEF_PROMISC) {
|
---|
| 91 | dep->de_recv_mode = ERSR_ALL | ERSR_RMASK;
|
---|
| 92 |
|
---|
| 93 | } else if (dep->de_flags & DEF_MULTI) {
|
---|
| 94 | dep->de_recv_mode = ERSR_MULTI | ERSR_RMASK;
|
---|
| 95 |
|
---|
| 96 | } else {
|
---|
| 97 | dep->de_recv_mode = ERSR_NONE | ERSR_RMASK;
|
---|
| 98 | }
|
---|
| 99 | outb_el1(dep, EL1_RECV, dep->de_recv_mode);
|
---|
| 100 | inb_el1(dep, EL1_RECV);
|
---|
| 101 | return;
|
---|
| 102 | }
|
---|
| 103 |
|
---|
| 104 | /*
|
---|
| 105 | ** Name: void el1_recv(dpeth_t *dep, int from, int size)
|
---|
| 106 | ** Function: Receive function. Called from interrupt handler to
|
---|
| 107 | ** unload recv. buffer or from main (packet to client)
|
---|
| 108 | */
|
---|
| 109 | static void el1_recv(dpeth_t * dep, int from, int size)
|
---|
| 110 | {
|
---|
| 111 | buff_t *rxptr;
|
---|
| 112 |
|
---|
| 113 | while ((dep->de_flags & DEF_READING) && (rxptr = dep->de_recvq_head)) {
|
---|
| 114 |
|
---|
| 115 | /* Remove buffer from queue and free buffer */
|
---|
| 116 | lock();
|
---|
| 117 | if (dep->de_recvq_tail == dep->de_recvq_head)
|
---|
| 118 | dep->de_recvq_head = dep->de_recvq_tail = NULL;
|
---|
| 119 | else
|
---|
| 120 | dep->de_recvq_head = rxptr->next;
|
---|
| 121 | unlock();
|
---|
| 122 |
|
---|
| 123 | /* Copy buffer to user area */
|
---|
| 124 | mem2user(dep, rxptr);
|
---|
| 125 |
|
---|
| 126 | /* Reply information */
|
---|
| 127 | dep->de_read_s = rxptr->size;
|
---|
| 128 | dep->de_flags |= DEF_ACK_RECV;
|
---|
| 129 | dep->de_flags &= NOT(DEF_READING);
|
---|
| 130 |
|
---|
| 131 | /* Return buffer to the idle pool */
|
---|
| 132 | free_buff(dep, rxptr);
|
---|
| 133 | }
|
---|
| 134 | return;
|
---|
| 135 | }
|
---|
| 136 |
|
---|
| 137 | /*
|
---|
| 138 | ** Name: void el1_send(dpeth_t *dep, int from_int, int pktsize)
|
---|
| 139 | ** Function: Send function. Called from main to transit a packet or
|
---|
| 140 | ** from interrupt handler when a new packet was queued.
|
---|
| 141 | */
|
---|
| 142 | static void el1_send(dpeth_t * dep, int from_int, int pktsize)
|
---|
| 143 | {
|
---|
| 144 | buff_t *txbuff;
|
---|
| 145 | clock_t now;
|
---|
| 146 |
|
---|
| 147 | if (from_int == FALSE) {
|
---|
| 148 |
|
---|
| 149 | if ((txbuff = alloc_buff(dep, pktsize + sizeof(buff_t))) != NULL) {
|
---|
| 150 |
|
---|
| 151 | /* Fill transmit buffer from user area */
|
---|
| 152 | txbuff->next = NULL;
|
---|
| 153 | txbuff->size = pktsize;
|
---|
| 154 | txbuff->client = dep->de_client;
|
---|
| 155 | user2mem(dep, txbuff);
|
---|
| 156 | } else
|
---|
| 157 | panic(dep->de_name, "out of memory for Tx", NO_NUM);
|
---|
| 158 |
|
---|
| 159 | } else if ((txbuff = dep->de_xmitq_head) != NULL) {
|
---|
| 160 |
|
---|
| 161 | /* Get first packet in queue */
|
---|
| 162 | lock();
|
---|
| 163 | if (dep->de_xmitq_tail == dep->de_xmitq_head)
|
---|
| 164 | dep->de_xmitq_head = dep->de_xmitq_tail = NULL;
|
---|
| 165 | else
|
---|
| 166 | dep->de_xmitq_head = txbuff->next;
|
---|
| 167 | unlock();
|
---|
| 168 | pktsize = txbuff->size;
|
---|
| 169 |
|
---|
| 170 | } else
|
---|
| 171 | panic(dep->de_name, "should not be sending ", NO_NUM);
|
---|
| 172 |
|
---|
| 173 | if ((dep->de_flags & DEF_XMIT_BUSY)) {
|
---|
| 174 | if (from_int) panic(dep->de_name, "should not be sending ", NO_NUM);
|
---|
| 175 | getuptime(&now);
|
---|
| 176 | if ((now - dep->de_xmit_start) > 4) {
|
---|
| 177 | /* Transmitter timed out */
|
---|
| 178 | DEBUG(printf("3c501: transmitter timed out ... \n"));
|
---|
| 179 | dep->de_stat.ets_sendErr += 1;
|
---|
| 180 | dep->de_flags &= NOT(DEF_XMIT_BUSY);
|
---|
| 181 | el1_reset(dep);
|
---|
| 182 | }
|
---|
| 183 |
|
---|
| 184 | /* Queue packet */
|
---|
| 185 | lock(); /* Queue packet to receive queue */
|
---|
| 186 | if (dep->de_xmitq_head == NULL)
|
---|
| 187 | dep->de_xmitq_head = txbuff;
|
---|
| 188 | else
|
---|
| 189 | dep->de_xmitq_tail->next = txbuff;
|
---|
| 190 | dep->de_xmitq_tail = txbuff;
|
---|
| 191 | unlock();
|
---|
| 192 | } else {
|
---|
| 193 | /* Save for retransmission */
|
---|
| 194 | TxBuff = txbuff;
|
---|
| 195 | dep->de_flags |= (DEF_XMIT_BUSY | DEF_ACK_SEND);
|
---|
| 196 |
|
---|
| 197 | /* Setup board for packet loading */
|
---|
| 198 | lock(); /* Buffer to processor */
|
---|
| 199 | outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_SYS);
|
---|
| 200 | inb_el1(dep, EL1_RECV); /* Clears any spurious interrupt */
|
---|
| 201 | inb_el1(dep, EL1_XMIT);
|
---|
| 202 | outw_el1(dep, EL1_RECVPTR, 0); /* Clears RX packet area */
|
---|
| 203 |
|
---|
| 204 | /* Loads packet */
|
---|
| 205 | outw_el1(dep, EL1_XMITPTR, (EL1_BFRSIZ - pktsize));
|
---|
| 206 | outsb(dep->de_data_port, SELF, txbuff->buffer, pktsize);
|
---|
| 207 | /* Starts transmitter */
|
---|
| 208 | outw_el1(dep, EL1_XMITPTR, (EL1_BFRSIZ - pktsize));
|
---|
| 209 | outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_XMIT); /* There it goes... */
|
---|
| 210 | unlock();
|
---|
| 211 |
|
---|
| 212 | getuptime(&dep->de_xmit_start);
|
---|
| 213 | dep->de_flags &= NOT(DEF_SENDING);
|
---|
| 214 | }
|
---|
| 215 | return;
|
---|
| 216 | }
|
---|
| 217 |
|
---|
| 218 | /*
|
---|
| 219 | ** Name: void el1_stop(dpeth_t *dep)
|
---|
| 220 | ** Function: Stops board and disable interrupts.
|
---|
| 221 | */
|
---|
| 222 | static void el1_stop(dpeth_t * dep)
|
---|
| 223 | {
|
---|
| 224 | int ix;
|
---|
| 225 |
|
---|
| 226 | DEBUG(printf("%s: stopping Etherlink ....\n", dep->de_name));
|
---|
| 227 | for (ix = 0; ix < 8; ix += 1) /* Reset board */
|
---|
| 228 | outb_el1(dep, EL1_CSR, ECSR_RESET);
|
---|
| 229 | outb_el1(dep, EL1_CSR, ECSR_SYS);
|
---|
| 230 | sys_irqdisable(&dep->de_hook); /* Disable interrupt */
|
---|
| 231 | return;
|
---|
| 232 | }
|
---|
| 233 |
|
---|
| 234 | /*
|
---|
| 235 | ** Name: void el1_interrupt(dpeth_t *dep)
|
---|
| 236 | ** Function: Interrupt handler. Acknwledges transmit interrupts
|
---|
| 237 | ** or unloads receive buffer to memory queue.
|
---|
| 238 | */
|
---|
| 239 | static void el1_interrupt(dpeth_t * dep)
|
---|
| 240 | {
|
---|
| 241 | u16_t csr, isr;
|
---|
| 242 | int pktsize;
|
---|
| 243 | buff_t *rxptr;
|
---|
| 244 |
|
---|
| 245 | csr = inb_el1(dep, EL1_CSR);
|
---|
| 246 | if ((csr & ECSR_XMIT) && (dep->de_flags & DEF_XMIT_BUSY)) {
|
---|
| 247 |
|
---|
| 248 | /* Got a transmit interrupt */
|
---|
| 249 | isr = inb_el1(dep, EL1_XMIT);
|
---|
| 250 | if ((isr & (EXSR_16JAM | EXSR_UNDER | EXSR_JAM)) || !(isr & EXSR_IDLE)) {
|
---|
| 251 | DEBUG(printf("3c501: got xmit interrupt (ASR=0x%02X XSR=0x%02X)\n", csr, isr));
|
---|
| 252 | if (isr & EXSR_JAM) {
|
---|
| 253 | /* Sending, packet got a collision */
|
---|
| 254 | dep->de_stat.ets_collision += 1;
|
---|
| 255 | /* Put pointer back to beginning of packet */
|
---|
| 256 | outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_SYS);
|
---|
| 257 | outw_el1(dep, EL1_XMITPTR, (EL1_BFRSIZ - TxBuff->size));
|
---|
| 258 | /* And retrigger transmission */
|
---|
| 259 | outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_XMIT);
|
---|
| 260 | return;
|
---|
| 261 |
|
---|
| 262 | } else if ((isr & EXSR_16JAM) || !(isr & EXSR_IDLE)) {
|
---|
| 263 | dep->de_stat.ets_sendErr += 1;
|
---|
| 264 |
|
---|
| 265 | } else if (isr & EXSR_UNDER) {
|
---|
| 266 | dep->de_stat.ets_fifoUnder += 1;
|
---|
| 267 | }
|
---|
| 268 | DEBUG(printf("3c501: got xmit interrupt (0x%02X)\n", isr));
|
---|
| 269 | el1_reset(dep);
|
---|
| 270 |
|
---|
| 271 | } else {
|
---|
| 272 | /** if (inw_el1(dep, EL1_XMITPTR) == EL1_BFRSIZ) **/
|
---|
| 273 | /* Packet transmitted successfully */
|
---|
| 274 | dep->de_stat.ets_packetT += 1;
|
---|
| 275 | dep->bytes_Tx += (long) (TxBuff->size);
|
---|
| 276 | free_buff(dep, TxBuff);
|
---|
| 277 | dep->de_flags &= NOT(DEF_XMIT_BUSY);
|
---|
| 278 | if ((dep->de_flags & DEF_SENDING) && dep->de_xmitq_head) {
|
---|
| 279 | /* Pending transmit request available in queue */
|
---|
| 280 | el1_send(dep, TRUE, 0);
|
---|
| 281 | if (dep->de_flags & (DEF_XMIT_BUSY | DEF_ACK_SEND))
|
---|
| 282 | return;
|
---|
| 283 | }
|
---|
| 284 | }
|
---|
| 285 |
|
---|
| 286 | } else if ((csr & (ECSR_RECV | ECSR_XMTBSY)) == (ECSR_RECV | ECSR_XMTBSY)) {
|
---|
| 287 |
|
---|
| 288 | /* Got a receive interrupt */
|
---|
| 289 | isr = inb_el1(dep, EL1_RECV);
|
---|
| 290 | pktsize = inw_el1(dep, EL1_RECVPTR);
|
---|
| 291 | if ((isr & ERSR_RERROR) || (isr & ERSR_STALE)) {
|
---|
| 292 | DEBUG(printf("Rx0 (ASR=0x%02X RSR=0x%02X size=%d)\n", csr, isr, pktsize));
|
---|
| 293 | dep->de_stat.ets_recvErr += 1;
|
---|
| 294 |
|
---|
| 295 | } else if (pktsize < ETH_MIN_PACK_SIZE || pktsize > ETH_MAX_PACK_SIZE) {
|
---|
| 296 | DEBUG(printf("Rx1 (ASR=0x%02X RSR=0x%02X size=%d)\n", csr, isr, pktsize));
|
---|
| 297 | dep->de_stat.ets_recvErr += 1;
|
---|
| 298 |
|
---|
| 299 | } else if ((rxptr = alloc_buff(dep, pktsize + sizeof(buff_t))) == NULL) {
|
---|
| 300 | /* Memory not available. Drop packet */
|
---|
| 301 | dep->de_stat.ets_fifoOver += 1;
|
---|
| 302 |
|
---|
| 303 | } else if (isr & (ERSR_GOOD | ERSR_ANY)) {
|
---|
| 304 | /* Got a good packet. Read it from buffer */
|
---|
| 305 | outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_SYS);
|
---|
| 306 | outw_el1(dep, EL1_XMITPTR, 0);
|
---|
| 307 | insb(dep->de_data_port, SELF, rxptr->buffer, pktsize);
|
---|
| 308 | rxptr->next = NULL;
|
---|
| 309 | rxptr->size = pktsize;
|
---|
| 310 | dep->de_stat.ets_packetR += 1;
|
---|
| 311 | dep->bytes_Rx += (long) pktsize;
|
---|
| 312 | lock(); /* Queue packet to receive queue */
|
---|
| 313 | if (dep->de_recvq_head == NULL)
|
---|
| 314 | dep->de_recvq_head = rxptr;
|
---|
| 315 | else
|
---|
| 316 | dep->de_recvq_tail->next = rxptr;
|
---|
| 317 | dep->de_recvq_tail = rxptr;
|
---|
| 318 | unlock();
|
---|
| 319 |
|
---|
| 320 | /* Reply to pending Receive requests, if any */
|
---|
| 321 | el1_recv(dep, TRUE, 0);
|
---|
| 322 | }
|
---|
| 323 | } else { /* Nasty condition, should never happen */
|
---|
| 324 | DEBUG(
|
---|
| 325 | printf("3c501: got interrupt with status 0x%02X\n"
|
---|
| 326 | " de_flags=0x%04X XSR=0x%02X RSR=0x%02X \n"
|
---|
| 327 | " xmit buffer = 0x%4X recv buffer = 0x%4X\n",
|
---|
| 328 | csr, dep->de_flags,
|
---|
| 329 | inb_el1(dep, EL1_RECV),
|
---|
| 330 | inb_el1(dep, EL1_XMIT),
|
---|
| 331 | inw_el1(dep, EL1_XMITPTR),
|
---|
| 332 | inw_el1(dep, EL1_RECVPTR))
|
---|
| 333 | );
|
---|
| 334 | el1_reset(dep);
|
---|
| 335 | }
|
---|
| 336 |
|
---|
| 337 | /* Move into receive mode */
|
---|
| 338 | outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_RECV);
|
---|
| 339 | outw_el1(dep, EL1_RECVPTR, 0);
|
---|
| 340 | /* Be sure that interrupts are cleared */
|
---|
| 341 | inb_el1(dep, EL1_RECV);
|
---|
| 342 | inb_el1(dep, EL1_XMIT);
|
---|
| 343 | return;
|
---|
| 344 | }
|
---|
| 345 |
|
---|
| 346 | /*
|
---|
| 347 | ** Name: void el1_init(dpeth_t *dep)
|
---|
| 348 | ** Function: Initalizes board hardware and driver data structures.
|
---|
| 349 | */
|
---|
| 350 | static void el1_init(dpeth_t * dep)
|
---|
| 351 | {
|
---|
| 352 | int ix;
|
---|
| 353 |
|
---|
| 354 | dep->de_irq &= NOT(DEI_DEFAULT); /* Strip the default flag. */
|
---|
| 355 | dep->de_offset_page = 0;
|
---|
| 356 | dep->de_data_port = dep->de_base_port + EL1_DATAPORT;
|
---|
| 357 |
|
---|
| 358 | el1_reset(dep); /* Reset and initialize board */
|
---|
| 359 |
|
---|
| 360 | /* Start receiver (default mode) */
|
---|
| 361 | outw_el1(dep, EL1_RECVPTR, 0);
|
---|
| 362 | outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_RECV);
|
---|
| 363 |
|
---|
| 364 | /* Initializes buffer pool */
|
---|
| 365 | init_buff(dep, NULL);
|
---|
| 366 | el1_mode_init(dep);
|
---|
| 367 |
|
---|
| 368 | printf("%s: Etherlink (%s) at %X:%d - ",
|
---|
| 369 | dep->de_name, "3c501", dep->de_base_port, dep->de_irq);
|
---|
| 370 | for (ix = 0; ix < SA_ADDR_LEN; ix += 1)
|
---|
| 371 | printf("%02X%c", (dep->de_address.ea_addr[ix] = StationAddress[ix]),
|
---|
| 372 | ix < SA_ADDR_LEN - 1 ? ':' : '\n');
|
---|
| 373 |
|
---|
| 374 | /* Device specific functions */
|
---|
| 375 | dep->de_recvf = el1_recv;
|
---|
| 376 | dep->de_sendf = el1_send;
|
---|
| 377 | dep->de_flagsf = el1_mode_init;
|
---|
| 378 | dep->de_resetf = el1_reset;
|
---|
| 379 | dep->de_getstatsf = el1_getstats;
|
---|
| 380 | dep->de_dumpstatsf = el1_dumpstats;
|
---|
| 381 | dep->de_interruptf = el1_interrupt;
|
---|
| 382 |
|
---|
| 383 | return; /* Done */
|
---|
| 384 | }
|
---|
| 385 |
|
---|
| 386 | /*
|
---|
| 387 | ** Name: int el1_probe(dpeth_t *dep)
|
---|
| 388 | ** Function: Checks for presence of the board.
|
---|
| 389 | */
|
---|
| 390 | PUBLIC int el1_probe(dpeth_t * dep)
|
---|
| 391 | {
|
---|
| 392 | int ix;
|
---|
| 393 |
|
---|
| 394 | for (ix = 0; ix < 8; ix += 1) /* Reset the board */
|
---|
| 395 | outb_el1(dep, EL1_CSR, ECSR_RESET);
|
---|
| 396 | outb_el1(dep, EL1_CSR, ECSR_SYS); /* Leaves buffer to system */
|
---|
| 397 |
|
---|
| 398 | /* Check station address */
|
---|
| 399 | for (ix = 0; ix < SA_ADDR_LEN; ix += 1) {
|
---|
| 400 | outw_el1(dep, EL1_XMITPTR, ix);
|
---|
| 401 | StationAddress[ix] = inb_el1(dep, EL1_SAPROM);
|
---|
| 402 | }
|
---|
| 403 | if (StationAddress[0] != 0x02 || /* Etherlink Station address */
|
---|
| 404 | StationAddress[1] != 0x60 || /* MUST be 02:60:8c:xx:xx:xx */
|
---|
| 405 | StationAddress[2] != 0x8C)
|
---|
| 406 | return FALSE; /* No Etherlink board at this address */
|
---|
| 407 |
|
---|
| 408 | dep->de_ramsize = 0; /* RAM size is meaningless */
|
---|
| 409 | dep->de_linmem = 0L; /* Access is via I/O port */
|
---|
| 410 |
|
---|
| 411 | /* Device specific functions */
|
---|
| 412 | dep->de_initf = el1_init;
|
---|
| 413 | dep->de_stopf = el1_stop;
|
---|
| 414 |
|
---|
| 415 | return TRUE; /* Etherlink board found */
|
---|
| 416 | }
|
---|
| 417 |
|
---|
| 418 | #endif /* ENABLE_3C501 */
|
---|
| 419 |
|
---|
| 420 | /** 3c501.c **/
|
---|