#include <gpxe/ethernet.h>#include "etherboot.h"#include "nic.h"#include <gpxe/isa.h>#include "3c509.h"Go to the source code of this file.
Enumerations | |
| enum | { none, bnc, utp } |
Functions | |
| FILE_LICENCE (BSD2) | |
| void | t5x9_disable (struct nic *nic) |
| static void | t509_enable (struct nic *nic) |
| static void | t509_reset (struct nic *nic) |
| static void | t509_transmit (struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p) |
| static int | t509_poll (struct nic *nic, int retrieve) |
| static void | t509_irq (struct nic *nic __unused, irq_action_t action __unused) |
| static int | eeprom_rdy (uint16_t ioaddr) |
| static int | get_e (uint16_t ioaddr, int offset) |
| int | t5x9_probe (struct nic *nic, uint16_t prod_id_check, uint16_t prod_id_mask) |
Variables | |
| static enum { ... } | connector |
| static char | padmap [] |
| static struct nic_operations | t509_operations |
| anonymous enum |
| FILE_LICENCE | ( | BSD2 | ) |
| void t5x9_disable | ( | struct nic * | nic | ) |
Definition at line 40 of file 3c5x9.c.
References C_INTR_LATCH, EP_COMMAND, EP_STATUS, EP_W0_CONFIG_CTRL, EP_W0_RESOURCE_CFG, GO_WINDOW, inw, nic::ioaddr, outw, RX_DISABLE, RX_DISCARD_TOP_PACK, RX_RESET, S_COMMAND_IN_PROGRESS, SET_INTR_MASK, SET_IRQ, SET_RD_0_MASK, SET_RX_FILTER, STOP_TRANSCEIVER, TX_DISABLE, TX_RESET, and udelay().
Referenced by el3_eisa_disable(), legacy_t509_disable(), t509_reset(), and t529_disable().
00040 { 00041 /* stop card */ 00042 outw(RX_DISABLE, nic->ioaddr + EP_COMMAND); 00043 outw(RX_DISCARD_TOP_PACK, nic->ioaddr + EP_COMMAND); 00044 while (inw(nic->ioaddr + EP_STATUS) & S_COMMAND_IN_PROGRESS) 00045 ; 00046 outw(TX_DISABLE, nic->ioaddr + EP_COMMAND); 00047 outw(STOP_TRANSCEIVER, nic->ioaddr + EP_COMMAND); 00048 udelay(1000); 00049 outw(RX_RESET, nic->ioaddr + EP_COMMAND); 00050 outw(TX_RESET, nic->ioaddr + EP_COMMAND); 00051 outw(C_INTR_LATCH, nic->ioaddr + EP_COMMAND); 00052 outw(SET_RD_0_MASK, nic->ioaddr + EP_COMMAND); 00053 outw(SET_INTR_MASK, nic->ioaddr + EP_COMMAND); 00054 outw(SET_RX_FILTER, nic->ioaddr + EP_COMMAND); 00055 00056 /* 00057 * wait for reset to complete 00058 */ 00059 while (inw(nic->ioaddr + EP_STATUS) & S_COMMAND_IN_PROGRESS) 00060 ; 00061 00062 GO_WINDOW(nic->ioaddr,0); 00063 00064 /* Disable the card */ 00065 outw(0, nic->ioaddr + EP_W0_CONFIG_CTRL); 00066 00067 /* Configure IRQ to none */ 00068 outw(SET_IRQ(0), nic->ioaddr + EP_W0_RESOURCE_CFG); 00069 }
| static void t509_enable | ( | struct nic * | nic | ) | [static] |
Definition at line 71 of file 3c5x9.c.
References ACK_INTR, bnc, connector, ENABLE_DRQ_IRQ, ENABLE_UTP, EP_COMMAND, EP_W0_CONFIG_CTRL, EP_W1_TX_STATUS, EP_W2_ADDR_0, EP_W4_MEDIA_TYPE, ETH_ALEN, ETH_ZLEN, FIL_BRDCST, FIL_GROUP, FIL_INDIVIDUAL, GO_WINDOW, inb, nic::ioaddr, nic::node_addr, outb, outw, RX_ENABLE, RX_RESET, S_5_INTS, SET_INTR_MASK, SET_RD_0_MASK, SET_RX_EARLY_THRESH, SET_RX_FILTER, SET_TX_START_THRESH, sleep(), START_TRANSCEIVER, TX_ENABLE, TX_RESET, udelay(), and utp.
Referenced by t509_reset().
00071 { 00072 int i; 00073 00074 /* Enable the card */ 00075 GO_WINDOW(nic->ioaddr,0); 00076 outw(ENABLE_DRQ_IRQ, nic->ioaddr + EP_W0_CONFIG_CTRL); 00077 00078 GO_WINDOW(nic->ioaddr,2); 00079 00080 /* Reload the ether_addr. */ 00081 for (i = 0; i < ETH_ALEN; i++) 00082 outb(nic->node_addr[i], nic->ioaddr + EP_W2_ADDR_0 + i); 00083 00084 outw(RX_RESET, nic->ioaddr + EP_COMMAND); 00085 outw(TX_RESET, nic->ioaddr + EP_COMMAND); 00086 00087 /* Window 1 is operating window */ 00088 GO_WINDOW(nic->ioaddr,1); 00089 for (i = 0; i < 31; i++) 00090 inb(nic->ioaddr + EP_W1_TX_STATUS); 00091 00092 /* get rid of stray intr's */ 00093 outw(ACK_INTR | 0xff, nic->ioaddr + EP_COMMAND); 00094 00095 outw(SET_RD_0_MASK | S_5_INTS, nic->ioaddr + EP_COMMAND); 00096 00097 outw(SET_INTR_MASK, nic->ioaddr + EP_COMMAND); 00098 00099 outw(SET_RX_FILTER | FIL_GROUP | FIL_INDIVIDUAL | FIL_BRDCST, 00100 nic->ioaddr + EP_COMMAND); 00101 00102 /* configure BNC */ 00103 if (connector == bnc) { 00104 outw(START_TRANSCEIVER, nic->ioaddr + EP_COMMAND); 00105 udelay(1000); 00106 } 00107 /* configure UTP */ 00108 else if (connector == utp) { 00109 GO_WINDOW(nic->ioaddr,4); 00110 outw(ENABLE_UTP, nic->ioaddr + EP_W4_MEDIA_TYPE); 00111 sleep(2); /* Give time for media to negotiate */ 00112 GO_WINDOW(nic->ioaddr,1); 00113 } 00114 00115 /* start transceiver and receiver */ 00116 outw(RX_ENABLE, nic->ioaddr + EP_COMMAND); 00117 outw(TX_ENABLE, nic->ioaddr + EP_COMMAND); 00118 00119 /* set early threshold for minimal packet length */ 00120 outw(SET_RX_EARLY_THRESH | ETH_ZLEN, nic->ioaddr + EP_COMMAND); 00121 outw(SET_TX_START_THRESH | 16, nic->ioaddr + EP_COMMAND); 00122 }
| static void t509_reset | ( | struct nic * | nic | ) | [static] |
Definition at line 124 of file 3c5x9.c.
References t509_enable(), and t5x9_disable().
Referenced by t5x9_probe().
00124 { 00125 t5x9_disable ( nic ); 00126 t509_enable ( nic ); 00127 }
| static void t509_transmit | ( | struct nic * | nic, | |
| const char * | d, | |||
| unsigned int | t, | |||
| unsigned int | s, | |||
| const char * | p | |||
| ) | [static] |
Definition at line 135 of file 3c5x9.c.
References EP_COMMAND, EP_STATUS, EP_W1_FREE_TX, EP_W1_TX_PIO_WR_1, EP_W1_TX_STATUS, ETH_ALEN, ETH_FRAME_LEN, ETH_HLEN, htons, inb, inw, nic::ioaddr, nic::node_addr, outb, outsw, outw, padmap, printf(), S_COMMAND_IN_PROGRESS, TX_ENABLE, TX_RESET, TXS_COMPLETE, TXS_MAX_COLLISION, TXS_STATUS_OVERFLOW, and TXS_UNDERRUN.
00141 { 00142 register unsigned int len; 00143 int pad; 00144 int status; 00145 00146 #ifdef EDEBUG 00147 printf("{l=%d,t=%hX}",s+ETH_HLEN,t); 00148 #endif 00149 00150 /* swap bytes of type */ 00151 t= htons(t); 00152 00153 len=s+ETH_HLEN; /* actual length of packet */ 00154 pad = padmap[len & 3]; 00155 00156 /* 00157 * The 3c509 automatically pads short packets to minimum ethernet length, 00158 * but we drop packets that are too large. Perhaps we should truncate 00159 * them instead? 00160 */ 00161 if (len + pad > ETH_FRAME_LEN) { 00162 return; 00163 } 00164 00165 /* drop acknowledgements */ 00166 while ((status=inb(nic->ioaddr + EP_W1_TX_STATUS)) & TXS_COMPLETE ) { 00167 if (status & (TXS_UNDERRUN|TXS_MAX_COLLISION|TXS_STATUS_OVERFLOW)) { 00168 outw(TX_RESET, nic->ioaddr + EP_COMMAND); 00169 outw(TX_ENABLE, nic->ioaddr + EP_COMMAND); 00170 } 00171 outb(0x0, nic->ioaddr + EP_W1_TX_STATUS); 00172 } 00173 00174 while (inw(nic->ioaddr + EP_W1_FREE_TX) < (unsigned short)len + pad + 4) 00175 ; /* no room in FIFO */ 00176 00177 outw(len, nic->ioaddr + EP_W1_TX_PIO_WR_1); 00178 outw(0x0, nic->ioaddr + EP_W1_TX_PIO_WR_1); /* Second dword meaningless */ 00179 00180 /* write packet */ 00181 outsw(nic->ioaddr + EP_W1_TX_PIO_WR_1, d, ETH_ALEN/2); 00182 outsw(nic->ioaddr + EP_W1_TX_PIO_WR_1, nic->node_addr, ETH_ALEN/2); 00183 outw(t, nic->ioaddr + EP_W1_TX_PIO_WR_1); 00184 outsw(nic->ioaddr + EP_W1_TX_PIO_WR_1, p, s / 2); 00185 if (s & 1) 00186 outb(*(p+s - 1), nic->ioaddr + EP_W1_TX_PIO_WR_1); 00187 00188 while (pad--) 00189 outb(0, nic->ioaddr + EP_W1_TX_PIO_WR_1); /* Padding */ 00190 00191 /* wait for Tx complete */ 00192 while((inw(nic->ioaddr + EP_STATUS) & S_COMMAND_IN_PROGRESS) != 0) 00193 ; 00194 }
| static int t509_poll | ( | struct nic * | nic, | |
| int | retrieve | |||
| ) | [static] |
Definition at line 199 of file 3c5x9.c.
References ACK_INTR, C_INTR_LATCH, EP_COMMAND, EP_STATUS, EP_W1_RX_PIO_RD_1, EP_W1_RX_STATUS, ERR_RX, ETH_ALEN, inb, insw, inw, nic::ioaddr, outw, nic::packet, nic::packetlen, printf(), RX_BYTES_MASK, RX_DISCARD_TOP_PACK, RX_INCOMPLETE, S_5_INTS, S_COMMAND_IN_PROGRESS, S_RX_COMPLETE, and udelay().
00200 { 00201 /* common variables */ 00202 /* variables for 3C509 */ 00203 short status, cst; 00204 register short rx_fifo; 00205 00206 cst=inw(nic->ioaddr + EP_STATUS); 00207 00208 #ifdef EDEBUG 00209 if(cst & 0x1FFF) 00210 printf("-%hX-",cst); 00211 #endif 00212 00213 if( (cst & S_RX_COMPLETE)==0 ) { 00214 /* acknowledge everything */ 00215 outw(ACK_INTR| (cst & S_5_INTS), nic->ioaddr + EP_COMMAND); 00216 outw(C_INTR_LATCH, nic->ioaddr + EP_COMMAND); 00217 00218 return 0; 00219 } 00220 00221 status = inw(nic->ioaddr + EP_W1_RX_STATUS); 00222 #ifdef EDEBUG 00223 printf("*%hX*",status); 00224 #endif 00225 00226 if (status & ERR_RX) { 00227 outw(RX_DISCARD_TOP_PACK, nic->ioaddr + EP_COMMAND); 00228 return 0; 00229 } 00230 00231 rx_fifo = status & RX_BYTES_MASK; 00232 if (rx_fifo==0) 00233 return 0; 00234 00235 if ( ! retrieve ) return 1; 00236 00237 /* read packet */ 00238 #ifdef EDEBUG 00239 printf("[l=%d",rx_fifo); 00240 #endif 00241 insw(nic->ioaddr + EP_W1_RX_PIO_RD_1, nic->packet, rx_fifo / 2); 00242 if(rx_fifo & 1) 00243 nic->packet[rx_fifo-1]=inb(nic->ioaddr + EP_W1_RX_PIO_RD_1); 00244 nic->packetlen=rx_fifo; 00245 00246 while(1) { 00247 status = inw(nic->ioaddr + EP_W1_RX_STATUS); 00248 #ifdef EDEBUG 00249 printf("*%hX*",status); 00250 #endif 00251 rx_fifo = status & RX_BYTES_MASK; 00252 if(rx_fifo>0) { 00253 insw(nic->ioaddr + EP_W1_RX_PIO_RD_1, nic->packet+nic->packetlen, rx_fifo / 2); 00254 if(rx_fifo & 1) 00255 nic->packet[nic->packetlen+rx_fifo-1]=inb(nic->ioaddr + EP_W1_RX_PIO_RD_1); 00256 nic->packetlen+=rx_fifo; 00257 #ifdef EDEBUG 00258 printf("+%d",rx_fifo); 00259 #endif 00260 } 00261 if(( status & RX_INCOMPLETE )==0) { 00262 #ifdef EDEBUG 00263 printf("=%d",nic->packetlen); 00264 #endif 00265 break; 00266 } 00267 udelay(1000); /* if incomplete wait 1 ms */ 00268 } 00269 /* acknowledge reception of packet */ 00270 outw(RX_DISCARD_TOP_PACK, nic->ioaddr + EP_COMMAND); 00271 while (inw(nic->ioaddr + EP_STATUS) & S_COMMAND_IN_PROGRESS) 00272 ; 00273 #ifdef EDEBUG 00274 { 00275 unsigned short type = 0; /* used by EDEBUG */ 00276 type = (nic->packet[12]<<8) | nic->packet[13]; 00277 if(nic->packet[0]+nic->packet[1]+nic->packet[2]+nic->packet[3]+nic->packet[4]+ 00278 nic->packet[5] == 0xFF*ETH_ALEN) 00279 printf(",t=%hX,b]",type); 00280 else 00281 printf(",t=%hX]",type); 00282 } 00283 #endif 00284 return (1); 00285 }
| static void t509_irq | ( | struct nic *nic | __unused, | |
| irq_action_t action | __unused | |||
| ) | [static] |
| static int eeprom_rdy | ( | uint16_t | ioaddr | ) | [static] |
Definition at line 306 of file 3c5x9.c.
References is_eeprom_busy, and MAX_EEPROMBUSY.
00306 { 00307 int i; 00308 00309 for (i = 0; is_eeprom_busy(ioaddr) && i < MAX_EEPROMBUSY; i++); 00310 if (i >= MAX_EEPROMBUSY) { 00311 /* printf("3c509: eeprom failed to come ready.\n"); */ 00312 /* memory in EPROM is tight */ 00313 /* printf("3c509: eeprom busy.\n"); */ 00314 return (0); 00315 } 00316 return (1); 00317 }
| static int get_e | ( | uint16_t | ioaddr, | |
| int | offset | |||
| ) | [static] |
Definition at line 322 of file 3c5x9.c.
References EEPROM_CMD_RD, eeprom_rdy(), EP_W0_EEPROM_COMMAND, EP_W0_EEPROM_DATA, GO_WINDOW, inw, and outw.
00322 { 00323 GO_WINDOW(ioaddr,0); 00324 if (!eeprom_rdy(ioaddr)) 00325 return (0xffff); 00326 outw(EEPROM_CMD_RD | offset, ioaddr + EP_W0_EEPROM_COMMAND); 00327 if (!eeprom_rdy(ioaddr)) 00328 return (0xffff); 00329 return (inw(ioaddr + EP_W0_EEPROM_DATA)); 00330 }
Definition at line 342 of file 3c5x9.c.
References bnc, connector, DBG, EEPROM_PROD_ID, EP_W0_ADDRESS_CFG, EP_W0_CONFIG_CTRL, EP_W2_ADDR_0, ETH_ALEN, eth_ntoa(), get_e(), GO_WINDOW, htons, inw, nic::ioaddr, IS_AUI, IS_BNC, IS_UTP, nic::nic_op, nic::node_addr, ntohs, outw, printf(), t509_reset(), and utp.
Referenced by el3_eisa_probe(), legacy_t509_probe(), and t529_probe().
00343 { 00344 uint16_t prod_id; 00345 int i,j; 00346 unsigned short *p; 00347 00348 /* Check product ID */ 00349 prod_id = get_e ( nic->ioaddr, EEPROM_PROD_ID ); 00350 if ( ( prod_id & prod_id_mask ) != prod_id_check ) { 00351 printf ( "EEPROM Product ID is incorrect (%hx & %hx != %hx)\n", 00352 prod_id, prod_id_mask, prod_id_check ); 00353 return 0; 00354 } 00355 00356 /* test for presence of connectors */ 00357 GO_WINDOW(nic->ioaddr,0); 00358 i = inw(nic->ioaddr + EP_W0_CONFIG_CTRL); 00359 j = (inw(nic->ioaddr + EP_W0_ADDRESS_CFG) >> 14) & 0x3; 00360 00361 switch(j) { 00362 case 0: 00363 if (i & IS_UTP) { 00364 printf("10baseT\n"); 00365 connector = utp; 00366 } else { 00367 printf("10baseT not present\n"); 00368 return 0; 00369 } 00370 break; 00371 case 1: 00372 if (i & IS_AUI) { 00373 printf("10base5\n"); 00374 } else { 00375 printf("10base5 not present\n"); 00376 return 0; 00377 } 00378 break; 00379 case 3: 00380 if (i & IS_BNC) { 00381 printf("10base2\n"); 00382 connector = bnc; 00383 } else { 00384 printf("10base2 not present\n"); 00385 return 0; 00386 } 00387 break; 00388 default: 00389 printf("unknown connector\n"); 00390 return 0; 00391 } 00392 00393 /* 00394 * Read the station address from the eeprom 00395 */ 00396 p = (unsigned short *) nic->node_addr; 00397 for (i = 0; i < ETH_ALEN / 2; i++) { 00398 p[i] = htons(get_e(nic->ioaddr,i)); 00399 GO_WINDOW(nic->ioaddr,2); 00400 outw(ntohs(p[i]), nic->ioaddr + EP_W2_ADDR_0 + (i * 2)); 00401 } 00402 00403 DBG ( "Ethernet Address: %s\n", eth_ntoa ( nic->node_addr ) ); 00404 00405 t509_reset(nic); 00406 00407 nic->nic_op = &t509_operations; 00408 return 1; 00409 00410 }
enum { ... } connector [static] |
Referenced by t509_enable(), and t5x9_probe().
struct nic_operations t509_operations [static] |
Initial value:
{
.connect = dummy_connect,
.poll = t509_poll,
.transmit = t509_transmit,
.irq = t509_irq,
}
1.5.7.1