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 <machine/pci.h> 16 #include <assert.h> 17 18 #include "dec21140A.h" 19 20 static u32_t io_inl(u16_t); 21 static void io_outl(u16_t, u32_t); 22 23 static int do_init(unsigned int, ether_addr_t *); 24 static void do_stop(void); 25 static int do_send(struct netdriver_data *, size_t); 26 static ssize_t do_recv(struct netdriver_data *, size_t); 27 static void do_stat(eth_stat_t *); 28 static void do_intr(unsigned int); 29 30 static int de_probe(dpeth_t *, unsigned int skip); 31 static void de_conf_addr(dpeth_t *, ether_addr_t *); 32 static void de_init_buf(dpeth_t *); 33 static void de_reset(const dpeth_t *); 34 static void de_hw_conf(const dpeth_t *); 35 static void de_start(const dpeth_t *); 36 static void de_setup_frame(const dpeth_t *, const ether_addr_t *); 37 static u16_t de_read_rom(const dpeth_t *, u8_t, u8_t); 38 39 static dpeth_t de_state; 40 static int de_instance; 41 42 static const struct netdriver de_table = { 43 .ndr_init = do_init, 44 .ndr_stop = do_stop, 45 .ndr_recv = do_recv, 46 .ndr_send = do_send, 47 .ndr_stat = do_stat, 48 .ndr_intr = do_intr 49 }; 50 51 int main(int argc, char *argv[]) 52 { 53 env_setargs(argc, argv); 54 55 netdriver_task(&de_table); 56 57 return 0; 58 } 59 60 static void de_init_hw(dpeth_t *dep, ether_addr_t *addr) 61 { 62 de_reset(dep); 63 de_conf_addr(dep, addr); 64 de_init_buf(dep); 65 66 /* Set the interrupt handler policy. Request interrupts not to be reenabled 67 * automatically. Return the IRQ line number when an interrupt occurs. 68 */ 69 dep->de_hook = dep->de_irq; 70 sys_irqsetpolicy(dep->de_irq, 0, &dep->de_hook); 71 sys_irqenable(&dep->de_hook); 72 73 de_reset(dep); 74 de_hw_conf(dep); 75 de_setup_frame(dep, addr); 76 de_start(dep); 77 } 78 79 static int do_init(unsigned int instance, ether_addr_t *addr) 80 { 81 /* Initialize the DEC 21140A driver. */ 82 dpeth_t *dep; 83 84 dep = &de_state; 85 memset(dep, 0, sizeof(*dep)); 86 87 strlcpy(dep->de_name, "dec21140A:?", sizeof(dep->de_name)); 88 dep->de_name[strlen(dep->de_name)-1] = '0' + instance; 89 90 de_instance = instance; 91 92 if (!de_probe(dep, instance)) 93 return ENXIO; 94 95 de_init_hw(dep, addr); 96 97 return OK; 98 } 99 100 static void do_stat(eth_stat_t *stat) 101 { 102 memcpy(stat, &de_state.de_stat, sizeof(*stat)); 103 } 104 105 static int de_probe(dpeth_t *dep, unsigned int skip) 106 { 107 int r, devind; 108 u16_t vid, did; 109 110 DEBUG(printf("PROBING...")); 111 112 pci_init(); 113 114 r= pci_first_dev(&devind, &vid, &did); 115 if (r == 0) 116 return FALSE; 117 118 while (skip--) 119 { 120 r= pci_next_dev(&devind, &vid, &did); 121 if (!r) 122 return FALSE; 123 } 124 125 pci_reserve(devind); 126 127 dep->de_base_port = pci_attr_r32(devind, PCI_BAR) & 0xffffffe0; 128 dep->de_irq = pci_attr_r8(devind, PCI_ILR); 129 130 if (dep->de_base_port < DE_MIN_BASE_ADDR) 131 panic("de_probe: base address invalid: %d", dep->de_base_port); 132 133 DEBUG(printf("%s: using I/O address 0x%lx, IRQ %d\n", 134 dep->de_name, (unsigned long)dep->de_base_port, 135 dep->de_irq)); 136 137 dep->de_type = pci_attr_r8(devind, PCI_REV); 138 139 /* device validation. We support only the DEC21140A */ 140 if(dep->de_type != DEC_21140A){ 141 printf("%s: unsupported card type %x\n", dep->de_name, dep->de_type); 142 return FALSE; 143 } 144 145 return TRUE; 146 } 147 148 static u16_t de_read_rom(const dpeth_t *dep, u8_t addr, u8_t nbAddrBits) 149 { 150 u16_t retVal = 0; 151 int i; 152 u32_t csr = 0; 153 u32_t csr2 = 0; /* csr2 is used to hold constant values that are 154 setup in the init phase, it makes this a little 155 more readable, the following macro is also just 156 to clear up the code a little.*/ 157 158 #define EMIT \ 159 do { \ 160 io_outl(CSR_ADDR(dep, CSR9), csr | csr2); \ 161 io_outl(CSR_ADDR(dep, CSR1), 0); \ 162 } while(0) 163 164 /* init */ 165 csr = 0; EMIT; 166 csr = CSR9_SR; EMIT; 167 csr = CSR9_SR | CSR9_RD; EMIT; 168 169 csr2 = CSR9_SR | CSR9_RD; 170 csr = 0; EMIT; 171 csr2 |= CSR9_CS; 172 173 csr = 0; EMIT; 174 csr = CSR9_SRC; EMIT; 175 csr = 0; EMIT; 176 177 /* cmd 110 - Read */ 178 csr = CSR9_DI; EMIT; 179 csr = CSR9_DI | CSR9_SRC; EMIT; 180 csr = CSR9_DI; EMIT; 181 csr = CSR9_DI | CSR9_SRC; EMIT; 182 csr = CSR9_DI; EMIT; 183 csr = 0; EMIT; 184 csr = CSR9_SRC; EMIT; 185 csr = 0; EMIT; 186 187 /* addr to read */ 188 for(i=nbAddrBits;i!=0;i--){ 189 csr = (addr&(1<<(i-1))) != 0 ? CSR9_DI : 0; EMIT; 190 csr ^= CSR9_SRC; EMIT; 191 csr ^= CSR9_SRC; EMIT; 192 } 193 194 /* actual read */ 195 retVal=0; 196 for(i=0;i<16;i++){ 197 retVal <<= 1; 198 csr = CSR9_SRC; EMIT; 199 retVal |= (io_inl(CSR_ADDR(dep, CSR9)) & CSR9_DO) == 0 ? 0 : 1; 200 csr = 0; EMIT; 201 } 202 203 /* clean up */ 204 csr = 0; EMIT; 205 206 #undef EMIT 207 return retVal; 208 } 209 210 static ssize_t do_recv(struct netdriver_data *data, size_t max) 211 { 212 u32_t size; 213 dpeth_t *dep; 214 de_loc_descr_t *descr; 215 216 dep = &de_state; 217 218 descr = &dep->descr[DESCR_RECV][dep->cur_descr[DESCR_RECV]]; 219 220 /* check if packet is in the current descr and only there */ 221 if ((descr->descr->des[DES0] & DES0_OWN) || 222 !(descr->descr->des[DES0] & DES0_FS) || 223 !(descr->descr->des[DES0] & DES0_LS)) 224 return SUSPEND; 225 226 /*TODO: multi-descr msgs...*/ 227 /* We only support packets contained in a single descriptor. 228 Setting the descriptor buffer size to less then 229 ETH_MAX_PACK_SIZE will result in multi-descriptor 230 packets that we won't be able to handle 231 */ 232 233 /* Check for abnormal messages. We assert here 234 because this driver is for a virtualized 235 envrionment where we will not get bad packets 236 */ 237 assert(!(descr->descr->des[DES0]&DES0_ES)); 238 assert(!(descr->descr->des[DES0]&DES0_RE)); 239 240 /* Copy buffer to user area and clear ownage */ 241 size = (descr->descr->des[DES0]&DES0_FL)>>DES0_FL_SHIFT; 242 243 /* HACK: VPC2007 sends short-sized packets, pad to minimum ethernet length */ 244 if(size<60){ 245 memset(&descr->buf1[size], 0, 60-size); 246 size=60; 247 } 248 249 /* Truncate large packets */ 250 if (size > max) 251 size = max; 252 253 netdriver_copyout(data, 0, descr->buf1, size); 254 255 dep->de_stat.ets_packetR++; 256 257 descr->descr->des[DES0]=DES0_OWN; 258 dep->cur_descr[DESCR_RECV]++; 259 if(dep->cur_descr[DESCR_RECV] >= DE_NB_RECV_DESCR) 260 dep->cur_descr[DESCR_RECV] = 0; 261 262 DEBUG(printf("Read returned size = %d\n", size)); 263 264 return size; 265 } 266 267 static void de_conf_addr(dpeth_t *dep, ether_addr_t *addr) 268 { 269 u16_t temp16; 270 int i; 271 272 DEBUG(printf("Reading SROM...\n")); 273 274 for(i=0;i<(1<<SROM_BITWIDTH)-1;i++){ 275 temp16 = de_read_rom(dep, i, SROM_BITWIDTH); 276 dep->srom[i*2] = temp16 & 0xFF; 277 dep->srom[i*2+1] = temp16 >> 8; 278 } 279 280 /* TODO: validate SROM content */ 281 /* acquire MAC addr */ 282 DEBUG(printf("Using MAC addr= ")); 283 for(i=0;i<6;i++){ 284 addr->ea_addr[i] = dep->srom[i+DE_SROM_EA_OFFSET]; 285 DEBUG(printf("%02X%c", addr->ea_addr[i],i!=5?'-':'\n')); 286 } 287 DEBUG(printf("probe success\n")); 288 } 289 290 static void de_init_buf(dpeth_t *dep) 291 { 292 int i,j,r; 293 vir_bytes descr_vir = (vir_bytes)dep->sendrecv_descr_buf; 294 vir_bytes buffer_vir = (vir_bytes)dep->sendrecv_buf; 295 de_loc_descr_t *loc_descr; 296 phys_bytes temp; 297 298 for(i=0;i<2;i++){ 299 loc_descr = &dep->descr[i][0]; 300 for(j=0; j < (i==DESCR_RECV ? DE_NB_RECV_DESCR : DE_NB_SEND_DESCR); j++){ 301 302 /* assign buffer space for descriptor */ 303 loc_descr->descr = (void*)descr_vir; 304 descr_vir += sizeof(de_descr_t); 305 306 /* assign space for buffer */ 307 loc_descr->buf1 = (u8_t*)buffer_vir; 308 buffer_vir += (i==DESCR_RECV ? DE_RECV_BUF_SIZE : DE_SEND_BUF_SIZE); 309 loc_descr->buf2 = 0; 310 loc_descr++; 311 } 312 } 313 314 /* Now that we have buffer space and descriptors, we need to 315 obtain their physical address to pass to the hardware 316 */ 317 for(i=0;i<2;i++){ 318 loc_descr = &dep->descr[i][0]; 319 temp = (i==DESCR_RECV ? DE_RECV_BUF_SIZE : DE_SEND_BUF_SIZE); 320 for(j=0; j < (i==DESCR_RECV ? DE_NB_RECV_DESCR : DE_NB_SEND_DESCR); j++){ 321 /* translate buffers physical address */ 322 r = sys_umap(SELF, VM_D, (vir_bytes)loc_descr->buf1, temp, 323 (phys_bytes *) &(loc_descr->descr->des[DES_BUF1])); 324 if(r != OK) panic("umap failed: %d", r); 325 loc_descr->descr->des[DES_BUF2] = 0; 326 memset(&loc_descr->descr->des[DES0],0,sizeof(u32_t)); 327 loc_descr->descr->des[DES1] = temp; 328 if(j==( (i==DESCR_RECV?DE_NB_RECV_DESCR:DE_NB_SEND_DESCR)-1)) 329 loc_descr->descr->des[DES1] |= DES1_ER; 330 if(i==DESCR_RECV) 331 loc_descr->descr->des[DES0] |= DES0_OWN; 332 loc_descr++; 333 } 334 } 335 336 /* record physical location of two first descriptor */ 337 r = sys_umap(SELF, VM_D, (vir_bytes)dep->descr[DESCR_RECV][0].descr, 338 sizeof(de_descr_t), &dep->sendrecv_descr_phys_addr[DESCR_RECV]); 339 if(r != OK) panic("sys_umap failed: %d", r); 340 341 r = sys_umap(SELF, VM_D, (vir_bytes)dep->descr[DESCR_TRAN][0].descr, 342 sizeof(de_descr_t), &dep->sendrecv_descr_phys_addr[DESCR_TRAN]); 343 if(r != OK) panic("sys_umap failed: %d", r); 344 345 DEBUG(printf("Descr: head tran=[%08X] head recv=[%08X]\n", 346 dep->sendrecv_descr_phys_addr[DESCR_TRAN], 347 dep->sendrecv_descr_phys_addr[DESCR_RECV])); 348 349 /* check alignment just to be extra safe */ 350 for(i=0;i<2;i++){ 351 loc_descr = &dep->descr[i][0]; 352 for(j=0;j< (i==DESCR_RECV?DE_NB_RECV_DESCR:DE_NB_SEND_DESCR);j++){ 353 r = sys_umap(SELF, VM_D, (vir_bytes)&(loc_descr->descr), 354 sizeof(de_descr_t), &temp); 355 if(r != OK) panic("sys_umap failed: %d", r); 356 357 if( ((loc_descr->descr->des[DES_BUF1] & 0x3) != 0) || 358 ((loc_descr->descr->des[DES_BUF2] & 0x3) != 0) || 359 ((temp&0x3)!=0) ) 360 panic("alignment error: 0x%lx", temp); 361 362 loc_descr++; 363 } 364 } 365 366 /* Init default values */ 367 dep->cur_descr[DESCR_TRAN]=1; 368 dep->cur_descr[DESCR_RECV]=0; 369 } 370 371 static void do_intr(unsigned int __unused mask) 372 { 373 dpeth_t *dep; 374 u32_t val; 375 376 dep = &de_state; 377 378 val = io_inl(CSR_ADDR(dep, CSR5)); 379 380 if(val & CSR5_AIS){ 381 panic("Abnormal Int CSR5=: %d", val); 382 } 383 384 if (val & CSR5_RI) 385 netdriver_recv(); 386 387 if (val & CSR5_TI) 388 netdriver_send(); 389 390 /* ack and reset interrupts */ 391 io_outl(CSR_ADDR(dep, CSR5), 0xFFFFFFFF); 392 393 sys_irqenable(&dep->de_hook); 394 } 395 396 static void de_reset(const dpeth_t *dep) 397 { 398 io_outl(CSR_ADDR(dep, CSR0), CSR0_SWR); 399 } 400 401 static void do_stop(void) 402 { 403 de_reset(&de_state); 404 } 405 406 static void de_hw_conf(const dpeth_t *dep) 407 { 408 u32_t val; 409 410 /* CSR0 - global host bus prop */ 411 val = CSR0_BAR | CSR0_CAL_8; 412 io_outl(CSR_ADDR(dep, CSR0), val); 413 414 /* CSR3 - Receive list BAR */ 415 val = dep->sendrecv_descr_phys_addr[DESCR_RECV]; 416 io_outl(CSR_ADDR(dep, CSR3), val); 417 418 /* CSR4 - Transmit list BAR */ 419 val = dep->sendrecv_descr_phys_addr[DESCR_TRAN]; 420 io_outl(CSR_ADDR(dep, CSR4), val); 421 422 /* CSR7 - interrupt mask */ 423 val = CSR7_TI | CSR7_RI | CSR7_AI; 424 io_outl(CSR_ADDR(dep, CSR7), val); 425 426 /* CSR6 - operating mode register */ 427 val = CSR6_MBO | CSR6_PS | CSR6_FD | CSR6_HBD | 428 CSR6_PCS | CSR6_SCR | CSR6_TR_00; 429 io_outl(CSR_ADDR(dep, CSR6), val); 430 } 431 432 static void de_start(const dpeth_t *dep) 433 { 434 u32_t val; 435 val = io_inl(CSR_ADDR(dep, CSR6)) | CSR6_ST | CSR6_SR; 436 io_outl(CSR_ADDR(dep, CSR6), val); 437 } 438 439 static void de_setup_frame(const dpeth_t *dep, const ether_addr_t *addr) 440 { 441 int i; 442 u32_t val; 443 444 /* this is not perfect... we assume pass all multicast and only 445 filter non-multicast frames */ 446 dep->descr[DESCR_TRAN][0].buf1[0] = 0xFF; 447 dep->descr[DESCR_TRAN][0].buf1[1] = 0xFF; 448 dep->descr[DESCR_TRAN][0].buf1[4] = 0xFF; 449 dep->descr[DESCR_TRAN][0].buf1[5] = 0xFF; 450 dep->descr[DESCR_TRAN][0].buf1[8] = 0xFF; 451 dep->descr[DESCR_TRAN][0].buf1[9] = 0xFF; 452 for(i=1;i<16;i++){ 453 memset(&(dep->descr[DESCR_TRAN][0].buf1[12*i]), 0, 12); 454 dep->descr[DESCR_TRAN][0].buf1[12*i+0] = addr->ea_addr[0]; 455 dep->descr[DESCR_TRAN][0].buf1[12*i+1] = addr->ea_addr[1]; 456 dep->descr[DESCR_TRAN][0].buf1[12*i+4] = addr->ea_addr[2]; 457 dep->descr[DESCR_TRAN][0].buf1[12*i+5] = addr->ea_addr[3]; 458 dep->descr[DESCR_TRAN][0].buf1[12*i+8] = addr->ea_addr[4]; 459 dep->descr[DESCR_TRAN][0].buf1[12*i+9] = addr->ea_addr[5]; 460 } 461 462 dep->descr[DESCR_TRAN][0].descr->des[DES0] = DES0_OWN; 463 dep->descr[DESCR_TRAN][0].descr->des[DES1] = DES1_SET | 464 DE_SETUP_FRAME_SIZE | DES1_IC; 465 466 /* start transmit process to process setup frame */ 467 val = io_inl(CSR_ADDR(dep, CSR6)) | CSR6_ST; 468 io_outl(CSR_ADDR(dep, CSR6), val); 469 io_outl(CSR_ADDR(dep, CSR1), 0xFFFFFFFF); 470 } 471 472 static int do_send(struct netdriver_data *data, size_t size) 473 { 474 static int setup_done = 0; 475 dpeth_t *dep; 476 de_loc_descr_t *descr = NULL; 477 478 dep = &de_state; 479 480 descr = &dep->descr[DESCR_TRAN][dep->cur_descr[DESCR_TRAN]]; 481 482 if(( descr->descr->des[DES0] & DES0_OWN)!=0) 483 return SUSPEND; 484 485 if(!setup_done && (dep->cur_descr[DESCR_TRAN] == 0) ){ 486 dep->descr[DESCR_TRAN][0].descr->des[DES0] = 0; 487 setup_done=1; 488 } 489 490 netdriver_copyin(data, 0, descr->buf1, size); 491 492 descr->descr->des[DES1] = (descr->descr->des[DES1]&DES1_ER) | 493 DES1_FS | DES1_LS | DES1_IC | size; 494 descr->descr->des[DES0] = DES0_OWN; 495 496 dep->cur_descr[DESCR_TRAN]++; 497 if(dep->cur_descr[DESCR_TRAN] >= DE_NB_SEND_DESCR) 498 dep->cur_descr[DESCR_TRAN] = 0; 499 500 io_outl(CSR_ADDR(dep, CSR1), 0xFFFFFFFF); 501 502 dep->de_stat.ets_packetT++; 503 504 return OK; 505 } 506 507 static u32_t io_inl(u16_t port) 508 { 509 u32_t value; 510 int rc; 511 if ((rc = sys_inl(port, &value)) != OK) 512 panic("sys_inl failed: %d", rc); 513 return value; 514 } 515 516 static void io_outl(u16_t port, u32_t value) 517 { 518 int rc; 519 if ((rc = sys_outl(port, value)) != OK) 520 panic("sys_outl failed: %d", rc); 521 } 522