From 5f5d09f948eaf77cace673812b5824d2c12bd6ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Revol?= Date: Thu, 9 Dec 2010 16:47:49 +0000 Subject: [PATCH] Port pc_serial to the new tty module. Builds but won't work because the tty module lacks essential calls to read and write data :^) Lots of ifdef since I need the R5 code around for now. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39791 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kernel/drivers/ports/pc_serial/Driver.cpp | 42 +- .../kernel/drivers/ports/pc_serial/Driver.h | 19 +- .../drivers/ports/pc_serial/SerialDevice.cpp | 489 +++++++++++++----- .../drivers/ports/pc_serial/SerialDevice.h | 19 +- .../drivers/ports/pc_serial/Tracing.cpp | 26 +- .../kernel/drivers/ports/pc_serial/Tracing.h | 7 +- 6 files changed, 460 insertions(+), 142 deletions(-) diff --git a/src/add-ons/kernel/drivers/ports/pc_serial/Driver.cpp b/src/add-ons/kernel/drivers/ports/pc_serial/Driver.cpp index 7e6693315f..0d1ca8900a 100644 --- a/src/add-ons/kernel/drivers/ports/pc_serial/Driver.cpp +++ b/src/add-ons/kernel/drivers/ports/pc_serial/Driver.cpp @@ -31,7 +31,9 @@ tty_module_info *gTTYModule = NULL; #else tty_module_info_v1_bone *gTTYModule = NULL; #endif +#ifdef __BEOS__ struct ddomain gSerialDomain; +#endif sem_id gDriverLock = -1; bool gHandleISA = false; @@ -297,10 +299,10 @@ scan_bus(bus_type bus) while ((gConfigManagerModule->get_next_device_info(bus, &cookie, &big_info.di, sizeof(big_info)) == B_OK)) { // skip disabled devices - if (dinfo.flags & B_DEVICE_INFO_ENABLED == 0) + if ((dinfo.flags & B_DEVICE_INFO_ENABLED) == 0) continue; // skip non configured devices - if (dinfo.flags & B_DEVICE_INFO_CONFIGURED == 0) + if ((dinfo.flags & B_DEVICE_INFO_CONFIGURED) == 0) continue; // and devices in error if (dinfo.config_status < B_OK) @@ -467,8 +469,12 @@ next_split: TRACE_ALWAYS("inserting device at io 0x%04lx as %s\n", ioport, supported->name); - + +#ifdef __HAIKU__ + device = new(std::nothrow) SerialDevice(supported, ioport, irq, master); +#else device = new SerialDevice(supported, ioport, irq, master); +#endif if (pc_serial_insert_device(device) < B_OK) { TRACE_ALWAYS("can't insert device\n"); continue; @@ -504,7 +510,7 @@ scan_pci_alt() // probe PCI devices for (ix = 0; (*gPCIModule->get_nth_pci_info)(ix, &info) == B_OK; ix++) { // sanity check - if (info.header_type & PCI_header_type_mask != PCI_header_type_generic) + if ((info.header_type & PCI_header_type_mask) != PCI_header_type_generic) continue; /* TRACE_ALWAYS("probing PCI device %2d [%x|%x|%x] %04x:%04x\n", @@ -614,7 +620,11 @@ next_split_alt: /**/ +#ifdef __HAIKU__ + device = new(std::nothrow) SerialDevice(supported, ioport, irq, master); +#else device = new SerialDevice(supported, ioport, irq, master); +#endif if (pc_serial_insert_device(device) < B_OK) { TRACE_ALWAYS("can't insert device\n"); continue; @@ -732,9 +742,10 @@ init_driver() status = ENOENT; +#ifdef __BEOS__ memset(&gSerialDomain, 0, sizeof(gSerialDomain)); ddbackground(&gSerialDomain); - +#endif scan_bus(B_ISA_BUS); //scan_bus(B_PCI_BUS); @@ -797,6 +808,26 @@ uninit_driver() } +#ifdef __HAIKU__ +bool +pc_serial_service(struct tty *tty, uint32 op, void *buffer, size_t length) +{ + TRACE_FUNCALLS("> pc_serial_service(%p, 0x%08lx, %p, %lu)\n", tty, + op, buffer, length); + + + for (int32 i = 0; i < DEVICES_COUNT; i++) { + if (gSerialDevices[i] + && gSerialDevices[i]->Service(tty, op, buffer, length)) { + TRACE_FUNCRET("< pc_serial_service() returns: true\n"); + return true; + } + } + + TRACE_FUNCRET("< pc_serial_service() returns: false\n"); + return false; +} +#else /* __HAIKU__ */ bool pc_serial_service(struct tty *ptty, struct ddrover *ddr, uint flags) { @@ -812,6 +843,7 @@ pc_serial_service(struct tty *ptty, struct ddrover *ddr, uint flags) TRACE_FUNCRET("< pc_serial_service() returns: false\n"); return false; } +#endif /* __HAIKU__ */ int32 diff --git a/src/add-ons/kernel/drivers/ports/pc_serial/Driver.h b/src/add-ons/kernel/drivers/ports/pc_serial/Driver.h index 5a4bc96c9f..abadbca1cd 100644 --- a/src/add-ons/kernel/drivers/ports/pc_serial/Driver.h +++ b/src/add-ons/kernel/drivers/ports/pc_serial/Driver.h @@ -22,14 +22,19 @@ #ifdef __HAIKU__ #include +#include #else #include "BeOSCompatibility.h" -#endif #include "kernel_cpp.h" +#endif #include "Tracing.h" extern "C" { +#ifdef __HAIKU__ +#include +#else #include +#endif } @@ -135,7 +140,7 @@ typedef struct pc_serial_line_coding_s { -#ifndef __HAIKU__ +#ifdef __BEOS__ // All this mess is due to BeOS R5 and BONE having // an incompatible module API for the same version @@ -184,8 +189,7 @@ struct tty_module_info_v1_bone { void (*ddrdone)(struct ddrover *); void (*ddacquire)(struct ddrover *, struct ddomain *); }; -#endif - +#endif /* __BEOS__ */ extern config_manager_for_driver_module_info *gConfigManagerModule; @@ -199,10 +203,16 @@ extern tty_module_info_v1_bone *gTTYModule; extern struct ddomain gSerialDomain; extern "C" { + status_t init_hardware(); void uninit_driver(); +#ifdef __BEOS__ bool pc_serial_service(struct tty *ptty, struct ddrover *ddr, uint flags); +#else +bool pc_serial_service(struct tty *tty, uint32 op, void *buffer, + size_t length); +#endif /* __BEOS__ */ int32 pc_serial_interrupt(void *arg); status_t pc_serial_open(const char *name, uint32 flags, void **cookie); @@ -216,6 +226,7 @@ status_t pc_serial_free(void *cookie); const char **publish_devices(); device_hooks *find_device(const char *name); + } diff --git a/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp b/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp index 0412824cfd..c90a73bacc 100644 --- a/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp +++ b/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp @@ -38,12 +38,19 @@ SerialDevice::SerialDevice(const struct serial_support_descriptor *device, fDoneWrite(-1), fControlOut(0), fInputStopped(false), +#ifdef __HAIKU__ + fMasterTTY(NULL), + fSlaveTTY(NULL), + fTTYCookie(NULL), +#endif /* __HAIKU__ */ fDeviceThread(-1), fStopDeviceThread(false) { +#ifdef __BEOS__ memset(&fTTYFile, 0, sizeof(ttyfile)); memset(&fTTY, 0, sizeof(tty)); memset(&fRover, 0, sizeof(ddrover)); +#endif /* __BEOS__ */ } @@ -87,21 +94,30 @@ SerialDevice::Init() } +#ifdef __BEOS__ void SerialDevice::SetModes() { struct termios tios; memcpy(&tios, &fTTY.t, sizeof(struct termios)); - //TRACE_FUNCRES(trace_termios, &tios); + SetModes(&tios); +} +#endif /* __BEOS__ */ + + +void +SerialDevice::SetModes(struct termios *tios) +{ + //TRACE_FUNCRES(trace_termios, tios); spin(10000); - uint32 baudIndex = tios.c_cflag & CBAUD; + uint32 baudIndex = tios->c_cflag & CBAUD; if (baudIndex > BLAST) baudIndex = BLAST; uint8 lcr = 0; uint16 divisor = SupportDescriptor()->bauds[baudIndex]; - switch (tios.c_cflag & CSIZE) { + switch (tios->c_cflag & CSIZE) { #if CS5 != CS7 // in case someday... case CS5: @@ -120,11 +136,11 @@ SerialDevice::SetModes() break; } - if (tios.c_cflag & CSTOPB) + if (tios->c_cflag & CSTOPB) lcr |= LCR_2STOP; - if (tios.c_cflag & PARENB) + if (tios->c_cflag & PARENB) lcr |= LCR_P_EN; - if (tios.c_cflag & PARODD == 0) + if ((tios->c_cflag & PARODD) == 0) lcr |= LCR_P_EVEN; if (baudIndex == B0) { @@ -179,16 +195,16 @@ SerialDevice::SetModes() usb_serial_line_coding lineCoding; lineCoding.speed = baudRates[baudIndex]; - lineCoding.stopbits = (tios.c_cflag & CSTOPB) ? LC_STOP_BIT_2 : LC_STOP_BIT_1; + lineCoding.stopbits = (tios->c_cflag & CSTOPB) ? LC_STOP_BIT_2 : LC_STOP_BIT_1; - if (tios.c_cflag & PARENB) { + if (tios->c_cflag & PARENB) { lineCoding.parity = LC_PARITY_EVEN; - if (tios.c_cflag & PARODD) + if (tios->c_cflag & PARODD) lineCoding.parity = LC_PARITY_ODD; } else lineCoding.parity = LC_PARITY_NONE; - lineCoding.databits = (tios.c_cflag & CS8) ? 8 : 7; + lineCoding.databits = (tios->c_cflag & CS8) ? 8 : 7; if (lineCoding.speed == 0) { newControl &= 0xfffffffe; @@ -216,6 +232,127 @@ SerialDevice::SetModes() } +#ifdef __HAIKU__ + + +bool +SerialDevice::Service(struct tty *tty, uint32 op, void *buffer, size_t length) +{ + uint8 msr; + status_t err; + + if (tty != fMasterTTY) + return false; + + TRACE("%s(,0x%08lx,,%d)\n", __FUNCTION__, op, length); + + switch (op) { + case TTYENABLE: + { + bool enable = *(bool *)buffer; + TRACE("TTYENABLE: %sable\n", enable ? "en" : "dis"); + + if (enable) { + //XXX:must call SetModes(); + err = install_io_interrupt_handler(IRQ(), pc_serial_interrupt, this, 0); + TRACE("installing irq handler for %d: %s\n", IRQ(), strerror(err)); + } else { + // remove the handler + remove_io_interrupt_handler(IRQ(), pc_serial_interrupt, this); + // disable IRQ + WriteReg8(IER, 0); + WriteReg8(MCR, 0); + } + + msr = ReadReg8(MSR); + + SignalControlLineState(TTYHWDCD, msr & MSR_DCD); + SignalControlLineState(TTYHWCTS, msr & MSR_CTS); + + if (enable) { + // + WriteReg8(MCR, MCR_DTR | MCR_RTS | MCR_IRQ_EN /*| MCR_LOOP*//*XXXXXXX*/); + // enable irqs + WriteReg8(IER, IER_RLS | IER_MS | IER_RDA); + //WriteReg8(IER, IER_RDA); + } + + return true; + } + + case TTYISTOP: + fInputStopped = *(bool *)buffer; + TRACE("TTYISTOP: %sstopped\n", fInputStopped ? "" : "not "); + + if (fInputStopped) + MaskReg8(MCR, MCR_RTS); + else + OrReg8(MCR, MCR_RTS); + + //gTTYModule->ttyhwsignal(ptty, ddr, TTYHWCTS, false); + //SignalControlLineState(TTYHWCTS, !fInputStopped); + //msr = ReadReg8(MSR); + //SignalControlLineState(TTYHWCTS, msr & MSR_CTS); + return true; + + case TTYGETSIGNALS: + TRACE("TTYGETSIGNALS\n"); + msr = ReadReg8(MSR); + SignalControlLineState(TTYHWDCD, msr & MSR_DCD); + SignalControlLineState(TTYHWCTS, msr & MSR_CTS); + SignalControlLineState(TTYHWDSR, msr & MSR_DSR); + SignalControlLineState(TTYHWRI, msr & MSR_RI); + return true; + + case TTYSETMODES: + TRACE("TTYSETMODES\n"); + SetModes((struct termios *)buffer); +//WriteReg8(IER, IER_RLS | IER_MS | IER_RDA); + return true; + + case TTYSETDTR: + case TTYSETRTS: + { + bool set = *(bool *)buffer; + uint8 bit = TTYSETDTR ? MCR_DTR : MCR_RTS; + if (set) + OrReg8(MCR, bit); + else + MaskReg8(MCR, bit); + + return true; + } + + case TTYOSTART: + TRACE("TTYOSTART\n"); + // enable irqs + WriteReg8(IER, IER_RLS | IER_MS | IER_RDA | IER_THRE); + return true; + case TTYOSYNC: + TRACE("TTYOSYNC\n"); + return (ReadReg8(LSR) & (LSR_THRE | LSR_TSRE)) == (LSR_THRE | LSR_TSRE); + return true; + case TTYSETBREAK: + { + bool set = *(bool *)buffer; + if (set) + OrReg8(MCR, LCR_BREAK); + else + MaskReg8(MCR, LCR_BREAK); + + return true; + } + default: + return false; + } + + return false; +} + + +#else /* __HAIKU__ */ + + bool SerialDevice::Service(struct tty *ptty, struct ddrover *ddr, uint flags) { @@ -227,113 +364,115 @@ SerialDevice::Service(struct tty *ptty, struct ddrover *ddr, uint flags) TRACE("%s(,,0x%08lx)\n", __FUNCTION__, flags); - if (flags <= TTYGETSIGNALS) { - switch (flags) { - case TTYENABLE: - TRACE("TTYENABLE\n"); - - SetModes(); - err = install_io_interrupt_handler(IRQ(), pc_serial_interrupt, this, 0); - TRACE("installing irq handler for %d: %s\n", IRQ(), strerror(err)); - msr = ReadReg8(MSR); - gTTYModule->ttyhwsignal(ptty, ddr, TTYHWDCD, msr & MSR_DCD); - gTTYModule->ttyhwsignal(ptty, ddr, TTYHWCTS, msr & MSR_CTS); - // - WriteReg8(MCR, MCR_DTR | MCR_RTS | MCR_IRQ_EN /*| MCR_LOOP*//*XXXXXXX*/); - // enable irqs - WriteReg8(IER, IER_RLS | IER_MS | IER_RDA); - //WriteReg8(IER, IER_RDA); - break; + switch (flags) { + case TTYENABLE: + TRACE("TTYENABLE\n"); - case TTYDISABLE: - TRACE("TTYDISABLE\n"); - // remove the handler - remove_io_interrupt_handler(IRQ(), pc_serial_interrupt, this); - // disable IRQ - WriteReg8(IER, 0); - WriteReg8(MCR, 0); - msr = ReadReg8(MSR); - gTTYModule->ttyhwsignal(ptty, ddr, TTYHWDCD, msr & MSR_DCD); - break; + SetModes(); + err = install_io_interrupt_handler(IRQ(), pc_serial_interrupt, this, 0); + TRACE("installing irq handler for %d: %s\n", IRQ(), strerror(err)); + msr = ReadReg8(MSR); + gTTYModule->ttyhwsignal(ptty, ddr, TTYHWDCD, msr & MSR_DCD); + gTTYModule->ttyhwsignal(ptty, ddr, TTYHWCTS, msr & MSR_CTS); + // + WriteReg8(MCR, MCR_DTR | MCR_RTS | MCR_IRQ_EN /*| MCR_LOOP*//*XXXXXXX*/); + // enable irqs + WriteReg8(IER, IER_RLS | IER_MS | IER_RDA); + //WriteReg8(IER, IER_RDA); + break; - case TTYISTOP: - TRACE("TTYISTOP\n"); - MaskReg8(MCR, MCR_RTS); - //fInputStopped = true; - //gTTYModule->ttyhwsignal(ptty, ddr, TTYHWCTS, false); - break; + case TTYDISABLE: + TRACE("TTYDISABLE\n"); + // remove the handler + remove_io_interrupt_handler(IRQ(), pc_serial_interrupt, this); + // disable IRQ + WriteReg8(IER, 0); + WriteReg8(MCR, 0); + msr = ReadReg8(MSR); + gTTYModule->ttyhwsignal(ptty, ddr, TTYHWDCD, msr & MSR_DCD); + break; - case TTYIRESUME: - TRACE("TTYIRESUME\n"); - OrReg8(MCR, MCR_RTS); - //gTTYModule->ttyhwsignal(ptty, ddr, TTYHWCTS, true); - //fInputStopped = false; - break; + case TTYISTOP: + TRACE("TTYISTOP\n"); + MaskReg8(MCR, MCR_RTS); + //fInputStopped = true; + //gTTYModule->ttyhwsignal(ptty, ddr, TTYHWCTS, false); + break; - case TTYGETSIGNALS: - TRACE("TTYGETSIGNALS\n"); - msr = ReadReg8(MSR); - gTTYModule->ttyhwsignal(ptty, ddr, TTYHWDCD, msr & MSR_DCD); - gTTYModule->ttyhwsignal(ptty, ddr, TTYHWCTS, msr & MSR_CTS); - gTTYModule->ttyhwsignal(ptty, ddr, TTYHWDSR, msr & MSR_DSR); - gTTYModule->ttyhwsignal(ptty, ddr, TTYHWRI, msr & MSR_RI); - break; + case TTYIRESUME: + TRACE("TTYIRESUME\n"); + OrReg8(MCR, MCR_RTS); + //gTTYModule->ttyhwsignal(ptty, ddr, TTYHWCTS, true); + //fInputStopped = false; + break; - case TTYSETMODES: - TRACE("TTYSETMODES\n"); - SetModes(); + case TTYGETSIGNALS: + TRACE("TTYGETSIGNALS\n"); + msr = ReadReg8(MSR); + gTTYModule->ttyhwsignal(ptty, ddr, TTYHWDCD, msr & MSR_DCD); + gTTYModule->ttyhwsignal(ptty, ddr, TTYHWCTS, msr & MSR_CTS); + gTTYModule->ttyhwsignal(ptty, ddr, TTYHWDSR, msr & MSR_DSR); + gTTYModule->ttyhwsignal(ptty, ddr, TTYHWRI, msr & MSR_RI); + break; + + case TTYSETMODES: + TRACE("TTYSETMODES\n"); + SetModes(); //WriteReg8(IER, IER_RLS | IER_MS | IER_RDA); - break; + break; - case TTYOSTART: - TRACE("TTYOSTART\n"); - // enable irqs - WriteReg8(IER, IER_RLS | IER_MS | IER_RDA | IER_THRE); - break; - case TTYOSYNC: - TRACE("TTYOSYNC\n"); - return (ReadReg8(LSR) & (LSR_THRE | LSR_TSRE)) == (LSR_THRE | LSR_TSRE); - break; - case TTYSETBREAK: - TRACE("TTYSETBREAK\n"); - OrReg8(LCR, LCR_BREAK); - break; - case TTYCLRBREAK: - TRACE("TTYCLRBREAK\n"); - MaskReg8(LCR, LCR_BREAK); - break; - case TTYSETDTR: - TRACE("TTYSETDTR\n"); - OrReg8(MCR, MCR_DTR); - break; - case TTYCLRDTR: - TRACE("TTYCLRDTR\n"); - MaskReg8(MCR, MCR_DTR); - break; - } - - return true; + case TTYOSTART: + TRACE("TTYOSTART\n"); + // enable irqs + WriteReg8(IER, IER_RLS | IER_MS | IER_RDA | IER_THRE); + break; + case TTYOSYNC: + TRACE("TTYOSYNC\n"); + return (ReadReg8(LSR) & (LSR_THRE | LSR_TSRE)) == (LSR_THRE | LSR_TSRE); + break; + case TTYSETBREAK: + TRACE("TTYSETBREAK\n"); + OrReg8(LCR, LCR_BREAK); + break; + case TTYCLRBREAK: + TRACE("TTYCLRBREAK\n"); + MaskReg8(LCR, LCR_BREAK); + break; + case TTYSETDTR: + TRACE("TTYSETDTR\n"); + OrReg8(MCR, MCR_DTR); + break; + case TTYCLRDTR: + TRACE("TTYCLRDTR\n"); + MaskReg8(MCR, MCR_DTR); + break; + default: + return false; } return false; } +#endif /* __HAIKU__ */ int32 SerialDevice::InterruptHandler() { int32 ret = B_UNHANDLED_INTERRUPT; +#ifdef __HAIKU__ + //XXX: what should we do here ? (certainly not use a mutex !) +#else /* __HAIKU__ */ gTTYModule->ddrstart(&fRover); gTTYModule->ttyilock(&fTTY, &fRover, true); +#endif /* __HAIKU__ */ uint8 iir, lsr, msr; - int count; while (((iir = ReadReg8(IIR)) & IIR_PENDING) == 0) { // 0 means yes int fifoavail = 1; //DEBUG -// for (count = 0; ReadReg8(LSR) & LSR_DR; count++) +// for (int count = 0; ReadReg8(LSR) & LSR_DR; count++) // gTTYModule->ttyin(&fTTY, &fRover, ReadReg8(RBR)); switch (iir & (IIR_IMASK | IIR_TO)) { @@ -341,12 +480,17 @@ SerialDevice::InterruptHandler() TRACE(("IIR_THRE\n")); // check how much fifo we can use //XXX: move to Init() ? - if (iir & IIR_FMASK == IIR_FMASK) + if ((iir & IIR_FMASK) == IIR_FMASK) fifoavail = 16; if (iir & IIR_F64EN) fifoavail = 64; for (int i = 0; i < fifoavail; i++) { - int chr = gTTYModule->ttyout(&fTTY, &fRover); + int chr; +#ifdef __HAIKU__ + chr = 'H';//XXX: what should we do here ? (certainly not call tty_read() !) +#else /* __HAIKU__ */ + chr = gTTYModule->ttyout(&fTTY, &fRover); +#endif /* __HAIKU__ */ if (chr < 0) { //WriteReg8(THB, (uint8)chr); break; @@ -361,7 +505,11 @@ SerialDevice::InterruptHandler() TRACE(("IIR_TO/RDA\n")); // while data is ready... get it while (ReadReg8(LSR) & LSR_DR) +#ifdef __HAIKU__ + ReadReg8(RBR);//XXX: what should we do here ? (certainly not call tty_write() !) +#else /* __HAIKU__ */ gTTYModule->ttyin(&fTTY, &fRover, ReadReg8(RBR)); +#endif /* __HAIKU__ */ break; case IIR_RLS: TRACE(("IIR_RLS\n")); @@ -374,13 +522,13 @@ SerialDevice::InterruptHandler() // modem signals changed msr = ReadReg8(MSR); if (msr & MSR_DDCD) - gTTYModule->ttyhwsignal(&fTTY, &fRover, TTYHWDCD, msr & MSR_DCD); + SignalControlLineState(TTYHWDCD, msr & MSR_DCD); if (msr & MSR_DCTS) - gTTYModule->ttyhwsignal(&fTTY, &fRover, TTYHWCTS, msr & MSR_CTS); + SignalControlLineState(TTYHWCTS, msr & MSR_CTS); if (msr & MSR_DDSR) - gTTYModule->ttyhwsignal(&fTTY, &fRover, TTYHWDSR, msr & MSR_DSR); + SignalControlLineState(TTYHWDSR, msr & MSR_DSR); if (msr & MSR_TERI) - gTTYModule->ttyhwsignal(&fTTY, &fRover, TTYHWRI, msr & MSR_RI); + SignalControlLineState(TTYHWRI, msr & MSR_RI); break; default: TRACE(("IIR_?\n")); @@ -392,8 +540,12 @@ SerialDevice::InterruptHandler() } +#ifdef __HAIKU__ + //XXX: what should we do here ? (certainly not use a mutex !) +#else /* __HAIKU__ */ gTTYModule->ttyilock(&fTTY, &fRover, false); gTTYModule->ddrdone(&fRover); +#endif /* __HAIKU__ */ TRACE_FUNCRET("< IRQ:%d\n", ret); return ret; } @@ -402,15 +554,45 @@ SerialDevice::InterruptHandler() status_t SerialDevice::Open(uint32 flags) { + status_t status = B_OK; + if (fDeviceOpen) return B_BUSY; if (fDeviceRemoved) return B_DEV_NOT_READY; +#ifdef __HAIKU__ + fMasterTTY = gTTYModule->tty_create(pc_serial_service, true); + if (fMasterTTY == NULL) { + TRACE_ALWAYS("open: failed to init master tty\n"); + return B_NO_MEMORY; + } + + fSlaveTTY = gTTYModule->tty_create(NULL, false); + if (fSlaveTTY == NULL) { + TRACE_ALWAYS("open: failed to init slave tty\n"); + gTTYModule->tty_destroy(fMasterTTY); + return B_NO_MEMORY; + } + + fTTYCookie = gTTYModule->tty_create_cookie(fMasterTTY, fSlaveTTY, flags); + if (fTTYCookie == NULL) { + TRACE_ALWAYS("open: failed to init tty cookie\n"); + gTTYModule->tty_destroy(fMasterTTY); + gTTYModule->tty_destroy(fSlaveTTY); + return B_NO_MEMORY; + } + + ResetDevice(); + +#else /* __HAIKU__ */ + gTTYModule->ttyinit(&fTTY, false); fTTYFile.tty = &fTTY; fTTYFile.flags = flags; + + ResetDevice(); struct ddrover *ddr = gTTYModule->ddrstart(NULL); @@ -418,9 +600,11 @@ SerialDevice::Open(uint32 flags) return B_NO_MEMORY; gTTYModule->ddacquire(ddr, &gSerialDomain); - status_t status = gTTYModule->ttyopen(&fTTYFile, ddr, pc_serial_service); + status = gTTYModule->ttyopen(&fTTYFile, ddr, pc_serial_service); gTTYModule->ddrdone(ddr); +#endif /* __HAIKU__ */ + if (status < B_OK) { TRACE_ALWAYS("open: failed to open tty\n"); return status; @@ -460,30 +644,33 @@ SerialDevice::Read(char *buffer, size_t *numBytes) } status_t status; -#if 0 - status_t status = mutex_lock(&fReadLock); + +#ifdef __HAIKU__ + + status = mutex_lock(&fReadLock); if (status != B_OK) { TRACE_ALWAYS("read: failed to get read lock\n"); *numBytes = 0; return status; } -#endif + + status = gTTYModule->tty_read(fTTYCookie, buffer, numBytes); + + mutex_unlock(&fReadLock); + +#else /* __HAIKU__ */ struct ddrover *ddr = gTTYModule->ddrstart(NULL); if (!ddr) { *numBytes = 0; -#if 0 - mutex_unlock(&fReadLock); -#endif return B_NO_MEMORY; } status = gTTYModule->ttyread(&fTTYFile, ddr, buffer, numBytes); gTTYModule->ddrdone(ddr); -#if 0 - mutex_unlock(&fReadLock); -#endif +#endif /* __HAIKU__ */ + return status; } @@ -491,10 +678,25 @@ SerialDevice::Read(char *buffer, size_t *numBytes) status_t SerialDevice::Write(const char *buffer, size_t *numBytes) { - size_t bytesLeft = *numBytes; + //size_t bytesLeft = *numBytes; //*numBytes = 0; status_t status = EINVAL; + +#ifdef __HAIKU__ + + status = mutex_lock(&fWriteLock); + if (status != B_OK) { + TRACE_ALWAYS("write: failed to get write lock\n"); + return status; + } + + //XXX: WTF tty_write() is not for write() hook ? + //status = gTTYModule->tty_write(fTTYCookie, buffer, numBytes); + mutex_unlock(&fWriteLock); + +#else /* __HAIKU__ */ + struct ddrover *ddr = gTTYModule->ddrstart(NULL); if (!ddr) { *numBytes = 0; @@ -504,6 +706,8 @@ SerialDevice::Write(const char *buffer, size_t *numBytes) status = gTTYModule->ttywrite(&fTTYFile, ddr, buffer, numBytes); gTTYModule->ddrdone(ddr); +#endif /* __HAIKU__ */ + #if 0 status_t status = mutex_lock(&fWriteLock); if (status != B_OK) { @@ -560,15 +764,26 @@ SerialDevice::Write(const char *buffer, size_t *numBytes) status_t SerialDevice::Control(uint32 op, void *arg, size_t length) { + status_t status = B_OK; + if (fDeviceRemoved) return B_DEV_NOT_READY; +#ifdef __HAIKU__ + + status = gTTYModule->tty_control(fTTYCookie, op, arg, length); + +#else /* __HAIKU__ */ + struct ddrover *ddr = gTTYModule->ddrstart(NULL); if (!ddr) return B_NO_MEMORY; - status_t status = gTTYModule->ttycontrol(&fTTYFile, ddr, op, arg, length); + status = gTTYModule->ttycontrol(&fTTYFile, ddr, op, arg, length); gTTYModule->ddrdone(ddr); + +#endif /* __HAIKU__ */ + return status; } @@ -579,13 +794,22 @@ SerialDevice::Select(uint8 event, uint32 ref, selectsync *sync) if (fDeviceRemoved) return B_DEV_NOT_READY; +#ifdef __HAIKU__ + + return gTTYModule->tty_select(fTTYCookie, event, ref, sync); + +#else /* __HAIKU__ */ + struct ddrover *ddr = gTTYModule->ddrstart(NULL); if (!ddr) return B_NO_MEMORY; status_t status = gTTYModule->ttyselect(&fTTYFile, ddr, event, ref, sync); gTTYModule->ddrdone(ddr); + return status; + +#endif /* __HAIKU__ */ } @@ -595,19 +819,30 @@ SerialDevice::DeSelect(uint8 event, selectsync *sync) if (fDeviceRemoved) return B_DEV_NOT_READY; +#ifdef __HAIKU__ + + return gTTYModule->tty_deselect(fTTYCookie, event, sync); + +#else /* __HAIKU__ */ + struct ddrover *ddr = gTTYModule->ddrstart(NULL); if (!ddr) return B_NO_MEMORY; status_t status = gTTYModule->ttydeselect(&fTTYFile, ddr, event, sync); gTTYModule->ddrdone(ddr); + return status; + +#endif /* __HAIKU__ */ } status_t SerialDevice::Close() { + status_t status = B_OK; + OnClose(); if (!fDeviceRemoved) { @@ -618,13 +853,18 @@ SerialDevice::Close() #endif } +#ifdef __HAIKU__ + gTTYModule->tty_destroy_cookie(fTTYCookie); +#else /* __HAIKU__ */ struct ddrover *ddr = gTTYModule->ddrstart(NULL); if (!ddr) return B_NO_MEMORY; - status_t status = gTTYModule->ttyclose(&fTTYFile, ddr); + status = gTTYModule->ttyclose(&fTTYFile, ddr); gTTYModule->ddrdone(ddr); +#endif /* __HAIKU__ */ + fDeviceOpen = false; return status; } @@ -633,12 +873,18 @@ SerialDevice::Close() status_t SerialDevice::Free() { + status_t status = B_OK; +#ifdef __HAIKU__ + gTTYModule->tty_destroy(fMasterTTY); + gTTYModule->tty_destroy(fSlaveTTY); +#else /* __HAIKU__ */ struct ddrover *ddr = gTTYModule->ddrstart(NULL); if (!ddr) return B_NO_MEMORY; - status_t status = gTTYModule->ttyfree(&fTTYFile, ddr); + status = gTTYModule->ttyfree(&fTTYFile, ddr); gTTYModule->ddrdone(ddr); +#endif /* __HAIKU__ */ return status; } @@ -661,7 +907,7 @@ SerialDevice::Removed() gUSBModule->cancel_queued_transfers(fControlPipe); #endif - int32 result = B_OK; + //int32 result = B_OK; //wait_for_thread(fDeviceThread, &result); fDeviceThread = -1; @@ -696,9 +942,14 @@ SerialDevice::SetLineCoding(usb_serial_line_coding *coding) #endif status_t -SerialDevice::SetControlLineState(uint16 state) +SerialDevice::SignalControlLineState(int line, bool enable) { - // default implementation - does nothing +#ifdef __HAIKU__ + gTTYModule->tty_hardware_signal(fTTYCookie, line, enable); +#else + // XXX: only works for interrupt handler, Service func must pass the ddrover + gTTYModule->ttyhwsignal(&fTTY, &fRover, line, enable); +#endif return B_OK; } @@ -727,8 +978,8 @@ SerialDevice::OnClose() int32 SerialDevice::DeviceThread(void *data) { - SerialDevice *device = (SerialDevice *)data; #if 0 + SerialDevice *device = (SerialDevice *)data; while (!device->fStopDeviceThread) { status_t status = gUSBModule->queue_bulk(device->fReadPipe, @@ -868,7 +1119,7 @@ SerialDevice::MakeDevice(usb_device device, uint16 vendorID, if (!description) break; - return new ProlificDevice(device, vendorID, productID, description); + return new(std::nothrow) ProlificDevice(device, vendorID, productID, description); } case VENDOR_FTDI: @@ -881,7 +1132,7 @@ SerialDevice::MakeDevice(usb_device device, uint16 vendorID, if (!description) break; - return new FTDIDevice(device, vendorID, productID, description); + return new(std::nothrow) FTDIDevice(device, vendorID, productID, description); } case VENDOR_PALM: @@ -895,11 +1146,11 @@ SerialDevice::MakeDevice(usb_device device, uint16 vendorID, if (!description) break; - return new KLSIDevice(device, vendorID, productID, description); + return new(std::nothrow) KLSIDevice(device, vendorID, productID, description); } } - return new ACMDevice(device, vendorID, productID, "CDC ACM compatible device"); + return new(std::nothrow) ACMDevice(device, vendorID, productID, "CDC ACM compatible device"); } #endif diff --git a/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.h b/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.h index f8d216d5e1..dbb62748be 100644 --- a/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.h +++ b/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.h @@ -43,9 +43,17 @@ static SerialDevice * MakeDevice(struct serial_config_descriptor char * WriteBuffer() { return fWriteBuffer; }; size_t WriteBufferSize() { return fWriteBufferSize; }; +#ifdef __BEOS__ void SetModes(); +#endif + void SetModes(struct termios *tios); +#ifdef __HAIKU__ + bool Service(struct tty *tty, uint32 op, + void *buffer, size_t length); +#else bool Service(struct tty *ptty, struct ddrover *ddr, uint flags); +#endif int32 InterruptHandler(); @@ -68,10 +76,11 @@ virtual status_t AddDevice(const struct serial_config_descriptor *device); virtual status_t ResetDevice(); //virtual status_t SetLineCoding(usb_serial_line_coding *coding); -virtual status_t SetControlLineState(uint16 state); +//virtual status_t SetControlLineState(uint16 state); +virtual status_t SignalControlLineState(int line, bool enable); virtual void OnRead(char **buffer, size_t *numBytes); -virtual void OnWrite(const char *buffer, size_t *numBytes, +virtual void OnWrite(const char *buffer, size_t *numBytes, size_t *packetBytes); virtual void OnClose(); @@ -138,9 +147,15 @@ static void InterruptCallbackFunction(void *cookie, uint16 fControlOut; bool fInputStopped; +#ifdef __HAIKU__ + struct tty * fMasterTTY; + struct tty * fSlaveTTY; + struct tty_cookie * fTTYCookie; +#else struct ttyfile fTTYFile; struct tty fTTY; struct ddrover fRover; +#endif /* device thread management */ thread_id fDeviceThread; diff --git a/src/add-ons/kernel/drivers/ports/pc_serial/Tracing.cpp b/src/add-ons/kernel/drivers/ports/pc_serial/Tracing.cpp index c2c47f7696..1cf8292134 100644 --- a/src/add-ons/kernel/drivers/ports/pc_serial/Tracing.cpp +++ b/src/add-ons/kernel/drivers/ports/pc_serial/Tracing.cpp @@ -69,7 +69,7 @@ create_log_file() void -usb_serial_trace(bool force, char *format, ...) +usb_serial_trace(bool force, const char *format, ...) { if (!gLogEnabled && !force) return; @@ -98,15 +98,6 @@ usb_serial_trace(bool force, char *format, ...) } -void -trace_ddomain(struct ddomain *dd) -{ - TRACE("struct ddomain:\n" - "\tddrover: 0x%08x\n" - "\tbg: %d, locked: %d\n", dd->r, dd->bg, dd->locked); -} - - void trace_termios(struct termios *tios) { @@ -128,6 +119,18 @@ trace_termios(struct termios *tios) } +#ifdef __BEOS__ + + +void +trace_ddomain(struct ddomain *dd) +{ + TRACE("struct ddomain:\n" + "\tddrover: 0x%08x\n" + "\tbg: %d, locked: %d\n", dd->r, dd->bg, dd->locked); +} + + void trace_str(struct str *str) { @@ -182,3 +185,6 @@ trace_tty(struct tty *tty) TRACE("\tservice: 0x%08x\n", tty->service); } + + +#endif /* __BEOS__ */ \ No newline at end of file diff --git a/src/add-ons/kernel/drivers/ports/pc_serial/Tracing.h b/src/add-ons/kernel/drivers/ports/pc_serial/Tracing.h index 77bf7941aa..bf8c987125 100644 --- a/src/add-ons/kernel/drivers/ports/pc_serial/Tracing.h +++ b/src/add-ons/kernel/drivers/ports/pc_serial/Tracing.h @@ -10,7 +10,7 @@ void load_settings(); void create_log_file(); -void usb_serial_trace(bool force, char *format, ...); +void usb_serial_trace(bool force, const char *format, ...); #define TRACE_ALWAYS(x...) usb_serial_trace(true, x); #define TRACE(x...) usb_serial_trace(false, x); @@ -30,10 +30,13 @@ extern bool gLogFunctionResults; if (gLogFunctionResults) \ func(param); -void trace_ddomain(struct ddomain *dd); void trace_termios(struct termios *tios); + +#ifdef __BEOS__ +void trace_ddomain(struct ddomain *dd); void trace_str(struct str *str); void trace_winsize(struct winsize *ws); void trace_tty(struct tty *tty); +#endif /* __BEOS__ */ #endif //_PC_SERIAL_TRACING_H_