1 /* 2 * Copyright 2007, Hugo Santos. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Hugo Santos, hugosantos@gmail.com 7 * 8 * Some of this code is based on previous work by Marcus Overhagen. 9 */ 10 11 #include "device.h" 12 13 #include <stdlib.h> 14 #include <Drivers.h> 15 #include <ether_driver.h> 16 17 #include <sys/sockio.h> 18 19 #include <compat/sys/haiku-module.h> 20 21 #include <compat/sys/bus.h> 22 #include <compat/sys/mbuf.h> 23 #include <compat/net/ethernet.h> 24 25 26 #define MAX_DEVICES 8 27 28 29 struct network_device *gDevices[MAX_DEVICES]; 30 const char *gDevNameList[MAX_DEVICES + 1]; 31 32 33 static struct network_device * 34 allocate_device(driver_t *driver) 35 { 36 char semName[64]; 37 38 struct network_device *dev = malloc(sizeof(struct network_device)); 39 if (dev == NULL) 40 return NULL; 41 42 memset(dev, 0, sizeof(struct device)); 43 44 if (init_device(DEVNET(dev), driver) == NULL) { 45 free(dev); 46 return NULL; 47 } 48 49 snprintf(semName, sizeof(semName), "%s rcv", gDriverName); 50 51 dev->receive_sem = create_sem(0, semName); 52 if (dev->receive_sem < 0) { 53 uninit_device(DEVNET(dev)); 54 free(dev); 55 return NULL; 56 } 57 58 dev->link_state_sem = -1; 59 60 ifq_init(&dev->receive_queue, semName); 61 62 return dev; 63 } 64 65 66 static void 67 free_device(struct network_device *dev) 68 { 69 delete_sem(dev->receive_sem); 70 ifq_uninit(&dev->receive_queue); 71 uninit_device(DEVNET(dev)); 72 free(dev); 73 } 74 75 76 device_method_signature_t 77 _resolve_method(driver_t *driver, const char *name) 78 { 79 device_method_signature_t method = NULL; 80 int i; 81 82 for (i = 0; method == NULL && driver->methods[i].name != NULL; i++) { 83 if (strcmp(driver->methods[i].name, name) == 0) 84 method = driver->methods[i].method; 85 } 86 87 return method; 88 } 89 90 91 static status_t 92 compat_open(const char *name, uint32 flags, void **cookie) 93 { 94 struct network_device *dev; 95 status_t status; 96 int i; 97 98 driver_printf("compat_open(%s, 0x%lx)\n", name, flags); 99 100 status = get_module(NET_STACK_MODULE_NAME, (module_info **)&gStack); 101 if (status < B_OK) 102 return status; 103 104 for (i = 0; gDevNameList[i] != NULL; i++) { 105 if (strcmp(gDevNameList[i], name) == 0) 106 break; 107 } 108 109 if (gDevNameList[i] == NULL) 110 return B_ERROR; 111 112 dev = gDevices[i]; 113 114 if (!atomic_test_and_set(&dev->open, 1, 0)) 115 return B_BUSY; 116 117 /* some drivers expect the softc to be zero'ed out */ 118 memset(dev->base.softc, 0, dev->base.driver->softc_size); 119 120 status = DEVNET(dev)->methods.attach(DEVNET(dev)); 121 if (status != 0) 122 atomic_and(&dev->open, 0); 123 124 driver_printf(" ... status = 0x%ld\n", status); 125 126 if (status == 0) { 127 struct ifnet *ifp = dev->ifp; 128 struct ifreq ifr; 129 130 ifp->if_flags &= ~IFF_UP; 131 ifp->if_ioctl(ifp, SIOCSIFFLAGS, NULL); 132 133 memset(&ifr, 0, sizeof(ifr)); 134 ifr.ifr_media = IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, 0); 135 ifp->if_ioctl(ifp, SIOCSIFMEDIA, (caddr_t)&ifr); 136 137 ifp->if_flags |= IFF_UP; 138 ifp->if_ioctl(ifp, SIOCSIFFLAGS, NULL); 139 } 140 141 *cookie = dev; 142 return status; 143 } 144 145 146 static status_t 147 compat_close(void *cookie) 148 { 149 struct network_device *dev = cookie; 150 151 device_printf(DEVNET(dev), "compat_close()\n"); 152 153 atomic_or(&DEVNET(dev)->flags, DEVICE_CLOSED); 154 155 /* do we need a memory barrier in read() or is the atomic_or 156 * (and the implicit 'lock') enough? */ 157 158 release_sem_etc(dev->receive_sem, 1, B_RELEASE_ALL); 159 160 return B_OK; 161 } 162 163 164 static status_t 165 compat_free(void *cookie) 166 { 167 struct network_device *dev = cookie; 168 169 device_printf(DEVNET(dev), "compat_free()\n"); 170 171 DEVNET(dev)->methods.detach(DEVNET(dev)); 172 173 /* XXX empty out the send queue */ 174 175 atomic_and(&dev->open, 0); 176 put_module(NET_STACK_MODULE_NAME); 177 178 return B_OK; 179 } 180 181 182 static status_t 183 compat_read(void *cookie, off_t position, void *buf, size_t *numBytes) 184 { 185 struct network_device *dev = cookie; 186 uint32 semFlags = B_CAN_INTERRUPT; 187 status_t status; 188 struct mbuf *mb; 189 size_t len; 190 191 device_printf(DEVNET(dev), "compat_read(%lld, %p, [%lu])\n", position, buf, 192 *numBytes); 193 194 if (DEVNET(dev)->flags & DEVICE_CLOSED) 195 return B_INTERRUPTED; 196 197 if (DEVNET(dev)->flags & DEVICE_NON_BLOCK) 198 semFlags |= B_RELATIVE_TIMEOUT; 199 200 do { 201 status = acquire_sem_etc(dev->receive_sem, 1, semFlags, 0); 202 if (DEVNET(dev)->flags & DEVICE_CLOSED) 203 return B_INTERRUPTED; 204 205 if (status == B_WOULD_BLOCK) { 206 *numBytes = 0; 207 return B_OK; 208 } else if (status < B_OK) 209 return status; 210 211 IF_DEQUEUE(&dev->receive_queue, mb); 212 } while (mb == NULL); 213 214 len = min_c(max_c((size_t)mb->m_len, 0), *numBytes); 215 216 #if 0 217 mb = m_defrag(mb, 0); 218 if (mb == NULL) { 219 *numBytes = 0; 220 return B_NO_MEMORY; 221 } 222 #endif 223 224 memcpy(buf, mtod(mb, const void *), len); 225 *numBytes = len; 226 227 m_freem(mb); 228 return B_OK; 229 } 230 231 232 static status_t 233 compat_write(void *cookie, off_t position, const void *buffer, 234 size_t *numBytes) 235 { 236 struct network_device *dev = cookie; 237 struct mbuf *mb; 238 239 device_printf(DEVNET(dev), "compat_write(%lld, %p, [%lu])\n", position, 240 buffer, *numBytes); 241 242 mb = m_getcl(0, MT_DATA, 0); 243 if (mb == NULL) 244 return ENOBUFS; 245 246 /* if we waited, check after if the ifp is still valid */ 247 248 mb->m_len = min_c(*numBytes, (size_t)MCLBYTES); 249 memcpy(mtod(mb, void *), buffer, mb->m_len); 250 251 return dev->ifp->if_output(dev->ifp, mb, NULL, NULL); 252 } 253 254 255 static status_t 256 compat_control(void *cookie, uint32 op, void *arg, size_t len) 257 { 258 struct network_device *dev = cookie; 259 struct ifnet *ifp = dev->ifp; 260 261 switch (op) { 262 case ETHER_INIT: 263 return B_OK; 264 265 case ETHER_GETADDR: 266 return user_memcpy(arg, IF_LLADDR(dev->ifp), ETHER_ADDR_LEN); 267 268 case ETHER_NONBLOCK: 269 { 270 int32 value; 271 if (len < 4) 272 return B_BAD_VALUE; 273 if (user_memcpy(&value, arg, sizeof(int32)) < B_OK) 274 return B_BAD_ADDRESS; 275 if (value) 276 DEVNET(dev)->flags |= DEVICE_NON_BLOCK; 277 else 278 DEVNET(dev)->flags &= ~DEVICE_NON_BLOCK; 279 return B_OK; 280 } 281 282 case ETHER_SETPROMISC: 283 { 284 int32 value; 285 if (len < 4) 286 return B_BAD_VALUE; 287 if (user_memcpy(&value, arg, sizeof(int32)) < B_OK) 288 return B_BAD_ADDRESS; 289 if (value) 290 ifp->if_flags |= IFF_PROMISC; 291 else 292 ifp->if_flags &= ~IFF_PROMISC; 293 return ifp->if_ioctl(ifp, SIOCSIFFLAGS, NULL); 294 } 295 296 case ETHER_GETFRAMESIZE: 297 { 298 uint32 frame_size; 299 if (len < 4) 300 return B_BAD_VALUE; 301 frame_size = dev->ifp->if_mtu + ETHER_HDR_LEN; 302 return user_memcpy(arg, &frame_size, 4); 303 } 304 305 case ETHER_ADDMULTI: 306 case ETHER_REMMULTI: 307 { 308 struct sockaddr_dl address; 309 310 if (!(ifp->if_flags & IFF_MULTICAST) == 0) 311 return EOPNOTSUPP; 312 313 memset(&address, 0, sizeof(address)); 314 address.sdl_family = AF_LINK; 315 memcpy(LLADDR(&address), arg, ETHER_ADDR_LEN); 316 317 if (op == ETHER_ADDMULTI) 318 return if_addmulti(ifp, (struct sockaddr *)&address, NULL); 319 else 320 return if_delmulti(ifp, (struct sockaddr *)&address); 321 } 322 323 case ETHER_GET_LINK_STATE: 324 { 325 struct ifmediareq mediareq; 326 ether_link_state_t state; 327 status_t status; 328 329 if (len < sizeof(ether_link_state_t)) 330 return EINVAL; 331 332 memset(&mediareq, 0, sizeof(mediareq)); 333 status = ifp->if_ioctl(ifp, SIOCGIFMEDIA, (caddr_t)&mediareq); 334 if (status < B_OK) 335 return status; 336 337 state.media = mediareq.ifm_active; 338 if (mediareq.ifm_status & IFM_ACTIVE) 339 state.media |= IFM_ACTIVE; 340 if (mediareq.ifm_active & IFM_10_T) 341 state.speed = 10000; 342 else if (mediareq.ifm_active & IFM_100_TX) 343 state.speed = 100000; 344 else 345 state.speed = 1000000; 346 state.quality = 1000; 347 348 return user_memcpy(arg, &state, sizeof(ether_link_state_t)); 349 } 350 351 case ETHER_SET_LINK_STATE_SEM: 352 if (user_memcpy(&dev->link_state_sem, arg, sizeof(sem_id)) < B_OK) { 353 dev->link_state_sem = -1; 354 return B_BAD_ADDRESS; 355 } 356 return B_OK; 357 } 358 359 return B_BAD_VALUE; 360 } 361 362 363 device_hooks gDeviceHooks = { 364 compat_open, 365 compat_close, 366 compat_free, 367 compat_control, 368 compat_read, 369 compat_write, 370 }; 371 372 373 status_t 374 _fbsd_init_hardware(driver_t *driver) 375 { 376 struct network_device fakeDevice; 377 device_probe_t *probe; 378 int i; 379 380 dprintf("%s: init_hardware(%p)\n", gDriverName, driver); 381 382 if (get_module(B_PCI_MODULE_NAME, (module_info **)&gPci) < B_OK) 383 return B_ERROR; 384 385 probe = (device_probe_t *)_resolve_method(driver, "device_probe"); 386 if (probe == NULL) { 387 dprintf("%s: driver has no device_probe method.\n", gDriverName); 388 return B_ERROR; 389 } 390 391 memset(&fakeDevice, 0, sizeof(struct device)); 392 393 for (i = 0; gPci->get_nth_pci_info(i, &fakeDevice.pci_info) == B_OK; i++) { 394 int result; 395 result = probe(DEVNET(&fakeDevice)); 396 if (result >= 0) { 397 dprintf("%s, found %s at %d\n", gDriverName, 398 device_get_desc(DEVNET(&fakeDevice)), i); 399 if (DEVNET(&fakeDevice)->flags & DEVICE_DESC_ALLOCED) 400 free((char *)DEVNET(&fakeDevice)->description); 401 put_module(B_PCI_MODULE_NAME); 402 return B_OK; 403 } 404 } 405 406 dprintf("%s: no hardware found.\n", gDriverName); 407 put_module(B_PCI_MODULE_NAME); 408 409 return B_ERROR; 410 } 411 412 413 status_t 414 _fbsd_init_driver(driver_t *driver) 415 { 416 int i, ncards = 0; 417 status_t status; 418 struct network_device *dev; 419 420 dprintf("%s: init_driver(%p)\n", gDriverName, driver); 421 422 status = get_module(B_PCI_MODULE_NAME, (module_info **)&gPci); 423 if (status < B_OK) { 424 driver_printf("Failed to load PCI module.\n"); 425 return status; 426 } 427 428 dev = allocate_device(driver); 429 if (dev == NULL) 430 goto err_1; 431 432 status = init_compat_layer(); 433 if (status < B_OK) 434 goto err_2; 435 436 status = init_mutexes(); 437 if (status < B_OK) 438 goto err_3; 439 440 if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) { 441 status = init_taskqueues(); 442 if (status < B_OK) 443 goto err_4; 444 } 445 446 status = init_mbufs(); 447 if (status < B_OK) 448 goto err_5; 449 450 init_bounce_pages(); 451 452 for (i = 0; dev != NULL 453 && gPci->get_nth_pci_info(i, &dev->pci_info) == B_OK; i++) { 454 device_t base = DEVNET(dev); 455 456 if (base->methods.probe(base) >= 0) { 457 device_sprintf_name(base, "net/%s/%i", gDriverName, ncards); 458 dprintf("%s, adding %s @%d -> /dev/%s\n", gDriverName, 459 device_get_desc(base), i, device_get_name(base)); 460 461 gDevices[ncards] = dev; 462 gDevNameList[ncards] = device_get_name(base); 463 464 ncards++; 465 if (ncards < MAX_DEVICES) 466 dev = allocate_device(driver); 467 else 468 dev = NULL; 469 } 470 } 471 472 if (dev != NULL) 473 free_device(dev); 474 475 dprintf("%s, ... %d cards.\n", gDriverName, ncards); 476 477 gDevNameList[ncards + 1] = NULL; 478 479 return B_OK; 480 481 err_5: 482 if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) 483 uninit_taskqueues(); 484 err_4: 485 uninit_mutexes(); 486 err_3: 487 err_2: 488 free(dev); 489 err_1: 490 put_module(B_PCI_MODULE_NAME); 491 return status; 492 } 493 494 495 void 496 _fbsd_uninit_driver(driver_t *driver) 497 { 498 int i; 499 500 dprintf("%s: uninit_driver(%p)\n", gDriverName, driver); 501 502 for (i = 0; gDevNameList[i] != NULL; i++) { 503 free_device(gDevices[i]); 504 } 505 506 uninit_bounce_pages(); 507 uninit_mbufs(); 508 if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) 509 uninit_taskqueues(); 510 uninit_mutexes(); 511 512 put_module(B_PCI_MODULE_NAME); 513 } 514