1 /* 2 * dec21041.c 3 * 4 * This file contains an ethernet device driver for DEC 21140A 5 * fast ethernet controllers as emulated by VirtualPC 2007. It is not 6 * intended to support the real card, as much more error checking 7 * and testing would be needed. It supports both bridged and NAT mode. 8 * 9 * Created: Mar 2008 by Nicolas Tittley <first.last@ google's mail> 10 */ 11 12 #include <minix/drivers.h> 13 #include <minix/netdriver.h> 14 15 #include <assert.h> 16 #include <machine/pci.h> 17 #include <minix/syslib.h> 18 #include <minix/endpoint.h> 19 #include <minix/com.h> 20 #include <minix/sef.h> 21 #include <minix/ds.h> 22 #include <net/gen/ether.h> 23 #include <net/gen/eth_io.h> 24 #include <stdlib.h> 25 26 #include "dec21140A.h" 27 28 29 static u32_t io_inl(u16_t); 30 static void io_outl(u16_t, u32_t); 31 static void do_conf(const message *); 32 static void do_get_stat_s(message *); 33 static void do_interrupt(const dpeth_t *); 34 static void do_reply(dpeth_t *); 35 static void do_vread_s(const message *, int); 36 static void do_watchdog(void *); 37 38 static void de_update_conf(dpeth_t *); 39 static int de_probe(dpeth_t *, int skip); 40 static void de_conf_addr(dpeth_t *); 41 static void de_first_init(dpeth_t *); 42 static void de_reset(const dpeth_t *); 43 static void de_hw_conf(const dpeth_t *); 44 static void de_start(const dpeth_t *); 45 static void de_setup_frame(const dpeth_t *); 46 static u16_t de_read_rom(const dpeth_t *, u8_t, u8_t); 47 static int de_calc_iov_size(iovec_dat_s_t *); 48 static void de_next_iov(iovec_dat_s_t *); 49 static void do_vwrite_s(const message *, int); 50 static void de_get_userdata_s(int, cp_grant_id_t, vir_bytes, int, void 51 *); 52 53 /* Error messages */ 54 static char str_CopyErrMsg[] = "unable to read/write user data"; 55 static char str_SendErrMsg[] = "send failed"; 56 static char str_SizeErrMsg[] = "illegal packet size"; 57 static char str_UmapErrMsg[] = "Unable to sys_umap"; 58 static char str_BusyErrMsg[] = "Send/Recv failed: busy"; 59 static char str_StatErrMsg[] = "Unable to send stats"; 60 static char str_AlignErrMsg[] = "Bad align of buffer/descriptor"; 61 static char str_DevName[] = "dec21140A:eth#?"; 62 63 static dpeth_t de_state; 64 static int de_instance; 65 66 /* SEF functions and variables. */ 67 static void sef_local_startup(void); 68 static int sef_cb_init_fresh(int type, sef_init_info_t *info); 69 70 /*===========================================================================* 71 * main * 72 *===========================================================================*/ 73 int main(int argc, char *argv[]) 74 { 75 dpeth_t *dep; 76 message m; 77 int ipc_status; 78 int r; 79 80 /* SEF local startup. */ 81 env_setargs(argc, argv); 82 sef_local_startup(); 83 84 while (TRUE) 85 { 86 if ((r= netdriver_receive(ANY, &m, &ipc_status)) != OK) 87 panic("netdriver_receive failed: %d", r); 88 89 if(is_ipc_notify(ipc_status)) { 90 switch(_ENDPOINT_P(m.m_source)) { 91 case CLOCK: 92 do_watchdog(&m); 93 break; 94 95 case HARDWARE: 96 dep = &de_state; 97 if (dep->de_mode == DEM_ENABLED) { 98 do_interrupt(dep); 99 if (dep->de_flags & (DEF_ACK_SEND | DEF_ACK_RECV)) 100 do_reply(dep); 101 sys_irqenable(&dep->de_hook); 102 } 103 break; 104 default: 105 printf("ignoring notify from %d\n", m.m_source); 106 break; 107 } 108 continue; 109 } 110 111 switch (m.m_type) 112 { 113 case DL_WRITEV_S: do_vwrite_s(&m, FALSE); break; 114 case DL_READV_S: do_vread_s(&m, FALSE); break; 115 case DL_CONF: do_conf(&m); break; 116 case DL_GETSTAT_S: do_get_stat_s(&m); break; 117 118 default: 119 printf("message 0x%x; %d from %d\n", 120 m.m_type, m.m_type-DL_RQ_BASE, m.m_source); 121 panic("illegal message: %d", m.m_type); 122 } 123 } 124 } 125 126 /*===========================================================================* 127 * sef_local_startup * 128 *===========================================================================*/ 129 static void sef_local_startup() 130 { 131 /* Register init callbacks. */ 132 sef_setcb_init_fresh(sef_cb_init_fresh); 133 sef_setcb_init_lu(sef_cb_init_fresh); 134 sef_setcb_init_restart(sef_cb_init_fresh); 135 136 /* Register live update callbacks. */ 137 sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready); 138 sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_workfree); 139 140 /* Register signal callbacks. */ 141 sef_setcb_signal_handler(sef_cb_signal_handler_term); 142 143 /* Let SEF perform startup. */ 144 sef_startup(); 145 } 146 147 /*===========================================================================* 148 * sef_cb_init_fresh * 149 *===========================================================================*/ 150 static int sef_cb_init_fresh(int type, sef_init_info_t *UNUSED(info)) 151 { 152 /* Initialize the DEC 21140A driver. */ 153 int fkeys, sfkeys; 154 long v; 155 156 v = 0; 157 (void) env_parse("instance", "d", 0, &v, 0, 255); 158 de_instance = (int) v; 159 160 /* Request function key for debug dumps */ 161 fkeys = sfkeys = 0; 162 bit_set(sfkeys, DE_FKEY); 163 if ((fkey_map(&fkeys, &sfkeys)) != OK) 164 printf("%s: error using Shift+F%d key(%d)\n", str_DevName, DE_FKEY, errno); 165 166 /* Announce we are up! */ 167 netdriver_announce(); 168 169 return OK; 170 } 171 172 static void do_get_stat_s(message * mp) 173 { 174 int rc; 175 dpeth_t *dep; 176 177 dep = &de_state; 178 179 if ((rc = sys_safecopyto(mp->m_source, mp->m_net_netdrv_dl_getstat_s.grant, 180 0, (vir_bytes)&dep->de_stat, sizeof(dep->de_stat))) != OK) 181 panic("%s %d", str_CopyErrMsg, rc); 182 183 mp->m_type = DL_STAT_REPLY; 184 rc = ipc_send(mp->m_source, mp); 185 if( rc != OK ) 186 panic("%s %d", str_StatErrMsg, rc); 187 return; 188 } 189 190 static void do_conf(const message * mp) 191 { 192 int r; 193 dpeth_t *dep; 194 message reply_mess; 195 196 dep = &de_state; 197 198 strncpy(dep->de_name, str_DevName, strlen(str_DevName)); 199 dep->de_name[strlen(dep->de_name)-1] = '0' + de_instance; 200 201 if (dep->de_mode == DEM_DISABLED) { 202 de_update_conf(dep); 203 pci_init(); 204 if (dep->de_mode == DEM_ENABLED && !de_probe(dep, de_instance)) { 205 printf("%s: warning no ethernet card found at 0x%04X\n", 206 dep->de_name, dep->de_base_port); 207 dep->de_mode = DEM_DISABLED; 208 } 209 } 210 211 r = OK; 212 213 /* 'de_mode' may change if probe routines fail, test again */ 214 switch (dep->de_mode) { 215 216 case DEM_DISABLED: 217 r = ENXIO; /* Device is OFF or hardware probe failed */ 218 break; 219 220 case DEM_ENABLED: 221 if (dep->de_flags == DEF_EMPTY) { 222 de_first_init(dep); 223 dep->de_flags |= DEF_ENABLED; 224 de_reset(dep); 225 de_hw_conf(dep); 226 de_setup_frame(dep); 227 de_start(dep); 228 } 229 230 /* TODO CHECK PROMISC AND MULTI */ 231 dep->de_flags &= NOT(DEF_PROMISC | DEF_MULTI | DEF_BROAD); 232 if (mp->m_net_netdrv_dl_conf.mode & DL_PROMISC_REQ) 233 dep->de_flags |= DEF_PROMISC | DEF_MULTI | DEF_BROAD; 234 if (mp->m_net_netdrv_dl_conf.mode & DL_MULTI_REQ) 235 dep->de_flags |= DEF_MULTI; 236 if (mp->m_net_netdrv_dl_conf.mode & DL_BROAD_REQ) 237 dep->de_flags |= DEF_BROAD; 238 break; 239 240 case DEM_SINK: 241 DEBUG(printf("%s running in sink mode\n", str_DevName)); 242 memset(dep->de_address.ea_addr, 0, sizeof(ether_addr_t)); 243 de_conf_addr(dep); 244 break; 245 246 default: break; 247 } 248 249 reply_mess.m_type = DL_CONF_REPLY; 250 reply_mess.m_netdrv_net_dl_conf.stat = r; 251 if(r == OK){ 252 memcpy(reply_mess.m_netdrv_net_dl_conf.hw_addr, dep->de_address.ea_addr, 253 sizeof(reply_mess.m_netdrv_net_dl_conf.hw_addr)); 254 } 255 256 if (ipc_send(mp->m_source, &reply_mess) != OK) 257 panic("%s %d", str_SendErrMsg, mp->m_source); 258 259 return; 260 } 261 262 static void do_reply(dpeth_t * dep) 263 { 264 message reply; 265 int r, flags = DL_NOFLAGS; 266 267 if (dep->de_flags & DEF_ACK_SEND) flags |= DL_PACK_SEND; 268 if (dep->de_flags & DEF_ACK_RECV) flags |= DL_PACK_RECV; 269 270 reply.m_type = DL_TASK_REPLY; 271 reply.m_netdrv_net_dl_task.flags = flags; 272 reply.m_netdrv_net_dl_task.count = dep->de_read_s; 273 274 r = ipc_send(dep->de_client, &reply); 275 276 if(r < 0) 277 panic("%s %d", str_SendErrMsg, r); 278 279 dep->de_read_s = 0; 280 dep->de_flags &= NOT(DEF_ACK_SEND | DEF_ACK_RECV); 281 return; 282 } 283 284 static void do_watchdog(void *UNUSED(message)) 285 { 286 /* nothing here yet */ 287 return; 288 } 289 290 static int de_probe(dpeth_t *dep, int skip) 291 { 292 int i, r, devind; 293 u16_t vid, did, temp16; 294 295 DEBUG(printf("PROBING...")); 296 297 r= pci_first_dev(&devind, &vid, &did); 298 if (r == 0) 299 return FALSE; 300 301 while (skip--) 302 { 303 r= pci_next_dev(&devind, &vid, &did); 304 if (!r) 305 return FALSE; 306 } 307 308 pci_reserve(devind); 309 310 dep->de_base_port = pci_attr_r32(devind, PCI_BAR) & 0xffffffe0; 311 dep->de_irq = pci_attr_r8(devind, PCI_ILR); 312 313 if (dep->de_base_port < DE_MIN_BASE_ADDR) 314 panic("de_probe: base address invalid: %d", dep->de_base_port); 315 316 DEBUG(printf("%s: using I/O address 0x%lx, IRQ %d\n", 317 dep->de_name, (unsigned long)dep->de_base_port, 318 dep->de_irq)); 319 320 dep->de_type = pci_attr_r8(devind, PCI_REV); 321 322 /* device validation. We support only the DEC21140A */ 323 if(dep->de_type != DEC_21140A){ 324 dep->de_type = DE_TYPE_UNKNOWN; 325 printf("%s: unsupported device\n", str_DevName); 326 return FALSE; 327 } 328 329 de_reset(dep); 330 331 DEBUG(printf("Reading SROM...\n")); 332 333 for(i=0;i<(1<<SROM_BITWIDTH)-1;i++){ 334 temp16 = de_read_rom(dep, i, SROM_BITWIDTH); 335 dep->srom[i*2] = temp16 & 0xFF; 336 dep->srom[i*2+1] = temp16 >> 8; 337 } 338 339 /* TODO: validate SROM content */ 340 /* acquire MAC addr */ 341 DEBUG(printf("Using MAC addr= ")); 342 for(i=0;i<6;i++){ 343 dep->de_address.ea_addr[i] = dep->srom[i+DE_SROM_EA_OFFSET]; 344 DEBUG(printf("%02X%c",dep->de_address.ea_addr[i],i!=5?'-':'\n')); 345 } 346 DEBUG(printf("probe success\n")); 347 return TRUE; 348 } 349 350 static u16_t de_read_rom(const dpeth_t *dep, u8_t addr, u8_t nbAddrBits){ 351 u16_t retVal = 0; 352 int i; 353 u32_t csr = 0; 354 u32_t csr2 = 0; /* csr2 is used to hold constant values that are 355 setup in the init phase, it makes this a little 356 more readable, the following macro is also just 357 to clear up the code a little.*/ 358 359 #define EMIT do { io_outl(CSR_ADDR(dep, CSR9), csr | csr2); io_outl(CSR_ADDR(dep, CSR1), 0);} while(0) 360 361 /* init */ 362 csr = 0; EMIT; 363 csr = CSR9_SR; EMIT; 364 csr = CSR9_SR | CSR9_RD; EMIT; 365 366 csr2 = CSR9_SR | CSR9_RD; 367 csr = 0; EMIT; 368 csr2 |= CSR9_CS; 369 370 csr = 0; EMIT; 371 csr = CSR9_SRC; EMIT; 372 csr = 0; EMIT; 373 374 /* cmd 110 - Read */ 375 csr = CSR9_DI; EMIT; 376 csr = CSR9_DI | CSR9_SRC; EMIT; 377 csr = CSR9_DI; EMIT; 378 csr = CSR9_DI | CSR9_SRC; EMIT; 379 csr = CSR9_DI; EMIT; 380 csr = 0; EMIT; 381 csr = CSR9_SRC; EMIT; 382 csr = 0; EMIT; 383 384 /* addr to read */ 385 for(i=nbAddrBits;i!=0;i--){ 386 csr = (addr&(1<<(i-1))) != 0 ? CSR9_DI : 0; EMIT; 387 csr ^= CSR9_SRC; EMIT; 388 csr ^= CSR9_SRC; EMIT; 389 } 390 391 /* actual read */ 392 retVal=0; 393 for(i=0;i<16;i++){ 394 retVal <<= 1; 395 csr = CSR9_SRC; EMIT; 396 retVal |= (io_inl(CSR_ADDR(dep, CSR9)) & CSR9_DO) == 0 ? 0 : 1; 397 csr = 0; EMIT; 398 } 399 400 /* clean up */ 401 csr = 0; EMIT; 402 403 #undef EMIT 404 return retVal; 405 } 406 407 static void de_update_conf(dpeth_t * dep) 408 { 409 static char dpc_fmt[] = "x:d:x"; 410 char ec_key[16]; 411 long val; 412 413 strlcpy(ec_key, "DEETH0", sizeof(ec_key)); 414 ec_key[5] += de_instance; 415 416 dep->de_mode = DEM_ENABLED; 417 switch (env_parse(ec_key, dpc_fmt, 0, &val, 0x000L, 0x3FFL)) { 418 case EP_OFF: dep->de_mode = DEM_DISABLED; break; 419 case EP_ON: dep->de_mode = DEM_SINK; break; 420 } 421 dep->de_base_port = 0; 422 423 return; 424 } 425 426 static void do_vread_s(const message * mp, int from_int) 427 { 428 u8_t *buffer; 429 u32_t size; 430 int r, ix = 0; 431 vir_bytes bytes; 432 dpeth_t *dep = NULL; 433 de_loc_descr_t *descr = NULL; 434 iovec_dat_s_t *iovp = NULL; 435 436 dep = &de_state; 437 438 dep->de_client = mp->m_source; 439 440 if (dep->de_mode == DEM_ENABLED) { 441 442 descr = &dep->descr[DESCR_RECV][dep->cur_descr[DESCR_RECV]]; 443 444 /* check if packet is in the current descr and only there */ 445 if( !( !(descr->descr->des[DES0] & DES0_OWN) && 446 (descr->descr->des[DES0] & DES0_FS) && 447 (descr->descr->des[DES0] & DES0_LS) )) 448 goto suspend; 449 450 451 /*TODO: multi-descr msgs...*/ 452 /* We only support packets contained in a single descriptor. 453 Setting the descriptor buffer size to less then 454 ETH_MAX_PACK_SIZE will result in multi-descriptor 455 packets that we won't be able to handle 456 */ 457 assert(!(descr->descr->des[DES0]&DES0_OWN)); 458 assert(descr->descr->des[DES0]&DES0_FS); 459 assert(descr->descr->des[DES0]&DES0_LS); 460 461 /* Check for abnormal messages. We assert here 462 because this driver is for a virtualized 463 envrionment where we will not get bad packets 464 */ 465 assert(!(descr->descr->des[DES0]&DES0_ES)); 466 assert(!(descr->descr->des[DES0]&DES0_RE)); 467 468 469 /* Setup the iovec entry to allow copying into 470 client layer 471 */ 472 dep->de_read_iovec.iod_proc_nr = mp->m_source; 473 de_get_userdata_s(mp->m_source, mp->m_net_netdrv_dl_readv_s.grant, 0, 474 mp->m_net_netdrv_dl_readv_s.count, 475 dep->de_read_iovec.iod_iovec); 476 dep->de_read_iovec.iod_iovec_s = mp->m_net_netdrv_dl_readv_s.count; 477 dep->de_read_iovec.iod_grant = mp->m_net_netdrv_dl_readv_s.grant; 478 dep->de_read_iovec.iod_iovec_offset = 0; 479 size = de_calc_iov_size(&dep->de_read_iovec); 480 if (size < ETH_MAX_PACK_SIZE) 481 panic("%s %d", str_SizeErrMsg, size); 482 483 /* Copy buffer to user area and clear ownage */ 484 size = (descr->descr->des[DES0]&DES0_FL)>>DES0_FL_SHIFT; 485 486 /*TODO: Complain to MS */ 487 /*HACK: VPC2007 returns packet of invalid size. Ethernet standard 488 specify 46 bytes as the minimum for valid payload. However, this is 489 artificial in so far as for certain packet types, notably ARP, less 490 then 46 bytes are needed to contain the full information. In a non 491 virtualized environment the 46 bytes rule is enforced in order to give 492 guarantee in the collison detection scheme. Of course, this being a 493 driver for a VPC2007, we won't have collisions and I can only suppose 494 MS decided to cut packet size to true minimum, regardless of the 495 46 bytes payload standard. Note that this seems to not happen in 496 bridged mode. Note also, that the card does not return runt or 497 incomplete frames to us, so this hack is safe 498 */ 499 if(size<60){ 500 memset(&descr->buf1[size], 0, 60-size); 501 size=60; 502 } 503 /* End ugly hack */ 504 505 iovp = &dep->de_read_iovec; 506 buffer = descr->buf1; 507 dep->bytes_rx += size; 508 dep->de_stat.ets_packetR++; 509 dep->de_read_s = size; 510 511 do { 512 bytes = iovp->iod_iovec[ix].iov_size; /* Size of buffer */ 513 if (bytes >= size) 514 bytes = size; 515 516 r= sys_safecopyto(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_grant, 0, 517 (vir_bytes)buffer, bytes); 518 if (r != OK) 519 panic("%s %d", str_CopyErrMsg, r); 520 buffer += bytes; 521 522 if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */ 523 de_next_iov(iovp); 524 ix = 0; 525 } 526 } while ((size -= bytes) > 0); 527 528 descr->descr->des[DES0]=DES0_OWN; 529 dep->cur_descr[DESCR_RECV]++; 530 if(dep->cur_descr[DESCR_RECV] >= DE_NB_RECV_DESCR) 531 dep->cur_descr[DESCR_RECV] = 0; 532 533 DEBUG(printf("Read returned size = %d\n", size)); 534 535 /* Reply information */ 536 dep->de_flags |= DEF_ACK_RECV; 537 dep->de_flags &= NOT(DEF_READING); 538 } 539 540 if(!from_int){ 541 do_reply(dep); 542 } 543 return; 544 545 suspend: 546 if(from_int){ 547 assert(dep->de_flags & DEF_READING); 548 return; 549 } 550 551 assert(!(dep->de_flags & DEF_READING)); 552 dep->rx_return_msg = *mp; 553 dep->de_flags |= DEF_READING; 554 do_reply(dep); 555 return; 556 } 557 558 static void de_conf_addr(dpeth_t * dep) 559 { 560 static char ea_fmt[] = "x:x:x:x:x:x"; 561 char ea_key[16]; 562 int ix; 563 long val; 564 565 strlcpy(ea_key, "DEETH0_EA", sizeof(ea_key)); 566 ea_key[5] += de_instance; 567 568 for (ix = 0; ix < SA_ADDR_LEN; ix++) { 569 val = dep->de_address.ea_addr[ix]; 570 if (env_parse(ea_key, ea_fmt, ix, &val, 0x00L, 0xFFL) != EP_SET) 571 break; 572 dep->de_address.ea_addr[ix] = val; 573 } 574 575 if (ix != 0 && ix != SA_ADDR_LEN) 576 env_parse(ea_key, "?", 0, &val, 0L, 0L); 577 return; 578 } 579 580 static void de_first_init(dpeth_t *dep) 581 { 582 int i,j,r; 583 vir_bytes descr_vir = (vir_bytes)dep->sendrecv_descr_buf; 584 vir_bytes buffer_vir = (vir_bytes)dep->sendrecv_buf; 585 de_loc_descr_t *loc_descr; 586 phys_bytes temp; 587 588 589 for(i=0;i<2;i++){ 590 loc_descr = &dep->descr[i][0]; 591 for(j=0; j < (i==DESCR_RECV ? DE_NB_RECV_DESCR : DE_NB_SEND_DESCR); j++){ 592 593 /* assign buffer space for descriptor */ 594 loc_descr->descr = (void*)descr_vir; 595 descr_vir += sizeof(de_descr_t); 596 597 /* assign space for buffer */ 598 loc_descr->buf1 = (u8_t*)buffer_vir; 599 buffer_vir += (i==DESCR_RECV ? DE_RECV_BUF_SIZE : DE_SEND_BUF_SIZE); 600 loc_descr->buf2 = 0; 601 loc_descr++; 602 } 603 } 604 605 /* Now that we have buffer space and descriptors, we need to 606 obtain their physical address to pass to the hardware 607 */ 608 for(i=0;i<2;i++){ 609 loc_descr = &dep->descr[i][0]; 610 temp = (i==DESCR_RECV ? DE_RECV_BUF_SIZE : DE_SEND_BUF_SIZE); 611 for(j=0; j < (i==DESCR_RECV ? DE_NB_RECV_DESCR : DE_NB_SEND_DESCR); j++){ 612 /* translate buffers physical address */ 613 r = sys_umap(SELF, VM_D, (vir_bytes)loc_descr->buf1, temp, 614 (phys_bytes *) &(loc_descr->descr->des[DES_BUF1])); 615 if(r != OK) panic("umap failed: %d", r); 616 loc_descr->descr->des[DES_BUF2] = 0; 617 memset(&loc_descr->descr->des[DES0],0,sizeof(u32_t)); 618 loc_descr->descr->des[DES1] = temp; 619 if(j==( (i==DESCR_RECV?DE_NB_RECV_DESCR:DE_NB_SEND_DESCR)-1)) 620 loc_descr->descr->des[DES1] |= DES1_ER; 621 if(i==DESCR_RECV) 622 loc_descr->descr->des[DES0] |= DES0_OWN; 623 loc_descr++; 624 } 625 } 626 627 /* record physical location of two first descriptor */ 628 r = sys_umap(SELF, VM_D, (vir_bytes)dep->descr[DESCR_RECV][0].descr, 629 sizeof(de_descr_t), &dep->sendrecv_descr_phys_addr[DESCR_RECV]); 630 if(r != OK) panic("%s %d", str_UmapErrMsg, r); 631 632 r = sys_umap(SELF, VM_D, (vir_bytes)dep->descr[DESCR_TRAN][0].descr, 633 sizeof(de_descr_t), &dep->sendrecv_descr_phys_addr[DESCR_TRAN]); 634 if(r != OK) panic("%s %d", str_UmapErrMsg, r); 635 636 DEBUG(printf("Descr: head tran=[%08X] head recv=[%08X]\n", 637 dep->sendrecv_descr_phys_addr[DESCR_TRAN], 638 dep->sendrecv_descr_phys_addr[DESCR_RECV])); 639 640 /* check alignment just to be extra safe */ 641 for(i=0;i<2;i++){ 642 loc_descr = &dep->descr[i][0]; 643 for(j=0;j< (i==DESCR_RECV?DE_NB_RECV_DESCR:DE_NB_SEND_DESCR);j++){ 644 r = sys_umap(SELF, VM_D, (vir_bytes)&(loc_descr->descr), 645 sizeof(de_descr_t), &temp); 646 if(r != OK) 647 panic("%s %d", str_UmapErrMsg, r); 648 649 if( ((loc_descr->descr->des[DES_BUF1] & 0x3) != 0) || 650 ((loc_descr->descr->des[DES_BUF2] & 0x3) != 0) || 651 ((temp&0x3)!=0) ) 652 panic("%s 0x%lx", str_AlignErrMsg, temp); 653 654 loc_descr++; 655 } 656 } 657 658 /* Init default values */ 659 dep->cur_descr[DESCR_TRAN]=1; 660 dep->cur_descr[DESCR_RECV]=0; 661 dep->bytes_rx = 0; 662 dep->bytes_tx = 0; 663 664 /* Set the interrupt handler policy. Request interrupts not to be reenabled 665 * automatically. Return the IRQ line number when an interrupt occurs. 666 */ 667 dep->de_hook = dep->de_irq; 668 sys_irqsetpolicy(dep->de_irq, 0, &dep->de_hook); 669 sys_irqenable(&dep->de_hook); 670 } 671 672 static void do_interrupt(const dpeth_t *dep){ 673 u32_t val; 674 val = io_inl(CSR_ADDR(dep, CSR5)); 675 676 if(val & CSR5_AIS){ 677 panic("Abnormal Int CSR5=: %d", val); 678 } 679 680 if( (dep->de_flags & DEF_READING) && (val & CSR5_RI) ){ 681 do_vread_s(&dep->rx_return_msg, TRUE); 682 } 683 684 if( (dep->de_flags & DEF_SENDING) && (val & CSR5_TI) ){ 685 do_vwrite_s(&dep->tx_return_msg, TRUE); 686 } 687 688 /* ack and reset interrupts */ 689 io_outl(CSR_ADDR(dep, CSR5), 0xFFFFFFFF); 690 return; 691 } 692 693 static void de_reset(const dpeth_t *dep){ 694 io_outl(CSR_ADDR(dep, CSR0), CSR0_SWR); 695 } 696 697 static void de_hw_conf(const dpeth_t *dep){ 698 u32_t val; 699 700 /* CSR0 - global host bus prop */ 701 val = CSR0_BAR | CSR0_CAL_8; 702 io_outl(CSR_ADDR(dep, CSR0), val); 703 704 /* CSR3 - Receive list BAR */ 705 val = dep->sendrecv_descr_phys_addr[DESCR_RECV]; 706 io_outl(CSR_ADDR(dep, CSR3), val); 707 708 /* CSR4 - Transmit list BAR */ 709 val = dep->sendrecv_descr_phys_addr[DESCR_TRAN]; 710 io_outl(CSR_ADDR(dep, CSR4), val); 711 712 /* CSR7 - interrupt mask */ 713 val = CSR7_TI | CSR7_RI | CSR7_AI; 714 io_outl(CSR_ADDR(dep, CSR7), val); 715 716 /* CSR6 - operating mode register */ 717 val = CSR6_MBO | CSR6_PS | CSR6_FD | CSR6_HBD | 718 CSR6_PCS | CSR6_SCR | CSR6_TR_00; 719 io_outl(CSR_ADDR(dep, CSR6), val); 720 } 721 722 static void de_start(const dpeth_t *dep){ 723 u32_t val; 724 val = io_inl(CSR_ADDR(dep, CSR6)) | CSR6_ST | CSR6_SR; 725 io_outl(CSR_ADDR(dep, CSR6), val); 726 } 727 728 static void de_setup_frame(const dpeth_t *dep){ 729 int i; 730 u32_t val; 731 732 /* this is not perfect... we assume pass all multicast and only 733 filter non-multicast frames */ 734 dep->descr[DESCR_TRAN][0].buf1[0] = 0xFF; 735 dep->descr[DESCR_TRAN][0].buf1[1] = 0xFF; 736 dep->descr[DESCR_TRAN][0].buf1[4] = 0xFF; 737 dep->descr[DESCR_TRAN][0].buf1[5] = 0xFF; 738 dep->descr[DESCR_TRAN][0].buf1[8] = 0xFF; 739 dep->descr[DESCR_TRAN][0].buf1[9] = 0xFF; 740 for(i=1;i<16;i++){ 741 memset(&(dep->descr[DESCR_TRAN][0].buf1[12*i]), 0, 12); 742 dep->descr[DESCR_TRAN][0].buf1[12*i+0] = dep->de_address.ea_addr[0]; 743 dep->descr[DESCR_TRAN][0].buf1[12*i+1] = dep->de_address.ea_addr[1]; 744 dep->descr[DESCR_TRAN][0].buf1[12*i+4] = dep->de_address.ea_addr[2]; 745 dep->descr[DESCR_TRAN][0].buf1[12*i+5] = dep->de_address.ea_addr[3]; 746 dep->descr[DESCR_TRAN][0].buf1[12*i+8] = dep->de_address.ea_addr[4]; 747 dep->descr[DESCR_TRAN][0].buf1[12*i+9] = dep->de_address.ea_addr[5]; 748 } 749 750 dep->descr[DESCR_TRAN][0].descr->des[DES0] = DES0_OWN; 751 dep->descr[DESCR_TRAN][0].descr->des[DES1] = DES1_SET | 752 DE_SETUP_FRAME_SIZE | DES1_IC; 753 754 /* start transmit process to process setup frame */ 755 val = io_inl(CSR_ADDR(dep, CSR6)) | CSR6_ST; 756 io_outl(CSR_ADDR(dep, CSR6), val); 757 io_outl(CSR_ADDR(dep, CSR1), 0xFFFFFFFF); 758 759 return; 760 } 761 762 static int de_calc_iov_size(iovec_dat_s_t * iovp){ 763 int size, ix; 764 size = ix = 0; 765 766 do{ 767 size += iovp->iod_iovec[ix].iov_size; 768 if (++ix >= IOVEC_NR) { 769 de_next_iov(iovp); 770 ix = 0; 771 } 772 } while (ix < iovp->iod_iovec_s); 773 return size; 774 } 775 776 static void de_get_userdata_s(int user_proc, cp_grant_id_t grant, 777 vir_bytes offset, int count, void *loc_addr){ 778 int rc; 779 vir_bytes len; 780 781 len = (count > IOVEC_NR ? IOVEC_NR : count) * sizeof(iovec_t); 782 rc = sys_safecopyfrom(user_proc, grant, 0, (vir_bytes)loc_addr, len); 783 if (rc != OK) 784 panic("%s %d", str_CopyErrMsg, rc); 785 return; 786 } 787 788 static void de_next_iov(iovec_dat_s_t * iovp){ 789 790 iovp->iod_iovec_s -= IOVEC_NR; 791 iovp->iod_iovec_offset += IOVEC_NR * sizeof(iovec_t); 792 de_get_userdata_s(iovp->iod_proc_nr, iovp->iod_grant, iovp->iod_iovec_offset, 793 iovp->iod_iovec_s, iovp->iod_iovec); 794 return; 795 } 796 797 static void do_vwrite_s(const message * mp, int from_int){ 798 static u8_t setupDone = 0; 799 int size, r, bytes, ix, totalsize; 800 dpeth_t *dep; 801 iovec_dat_s_t *iovp = NULL; 802 de_loc_descr_t *descr = NULL; 803 u8_t *buffer = NULL; 804 805 dep = &de_state; 806 807 dep->de_client = mp->m_source; 808 809 if (dep->de_mode == DEM_ENABLED) { 810 811 if (!from_int && (dep->de_flags & DEF_SENDING)) 812 panic("%s", str_BusyErrMsg); 813 814 descr = &dep->descr[DESCR_TRAN][dep->cur_descr[DESCR_TRAN]]; 815 816 if(( descr->descr->des[DES0] & DES0_OWN)!=0) 817 goto suspend; 818 819 if(!setupDone && (dep->cur_descr[DESCR_TRAN] == 0) ){ 820 dep->descr[DESCR_TRAN][0].descr->des[DES0] = 0; 821 setupDone=1; 822 } 823 824 buffer = descr->buf1; 825 iovp = &dep->de_write_iovec; 826 iovp->iod_proc_nr = mp->m_source; 827 de_get_userdata_s(mp->m_source, mp->m_net_netdrv_dl_writev_s.grant, 0, 828 mp->m_net_netdrv_dl_writev_s.count, iovp->iod_iovec); 829 iovp->iod_iovec_s = mp->m_net_netdrv_dl_writev_s.count; 830 iovp->iod_grant = mp->m_net_netdrv_dl_writev_s.grant; 831 iovp->iod_iovec_offset = 0; 832 totalsize = size = de_calc_iov_size(iovp); 833 if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE) 834 panic("%s %d", str_SizeErrMsg, size); 835 836 dep->bytes_tx += size; 837 dep->de_stat.ets_packetT++; 838 839 ix=0; 840 do { 841 bytes = iovp->iod_iovec[ix].iov_size; 842 if (bytes >= size) 843 bytes = size; 844 845 r= sys_safecopyfrom(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_grant, 846 0, (vir_bytes)buffer, bytes); 847 if (r != OK) 848 panic("%s %d", str_CopyErrMsg, r); 849 buffer += bytes; 850 851 if (++ix >= IOVEC_NR) { 852 de_next_iov(iovp); 853 ix = 0; 854 } 855 } while ((size -= bytes) > 0); 856 857 descr->descr->des[DES1] = (descr->descr->des[DES1]&DES1_ER) | 858 DES1_FS | DES1_LS | DES1_IC | totalsize; 859 descr->descr->des[DES0] = DES0_OWN; 860 861 dep->cur_descr[DESCR_TRAN]++; 862 if(dep->cur_descr[DESCR_TRAN] >= DE_NB_SEND_DESCR) 863 dep->cur_descr[DESCR_TRAN] = 0; 864 865 io_outl(CSR_ADDR(dep, CSR1), 0xFFFFFFFF); 866 } 867 868 dep->de_flags |= DEF_ACK_SEND; 869 if(from_int){ 870 dep->de_flags &= NOT(DEF_SENDING); 871 return; 872 } 873 do_reply(dep); 874 return; 875 876 suspend: 877 if(from_int) 878 panic("should not happen: %d", 0); 879 880 dep->de_stat.ets_transDef++; 881 dep->de_flags |= DEF_SENDING; 882 dep->de_stat.ets_transDef++; 883 dep->tx_return_msg = *mp; 884 do_reply(dep); 885 } 886 887 static void warning(const char *type, int err){ 888 printf("Warning: %s sys_%s failed (%d)\n", str_DevName, type, err); 889 return; 890 } 891 892 static u32_t io_inl(u16_t port){ 893 u32_t value; 894 int rc; 895 if ((rc = sys_inl(port, &value)) != OK) warning("inl", rc); 896 return value; 897 } 898 899 static void io_outl(u16_t port, u32_t value){ 900 int rc; 901 if ((rc = sys_outl(port, value)) != OK) warning("outl", rc); 902 return; 903 } 904