1 #include <assert.h> 2 /* 3 ** File: 8390.c May 02, 2000 4 ** 5 ** Author: Giovanni Falzoni <gfalzoni@inwind.it> 6 ** 7 ** This file contains an ethernet device driver for NICs 8 ** equipped with the National Semiconductor NS 8390 chip. 9 ** It has to be associated with the board specific driver. 10 ** Rewritten from Minix 2.0.0 ethernet driver dp8390.c 11 ** to extract the NS 8390 common functions. 12 */ 13 14 #include <minix/drivers.h> 15 #include <minix/com.h> 16 #include <net/gen/ether.h> 17 #include <net/gen/eth_io.h> 18 #include "dp.h" 19 20 #if (ENABLE_DP8390 == 1) 21 22 #define PIO16 0 /* NOTE: pio 16 functions missing */ 23 24 #include "8390.h" 25 26 #if 0 27 #define sys_nic2mem(srcOffs,dstProc,dstOffs,length) \ 28 sys_vircopy(SELF,dep->de_memsegm,(vir_bytes)(srcOffs),\ 29 (dstProc),D,(vir_bytes)(dstOffs),length) 30 #endif 31 #if 0 32 #define sys_user2nic_s(srcProc,grant,dstOffs,length) \ 33 sys_safecopyfrom((srcProc),(grant),0, \ 34 (vir_bytes)(dstOffs),length,dep->de_memsegm) 35 #endif 36 37 static char RdmaErrMsg[] = "remote dma failed to complete"; 38 39 /* 40 ** Name: void ns_rw_setup(dpeth_t *dep, int mode, int size, u16_t offset); 41 ** Function: Sets the board for reading/writing. 42 */ 43 static void ns_rw_setup(const dpeth_t *dep, int mode, int size, u16_t offset) 44 { 45 46 if (mode == CR_DM_RW) outb_reg0(dep, DP_ISR, ISR_RDC); 47 outb_reg0(dep, DP_RBCR0, size & 0xFF); 48 outb_reg0(dep, DP_RBCR1, (size >> 8) & 0xFF); 49 outb_reg0(dep, DP_RSAR0, offset & 0xFF); 50 outb_reg0(dep, DP_RSAR1, (offset >> 8) & 0xFF); 51 mode |= (CR_PS_P0 | CR_STA); 52 outb_reg0(dep, DP_CR, mode); 53 return; 54 } 55 56 /* 57 ** Name: void ns_start_xmit(dpeth_t *dep, int size, int pageno); 58 ** Function: Sets the board for for transmitting and fires it. 59 */ 60 static void ns_start_xmit(const dpeth_t * dep, int size, int pageno) 61 { 62 63 outb_reg0(dep, DP_TPSR, pageno); 64 outb_reg0(dep, DP_TBCR1, size >> 8); 65 outb_reg0(dep, DP_TBCR0, size & 0xFF); 66 outb_reg0(dep, DP_CR, CR_NO_DMA | CR_STA | CR_TXP); /* Fires transmission */ 67 return; 68 } 69 70 /* 71 ** Name: void mem_getblock(dpeth_t *dep, u16_t offset, 72 ** int size, void *dst) 73 ** Function: Reads a block of packet from board (shared memory). 74 */ 75 static void mem_getblock(dpeth_t *dep, u16_t offset, int size, void *dst) 76 { 77 panic("mem_getblock: not converted to safecopies"); 78 #if 0 79 sys_nic2mem(dep->de_linmem + offset, SELF, dst, size); 80 return; 81 #endif 82 } 83 84 /* 85 ** Name: void mem_nic2user(dpeth_t *dep, int pageno, int pktsize); 86 ** Function: Copies a packet from board to user area (shared memory). 87 */ 88 static void mem_nic2user(dpeth_t * dep, int pageno, int pktsize) 89 { 90 panic("mem_nic2user: not converted to safecopies"); 91 #if 0 92 phys_bytes offset; 93 iovec_dat_s_t *iovp = &dep->de_read_iovec; 94 int bytes, ix = 0; 95 96 97 /* Computes shared memory address (skipping receive header) */ 98 offset = pageno * DP_PAGESIZE + sizeof(dp_rcvhdr_t); 99 100 do { /* Reads chuncks of packet into user area */ 101 102 bytes = iovp->iod_iovec[ix].iov_size; /* Size of a chunck */ 103 if (bytes > pktsize) bytes = pktsize; 104 105 /* Reads from board to user area */ 106 if ((offset + bytes) > (dep->de_stoppage * DP_PAGESIZE)) { 107 108 /* Circular buffer wrap-around */ 109 bytes = dep->de_stoppage * DP_PAGESIZE - offset; 110 sys_nic2mem_s(dep->de_linmem + offset, iovp->iod_proc_nr, 111 iovp->iod_iovec[ix].iov_grant, bytes); 112 pktsize -= bytes; 113 phys_user += bytes; 114 bytes = iovp->iod_iovec[ix].iov_size - bytes; 115 if (bytes > pktsize) bytes = pktsize; 116 offset = dep->de_startpage * DP_PAGESIZE; 117 } 118 sys_nic2mem_s(dep->de_linmem + offset, iovp->iod_proc_nr, 119 iovp->iod_iovec[ix].iov_grant, bytes); 120 offset += bytes; 121 122 if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */ 123 dp_next_iovec(iovp); 124 ix = 0; 125 } 126 /* Till packet done */ 127 } while ((pktsize -= bytes) > 0); 128 return; 129 #endif 130 } 131 132 /* 133 ** Name: void mem_user2nic(dpeth_t *dep, int pageno, int pktsize) 134 ** Function: Copies a packet from user area to board (shared memory). 135 */ 136 static void mem_user2nic(dpeth_t *dep, int pageno, int pktsize) 137 { 138 #if 1 139 panic("mem_user2nic: not converted to safecopies"); 140 #else 141 phys_bytes offset, phys_user; 142 iovec_dat_s_t *iovp = &dep->de_write_iovec; 143 int bytes, ix = 0; 144 145 /* Computes shared memory address */ 146 offset = pageno * DP_PAGESIZE; 147 148 do { /* Reads chuncks of packet from user area */ 149 150 bytes = iovp->iod_iovec[ix].iov_size; /* Size of chunck */ 151 if (bytes > pktsize) bytes = pktsize; 152 153 /* Reads from user area to board (shared memory) */ 154 sys_user2nic_s(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_grant, 155 dep->de_linmem + offset, bytes); 156 offset += bytes; 157 158 if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */ 159 dp_next_iovec(iovp); 160 ix = 0; 161 } 162 /* Till packet done */ 163 } while ((pktsize -= bytes) > 0); 164 return; 165 #endif 166 } 167 168 /* 169 ** Name: void pio_getblock(dpeth_t *dep, u16_t offset, 170 ** int size, void *dst) 171 ** Function: Reads a block of packet from board (Prog. I/O). 172 */ 173 static void pio_getblock(dpeth_t *dep, u16_t offset, int size, void *dst) 174 { 175 176 /* Sets up board for reading */ 177 ns_rw_setup(dep, CR_DM_RR, size, offset); 178 179 #if PIO16 == 0 180 insb(dep->de_data_port, SELF, dst, size); 181 #else 182 if (dep->de_16bit == TRUE) { 183 insw(dep->de_data_port, dst, size); 184 } else { 185 insb(dep->de_data_port, dst, size); 186 } 187 #endif 188 return; 189 } 190 191 /* 192 ** Name: void pio_nic2user(dpeth_t *dep, int pageno, int pktsize) 193 ** Function: Copies a packet from board to user area (Prog. I/O). 194 */ 195 static void pio_nic2user(dpeth_t *dep, int pageno, int pktsize) 196 { 197 iovec_dat_s_t *iovp = &dep->de_read_iovec; 198 unsigned offset, iov_offset; int r, bytes, ix = 0; 199 200 /* Computes memory address (skipping receive header) */ 201 offset = pageno * DP_PAGESIZE + sizeof(dp_rcvhdr_t); 202 /* Sets up board for reading */ 203 ns_rw_setup(dep, CR_DM_RR, ((offset + pktsize) > (dep->de_stoppage * DP_PAGESIZE)) ? 204 (dep->de_stoppage * DP_PAGESIZE) - offset : pktsize, offset); 205 206 iov_offset= 0; 207 do { /* Reads chuncks of packet into user area */ 208 209 bytes = iovp->iod_iovec[ix].iov_size; /* Size of a chunck */ 210 if (bytes > pktsize) bytes = pktsize; 211 212 if ((offset + bytes) > (dep->de_stoppage * DP_PAGESIZE)) { 213 214 /* Circular buffer wrap-around */ 215 bytes = dep->de_stoppage * DP_PAGESIZE - offset; 216 r= sys_safe_insb(dep->de_data_port, iovp->iod_proc_nr, 217 iovp->iod_iovec[ix].iov_grant, iov_offset, bytes); 218 if (r != OK) { 219 panic("pio_nic2user: sys_safe_insb failed: %d", r); 220 } 221 pktsize -= bytes; 222 iov_offset += bytes; 223 bytes = iovp->iod_iovec[ix].iov_size - bytes; 224 if (bytes > pktsize) bytes = pktsize; 225 offset = dep->de_startpage * DP_PAGESIZE; 226 ns_rw_setup(dep, CR_DM_RR, pktsize, offset); 227 } 228 r= sys_safe_insb(dep->de_data_port, iovp->iod_proc_nr, 229 iovp->iod_iovec[ix].iov_grant, iov_offset, bytes); 230 if (r != OK) 231 panic("pio_nic2user: sys_safe_insb failed: %d", r); 232 offset += bytes; 233 234 if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */ 235 dp_next_iovec(iovp); 236 ix = 0; 237 } 238 iov_offset= 0; 239 /* Till packet done */ 240 } while ((pktsize -= bytes) > 0); 241 return; 242 } 243 244 /* 245 ** Name: void pio_user2nic(dpeth_t *dep, int pageno, int pktsize) 246 ** Function: Copies a packet from user area to board (Prog. I/O). 247 */ 248 static void pio_user2nic(dpeth_t *dep, int pageno, int pktsize) 249 { 250 iovec_dat_s_t *iovp = &dep->de_write_iovec; 251 int r, bytes, ix = 0; 252 253 /* Sets up board for writing */ 254 ns_rw_setup(dep, CR_DM_RW, pktsize, pageno * DP_PAGESIZE); 255 256 do { /* Reads chuncks of packet from user area */ 257 258 bytes = iovp->iod_iovec[ix].iov_size; /* Size of chunck */ 259 if (bytes > pktsize) bytes = pktsize; 260 r= sys_safe_outsb(dep->de_data_port, iovp->iod_proc_nr, 261 iovp->iod_iovec[ix].iov_grant, 0, bytes); 262 if (r != OK) 263 panic("pio_user2nic: sys_safe_outsb failed: %d", r); 264 265 if (++ix >= IOVEC_NR) { /* Next buffer of I/O vector */ 266 dp_next_iovec(iovp); 267 ix = 0; 268 } 269 /* Till packet done */ 270 } while ((pktsize -= bytes) > 0); 271 272 for (ix = 0; ix < 100; ix += 1) { 273 if (inb_reg0(dep, DP_ISR) & ISR_RDC) break; 274 } 275 if (ix == 100) { 276 panic("%s", RdmaErrMsg); 277 } 278 return; 279 } 280 281 /* 282 ** Name: void ns_stats(dpeth_t * dep) 283 ** Function: Updates counters reading from device 284 */ 285 static void ns_stats(dpeth_t * dep) 286 { 287 288 dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0); 289 dep->de_stat.ets_recvErr += inb_reg0(dep, DP_CNTR1); 290 dep->de_stat.ets_fifoOver += inb_reg0(dep, DP_CNTR2); 291 return; 292 } 293 294 /* 295 ** Name: void ns_dodump(dpeth_t * dep) 296 ** Function: Displays statistics (a request from F5 key). 297 */ 298 static void ns_dodump(dpeth_t * dep) 299 { 300 301 ns_stats(dep); /* Forces reading fo counters from board */ 302 return; 303 } 304 305 /* 306 ** Name: void ns_reinit(dpeth_t *dep) 307 ** Function: Updates receiver configuration. 308 */ 309 static void ns_reinit(dpeth_t * dep) 310 { 311 int dp_reg = 0; 312 313 if (dep->de_flags & DEF_PROMISC) dp_reg |= RCR_AB | RCR_PRO | RCR_AM; 314 if (dep->de_flags & DEF_BROAD) dp_reg |= RCR_AB; 315 if (dep->de_flags & DEF_MULTI) dp_reg |= RCR_AM; 316 outb_reg0(dep, DP_CR, CR_PS_P0); 317 outb_reg0(dep, DP_RCR, dp_reg); 318 return; 319 } 320 321 /* 322 ** Name: void ns_send(dpeth_t * dep, int from_int, int size) 323 ** Function: Transfers packet to device and starts sending. 324 */ 325 static void ns_send(dpeth_t * dep, int from_int, int size) 326 { 327 int queue; 328 329 if (queue = dep->de_sendq_head, dep->de_sendq[queue].sq_filled) { 330 if (from_int) panic("should not be sending "); 331 dep->de_send_s = size; 332 return; 333 } 334 (dep->de_user2nicf) (dep, dep->de_sendq[queue].sq_sendpage, size); 335 dep->bytes_Tx += (long) size; 336 dep->de_sendq[queue].sq_filled = TRUE; 337 dep->de_flags |= (DEF_XMIT_BUSY | DEF_ACK_SEND); 338 if (dep->de_sendq_tail == queue) { /* there it goes.. */ 339 ns_start_xmit(dep, size, dep->de_sendq[queue].sq_sendpage); 340 } else 341 dep->de_sendq[queue].sq_size = size; 342 343 if (++queue == dep->de_sendq_nr) queue = 0; 344 dep->de_sendq_head = queue; 345 dep->de_flags &= NOT(DEF_SENDING); 346 347 return; 348 } 349 350 /* 351 ** Name: void ns_reset(dpeth_t *dep) 352 ** Function: Resets device. 353 */ 354 static void ns_reset(dpeth_t * dep) 355 { 356 int ix; 357 358 /* Stop chip */ 359 outb_reg0(dep, DP_CR, CR_STP | CR_NO_DMA); 360 outb_reg0(dep, DP_RBCR0, 0); 361 outb_reg0(dep, DP_RBCR1, 0); 362 for (ix = 0; ix < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); ix += 1) 363 /* Do nothing */ ; 364 outb_reg0(dep, DP_TCR, TCR_1EXTERNAL | TCR_OFST); 365 outb_reg0(dep, DP_CR, CR_STA | CR_NO_DMA); 366 outb_reg0(dep, DP_TCR, TCR_NORMAL | TCR_OFST); 367 368 /* Acknowledge the ISR_RDC (remote dma) interrupt. */ 369 for (ix = 0; ix < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RDC) == 0); ix += 1) 370 /* Do nothing */ ; 371 outb_reg0(dep, DP_ISR, inb_reg0(dep, DP_ISR) & NOT(ISR_RDC)); 372 373 /* Reset the transmit ring. If we were transmitting a packet, we 374 * pretend that the packet is processed. Higher layers will 375 * retransmit if the packet wasn't actually sent. */ 376 dep->de_sendq_head = dep->de_sendq_tail = 0; 377 for (ix = 0; ix < dep->de_sendq_nr; ix++) 378 dep->de_sendq[ix].sq_filled = FALSE; 379 ns_send(dep, TRUE, dep->de_send_s); 380 return; 381 } 382 383 /* 384 ** Name: void ns_recv(dpeth_t *dep, int fromint, int size) 385 ** Function: Gets a packet from device 386 */ 387 static void ns_recv(dpeth_t *dep, int fromint, int size) 388 { 389 dp_rcvhdr_t header; 390 unsigned pageno, curr, next; 391 vir_bytes length; 392 int packet_processed = FALSE; 393 #ifdef ETH_IGN_PROTO 394 u16_t eth_type; 395 #endif 396 397 pageno = inb_reg0(dep, DP_BNRY) + 1; 398 if (pageno == dep->de_stoppage) pageno = dep->de_startpage; 399 400 do { 401 /* */ 402 outb_reg0(dep, DP_CR, CR_PS_P1); 403 curr = inb_reg1(dep, DP_CURR); 404 outb_reg0(dep, DP_CR, CR_PS_P0 | CR_NO_DMA | CR_STA); 405 406 if (curr == pageno) break; 407 408 (dep->de_getblockf) (dep, pageno * DP_PAGESIZE, sizeof(header), &header); 409 #ifdef ETH_IGN_PROTO 410 (dep->de_getblockf) (dep, pageno * DP_PAGESIZE + sizeof(header) + 2 * sizeof(ether_addr_t), sizeof(eth_type), ð_type); 411 #endif 412 length = (header.dr_rbcl | (header.dr_rbch << 8)) - sizeof(dp_rcvhdr_t); 413 next = header.dr_next; 414 415 if (length < ETH_MIN_PACK_SIZE || length > ETH_MAX_PACK_SIZE) { 416 printf("%s: packet with strange length arrived: %ld\n", 417 dep->de_name, length); 418 dep->de_stat.ets_recvErr += 1; 419 next = curr; 420 421 } else if (next < dep->de_startpage || next >= dep->de_stoppage) { 422 printf("%s: strange next page\n", dep->de_name); 423 dep->de_stat.ets_recvErr += 1; 424 next = curr; 425 426 #ifdef ETH_IGN_PROTO 427 } else if (eth_type == eth_ign_proto) { 428 /* Hack: ignore packets of a given protocol */ 429 static int first = TRUE; 430 if (first) { 431 first = FALSE; 432 printf("%s: dropping proto %04x packet\n", dep->de_name, ntohs(eth_ign_proto)); 433 } 434 next = curr; 435 #endif 436 } else if (header.dr_status & RSR_FO) { 437 /* This is very serious, issue a warning and reset buffers */ 438 printf("%s: fifo overrun, resetting receive buffer\n", dep->de_name); 439 dep->de_stat.ets_fifoOver += 1; 440 next = curr; 441 442 } else if ((header.dr_status & RSR_PRX) && (dep->de_flags & DEF_ENABLED)) { 443 444 if (!(dep->de_flags & DEF_READING)) break; 445 446 (dep->de_nic2userf) (dep, pageno, length); 447 dep->de_read_s = length; 448 dep->de_flags |= DEF_ACK_RECV; 449 dep->de_flags &= NOT(DEF_READING); 450 packet_processed = TRUE; 451 } 452 dep->bytes_Rx += (long) length; 453 dep->de_stat.ets_packetR += 1; 454 outb_reg0(dep, DP_BNRY, (next == dep->de_startpage ? dep->de_stoppage : next) - 1); 455 pageno = next; 456 457 } while (!packet_processed); 458 #if 0 459 if ((dep->de_flags & (DEF_READING | DEF_STOPPED)) == (DEF_READING | DEF_STOPPED)) 460 /* The chip is stopped, and all arrived packets delivered */ 461 (*dep->de_resetf) (dep); 462 dep->de_flags &= NOT(DEF_STOPPED); 463 #endif 464 return; 465 } 466 467 /* 468 ** Name: void ns_interrupt(dpeth_t * dep) 469 ** Function: Handles interrupt. 470 */ 471 static void ns_interrupt(dpeth_t * dep) 472 { 473 int isr, tsr; 474 int queue; 475 476 while ((isr = inb_reg0(dep, DP_ISR)) != 0) { 477 478 outb_reg0(dep, DP_ISR, isr); 479 if (isr & (ISR_PTX | ISR_TXE)) { 480 481 tsr = inb_reg0(dep, DP_TSR); 482 if (tsr & TSR_PTX) { 483 dep->de_stat.ets_packetT++; 484 } 485 if (tsr & TSR_COL) dep->de_stat.ets_collision++; 486 if (tsr & (TSR_ABT | TSR_FU)) { 487 dep->de_stat.ets_fifoUnder++; 488 } 489 if ((isr & ISR_TXE) || (tsr & (TSR_CRS | TSR_CDH | TSR_OWC))) { 490 printf("%s: got send Error (0x%02X)\n", dep->de_name, tsr); 491 dep->de_stat.ets_sendErr++; 492 } 493 queue = dep->de_sendq_tail; 494 495 if (!(dep->de_sendq[queue].sq_filled)) { /* Hardware bug? */ 496 printf("%s: transmit interrupt, but not sending\n", dep->de_name); 497 continue; 498 } 499 dep->de_sendq[queue].sq_filled = FALSE; 500 if (++queue == dep->de_sendq_nr) queue = 0; 501 dep->de_sendq_tail = queue; 502 if (dep->de_sendq[queue].sq_filled) { 503 ns_start_xmit(dep, dep->de_sendq[queue].sq_size, 504 dep->de_sendq[queue].sq_sendpage); 505 } 506 if (dep->de_flags & DEF_SENDING) { 507 ns_send(dep, TRUE, dep->de_send_s); 508 } 509 } 510 if (isr & ISR_PRX) { 511 ns_recv(dep, TRUE, 0); 512 } 513 if (isr & ISR_RXE) { 514 printf("%s: got recv Error (0x%04X)\n", dep->de_name, inb_reg0(dep, DP_RSR)); 515 dep->de_stat.ets_recvErr++; 516 } 517 if (isr & ISR_CNT) { 518 dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0); 519 dep->de_stat.ets_recvErr += inb_reg0(dep, DP_CNTR1); 520 dep->de_stat.ets_fifoOver += inb_reg0(dep, DP_CNTR2); 521 } 522 if (isr & ISR_OVW) { 523 printf("%s: got overwrite warning\n", dep->de_name); 524 } 525 if (isr & ISR_RDC) { 526 /* Nothing to do */ 527 } 528 if (isr & ISR_RST) { 529 /* This means we got an interrupt but the ethernet 530 * chip is shutdown. We set the flag DEF_STOPPED, and 531 * continue processing arrived packets. When the 532 * receive buffer is empty, we reset the dp8390. */ 533 printf("%s: network interface stopped\n", dep->de_name); 534 dep->de_flags |= DEF_STOPPED; 535 break; 536 } 537 } 538 if ((dep->de_flags & (DEF_READING | DEF_STOPPED)) == (DEF_READING | DEF_STOPPED)) { 539 540 /* The chip is stopped, and all arrived packets delivered */ 541 ns_reset(dep); 542 dep->de_flags &= NOT(DEF_STOPPED); 543 } 544 return; 545 } 546 547 /* 548 ** Name: void ns_init(dpeth_t *dep) 549 ** Function: Initializes the NS 8390 550 */ 551 void ns_init(dpeth_t * dep) 552 { 553 int dp_reg; 554 int ix; 555 556 /* NS8390 initialization (as recommended in National Semiconductor specs) */ 557 outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_NO_DMA); /* 0x21 */ 558 #if PIO16 == 0 559 outb_reg0(dep, DP_DCR, (DCR_BYTEWIDE | DCR_LTLENDIAN | DCR_8BYTES | DCR_BMS)); 560 #else 561 outb_reg0(dep, DP_DCR, (((dep->de_16bit) ? DCR_WORDWIDE : DCR_BYTEWIDE) | 562 DCR_LTLENDIAN | DCR_8BYTES | DCR_BMS)); 563 #endif 564 outb_reg0(dep, DP_RBCR0, 0); 565 outb_reg0(dep, DP_RBCR1, 0); 566 outb_reg0(dep, DP_RCR, RCR_MON); /* Sets Monitor mode */ 567 outb_reg0(dep, DP_TCR, TCR_INTERNAL); /* Sets Loopback mode 1 */ 568 outb_reg0(dep, DP_PSTART, dep->de_startpage); 569 outb_reg0(dep, DP_PSTOP, dep->de_stoppage); 570 outb_reg0(dep, DP_BNRY, dep->de_stoppage - 1); 571 outb_reg0(dep, DP_ISR, 0xFF); /* Clears Interrupt Status Register */ 572 outb_reg0(dep, DP_IMR, 0); /* Clears Interrupt Mask Register */ 573 574 /* Copies station address in page 1 registers */ 575 outb_reg0(dep, DP_CR, CR_PS_P1 | CR_NO_DMA); /* Selects Page 1 */ 576 for (ix = 0; ix < SA_ADDR_LEN; ix += 1) /* Initializes address */ 577 outb_reg1(dep, DP_PAR0 + ix, dep->de_address.ea_addr[ix]); 578 for (ix = DP_MAR0; ix <= DP_MAR7; ix += 1) /* Initializes address */ 579 outb_reg1(dep, ix, 0xFF); 580 581 outb_reg1(dep, DP_CURR, dep->de_startpage); 582 outb_reg1(dep, DP_CR, CR_PS_P0 | CR_NO_DMA); /* Selects Page 0 */ 583 584 inb_reg0(dep, DP_CNTR0); /* Resets counters by reading them */ 585 inb_reg0(dep, DP_CNTR1); 586 inb_reg0(dep, DP_CNTR2); 587 588 dp_reg = IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE | IMR_OVWE | IMR_CNTE; 589 outb_reg0(dep, DP_ISR, 0xFF); /* Clears Interrupt Status Register */ 590 outb_reg0(dep, DP_IMR, dp_reg); /* Sets Interrupt Mask register */ 591 592 dp_reg = 0; 593 if (dep->de_flags & DEF_PROMISC) dp_reg |= RCR_AB | RCR_PRO | RCR_AM; 594 if (dep->de_flags & DEF_BROAD) dp_reg |= RCR_AB; 595 if (dep->de_flags & DEF_MULTI) dp_reg |= RCR_AM; 596 outb_reg0(dep, DP_RCR, dp_reg); /* Sets receive as requested */ 597 outb_reg0(dep, DP_TCR, TCR_NORMAL); /* Sets transmitter */ 598 599 outb_reg0(dep, DP_CR, CR_STA | CR_NO_DMA); /* Starts board */ 600 601 /* Initializes the send queue. */ 602 for (ix = 0; ix < dep->de_sendq_nr; ix += 1) 603 dep->de_sendq[ix].sq_filled = 0; 604 dep->de_sendq_head = dep->de_sendq_tail = 0; 605 606 /* Device specific functions */ 607 if (!dep->de_prog_IO) { 608 dep->de_user2nicf = mem_user2nic; 609 dep->de_nic2userf = mem_nic2user; 610 dep->de_getblockf = mem_getblock; 611 } else { 612 #if PIO16 == 0 613 dep->de_user2nicf = pio_user2nic; 614 dep->de_nic2userf = pio_nic2user; 615 dep->de_getblockf = pio_getblock; 616 #else 617 #error Missing I/O functions for pio 16 bits 618 #endif 619 } 620 dep->de_recvf = ns_recv; 621 dep->de_sendf = ns_send; 622 dep->de_flagsf = ns_reinit; 623 dep->de_resetf = ns_reset; 624 dep->de_getstatsf = ns_stats; 625 dep->de_dumpstatsf = ns_dodump; 626 dep->de_interruptf = ns_interrupt; 627 628 return; /* Done */ 629 } 630 631 #if PIO16 == 1 632 633 /* 634 ** Name: void dp_pio16_user2nic(dpeth_t *dep, int pageno, int pktsize) 635 ** Function: Copies a packet from user area to board (Prog. I/O, 16bits). 636 */ 637 static void dp_pio16_user2nic(dpeth_t *dep, int pageno, int pktsize) 638 { 639 u8_t two_bytes[2]; 640 phys_bytes phys_user, phys_2bytes = vir2phys(two_bytes); 641 vir_bytes ecount = (pktsize + 1) & NOT(0x0001); 642 int bytes, ix = 0, odd_byte = 0; 643 iovec_dat_t *iovp = &dep->de_write_iovec; 644 645 outb_reg0(dep, DP_ISR, ISR_RDC); 646 dp_read_setup(dep, ecount, pageno * DP_PAGESIZE); 647 648 do { 649 bytes = iovp->iod_iovec[ix].iov_size; 650 if (bytes > pktsize) bytes = pktsize; 651 652 phys_user = numap(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_addr, bytes); 653 if (!phys_user) panic(UmapErrMsg); 654 655 if (odd_byte) { 656 phys_copy(phys_user, phys_2bytes + 1, (phys_bytes) 1); 657 out_word(dep->de_data_port, *(u16_t *)two_bytes); 658 pktsize--; 659 bytes--; 660 phys_user++; 661 odd_byte = 0; 662 if (!bytes) continue; 663 } 664 ecount = bytes & NOT(0x0001); 665 if (ecount != 0) { 666 phys_outsw(dep->de_data_port, phys_user, ecount); 667 pktsize -= ecount; 668 bytes -= ecount; 669 phys_user += ecount; 670 } 671 if (bytes) { 672 phys_copy(phys_user, phys_2bytes, (phys_bytes) 1); 673 pktsize--; 674 bytes--; 675 phys_user++; 676 odd_byte = 1; 677 } 678 if (++ix >= IOVEC_NR) { /* Next buffer of I/O vector */ 679 dp_next_iovec(iovp); 680 ix = 0; 681 } 682 683 } while (bytes > 0); 684 685 if (odd_byte) out_word(dep->de_data_port, *(u16_t *) two_bytes); 686 for (ix = 0; ix < 100; ix++) { 687 if (inb_reg0(dep, DP_ISR) & ISR_RDC) break; 688 } 689 if (ix == 100) { 690 panic(RdmaErrMsg); 691 } 692 return; 693 } 694 695 /* 696 ** Name: void dp_pio16_nic2user(dpeth_t *dep, int pageno, int pktsize) 697 ** Function: Copies a packet from board to user area (Prog. I/O, 16bits). 698 */ 699 static void dp_pio16_nic2user(dpeth_t * dep, int nic_addr, int count) 700 { 701 phys_bytes phys_user; 702 vir_bytes ecount; 703 int bytes, i; 704 u8_t two_bytes[2]; 705 phys_bytes phys_2bytes; 706 int odd_byte; 707 708 ecount = (count + 1) & ~1; 709 phys_2bytes = vir2phys(two_bytes); 710 odd_byte = 0; 711 712 dp_read_setup(dep, ecount, nic_addr); 713 714 i = 0; 715 while (count > 0) { 716 if (i >= IOVEC_NR) { 717 dp_next_iovec(iovp); 718 i = 0; 719 continue; 720 } 721 bytes = iovp->iod_iovec[i].iov_size; 722 if (bytes > count) bytes = count; 723 724 phys_user = numap(iovp->iod_proc_nr, 725 iovp->iod_iovec[i].iov_addr, bytes); 726 if (!phys_user) panic(UmapErrMsg); 727 if (odd_byte) { 728 phys_copy(phys_2bytes + 1, phys_user, (phys_bytes) 1); 729 count--; 730 bytes--; 731 phys_user++; 732 odd_byte = 0; 733 if (!bytes) continue; 734 } 735 ecount = bytes & ~1; 736 if (ecount != 0) { 737 phys_insw(dep->de_data_port, phys_user, ecount); 738 count -= ecount; 739 bytes -= ecount; 740 phys_user += ecount; 741 } 742 if (bytes) { 743 *(u16_t *) two_bytes = in_word(dep->de_data_port); 744 phys_copy(phys_2bytes, phys_user, (phys_bytes) 1); 745 count--; 746 bytes--; 747 phys_user++; 748 odd_byte = 1; 749 } 750 } 751 return; 752 } 753 754 #endif /* PIO16 == 1 */ 755 756 #endif /* ENABLE_DP8390 */ 757 758 /** end 8390.c **/ 759