1 /* 2 ** File: 8390.c May 02, 2000 3 ** 4 ** Author: Giovanni Falzoni <gfalzoni@inwind.it> 5 ** 6 ** This file contains an ethernet device driver for NICs 7 ** equipped with the National Semiconductor NS 8390 chip. 8 ** It has to be associated with the board specific driver. 9 ** Rewritten from Minix 2.0.0 ethernet driver dp8390.c 10 ** to extract the NS 8390 common functions. 11 */ 12 13 #include <minix/drivers.h> 14 #include <minix/netdriver.h> 15 #include <net/gen/ether.h> 16 #include <net/gen/eth_io.h> 17 #include <assert.h> 18 #include "dp.h" 19 20 #if (ENABLE_DP8390 == 1) 21 22 #include "8390.h" 23 24 /* 25 ** Name: ns_rw_setup 26 ** Function: Sets the board for reading/writing. 27 */ 28 static void ns_rw_setup(const dpeth_t *dep, int mode, int size, u16_t offset) 29 { 30 31 if (mode == CR_DM_RW) outb_reg0(dep, DP_ISR, ISR_RDC); 32 outb_reg0(dep, DP_RBCR0, size & 0xFF); 33 outb_reg0(dep, DP_RBCR1, (size >> 8) & 0xFF); 34 outb_reg0(dep, DP_RSAR0, offset & 0xFF); 35 outb_reg0(dep, DP_RSAR1, (offset >> 8) & 0xFF); 36 mode |= (CR_PS_P0 | CR_STA); 37 outb_reg0(dep, DP_CR, mode); 38 } 39 40 /* 41 ** Name: ns_start_xmit 42 ** Function: Sets the board for for transmitting and fires it. 43 */ 44 static void ns_start_xmit(const dpeth_t * dep, int size, int pageno) 45 { 46 47 outb_reg0(dep, DP_TPSR, pageno); 48 outb_reg0(dep, DP_TBCR1, size >> 8); 49 outb_reg0(dep, DP_TBCR0, size & 0xFF); 50 outb_reg0(dep, DP_CR, CR_NO_DMA | CR_STA | CR_TXP); /* Fires transmission */ 51 } 52 53 /* 54 ** Name: mem_getblock 55 ** Function: Reads a block of packet from board (shared memory). 56 */ 57 static void mem_getblock(dpeth_t *dep, u16_t offset, int size, void *dst) 58 { 59 60 assert(offset + size <= dep->de_ramsize); 61 62 memcpy(dst, dep->de_locmem + offset, size); 63 } 64 65 /* 66 ** Name: mem_nic2user 67 ** Function: Copies a packet from board to user area (shared memory). 68 */ 69 static void mem_nic2user(dpeth_t *dep, int pageno, struct netdriver_data *data, 70 size_t size) 71 { 72 size_t offset, left; 73 74 /* Computes shared memory address (skipping receive header) */ 75 offset = pageno * DP_PAGESIZE + sizeof(dp_rcvhdr_t); 76 77 if (offset + size > dep->de_stoppage * DP_PAGESIZE) { 78 left = dep->de_stoppage * DP_PAGESIZE - offset; 79 netdriver_copyout(data, 0, dep->de_locmem + offset, left); 80 offset = dep->de_startpage * DP_PAGESIZE; 81 netdriver_copyout(data, left, dep->de_locmem + offset, size - left); 82 } else 83 netdriver_copyout(data, 0, dep->de_locmem + offset, size); 84 } 85 86 /* 87 ** Name: mem_user2nic 88 ** Function: Copies a packet from user area to board (shared memory). 89 */ 90 static void mem_user2nic(dpeth_t *dep, int pageno, struct netdriver_data *data, 91 size_t size) 92 { 93 size_t offset; 94 95 /* Computes shared memory address */ 96 offset = pageno * DP_PAGESIZE; 97 98 netdriver_copyin(data, 0, dep->de_locmem + offset, size); 99 } 100 101 /* 102 ** Name: pio_getblock 103 ** Function: Reads a block of packet from board (Prog. I/O). 104 */ 105 static void pio_getblock(dpeth_t *dep, u16_t offset, int size, void *dst) 106 { 107 108 /* Sets up board for reading */ 109 ns_rw_setup(dep, CR_DM_RR, size, offset); 110 111 if (dep->de_16bit == TRUE) 112 insw(dep->de_data_port, dst, size); 113 else 114 insb(dep->de_data_port, dst, size); 115 } 116 117 /* 118 ** Name: pio_nic2user 119 ** Function: Copies a packet from board to user area (Prog. I/O). 120 */ 121 static void pio_nic2user(dpeth_t *dep, int pageno, struct netdriver_data *data, 122 size_t size) 123 { 124 size_t offset, left; 125 126 /* Computes memory address (skipping receive header) */ 127 offset = pageno * DP_PAGESIZE + sizeof(dp_rcvhdr_t); 128 129 if (offset + size > dep->de_stoppage * DP_PAGESIZE) { 130 left = dep->de_stoppage * DP_PAGESIZE - offset; 131 132 ns_rw_setup(dep, CR_DM_RR, left, offset); 133 134 if (dep->de_16bit) 135 netdriver_portinw(data, 0, dep->de_data_port, left); 136 else 137 netdriver_portinb(data, 0, dep->de_data_port, left); 138 139 offset = dep->de_startpage * DP_PAGESIZE; 140 } else 141 left = 0; 142 143 ns_rw_setup(dep, CR_DM_RR, size - left, offset); 144 145 if (dep->de_16bit) 146 netdriver_portinw(data, left, dep->de_data_port, size - left); 147 else 148 netdriver_portinb(data, left, dep->de_data_port, size - left); 149 } 150 151 /* 152 ** Name: pio_user2nic 153 ** Function: Copies a packet from user area to board (Prog. I/O). 154 */ 155 static void pio_user2nic(dpeth_t *dep, int pageno, struct netdriver_data *data, 156 size_t size) 157 { 158 int ix; 159 160 /* Sets up board for writing */ 161 ns_rw_setup(dep, CR_DM_RW, size, pageno * DP_PAGESIZE); 162 163 if (dep->de_16bit) 164 netdriver_portoutw(data, 0, dep->de_data_port, size); 165 else 166 netdriver_portoutb(data, 0, dep->de_data_port, size); 167 168 for (ix = 0; ix < 100; ix += 1) { 169 if (inb_reg0(dep, DP_ISR) & ISR_RDC) break; 170 } 171 if (ix == 100) 172 panic("remote dma failed to complete"); 173 } 174 175 /* 176 ** Name: ns_stats 177 ** Function: Updates counters reading from device 178 */ 179 static void ns_stats(dpeth_t * dep) 180 { 181 182 dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0); 183 dep->de_stat.ets_recvErr += inb_reg0(dep, DP_CNTR1); 184 dep->de_stat.ets_fifoOver += inb_reg0(dep, DP_CNTR2); 185 } 186 187 /* 188 ** Name: ns_dodump 189 ** Function: Displays statistics (a request from a function key). 190 */ 191 static void ns_dodump(dpeth_t * dep) 192 { 193 194 ns_stats(dep); /* Forces reading of counters from board */ 195 } 196 197 /* 198 ** Name: ns_reinit 199 ** Function: Updates receiver configuration. 200 */ 201 static void ns_reinit(dpeth_t * dep) 202 { 203 int dp_reg = 0; 204 205 if (dep->de_flags & DEF_PROMISC) dp_reg |= RCR_AB | RCR_PRO | RCR_AM; 206 if (dep->de_flags & DEF_BROAD) dp_reg |= RCR_AB; 207 if (dep->de_flags & DEF_MULTI) dp_reg |= RCR_AM; 208 outb_reg0(dep, DP_CR, CR_PS_P0); 209 outb_reg0(dep, DP_RCR, dp_reg); 210 } 211 212 /* 213 ** Name: ns_send 214 ** Function: Transfers packet to device and starts sending. 215 */ 216 static int ns_send(dpeth_t *dep, struct netdriver_data *data, size_t size) 217 { 218 int queue; 219 220 queue = dep->de_sendq_head; 221 if (dep->de_sendq[queue].sq_filled) 222 return SUSPEND; 223 224 (dep->de_user2nicf)(dep, dep->de_sendq[queue].sq_sendpage, data, size); 225 dep->bytes_Tx += (long) size; 226 dep->de_sendq[queue].sq_filled = TRUE; 227 dep->de_flags |= DEF_XMIT_BUSY; 228 if (dep->de_sendq_tail == queue) { /* there it goes.. */ 229 ns_start_xmit(dep, size, dep->de_sendq[queue].sq_sendpage); 230 } else 231 dep->de_sendq[queue].sq_size = size; 232 233 if (++queue == dep->de_sendq_nr) queue = 0; 234 dep->de_sendq_head = queue; 235 236 return OK; 237 } 238 239 /* 240 ** Name: ns_reset 241 ** Function: Resets device. 242 */ 243 static void ns_reset(dpeth_t * dep) 244 { 245 int ix; 246 247 /* Stop chip */ 248 outb_reg0(dep, DP_CR, CR_STP | CR_NO_DMA); 249 outb_reg0(dep, DP_RBCR0, 0); 250 outb_reg0(dep, DP_RBCR1, 0); 251 for (ix = 0; ix < 0x1000 && (inb_reg0(dep, DP_ISR) & ISR_RST) == 0; ix += 1) 252 /* Do nothing */ ; 253 outb_reg0(dep, DP_TCR, TCR_1EXTERNAL | TCR_OFST); 254 outb_reg0(dep, DP_CR, CR_STA | CR_NO_DMA); 255 outb_reg0(dep, DP_TCR, TCR_NORMAL | TCR_OFST); 256 257 /* Acknowledge the ISR_RDC (remote dma) interrupt. */ 258 for (ix = 0; ix < 0x1000 && (inb_reg0(dep, DP_ISR) & ISR_RDC) == 0; ix += 1) 259 /* Do nothing */ ; 260 outb_reg0(dep, DP_ISR, inb_reg0(dep, DP_ISR) & NOT(ISR_RDC)); 261 262 /* Reset the transmit ring. If we were transmitting a packet, we 263 * pretend that the packet is processed. Higher layers will 264 * retransmit if the packet wasn't actually sent. */ 265 dep->de_sendq_head = dep->de_sendq_tail = 0; 266 for (ix = 0; ix < dep->de_sendq_nr; ix++) 267 dep->de_sendq[ix].sq_filled = FALSE; 268 netdriver_send(); 269 } 270 271 /* 272 ** Name: ns_recv 273 ** Function: Gets a packet from device 274 */ 275 static ssize_t ns_recv(dpeth_t *dep, struct netdriver_data *data, size_t max) 276 { 277 dp_rcvhdr_t header; 278 unsigned pageno, curr, next; 279 size_t length; 280 int packet_processed = FALSE; 281 #ifdef ETH_IGN_PROTO 282 u16_t eth_type; 283 #endif 284 285 pageno = inb_reg0(dep, DP_BNRY) + 1; 286 if (pageno == dep->de_stoppage) pageno = dep->de_startpage; 287 288 do { 289 /* */ 290 outb_reg0(dep, DP_CR, CR_PS_P1); 291 curr = inb_reg1(dep, DP_CURR); 292 outb_reg0(dep, DP_CR, CR_PS_P0 | CR_NO_DMA | CR_STA); 293 294 if (curr == pageno) 295 return SUSPEND; 296 297 (dep->de_getblockf)(dep, pageno * DP_PAGESIZE, sizeof(header), 298 &header); 299 #ifdef ETH_IGN_PROTO 300 (dep->de_getblockf)(dep, pageno * DP_PAGESIZE + sizeof(header) + 301 2 * sizeof(ether_addr_t), sizeof(eth_type), ð_type); 302 #endif 303 length = (header.dr_rbcl | (header.dr_rbch << 8)) - 304 sizeof(dp_rcvhdr_t); 305 next = header.dr_next; 306 307 if (length < ETH_MIN_PACK_SIZE || length > max) { 308 printf("%s: packet with strange length arrived: %zu\n", 309 dep->de_name, length); 310 dep->de_stat.ets_recvErr += 1; 311 next = curr; 312 313 } else if (next < dep->de_startpage || next >= dep->de_stoppage) { 314 printf("%s: strange next page\n", dep->de_name); 315 dep->de_stat.ets_recvErr += 1; 316 next = curr; 317 #ifdef ETH_IGN_PROTO 318 } else if (eth_type == eth_ign_proto) { 319 /* Hack: ignore packets of a given protocol */ 320 static int first = TRUE; 321 if (first) { 322 first = FALSE; 323 printf("%s: dropping proto %04x packet\n", 324 dep->de_name, ntohs(eth_ign_proto)); 325 } 326 next = curr; 327 #endif 328 } else if (header.dr_status & RSR_FO) { 329 /* This is very serious, issue a warning and reset buffers */ 330 printf("%s: fifo overrun, resetting receive buffer\n", 331 dep->de_name); 332 dep->de_stat.ets_fifoOver += 1; 333 next = curr; 334 335 } else if (header.dr_status & RSR_PRX) { 336 (dep->de_nic2userf)(dep, pageno, data, length); 337 packet_processed = TRUE; 338 } 339 dep->bytes_Rx += (long) length; 340 dep->de_stat.ets_packetR += 1; 341 outb_reg0(dep, DP_BNRY, 342 (next == dep->de_startpage ? dep->de_stoppage : next) - 1); 343 pageno = next; 344 } while (!packet_processed); 345 346 return length; 347 } 348 349 /* 350 ** Name: ns_interrupt 351 ** Function: Handles interrupt. 352 */ 353 static void ns_interrupt(dpeth_t * dep) 354 { 355 int isr, tsr; 356 int queue; 357 358 while ((isr = inb_reg0(dep, DP_ISR)) != 0) { 359 360 outb_reg0(dep, DP_ISR, isr); 361 if (isr & (ISR_PTX | ISR_TXE)) { 362 363 tsr = inb_reg0(dep, DP_TSR); 364 if (tsr & TSR_PTX) { 365 dep->de_stat.ets_packetT++; 366 } 367 if (tsr & TSR_COL) dep->de_stat.ets_collision++; 368 if (tsr & (TSR_ABT | TSR_FU)) { 369 dep->de_stat.ets_fifoUnder++; 370 } 371 if ((isr & ISR_TXE) || (tsr & (TSR_CRS | TSR_CDH | TSR_OWC))) { 372 printf("%s: got send Error (0x%02X)\n", 373 dep->de_name, tsr); 374 dep->de_stat.ets_sendErr++; 375 } 376 queue = dep->de_sendq_tail; 377 378 if (!(dep->de_sendq[queue].sq_filled)) { /* Hardware bug? */ 379 printf("%s: transmit interrupt, but not sending\n", 380 dep->de_name); 381 continue; 382 } 383 dep->de_sendq[queue].sq_filled = FALSE; 384 if (++queue == dep->de_sendq_nr) queue = 0; 385 dep->de_sendq_tail = queue; 386 if (dep->de_sendq[queue].sq_filled) { 387 ns_start_xmit(dep, dep->de_sendq[queue].sq_size, 388 dep->de_sendq[queue].sq_sendpage); 389 } 390 netdriver_send(); 391 } 392 if (isr & ISR_PRX) { 393 netdriver_recv(); 394 } 395 if (isr & ISR_RXE) { 396 printf("%s: got recv Error (0x%04X)\n", 397 dep->de_name, inb_reg0(dep, DP_RSR)); 398 dep->de_stat.ets_recvErr++; 399 } 400 if (isr & ISR_CNT) { 401 dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0); 402 dep->de_stat.ets_recvErr += inb_reg0(dep, DP_CNTR1); 403 dep->de_stat.ets_fifoOver += inb_reg0(dep, DP_CNTR2); 404 } 405 if (isr & ISR_OVW) { 406 printf("%s: got overwrite warning\n", dep->de_name); 407 } 408 if (isr & ISR_RDC) { 409 /* Nothing to do */ 410 } 411 if (isr & ISR_RST) { 412 /* This means we got an interrupt but the ethernet chip is shut 413 * down. We reset the chip right away, possibly losing received 414 * packets in the process. There used to be a more elaborate 415 * approach of resetting only after all pending packets had 416 * been accepted, but it was broken and this is simpler anyway. 417 */ 418 printf("%s: network interface stopped\n", dep->de_name); 419 ns_reset(dep); 420 break; 421 } 422 } 423 } 424 425 /* 426 ** Name: ns_init 427 ** Function: Initializes the NS 8390 428 */ 429 void ns_init(dpeth_t * dep) 430 { 431 int dp_reg; 432 int ix; 433 434 /* NS8390 initialization (as recommended in National Semiconductor specs) */ 435 outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_NO_DMA); /* 0x21 */ 436 outb_reg0(dep, DP_DCR, (((dep->de_16bit) ? DCR_WORDWIDE : DCR_BYTEWIDE) | 437 DCR_LTLENDIAN | DCR_8BYTES | DCR_BMS)); 438 outb_reg0(dep, DP_RBCR0, 0); 439 outb_reg0(dep, DP_RBCR1, 0); 440 outb_reg0(dep, DP_RCR, RCR_MON); /* Sets Monitor mode */ 441 outb_reg0(dep, DP_TCR, TCR_INTERNAL); /* Sets Loopback mode 1 */ 442 outb_reg0(dep, DP_PSTART, dep->de_startpage); 443 outb_reg0(dep, DP_PSTOP, dep->de_stoppage); 444 outb_reg0(dep, DP_BNRY, dep->de_stoppage - 1); 445 outb_reg0(dep, DP_ISR, 0xFF); /* Clears Interrupt Status Register */ 446 outb_reg0(dep, DP_IMR, 0); /* Clears Interrupt Mask Register */ 447 448 /* Copies station address in page 1 registers */ 449 outb_reg0(dep, DP_CR, CR_PS_P1 | CR_NO_DMA); /* Selects Page 1 */ 450 for (ix = 0; ix < SA_ADDR_LEN; ix += 1) /* Initializes address */ 451 outb_reg1(dep, DP_PAR0 + ix, dep->de_address.ea_addr[ix]); 452 for (ix = DP_MAR0; ix <= DP_MAR7; ix += 1) /* Initializes address */ 453 outb_reg1(dep, ix, 0xFF); 454 455 outb_reg1(dep, DP_CURR, dep->de_startpage); 456 outb_reg1(dep, DP_CR, CR_PS_P0 | CR_NO_DMA); /* Selects Page 0 */ 457 458 inb_reg0(dep, DP_CNTR0); /* Resets counters by reading them */ 459 inb_reg0(dep, DP_CNTR1); 460 inb_reg0(dep, DP_CNTR2); 461 462 dp_reg = IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE | IMR_OVWE | IMR_CNTE; 463 outb_reg0(dep, DP_ISR, 0xFF); /* Clears Interrupt Status Register */ 464 outb_reg0(dep, DP_IMR, dp_reg); /* Sets Interrupt Mask register */ 465 466 dp_reg = 0; 467 if (dep->de_flags & DEF_PROMISC) dp_reg |= RCR_AB | RCR_PRO | RCR_AM; 468 if (dep->de_flags & DEF_BROAD) dp_reg |= RCR_AB; 469 if (dep->de_flags & DEF_MULTI) dp_reg |= RCR_AM; 470 outb_reg0(dep, DP_RCR, dp_reg); /* Sets receive as requested */ 471 outb_reg0(dep, DP_TCR, TCR_NORMAL); /* Sets transmitter */ 472 473 outb_reg0(dep, DP_CR, CR_STA | CR_NO_DMA); /* Starts board */ 474 475 /* Initializes the send queue. */ 476 for (ix = 0; ix < dep->de_sendq_nr; ix += 1) 477 dep->de_sendq[ix].sq_filled = 0; 478 dep->de_sendq_head = dep->de_sendq_tail = 0; 479 480 /* Device specific functions */ 481 if (!dep->de_prog_IO) { 482 dep->de_user2nicf = mem_user2nic; 483 dep->de_nic2userf = mem_nic2user; 484 dep->de_getblockf = mem_getblock; 485 } else { 486 dep->de_user2nicf = pio_user2nic; 487 dep->de_nic2userf = pio_nic2user; 488 dep->de_getblockf = pio_getblock; 489 } 490 dep->de_recvf = ns_recv; 491 dep->de_sendf = ns_send; 492 dep->de_flagsf = ns_reinit; 493 dep->de_resetf = ns_reset; 494 dep->de_getstatsf = ns_stats; 495 dep->de_dumpstatsf = ns_dodump; 496 dep->de_interruptf = ns_interrupt; 497 } 498 499 #endif /* ENABLE_DP8390 */ 500 501 /** end 8390.c **/ 502