aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Petter Selasky <hselasky@FreeBSD.org>2021-01-07 14:34:26 +0000
committerHans Petter Selasky <hselasky@FreeBSD.org>2021-02-01 09:31:58 +0000
commit671c393854a5ae60369beadfb74007e240bb18ab (patch)
tree3f9e538344e58247731f422b0ab7530a020a4411
parent8340ed8900e4ff48e7a428f30a98c0e91c91da03 (diff)
downloadsrc-671c393854a5ae60369beadfb74007e240bb18ab.tar.gz
src-671c393854a5ae60369beadfb74007e240bb18ab.zip
MFC ea0efc370416:
Add support for PL2303HXN to uplcom(4). Code changes in this commit were obtained from straight from OpenBSD's uplcom.c with almost no modification, the list of chip names and USB IDs was obtained from Linux. Differential Revision: https://reviews.freebsd.org/D27952 Submitted by: tomli_tomli.me (Yifeng Li) Sponsored by: Mellanox Technologies // NVIDIA Networking (cherry picked from commit ea0efc37041640686fbfb226e80ee60e58cb17f1)
-rw-r--r--share/man/man4/uplcom.44
-rw-r--r--sys/dev/usb/serial/uplcom.c94
-rw-r--r--sys/dev/usb/usbdevs6
3 files changed, 92 insertions, 12 deletions
diff --git a/share/man/man4/uplcom.4 b/share/man/man4/uplcom.4
index b3f1fbb3ff18..ca29ee8d454d 100644
--- a/share/man/man4/uplcom.4
+++ b/share/man/man4/uplcom.4
@@ -29,7 +29,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd April 26, 2017
+.Dd January 7, 2021
.Dt UPLCOM 4
.Os
.Sh NAME
@@ -132,6 +132,8 @@ PLANEX USB-RS232 URS-03
.It
Prolific Generic USB-Serial Adapters
.It
+Prolific Generic USB-Serial Adapters (HXN)
+.It
Prolific Pharos USB-Serial Adapter
.It
RATOC REX-USB60
diff --git a/sys/dev/usb/serial/uplcom.c b/sys/dev/usb/serial/uplcom.c
index 27858af68692..0913cc7890d4 100644
--- a/sys/dev/usb/serial/uplcom.c
+++ b/sys/dev/usb/serial/uplcom.c
@@ -129,8 +129,13 @@ SYSCTL_INT(_hw_usb_uplcom, OID_AUTO, debug, CTLFLAG_RWTUN,
#define UPLCOM_BULK_BUF_SIZE 1024 /* bytes */
#define UPLCOM_SET_REQUEST 0x01
+#define UPLCOM_SET_REQUEST_PL2303HXN 0x80
#define UPLCOM_SET_CRTSCTS 0x41
#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_OVERRUN_ERROR 0x40
#define RSAQ_STATUS_PARITY_ERROR 0x20
@@ -143,6 +148,7 @@ SYSCTL_INT(_hw_usb_uplcom, OID_AUTO, debug, CTLFLAG_RWTUN,
#define TYPE_PL2303 0
#define TYPE_PL2303HX 1
#define TYPE_PL2303HXD 2
+#define TYPE_PL2303HXN 3
#define UPLCOM_STATE_INDEX 8
@@ -286,6 +292,12 @@ static const STRUCT_USB_HOST_ID uplcom_devs[] = {
UPLCOM_DEV(PROLIFIC, MOTOROLA), /* Motorola cable */
UPLCOM_DEV(PROLIFIC, PHAROS), /* Prolific Pharos */
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, RSAQ3), /* I/O DATA USB-RSAQ3 */
UPLCOM_DEV(PROLIFIC, UIC_MSR206), /* UIC MSR206 Card Reader */
@@ -365,6 +377,10 @@ uplcom_attach(device_t dev)
struct usb_device_descriptor *dd;
int error;
+ struct usb_device_request req;
+ usb_error_t err;
+ uint8_t buf[4];
+
DPRINTFN(11, "\n");
device_set_usb_desc(dev);
@@ -404,6 +420,25 @@ uplcom_attach(device_t dev)
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) {
case TYPE_PL2303:
DPRINTF("chiptype: 2303\n");
@@ -411,6 +446,9 @@ uplcom_attach(device_t dev)
case TYPE_PL2303HX:
DPRINTF("chiptype: 2303HX/TA\n");
break;
+ case TYPE_PL2303HXN:
+ DPRINTF("chiptype: 2303HXN\n");
+ break;
case TYPE_PL2303HXD:
DPRINTF("chiptype: 2303HXD/TB/RA/EA\n");
break;
@@ -472,7 +510,8 @@ uplcom_attach(device_t dev)
usbd_xfer_set_stall(sc->sc_xfer[UPLCOM_BULK_DT_WR]);
usbd_xfer_set_stall(sc->sc_xfer[UPLCOM_BULK_DT_RD]);
mtx_unlock(&sc->sc_mtx);
- } else {
+ } else if (sc->sc_chiptype == TYPE_PL2303HX ||
+ sc->sc_chiptype == TYPE_PL2303HXD) {
/* reset upstream data pipes */
if (uplcom_pl2303_do(sc->sc_udev, UT_WRITE_VENDOR_DEVICE,
UPLCOM_SET_REQUEST, 8, 0, 0) ||
@@ -480,6 +519,12 @@ uplcom_attach(device_t dev)
UPLCOM_SET_REQUEST, 9, 0, 0)) {
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,
@@ -543,6 +588,11 @@ uplcom_reset(struct uplcom_softc *sc, struct usb_device *udev)
{
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.bRequest = UPLCOM_SET_REQUEST;
USETW(req.wValue, 0);
@@ -580,6 +630,11 @@ uplcom_pl2303_init(struct usb_device *udev, uint8_t chiptype)
{
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)
|| 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)
@@ -726,7 +781,7 @@ uplcom_pre_param(struct ucom_softc *ucom, struct termios *t)
*
* The PL2303 can only set specific baud rates, up to 1228800 baud.
* 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.
*
*/
@@ -734,6 +789,10 @@ uplcom_pre_param(struct ucom_softc *ucom, struct termios *t)
if (t->c_ospeed & 0x80000000)
return 0;
switch (sc->sc_chiptype) {
+ case TYPE_PL2303HXN:
+ if (t->c_ospeed <= 12000000)
+ return (0);
+ break;
case TYPE_PL2303HXD:
if (t->c_ospeed <= 12000000)
return (0);
@@ -871,21 +930,34 @@ uplcom_cfg_param(struct ucom_softc *ucom, struct termios *t)
DPRINTF("crtscts = on\n");
req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
- req.bRequest = UPLCOM_SET_REQUEST;
- USETW(req.wValue, 0);
- if (sc->sc_chiptype != TYPE_PL2303)
- USETW(req.wIndex, UPLCOM_SET_CRTSCTS_PL2303X);
- else
- USETW(req.wIndex, UPLCOM_SET_CRTSCTS);
+ 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;
+ USETW(req.wValue, 0);
+ if (sc->sc_chiptype != TYPE_PL2303)
+ USETW(req.wIndex, UPLCOM_SET_CRTSCTS_PL2303X);
+ else
+ USETW(req.wIndex, UPLCOM_SET_CRTSCTS);
+ }
USETW(req.wLength, 0);
ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom,
&req, NULL, 0, 1000);
} else {
req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
- req.bRequest = UPLCOM_SET_REQUEST;
- USETW(req.wValue, 0);
- USETW(req.wIndex, 0);
+ 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;
+ USETW(req.wValue, 0);
+ USETW(req.wIndex, 0);
+ }
USETW(req.wLength, 0);
ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom,
&req, NULL, 0, 1000);
diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs
index 5d52ff0f7217..2bb5e05035f6 100644
--- a/sys/dev/usb/usbdevs
+++ b/sys/dev/usb/usbdevs
@@ -3654,6 +3654,12 @@ product PROLIFIC MICROMAX_610U 0x0612 Micromax 610U
product PROLIFIC DCU11 0x1234 DCU-11 Phone Cable
product PROLIFIC UIC_MSR206 0x206a UIC MSR206 Card Reader
product PROLIFIC PL2303 0x2303 PL2303 Serial (ATEN/IOGEAR UC232A)
+product PROLIFIC PL2303GC 0x23a3 PL2303HXN Serial, type GC
+product PROLIFIC PL2303GB 0x23b3 PL2303HXN Serial, type GB
+product PROLIFIC PL2303GT 0x23c3 PL2303HXN Serial, type GT
+product PROLIFIC PL2303GL 0x23d3 PL2303HXN Serial, type GL
+product PROLIFIC PL2303GE 0x23e3 PL2303HXN Serial, type GE
+product PROLIFIC PL2303GS 0x23f3 PL2303HXN Serial, type GS
product PROLIFIC PL2305 0x2305 Parallel printer
product PROLIFIC ATAPI4 0x2307 ATAPI-4 Controller
product PROLIFIC PL2501 0x2501 PL2501 Host-Host interface