1/* 2 * Copyright 2006, Hideyuki Abe. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6//! Ethernet Driver for VMware PCnet/PCI virtual network controller 7 8#include "vlance.h" 9 10#include <ether_driver.h> 11 12#include <Drivers.h> 13#include <KernelExport.h> 14#include <OS.h> 15#include <PCI.h> 16 17#include <stdarg.h> 18#include <stdlib.h> 19#include <stdio.h> 20#include <string.h> 21 22 23/* debug flag definitions */ 24#define ERR 0x0001 25#define INFO 0x0002 26#define RX 0x0004 /* dump received frames */ 27#define TX 0x0008 /* dump transmitted frames */ 28#define INTERRUPT 0x0010 /* interrupt calls */ 29#define FUNCTION 0x0020 /* function calls */ 30#define PCI_IO 0x0040 /* pci reads and writes */ 31#define SEQ 0x0080 /* trasnmit & receive TCP/IP sequence sequence numbers */ 32#define WARN 0x0100 /* Warnings - off on final release */ 33 34/* debug flag */ 35//#define DEBUG_FLG ( ERR | INFO | WARN ) 36//#define DEBUG_FLG ( ERR | INFO | INTERRUPT | FUNCTION | WARN ) 37#define DEBUG_FLG ( ERR | WARN ) 38 39#define DEBUG(x) (DEBUG_FLG & (x)) 40#define TRACE(x) dprintf x 41 42/* PCI vendor and device ID's */ 43#define VENDOR_ID 0x1022 /* AMD */ 44#define DEVICE_ID 0x2000 /* PCnet/PCI */ 45 46 47#define DEVICE_NAME "vlance" 48#define DEVICE_NAME_LEN 64 49 50#define MAX_CARDS 4 /* maximum number of driver instances */ 51 52#define BUFFER_SIZE 2048L /* B_PAGE_SIZE divided into even amounts that will hold a 1518 frame */ 53#define MAX_FRAME_SIZE 1514 /* 1514 + 4 bytes checksum */ 54 55/* ring buffer sizes */ 56#define TX_BUFF_IDX (4) 57#define RX_BUFF_IDX (5) 58#define TX_BUFFERS (1 << TX_BUFF_IDX) 59#define RX_BUFFERS (1 << RX_BUFF_IDX) /* Must be a power of 2 */ 60 61/* max number of multicast address */ 62#define MAX_MULTI (4) 63 64 65/* 66 * 6-octet MAC address 67 */ 68typedef struct { 69 uint8 ch[6]; 70 uint8 rsv[2]; 71} mac_addr_t; 72 73 74/* driver intance definition */ 75typedef struct { 76 mac_addr_t mac_addr; /* MAC address */ 77 int32 devID; /* device identifier */ 78 pci_info *devInfo; /* device information */ 79 uint16 irq; /* our IRQ line */ 80 sem_id ilock, olock; /* I/O semaphores */ 81 int32 readLock, writeLock; /* reentrant read/write lock */ 82 int32 blockFlg; /* for blocking (0) or nonblocking (!=0) read */ 83 init_block_t init_blk; /* Initialization Block */ 84 uint32 phys_init_blk; /* Initialization Block physical address */ 85 area_id tx_desc_area; /* transmit descriptor area */ 86 area_id tx_buf_area; /* transmit buffer area */ 87 area_id rx_desc_area; /* receive descriptor area */ 88 area_id rx_buf_area; /* receive buffer area */ 89 uchar *tx_buf[TX_BUFFERS]; /* tx buffers */ 90 uchar *rx_buf[RX_BUFFERS]; /* rx buffers */ 91 trns_desc_t *tx_desc[TX_BUFFERS]; /* tx frame descriptors */ 92 recv_desc_t *rx_desc[RX_BUFFERS]; /* rx frame descriptors */ 93 uint32 phys_tx_buf; /* tx buffer physical address */ 94 uint32 phys_rx_buf; /* rx buffer physical address */ 95 uint32 phys_tx_desc; /* tx descriptor physical address */ 96 uint32 phys_rx_desc; /* rx descriptor physical address */ 97 int16 tx_sent, tx_acked; /* in & out index to tx buffers */ 98 int16 rx_received, rx_acked; /* in & out index to rx buffers */ 99 int32 nmulti; /* number of multicast address */ 100 mac_addr_t multi[MAX_MULTI]; /* multicast address */ 101 uint32 reg_base; /* base address of PCI regs */ 102} dev_info_t; 103 104 105/* function prototypes */ 106static status_t vlance_open(const char *name, uint32 flags, void **_cookie); 107static status_t vlance_close(void *_device); 108static status_t vlance_free(void *_device); 109static status_t vlance_control(void *cookie, uint32 msg, void *buf, size_t len); 110static status_t vlance_read(void *_device, off_t pos, void *buf, size_t *len); 111static status_t vlance_write(void *_device, off_t pos, const void *buf, size_t *len); 112static int32 vlance_interrupt(void *_device); 113 114static device_hooks sDeviceHooks = { 115 vlance_open, /* open entry point */ 116 vlance_close, /* close entry point */ 117 vlance_free, /* free entry point */ 118 vlance_control, /* control entry point */ 119 vlance_read, /* read entry point */ 120 vlance_write, /* write entry point */ 121 NULL, /* select entry point */ 122 NULL, /* deselect entry point */ 123 NULL, /* readv */ 124 NULL /* writev */ 125}; 126 127int32 api_version = B_CUR_DRIVER_API_VERSION; 128 129static pci_module_info *sPCI; 130static uint32 sNumOfCards; 131static char *sDeviceNames[MAX_CARDS + 1]; /* NULL-terminated */ 132static pci_info *sCardInfo[MAX_CARDS]; 133static int32 sOpenLock[MAX_CARDS]; 134 135 136#define write8(addr, val) (*sPCI->write_io_8)((addr), (val)) 137#define write16(addr, val) (*sPCI->write_io_16)((addr), (val)) 138#define write32(addr, val) (*sPCI->write_io_32)((addr), (val)) 139#define read8(addr) ((*sPCI->read_io_8)(addr)) 140#define read16(addr) ((*sPCI->read_io_16)(addr)) 141#define read32(addr) ((*sPCI->read_io_32)(addr)) 142 143#define RNDUP(x, y) (((x) + (y) - 1) & ~((y) - 1)) 144 145 146// #pragma mark - register access 147 148 149static inline uint32 150csr_read(dev_info_t *device, uint32 reg_num) 151{ 152 write32(device->reg_base + PCNET_RAP_OFFSET, reg_num); 153 return read32(device->reg_base + PCNET_RDP_OFFSET); 154} 155 156 157static inline void 158csr_write(dev_info_t *device, uint32 reg_num, uint32 data) 159{ 160 write32(device->reg_base + PCNET_RAP_OFFSET, reg_num); 161 write32(device->reg_base + PCNET_RDP_OFFSET, data); 162} 163 164 165static inline uint32 166bcr_read(dev_info_t *device, uint32 reg_num) 167{ 168 write32(device->reg_base + PCNET_RAP_OFFSET, reg_num); 169 return read32(device->reg_base + PCNET_BDP_OFFSET); 170} 171 172 173static inline void 174bcr_write(dev_info_t *device, uint32 reg_num, uint32 data) 175{ 176 write32(device->reg_base + PCNET_RAP_OFFSET, reg_num); 177 write32(device->reg_base + PCNET_BDP_OFFSET, data); 178} 179 180 181// #pragma mark - misc 182 183 184static int32 185get_card_info(pci_info *info[]) 186{ 187 status_t status; 188 int32 i, entries; 189 pci_info *item = (pci_info *)malloc(sizeof(pci_info)); 190 if (item == NULL) 191 return 0; 192 193 for (i = 0, entries = 0; entries < MAX_CARDS; i++) { 194 status = sPCI->get_nth_pci_info(i, item); 195 if (status != B_OK) 196 break; 197 198 if (item->vendor_id == VENDOR_ID && item->device_id == DEVICE_ID) { 199 /* check if the device really has an IRQ */ 200 if (item->u.h0.interrupt_line == 0 || item->u.h0.interrupt_line == 0xff) { 201 TRACE((DEVICE_NAME " found with invalid IRQ - check IRQ assignement\n")); 202 continue; 203 } 204 205 TRACE((DEVICE_NAME " found at IRQ %x\n", item->u.h0.interrupt_line)); 206 207 info[entries++] = item; 208 item = (pci_info *)malloc(sizeof(pci_info)); 209 } 210 } 211 212 free(item); 213 return entries; 214} 215 216 217static status_t 218free_card_info(pci_info *info[]) 219{ 220 int32 i; 221 222 for (i = 0; i < sNumOfCards; i++) { 223 free(info[i]); 224 } 225 226 return B_OK; 227} 228 229 230static status_t 231map_pci_addr(dev_info_t *device) 232{ 233 pci_info *dev_info = device->devInfo; 234 int32 pci_cmd; 235 236 pci_cmd = sPCI->read_pci_config(dev_info->bus, dev_info->device, 237 dev_info->function, PCI_command, 2); 238 239 /* turn on I/O port decode, Memory Address Decode, and Bus Mastering */ 240 sPCI->write_pci_config(dev_info->bus, dev_info->device, 241 dev_info->function, PCI_command, 2, 242 pci_cmd | PCI_command_io | PCI_command_memory | PCI_command_master); 243 244 device->reg_base = dev_info->u.h0.base_registers[0]; 245 246#if DEBUG(PCI_IO) 247 dprintf(DEVICE_NAME ": reg_base=%x\n", device->reg_base); 248#endif 249 250 return B_OK; 251} 252 253 254static status_t 255alloc_buffers(dev_info_t *device) 256{ 257 uint32 size; 258 uint16 i; 259 physical_entry entry; 260 261 /* get physical address of Initialization Block */ 262 size = RNDUP(sizeof(dev_info_t), B_PAGE_SIZE); 263 get_memory_map(&(device->init_blk), size, &entry, 1); 264 device->phys_init_blk = entry.address; 265 266 TRACE((DEVICE_NAME " init block va=%p pa=%p, size %lx\n", 267 &(device->init_blk), (void *)device->phys_init_blk, size)); 268 269 /* create tx descriptor area */ 270 size = RNDUP(sizeof(trns_desc_t) * TX_BUFFERS, B_PAGE_SIZE); 271 device->tx_desc_area = create_area(DEVICE_NAME " tx descriptors", 272 (void **)device->tx_desc, B_ANY_KERNEL_ADDRESS, size, 273 B_32_BIT_FULL_LOCK, B_READ_AREA | B_WRITE_AREA); 274 if (device->tx_desc_area < 0) 275 return device->tx_desc_area; 276 277 for (i = 1; i < TX_BUFFERS; i++) { 278 device->tx_desc[i] = (device->tx_desc[i-1]) + 1; 279 } 280 /* get physical address of tx descriptor */ 281 get_memory_map(device->tx_desc[0], size, &entry, 1); 282 device->phys_tx_desc = entry.address; 283 284 TRACE((DEVICE_NAME " create tx desc area va=%p pa=%p sz=%lx\n", 285 device->tx_desc[0], (void *)device->phys_tx_desc, size)); 286 287 /* create tx buffer area */ 288 size = RNDUP(BUFFER_SIZE * TX_BUFFERS, B_PAGE_SIZE); 289 device->tx_buf_area = create_area(DEVICE_NAME " tx buffers", 290 (void **)device->tx_buf, B_ANY_KERNEL_ADDRESS, size, 291 B_32_BIT_FULL_LOCK, B_READ_AREA | B_WRITE_AREA); 292 if (device->tx_buf_area < 0) { 293 delete_area(device->tx_desc_area); // sensitive to alloc ordering 294 return device->tx_buf_area; 295 } 296 297 for (i = 1; i < TX_BUFFERS; i++) { 298 device->tx_buf[i] = (device->tx_buf[i-1]) + BUFFER_SIZE; 299 } 300 301 /* get physical address of tx buffer */ 302 get_memory_map(device->tx_buf[0], size, &entry, 1); 303 device->phys_tx_buf = entry.address; 304 305 TRACE((DEVICE_NAME " create tx buf area va=%p pa=%08lx sz=%lx\n", 306 device->tx_buf[0], device->tx_desc[0]->s.tbadr, size)); 307 308 /* create rx descriptor area */ 309 size = RNDUP( sizeof(recv_desc_t) * RX_BUFFERS, B_PAGE_SIZE); 310 device->rx_desc_area = create_area(DEVICE_NAME " rx descriptors", 311 (void **)device->rx_desc, B_ANY_KERNEL_ADDRESS, size, 312 B_32_BIT_FULL_LOCK, B_READ_AREA | B_WRITE_AREA); 313 if (device->rx_desc_area < 0) { 314 delete_area(device->tx_desc_area); 315 delete_area(device->tx_buf_area); // sensitive to alloc ordering 316 return device->rx_desc_area; 317 } 318 319 for (i = 1; i < RX_BUFFERS; i++) { 320 device->rx_desc[i] = (device->rx_desc[i-1]) + 1; 321 } 322 /* get physical address of rx descriptor */ 323 get_memory_map(device->rx_desc[0], size, &entry, 1); 324 device->phys_rx_desc = entry.address; 325 326 TRACE((DEVICE_NAME " create rx desc area va=%p pa=%p sz=%lx\n", 327 device->rx_desc[0], (void *)device->phys_rx_desc, size)); 328 329 /* create rx buffer area */ 330 size = RNDUP(BUFFER_SIZE * RX_BUFFERS, B_PAGE_SIZE); 331 device->rx_buf_area = create_area(DEVICE_NAME " rx buffers", 332 (void **)device->rx_buf, B_ANY_KERNEL_ADDRESS, size, 333 B_32_BIT_FULL_LOCK, B_READ_AREA | B_WRITE_AREA); 334 if (device->rx_buf_area < 0) { 335 delete_area(device->tx_desc_area); 336 delete_area(device->tx_buf_area); 337 delete_area(device->rx_desc_area); // sensitive to alloc ordering 338 return device->rx_buf_area; 339 } 340 for (i = 1; i < RX_BUFFERS; i++) { 341 device->rx_buf[i] = (device->rx_buf[i-1]) + BUFFER_SIZE; 342 } 343 /* get physical address of rx buffer */ 344 get_memory_map(device->rx_buf[0], size, &entry, 1); 345 device->phys_rx_buf = entry.address; 346 347 TRACE((DEVICE_NAME " create rx buf area va=%p pa=%08lx sz=%lx\n", 348 device->rx_buf[0], device->rx_desc[0]->s.rbadr, size)); 349 350 return B_OK; 351} 352 353 354static status_t 355init_buffers(dev_info_t *device) 356{ 357 int i; 358 359 /* initilize tx descriptors */ 360 for (i = 0; i < TX_BUFFERS; i++) { 361 device->tx_desc[i]->s.tbadr = device->phys_tx_buf + BUFFER_SIZE * i; 362 device->tx_desc[i]->s.bcnt = -BUFFER_SIZE; 363 device->tx_desc[i]->s.status = 0; 364 device->tx_desc[i]->s.misc = 0UL; 365 device->tx_desc[i]->s.rsvd = 0UL; 366 } 367 368 /* initialize rx descriptors */ 369 for (i = 0; i < RX_BUFFERS; i++) { 370 device->rx_desc[i]->s.rbadr = device->phys_rx_buf + BUFFER_SIZE * i; 371 device->rx_desc[i]->s.bcnt = -BUFFER_SIZE; 372// device->rx_desc[i]->s.status = 0; 373 device->rx_desc[i]->s.status = 0x8000; /* OWN */ 374 device->rx_desc[i]->s.mcnt = 0UL; 375 device->rx_desc[i]->s.rsvd = 0UL; 376 } 377 378 /* initialize frame indexes */ 379 device->tx_sent = device->tx_acked = device->rx_received = device->rx_acked = 0; 380 381 return B_OK; 382} 383 384 385static void 386free_buffers(dev_info_t *device) 387{ 388 delete_area(device->tx_desc_area); 389 delete_area(device->tx_buf_area); 390 delete_area(device->rx_desc_area); 391 delete_area(device->rx_buf_area); 392} 393 394 395static void 396get_mac_addr(dev_info_t *device) 397{ 398 int i; 399 400 TRACE((DEVICE_NAME ": Mac address: ")); 401 402 for (i = 0; i < 6; i++) { 403 device->mac_addr.ch[i] = read8(device->reg_base + PCNET_APROM_OFFSET + i); 404 TRACE((" %02x", device->mac_addr.ch[i])); 405 } 406 407 TRACE(("\n")); 408} 409 410 411/* set hardware so all packets are received. */ 412static status_t 413setpromisc(dev_info_t *device) 414{ 415 TRACE((DEVICE_NAME ":setpormisc\n")); 416 417 csr_write(device, PCNET_CSR_STATUS, 0x0004UL); 418 csr_write(device, PCNET_CSR_MODE, 0x8000UL); /* promiscous mode */ 419 csr_write(device, PCNET_CSR_STATUS, 0x0042UL); 420 421 return B_OK; 422} 423 424 425#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ 426 427static status_t 428domulti(dev_info_t *device, uint8 *addr) 429{ 430 uint16 mcast_table[4]; 431 uint8 *addrs; 432 int i, j, bit, byte; 433 uint32 crc, poly = CRC_POLYNOMIAL_LE; 434 435 if (device->nmulti == MAX_MULTI) 436 return B_ERROR; 437 438 for (i = 0; i < device->nmulti; i++) { 439 if (memcmp(&device->multi[i], addr, sizeof(device->multi[i])) == 0) 440 break; 441 } 442 if (i != device->nmulti) 443 return B_ERROR; 444 445 // only copy if it isn't there already 446 memcpy(&device->multi[i], addr, sizeof(device->multi[i])); 447 device->nmulti++; 448 449 TRACE((DEVICE_NAME ": domulti %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", 450 addr[0],addr[1],addr[2],addr[3],addr[4],addr[5])); 451 452 /* clear the multicast filter */ 453 mcast_table[0] = 0; mcast_table[1] = 0; 454 mcast_table[2] = 0; mcast_table[3] = 0; 455 456 /* set addresses */ 457 for (i = 0; i < device->nmulti; i++) { 458 addrs = (uint8 *)(&(device->multi[i])); 459 /* multicast address? */ 460 if (!(*addrs & 1)) 461 break; 462 463 crc = 0xffffffff; 464 for (byte = 0; byte < 6; byte++) { 465 for (bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) { 466 int test; 467 468 test = ((bit ^ crc) & 0x01); 469 crc >>= 1; 470 if (test) 471 crc = crc ^ poly; 472 } 473 } 474 crc = crc >> 26; 475 mcast_table[crc >> 4] |= 1 << (crc & 0xf); 476 } 477 478 csr_write(device, PCNET_CSR_STATUS, 0x0004UL); 479 csr_write(device, PCNET_CSR_MODE, 0x0000UL); /* portsel ?? */ 480 csr_write(device, PCNET_CSR_LADRF0, mcast_table[0]); 481 csr_write(device, PCNET_CSR_LADRF1, mcast_table[1]); 482 csr_write(device, PCNET_CSR_LADRF2, mcast_table[2]); 483 csr_write(device, PCNET_CSR_LADRF3, mcast_table[3]); 484 csr_write(device, PCNET_CSR_STATUS, 0x0042UL); 485 486 return B_OK; 487} 488 489 490static void 491reset_device(dev_info_t *device) 492{ 493 TRACE((DEVICE_NAME ": reset_device reset the NIC hardware\n")); 494 495 read32(device->reg_base + PCNET_RST_OFFSET); 496 write32(device->reg_base + PCNET_RST_OFFSET, 0UL); 497 snooze(2); /* wait >1us */ 498}; 499 500 501/* 502 * allocate and initialize semaphores. 503 */ 504static status_t 505alloc_resources(dev_info_t *device) 506{ 507 /* rx semaphores */ 508 device->ilock = create_sem(0, DEVICE_NAME " rx"); 509 if (device->ilock < 0) 510 return device->ilock; 511 512 set_sem_owner(device->ilock, B_SYSTEM_TEAM); 513 514 /* tx semaphores */ 515 device->olock = create_sem(TX_BUFFERS, DEVICE_NAME " tx"); 516 if (device->olock < 0) { 517 delete_sem(device->ilock); 518 return device->olock; 519 } 520 521 set_sem_owner(device->olock, B_SYSTEM_TEAM); 522 523 device->readLock = device->writeLock = 0; 524 device->blockFlg = 0; // set blocking 525 526 return B_OK; 527} 528 529 530static void 531free_resources(dev_info_t *device) 532{ 533 delete_sem(device->ilock); 534 delete_sem(device->olock); 535} 536 537 538// #pragma mark - driver API 539 540 541status_t 542init_hardware(void) 543{ 544 TRACE((DEVICE_NAME ": init hardware\n")); 545 return B_OK; 546} 547 548 549status_t 550init_driver() 551{ 552 status_t status; 553 char devName[DEVICE_NAME_LEN]; 554 int32 i; 555 556 TRACE((DEVICE_NAME ": init_driver\n")); 557 558// TODO: this does not compile with our GCC 2.95.3 559#if 0 560{ 561 uint32 mgc_num; 562 /* check VMware */ 563 asm volatile ( 564 "movl $0x564d5868, %%eax; " 565 "movl $0, %%ebx; " 566 "movw $0x000a, %%cx; " 567 "movw $0x5658, %%dx; " 568 "inl %%dx, %%eax" 569 : "=b"(mgc_num) 570 : 571 : "eax", "ecx", "edx"); 572 573 TRACE((DEVICE_NAME ": VMware magic number %lx\n", mgc_num)); 574 575 if (!(mgc_num == 0x564d5868)) 576 return ENODEV; 577} 578#endif 579 580 status = get_module(B_PCI_MODULE_NAME, (module_info **)&sPCI); 581 if (status != B_OK) 582 return status; 583 584 /* find LAN cards */ 585 sNumOfCards = get_card_info(sCardInfo); 586 if (sNumOfCards == 0) { 587 free_card_info(sCardInfo); 588 put_module(B_PCI_MODULE_NAME); 589 return B_ERROR; 590 } 591 592 /* create device name list*/ 593 for (i = 0; i < sNumOfCards; i++) { 594 sprintf(devName, "net/%s/%ld", DEVICE_NAME, i); 595 sDeviceNames[i] = (char *)malloc(DEVICE_NAME_LEN); 596 strcpy(sDeviceNames[i], devName); 597 } 598 sDeviceNames[sNumOfCards] = NULL; 599 600 return B_OK; 601} 602 603 604void 605uninit_driver(void) 606{ 607 int32 i; 608 609 /* free device name list*/ 610 for (i = 0; i < sNumOfCards; i++) { 611 free(sDeviceNames[i]); 612 } 613 614 /* free device list*/ 615 free_card_info(sCardInfo); 616 put_module(B_PCI_MODULE_NAME); 617} 618 619 620const char ** 621publish_devices(void) 622{ 623 TRACE((DEVICE_NAME ": publish_devices()\n" )); 624 return (const char **)sDeviceNames; 625} 626 627 628device_hooks * 629find_device(const char *name) 630{ 631 int32 i; 632 633 /* find device name */ 634 for (i = 0; i < sNumOfCards; i++) { 635 if (!strcmp(name, sDeviceNames[i])) 636 return &sDeviceHooks; 637 } 638 639 return NULL; 640} 641 642 643// #pragma mark - device API 644 645 646static status_t 647vlance_open(const char *name, uint32 flags, void **cookie) 648{ 649 int32 devID; 650 status_t status; 651 dev_info_t *device; 652 653 /* find device name */ 654 for (devID = 0; devID < sNumOfCards; devID++) { 655 if (!strcmp(name, sDeviceNames[devID])) 656 break; 657 } 658 if (devID >= sNumOfCards) 659 return B_BAD_VALUE; 660 661 /* check if the device is busy and set in-use flag if not */ 662 if (atomic_or(&(sOpenLock[devID]), 1)) 663 return B_BUSY; 664 665 /* allocate storage for the cookie */ 666 *cookie = device = (dev_info_t *)malloc(sizeof(dev_info_t)); 667 if (device == NULL) { 668 status = B_NO_MEMORY; 669 goto err0; 670 } 671 memset(device, 0, sizeof(dev_info_t)); 672 673 /* setup the cookie */ 674 device->devInfo = sCardInfo[devID]; 675 device->devID = devID; 676 677 TRACE((DEVICE_NAME ": open %s device=%p\n", name, device)); 678 679 /* enable access to the cards address space */ 680 status = map_pci_addr(device); 681 if (status != B_OK) 682 goto err1; 683 684 status = alloc_resources(device); 685 if (status != B_OK) 686 goto err1; 687 688 /* init device */ 689 reset_device(device); 690 691 /* allocate and initialize frame buffer rings & descriptors */ 692 status = alloc_buffers(device); 693 if (status != B_OK) 694 goto err2; 695 status = init_buffers(device); 696 if (status != B_OK) 697 goto err2; 698 699 /* setup interrupts */ 700 install_io_interrupt_handler(device->devInfo->u.h0.interrupt_line, 701 vlance_interrupt, *cookie, 0); 702 /* init hardware */ 703 704 TRACE((DEVICE_NAME ": hardware specific init\n")); 705 706 write32(device->reg_base + PCNET_RDP_OFFSET, 0UL); /* DWIO mode */ 707 bcr_write(device, PCNET_BCR_SWS, 0x0002UL); /* 32bit mode */ 708 709 get_mac_addr(device); 710 711 device->init_blk.s.mode = ((TX_BUFF_IDX & 0x0f) << 28) | ((RX_BUFF_IDX & 0x0f) << 20) | 0x0000UL; /* TLEN, RLEN */ 712 memcpy(device->init_blk.s.padr, &(device->mac_addr), sizeof(mac_addr_t)); 713 device->init_blk.s.padr[6] = 0; 714 device->init_blk.s.padr[7] = 0; 715 device->init_blk.s.ladr[0] = 0UL; 716 device->init_blk.s.ladr[1] = 0UL; 717 device->init_blk.s.rdra = device->phys_rx_desc; 718 device->init_blk.s.tdra = device->phys_tx_desc; 719 720 { 721 int i; 722 for (i = 0; i < sizeof(init_block_t); i++) { 723 TRACE((" %02X", *(((unsigned char *)&(device->init_blk)) + i))); 724 } 725 TRACE(("\n")); 726 } 727 728 csr_write(device, PCNET_CSR_IADDR0, (device->phys_init_blk) & 0xffffUL); /* set init block address L */ 729 csr_write(device, PCNET_CSR_IADDR1, (device->phys_init_blk) >> 16); /* set init block address H */ 730 csr_write(device, PCNET_CSR_STATUS, 0x0001UL); /* INIT */ 731 while (!(csr_read(device, PCNET_CSR_STATUS) & 0x0100UL)); /* check IDON */ 732 csr_write(device, PCNET_CSR_STATUS, 0x0004UL); /* STOP */ 733 734#if DEBUG(INFO) 735 dprintf(DEVICE_NAME ": STATUS = %04X\n", csr_read(device, PCNET_CSR_STATUS)); 736 dprintf(DEVICE_NAME ": IADDR0 = %04X\n", csr_read(device, PCNET_CSR_IADDR0)); 737 dprintf(DEVICE_NAME ": IADDR1 = %04X\n", csr_read(device, PCNET_CSR_IADDR1)); 738 dprintf(DEVICE_NAME ": MODE = %04X\n", csr_read(device, PCNET_CSR_MODE)); 739 dprintf(DEVICE_NAME ": PADR0 = %04X\n", csr_read(device, PCNET_CSR_PADR0)); 740 dprintf(DEVICE_NAME ": PADR1 = %04X\n", csr_read(device, PCNET_CSR_PADR1)); 741 dprintf(DEVICE_NAME ": PADR2 = %04X\n", csr_read(device, PCNET_CSR_PADR2)); 742 dprintf(DEVICE_NAME ": LADRF0 = %04X\n", csr_read(device, PCNET_CSR_LADRF0)); 743 dprintf(DEVICE_NAME ": LADRF1 = %04X\n", csr_read(device, PCNET_CSR_LADRF1)); 744 dprintf(DEVICE_NAME ": LADRF2 = %04X\n", csr_read(device, PCNET_CSR_LADRF2)); 745 dprintf(DEVICE_NAME ": LADRF3 = %04X\n", csr_read(device, PCNET_CSR_LADRF3)); 746 dprintf(DEVICE_NAME ": BADRL = %04X\n", csr_read(device, PCNET_CSR_BADRL)); 747 dprintf(DEVICE_NAME ": BADRH = %04X\n", csr_read(device, PCNET_CSR_BADRH)); 748 dprintf(DEVICE_NAME ": BADXL = %04X\n", csr_read(device, PCNET_CSR_BADXL)); 749 dprintf(DEVICE_NAME ": BADXH = %04X\n", csr_read(device, PCNET_CSR_BADXH)); 750 dprintf(DEVICE_NAME ": BCR18 = %04X\n", bcr_read(device, PCNET_BCR_BSBC)); 751 dprintf(DEVICE_NAME ": BCR20 = %04X\n", bcr_read(device, PCNET_BCR_SWS)); 752#endif 753 csr_write(device, PCNET_CSR_STATUS, 0x7f00); /* clear int source */ 754 csr_write(device, PCNET_CSR_STATUS, 0x0042); /* IENA, STRT */ 755 756 return B_OK; 757 758err2: 759 free_buffers(device); 760err1: 761 free_resources(device); 762 free(device); 763err0: 764 atomic_and(&(sOpenLock[devID]), 0); 765 return status; 766} 767 768 769static status_t 770vlance_close(void *_device) 771{ 772 dev_info_t *device = (dev_info_t *) _device; 773 774 TRACE((DEVICE_NAME ": vlance_close\n")); 775 776 csr_write(device, PCNET_CSR_STATUS, 0x0004); /* STOP */ 777 TRACE((DEVICE_NAME ": STATUS = %04lx\n", csr_read(device,PCNET_CSR_STATUS))); 778 779 /* release resources */ 780 free_resources(device); 781 782 return B_OK; 783} 784 785 786static status_t 787vlance_free(void *cookie) 788{ 789 dev_info_t *device = (dev_info_t *)cookie; 790 791 TRACE((DEVICE_NAME": free %p\n", device)); 792 793 /* remove Interrupt Handler */ 794 remove_io_interrupt_handler(device->devInfo->u.h0.interrupt_line, vlance_interrupt, cookie); 795 796 free_buffers(device); 797 798 /* device is now available again */ 799 atomic_and(&(sOpenLock[device->devID]), 0); 800 801 free(device); 802 return B_OK; 803} 804 805 806static status_t 807vlance_control(void *cookie, uint32 op, void *buf, size_t len) 808{ 809 dev_info_t *device = (dev_info_t *)cookie; 810 811 switch (op) { 812 case ETHER_GETADDR: { 813 uint8 i; 814 TRACE((DEVICE_NAME ": control ether_getaddr\n")); 815 816 for (i = 0; i < 6; i++) { 817 ((uint8 *)buf)[i] = device->mac_addr.ch[i]; 818 } 819 return B_OK; 820 } 821 case ETHER_INIT: 822 TRACE((DEVICE_NAME ": control init\n")); 823 return B_OK; 824 825 case ETHER_GETFRAMESIZE: 826 TRACE((DEVICE_NAME ": control get_framesize\n")); 827 *(uint32 *)buf = MAX_FRAME_SIZE; 828 return B_OK; 829 830 case ETHER_ADDMULTI: 831 TRACE((DEVICE_NAME ": control add multi\n")); 832 return domulti(device, (unsigned char *)buf); 833 834 case ETHER_SETPROMISC: 835 TRACE((DEVICE_NAME ": control set promiscuous\n")); 836 return setpromisc(device); 837 838 case ETHER_NONBLOCK: 839 TRACE((DEVICE_NAME ": control blocking %ld\n", *((int32*)buf))); 840 841 if (*((int32 *)buf)) 842 device->blockFlg = 1; // set non-blocking 843 else 844 device->blockFlg = 0; // set blocking 845 return B_OK; 846 } 847 848 return B_BAD_VALUE; 849} 850 851 852static status_t 853vlance_read(void *_device, off_t pos, void *buf, size_t *len) 854{ 855 dev_info_t *device = (dev_info_t *) _device; 856 int16 frame_size; 857 uint32 flags; 858 status_t status; 859 860// *len = 0; 861 862#if DEBUG(INFO) 863 dprintf(DEVICE_NAME ": read buf %p, len %d\n", buf, *len); 864#endif 865 866 /* block until data is available (default) */ 867 flags = B_CAN_INTERRUPT; 868 if(device->blockFlg) flags |= B_RELATIVE_TIMEOUT; // non-blocking (0-timeout) 869 status = acquire_sem_etc(device->ilock, 1, flags, 0); 870 if(status != B_NO_ERROR) { 871#if DEBUG(INFO) 872 dprintf(DEVICE_NAME ": cannot acquire rx semaphore\n"); 873#endif 874 *len = 0; 875 return status; 876 } 877#if DEBUG(INFO) 878 dprintf(DEVICE_NAME ": try to atomic_or readLock\n"); 879#endif 880 /* prevent reentrant read */ 881 if(atomic_or(&device->readLock, 1)) { 882#if DEBUG(ERR) 883 dprintf(DEVICE_NAME ": cannot atomic_or readLock\n"); 884#endif 885 release_sem_etc(device->ilock, 1, 0); 886 *len = 0; 887 return B_ERROR; 888 } 889 890 /* hardware specific code to copy data from the NIC into buf */ 891 if((device->rx_desc[device->rx_acked]->s.status) & 0x8000) { /* owned by controller */ 892#if DEBUG(ERR) 893 dprintf(DEVICE_NAME ": rx desc owned by controller\n"); 894#endif 895 *len = 0; 896 status = B_ERROR; 897 } else { 898#if DEBUG(INFO) 899 dprintf(DEVICE_NAME ": rx desc owned by host\n"); 900#endif 901 frame_size = 0; 902 status = B_ERROR; 903 if(!((device->rx_desc[device->rx_acked]->s.status) & 0x4000)) { /* not receive error */ 904 frame_size = (device->rx_desc[device->rx_acked]->s.mcnt) & 0xfff; 905 if(frame_size > *len) frame_size = *len; 906 memcpy(buf, device->rx_buf[device->rx_acked], frame_size); 907 status = B_OK; 908 } 909 if(frame_size < *len) *len = frame_size; 910 device->rx_desc[device->rx_acked]->s.mcnt = 0; 911 device->rx_desc[device->rx_acked]->s.status = 0x8000; /* OWN */ 912 device->rx_acked = (device->rx_acked + 1) & (RX_BUFFERS - 1); 913 } 914 915 /* release reentrant lock */ 916 atomic_and(&device->readLock, 0); 917 918 return status; 919} 920 921 922static status_t 923vlance_write(void *_device, off_t pos, const void *buf, size_t *len) 924{ 925 dev_info_t *device = (dev_info_t *)_device; 926 int16 frame_size; 927 status_t status; 928 929 TRACE((DEVICE_NAME ": write buf %p len %lu\n", buf, *len)); 930 931 if (*len > MAX_FRAME_SIZE) { 932#if DEBUG(ERR) 933 dprintf(DEVICE_NAME ": write %lu > 1514 tooo long\n", *len); 934#endif 935 *len = MAX_FRAME_SIZE; 936 } 937 frame_size = *len; 938 939 status = acquire_sem_etc(device->olock, 1, B_CAN_INTERRUPT, 0); 940 if (status != B_NO_ERROR) { 941 *len = 0; 942 return status; 943 } 944 945 /* prevent reentrant write */ 946 if (atomic_or(&device->writeLock, 1)) { 947 release_sem_etc(device->olock, 1, 0); 948 *len = 0; 949 return B_ERROR; 950 } 951 952 /* hardware specific code to transmit buff */ 953 if ((device->tx_desc[device->tx_sent]->s.status) & 0x8000) { 954 /* owned by controller */ 955#if DEBUG(ERR) 956 dprintf(DEVICE_NAME ": tx desc owned by controller\n"); 957#endif 958 } else { 959 TRACE((DEVICE_NAME ": tx desc owned by host\n")); 960 961 memcpy(device->tx_buf[device->tx_sent], buf, frame_size); 962 device->tx_desc[device->tx_sent]->s.bcnt = -frame_size; 963// (device->tx_desc[device->tx_sent]->s.status) |= 0x8300; /* OWN, STP, ENP */ 964 (device->tx_desc[device->tx_sent]->s.status) |= 0x9300; /* OWN, LTINT, STP, ENP */ 965 device->tx_sent = (device->tx_sent + 1) & (TX_BUFFERS - 1); 966 csr_write(device, PCNET_CSR_STATUS, 0x0048UL); /* IENA, TDMD */ 967 } 968 969 /* release reentrant lock */ 970 atomic_and(&device->writeLock, 0); 971 972 return B_OK; 973} 974 975 976/*! LAN controller interrupt handler */ 977static int32 978vlance_interrupt(void *_device) 979{ 980 dev_info_t *device = (dev_info_t *)_device; 981 int32 handled = B_UNHANDLED_INTERRUPT; 982 int32 interruptStatus; 983 cpu_status state; 984 985#if DEBUG(INTERRUPT) 986 dprintf(DEVICE_NAME ": ISR_ENTRY\n"); 987#endif 988 state = disable_interrupts(); /* disable int state */ 989 990 interruptStatus = csr_read(device, PCNET_CSR_STATUS); 991 if (interruptStatus & 0x0080) { 992#if DEBUG(INTERRUPT) 993 dprintf(DEVICE_NAME ": status %04X\n", interruptStatus); 994#endif 995 996 /* clear interrupts */ 997 csr_write(device, PCNET_CSR_STATUS, 0x7f00); 998 999 if (interruptStatus & 0x8000) { 1000 /* Error */ 1001#if DEBUG(ERR) 1002 dprintf(DEVICE_NAME ": int error status %04lx\n", interruptStatus); 1003#endif 1004 csr_write(device, PCNET_CSR_STATUS, 0x0004); /* STOP */ 1005 init_buffers(device); 1006 csr_write(device, PCNET_CSR_STATUS, 0x0001UL); /* INIT */ 1007 while(!(csr_read(device, PCNET_CSR_STATUS) & 0x0100UL)); /* check IDON */ 1008 csr_write(device, PCNET_CSR_STATUS, 0x0042); /* IENA, STRT */ 1009 /* init semaphore ??? */ 1010 release_sem_etc(device->olock, TX_BUFFERS, B_DO_NOT_RESCHEDULE); 1011 acquire_sem_etc(device->ilock, RX_BUFFERS, B_RELATIVE_TIMEOUT, 0); 1012 /* not count TINT & RINT ??? */ 1013 interruptStatus &= ~0x0600; 1014 } 1015 if (interruptStatus & 0x0200) { /* TINT */ 1016 while (!((device->tx_desc[device->tx_acked]->s.status) & 0x8000)) { 1017 //dprintf(DEVICE_NAME ": rel tx sem\n"); 1018 release_sem_etc(device->olock, 1, B_DO_NOT_RESCHEDULE); 1019 device->tx_acked = (device->tx_acked + 1) & (TX_BUFFERS - 1); 1020 if(device->tx_acked == device->tx_sent) break; 1021 } 1022 } 1023 if (interruptStatus & 0x0400) { /* RINT */ 1024 while (!((device->rx_desc[device->rx_received]->s.status) & 0x8000)) { 1025 //dprintf(DEVICE_NAME ": rel rx sem\n"); 1026 release_sem_etc(device->ilock, 1, B_DO_NOT_RESCHEDULE); 1027 device->rx_received = (device->rx_received + 1) & (RX_BUFFERS - 1); 1028 } 1029 } 1030 1031 handled = B_INVOKE_SCHEDULER; /* set because the interrupt was from the NIC, not some other device sharing the interrupt line */ 1032 1033#if DEBUG(INTERRUPT) 1034 dprintf(DEVICE_NAME ": ISR - its ours\n"); 1035#endif 1036 } 1037 1038 csr_write(device, PCNET_CSR_STATUS, 0x0042); 1039 1040 restore_interrupts(state); /* restore int state */ 1041 1042 return handled; 1043} 1044 1045 1046