00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 #include "../drivers.h"
00050
00051 #include <stdlib.h>
00052 #include <minix/com.h>
00053 #include <net/hton.h>
00054 #include <net/gen/ether.h>
00055 #include <net/gen/eth_io.h>
00056 #include "assert.h"
00057
00058 #include "local.h"
00059 #include "dp8390.h"
00060
00061 #define DE_PORT_NR 3
00062
00063 static dpeth_t de_table[DE_PORT_NR];
00064 static u16_t eth_ign_proto;
00065 static char *progname;
00066
00067
00068 typedef struct dp_conf
00069 {
00070 port_t dpc_port;
00071 int dpc_irq;
00072 phys_bytes dpc_mem;
00073 char *dpc_envvar;
00074 } dp_conf_t;
00075
00076 dp_conf_t dp_conf[]=
00077 {
00078
00079 { 0x280, 3, 0xD0000, "DPETH0" },
00080 { 0x300, 5, 0xC8000, "DPETH1" },
00081 { 0x380, 10, 0xD8000, "DPETH2" },
00082 };
00083
00084
00085
00086
00087 extern int ___dummy[DE_PORT_NR == sizeof(dp_conf)/sizeof(dp_conf[0]) ? 1 : -1];
00088
00089
00090 #if !ENABLE_WDETH
00091 #define wdeth_probe(dep) (0)
00092 #endif
00093 #if !ENABLE_NE2000
00094 #define ne_probe(dep) (0)
00095 #endif
00096 #if !ENABLE_3C503
00097 #define el2_probe(dep) (0)
00098 #endif
00099
00100
00101
00102
00103
00104 #define CR_EXTRA CR_STA
00105
00106 #if ENABLE_PCI
00107 _PROTOTYPE( static void pci_conf, (void) );
00108 #endif
00109 _PROTOTYPE( static void do_vwrite, (message *mp, int from_int,
00110 int vectored) );
00111 _PROTOTYPE( static void do_vread, (message *mp, int vectored) );
00112 _PROTOTYPE( static void do_init, (message *mp) );
00113 _PROTOTYPE( static void do_int, (dpeth_t *dep) );
00114 _PROTOTYPE( static void do_getstat, (message *mp) );
00115 _PROTOTYPE( static void do_getname, (message *mp) );
00116 _PROTOTYPE( static void do_stop, (message *mp) );
00117 _PROTOTYPE( static void dp_init, (dpeth_t *dep) );
00118 _PROTOTYPE( static void dp_confaddr, (dpeth_t *dep) );
00119 _PROTOTYPE( static void dp_reinit, (dpeth_t *dep) );
00120 _PROTOTYPE( static void dp_reset, (dpeth_t *dep) );
00121 _PROTOTYPE( static void dp_check_ints, (dpeth_t *dep) );
00122 _PROTOTYPE( static void dp_recv, (dpeth_t *dep) );
00123 _PROTOTYPE( static void dp_send, (dpeth_t *dep) );
00124 _PROTOTYPE( static void dp8390_stop, (void) );
00125 _PROTOTYPE( static void dp_getblock, (dpeth_t *dep, int page,
00126 size_t offset, size_t size, void *dst) );
00127 _PROTOTYPE( static void dp_pio8_getblock, (dpeth_t *dep, int page,
00128 size_t offset, size_t size, void *dst) );
00129 _PROTOTYPE( static void dp_pio16_getblock, (dpeth_t *dep, int page,
00130 size_t offset, size_t size, void *dst) );
00131 _PROTOTYPE( static int dp_pkt2user, (dpeth_t *dep, int page,
00132 int length) );
00133 _PROTOTYPE( static void dp_user2nic, (dpeth_t *dep, iovec_dat_t *iovp,
00134 vir_bytes offset, int nic_addr, vir_bytes count) );
00135 _PROTOTYPE( static void dp_pio8_user2nic, (dpeth_t *dep,
00136 iovec_dat_t *iovp, vir_bytes offset,
00137 int nic_addr, vir_bytes count) );
00138 _PROTOTYPE( static void dp_pio16_user2nic, (dpeth_t *dep,
00139 iovec_dat_t *iovp, vir_bytes offset,
00140 int nic_addr, vir_bytes count) );
00141 _PROTOTYPE( static void dp_nic2user, (dpeth_t *dep, int nic_addr,
00142 iovec_dat_t *iovp, vir_bytes offset, vir_bytes count) );
00143 _PROTOTYPE( static void dp_pio8_nic2user, (dpeth_t *dep, int nic_addr,
00144 iovec_dat_t *iovp, vir_bytes offset, vir_bytes count) );
00145 _PROTOTYPE( static void dp_pio16_nic2user, (dpeth_t *dep, int nic_addr,
00146 iovec_dat_t *iovp, vir_bytes offset, vir_bytes count) );
00147 _PROTOTYPE( static void dp_next_iovec, (iovec_dat_t *iovp) );
00148 _PROTOTYPE( static void conf_hw, (dpeth_t *dep) );
00149 _PROTOTYPE( static void update_conf, (dpeth_t *dep, dp_conf_t *dcp) );
00150 _PROTOTYPE( static int calc_iovec_size, (iovec_dat_t *iovp) );
00151 _PROTOTYPE( static void reply, (dpeth_t *dep, int err, int may_block) );
00152 _PROTOTYPE( static void mess_reply, (message *req, message *reply) );
00153 _PROTOTYPE( static void get_userdata, (int user_proc,
00154 vir_bytes user_addr, vir_bytes count, void *loc_addr) );
00155 _PROTOTYPE( static void put_userdata, (int user_proc,
00156 vir_bytes user_addr, vir_bytes count, void *loc_addr) );
00157 _PROTOTYPE( static void insb, (port_t port, void *buf, size_t size) );
00158 _PROTOTYPE( static void insw, (port_t port, void *buf, size_t size) );
00159 _PROTOTYPE( static void do_vir_insb, (port_t port, int proc,
00160 vir_bytes buf, size_t size) );
00161 _PROTOTYPE( static void do_vir_insw, (port_t port, int proc,
00162 vir_bytes buf, size_t size) );
00163 _PROTOTYPE( static void do_vir_outsb, (port_t port, int proc,
00164 vir_bytes buf, size_t size) );
00165 _PROTOTYPE( static void do_vir_outsw, (port_t port, int proc,
00166 vir_bytes buf, size_t size) );
00167
00168
00169
00170
00171 int main(int argc, char *argv[])
00172 {
00173 message m;
00174 int i, irq, r, tasknr;
00175 dpeth_t *dep;
00176 long v;
00177
00178 if (argc < 1)
00179 {
00180 panic("DP8390",
00181 "A head which at this time has no name", NO_NUM);
00182 }
00183 (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
00184
00185 env_setargs(argc, argv);
00186
00187 for (i= 0, dep= de_table; i<DE_PORT_NR; i++, dep++)
00188 {
00189 strcpy(dep->de_name, "dp8390#0");
00190 dep->de_name[7] += i;
00191 }
00192
00193 v= 0;
00194 (void) env_parse("ETH_IGN_PROTO", "x", 0, &v, 0x0000L, 0xFFFFL);
00195 eth_ign_proto= htons((u16_t) v);
00196
00197
00198 r = _pm_findproc("inet", &tasknr);
00199 if (r == OK)
00200 notify(tasknr);
00201
00202 while (TRUE)
00203 {
00204 if ((r= receive(ANY, &m)) != OK)
00205 panic("", "dp8390: receive failed", r);
00206
00207 switch (m.m_type)
00208 {
00209 case DEV_PING: notify(m.m_source); continue;
00210 case DL_WRITE: do_vwrite(&m, FALSE, FALSE); break;
00211 case DL_WRITEV: do_vwrite(&m, FALSE, TRUE); break;
00212 case DL_READ: do_vread(&m, FALSE); break;
00213 case DL_READV: do_vread(&m, TRUE); break;
00214 case DL_INIT: do_init(&m); break;
00215 case DL_GETSTAT: do_getstat(&m); break;
00216 case DL_GETNAME: do_getname(&m); break;
00217 case DL_STOP: do_stop(&m); break;
00218 case HARD_INT:
00219 for (i= 0, dep= &de_table[0]; i<DE_PORT_NR; i++, dep++)
00220 {
00221 if (dep->de_mode != DEM_ENABLED)
00222 continue;
00223 assert(dep->de_flags & DEF_ENABLED);
00224 irq= dep->de_irq;
00225 assert(irq >= 0 && irq < NR_IRQ_VECTORS);
00226 if (dep->de_int_pending || 1)
00227 {
00228 dep->de_int_pending= 0;
00229 dp_check_ints(dep);
00230 do_int(dep);
00231 r= sys_irqenable(&dep->de_hook);
00232 if (r != OK)
00233 {
00234 panic("DP8390",
00235 "unable enable interrupts", r);
00236 }
00237 }
00238 }
00239 break;
00240 case SYS_SIG: {
00241 sigset_t sigset = m.NOTIFY_ARG;
00242 if (sigismember(&sigset, SIGKSTOP)) dp8390_stop();
00243 break;
00244 }
00245 case SYN_ALARM:
00246 printf("dp8390: strange, got SYN_ALARM\n");
00247 break;
00248 case PROC_EVENT:
00249 break;
00250 default:
00251 panic("", "dp8390: illegal message", m.m_type);
00252 }
00253 }
00254 }
00255
00256 #if 0
00257
00258
00259
00260 void dp8390_dump()
00261 {
00262 dpeth_t *dep;
00263 int i, isr;
00264
00265 printf("\n");
00266 for (i= 0, dep = &de_table[0]; i<DE_PORT_NR; i++, dep++)
00267 {
00268 #if XXX
00269 if (dep->de_mode == DEM_DISABLED)
00270 printf("dp8390 port %d is disabled\n", i);
00271 else if (dep->de_mode == DEM_SINK)
00272 printf("dp8390 port %d is in sink mode\n", i);
00273 #endif
00274
00275 if (dep->de_mode != DEM_ENABLED)
00276 continue;
00277
00278 printf("dp8390 statistics of port %d:\n", i);
00279
00280 printf("recvErr :%8ld\t", dep->de_stat.ets_recvErr);
00281 printf("sendErr :%8ld\t", dep->de_stat.ets_sendErr);
00282 printf("OVW :%8ld\n", dep->de_stat.ets_OVW);
00283
00284 printf("CRCerr :%8ld\t", dep->de_stat.ets_CRCerr);
00285 printf("frameAll :%8ld\t", dep->de_stat.ets_frameAll);
00286 printf("missedP :%8ld\n", dep->de_stat.ets_missedP);
00287
00288 printf("packetR :%8ld\t", dep->de_stat.ets_packetR);
00289 printf("packetT :%8ld\t", dep->de_stat.ets_packetT);
00290 printf("transDef :%8ld\n", dep->de_stat.ets_transDef);
00291
00292 printf("collision :%8ld\t", dep->de_stat.ets_collision);
00293 printf("transAb :%8ld\t", dep->de_stat.ets_transAb);
00294 printf("carrSense :%8ld\n", dep->de_stat.ets_carrSense);
00295
00296 printf("fifoUnder :%8ld\t", dep->de_stat.ets_fifoUnder);
00297 printf("fifoOver :%8ld\t", dep->de_stat.ets_fifoOver);
00298 printf("CDheartbeat:%8ld\n", dep->de_stat.ets_CDheartbeat);
00299
00300 printf("OWC :%8ld\t", dep->de_stat.ets_OWC);
00301
00302 isr= inb_reg0(dep, DP_ISR);
00303 printf("dp_isr = 0x%x + 0x%x, de_flags = 0x%x\n", isr,
00304 inb_reg0(dep, DP_ISR), dep->de_flags);
00305 }
00306 }
00307 #endif
00308
00309
00310
00311
00312 static void dp8390_stop()
00313 {
00314 message mess;
00315 int i;
00316
00317 for (i= 0; i<DE_PORT_NR; i++)
00318 {
00319 if (de_table[i].de_mode != DEM_ENABLED)
00320 continue;
00321 mess.m_type= DL_STOP;
00322 mess.DL_PORT= i;
00323 do_stop(&mess);
00324 }
00325 }
00326
00327 #if ENABLE_PCI
00328
00329
00330
00331 static void pci_conf()
00332 {
00333 int i, h;
00334 char *envvar;
00335 struct dpeth *dep;
00336 static char envfmt[] = "*:d.d.d";
00337 long v;
00338 static int first_time= 1;
00339
00340 if (!first_time)
00341 return;
00342 first_time= 0;
00343
00344 for (i= 0, dep= de_table; i<DE_PORT_NR; i++, dep++)
00345 {
00346 envvar= dp_conf[i].dpc_envvar;
00347 if (!(dep->de_pci= env_prefix(envvar, "pci")))
00348 continue;
00349 v= 0;
00350 (void) env_parse(envvar, envfmt, 1, &v, 0, 255);
00351 dep->de_pcibus= v;
00352 v= 0;
00353 (void) env_parse(envvar, envfmt, 2, &v, 0, 255);
00354 dep->de_pcidev= v;
00355 v= 0;
00356 (void) env_parse(envvar, envfmt, 3, &v, 0, 255);
00357 dep->de_pcifunc= v;
00358 }
00359
00360 for (h= 1; h >= 0; h--) {
00361 for (i= 0, dep= de_table; i<DE_PORT_NR; i++, dep++)
00362 {
00363 if (!dep->de_pci)
00364 continue;
00365 if (((dep->de_pcibus | dep->de_pcidev |
00366 dep->de_pcifunc) != 0) != h)
00367 {
00368 continue;
00369 }
00370 if (!rtl_probe(dep))
00371 dep->de_pci= -1;
00372 }
00373 }
00374 }
00375 #endif
00376
00377
00378
00379
00380 static void do_vwrite(mp, from_int, vectored)
00381 message *mp;
00382 int from_int;
00383 int vectored;
00384 {
00385 int port, count, size;
00386 int sendq_head;
00387 dpeth_t *dep;
00388
00389 port = mp->DL_PORT;
00390 count = mp->DL_COUNT;
00391 if (port < 0 || port >= DE_PORT_NR)
00392 panic("", "dp8390: illegal port", port);
00393 dep= &de_table[port];
00394 dep->de_client= mp->DL_PROC;
00395
00396 if (dep->de_mode == DEM_SINK)
00397 {
00398 assert(!from_int);
00399 dep->de_flags |= DEF_PACK_SEND;
00400 reply(dep, OK, FALSE);
00401 return;
00402 }
00403 assert(dep->de_mode == DEM_ENABLED);
00404 assert(dep->de_flags & DEF_ENABLED);
00405 if (dep->de_flags & DEF_SEND_AVAIL)
00406 panic("", "dp8390: send already in progress", NO_NUM);
00407
00408 sendq_head= dep->de_sendq_head;
00409 if (dep->de_sendq[sendq_head].sq_filled)
00410 {
00411 if (from_int)
00412 panic("", "dp8390: should not be sending\n", NO_NUM);
00413 dep->de_sendmsg= *mp;
00414 dep->de_flags |= DEF_SEND_AVAIL;
00415 reply(dep, OK, FALSE);
00416 return;
00417 }
00418 assert(!(dep->de_flags & DEF_PACK_SEND));
00419
00420 if (vectored)
00421 {
00422 get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
00423 (count > IOVEC_NR ? IOVEC_NR : count) *
00424 sizeof(iovec_t), dep->de_write_iovec.iod_iovec);
00425 dep->de_write_iovec.iod_iovec_s = count;
00426 dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
00427 dep->de_write_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
00428
00429 dep->de_tmp_iovec = dep->de_write_iovec;
00430 size = calc_iovec_size(&dep->de_tmp_iovec);
00431 }
00432 else
00433 {
00434 dep->de_write_iovec.iod_iovec[0].iov_addr =
00435 (vir_bytes) mp->DL_ADDR;
00436 dep->de_write_iovec.iod_iovec[0].iov_size =
00437 mp->DL_COUNT;
00438 dep->de_write_iovec.iod_iovec_s = 1;
00439 dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
00440 dep->de_write_iovec.iod_iovec_addr = 0;
00441 size= mp->DL_COUNT;
00442 }
00443 if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED)
00444 {
00445 panic("", "dp8390: invalid packet size", size);
00446 }
00447 (dep->de_user2nicf)(dep, &dep->de_write_iovec, 0,
00448 dep->de_sendq[sendq_head].sq_sendpage * DP_PAGESIZE,
00449 size);
00450 dep->de_sendq[sendq_head].sq_filled= TRUE;
00451 if (dep->de_sendq_tail == sendq_head)
00452 {
00453 outb_reg0(dep, DP_TPSR, dep->de_sendq[sendq_head].sq_sendpage);
00454 outb_reg0(dep, DP_TBCR1, size >> 8);
00455 outb_reg0(dep, DP_TBCR0, size & 0xff);
00456 outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);
00457 }
00458 else
00459 dep->de_sendq[sendq_head].sq_size= size;
00460
00461 if (++sendq_head == dep->de_sendq_nr)
00462 sendq_head= 0;
00463 assert(sendq_head < SENDQ_NR);
00464 dep->de_sendq_head= sendq_head;
00465
00466 dep->de_flags |= DEF_PACK_SEND;
00467
00468
00469
00470
00471 if (from_int)
00472 return;
00473 reply(dep, OK, FALSE);
00474
00475 assert(dep->de_mode == DEM_ENABLED);
00476 assert(dep->de_flags & DEF_ENABLED);
00477 }
00478
00479
00480
00481
00482 static void do_vread(mp, vectored)
00483 message *mp;
00484 int vectored;
00485 {
00486 int port, count;
00487 int size;
00488 dpeth_t *dep;
00489
00490 port = mp->DL_PORT;
00491 count = mp->DL_COUNT;
00492 if (port < 0 || port >= DE_PORT_NR)
00493 panic("", "dp8390: illegal port", port);
00494 dep= &de_table[port];
00495 dep->de_client= mp->DL_PROC;
00496 if (dep->de_mode == DEM_SINK)
00497 {
00498 reply(dep, OK, FALSE);
00499 return;
00500 }
00501 assert(dep->de_mode == DEM_ENABLED);
00502 assert(dep->de_flags & DEF_ENABLED);
00503
00504 if(dep->de_flags & DEF_READING)
00505 panic("", "dp8390: read already in progress", NO_NUM);
00506
00507 if (vectored)
00508 {
00509 get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
00510 (count > IOVEC_NR ? IOVEC_NR : count) *
00511 sizeof(iovec_t), dep->de_read_iovec.iod_iovec);
00512 dep->de_read_iovec.iod_iovec_s = count;
00513 dep->de_read_iovec.iod_proc_nr = mp->DL_PROC;
00514 dep->de_read_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
00515
00516 dep->de_tmp_iovec = dep->de_read_iovec;
00517 size= calc_iovec_size(&dep->de_tmp_iovec);
00518 }
00519 else
00520 {
00521 dep->de_read_iovec.iod_iovec[0].iov_addr =
00522 (vir_bytes) mp->DL_ADDR;
00523 dep->de_read_iovec.iod_iovec[0].iov_size =
00524 mp->DL_COUNT;
00525 dep->de_read_iovec.iod_iovec_s = 1;
00526 dep->de_read_iovec.iod_proc_nr = mp->DL_PROC;
00527 dep->de_read_iovec.iod_iovec_addr = 0;
00528 size= count;
00529 }
00530 if (size < ETH_MAX_PACK_SIZE_TAGGED)
00531 panic("", "dp8390: wrong packet size", size);
00532 dep->de_flags |= DEF_READING;
00533
00534 dp_recv(dep);
00535
00536 if ((dep->de_flags & (DEF_READING|DEF_STOPPED)) ==
00537 (DEF_READING|DEF_STOPPED))
00538 {
00539
00540
00541
00542 dp_reset(dep);
00543 }
00544 reply(dep, OK, FALSE);
00545 }
00546
00547
00548
00549
00550 static void do_init(mp)
00551 message *mp;
00552 {
00553 int port;
00554 dpeth_t *dep;
00555 message reply_mess;
00556
00557 #if ENABLE_PCI
00558 pci_conf();
00559 #endif
00560
00561 port = mp->DL_PORT;
00562 if (port < 0 || port >= DE_PORT_NR)
00563 {
00564 reply_mess.m_type= DL_INIT_REPLY;
00565 reply_mess.m3_i1= ENXIO;
00566 mess_reply(mp, &reply_mess);
00567 return;
00568 }
00569 dep= &de_table[port];
00570 if (dep->de_mode == DEM_DISABLED)
00571 {
00572
00573 conf_hw(dep);
00574 if (dep->de_mode == DEM_DISABLED)
00575 {
00576
00577 reply_mess.m_type= DL_INIT_REPLY;
00578 reply_mess.m3_i1= ENXIO;
00579 mess_reply(mp, &reply_mess);
00580 return;
00581 }
00582 if (dep->de_mode == DEM_ENABLED)
00583 dp_init(dep);
00584 }
00585
00586 if (dep->de_mode == DEM_SINK)
00587 {
00588 strncpy((char *) dep->de_address.ea_addr, "ZDP", 6);
00589 dep->de_address.ea_addr[5] = port;
00590 dp_confaddr(dep);
00591 reply_mess.m_type = DL_INIT_REPLY;
00592 reply_mess.m3_i1 = mp->DL_PORT;
00593 reply_mess.m3_i2 = DE_PORT_NR;
00594 *(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;
00595 mess_reply(mp, &reply_mess);
00596 return;
00597 }
00598 assert(dep->de_mode == DEM_ENABLED);
00599 assert(dep->de_flags & DEF_ENABLED);
00600
00601 dep->de_flags &= ~(DEF_PROMISC | DEF_MULTI | DEF_BROAD);
00602
00603 if (mp->DL_MODE & DL_PROMISC_REQ)
00604 dep->de_flags |= DEF_PROMISC | DEF_MULTI | DEF_BROAD;
00605 if (mp->DL_MODE & DL_MULTI_REQ)
00606 dep->de_flags |= DEF_MULTI;
00607 if (mp->DL_MODE & DL_BROAD_REQ)
00608 dep->de_flags |= DEF_BROAD;
00609
00610 dep->de_client = mp->m_source;
00611 dp_reinit(dep);
00612
00613 reply_mess.m_type = DL_INIT_REPLY;
00614 reply_mess.m3_i1 = mp->DL_PORT;
00615 reply_mess.m3_i2 = DE_PORT_NR;
00616 *(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;
00617
00618 mess_reply(mp, &reply_mess);
00619 }
00620
00621
00622
00623
00624 static void do_int(dep)
00625 dpeth_t *dep;
00626 {
00627 if (dep->de_flags & (DEF_PACK_SEND | DEF_PACK_RECV))
00628 reply(dep, OK, TRUE);
00629 }
00630
00631
00632
00633
00634 static void do_getstat(mp)
00635 message *mp;
00636 {
00637 int port;
00638 dpeth_t *dep;
00639
00640 port = mp->DL_PORT;
00641 if (port < 0 || port >= DE_PORT_NR)
00642 panic("", "dp8390: illegal port", port);
00643 dep= &de_table[port];
00644 dep->de_client= mp->DL_PROC;
00645 if (dep->de_mode == DEM_SINK)
00646 {
00647 put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
00648 (vir_bytes) sizeof(dep->de_stat), &dep->de_stat);
00649 reply(dep, OK, FALSE);
00650 return;
00651 }
00652 assert(dep->de_mode == DEM_ENABLED);
00653 assert(dep->de_flags & DEF_ENABLED);
00654
00655 dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
00656 dep->de_stat.ets_frameAll += inb_reg0(dep, DP_CNTR1);
00657 dep->de_stat.ets_missedP += inb_reg0(dep, DP_CNTR2);
00658
00659 put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
00660 (vir_bytes) sizeof(dep->de_stat), &dep->de_stat);
00661 reply(dep, OK, FALSE);
00662 }
00663
00664
00665
00666
00667 static void do_getname(mp)
00668 message *mp;
00669 {
00670 int r;
00671
00672 strncpy(mp->DL_NAME, progname, sizeof(mp->DL_NAME));
00673 mp->DL_NAME[sizeof(mp->DL_NAME)-1]= '\0';
00674 mp->m_type= DL_NAME_REPLY;
00675 r= send(mp->m_source, mp);
00676 if (r != OK)
00677 panic("dp8390", "do_getname: send failed: %d\n", r);
00678 }
00679
00680
00681
00682
00683 static void do_stop(mp)
00684 message *mp;
00685 {
00686 int port;
00687 dpeth_t *dep;
00688
00689 port = mp->DL_PORT;
00690
00691 if (port < 0 || port >= DE_PORT_NR)
00692 panic("", "dp8390: illegal port", port);
00693 dep= &de_table[port];
00694 if (dep->de_mode == DEM_SINK)
00695 return;
00696 assert(dep->de_mode == DEM_ENABLED);
00697
00698 if (!(dep->de_flags & DEF_ENABLED))
00699 return;
00700
00701 outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
00702 (dep->de_stopf)(dep);
00703
00704 dep->de_flags= DEF_EMPTY;
00705 }
00706
00707
00708
00709
00710 static void dp_init(dep)
00711 dpeth_t *dep;
00712 {
00713 int dp_rcr_reg;
00714 int i, r;
00715
00716
00717 dep->de_flags = DEF_EMPTY;
00718 (*dep->de_initf)(dep);
00719
00720 dp_confaddr(dep);
00721
00722 if (debug)
00723 {
00724 printf("%s: Ethernet address ", dep->de_name);
00725 for (i= 0; i < 6; i++)
00726 printf("%x%c", dep->de_address.ea_addr[i],
00727 i < 5 ? ':' : '\n');
00728 }
00729
00730
00731
00732
00733
00734
00735 outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_DM_ABORT);
00736
00737 if (dep->de_16bit)
00738 outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS);
00739 else
00740 outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES | DCR_BMS);
00741
00742 outb_reg0(dep, DP_RBCR0, 0);
00743 outb_reg0(dep, DP_RBCR1, 0);
00744
00745 dp_rcr_reg = 0;
00746 if (dep->de_flags & DEF_PROMISC)
00747 dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
00748 if (dep->de_flags & DEF_BROAD)
00749 dp_rcr_reg |= RCR_AB;
00750 if (dep->de_flags & DEF_MULTI)
00751 dp_rcr_reg |= RCR_AM;
00752 outb_reg0(dep, DP_RCR, dp_rcr_reg);
00753
00754 outb_reg0(dep, DP_TCR, TCR_INTERNAL);
00755
00756 outb_reg0(dep, DP_BNRY, dep->de_startpage);
00757 outb_reg0(dep, DP_PSTART, dep->de_startpage);
00758 outb_reg0(dep, DP_PSTOP, dep->de_stoppage);
00759
00760 outb_reg0(dep, DP_ISR, 0xFF);
00761
00762 outb_reg0(dep, DP_IMR, IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE |
00763 IMR_OVWE | IMR_CNTE);
00764
00765 outb_reg0(dep, DP_CR, CR_PS_P1 | CR_DM_ABORT | CR_STP);
00766
00767 outb_reg1(dep, DP_PAR0, dep->de_address.ea_addr[0]);
00768 outb_reg1(dep, DP_PAR1, dep->de_address.ea_addr[1]);
00769 outb_reg1(dep, DP_PAR2, dep->de_address.ea_addr[2]);
00770 outb_reg1(dep, DP_PAR3, dep->de_address.ea_addr[3]);
00771 outb_reg1(dep, DP_PAR4, dep->de_address.ea_addr[4]);
00772 outb_reg1(dep, DP_PAR5, dep->de_address.ea_addr[5]);
00773
00774 outb_reg1(dep, DP_MAR0, 0xff);
00775 outb_reg1(dep, DP_MAR1, 0xff);
00776 outb_reg1(dep, DP_MAR2, 0xff);
00777 outb_reg1(dep, DP_MAR3, 0xff);
00778 outb_reg1(dep, DP_MAR4, 0xff);
00779 outb_reg1(dep, DP_MAR5, 0xff);
00780 outb_reg1(dep, DP_MAR6, 0xff);
00781 outb_reg1(dep, DP_MAR7, 0xff);
00782
00783 outb_reg1(dep, DP_CURR, dep->de_startpage + 1);
00784
00785 outb_reg0(dep, DP_CR, CR_DM_ABORT | CR_STA);
00786
00787 outb_reg0(dep, DP_TCR, TCR_NORMAL);
00788
00789 inb_reg0(dep, DP_CNTR0);
00790 inb_reg0(dep, DP_CNTR1);
00791 inb_reg0(dep, DP_CNTR2);
00792
00793
00794 dep->de_flags |= DEF_ENABLED;
00795 for (i= 0; i<dep->de_sendq_nr; i++)
00796 dep->de_sendq[i].sq_filled= 0;
00797 dep->de_sendq_head= 0;
00798 dep->de_sendq_tail= 0;
00799 if (!dep->de_prog_IO)
00800 {
00801 dep->de_user2nicf= dp_user2nic;
00802 dep->de_nic2userf= dp_nic2user;
00803 dep->de_getblockf= dp_getblock;
00804 }
00805 else if (dep->de_16bit)
00806 {
00807 dep->de_user2nicf= dp_pio16_user2nic;
00808 dep->de_nic2userf= dp_pio16_nic2user;
00809 dep->de_getblockf= dp_pio16_getblock;
00810 }
00811 else
00812 {
00813 dep->de_user2nicf= dp_pio8_user2nic;
00814 dep->de_nic2userf= dp_pio8_nic2user;
00815 dep->de_getblockf= dp_pio8_getblock;
00816 }
00817
00818
00819
00820
00821 dep->de_hook = dep->de_irq;
00822 r= sys_irqsetpolicy(dep->de_irq, 0, &dep->de_hook);
00823 if (r != OK)
00824 panic("DP8390", "sys_irqsetpolicy failed", r);
00825
00826 r= sys_irqenable(&dep->de_hook);
00827 if (r != OK)
00828 {
00829 panic("DP8390", "unable enable interrupts", r);
00830 }
00831 }
00832
00833
00834
00835
00836 static void dp_confaddr(dep)
00837 dpeth_t *dep;
00838 {
00839 int i;
00840 char eakey[16];
00841 static char eafmt[]= "x:x:x:x:x:x";
00842 long v;
00843
00844
00845 strcpy(eakey, dp_conf[dep-de_table].dpc_envvar);
00846 strcat(eakey, "_EA");
00847
00848 for (i= 0; i < 6; i++)
00849 {
00850 v= dep->de_address.ea_addr[i];
00851 if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
00852 {
00853 break;
00854 }
00855 dep->de_address.ea_addr[i]= v;
00856 }
00857
00858 if (i != 0 && i != 6) env_panic(eakey);
00859 }
00860
00861
00862
00863
00864 static void dp_reinit(dep)
00865 dpeth_t *dep;
00866 {
00867 int dp_rcr_reg;
00868
00869 outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
00870
00871 dp_rcr_reg = 0;
00872 if (dep->de_flags & DEF_PROMISC)
00873 dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
00874 if (dep->de_flags & DEF_BROAD)
00875 dp_rcr_reg |= RCR_AB;
00876 if (dep->de_flags & DEF_MULTI)
00877 dp_rcr_reg |= RCR_AM;
00878 outb_reg0(dep, DP_RCR, dp_rcr_reg);
00879 }
00880
00881
00882
00883
00884 static void dp_reset(dep)
00885 dpeth_t *dep;
00886 {
00887 int i;
00888
00889
00890 outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
00891 outb_reg0(dep, DP_RBCR0, 0);
00892 outb_reg0(dep, DP_RBCR1, 0);
00893 for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++)
00894 ;
00895 outb_reg0(dep, DP_TCR, TCR_1EXTERNAL|TCR_OFST);
00896 outb_reg0(dep, DP_CR, CR_STA|CR_DM_ABORT);
00897 outb_reg0(dep, DP_TCR, TCR_NORMAL);
00898
00899
00900 for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RDC) == 0); i++)
00901 ;
00902 outb_reg0(dep, DP_ISR, inb_reg0(dep, DP_ISR) & ~ISR_RDC);
00903
00904
00905
00906
00907
00908 dep->de_sendq_head= dep->de_sendq_tail= 0;
00909 for (i= 0; i<dep->de_sendq_nr; i++)
00910 dep->de_sendq[i].sq_filled= 0;
00911 dp_send(dep);
00912 dep->de_flags &= ~DEF_STOPPED;
00913 }
00914
00915
00916
00917
00918 static void dp_check_ints(dep)
00919 dpeth_t *dep;
00920 {
00921 int isr, tsr;
00922 int size, sendq_tail;
00923
00924 if (!(dep->de_flags & DEF_ENABLED))
00925 panic("", "dp8390: got premature interrupt", NO_NUM);
00926
00927 for(;;)
00928 {
00929 isr = inb_reg0(dep, DP_ISR);
00930 if (!isr)
00931 break;
00932 outb_reg0(dep, DP_ISR, isr);
00933 if (isr & (ISR_PTX|ISR_TXE))
00934 {
00935 if (isr & ISR_TXE)
00936 {
00937 #if DEBUG
00938 { printf("%s: got send Error\n", dep->de_name); }
00939 #endif
00940 dep->de_stat.ets_sendErr++;
00941 }
00942 else
00943 {
00944 tsr = inb_reg0(dep, DP_TSR);
00945
00946 if (tsr & TSR_PTX) dep->de_stat.ets_packetT++;
00947 #if 0
00948 if (!(tsr & TSR_DFR))
00949 {
00950
00951
00952
00953
00954 dep->de_stat.ets_transDef++;
00955 }
00956 #endif
00957 if (tsr & TSR_COL) dep->de_stat.ets_collision++;
00958 if (tsr & TSR_ABT) dep->de_stat.ets_transAb++;
00959 if (tsr & TSR_CRS) dep->de_stat.ets_carrSense++;
00960 if (tsr & TSR_FU
00961 && ++dep->de_stat.ets_fifoUnder <= 10)
00962 {
00963 printf("%s: fifo underrun\n",
00964 dep->de_name);
00965 }
00966 if (tsr & TSR_CDH
00967 && ++dep->de_stat.ets_CDheartbeat <= 10)
00968 {
00969 printf("%s: CD heart beat failure\n",
00970 dep->de_name);
00971 }
00972 if (tsr & TSR_OWC) dep->de_stat.ets_OWC++;
00973 }
00974 sendq_tail= dep->de_sendq_tail;
00975
00976 if (!(dep->de_sendq[sendq_tail].sq_filled))
00977 {
00978
00979 assert(!debug);
00980
00981
00982 printf(
00983 "%s: transmit interrupt, but not sending\n",
00984 dep->de_name);
00985 continue;
00986 }
00987 dep->de_sendq[sendq_tail].sq_filled= 0;
00988 if (++sendq_tail == dep->de_sendq_nr)
00989 sendq_tail= 0;
00990 dep->de_sendq_tail= sendq_tail;
00991 if (dep->de_sendq[sendq_tail].sq_filled)
00992 {
00993 size= dep->de_sendq[sendq_tail].sq_size;
00994 outb_reg0(dep, DP_TPSR,
00995 dep->de_sendq[sendq_tail].sq_sendpage);
00996 outb_reg0(dep, DP_TBCR1, size >> 8);
00997 outb_reg0(dep, DP_TBCR0, size & 0xff);
00998 outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);
00999 }
01000 if (dep->de_flags & DEF_SEND_AVAIL)
01001 dp_send(dep);
01002 }
01003
01004 if (isr & ISR_PRX)
01005 {
01006
01007 if (dep->de_flags & DEF_READING)
01008 dp_recv(dep);
01009 }
01010
01011 if (isr & ISR_RXE) dep->de_stat.ets_recvErr++;
01012 if (isr & ISR_CNT)
01013 {
01014 dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
01015 dep->de_stat.ets_frameAll += inb_reg0(dep, DP_CNTR1);
01016 dep->de_stat.ets_missedP += inb_reg0(dep, DP_CNTR2);
01017 }
01018 if (isr & ISR_OVW)
01019 {
01020 dep->de_stat.ets_OVW++;
01021 #if 0
01022 { printW(); printf(
01023 "%s: got overwrite warning\n", dep->de_name); }
01024 #endif
01025 if (dep->de_flags & DEF_READING)
01026 {
01027 printf(
01028 "dp_check_ints: strange: overwrite warning and pending read request\n");
01029 dp_recv(dep);
01030 }
01031 }
01032 if (isr & ISR_RDC)
01033 {
01034
01035 }
01036 if (isr & ISR_RST)
01037 {
01038
01039
01040
01041
01042
01043 #if 0
01044 { printW(); printf(
01045 "%s: NIC stopped\n", dep->de_name); }
01046 #endif
01047 dep->de_flags |= DEF_STOPPED;
01048 break;
01049 }
01050 }
01051 if ((dep->de_flags & (DEF_READING|DEF_STOPPED)) ==
01052 (DEF_READING|DEF_STOPPED))
01053 {
01054
01055
01056
01057 dp_reset(dep);
01058 }
01059 }
01060
01061
01062
01063
01064 static void dp_recv(dep)
01065 dpeth_t *dep;
01066 {
01067 dp_rcvhdr_t header;
01068 unsigned pageno, curr, next;
01069 vir_bytes length;
01070 int packet_processed, r;
01071 u16_t eth_type;
01072
01073 packet_processed = FALSE;
01074 pageno = inb_reg0(dep, DP_BNRY) + 1;
01075 if (pageno == dep->de_stoppage) pageno = dep->de_startpage;
01076
01077 do
01078 {
01079 outb_reg0(dep, DP_CR, CR_PS_P1 | CR_EXTRA);
01080 curr = inb_reg1(dep, DP_CURR);
01081 outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
01082
01083 if (curr == pageno) break;
01084
01085 (dep->de_getblockf)(dep, pageno, (size_t)0, sizeof(header),
01086 &header);
01087 (dep->de_getblockf)(dep, pageno, sizeof(header) +
01088 2*sizeof(ether_addr_t), sizeof(eth_type), ð_type);
01089
01090 length = (header.dr_rbcl | (header.dr_rbch << 8)) -
01091 sizeof(dp_rcvhdr_t);
01092 next = header.dr_next;
01093 if (length < ETH_MIN_PACK_SIZE ||
01094 length > ETH_MAX_PACK_SIZE_TAGGED)
01095 {
01096 printf("%s: packet with strange length arrived: %d\n",
01097 dep->de_name, (int) length);
01098 next= curr;
01099 }
01100 else if (next < dep->de_startpage || next >= dep->de_stoppage)
01101 {
01102 printf("%s: strange next page\n", dep->de_name);
01103 next= curr;
01104 }
01105 else if (eth_type == eth_ign_proto)
01106 {
01107
01108
01109
01110
01111 static int first= 1;
01112 if (first)
01113 {
01114 first= 0;
01115 printf("%s: dropping proto 0x%04x packets\n",
01116 dep->de_name,
01117 ntohs(eth_ign_proto));
01118 }
01119 dep->de_stat.ets_packetR++;
01120 }
01121 else if (header.dr_status & RSR_FO)
01122 {
01123
01124
01125 printf("%s: fifo overrun, resetting receive buffer\n",
01126 dep->de_name);
01127 dep->de_stat.ets_fifoOver++;
01128 next = curr;
01129 }
01130 else if ((header.dr_status & RSR_PRX) &&
01131 (dep->de_flags & DEF_ENABLED))
01132 {
01133 r = dp_pkt2user(dep, pageno, length);
01134 if (r != OK)
01135 return;
01136
01137 packet_processed = TRUE;
01138 dep->de_stat.ets_packetR++;
01139 }
01140 if (next == dep->de_startpage)
01141 outb_reg0(dep, DP_BNRY, dep->de_stoppage - 1);
01142 else
01143 outb_reg0(dep, DP_BNRY, next - 1);
01144
01145 pageno = next;
01146 }
01147 while (!packet_processed);
01148 }
01149
01150
01151
01152
01153 static void dp_send(dep)
01154 dpeth_t *dep;
01155 {
01156 if (!(dep->de_flags & DEF_SEND_AVAIL))
01157 return;
01158
01159 dep->de_flags &= ~DEF_SEND_AVAIL;
01160 switch(dep->de_sendmsg.m_type)
01161 {
01162 case DL_WRITE: do_vwrite(&dep->de_sendmsg, TRUE, FALSE); break;
01163 case DL_WRITEV: do_vwrite(&dep->de_sendmsg, TRUE, TRUE); break;
01164 default:
01165 panic("", "dp8390: wrong type:", dep->de_sendmsg.m_type);
01166 break;
01167 }
01168 }
01169
01170
01171
01172
01173 static void dp_getblock(dep, page, offset, size, dst)
01174 dpeth_t *dep;
01175 int page;
01176 size_t offset;
01177 size_t size;
01178 void *dst;
01179 {
01180 int r;
01181
01182 offset = page * DP_PAGESIZE + offset;
01183
01184 r = sys_vircopy(SELF, BIOS_SEG, dep->de_linmem + offset,
01185 SELF, D, (vir_bytes)dst, size);
01186
01187 if (r != OK)
01188 panic("DP8390", "dp_getblock: sys_vircopy failed", r);
01189 }
01190
01191
01192
01193
01194 static void dp_pio8_getblock(dep, page, offset, size, dst)
01195 dpeth_t *dep;
01196 int page;
01197 size_t offset;
01198 size_t size;
01199 void *dst;
01200 {
01201 offset = page * DP_PAGESIZE + offset;
01202 outb_reg0(dep, DP_RBCR0, size & 0xFF);
01203 outb_reg0(dep, DP_RBCR1, size >> 8);
01204 outb_reg0(dep, DP_RSAR0, offset & 0xFF);
01205 outb_reg0(dep, DP_RSAR1, offset >> 8);
01206 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
01207
01208 insb(dep->de_data_port, dst, size);
01209 }
01210
01211
01212
01213
01214 static void dp_pio16_getblock(dep, page, offset, size, dst)
01215 dpeth_t *dep;
01216 int page;
01217 size_t offset;
01218 size_t size;
01219 void *dst;
01220 {
01221 offset = page * DP_PAGESIZE + offset;
01222 outb_reg0(dep, DP_RBCR0, size & 0xFF);
01223 outb_reg0(dep, DP_RBCR1, size >> 8);
01224 outb_reg0(dep, DP_RSAR0, offset & 0xFF);
01225 outb_reg0(dep, DP_RSAR1, offset >> 8);
01226 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
01227
01228 assert (!(size & 1));
01229 insw(dep->de_data_port, dst, size);
01230 }
01231
01232
01233
01234
01235 static int dp_pkt2user(dep, page, length)
01236 dpeth_t *dep;
01237 int page, length;
01238 {
01239 int last, count;
01240
01241 if (!(dep->de_flags & DEF_READING))
01242 return EGENERIC;
01243
01244 last = page + (length - 1) / DP_PAGESIZE;
01245 if (last >= dep->de_stoppage)
01246 {
01247 count = (dep->de_stoppage - page) * DP_PAGESIZE -
01248 sizeof(dp_rcvhdr_t);
01249
01250
01251 dep->de_tmp_iovec = dep->de_read_iovec;
01252 (dep->de_nic2userf)(dep, page * DP_PAGESIZE +
01253 sizeof(dp_rcvhdr_t), &dep->de_tmp_iovec, 0, count);
01254 (dep->de_nic2userf)(dep, dep->de_startpage * DP_PAGESIZE,
01255 &dep->de_read_iovec, count, length - count);
01256 }
01257 else
01258 {
01259 (dep->de_nic2userf)(dep, page * DP_PAGESIZE +
01260 sizeof(dp_rcvhdr_t), &dep->de_read_iovec, 0, length);
01261 }
01262
01263 dep->de_read_s = length;
01264 dep->de_flags |= DEF_PACK_RECV;
01265 dep->de_flags &= ~DEF_READING;
01266
01267 return OK;
01268 }
01269
01270
01271
01272
01273 static void dp_user2nic(dep, iovp, offset, nic_addr, count)
01274 dpeth_t *dep;
01275 iovec_dat_t *iovp;
01276 vir_bytes offset;
01277 int nic_addr;
01278 vir_bytes count;
01279 {
01280 vir_bytes vir_hw, vir_user;
01281 int bytes, i, r;
01282
01283 vir_hw = dep->de_linmem + nic_addr;
01284
01285 i= 0;
01286 while (count > 0)
01287 {
01288 if (i >= IOVEC_NR)
01289 {
01290 dp_next_iovec(iovp);
01291 i= 0;
01292 continue;
01293 }
01294 assert(i < iovp->iod_iovec_s);
01295 if (offset >= iovp->iod_iovec[i].iov_size)
01296 {
01297 offset -= iovp->iod_iovec[i].iov_size;
01298 i++;
01299 continue;
01300 }
01301 bytes = iovp->iod_iovec[i].iov_size - offset;
01302 if (bytes > count)
01303 bytes = count;
01304
01305 r= sys_vircopy(iovp->iod_proc_nr, D,
01306 iovp->iod_iovec[i].iov_addr + offset,
01307 SELF, BIOS_SEG, vir_hw, bytes);
01308 if (r != OK)
01309 panic("DP8390", "dp_user2nic: sys_vircopy failed", r);
01310
01311 count -= bytes;
01312 vir_hw += bytes;
01313 offset += bytes;
01314 }
01315 assert(count == 0);
01316 }
01317
01318
01319
01320
01321 static void dp_pio8_user2nic(dep, iovp, offset, nic_addr, count)
01322 dpeth_t *dep;
01323 iovec_dat_t *iovp;
01324 vir_bytes offset;
01325 int nic_addr;
01326 vir_bytes count;
01327 {
01328 phys_bytes phys_user;
01329 int bytes, i;
01330
01331 outb_reg0(dep, DP_ISR, ISR_RDC);
01332
01333 outb_reg0(dep, DP_RBCR0, count & 0xFF);
01334 outb_reg0(dep, DP_RBCR1, count >> 8);
01335 outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
01336 outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
01337 outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
01338
01339 i= 0;
01340 while (count > 0)
01341 {
01342 if (i >= IOVEC_NR)
01343 {
01344 dp_next_iovec(iovp);
01345 i= 0;
01346 continue;
01347 }
01348 assert(i < iovp->iod_iovec_s);
01349 if (offset >= iovp->iod_iovec[i].iov_size)
01350 {
01351 offset -= iovp->iod_iovec[i].iov_size;
01352 i++;
01353 continue;
01354 }
01355 bytes = iovp->iod_iovec[i].iov_size - offset;
01356 if (bytes > count)
01357 bytes = count;
01358
01359 do_vir_outsb(dep->de_data_port, iovp->iod_proc_nr,
01360 iovp->iod_iovec[i].iov_addr + offset, bytes);
01361 count -= bytes;
01362 offset += bytes;
01363 }
01364 assert(count == 0);
01365
01366 for (i= 0; i<100; i++)
01367 {
01368 if (inb_reg0(dep, DP_ISR) & ISR_RDC)
01369 break;
01370 }
01371 if (i == 100)
01372 {
01373 panic("", "dp8390: remote dma failed to complete", NO_NUM);
01374 }
01375 }
01376
01377
01378
01379
01380 static void dp_pio16_user2nic(dep, iovp, offset, nic_addr, count)
01381 dpeth_t *dep;
01382 iovec_dat_t *iovp;
01383 vir_bytes offset;
01384 int nic_addr;
01385 vir_bytes count;
01386 {
01387 vir_bytes vir_user;
01388 vir_bytes ecount;
01389 int i, r, bytes, user_proc;
01390 u8_t two_bytes[2];
01391 int odd_byte;
01392
01393 ecount= (count+1) & ~1;
01394 odd_byte= 0;
01395
01396 outb_reg0(dep, DP_ISR, ISR_RDC);
01397 outb_reg0(dep, DP_RBCR0, ecount & 0xFF);
01398 outb_reg0(dep, DP_RBCR1, ecount >> 8);
01399 outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
01400 outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
01401 outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
01402
01403 i= 0;
01404 while (count > 0)
01405 {
01406 if (i >= IOVEC_NR)
01407 {
01408 dp_next_iovec(iovp);
01409 i= 0;
01410 continue;
01411 }
01412 assert(i < iovp->iod_iovec_s);
01413 if (offset >= iovp->iod_iovec[i].iov_size)
01414 {
01415 offset -= iovp->iod_iovec[i].iov_size;
01416 i++;
01417 continue;
01418 }
01419 bytes = iovp->iod_iovec[i].iov_size - offset;
01420 if (bytes > count)
01421 bytes = count;
01422
01423 user_proc= iovp->iod_proc_nr;
01424 vir_user= iovp->iod_iovec[i].iov_addr + offset;
01425 if (odd_byte)
01426 {
01427 r= sys_vircopy(user_proc, D, vir_user,
01428 SELF, D, (vir_bytes)&two_bytes[1], 1);
01429 if (r != OK)
01430 {
01431 panic("DP8390",
01432 "dp_pio16_user2nic: sys_vircopy failed",
01433 r);
01434 }
01435 outw(dep->de_data_port, *(u16_t *)two_bytes);
01436 count--;
01437 offset++;
01438 bytes--;
01439 vir_user++;
01440 odd_byte= 0;
01441 if (!bytes)
01442 continue;
01443 }
01444 ecount= bytes & ~1;
01445 if (ecount != 0)
01446 {
01447 do_vir_outsw(dep->de_data_port, user_proc, vir_user,
01448 ecount);
01449 count -= ecount;
01450 offset += ecount;
01451 bytes -= ecount;
01452 vir_user += ecount;
01453 }
01454 if (bytes)
01455 {
01456 assert(bytes == 1);
01457 r= sys_vircopy(user_proc, D, vir_user,
01458 SELF, D, (vir_bytes)&two_bytes[0], 1);
01459 if (r != OK)
01460 {
01461 panic("DP8390",
01462 "dp_pio16_user2nic: sys_vircopy failed",
01463 r);
01464 }
01465 count--;
01466 offset++;
01467 bytes--;
01468 vir_user++;
01469 odd_byte= 1;
01470 }
01471 }
01472 assert(count == 0);
01473
01474 if (odd_byte)
01475 outw(dep->de_data_port, *(u16_t *)two_bytes);
01476
01477 for (i= 0; i<100; i++)
01478 {
01479 if (inb_reg0(dep, DP_ISR) & ISR_RDC)
01480 break;
01481 }
01482 if (i == 100)
01483 {
01484 panic("", "dp8390: remote dma failed to complete", NO_NUM);
01485 }
01486 }
01487
01488
01489
01490
01491 static void dp_nic2user(dep, nic_addr, iovp, offset, count)
01492 dpeth_t *dep;
01493 int nic_addr;
01494 iovec_dat_t *iovp;
01495 vir_bytes offset;
01496 vir_bytes count;
01497 {
01498 vir_bytes vir_hw, vir_user;
01499 int bytes, i, r;
01500
01501 vir_hw = dep->de_linmem + nic_addr;
01502
01503 i= 0;
01504 while (count > 0)
01505 {
01506 if (i >= IOVEC_NR)
01507 {
01508 dp_next_iovec(iovp);
01509 i= 0;
01510 continue;
01511 }
01512 assert(i < iovp->iod_iovec_s);
01513 if (offset >= iovp->iod_iovec[i].iov_size)
01514 {
01515 offset -= iovp->iod_iovec[i].iov_size;
01516 i++;
01517 continue;
01518 }
01519 bytes = iovp->iod_iovec[i].iov_size - offset;
01520 if (bytes > count)
01521 bytes = count;
01522
01523 r= sys_vircopy(SELF, BIOS_SEG, vir_hw,
01524 iovp->iod_proc_nr, D,
01525 iovp->iod_iovec[i].iov_addr + offset, bytes);
01526 if (r != OK)
01527 panic("DP8390", "dp_nic2user: sys_vircopy failed", r);
01528
01529 count -= bytes;
01530 vir_hw += bytes;
01531 offset += bytes;
01532 }
01533 assert(count == 0);
01534 }
01535
01536
01537
01538
01539 static void dp_pio8_nic2user(dep, nic_addr, iovp, offset, count)
01540 dpeth_t *dep;
01541 int nic_addr;
01542 iovec_dat_t *iovp;
01543 vir_bytes offset;
01544 vir_bytes count;
01545 {
01546 phys_bytes phys_user;
01547 int bytes, i;
01548
01549 outb_reg0(dep, DP_RBCR0, count & 0xFF);
01550 outb_reg0(dep, DP_RBCR1, count >> 8);
01551 outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
01552 outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
01553 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
01554
01555 i= 0;
01556 while (count > 0)
01557 {
01558 if (i >= IOVEC_NR)
01559 {
01560 dp_next_iovec(iovp);
01561 i= 0;
01562 continue;
01563 }
01564 assert(i < iovp->iod_iovec_s);
01565 if (offset >= iovp->iod_iovec[i].iov_size)
01566 {
01567 offset -= iovp->iod_iovec[i].iov_size;
01568 i++;
01569 continue;
01570 }
01571 bytes = iovp->iod_iovec[i].iov_size - offset;
01572 if (bytes > count)
01573 bytes = count;
01574
01575 do_vir_insb(dep->de_data_port, iovp->iod_proc_nr,
01576 iovp->iod_iovec[i].iov_addr + offset, bytes);
01577 count -= bytes;
01578 offset += bytes;
01579 }
01580 assert(count == 0);
01581 }
01582
01583
01584
01585
01586 static void dp_pio16_nic2user(dep, nic_addr, iovp, offset, count)
01587 dpeth_t *dep;
01588 int nic_addr;
01589 iovec_dat_t *iovp;
01590 vir_bytes offset;
01591 vir_bytes count;
01592 {
01593 vir_bytes vir_user;
01594 vir_bytes ecount;
01595 int i, r, bytes, user_proc;
01596 u8_t two_bytes[2];
01597 int odd_byte;
01598
01599 ecount= (count+1) & ~1;
01600 odd_byte= 0;
01601
01602 outb_reg0(dep, DP_RBCR0, ecount & 0xFF);
01603 outb_reg0(dep, DP_RBCR1, ecount >> 8);
01604 outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
01605 outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
01606 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
01607
01608 i= 0;
01609 while (count > 0)
01610 {
01611 if (i >= IOVEC_NR)
01612 {
01613 dp_next_iovec(iovp);
01614 i= 0;
01615 continue;
01616 }
01617 assert(i < iovp->iod_iovec_s);
01618 if (offset >= iovp->iod_iovec[i].iov_size)
01619 {
01620 offset -= iovp->iod_iovec[i].iov_size;
01621 i++;
01622 continue;
01623 }
01624 bytes = iovp->iod_iovec[i].iov_size - offset;
01625 if (bytes > count)
01626 bytes = count;
01627
01628 user_proc= iovp->iod_proc_nr;
01629 vir_user= iovp->iod_iovec[i].iov_addr + offset;
01630 if (odd_byte)
01631 {
01632 r= sys_vircopy(SELF, D, (vir_bytes)&two_bytes[1],
01633 user_proc, D, vir_user, 1);
01634 if (r != OK)
01635 {
01636 panic("DP8390",
01637 "dp_pio16_nic2user: sys_vircopy failed",
01638 r);
01639 }
01640 count--;
01641 offset++;
01642 bytes--;
01643 vir_user++;
01644 odd_byte= 0;
01645 if (!bytes)
01646 continue;
01647 }
01648 ecount= bytes & ~1;
01649 if (ecount != 0)
01650 {
01651 do_vir_insw(dep->de_data_port, user_proc, vir_user,
01652 ecount);
01653 count -= ecount;
01654 offset += ecount;
01655 bytes -= ecount;
01656 vir_user += ecount;
01657 }
01658 if (bytes)
01659 {
01660 assert(bytes == 1);
01661 *(u16_t *)two_bytes= inw(dep->de_data_port);
01662 r= sys_vircopy(SELF, D, (vir_bytes)&two_bytes[0],
01663 user_proc, D, vir_user, 1);
01664 if (r != OK)
01665 {
01666 panic("DP8390",
01667 "dp_pio16_nic2user: sys_vircopy failed",
01668 r);
01669 }
01670 count--;
01671 offset++;
01672 bytes--;
01673 vir_user++;
01674 odd_byte= 1;
01675 }
01676 }
01677 assert(count == 0);
01678 }
01679
01680
01681
01682
01683 static void dp_next_iovec(iovp)
01684 iovec_dat_t *iovp;
01685 {
01686 assert(iovp->iod_iovec_s > IOVEC_NR);
01687
01688 iovp->iod_iovec_s -= IOVEC_NR;
01689
01690 iovp->iod_iovec_addr += IOVEC_NR * sizeof(iovec_t);
01691
01692 get_userdata(iovp->iod_proc_nr, iovp->iod_iovec_addr,
01693 (iovp->iod_iovec_s > IOVEC_NR ? IOVEC_NR : iovp->iod_iovec_s) *
01694 sizeof(iovec_t), iovp->iod_iovec);
01695 }
01696
01697
01698
01699
01700 static void conf_hw(dep)
01701 dpeth_t *dep;
01702 {
01703 static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0 };
01704
01705 int ifnr;
01706 dp_conf_t *dcp;
01707
01708 dep->de_mode= DEM_DISABLED;
01709 ifnr= dep-de_table;
01710
01711 dcp= &dp_conf[ifnr];
01712 update_conf(dep, dcp);
01713 if (dep->de_mode != DEM_ENABLED)
01714 return;
01715 if (!wdeth_probe(dep) && !ne_probe(dep) && !el2_probe(dep))
01716 {
01717 printf("%s: No ethernet card found at 0x%x\n",
01718 dep->de_name, dep->de_base_port);
01719 dep->de_mode= DEM_DISABLED;
01720 return;
01721 }
01722
01723 if (dep->de_linmem == 0) dep->de_linmem= 0xFFFF0000;
01724
01725 dep->de_flags = DEF_EMPTY;
01726 dep->de_stat = empty_stat;
01727 }
01728
01729
01730
01731
01732 static void update_conf(dep, dcp)
01733 dpeth_t *dep;
01734 dp_conf_t *dcp;
01735 {
01736 long v;
01737 static char dpc_fmt[] = "x:d:x:x";
01738
01739 #if ENABLE_PCI
01740 if (dep->de_pci)
01741 {
01742 if (dep->de_pci == 1)
01743 {
01744
01745 dep->de_mode= DEM_ENABLED;
01746 }
01747 return;
01748 }
01749 #endif
01750
01751
01752 dep->de_mode= DEM_SINK;
01753 v= dcp->dpc_port;
01754 switch (env_parse(dcp->dpc_envvar, dpc_fmt, 0, &v, 0x0000L, 0xFFFFL)) {
01755 case EP_OFF:
01756 dep->de_mode= DEM_DISABLED;
01757 break;
01758 case EP_ON:
01759 case EP_SET:
01760 dep->de_mode= DEM_ENABLED;
01761
01762 break;
01763 }
01764 dep->de_base_port= v;
01765
01766 v= dcp->dpc_irq | DEI_DEFAULT;
01767 (void) env_parse(dcp->dpc_envvar, dpc_fmt, 1, &v, 0L,
01768 (long) NR_IRQ_VECTORS - 1);
01769 dep->de_irq= v;
01770
01771 v= dcp->dpc_mem;
01772 (void) env_parse(dcp->dpc_envvar, dpc_fmt, 2, &v, 0L, 0xFFFFFL);
01773 dep->de_linmem= v;
01774
01775 v= 0;
01776 (void) env_parse(dcp->dpc_envvar, dpc_fmt, 3, &v, 0x2000L, 0x8000L);
01777 dep->de_ramsize= v;
01778 }
01779
01780
01781
01782
01783 static int calc_iovec_size(iovp)
01784 iovec_dat_t *iovp;
01785 {
01786
01787
01788
01789 int size;
01790 int i;
01791
01792 size= 0;
01793 i= 0;
01794 while (i < iovp->iod_iovec_s)
01795 {
01796 if (i >= IOVEC_NR)
01797 {
01798 dp_next_iovec(iovp);
01799 i= 0;
01800 continue;
01801 }
01802 size += iovp->iod_iovec[i].iov_size;
01803 i++;
01804 }
01805 return size;
01806 }
01807
01808
01809
01810
01811 static void reply(dep, err, may_block)
01812 dpeth_t *dep;
01813 int err;
01814 int may_block;
01815 {
01816 message reply;
01817 int status;
01818 int r;
01819
01820 status = 0;
01821 if (dep->de_flags & DEF_PACK_SEND)
01822 status |= DL_PACK_SEND;
01823 if (dep->de_flags & DEF_PACK_RECV)
01824 status |= DL_PACK_RECV;
01825
01826 reply.m_type = DL_TASK_REPLY;
01827 reply.DL_PORT = dep - de_table;
01828 reply.DL_PROC = dep->de_client;
01829 reply.DL_STAT = status | ((u32_t) err << 16);
01830 reply.DL_COUNT = dep->de_read_s;
01831 reply.DL_CLCK = 0;
01832 r= send(dep->de_client, &reply);
01833
01834 if (r == ELOCKED && may_block)
01835 {
01836 #if 0
01837 printf("send locked\n");
01838 #endif
01839 return;
01840 }
01841
01842 if (r < 0)
01843 panic("", "dp8390: send failed:", r);
01844
01845 dep->de_read_s = 0;
01846 dep->de_flags &= ~(DEF_PACK_SEND | DEF_PACK_RECV);
01847 }
01848
01849
01850
01851
01852 static void mess_reply(req, reply_mess)
01853 message *req;
01854 message *reply_mess;
01855 {
01856 if (send(req->m_source, reply_mess) != OK)
01857 panic("", "dp8390: unable to mess_reply", NO_NUM);
01858 }
01859
01860
01861
01862
01863 static void get_userdata(user_proc, user_addr, count, loc_addr)
01864 int user_proc;
01865 vir_bytes user_addr;
01866 vir_bytes count;
01867 void *loc_addr;
01868 {
01869 int r;
01870
01871 r= sys_vircopy(user_proc, D, user_addr,
01872 SELF, D, (vir_bytes)loc_addr, count);
01873 if (r != OK)
01874 panic("DP8390", "get_userdata: sys_vircopy failed", r);
01875 }
01876
01877
01878
01879
01880 static void put_userdata(user_proc, user_addr, count, loc_addr)
01881 int user_proc;
01882 vir_bytes user_addr;
01883 vir_bytes count;
01884 void *loc_addr;
01885 {
01886 int r;
01887
01888 r= sys_vircopy(SELF, D, (vir_bytes)loc_addr,
01889 user_proc, D, user_addr, count);
01890 if (r != OK)
01891 panic("DP8390", "put_userdata: sys_vircopy failed", r);
01892 }
01893
01894 u8_t inb(port_t port)
01895 {
01896 int r;
01897 u32_t value;
01898
01899 r= sys_inb(port, &value);
01900 if (r != OK)
01901 panic("DP8390","sys_inb failed", r);
01902 return value;
01903 }
01904
01905 u16_t inw(port_t port)
01906 {
01907 int r;
01908 unsigned long value;
01909
01910 r= sys_inw(port, &value);
01911 if (r != OK)
01912 panic("DP8390", "sys_inw failed", r);
01913 return (u16_t) value;
01914 }
01915
01916 void outb(port_t port, u8_t value)
01917 {
01918 int r;
01919
01920 r= sys_outb(port, value);
01921 if (r != OK)
01922 panic("DP8390", "sys_outb failed", r);
01923 }
01924
01925 void outw(port_t port, u16_t value)
01926 {
01927 int r;
01928
01929 r= sys_outw(port, value);
01930 if (r != OK)
01931 panic("DP8390", "sys_outw failed", r);
01932 }
01933
01934 static void insb(port_t port, void *buf, size_t size)
01935 {
01936 do_vir_insb(port, SELF, (vir_bytes)buf, size);
01937 }
01938
01939 static void insw(port_t port, void *buf, size_t size)
01940 {
01941 do_vir_insw(port, SELF, (vir_bytes)buf, size);
01942 }
01943
01944 static void do_vir_insb(port_t port, int proc, vir_bytes buf, size_t size)
01945 {
01946 int r;
01947
01948 r= sys_sdevio(DIO_INPUT, port, DIO_BYTE, proc, (void *)buf, size);
01949 if (r != OK)
01950 panic("DP8390", "sys_sdevio failed", r);
01951 }
01952
01953 static void do_vir_insw(port_t port, int proc, vir_bytes buf, size_t size)
01954 {
01955 int r;
01956
01957 r= sys_sdevio(DIO_INPUT, port, DIO_WORD, proc, (void *)buf, size);
01958 if (r != OK)
01959 panic("DP8390", "sys_sdevio failed", r);
01960 }
01961
01962 static void do_vir_outsb(port_t port, int proc, vir_bytes buf, size_t size)
01963 {
01964 int r;
01965
01966 r= sys_sdevio(DIO_OUTPUT, port, DIO_BYTE, proc, (void *)buf, size);
01967 if (r != OK)
01968 panic("DP8390", "sys_sdevio failed", r);
01969 }
01970
01971 static void do_vir_outsw(port_t port, int proc, vir_bytes buf, size_t size)
01972 {
01973 int r;
01974
01975 r= sys_sdevio(DIO_OUTPUT, port, DIO_WORD, proc, (void *)buf, size);
01976 if (r != OK)
01977 panic("DP8390", "sys_sdevio failed", r);
01978 }
01979
01980
01981
01982