1#include <PCI.h> 2#include <Drivers.h> 3#include <malloc.h> 4#include <ether_driver.h> 5 6#ifdef HAIKU_TARGET_PLATFORM_HAIKU 7# include <net/if_media.h> 8#endif 9 10#include "mm.h" 11#include "lm.h" 12#include "mempool.h" 13 14struct pci_module_info *pci = NULL; 15 16const char *dev_list[11]; 17struct be_b57_dev be_b57_dev_cards[10]; 18int cards_found = 0; 19 20int b57_Packet_Desc_Size = sizeof(struct B_UM_PACKET); 21 22#define ROUND_UP_TO_PAGE(size) ((size % 4096 != 0) ? 4096 - (size % 4096) + size : size) 23 24struct pci_device_id { 25 unsigned int vendor, device; /* Vendor and device ID or PCI_ANY_ID */ 26 unsigned int subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */ 27 unsigned int class, class_mask; /* (class,subclass,prog-if) triplet */ 28 unsigned long driver_data; /* Data private to the driver */ 29}; 30 31#define PCI_ANY_ID 0 32 33typedef enum { 34 BCM5700A6 = 0, 35 BCM5700T6, 36 BCM5700A9, 37 BCM5700T9, 38 BCM5700, 39 BCM5701A5, 40 BCM5701T1, 41 BCM5701T8, 42 BCM5701A7, 43 BCM5701A10, 44 BCM5701A12, 45 BCM5701, 46 BCM5702, 47 BCM5703, 48 BCM5703A31, 49 BCM5703ARBUCKLE, 50 TC996T, 51 TC996ST, 52 TC996SSX, 53 TC996SX, 54 TC996BT, 55 TC997T, 56 TC997SX, 57 TC1000T, 58 TC1000BT, 59 TC940BR01, 60 TC942BR01, 61 TC998T, 62 TC998SX, 63 TC999T, 64 NC6770, 65 NC1020, 66 NC150T, 67 NC7760, 68 NC7761, 69 NC7770, 70 NC7771, 71 NC7780, 72 NC7781, 73 NC7772, 74 NC7782, 75 NC7783, 76 NC320T, 77 BCM5704CIOBE, 78 BCM5704, 79 BCM5704S, 80 BCM5705, 81 BCM5705M, 82 BCM5705F, 83 BCM5901, 84 BCM5782, 85 BCM5788, 86 BCM5789, 87 BCM5750, 88 BCM5750M, 89 BCM5720, 90 BCM5751, 91 BCM5751M, 92 BCM5751F, 93 BCM5721, 94} board_t; 95 96 97/* indexed by board_t, above */ 98static struct { 99 char *name; 100} board_info[] = { 101 { "Broadcom BCM5700 1000Base-T" }, 102 { "Broadcom BCM5700 1000Base-SX" }, 103 { "Broadcom BCM5700 1000Base-SX" }, 104 { "Broadcom BCM5700 1000Base-T" }, 105 { "Broadcom BCM5700" }, 106 { "Broadcom BCM5701 1000Base-T" }, 107 { "Broadcom BCM5701 1000Base-T" }, 108 { "Broadcom BCM5701 1000Base-T" }, 109 { "Broadcom BCM5701 1000Base-SX" }, 110 { "Broadcom BCM5701 1000Base-T" }, 111 { "Broadcom BCM5701 1000Base-T" }, 112 { "Broadcom BCM5701" }, 113 { "Broadcom BCM5702 1000Base-T" }, 114 { "Broadcom BCM5703 1000Base-T" }, 115 { "Broadcom BCM5703 1000Base-SX" }, 116 { "Broadcom B5703 1000Base-SX" }, 117 { "3Com 3C996 10/100/1000 Server NIC" }, 118 { "3Com 3C996 10/100/1000 Server NIC" }, 119 { "3Com 3C996 Gigabit Fiber-SX Server NIC" }, 120 { "3Com 3C996 Gigabit Fiber-SX Server NIC" }, 121 { "3Com 3C996B Gigabit Server NIC" }, 122 { "3Com 3C997 Gigabit Server NIC" }, 123 { "3Com 3C997 Gigabit Fiber-SX Server NIC" }, 124 { "3Com 3C1000 Gigabit NIC" }, 125 { "3Com 3C1000B-T 10/100/1000 PCI" }, 126 { "3Com 3C940 Gigabit LOM (21X21)" }, 127 { "3Com 3C942 Gigabit LOM (31X31)" }, 128 { "3Com 3C998-T Dual Port 10/100/1000 PCI-X Server NIC" }, 129 { "3Com 3C998-SX Dual Port 1000-SX PCI-X Server NIC" }, 130 { "3Com 3C999-T Quad Port 10/100/1000 PCI-X Server NIC" }, 131 { "HP NC6770 Gigabit Server Adapter" }, 132 { "NC1020 HP ProLiant Gigabit Server Adapter 32 PCI" }, 133 { "HP ProLiant NC 150T PCI 4-port Gigabit Combo Switch Adapter" }, 134 { "HP NC7760 Gigabit Server Adapter" }, 135 { "HP NC7761 Gigabit Server Adapter" }, 136 { "HP NC7770 Gigabit Server Adapter" }, 137 { "HP NC7771 Gigabit Server Adapter" }, 138 { "HP NC7780 Gigabit Server Adapter" }, 139 { "HP NC7781 Gigabit Server Adapter" }, 140 { "HP NC7772 Gigabit Server Adapter" }, 141 { "HP NC7782 Gigabit Server Adapter" }, 142 { "HP NC7783 Gigabit Server Adapter" }, 143 { "HP ProLiant NC 320T PCI Express Gigabit Server Adapter" }, 144 { "Broadcom BCM5704 CIOB-E 1000Base-T" }, 145 { "Broadcom BCM5704 1000Base-T" }, 146 { "Broadcom BCM5704 1000Base-SX" }, 147 { "Broadcom BCM5705 1000Base-T" }, 148 { "Broadcom BCM5705M 1000Base-T" }, 149 { "Broadcom 570x 10/100 Integrated Controller" }, 150 { "Broadcom BCM5901 100Base-TX" }, 151 { "Broadcom NetXtreme Gigabit Ethernet for hp" }, 152 { "Broadcom BCM5788 NetLink 1000Base-T" }, 153 { "Broadcom BCM5789 NetLink 1000Base-T PCI Express" }, 154 { "Broadcom BCM5750 1000Base-T PCI" }, 155 { "Broadcom BCM5750M 1000Base-T PCI" }, 156 { "Broadcom BCM5720 1000Base-T PCI" }, 157 { "Broadcom BCM5751 1000Base-T PCI Express" }, 158 { "Broadcom BCM5751M 1000Base-T PCI Express" }, 159 { "Broadcom BCM5751F 100Base-TX PCI Express" }, 160 { "Broadcom BCM5721 1000Base-T PCI Express" }, 161 { 0 }, 162 }; 163 164static struct pci_device_id bcm5700_pci_tbl[] = { 165 {0x14e4, 0x1644, 0x14e4, 0x1644, 0, 0, BCM5700A6 }, 166 {0x14e4, 0x1644, 0x14e4, 0x2, 0, 0, BCM5700T6 }, 167 {0x14e4, 0x1644, 0x14e4, 0x3, 0, 0, BCM5700A9 }, 168 {0x14e4, 0x1644, 0x14e4, 0x4, 0, 0, BCM5700T9 }, 169 {0x14e4, 0x1644, 0x1028, 0xd1, 0, 0, BCM5700 }, 170 {0x14e4, 0x1644, 0x1028, 0x0106, 0, 0, BCM5700 }, 171 {0x14e4, 0x1644, 0x1028, 0x0109, 0, 0, BCM5700 }, 172 {0x14e4, 0x1644, 0x1028, 0x010a, 0, 0, BCM5700 }, 173 {0x14e4, 0x1644, 0x10b7, 0x1000, 0, 0, TC996T }, 174 {0x14e4, 0x1644, 0x10b7, 0x1001, 0, 0, TC996ST }, 175 {0x14e4, 0x1644, 0x10b7, 0x1002, 0, 0, TC996SSX }, 176 {0x14e4, 0x1644, 0x10b7, 0x1003, 0, 0, TC997T }, 177 {0x14e4, 0x1644, 0x10b7, 0x1005, 0, 0, TC997SX }, 178 {0x14e4, 0x1644, 0x10b7, 0x1008, 0, 0, TC942BR01 }, 179 {0x14e4, 0x1644, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5700 }, 180 {0x14e4, 0x1645, 0x14e4, 1, 0, 0, BCM5701A5 }, 181 {0x14e4, 0x1645, 0x14e4, 5, 0, 0, BCM5701T1 }, 182 {0x14e4, 0x1645, 0x14e4, 6, 0, 0, BCM5701T8 }, 183 {0x14e4, 0x1645, 0x14e4, 7, 0, 0, BCM5701A7 }, 184 {0x14e4, 0x1645, 0x14e4, 8, 0, 0, BCM5701A10 }, 185 {0x14e4, 0x1645, 0x14e4, 0x8008, 0, 0, BCM5701A12 }, 186 {0x14e4, 0x1645, 0x0e11, 0xc1, 0, 0, NC6770 }, 187 {0x14e4, 0x1645, 0x0e11, 0x7c, 0, 0, NC7770 }, 188 {0x14e4, 0x1645, 0x0e11, 0x85, 0, 0, NC7780 }, 189 {0x14e4, 0x1645, 0x1028, 0x0121, 0, 0, BCM5701 }, 190 {0x14e4, 0x1645, 0x10b7, 0x1004, 0, 0, TC996SX }, 191 {0x14e4, 0x1645, 0x10b7, 0x1006, 0, 0, TC996BT }, 192 {0x14e4, 0x1645, 0x10b7, 0x1007, 0, 0, TC1000T }, 193 {0x14e4, 0x1645, 0x10b7, 0x1008, 0, 0, TC940BR01 }, 194 {0x14e4, 0x1645, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5701 }, 195 {0x14e4, 0x1646, 0x14e4, 0x8009, 0, 0, BCM5702 }, 196 {0x14e4, 0x1646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702 }, 197 {0x14e4, 0x16a6, 0x14e4, 0x8009, 0, 0, BCM5702 }, 198 {0x14e4, 0x16a6, 0x14e4, 0x000c, 0, 0, BCM5702 }, 199 {0x14e4, 0x16a6, 0x0e11, 0xbb, 0, 0, NC7760 }, 200 {0x14e4, 0x16a6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702 }, 201 {0x14e4, 0x16c6, 0x10b7, 0x1100, 0, 0, TC1000BT }, 202 {0x14e4, 0x16c6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5702 }, 203 {0x14e4, 0x1647, 0x14e4, 0x0009, 0, 0, BCM5703 }, 204 {0x14e4, 0x1647, 0x14e4, 0x000a, 0, 0, BCM5703A31 }, 205 {0x14e4, 0x1647, 0x14e4, 0x000b, 0, 0, BCM5703 }, 206 {0x14e4, 0x1647, 0x14e4, 0x800a, 0, 0, BCM5703 }, 207 {0x14e4, 0x1647, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703 }, 208 {0x14e4, 0x16a7, 0x14e4, 0x0009, 0, 0, BCM5703 }, 209 {0x14e4, 0x16a7, 0x14e4, 0x000a, 0, 0, BCM5703A31 }, 210 {0x14e4, 0x16a7, 0x14e4, 0x000b, 0, 0, BCM5703 }, 211 {0x14e4, 0x16a7, 0x14e4, 0x800a, 0, 0, BCM5703 }, 212 {0x14e4, 0x16a7, 0x0e11, 0xca, 0, 0, NC7771 }, 213 {0x14e4, 0x16a7, 0x0e11, 0xcb, 0, 0, NC7781 }, 214 {0x14e4, 0x16a7, 0x1014, 0x0281, 0, 0, BCM5703ARBUCKLE }, 215 {0x14e4, 0x16a7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703 }, 216 {0x14e4, 0x16c7, 0x14e4, 0x000a, 0, 0, BCM5703A31 }, 217 {0x14e4, 0x16c7, 0x0e11, 0xca, 0, 0, NC7771 }, 218 {0x14e4, 0x16c7, 0x0e11, 0xcb, 0, 0, NC7781 }, 219 {0x14e4, 0x16c7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5703 }, 220 {0x14e4, 0x1648, 0x0e11, 0xcf, 0, 0, NC7772 }, 221 {0x14e4, 0x1648, 0x0e11, 0xd0, 0, 0, NC7782 }, 222 {0x14e4, 0x1648, 0x0e11, 0xd1, 0, 0, NC7783 }, 223 {0x14e4, 0x1648, 0x10b7, 0x2000, 0, 0, TC998T }, 224 {0x14e4, 0x1648, 0x10b7, 0x3000, 0, 0, TC999T }, 225 {0x14e4, 0x1648, 0x1166, 0x1648, 0, 0, BCM5704CIOBE }, 226 {0x14e4, 0x1648, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5704 }, 227 {0x14e4, 0x1649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5704S }, 228 {0x14e4, 0x16a8, 0x14e4, 0x16a8, 0, 0, BCM5704S }, 229 {0x14e4, 0x16a8, 0x10b7, 0x2001, 0, 0, TC998SX }, 230 {0x14e4, 0x16a8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5704S }, 231 {0x14e4, 0x1653, 0x0e11, 0x00e3, 0, 0, NC7761 }, 232 {0x14e4, 0x1653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5705 }, 233 {0x14e4, 0x1654, 0x0e11, 0x00e3, 0, 0, NC7761 }, 234 {0x14e4, 0x1654, 0x103c, 0x3100, 0, 0, NC1020 }, 235 {0x14e4, 0x1654, 0x103c, 0x3226, 0, 0, NC150T }, 236 {0x14e4, 0x1654, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5705 }, 237 {0x14e4, 0x165d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5705M }, 238 {0x14e4, 0x165e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5705M }, 239 {0x14e4, 0x166e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5705F }, 240 {0x14e4, 0x1696, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5782 }, 241 {0x14e4, 0x169c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5788 }, 242 {0x14e4, 0x169d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5789 }, 243 {0x14e4, 0x170d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5901 }, 244 {0x14e4, 0x170e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5901 }, 245 {0x14e4, 0x1676, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5750 }, 246 {0x14e4, 0x167c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5750M }, 247 {0x14e4, 0x1677, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5751 }, 248 {0x14e4, 0x167d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5751M }, 249 {0x14e4, 0x167e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5751F }, 250 {0x14e4, 0x1658, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5720 }, 251 {0x14e4, 0x1659, 0x103c, 0x7031, 0, 0, NC320T }, 252 {0x14e4, 0x1659, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5721 }, 253 {0,} 254}; 255 256/* -------- BeOS Driver Hooks ------------ */ 257 258static status_t b57_open(const char *name, uint32 flags, void **cookie); 259static status_t b57_close(void *cookie); 260static status_t b57_free(void *cookie); 261static status_t b57_ioctl(void *cookie,uint32 op,void *data,size_t len); 262static status_t b57_read(void *cookie,off_t pos,void *data,size_t *numBytes); 263static status_t b57_write(void *cookie,off_t pos,const void *data,size_t *numBytes); 264static int32 b57_interrupt(void *cookie); 265static int32 tx_cleanup_thread(void *us); 266 267device_hooks b57_hooks = {b57_open,b57_close,b57_free,b57_ioctl,b57_read,b57_write,NULL,NULL,NULL,NULL}; 268int32 api_version = B_CUR_DRIVER_API_VERSION; 269 270//int debug_fd; 271 272 273status_t 274init_hardware(void) 275{ 276 return B_OK; 277} 278 279 280const char ** 281publish_devices(void) 282{ 283 return dev_list; 284} 285 286 287device_hooks * 288find_device(const char *name) 289{ 290 return &b57_hooks; 291} 292 293 294status_t 295init_driver(void) 296{ 297 int i = 0, j = 0, is_detected; 298 pci_info dev_info; 299 300 //debug_fd = open("/tmp/broadcom_traffic_log",O_RDWR | B_CREATE_FILE); 301 302 if (get_module(B_PCI_MODULE_NAME, (module_info **)&pci) != B_OK) 303 return B_ERROR; 304 305 while (pci->get_nth_pci_info(i++, &dev_info) == 0) { 306 is_detected = 0; 307 if ((dev_info.class_base == PCI_network) && (dev_info.class_sub == PCI_ethernet)) { 308 for (j = 0; bcm5700_pci_tbl[j].vendor != 0; j++) { 309 if ((dev_info.vendor_id == bcm5700_pci_tbl[j].vendor) && (dev_info.device_id == bcm5700_pci_tbl[j].device)) { 310 is_detected = 1; 311 break; 312 } 313 } 314 } 315 316 if (!is_detected) 317 continue; 318 319 if (cards_found >= 10) 320 break; 321 322 dev_list[cards_found] = (char *)malloc(16 /* net/bcm570x/xx */); 323 sprintf(dev_list[cards_found],"net/bcm570x/%d",cards_found); 324 be_b57_dev_cards[cards_found].pci_data = dev_info; 325 be_b57_dev_cards[cards_found].packet_release_sem = create_sem(0,dev_list[cards_found]); 326 be_b57_dev_cards[cards_found].mem_list_num = 0; 327 be_b57_dev_cards[cards_found].lockmem_list_num = 0; 328 be_b57_dev_cards[cards_found].opened = 0; 329 be_b57_dev_cards[cards_found].block = 1; 330 be_b57_dev_cards[cards_found].lock = 0; 331#ifdef HAIKU_TARGET_PLATFORM_HAIKU 332 be_b57_dev_cards[cards_found].linkChangeSem = -1; 333#endif 334 335 if (LM_GetAdapterInfo(&be_b57_dev_cards[cards_found].lm_dev) != LM_STATUS_SUCCESS) { 336 for (j = 0; j < cards_found; j++) { 337 free(dev_list[j]); 338 delete_sem(be_b57_dev_cards[j].packet_release_sem); 339 } 340 put_module(B_PCI_MODULE_NAME); 341 return ENODEV; 342 } 343 344 QQ_InitQueue(&be_b57_dev_cards[cards_found].RxPacketReadQ.Container,MAX_RX_PACKET_DESC_COUNT); 345 346 cards_found++; 347 } 348 349 mempool_init((MAX_RX_PACKET_DESC_COUNT+MAX_TX_PACKET_DESC_COUNT) * cards_found); 350 dev_list[cards_found] = NULL; 351 352 return B_OK; 353} 354 355 356void 357uninit_driver(void) 358{ 359 struct be_b57_dev *pUmDevice; 360 int i, j; 361 362 for (j = 0; j < cards_found; j++) { 363 pUmDevice = &be_b57_dev_cards[j]; 364 365 for (i = 0; i < pUmDevice->mem_list_num; i++) 366 free(pUmDevice->mem_list[i]); 367 for (i = 0; i < pUmDevice->lockmem_list_num; i++) 368 delete_area(pUmDevice->lockmem_list[i]); 369 370 delete_area(pUmDevice->mem_base); 371 delete_sem(be_b57_dev_cards[j].packet_release_sem); 372 free((void *)dev_list[j]); 373 } 374 375 mempool_exit(); 376 put_module(B_PCI_MODULE_NAME); 377} 378 379 380// #pragma mark - 381 382 383static status_t 384b57_open(const char *name, uint32 flags, void **cookie) 385{ 386 struct be_b57_dev *pDevice = NULL; 387 int i; 388 389 *cookie = NULL; 390 for (i = 0; i < cards_found; i++) { 391 if (strcmp(dev_list[i],name) == 0) { 392 *cookie = pDevice = &be_b57_dev_cards[i]; 393 break; 394 } 395 } 396 397 if (*cookie == NULL) 398 return B_FILE_NOT_FOUND; 399 400 if (atomic_or(&pDevice->opened, 1)) { 401 *cookie = pDevice = NULL; 402 return B_BUSY; 403 } 404 405 install_io_interrupt_handler(pDevice->pci_data.u.h0.interrupt_line, 406 b57_interrupt, *cookie, 0); 407 if (LM_InitializeAdapter(&pDevice->lm_dev) != LM_STATUS_SUCCESS) { 408 atomic_and(&pDevice->opened,0); 409 remove_io_interrupt_handler(pDevice->pci_data.u.h0.interrupt_line, b57_interrupt, *cookie); 410 *cookie = NULL; 411 return B_ERROR; 412 } 413 414 /*QQ_InitQueue(&pDevice->rx_out_of_buf_q.Container, 415 MAX_RX_PACKET_DESC_COUNT);*/ 416 417 //pDevice->lm_dev.PhyCrcCount = 0; 418 LM_EnableInterrupt(&pDevice->lm_dev); 419 420 dprintf("Broadcom 57xx adapter successfully inited at %s:\n", name); 421 dprintf("MAC Address: %02x:%02x:%02x:%02x:%02x:%02x\n", 422 pDevice->lm_dev.NodeAddress[0], pDevice->lm_dev.NodeAddress[1], 423 pDevice->lm_dev.NodeAddress[2], pDevice->lm_dev.NodeAddress[3], 424 pDevice->lm_dev.NodeAddress[4], pDevice->lm_dev.NodeAddress[5]); 425 dprintf("PCI Data: 0x%08x\n", pDevice->pci_data.u.h0.base_registers[0]); 426 dprintf("IRQ: %d\n", pDevice->pci_data.u.h0.interrupt_line); 427 428 return B_OK; 429} 430 431 432static status_t 433b57_close(void *cookie) 434{ 435 struct be_b57_dev *pUmDevice = (struct be_b57_dev *)(cookie); 436 437 if (cookie == NULL) 438 return B_OK; 439 440 LM_DisableInterrupt(&pUmDevice->lm_dev); 441 LM_Halt(&pUmDevice->lm_dev); 442 pUmDevice->lm_dev.InitDone = 0; 443 atomic_and(&pUmDevice->opened, 0); 444 445 return B_OK; 446} 447 448 449static status_t 450b57_free(void *cookie) 451{ 452 struct be_b57_dev *pUmDevice = (struct be_b57_dev *)(cookie); 453 454 if (cookie == NULL) 455 return B_OK; 456 457 remove_io_interrupt_handler(pUmDevice->pci_data.u.h1.interrupt_line, b57_interrupt, cookie); 458 return B_OK; 459} 460 461 462static status_t 463b57_ioctl(void *cookie,uint32 op,void *data,size_t len) 464{ 465 struct be_b57_dev *pUmDevice = (struct be_b57_dev *)(cookie); 466 467 switch (op) { 468 case ETHER_INIT: 469 return B_OK; 470 case ETHER_GETADDR: 471 if (data == NULL) 472 return B_ERROR; 473 474 memcpy(data, pUmDevice->lm_dev.NodeAddress, 6); 475 return B_OK; 476 case ETHER_NONBLOCK: 477 pUmDevice->block = !*((uint8 *)(data)); 478 return B_OK; 479 case ETHER_ADDMULTI: 480 return (LM_MulticastAdd(&pUmDevice->lm_dev, 481 (PLM_UINT8)(data)) == LM_STATUS_SUCCESS) ? B_OK : B_ERROR; 482 case ETHER_REMMULTI: 483 return (LM_MulticastDel(&pUmDevice->lm_dev, 484 (PLM_UINT8)(data)) == LM_STATUS_SUCCESS) ? B_OK : B_ERROR; 485 case ETHER_SETPROMISC: 486 if (*((uint8 *)(data))) { 487 LM_SetReceiveMask(&pUmDevice->lm_dev, 488 pUmDevice->lm_dev.ReceiveMask | LM_PROMISCUOUS_MODE); 489 } else { 490 LM_SetReceiveMask(&pUmDevice->lm_dev, 491 pUmDevice->lm_dev.ReceiveMask & ~LM_PROMISCUOUS_MODE); 492 } 493 return B_OK; 494#ifndef HAIKU_TARGET_PLATFORM_HAIKU 495 case ETHER_GETLINKSTATE: 496 { 497 ether_link_state_t *state_buffer = (ether_link_state_t *)(data); 498 state_buffer->link_speed = pUmDevice->lm_dev.LineSpeed; 499 state_buffer->link_quality = (pUmDevice->lm_dev.LinkStatus == LM_STATUS_LINK_DOWN) ? 0.0 : 1.0; 500 state_buffer->duplex_mode = (pUmDevice->lm_dev.DuplexMode == LM_DUPLEX_MODE_FULL); 501 return B_OK; 502 } 503#else 504 case ETHER_GET_LINK_STATE: 505 { 506 ether_link_state_t state; 507 state.media = (pUmDevice->lm_dev.LinkStatus 508 == LM_STATUS_LINK_DOWN ? 0 : IFM_ACTIVE) | IFM_ETHER; 509 switch (pUmDevice->lm_dev.LineSpeed) { 510 case LM_LINE_SPEED_10MBPS: 511 state.media |= IFM_10_T; 512 state.speed = 10000000; 513 break; 514 case LM_LINE_SPEED_100MBPS: 515 state.media |= IFM_100_TX; 516 state.speed = 100000000; 517 break; 518 case LM_LINE_SPEED_1000MBPS: 519 state.media |= IFM_1000_T; 520 state.speed = 1000000000; 521 break; 522 default: 523 state.speed = 0; 524 } 525 state.media |= (pUmDevice->lm_dev.DuplexMode 526 == LM_DUPLEX_MODE_FULL ? IFM_FULL_DUPLEX : IFM_HALF_DUPLEX); 527 state.quality = 1000; 528 529 return user_memcpy(data, &state, sizeof(ether_link_state_t)); 530 } 531 case ETHER_SET_LINK_STATE_SEM: 532 { 533 if (user_memcpy(&pUmDevice->linkChangeSem, data, sizeof(sem_id)) < B_OK) { 534 pUmDevice->linkChangeSem = -1; 535 return B_BAD_ADDRESS; 536 } 537 return B_OK; 538 } 539 540#endif 541 } 542 return B_ERROR; 543} 544 545 546static int32 547b57_interrupt(void *cookie) 548{ 549 struct be_b57_dev *pUmDevice = (struct be_b57_dev *)cookie; 550 PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice; 551 unsigned int handled = 1; 552 int i, max_intr_loop; 553 LM_UINT32 oldtag, newtag; 554 555 if (!pDevice->InitDone) 556 return B_UNHANDLED_INTERRUPT; 557 558 if (pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) { 559 max_intr_loop = 50; 560 if (pDevice->Flags & USE_TAGGED_STATUS_FLAG) { 561 MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 1); 562 oldtag = pDevice->pStatusBlkVirt->StatusTag; 563 564 for (i = 0; ; i++) { 565 pDevice->pStatusBlkVirt->Status &= 566 ~STATUS_BLOCK_UPDATED; 567 568 LM_ServiceInterrupts(pDevice); 569 newtag = pDevice->pStatusBlkVirt->StatusTag; 570 if ((newtag == oldtag) || (i > max_intr_loop)) { 571 MB_REG_WR(pDevice, 572 Mailbox.Interrupt[0].Low, 573 oldtag << 24); 574 pDevice->LastTag = oldtag; 575 if (pDevice->Flags & UNDI_FIX_FLAG) { 576 REG_WR(pDevice, Grc.LocalCtrl, 577 pDevice->GrcLocalCtrl | 0x2); 578 } 579 break; 580 } 581 oldtag = newtag; 582 } 583 } else { 584 i = 0; 585 do { 586 uint dummy; 587 588 MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 1); 589 pDevice->pStatusBlkVirt->Status &= 590 ~STATUS_BLOCK_UPDATED; 591 LM_ServiceInterrupts(pDevice); 592 MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 0); 593 dummy = MB_REG_RD(pDevice, 594 Mailbox.Interrupt[0].Low); 595 i++; 596 } 597 598 while ((pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) != 0 599 && i < max_intr_loop) 600 ; 601 602 if (pDevice->Flags & UNDI_FIX_FLAG) { 603 REG_WR(pDevice, Grc.LocalCtrl, 604 pDevice->GrcLocalCtrl | 0x2); 605 } 606 } 607 } else 608 handled = 0; 609 610 if (QQ_GetEntryCnt(&pDevice->RxPacketFreeQ.Container) 611 || pDevice->QueueAgain) { 612 LM_QueueRxPackets(pDevice); 613 } 614 615 return handled ? B_INVOKE_SCHEDULER : B_UNHANDLED_INTERRUPT; 616} 617 618 619static status_t 620b57_read(void *cookie,off_t pos,void *data,size_t *numBytes) 621{ 622 struct be_b57_dev *pUmDevice = (struct be_b57_dev *)cookie; 623 PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice; 624 PLM_PACKET pPacket; 625 struct B_UM_PACKET *pUmPacket; 626 cpu_status cpu; 627 628 if (pUmDevice->block) 629 acquire_sem(pUmDevice->packet_release_sem); 630 else { 631 /* Decrement the receive sem anyway, but don't block 632 this is a horrible hack, but it works. */ 633 acquire_sem_etc(pUmDevice->packet_release_sem, 1, B_RELATIVE_TIMEOUT, 0); 634 } 635 636 cpu = disable_interrupts(); 637 acquire_spinlock(&pUmDevice->lock); 638 639 pPacket = (PLM_PACKET) 640 QQ_PopHead(&pUmDevice->RxPacketReadQ.Container); 641 642 release_spinlock(&pUmDevice->lock); 643 restore_interrupts(cpu); 644 645 if (pPacket == 0) { 646 *numBytes = -1; 647 return B_ERROR; 648 } 649 650 pUmPacket = (struct B_UM_PACKET *) pPacket; 651 if (pPacket->PacketStatus != LM_STATUS_SUCCESS 652 || pPacket->PacketSize > 1518) { 653 cpu = disable_interrupts(); 654 acquire_spinlock(&pUmDevice->lock); 655 656 QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket); 657 658 release_spinlock(&pUmDevice->lock); 659 restore_interrupts(cpu); 660 *numBytes = -1; 661 return B_ERROR; 662 } 663 664 if ((pPacket->PacketSize) < *numBytes) 665 *numBytes = pPacket->PacketSize; 666 667 memcpy(data,pUmPacket->data,*numBytes); 668 cpu = disable_interrupts(); 669 acquire_spinlock(&pUmDevice->lock); 670 671 QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket); 672 673 release_spinlock(&pUmDevice->lock); 674 restore_interrupts(cpu); 675 676 return B_OK; 677} 678 679 680static status_t 681b57_write(void *cookie,off_t pos,const void *data,size_t *numBytes) 682{ 683 struct be_b57_dev *pUmDevice = (struct be_b57_dev *)cookie; 684 PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK) pUmDevice; 685 PLM_PACKET pPacket; 686 struct B_UM_PACKET *pUmPacket; 687 cpu_status cpu; 688 689 /*if ((pDevice->LinkStatus == LM_STATUS_LINK_DOWN) || !pDevice->InitDone) 690 { 691 return ENETDOWN; 692 }*/ 693 694 pPacket = (PLM_PACKET) 695 QQ_PopHead(&pDevice->TxPacketFreeQ.Container); 696 697 if (pPacket == 0) 698 return B_ERROR; 699 700 pUmPacket = (struct B_UM_PACKET *)pPacket; 701 pUmPacket->data = chunk_pool_get(); 702 703 memcpy(pUmPacket->data,data,*numBytes); /* no guarantee data is contiguous, so we have to copy */ 704 pPacket->PacketSize = pUmPacket->size = *numBytes; 705 706 pPacket->u.Tx.FragCount = 1; 707 pPacket->Flags = 0; 708 709 tx_cleanup_thread(pUmDevice); 710 711 cpu = disable_interrupts(); 712 acquire_spinlock(&pUmDevice->lock); 713 714 LM_SendPacket(pDevice, pPacket); 715 716 release_spinlock(&pUmDevice->lock); 717 restore_interrupts(cpu); 718 719 return B_OK; 720} 721 722 723// #pragma mark - 724/* -------- Broadcom MM hooks ----------- */ 725 726 727LM_STATUS 728MM_ReadConfig16(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, 729 LM_UINT16 *pValue16) 730{ 731 *pValue16 = (LM_UINT16)pci->read_pci_config(((struct be_b57_dev *)(pDevice))->pci_data.bus, 732 ((struct be_b57_dev *)(pDevice))->pci_data.device, 733 ((struct be_b57_dev *)(pDevice))->pci_data.function, 734 (uchar)Offset, sizeof(LM_UINT16)); 735 return LM_STATUS_SUCCESS; 736} 737 738 739LM_STATUS 740MM_WriteConfig16(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, 741 LM_UINT16 Value16) 742{ 743 pci->write_pci_config(((struct be_b57_dev *)(pDevice))->pci_data.bus, 744 ((struct be_b57_dev *)(pDevice))->pci_data.device, 745 ((struct be_b57_dev *)(pDevice))->pci_data.function, 746 (uchar)Offset, sizeof(LM_UINT16), (uint32)Value16); 747 return LM_STATUS_SUCCESS; 748} 749 750 751LM_STATUS 752MM_ReadConfig32(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, 753 LM_UINT32 *pValue32) 754{ 755 *pValue32 = (LM_UINT32)pci->read_pci_config(((struct be_b57_dev *)(pDevice))->pci_data.bus, 756 ((struct be_b57_dev *)(pDevice))->pci_data.device, 757 ((struct be_b57_dev *)(pDevice))->pci_data.function, 758 (uchar)Offset, sizeof(LM_UINT32)); 759 return LM_STATUS_SUCCESS; 760} 761 762 763LM_STATUS 764MM_WriteConfig32(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, 765 LM_UINT32 Value32) 766{ 767 pci->write_pci_config(((struct be_b57_dev *)(pDevice))->pci_data.bus, 768 ((struct be_b57_dev *)(pDevice))->pci_data.device, 769 ((struct be_b57_dev *)(pDevice))->pci_data.function, 770 (uchar)Offset, sizeof(LM_UINT32), (uint32)Value32); 771 return LM_STATUS_SUCCESS; 772} 773 774 775LM_STATUS 776MM_MapMemBase(PLM_DEVICE_BLOCK pDevice) 777{ 778 struct be_b57_dev *pUmDevice = (struct be_b57_dev *)(pDevice); 779 size_t size = pUmDevice->pci_data.u.h0.base_register_sizes[0]; 780 781 size = ROUND_UP_TO_PAGE(size); 782 pUmDevice->mem_base = map_physical_memory("broadcom_regs", 783 pUmDevice->pci_data.u.h0.base_registers[0], size, 784 B_ANY_KERNEL_BLOCK_ADDRESS, 0, 785 (void **)(&pDevice->pMappedMemBase)); 786 787 return LM_STATUS_SUCCESS; 788} 789 790/* 791LM_STATUS 792MM_MapIoBase(PLM_DEVICE_BLOCK pDevice) 793{ 794 pDevice->pMappedMemBase = pci->ram_address(((struct be_b57_dev *)(pDevice))->pci_data.memory_base); 795 return LM_STATUS_SUCCESS; 796} 797*/ 798 799LM_STATUS 800MM_IndicateRxPackets(PLM_DEVICE_BLOCK pDevice) 801{ 802 struct be_b57_dev *dev = (struct be_b57_dev *)pDevice; 803 PLM_PACKET pPacket; 804 805 while (1) { 806 pPacket = (PLM_PACKET) 807 QQ_PopHead(&pDevice->RxPacketReceivedQ.Container); 808 if (pPacket == 0) 809 break; 810 811 acquire_spinlock(&dev->lock); 812 release_sem_etc(dev->packet_release_sem, 1, B_DO_NOT_RESCHEDULE); 813 release_spinlock(&dev->lock); 814 QQ_PushTail(&dev->RxPacketReadQ.Container, pPacket); 815 } 816 817 return LM_STATUS_SUCCESS; 818} 819 820 821LM_STATUS 822MM_IndicateTxPackets(PLM_DEVICE_BLOCK pDevice) 823{ 824 return LM_STATUS_SUCCESS; 825} 826 827 828int32 829tx_cleanup_thread(void *us) 830{ 831 PLM_PACKET pPacket; 832 PLM_DEVICE_BLOCK pDevice = (PLM_DEVICE_BLOCK)(us); 833 struct be_b57_dev *pUmDevice = (struct be_b57_dev *)(us); 834 struct B_UM_PACKET *pUmPacket; 835 cpu_status cpu; 836 837 while (1) { 838 cpu = disable_interrupts(); 839 acquire_spinlock(&pUmDevice->lock); 840 841 pPacket = (PLM_PACKET) 842 QQ_PopHead(&pDevice->TxPacketXmittedQ.Container); 843 844 release_spinlock(&pUmDevice->lock); 845 restore_interrupts(cpu); 846 if (pPacket == 0) 847 break; 848 pUmPacket = (struct B_UM_PACKET *)(pPacket); 849 chunk_pool_put(pUmPacket->data); 850 pUmPacket->data = NULL; 851 852 cpu = disable_interrupts(); 853 acquire_spinlock(&pUmDevice->lock); 854 QQ_PushTail(&pDevice->TxPacketFreeQ.Container, pPacket); 855 release_spinlock(&pUmDevice->lock); 856 restore_interrupts(cpu); 857 } 858 return LM_STATUS_SUCCESS; 859} 860 861/*LM_STATUS MM_StartTxDma(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket); 862LM_STATUS MM_CompleteTxDma(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket);*/ 863 864LM_STATUS 865MM_AllocateMemory(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize, 866 PLM_VOID *pMemoryBlockVirt) 867{ 868 struct be_b57_dev *dev = (struct be_b57_dev *)(pDevice); 869 870 if (dev->mem_list_num == 16) 871 return LM_STATUS_FAILURE; 872 873 *pMemoryBlockVirt = dev->mem_list[(dev->mem_list_num)++] = (void *)malloc(BlockSize); 874 return LM_STATUS_SUCCESS; 875} 876 877 878LM_STATUS 879MM_AllocateSharedMemory(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize, 880 PLM_VOID *pMemoryBlockVirt, PLM_PHYSICAL_ADDRESS pMemoryBlockPhy, 881 LM_BOOL cached /* we ignore this */) 882{ 883 struct be_b57_dev *dev; 884 void *pvirt = NULL; 885 area_id area_desc; 886 physical_entry entry; 887 888 dev = (struct be_b57_dev *)(pDevice); 889 area_desc = dev->lockmem_list[dev->lockmem_list_num++] = create_area("broadcom_shared_mem", 890 &pvirt, B_ANY_KERNEL_ADDRESS, ROUND_UP_TO_PAGE(BlockSize), 891 B_CONTIGUOUS, 0); 892 893 if (area_desc < B_OK) 894 return LM_STATUS_FAILURE; 895 896 memset(pvirt, 0, BlockSize); 897 *pMemoryBlockVirt = (PLM_VOID) pvirt; 898 899 get_memory_map(pvirt,BlockSize,&entry,1); 900 pMemoryBlockPhy->Low = (uint32)entry.address; 901 pMemoryBlockPhy->High = (uint32)(entry.address >> 32); 902 /* We only support 32 bit */ 903 904 return LM_STATUS_SUCCESS; 905} 906 907 908LM_STATUS 909MM_GetConfig(PLM_DEVICE_BLOCK pDevice) 910{ 911 pDevice->DisableAutoNeg = FALSE; 912 pDevice->RequestedLineSpeed = LM_LINE_SPEED_AUTO; 913 pDevice->RequestedDuplexMode = LM_DUPLEX_MODE_FULL; 914 pDevice->FlowControlCap = LM_FLOW_CONTROL_AUTO_PAUSE; 915 pDevice->RxPacketDescCnt = DEFAULT_RX_PACKET_DESC_COUNT; 916 pDevice->TxPacketDescCnt = DEFAULT_TX_PACKET_DESC_COUNT; 917 pDevice->TxMaxCoalescedFrames = DEFAULT_TX_MAX_COALESCED_FRAMES; 918 pDevice->RxMaxCoalescedFrames = DEFAULT_RX_MAX_COALESCED_FRAMES; 919 pDevice->RxStdDescCnt = DEFAULT_STD_RCV_DESC_COUNT; 920 pDevice->RxCoalescingTicks = DEFAULT_RX_COALESCING_TICKS; 921 pDevice->TxCoalescingTicks = DEFAULT_TX_COALESCING_TICKS; 922 pDevice->StatsCoalescingTicks = DEFAULT_STATS_COALESCING_TICKS; 923 pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE; 924 925 return LM_STATUS_SUCCESS; 926} 927 928 929LM_STATUS 930MM_IndicateStatus(PLM_DEVICE_BLOCK pDevice, LM_STATUS Status) 931{ 932#ifdef HAIKU_TARGET_PLATFORM_HAIKU 933 struct be_b57_dev *pUmDevice = (struct be_b57_dev *)pDevice; 934 935 if (pUmDevice->linkChangeSem != -1) 936 release_sem_etc(pUmDevice->linkChangeSem, 1, 937 B_DO_NOT_RESCHEDULE); 938#endif 939 940 return LM_STATUS_SUCCESS; 941} 942 943 944LM_STATUS 945MM_InitializeUmPackets(PLM_DEVICE_BLOCK pDevice) 946{ 947 int i; 948 struct be_b57_dev *pUmDevice = (struct be_b57_dev *) pDevice; 949 struct B_UM_PACKET *pUmPacket; 950 PLM_PACKET pPacket; 951 952 for (i = 0; i < pDevice->RxPacketDescCnt; i++) { 953 pPacket = QQ_PopHead(&pDevice->RxPacketFreeQ.Container); 954 pUmPacket = (struct B_UM_PACKET *) pPacket; 955 pUmPacket->data = chunk_pool_get(); 956 if (pUmPacket->data == 0) { 957 //QQ_PushTail(&pUmDevice->rx_out_of_buf_q.Container, pPacket); 958 // No pretty rx_out_of_buf_q, but we sure as hell don't want anything to do with these packets, so we leak them. 959 // Probably not the best idea, but it works. 960 continue; 961 } 962 QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket); 963 } 964 965 return LM_STATUS_SUCCESS; 966} 967 968LM_STATUS MM_FreeRxBuffer(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket) { 969 struct B_UM_PACKET *pUmPacket; 970 struct be_b57_dev *pUmDevice = (struct be_b57_dev *) pDevice; 971 pUmPacket = (struct B_UM_PACKET *) pPacket; 972 chunk_pool_put(pUmPacket->data); 973 pUmPacket->data = NULL; 974 return LM_STATUS_SUCCESS; 975} 976 977 978void 979MM_UnmapRxDma(LM_DEVICE_BLOCK *pDevice, LM_PACKET *pPacket) 980{ 981} 982 983 984LM_STATUS 985MM_CoalesceTxBuffer(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket) 986{ 987 /* Our buffers are pre-coalesced (which slows things down a little) */ 988 return LM_STATUS_SUCCESS; 989} 990 991 992LM_DEVICE_BLOCK * 993MM_FindPeerDev(LM_DEVICE_BLOCK *pDevice) 994{ 995 /* I have no idea what this routine does. I think it's optional... */ 996 return 0; 997} 998 999 1000LM_STATUS 1001MM_Sleep(LM_DEVICE_BLOCK *pDevice, LM_UINT32 msec) 1002{ 1003 snooze(msec*1e3); 1004 return LM_STATUS_SUCCESS; 1005} 1006