Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/usb/serial/uplcom.c
Show First 20 Lines • Show All 126 Lines • ▼ Show 20 Lines | |||||
#ifndef UPLCOM_INTR_INTERVAL | #ifndef UPLCOM_INTR_INTERVAL | ||||
#define UPLCOM_INTR_INTERVAL 0 /* default */ | #define UPLCOM_INTR_INTERVAL 0 /* default */ | ||||
#endif | #endif | ||||
#define UPLCOM_BULK_BUF_SIZE 1024 /* bytes */ | #define UPLCOM_BULK_BUF_SIZE 1024 /* bytes */ | ||||
#define UPLCOM_SET_REQUEST 0x01 | #define UPLCOM_SET_REQUEST 0x01 | ||||
#define UPLCOM_SET_REQUEST_PL2303HXN 0x80 | |||||
#define UPLCOM_SET_CRTSCTS 0x41 | #define UPLCOM_SET_CRTSCTS 0x41 | ||||
#define UPLCOM_SET_CRTSCTS_PL2303X 0x61 | #define UPLCOM_SET_CRTSCTS_PL2303X 0x61 | ||||
#define UPLCOM_SET_CRTSCTS_PL2303HXN 0xFA | |||||
#define UPLCOM_CLEAR_CRTSCTS_PL2303HXN 0xFF | |||||
#define UPLCOM_CRTSCTS_REG_PL2303HXN 0x0A | |||||
#define UPLCOM_STATUS_REG_PL2303HX 0x8080 | |||||
#define RSAQ_STATUS_CTS 0x80 | #define RSAQ_STATUS_CTS 0x80 | ||||
#define RSAQ_STATUS_OVERRUN_ERROR 0x40 | #define RSAQ_STATUS_OVERRUN_ERROR 0x40 | ||||
#define RSAQ_STATUS_PARITY_ERROR 0x20 | #define RSAQ_STATUS_PARITY_ERROR 0x20 | ||||
#define RSAQ_STATUS_FRAME_ERROR 0x10 | #define RSAQ_STATUS_FRAME_ERROR 0x10 | ||||
#define RSAQ_STATUS_RING 0x08 | #define RSAQ_STATUS_RING 0x08 | ||||
#define RSAQ_STATUS_BREAK_ERROR 0x04 | #define RSAQ_STATUS_BREAK_ERROR 0x04 | ||||
#define RSAQ_STATUS_DSR 0x02 | #define RSAQ_STATUS_DSR 0x02 | ||||
#define RSAQ_STATUS_DCD 0x01 | #define RSAQ_STATUS_DCD 0x01 | ||||
#define TYPE_PL2303 0 | #define TYPE_PL2303 0 | ||||
#define TYPE_PL2303HX 1 | #define TYPE_PL2303HX 1 | ||||
#define TYPE_PL2303HXD 2 | #define TYPE_PL2303HXD 2 | ||||
#define TYPE_PL2303HXN 3 | |||||
#define UPLCOM_STATE_INDEX 8 | #define UPLCOM_STATE_INDEX 8 | ||||
enum { | enum { | ||||
UPLCOM_BULK_DT_WR, | UPLCOM_BULK_DT_WR, | ||||
UPLCOM_BULK_DT_RD, | UPLCOM_BULK_DT_RD, | ||||
UPLCOM_INTR_DT_RD, | UPLCOM_INTR_DT_RD, | ||||
UPLCOM_N_TRANSFER, | UPLCOM_N_TRANSFER, | ||||
▲ Show 20 Lines • Show All 127 Lines • ▼ Show 20 Lines | static const STRUCT_USB_HOST_ID uplcom_devs[] = { | ||||
UPLCOM_DEV(PROLIFIC, ALLTRONIX_GPRS), /* Alltronix ACM003U00 modem */ | UPLCOM_DEV(PROLIFIC, ALLTRONIX_GPRS), /* Alltronix ACM003U00 modem */ | ||||
UPLCOM_DEV(PROLIFIC, ALDIGA_AL11U), /* AlDiga AL-11U modem */ | UPLCOM_DEV(PROLIFIC, ALDIGA_AL11U), /* AlDiga AL-11U modem */ | ||||
UPLCOM_DEV(PROLIFIC, DCU11), /* DCU-11 Phone Cable */ | UPLCOM_DEV(PROLIFIC, DCU11), /* DCU-11 Phone Cable */ | ||||
UPLCOM_DEV(PROLIFIC, HCR331), /* HCR331 Card Reader */ | UPLCOM_DEV(PROLIFIC, HCR331), /* HCR331 Card Reader */ | ||||
UPLCOM_DEV(PROLIFIC, MICROMAX_610U), /* Micromax 610U modem */ | UPLCOM_DEV(PROLIFIC, MICROMAX_610U), /* Micromax 610U modem */ | ||||
UPLCOM_DEV(PROLIFIC, MOTOROLA), /* Motorola cable */ | UPLCOM_DEV(PROLIFIC, MOTOROLA), /* Motorola cable */ | ||||
UPLCOM_DEV(PROLIFIC, PHAROS), /* Prolific Pharos */ | UPLCOM_DEV(PROLIFIC, PHAROS), /* Prolific Pharos */ | ||||
UPLCOM_DEV(PROLIFIC, PL2303), /* Generic adapter */ | UPLCOM_DEV(PROLIFIC, PL2303), /* Generic adapter */ | ||||
UPLCOM_DEV(PROLIFIC, PL2303GC), /* Generic adapter (PL2303HXN, type GC) */ | |||||
UPLCOM_DEV(PROLIFIC, PL2303GB), /* Generic adapter (PL2303HXN, type GB) */ | |||||
UPLCOM_DEV(PROLIFIC, PL2303GT), /* Generic adapter (PL2303HXN, type GT) */ | |||||
UPLCOM_DEV(PROLIFIC, PL2303GL), /* Generic adapter (PL2303HXN, type GL) */ | |||||
UPLCOM_DEV(PROLIFIC, PL2303GE), /* Generic adapter (PL2303HXN, type GE) */ | |||||
UPLCOM_DEV(PROLIFIC, PL2303GS), /* Generic adapter (PL2303HXN, type GS) */ | |||||
UPLCOM_DEV(PROLIFIC, RSAQ2), /* I/O DATA USB-RSAQ2 */ | UPLCOM_DEV(PROLIFIC, RSAQ2), /* I/O DATA USB-RSAQ2 */ | ||||
UPLCOM_DEV(PROLIFIC, RSAQ3), /* I/O DATA USB-RSAQ3 */ | UPLCOM_DEV(PROLIFIC, RSAQ3), /* I/O DATA USB-RSAQ3 */ | ||||
UPLCOM_DEV(PROLIFIC, UIC_MSR206), /* UIC MSR206 Card Reader */ | UPLCOM_DEV(PROLIFIC, UIC_MSR206), /* UIC MSR206 Card Reader */ | ||||
UPLCOM_DEV(PROLIFIC2, PL2303), /* Prolific adapter */ | UPLCOM_DEV(PROLIFIC2, PL2303), /* Prolific adapter */ | ||||
UPLCOM_DEV(RADIOSHACK, USBCABLE), /* Radio Shack USB Adapter */ | UPLCOM_DEV(RADIOSHACK, USBCABLE), /* Radio Shack USB Adapter */ | ||||
UPLCOM_DEV(RATOC, REXUSB60), /* RATOC REX-USB60 */ | UPLCOM_DEV(RATOC, REXUSB60), /* RATOC REX-USB60 */ | ||||
UPLCOM_DEV(SAGEM, USBSERIAL), /* Sagem USB-Serial Controller */ | UPLCOM_DEV(SAGEM, USBSERIAL), /* Sagem USB-Serial Controller */ | ||||
UPLCOM_DEV(SAMSUNG, I330), /* Samsung I330 phone cradle */ | UPLCOM_DEV(SAMSUNG, I330), /* Samsung I330 phone cradle */ | ||||
▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
struct usb_attach_arg *uaa = device_get_ivars(dev); | struct usb_attach_arg *uaa = device_get_ivars(dev); | ||||
struct uplcom_softc *sc = device_get_softc(dev); | struct uplcom_softc *sc = device_get_softc(dev); | ||||
struct usb_interface *iface; | struct usb_interface *iface; | ||||
struct usb_interface_descriptor *id; | struct usb_interface_descriptor *id; | ||||
struct usb_device_descriptor *dd; | struct usb_device_descriptor *dd; | ||||
int error; | int error; | ||||
struct usb_device_request req; | |||||
usb_error_t err; | |||||
uint8_t buf[4]; | |||||
DPRINTFN(11, "\n"); | DPRINTFN(11, "\n"); | ||||
device_set_usb_desc(dev); | device_set_usb_desc(dev); | ||||
mtx_init(&sc->sc_mtx, "uplcom", NULL, MTX_DEF); | mtx_init(&sc->sc_mtx, "uplcom", NULL, MTX_DEF); | ||||
ucom_ref(&sc->sc_super_ucom); | ucom_ref(&sc->sc_super_ucom); | ||||
DPRINTF("sc = %p\n", sc); | DPRINTF("sc = %p\n", sc); | ||||
Show All 23 Lines | if (dd->bDeviceClass == 0x02) | ||||
sc->sc_chiptype = TYPE_PL2303; | sc->sc_chiptype = TYPE_PL2303; | ||||
else if (dd->bMaxPacketSize == 0x40) | else if (dd->bMaxPacketSize == 0x40) | ||||
sc->sc_chiptype = TYPE_PL2303HX; | sc->sc_chiptype = TYPE_PL2303HX; | ||||
else | else | ||||
sc->sc_chiptype = TYPE_PL2303; | sc->sc_chiptype = TYPE_PL2303; | ||||
break; | break; | ||||
} | } | ||||
/* | |||||
* The new chip revision PL2303HXN is only compatible with the new | |||||
* UPLCOM_SET_REQUEST_PL2303HXN command. Issuing the old command | |||||
* UPLCOM_SET_REQUEST to the new chip raises an error. Thus, PL2303HX | |||||
* and PL2303HXN can be distinguished by issuing an old-style request | |||||
* (on a status register) to the new chip and checking the error. | |||||
*/ | |||||
if (sc->sc_chiptype == TYPE_PL2303HX) { | |||||
req.bmRequestType = UT_READ_VENDOR_DEVICE; | |||||
req.bRequest = UPLCOM_SET_REQUEST; | |||||
USETW(req.wValue, UPLCOM_STATUS_REG_PL2303HX); | |||||
req.wIndex[0] = sc->sc_data_iface_no; | |||||
req.wIndex[1] = 0; | |||||
USETW(req.wLength, 1); | |||||
err = usbd_do_request(sc->sc_udev, NULL, &req, buf); | |||||
if (err) | |||||
sc->sc_chiptype = TYPE_PL2303HXN; | |||||
} | |||||
switch (sc->sc_chiptype) { | switch (sc->sc_chiptype) { | ||||
case TYPE_PL2303: | case TYPE_PL2303: | ||||
DPRINTF("chiptype: 2303\n"); | DPRINTF("chiptype: 2303\n"); | ||||
break; | break; | ||||
case TYPE_PL2303HX: | case TYPE_PL2303HX: | ||||
DPRINTF("chiptype: 2303HX/TA\n"); | DPRINTF("chiptype: 2303HX/TA\n"); | ||||
break; | break; | ||||
case TYPE_PL2303HXN: | |||||
DPRINTF("chiptype: 2303HXN\n"); | |||||
break; | |||||
case TYPE_PL2303HXD: | case TYPE_PL2303HXD: | ||||
DPRINTF("chiptype: 2303HXD/TB/RA/EA\n"); | DPRINTF("chiptype: 2303HXD/TB/RA/EA\n"); | ||||
break; | break; | ||||
default: | default: | ||||
DPRINTF("chiptype: unknown %d\n", sc->sc_chiptype); | DPRINTF("chiptype: unknown %d\n", sc->sc_chiptype); | ||||
break; | break; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | uplcom_attach(device_t dev) | ||||
} | } | ||||
if (sc->sc_chiptype == TYPE_PL2303) { | if (sc->sc_chiptype == TYPE_PL2303) { | ||||
/* HX variants seem to lock up after a clear stall request. */ | /* HX variants seem to lock up after a clear stall request. */ | ||||
mtx_lock(&sc->sc_mtx); | mtx_lock(&sc->sc_mtx); | ||||
usbd_xfer_set_stall(sc->sc_xfer[UPLCOM_BULK_DT_WR]); | usbd_xfer_set_stall(sc->sc_xfer[UPLCOM_BULK_DT_WR]); | ||||
usbd_xfer_set_stall(sc->sc_xfer[UPLCOM_BULK_DT_RD]); | usbd_xfer_set_stall(sc->sc_xfer[UPLCOM_BULK_DT_RD]); | ||||
mtx_unlock(&sc->sc_mtx); | mtx_unlock(&sc->sc_mtx); | ||||
} else { | } else if (sc->sc_chiptype == TYPE_PL2303HX || | ||||
sc->sc_chiptype == TYPE_PL2303HXD) { | |||||
/* reset upstream data pipes */ | /* reset upstream data pipes */ | ||||
if (uplcom_pl2303_do(sc->sc_udev, UT_WRITE_VENDOR_DEVICE, | if (uplcom_pl2303_do(sc->sc_udev, UT_WRITE_VENDOR_DEVICE, | ||||
UPLCOM_SET_REQUEST, 8, 0, 0) || | UPLCOM_SET_REQUEST, 8, 0, 0) || | ||||
uplcom_pl2303_do(sc->sc_udev, UT_WRITE_VENDOR_DEVICE, | uplcom_pl2303_do(sc->sc_udev, UT_WRITE_VENDOR_DEVICE, | ||||
UPLCOM_SET_REQUEST, 9, 0, 0)) { | UPLCOM_SET_REQUEST, 9, 0, 0)) { | ||||
goto detach; | goto detach; | ||||
} | } | ||||
} else if (sc->sc_chiptype == TYPE_PL2303HXN) { | |||||
/* reset upstream data pipes */ | |||||
if (uplcom_pl2303_do(sc->sc_udev, UT_WRITE_VENDOR_DEVICE, | |||||
UPLCOM_SET_REQUEST_PL2303HXN, 0x07, 0x03, 0)) { | |||||
goto detach; | |||||
} | } | ||||
} | |||||
error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, | error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, | ||||
&uplcom_callback, &sc->sc_mtx); | &uplcom_callback, &sc->sc_mtx); | ||||
if (error) { | if (error) { | ||||
goto detach; | goto detach; | ||||
} | } | ||||
/* | /* | ||||
* do the initialization during attach so that the system does not | * do the initialization during attach so that the system does not | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | uplcom_free(struct ucom_softc *ucom) | ||||
uplcom_free_softc(ucom->sc_parent); | uplcom_free_softc(ucom->sc_parent); | ||||
} | } | ||||
static usb_error_t | static usb_error_t | ||||
uplcom_reset(struct uplcom_softc *sc, struct usb_device *udev) | uplcom_reset(struct uplcom_softc *sc, struct usb_device *udev) | ||||
{ | { | ||||
struct usb_device_request req; | struct usb_device_request req; | ||||
if (sc->sc_chiptype == TYPE_PL2303HXN) { | |||||
/* PL2303HXN doesn't need this reset sequence */ | |||||
return (0); | |||||
} | |||||
req.bmRequestType = UT_WRITE_VENDOR_DEVICE; | req.bmRequestType = UT_WRITE_VENDOR_DEVICE; | ||||
req.bRequest = UPLCOM_SET_REQUEST; | req.bRequest = UPLCOM_SET_REQUEST; | ||||
USETW(req.wValue, 0); | USETW(req.wValue, 0); | ||||
req.wIndex[0] = sc->sc_data_iface_no; | req.wIndex[0] = sc->sc_data_iface_no; | ||||
req.wIndex[1] = 0; | req.wIndex[1] = 0; | ||||
USETW(req.wLength, 0); | USETW(req.wLength, 0); | ||||
return (usbd_do_request(udev, NULL, &req, NULL)); | return (usbd_do_request(udev, NULL, &req, NULL)); | ||||
Show All 21 Lines | uplcom_pl2303_do(struct usb_device *udev, uint8_t req_type, uint8_t request, | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
uplcom_pl2303_init(struct usb_device *udev, uint8_t chiptype) | uplcom_pl2303_init(struct usb_device *udev, uint8_t chiptype) | ||||
{ | { | ||||
int err; | int err; | ||||
if (chiptype == TYPE_PL2303HXN) { | |||||
/* PL2303HXN doesn't need this initialization sequence */ | |||||
return (0); | |||||
} | |||||
if (uplcom_pl2303_do(udev, UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 1) | if (uplcom_pl2303_do(udev, UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 1) | ||||
|| uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x0404, 0, 0) | || uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x0404, 0, 0) | ||||
|| uplcom_pl2303_do(udev, UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 1) | || uplcom_pl2303_do(udev, UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 1) | ||||
|| uplcom_pl2303_do(udev, UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8383, 0, 1) | || uplcom_pl2303_do(udev, UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8383, 0, 1) | ||||
|| uplcom_pl2303_do(udev, UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 1) | || uplcom_pl2303_do(udev, UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 1) | ||||
|| uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x0404, 1, 0) | || uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x0404, 1, 0) | ||||
|| uplcom_pl2303_do(udev, UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 1) | || uplcom_pl2303_do(udev, UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 1) | ||||
|| uplcom_pl2303_do(udev, UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8383, 0, 1) | || uplcom_pl2303_do(udev, UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8383, 0, 1) | ||||
▲ Show 20 Lines • Show All 130 Lines • ▼ Show 20 Lines | uplcom_pre_param(struct ucom_softc *ucom, struct termios *t) | ||||
DPRINTF("\n"); | DPRINTF("\n"); | ||||
/** | /** | ||||
* Check requested baud rate. | * Check requested baud rate. | ||||
* | * | ||||
* The PL2303 can only set specific baud rates, up to 1228800 baud. | * The PL2303 can only set specific baud rates, up to 1228800 baud. | ||||
* The PL2303HX can set any baud rate up to 6Mb. | * The PL2303HX can set any baud rate up to 6Mb. | ||||
* The PL2303HX rev. D can set any baud rate up to 12Mb. | * The PL2303HX rev. D and PL2303HXN can set any baud rate up to 12Mb. | ||||
* | * | ||||
*/ | */ | ||||
/* accept raw divisor data, if someone wants to do the math in user domain */ | /* accept raw divisor data, if someone wants to do the math in user domain */ | ||||
if (t->c_ospeed & 0x80000000) | if (t->c_ospeed & 0x80000000) | ||||
return 0; | return 0; | ||||
switch (sc->sc_chiptype) { | switch (sc->sc_chiptype) { | ||||
case TYPE_PL2303HXN: | |||||
if (t->c_ospeed <= 12000000) | |||||
return (0); | |||||
break; | |||||
case TYPE_PL2303HXD: | case TYPE_PL2303HXD: | ||||
if (t->c_ospeed <= 12000000) | if (t->c_ospeed <= 12000000) | ||||
return (0); | return (0); | ||||
break; | break; | ||||
case TYPE_PL2303HX: | case TYPE_PL2303HX: | ||||
if (t->c_ospeed <= 6000000) | if (t->c_ospeed <= 6000000) | ||||
return (0); | return (0); | ||||
break; | break; | ||||
▲ Show 20 Lines • Show All 120 Lines • ▼ Show 20 Lines | uplcom_cfg_param(struct ucom_softc *ucom, struct termios *t) | ||||
ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, | ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, | ||||
&req, &ls, 0, 1000); | &req, &ls, 0, 1000); | ||||
if (t->c_cflag & CRTSCTS) { | if (t->c_cflag & CRTSCTS) { | ||||
DPRINTF("crtscts = on\n"); | DPRINTF("crtscts = on\n"); | ||||
req.bmRequestType = UT_WRITE_VENDOR_DEVICE; | req.bmRequestType = UT_WRITE_VENDOR_DEVICE; | ||||
if (sc->sc_chiptype == TYPE_PL2303HXN) { | |||||
req.bRequest = UPLCOM_SET_REQUEST_PL2303HXN; | |||||
USETW(req.wValue, UPLCOM_CRTSCTS_REG_PL2303HXN); | |||||
USETW(req.wIndex, UPLCOM_SET_CRTSCTS_PL2303HXN); | |||||
} else { | |||||
req.bRequest = UPLCOM_SET_REQUEST; | req.bRequest = UPLCOM_SET_REQUEST; | ||||
USETW(req.wValue, 0); | USETW(req.wValue, 0); | ||||
if (sc->sc_chiptype != TYPE_PL2303) | if (sc->sc_chiptype != TYPE_PL2303) | ||||
USETW(req.wIndex, UPLCOM_SET_CRTSCTS_PL2303X); | USETW(req.wIndex, UPLCOM_SET_CRTSCTS_PL2303X); | ||||
else | else | ||||
USETW(req.wIndex, UPLCOM_SET_CRTSCTS); | USETW(req.wIndex, UPLCOM_SET_CRTSCTS); | ||||
} | |||||
USETW(req.wLength, 0); | USETW(req.wLength, 0); | ||||
ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, | ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, | ||||
&req, NULL, 0, 1000); | &req, NULL, 0, 1000); | ||||
} else { | } else { | ||||
req.bmRequestType = UT_WRITE_VENDOR_DEVICE; | req.bmRequestType = UT_WRITE_VENDOR_DEVICE; | ||||
if (sc->sc_chiptype == TYPE_PL2303HXN) { | |||||
req.bRequest = UPLCOM_SET_REQUEST_PL2303HXN; | |||||
USETW(req.wValue, UPLCOM_CRTSCTS_REG_PL2303HXN); | |||||
USETW(req.wIndex, UPLCOM_CLEAR_CRTSCTS_PL2303HXN); | |||||
} | |||||
else { | |||||
req.bRequest = UPLCOM_SET_REQUEST; | req.bRequest = UPLCOM_SET_REQUEST; | ||||
USETW(req.wValue, 0); | USETW(req.wValue, 0); | ||||
USETW(req.wIndex, 0); | USETW(req.wIndex, 0); | ||||
} | |||||
USETW(req.wLength, 0); | USETW(req.wLength, 0); | ||||
ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, | ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, | ||||
&req, NULL, 0, 1000); | &req, NULL, 0, 1000); | ||||
} | } | ||||
} | } | ||||
static void | static void | ||||
uplcom_start_read(struct ucom_softc *ucom) | uplcom_start_read(struct ucom_softc *ucom) | ||||
▲ Show 20 Lines • Show All 182 Lines • Show Last 20 Lines |