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