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