1 /* 2 * Copyright 2009-2010, François Revol, <revol@free.fr>. 3 * Sponsored by TuneTracker Systems. 4 * Based on the Haiku usb_serial driver which is: 5 * 6 * Copyright (c) 2007-2008 by Michael Lotz 7 * Heavily based on the original usb_serial driver which is: 8 * 9 * Copyright (c) 2003 by Siarzhuk Zharski <imker@gmx.li> 10 * Distributed under the terms of the MIT License. 11 */ 12 #include <KernelExport.h> 13 #include <dpc.h> 14 #include <Drivers.h> 15 #include <driver_settings.h> 16 #include <image.h> 17 #include <malloc.h> 18 #include <stdio.h> 19 #include <stdlib.h> 20 21 #include "Driver.h" 22 #include "SerialDevice.h" 23 24 int32 api_version = B_CUR_DRIVER_API_VERSION; 25 static const char *sDeviceBaseName = DEVFS_BASE; 26 SerialDevice *gSerialDevices[DEVICES_COUNT]; 27 char *gDeviceNames[DEVICES_COUNT + 1]; 28 config_manager_for_driver_module_info *gConfigManagerModule = NULL; 29 isa_module_info *gISAModule = NULL; 30 pci_module_info *gPCIModule = NULL; 31 tty_module_info *gTTYModule = NULL; 32 dpc_module_info *gDPCModule = NULL; 33 void* gDPCHandle = NULL; 34 sem_id gDriverLock = -1; 35 bool gHandleISA = false; 36 uint32 gKernelDebugPort = 0x3f8; 37 38 // 24 MHz clock 39 static const uint32 sDefaultRates[] = { 40 0, //B0 41 2304, //B50 42 1536, //B75 43 1047, //B110 44 857, //B134 45 768, //B150 46 512, //B200 47 384, //B300 48 192, //B600 49 0, //B1200 50 0, //B1800 51 48, //B2400 52 24, //B4800 53 12, //B9600 54 6, //B19200 55 3, //B38400 56 2, //B57600 57 1, //B115200 58 0, //B230400 59 4, //B31250 60 0, //921600 !? 61 }; 62 63 // 8MHz clock on serial3 and 4 on the BeBox 64 #if 0 65 static const uint32 sBeBoxRates[] = { 66 0, //B0 67 //... TODO 68 }; 69 #endif 70 71 // XXX: should really be generated from metadata (CSV ?) 72 73 static const struct serial_support_descriptor sSupportedDevices[] = { 74 75 #ifdef HANDLE_ISA_COM 76 // ISA devices 77 { B_ISA_BUS, "Generic 16550 Serial Port", sDefaultRates, NULL, { 8, 8, 8 }, 78 { PCI_simple_communications, PCI_serial, PCI_serial_16550 } }, 79 #endif 80 // PCI devices 81 82 // vendor/device matches first 83 84 /* 85 // vendor: OxfordSemi 86 #define VN "OxfordSemi" 87 // http://www.softio.com/ox16pci954ds.pdf 88 { B_PCI_BUS, "OxfordSemi 16950 Serial Port", sDefaultRates, NULL, { 32, 32, 8 }, 89 { PCI_simple_communications, PCI_serial, PCI_serial_16950, 90 0x1415, 0x9501, PCI_INVAL, PCI_INVAL } }, 91 92 // http://www.softio.com/ox16pci952ds.pdf 93 { B_PCI_BUS, "OxfordSemi 16950 Serial Port", sDefaultRates, NULL, { 8, 8, 8 }, 94 { PCI_simple_communications, PCI_serial, PCI_serial_16950, 95 0x1415, 0x9521, PCI_INVAL, PCI_INVAL } }, 96 */ 97 98 99 // vendor: NetMos 100 #define VN "MosChip" 101 102 // used in Manhattan cards 103 // 1 function / port 104 // http://www.moschip.com/data/products/MCS9865/Data%20Sheet_9865.pdf 105 { B_PCI_BUS, VN" 16550 Serial Port", sDefaultRates, NULL, { 8, 8, 8, 0, 0, 0 }, 106 { PCI_simple_communications, PCI_serial, PCI_serial_16550, 107 0x9710, 0x9865, PCI_INVAL, PCI_INVAL } }, 108 109 // single function with all ports 110 // only BAR 0 & 1 are UART 111 // http://www.moschip.com/data/products/NM9835/Data%20Sheet_9835.pdf 112 { B_PCI_BUS, VN" 16550 Serial Port", sDefaultRates, NULL, { 8, 8, 8, (uint8)~0x3, 2, 0x000f }, 113 { PCI_simple_communications, PCI_serial, PCI_serial_16550, 114 0x9710, 0x9835, PCI_INVAL, PCI_INVAL } }, 115 116 #undef VN 117 118 119 120 // generic fallback matches 121 /* 122 { B_PCI_BUS, "Generic XT Serial Port", NULL }, 123 { PCI_INVAL, PCI_INVAL, PCI_simple_communications, 124 PCI_serial, PCI_serial_xt, PCI_INVAL, PCI_INVAL } }, 125 126 { B_PCI_BUS, "Generic 16450 Serial Port", NULL }, 127 { PCI_INVAL, PCI_INVAL, PCI_simple_communications, 128 PCI_serial, PCI_serial_16450, PCI_INVAL, PCI_INVAL } }, 129 130 */ 131 { B_PCI_BUS, "Generic 16550 Serial Port", sDefaultRates, NULL, { 8, 8, 8 }, 132 { PCI_simple_communications, PCI_serial, PCI_serial_16550, 133 PCI_INVAL, PCI_INVAL, PCI_INVAL, PCI_INVAL } }, 134 135 { B_PCI_BUS, "Generic 16650 Serial Port", sDefaultRates, NULL, { 8, 8, 8 }, 136 { PCI_simple_communications, PCI_serial, PCI_serial_16650, 137 PCI_INVAL, PCI_INVAL, PCI_INVAL, PCI_INVAL } }, 138 139 { B_PCI_BUS, "Generic 16750 Serial Port", sDefaultRates, NULL, { 8, 8, 8 }, 140 { PCI_simple_communications, PCI_serial, PCI_serial_16750, 141 PCI_INVAL, PCI_INVAL, PCI_INVAL, PCI_INVAL } }, 142 143 { B_PCI_BUS, "Generic 16850 Serial Port", sDefaultRates, NULL, { 8, 8, 8 }, 144 { PCI_simple_communications, PCI_serial, PCI_serial_16850, 145 PCI_INVAL, PCI_INVAL, PCI_INVAL, PCI_INVAL } }, 146 147 { B_PCI_BUS, "Generic 16950 Serial Port", sDefaultRates, NULL, { 8, 8, 8 }, 148 { PCI_simple_communications, PCI_serial, PCI_serial_16950, 149 PCI_INVAL, PCI_INVAL, PCI_INVAL, PCI_INVAL } }, 150 151 // non PCI_serial devices 152 153 // beos zz driver supported that one 154 { B_PCI_BUS, "Lucent Modem", sDefaultRates, NULL, { 8, 8, 8 }, 155 { PCI_simple_communications, PCI_simple_communications_other, 0x00, 156 0x11C1, 0x0480, PCI_INVAL, PCI_INVAL } }, 157 158 { B_PCI_BUS, NULL, NULL, NULL, {0}, {0} } 159 }; 160 161 162 // hardcoded ISA ports 163 static struct isa_ports { 164 uint32 ioBase; 165 uint32 irq; 166 } sHardcodedPorts[] = { 167 { 0x3f8, 4 }, 168 { 0x2f8, 3 }, 169 { 0x3e8, 4 }, 170 { 0x2e8, 3 }, 171 }; 172 173 #if 0 174 status_t 175 pc_serial_device_added(pc_device device, void **cookie) 176 { 177 TRACE_FUNCALLS("> pc_serial_device_added(0x%08x, 0x%08x)\n", device, cookie); 178 179 status_t status = B_OK; 180 const pc_device_descriptor *descriptor 181 = gUSBModule->get_device_descriptor(device); 182 183 TRACE_ALWAYS("probing device: 0x%04x/0x%04x\n", descriptor->vendor_id, 184 descriptor->product_id); 185 186 *cookie = NULL; 187 SerialDevice *serialDevice = SerialDevice::MakeDevice(device, 188 descriptor->vendor_id, descriptor->product_id); 189 190 const pc_configuration_info *configuration 191 = gUSBModule->get_nth_configuration(device, 0); 192 193 if (!configuration) 194 return B_ERROR; 195 196 status = serialDevice->AddDevice(configuration); 197 if (status < B_OK) { 198 delete serialDevice; 199 return status; 200 } 201 202 acquire_sem(gDriverLock); 203 for (int32 i = 0; i < DEVICES_COUNT; i++) { 204 if (gSerialDevices[i] != NULL) 205 continue; 206 207 status = serialDevice->Init(); 208 if (status < B_OK) { 209 delete serialDevice; 210 return status; 211 } 212 213 gSerialDevices[i] = serialDevice; 214 *cookie = serialDevice; 215 216 release_sem(gDriverLock); 217 TRACE_ALWAYS("%s (0x%04x/0x%04x) added\n", serialDevice->Description(), 218 descriptor->vendor_id, descriptor->product_id); 219 return B_OK; 220 } 221 222 release_sem(gDriverLock); 223 return B_ERROR; 224 } 225 226 227 status_t 228 pc_serial_device_removed(void *cookie) 229 { 230 TRACE_FUNCALLS("> pc_serial_device_removed(0x%08x)\n", cookie); 231 232 acquire_sem(gDriverLock); 233 234 SerialDevice *device = (SerialDevice *)cookie; 235 for (int32 i = 0; i < DEVICES_COUNT; i++) { 236 if (gSerialDevices[i] == device) { 237 if (device->IsOpen()) { 238 // the device will be deleted upon being freed 239 device->Removed(); 240 } else { 241 delete device; 242 gSerialDevices[i] = NULL; 243 } 244 break; 245 } 246 } 247 248 release_sem(gDriverLock); 249 TRACE_FUNCRET("< pc_serial_device_removed() returns\n"); 250 return B_OK; 251 } 252 #endif 253 254 //#pragma mark - 255 256 status_t 257 pc_serial_insert_device(SerialDevice *device) 258 { 259 status_t status = B_OK; 260 261 //XXX fix leaks! 262 acquire_sem(gDriverLock); 263 for (int32 i = 0; i < DEVICES_COUNT; i++) { 264 if (gSerialDevices[i] != NULL) 265 continue; 266 267 status = device->Init(); 268 if (status < B_OK) { 269 delete device; 270 //return status; 271 break; 272 } 273 274 gSerialDevices[i] = device; 275 276 release_sem(gDriverLock); 277 TRACE_ALWAYS("%s added\n", device->Description()); 278 return B_OK; 279 } 280 281 release_sem(gDriverLock); 282 return B_ERROR; 283 } 284 285 286 // probe devices with config_manager 287 static status_t 288 scan_bus(bus_type bus) 289 { 290 const char *bus_name = "Unknown"; 291 uint64 cookie = 0; 292 //status_t status; 293 struct { 294 device_info di; 295 pci_info pi; 296 } big_info; 297 struct device_info &dinfo = big_info.di; 298 299 switch (bus) { 300 case B_ISA_BUS: 301 bus_name = "ISA"; 302 break; 303 case B_PCI_BUS: 304 bus_name = "PCI"; 305 break; 306 case B_PCMCIA_BUS: 307 default: 308 return EINVAL; 309 } 310 TRACE_ALWAYS("scanning %s bus...\n", bus_name); 311 312 //XXX: clean up this mess 313 314 while ((gConfigManagerModule->get_next_device_info(bus, 315 &cookie, &big_info.di, sizeof(big_info)) == B_OK)) { 316 // skip disabled devices 317 if ((dinfo.flags & B_DEVICE_INFO_ENABLED) == 0) 318 continue; 319 // skip non configured devices 320 if ((dinfo.flags & B_DEVICE_INFO_CONFIGURED) == 0) 321 continue; 322 // and devices in error 323 if (dinfo.config_status < B_OK) 324 continue; 325 326 327 /* 328 TRACE_ALWAYS("device: 0x%08lx 0x%08lx 0x%08lx 0x%08lx\n", 329 dinfo.id[0], dinfo.id[1], dinfo.id[2], dinfo.id[3]); 330 */ 331 332 /* 333 if (bus == B_PCI_BUS) { 334 pci_info *pcii = (pci_info *)(((char *)&dinfo) + 335 dinfo.bus_dependent_info_offset); 336 TRACE_ALWAYS("pci: %04x:%04x\n", 337 pcii->vendor_id, pcii->device_id); 338 if ((pcii->header_type & PCI_header_type_mask) == 339 PCI_header_type_generic) { 340 TRACE_ALWAYS("subsys: %04x:%04x\n", 341 pcii->u.h0.subsystem_vendor_id, pcii->u.h0.subsystem_id); 342 } 343 } 344 */ 345 346 const struct serial_support_descriptor *supported = NULL; 347 for (int i = 0; sSupportedDevices[i].name; i++) { 348 if (sSupportedDevices[i].bus != bus) 349 continue; 350 if (sSupportedDevices[i].match.class_base != PCI_undefined && 351 sSupportedDevices[i].match.class_base != dinfo.devtype.base) 352 continue; 353 if (sSupportedDevices[i].match.class_sub != PCI_undefined && 354 sSupportedDevices[i].match.class_sub != dinfo.devtype.subtype) 355 continue; 356 if (sSupportedDevices[i].match.class_api != PCI_undefined && 357 sSupportedDevices[i].match.class_api != dinfo.devtype.interface) 358 continue; 359 360 #if 0 361 // either this way 362 if (bus == B_PCI_BUS) { 363 pci_info *pcii = (pci_info *)(((char *)&dinfo) + 364 dinfo.bus_dependent_info_offset); 365 if (sSupportedDevices[i].match.vendor_id != PCI_INVAL && 366 sSupportedDevices[i].match.vendor_id != pcii->vendor_id) 367 continue; 368 if (sSupportedDevices[i].match.device_id != PCI_INVAL && 369 sSupportedDevices[i].match.device_id != pcii->device_id) 370 continue; 371 } 372 #endif 373 // or this one: 374 // .id[0] = vendor_id and .id[1] = device_id 375 // .id[3?] = subsys_vendor_id and .id[2?] = subsys_device_id 376 if (bus == B_PCI_BUS && 377 sSupportedDevices[i].match.vendor_id != PCI_INVAL && 378 sSupportedDevices[i].match.vendor_id != dinfo.id[0]) 379 continue; 380 381 if (bus == B_PCI_BUS && 382 sSupportedDevices[i].match.device_id != PCI_INVAL && 383 sSupportedDevices[i].match.device_id != dinfo.id[1]) 384 continue; 385 386 387 supported = &sSupportedDevices[i]; 388 break; 389 } 390 if (supported == NULL) 391 continue; 392 393 struct { 394 struct device_configuration c; 395 resource_descriptor res[16]; 396 } config; 397 if (gConfigManagerModule->get_size_of_current_configuration_for( 398 cookie) > (int)sizeof(config)) { 399 TRACE_ALWAYS("config size too big for device\n"); 400 continue; 401 } 402 403 if (gConfigManagerModule->get_current_configuration_for(cookie, 404 &config.c, sizeof(config)) < B_OK) { 405 TRACE_ALWAYS("can't get config for device\n"); 406 continue; 407 408 } 409 410 TRACE_ALWAYS("device %Ld resources: %d irq %d dma %d io %d mem\n", 411 cookie, 412 gConfigManagerModule->count_resource_descriptors_of_type( 413 &config.c, B_IRQ_RESOURCE), 414 gConfigManagerModule->count_resource_descriptors_of_type( 415 &config.c, B_DMA_RESOURCE), 416 gConfigManagerModule->count_resource_descriptors_of_type( 417 &config.c, B_IO_PORT_RESOURCE), 418 gConfigManagerModule->count_resource_descriptors_of_type( 419 &config.c, B_MEMORY_RESOURCE)); 420 421 422 // we first need the IRQ 423 resource_descriptor irqdesc; 424 if (gConfigManagerModule->get_nth_resource_descriptor_of_type( 425 &config.c, 0, B_IRQ_RESOURCE, &irqdesc, sizeof(irqdesc)) < B_OK) { 426 TRACE_ALWAYS("can't find IRQ for device\n"); 427 continue; 428 } 429 int irq; 430 // XXX: what about APIC lines ? 431 for (irq = 0; irq < 32; irq++) { 432 if (irqdesc.d.m.mask & (1 << irq)) 433 break; 434 } 435 //TRACE_ALWAYS("irq %d\n", irq); 436 //TRACE_ALWAYS("irq: %lx,%lx,%lx\n", irqdesc.d.m.mask, irqdesc.d.m.flags, irqdesc.d.m.cookie); 437 438 TRACE_ALWAYS("found %s device %Ld [%x|%x|%x] " 439 /*"ID: '%16.16s'"*/" irq: %d flags: %08lx status: %s\n", 440 bus_name, cookie, dinfo.devtype.base, dinfo.devtype.subtype, 441 dinfo.devtype.interface, /*dinfo.id,*/ irq, dinfo.flags, 442 strerror(dinfo.config_status)); 443 444 // force enable I/O ports on PCI devices 445 #if 0 446 if (bus == B_PCI_BUS) { 447 pci_info *pcii = (pci_info *)(((char *)&dinfo) + 448 dinfo.bus_dependent_info_offset); 449 450 uint32 cmd = gPCIModule->read_pci_config(pcii->bus, pcii->device, 451 pcii->function, PCI_command, 2); 452 TRACE_ALWAYS("PCI_command: 0x%04lx\n", cmd); 453 cmd |= PCI_command_io; 454 gPCIModule->write_pci_config(pcii->bus, pcii->device, 455 pcii->function, PCI_command, 2, cmd); 456 } 457 #endif 458 459 resource_descriptor iodesc; 460 SerialDevice *master = NULL; 461 462 //TODO: handle maxports 463 //TODO: handle subsystem_id_mask 464 465 // instanciate devices on IO ports 466 for (int i = 0; 467 gConfigManagerModule->get_nth_resource_descriptor_of_type( 468 &config.c, i, B_IO_PORT_RESOURCE, &iodesc, sizeof(iodesc)) == B_OK; 469 i++) { 470 TRACE_ALWAYS("io at 0x%04lx len 0x%04lx\n", iodesc.d.r.minbase, 471 iodesc.d.r.len); 472 473 if (iodesc.d.r.len < supported->constraints.minsize) 474 continue; 475 if (iodesc.d.r.len > supported->constraints.maxsize) 476 continue; 477 SerialDevice *device; 478 uint32 ioport = iodesc.d.r.minbase; 479 next_split: 480 // no more to split 481 if ((ioport - iodesc.d.r.minbase) >= iodesc.d.r.len) 482 continue; 483 484 TRACE_ALWAYS("inserting device at io 0x%04lx as %s\n", ioport, 485 supported->name); 486 487 488 device = new(std::nothrow) SerialDevice(supported, ioport, irq, master); 489 if (device == NULL) { 490 TRACE_ALWAYS("can't allocate device\n"); 491 continue; 492 } 493 494 if (pc_serial_insert_device(device) < B_OK) { 495 TRACE_ALWAYS("can't insert device\n"); 496 continue; 497 } 498 if (master == NULL) 499 master = device; 500 501 ioport += supported->constraints.split; 502 goto next_split; 503 // try next part of the I/O range now 504 } 505 // we have at least one device 506 if (master) { 507 // hook up the irq 508 #if 0 509 status = install_io_interrupt_handler(irq, pc_serial_interrupt, 510 master, 0); 511 TRACE_ALWAYS("installing irq %d handler: %s\n", irq, strerror(status)); 512 #endif 513 } 514 } 515 return B_OK; 516 } 517 518 519 // until we support ISA device enumeration from PnP BIOS or ACPI, 520 // we have to probe the 4 default COM ports... 521 status_t 522 scan_isa_hardcoded() 523 { 524 #ifdef HANDLE_ISA_COM 525 int i; 526 527 for (i = 0; i < 4; i++) { 528 // skip the port used for kernel debugging... 529 if (sHardcodedPorts[i].ioBase == gKernelDebugPort) 530 continue; 531 532 SerialDevice *device; 533 device = new(std::nothrow) SerialDevice(&sSupportedDevices[0], 534 sHardcodedPorts[i].ioBase, sHardcodedPorts[i].irq); 535 if (device != NULL && device->Probe()) 536 pc_serial_insert_device(device); 537 else 538 delete device; 539 } 540 #endif 541 return B_OK; 542 } 543 544 545 // this version doesn't use config_manager, but can't probe the IRQ yet 546 status_t 547 scan_pci_alt() 548 { 549 pci_info info; 550 int ix; 551 TRACE_ALWAYS("scanning PCI bus (alt)...\n"); 552 553 // probe PCI devices 554 for (ix = 0; (*gPCIModule->get_nth_pci_info)(ix, &info) == B_OK; ix++) { 555 // sanity check 556 if ((info.header_type & PCI_header_type_mask) != PCI_header_type_generic) 557 continue; 558 /* 559 TRACE_ALWAYS("probing PCI device %2d [%x|%x|%x] %04x:%04x\n", 560 ix, info.class_base, info.class_sub, info.class_api, 561 info.vendor_id, info.device_id); 562 */ 563 564 const struct serial_support_descriptor *supported = NULL; 565 for (int i = 0; sSupportedDevices[i].name; i++) { 566 if (sSupportedDevices[i].bus != B_PCI_BUS) 567 continue; 568 if (info.class_base != sSupportedDevices[i].match.class_base) 569 continue; 570 if (info.class_sub != sSupportedDevices[i].match.class_sub) 571 continue; 572 if (info.class_api != sSupportedDevices[i].match.class_api) 573 continue; 574 if (sSupportedDevices[i].match.vendor_id != PCI_INVAL 575 && info.vendor_id != sSupportedDevices[i].match.vendor_id) 576 continue; 577 if (sSupportedDevices[i].match.device_id != PCI_INVAL 578 && info.device_id != sSupportedDevices[i].match.device_id) 579 continue; 580 supported = &sSupportedDevices[i]; 581 break; 582 } 583 if (supported == NULL) 584 continue; 585 586 TRACE_ALWAYS("found PCI device %2d [%x|%x|%x] %04x:%04x as %s\n", 587 ix, info.class_base, info.class_sub, info.class_api, 588 info.vendor_id, info.device_id, supported->name); 589 590 // XXX: interrupt_line doesn't seem to 591 TRACE_ALWAYS("irq line %d, pin %d\n", 592 info.u.h0.interrupt_line, info.u.h0.interrupt_pin); 593 int irq = info.u.h0.interrupt_line; 594 595 SerialDevice *master = NULL; 596 597 uint8 portCount = 0; 598 uint32 maxPorts = DEVICES_COUNT; 599 600 if (supported->constraints.maxports) { 601 maxPorts = supported->constraints.maxports; 602 TRACE_ALWAYS("card supports up to %d ports\n", maxPorts); 603 } 604 if (supported->constraints.subsystem_id_mask) { 605 uint32 id = info.u.h0.subsystem_id; 606 uint32 mask = supported->constraints.subsystem_id_mask; 607 id &= mask; 608 //TRACE_ALWAYS("mask: %lx, masked: %lx\n", mask, id); 609 while (!(mask & 0x1)) { 610 mask >>= 1; 611 id >>= 1; 612 } 613 maxPorts = (uint8)id; 614 TRACE_ALWAYS("subsystem id tells card has %d ports\n", maxPorts); 615 } 616 617 // find I/O ports 618 for (int r = 0; r < 6; r++) { 619 uint32 regbase = info.u.h0.base_registers[r]; 620 uint32 reglen = info.u.h0.base_register_sizes[r]; 621 622 /**/ 623 TRACE("ranges[%d] at 0x%08lx len 0x%lx flags 0x%02x\n", r, 624 regbase, reglen, info.u.h0.base_register_flags[r]); 625 /**/ 626 627 // empty 628 if (reglen == 0) 629 continue; 630 631 // not I/O 632 if ((info.u.h0.base_register_flags[r] & PCI_address_space) == 0) 633 continue; 634 635 // the range for sure doesn't contain any UART 636 if (supported->constraints.ignoremask & (1 << r)) { 637 TRACE_ALWAYS("ignored regs at 0x%08lx len 0x%lx\n", 638 regbase, reglen); 639 continue; 640 } 641 642 TRACE_ALWAYS("regs at 0x%08lx len 0x%lx\n", 643 regbase, reglen); 644 //&PCI_address_io_mask 645 646 if (reglen < supported->constraints.minsize) 647 continue; 648 if (reglen > supported->constraints.maxsize) 649 continue; 650 651 SerialDevice *device; 652 uint32 ioport = regbase; 653 next_split_alt: 654 // no more to split 655 if ((ioport - regbase) >= reglen) 656 continue; 657 658 if (portCount >= maxPorts) 659 break; 660 661 TRACE_ALWAYS("inserting device at io 0x%04lx as %s\n", ioport, 662 supported->name); 663 664 665 /**/ 666 device = new(std::nothrow) SerialDevice(supported, ioport, irq, master); 667 if (device == NULL) { 668 TRACE_ALWAYS("can't allocate device\n"); 669 continue; 670 } 671 672 if (pc_serial_insert_device(device) < B_OK) { 673 TRACE_ALWAYS("can't insert device\n"); 674 continue; 675 } 676 /**/ if (master == NULL) 677 master = device; 678 679 ioport += supported->constraints.split; 680 portCount++; 681 goto next_split_alt; 682 // try next part of the I/O range now 683 684 } 685 } 686 687 return B_OK; 688 } 689 690 691 static void 692 check_kernel_debug_port() 693 { 694 void *handle; 695 long int value; 696 697 handle = load_driver_settings("kernel"); 698 if (handle == NULL) 699 return; 700 701 const char *str = get_driver_parameter(handle, "serial_debug_port", 702 NULL, NULL); 703 if (str != NULL) { 704 value = strtol(str, NULL, 0); 705 if (value >= 4) // XXX: actually should be MAX_SERIAL_PORTS... 706 gKernelDebugPort = (uint32)value; 707 else if (value >= 0) // XXX: we should use the kernel_arg's table... 708 gKernelDebugPort = sHardcodedPorts[value].ioBase; 709 } 710 711 /* TODO: actually handle this in the kernel debugger too! 712 bool enabled = get_driver_boolean_parameter(handle, "serial_debug_output", 713 false, true); 714 if (!enabled) 715 gKernelDebugPort = 0; 716 */ 717 718 unload_driver_settings(handle); 719 } 720 721 722 //#pragma mark - 723 724 725 /* init_hardware - called once the first time the driver is loaded */ 726 status_t 727 init_hardware() 728 { 729 TRACE("init_hardware\n"); 730 return B_OK; 731 } 732 733 734 /* init_driver - called every time the driver is loaded. */ 735 status_t 736 init_driver() 737 { 738 status_t status; 739 load_settings(); 740 create_log_file(); 741 742 TRACE_FUNCALLS("> init_driver()\n"); 743 744 status = get_module(B_DPC_MODULE_NAME, (module_info **)&gDPCModule); 745 if (status < B_OK) 746 goto err_dpc; 747 748 status = get_module(B_TTY_MODULE_NAME, (module_info **)&gTTYModule); 749 if (status < B_OK) 750 goto err_tty; 751 752 status = get_module(B_PCI_MODULE_NAME, (module_info **)&gPCIModule); 753 if (status < B_OK) 754 goto err_pci; 755 756 status = get_module(B_ISA_MODULE_NAME, (module_info **)&gISAModule); 757 if (status < B_OK) 758 goto err_isa; 759 760 status = get_module(B_CONFIG_MANAGER_FOR_DRIVER_MODULE_NAME, 761 (module_info **)&gConfigManagerModule); 762 if (status < B_OK) 763 goto err_cm; 764 765 status = gDPCModule->new_dpc_queue(&gDPCHandle, "pc_serial irq", 766 B_REAL_TIME_PRIORITY); 767 if (status != B_OK) 768 goto err_dpcq; 769 770 for (int32 i = 0; i < DEVICES_COUNT; i++) 771 gSerialDevices[i] = NULL; 772 773 gDeviceNames[0] = NULL; 774 775 gDriverLock = create_sem(1, DRIVER_NAME"_devices_table_lock"); 776 if (gDriverLock < B_OK) { 777 status = gDriverLock; 778 goto err_sem; 779 } 780 781 status = ENOENT; 782 783 check_kernel_debug_port(); 784 785 (void)scan_bus; 786 //scan_bus(B_ISA_BUS); 787 //scan_bus(B_PCI_BUS); 788 scan_isa_hardcoded(); 789 scan_pci_alt(); 790 791 // XXX: ISA cards 792 // XXX: pcmcia 793 794 TRACE_FUNCRET("< init_driver() returns\n"); 795 return B_OK; 796 797 //err_none: 798 delete_sem(gDriverLock); 799 err_sem: 800 gDPCModule->delete_dpc_queue(gDPCHandle); 801 gDPCHandle = NULL; 802 err_dpcq: 803 put_module(B_CONFIG_MANAGER_FOR_DRIVER_MODULE_NAME); 804 err_cm: 805 put_module(B_ISA_MODULE_NAME); 806 err_isa: 807 put_module(B_PCI_MODULE_NAME); 808 err_pci: 809 put_module(B_TTY_MODULE_NAME); 810 err_tty: 811 put_module(B_DPC_MODULE_NAME); 812 err_dpc: 813 TRACE_FUNCRET("< init_driver() returns %s\n", strerror(status)); 814 return status; 815 } 816 817 818 /* uninit_driver - called every time the driver is unloaded */ 819 void 820 uninit_driver() 821 { 822 TRACE_FUNCALLS("> uninit_driver()\n"); 823 824 //gUSBModule->uninstall_notify(DRIVER_NAME); 825 acquire_sem(gDriverLock); 826 827 for (int32 i = 0; i < DEVICES_COUNT; i++) { 828 if (gSerialDevices[i]) { 829 /* 830 if (gSerialDevices[i]->Master() == gSerialDevices[i]) 831 remove_io_interrupt_handler(gSerialDevices[i]->IRQ(), 832 pc_serial_interrupt, gSerialDevices[i]); 833 */ 834 delete gSerialDevices[i]; 835 gSerialDevices[i] = NULL; 836 } 837 } 838 839 for (int32 i = 0; gDeviceNames[i]; i++) 840 free(gDeviceNames[i]); 841 842 delete_sem(gDriverLock); 843 gDPCModule->delete_dpc_queue(gDPCHandle); 844 gDPCHandle = NULL; 845 put_module(B_CONFIG_MANAGER_FOR_DRIVER_MODULE_NAME); 846 put_module(B_ISA_MODULE_NAME); 847 put_module(B_PCI_MODULE_NAME); 848 put_module(B_TTY_MODULE_NAME); 849 put_module(B_DPC_MODULE_NAME); 850 851 TRACE_FUNCRET("< uninit_driver() returns\n"); 852 } 853 854 855 bool 856 pc_serial_service(struct tty *tty, uint32 op, void *buffer, size_t length) 857 { 858 TRACE_FUNCALLS("> pc_serial_service(%p, 0x%08lx, %p, %lu)\n", tty, 859 op, buffer, length); 860 861 862 for (int32 i = 0; i < DEVICES_COUNT; i++) { 863 if (gSerialDevices[i] 864 && gSerialDevices[i]->Service(tty, op, buffer, length)) { 865 TRACE_FUNCRET("< pc_serial_service() returns: true\n"); 866 return true; 867 } 868 } 869 870 TRACE_FUNCRET("< pc_serial_service() returns: false\n"); 871 return false; 872 } 873 874 875 static void 876 pc_serial_dpc(void *arg) 877 { 878 SerialDevice *master = (SerialDevice *)arg; 879 TRACE_FUNCALLS("> pc_serial_dpc(%p)\n", arg); 880 master->InterruptHandler(); 881 } 882 883 884 int32 885 pc_serial_interrupt(void *arg) 886 { 887 SerialDevice *device = (SerialDevice *)arg; 888 TRACE_FUNCALLS("> pc_serial_interrupt(%p)\n", arg); 889 890 if (!device) 891 return B_UNHANDLED_INTERRUPT; 892 893 if (device->IsInterruptPending()) { 894 status_t err; 895 err = gDPCModule->queue_dpc(gDPCHandle, pc_serial_dpc, device); 896 if (err != B_OK) 897 dprintf(DRIVER_NAME ": error queing irq: %s\n", strerror(err)); 898 else { 899 TRACE_FUNCRET("< pc_serial_interrupt() returns: resched\n"); 900 return B_INVOKE_SCHEDULER; 901 } 902 } 903 904 TRACE_FUNCRET("< pc_serial_interrupt() returns: unhandled\n"); 905 return B_UNHANDLED_INTERRUPT; 906 } 907 908 909 /* pc_serial_open - handle open() calls */ 910 status_t 911 pc_serial_open(const char *name, uint32 flags, void **cookie) 912 { 913 TRACE_FUNCALLS("> pc_serial_open(%s, 0x%08x, 0x%08x)\n", name, flags, cookie); 914 acquire_sem(gDriverLock); 915 status_t status = ENODEV; 916 917 *cookie = NULL; 918 int i = strtol(name + strlen(sDeviceBaseName), NULL, 10); 919 if (i >= 0 && i < DEVICES_COUNT && gSerialDevices[i]) { 920 status = gSerialDevices[i]->Open(flags); 921 *cookie = gSerialDevices[i]; 922 } 923 924 release_sem(gDriverLock); 925 TRACE_FUNCRET("< pc_serial_open() returns: 0x%08x\n", status); 926 return status; 927 } 928 929 930 /* pc_serial_read - handle read() calls */ 931 status_t 932 pc_serial_read(void *cookie, off_t position, void *buffer, size_t *numBytes) 933 { 934 TRACE_FUNCALLS("> pc_serial_read(0x%08x, %Ld, 0x%08x, %d)\n", cookie, 935 position, buffer, *numBytes); 936 SerialDevice *device = (SerialDevice *)cookie; 937 return device->Read((char *)buffer, numBytes); 938 } 939 940 941 /* pc_serial_write - handle write() calls */ 942 status_t 943 pc_serial_write(void *cookie, off_t position, const void *buffer, 944 size_t *numBytes) 945 { 946 TRACE_FUNCALLS("> pc_serial_write(0x%08x, %Ld, 0x%08x, %d)\n", cookie, 947 position, buffer, *numBytes); 948 SerialDevice *device = (SerialDevice *)cookie; 949 return device->Write((const char *)buffer, numBytes); 950 } 951 952 953 /* pc_serial_control - handle ioctl calls */ 954 status_t 955 pc_serial_control(void *cookie, uint32 op, void *arg, size_t length) 956 { 957 TRACE_FUNCALLS("> pc_serial_control(0x%08x, 0x%08x, 0x%08x, %d)\n", 958 cookie, op, arg, length); 959 SerialDevice *device = (SerialDevice *)cookie; 960 return device->Control(op, arg, length); 961 } 962 963 964 /* pc_serial_select - handle select start */ 965 status_t 966 pc_serial_select(void *cookie, uint8 event, uint32 ref, selectsync *sync) 967 { 968 TRACE_FUNCALLS("> pc_serial_select(0x%08x, 0x%08x, 0x%08x, %p)\n", 969 cookie, event, ref, sync); 970 SerialDevice *device = (SerialDevice *)cookie; 971 return device->Select(event, ref, sync); 972 } 973 974 975 /* pc_serial_deselect - handle select exit */ 976 status_t 977 pc_serial_deselect(void *cookie, uint8 event, selectsync *sync) 978 { 979 TRACE_FUNCALLS("> pc_serial_deselect(0x%08x, 0x%08x, %p)\n", 980 cookie, event, sync); 981 SerialDevice *device = (SerialDevice *)cookie; 982 return device->DeSelect(event, sync); 983 } 984 985 986 /* pc_serial_close - handle close() calls */ 987 status_t 988 pc_serial_close(void *cookie) 989 { 990 TRACE_FUNCALLS("> pc_serial_close(0x%08x)\n", cookie); 991 SerialDevice *device = (SerialDevice *)cookie; 992 return device->Close(); 993 } 994 995 996 /* pc_serial_free - called after last device is closed, and all i/o complete. */ 997 status_t 998 pc_serial_free(void *cookie) 999 { 1000 TRACE_FUNCALLS("> pc_serial_free(0x%08x)\n", cookie); 1001 SerialDevice *device = (SerialDevice *)cookie; 1002 acquire_sem(gDriverLock); 1003 status_t status = device->Free(); 1004 if (device->IsRemoved()) { 1005 for (int32 i = 0; i < DEVICES_COUNT; i++) { 1006 if (gSerialDevices[i] == device) { 1007 // the device is removed already but as it was open the 1008 // removed hook has not deleted the object 1009 delete device; 1010 gSerialDevices[i] = NULL; 1011 break; 1012 } 1013 } 1014 } 1015 1016 release_sem(gDriverLock); 1017 return status; 1018 } 1019 1020 1021 /* publish_devices - null-terminated array of devices supported by this driver. */ 1022 const char ** 1023 publish_devices() 1024 { 1025 TRACE_FUNCALLS("> publish_devices()\n"); 1026 for (int32 i = 0; gDeviceNames[i]; i++) 1027 free(gDeviceNames[i]); 1028 1029 int j = 0; 1030 acquire_sem(gDriverLock); 1031 for(int i = 0; i < DEVICES_COUNT; i++) { 1032 if (gSerialDevices[i]) { 1033 gDeviceNames[j] = (char *)malloc(strlen(sDeviceBaseName) + 4); 1034 if (gDeviceNames[j]) { 1035 sprintf(gDeviceNames[j], "%s%d", sDeviceBaseName, i); 1036 j++; 1037 } else 1038 TRACE_ALWAYS("publish_devices - no memory to allocate device names\n"); 1039 } 1040 } 1041 1042 gDeviceNames[j] = NULL; 1043 release_sem(gDriverLock); 1044 return (const char **)&gDeviceNames[0]; 1045 } 1046 1047 1048 /* find_device - return poiter to device hooks structure for a given device */ 1049 device_hooks * 1050 find_device(const char *name) 1051 { 1052 static device_hooks deviceHooks = { 1053 pc_serial_open, /* -> open entry point */ 1054 pc_serial_close, /* -> close entry point */ 1055 pc_serial_free, /* -> free cookie */ 1056 pc_serial_control, /* -> control entry point */ 1057 pc_serial_read, /* -> read entry point */ 1058 pc_serial_write, /* -> write entry point */ 1059 pc_serial_select, /* -> select entry point */ 1060 pc_serial_deselect /* -> deselect entry point */ 1061 }; 1062 1063 TRACE_FUNCALLS("> find_device(%s)\n", name); 1064 return &deviceHooks; 1065 } 1066