uftdi.c (9f7fef595d2cfa38db0e2608d63e3b6b08f38baf) | uftdi.c (a9d84a2ba7b4f96cea914b6142e93ae71373dcb7) |
---|---|
1/* $NetBSD: uftdi.c,v 1.13 2002/09/23 05:51:23 simonb Exp $ */ 2 3/*- 4 * Copyright (c) 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Lennart Augustsson (lennart@augustsson.net). --- 24 unchanged lines hidden (view full) --- 33__FBSDID("$FreeBSD$"); 34 35/* 36 * NOTE: all function names beginning like "uftdi_cfg_" can only 37 * be called from within the config thread function ! 38 */ 39 40/* | 1/* $NetBSD: uftdi.c,v 1.13 2002/09/23 05:51:23 simonb Exp $ */ 2 3/*- 4 * Copyright (c) 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Lennart Augustsson (lennart@augustsson.net). --- 24 unchanged lines hidden (view full) --- 33__FBSDID("$FreeBSD$"); 34 35/* 36 * NOTE: all function names beginning like "uftdi_cfg_" can only 37 * be called from within the config thread function ! 38 */ 39 40/* |
41 * FTDI FT2232x, FT8U100AX and FT8U232AM serial adapter driver | 41 * FTDI FT232x, FT2232x, FT4232x, FT8U100AX and FT8U232xM serial adapters. 42 * 43 * Note that we specifically do not do a reset or otherwise alter the state of 44 * the chip during attach, detach, open, and close, because it could be 45 * pre-initialized (via an attached serial eeprom) to power-on into a mode such 46 * as bitbang in which the pins are being driven to a specific state which we 47 * must not perturb. The device gets reset at power-on, and doesn't need to be 48 * reset again after that to function, except as directed by ioctl() calls. |
42 */ 43 44#include <sys/stdint.h> 45#include <sys/stddef.h> 46#include <sys/param.h> 47#include <sys/queue.h> 48#include <sys/types.h> 49#include <sys/systm.h> --- 9 unchanged lines hidden (view full) --- 59#include <sys/callout.h> 60#include <sys/malloc.h> 61#include <sys/priv.h> 62 63#include <dev/usb/usb.h> 64#include <dev/usb/usbdi.h> 65#include <dev/usb/usbdi_util.h> 66#include <dev/usb/usb_core.h> | 49 */ 50 51#include <sys/stdint.h> 52#include <sys/stddef.h> 53#include <sys/param.h> 54#include <sys/queue.h> 55#include <sys/types.h> 56#include <sys/systm.h> --- 9 unchanged lines hidden (view full) --- 66#include <sys/callout.h> 67#include <sys/malloc.h> 68#include <sys/priv.h> 69 70#include <dev/usb/usb.h> 71#include <dev/usb/usbdi.h> 72#include <dev/usb/usbdi_util.h> 73#include <dev/usb/usb_core.h> |
74#include <dev/usb/usb_ioctl.h> |
|
67#include "usbdevs.h" 68 69#define USB_DEBUG_VAR uftdi_debug 70#include <dev/usb/usb_debug.h> 71#include <dev/usb/usb_process.h> 72 73#include <dev/usb/serial/usb_serial.h> 74#include <dev/usb/serial/uftdi_reg.h> | 75#include "usbdevs.h" 76 77#define USB_DEBUG_VAR uftdi_debug 78#include <dev/usb/usb_debug.h> 79#include <dev/usb/usb_process.h> 80 81#include <dev/usb/serial/usb_serial.h> 82#include <dev/usb/serial/uftdi_reg.h> |
83#include <dev/usb/uftdiio.h> |
|
75 76#ifdef USB_DEBUG 77static int uftdi_debug = 0; 78 79static SYSCTL_NODE(_hw_usb, OID_AUTO, uftdi, CTLFLAG_RW, 0, "USB uftdi"); 80SYSCTL_INT(_hw_usb_uftdi, OID_AUTO, debug, CTLFLAG_RW, 81 &uftdi_debug, 0, "Debug level"); 82#endif --- 58 unchanged lines hidden (view full) --- 141 struct usb_device *sc_udev; 142 struct usb_xfer *sc_xfer[UFTDI_N_TRANSFER]; 143 device_t sc_dev; 144 struct mtx sc_mtx; 145 146 uint32_t sc_unit; 147 148 uint16_t sc_last_lcr; | 84 85#ifdef USB_DEBUG 86static int uftdi_debug = 0; 87 88static SYSCTL_NODE(_hw_usb, OID_AUTO, uftdi, CTLFLAG_RW, 0, "USB uftdi"); 89SYSCTL_INT(_hw_usb_uftdi, OID_AUTO, debug, CTLFLAG_RW, 90 &uftdi_debug, 0, "Debug level"); 91#endif --- 58 unchanged lines hidden (view full) --- 150 struct usb_device *sc_udev; 151 struct usb_xfer *sc_xfer[UFTDI_N_TRANSFER]; 152 device_t sc_dev; 153 struct mtx sc_mtx; 154 155 uint32_t sc_unit; 156 157 uint16_t sc_last_lcr; |
158 uint16_t sc_bcdDevice; |
|
149 150 uint8_t sc_devtype; 151 uint8_t sc_devflags; 152 uint8_t sc_hdrlen; 153 uint8_t sc_msr; 154 uint8_t sc_lsr; 155}; 156 --- 13 unchanged lines hidden (view full) --- 170static device_detach_t uftdi_detach; 171static void uftdi_free_softc(struct uftdi_softc *); 172 173static usb_callback_t uftdi_write_callback; 174static usb_callback_t uftdi_read_callback; 175 176static void uftdi_free(struct ucom_softc *); 177static void uftdi_cfg_open(struct ucom_softc *); | 159 160 uint8_t sc_devtype; 161 uint8_t sc_devflags; 162 uint8_t sc_hdrlen; 163 uint8_t sc_msr; 164 uint8_t sc_lsr; 165}; 166 --- 13 unchanged lines hidden (view full) --- 180static device_detach_t uftdi_detach; 181static void uftdi_free_softc(struct uftdi_softc *); 182 183static usb_callback_t uftdi_write_callback; 184static usb_callback_t uftdi_read_callback; 185 186static void uftdi_free(struct ucom_softc *); 187static void uftdi_cfg_open(struct ucom_softc *); |
188static void uftdi_cfg_close(struct ucom_softc *); |
|
178static void uftdi_cfg_set_dtr(struct ucom_softc *, uint8_t); 179static void uftdi_cfg_set_rts(struct ucom_softc *, uint8_t); 180static void uftdi_cfg_set_break(struct ucom_softc *, uint8_t); 181static int uftdi_set_parm_soft(struct ucom_softc *, struct termios *, 182 struct uftdi_param_config *); 183static int uftdi_pre_param(struct ucom_softc *, struct termios *); 184static void uftdi_cfg_param(struct ucom_softc *, struct termios *); 185static void uftdi_cfg_get_status(struct ucom_softc *, uint8_t *, 186 uint8_t *); | 189static void uftdi_cfg_set_dtr(struct ucom_softc *, uint8_t); 190static void uftdi_cfg_set_rts(struct ucom_softc *, uint8_t); 191static void uftdi_cfg_set_break(struct ucom_softc *, uint8_t); 192static int uftdi_set_parm_soft(struct ucom_softc *, struct termios *, 193 struct uftdi_param_config *); 194static int uftdi_pre_param(struct ucom_softc *, struct termios *); 195static void uftdi_cfg_param(struct ucom_softc *, struct termios *); 196static void uftdi_cfg_get_status(struct ucom_softc *, uint8_t *, 197 uint8_t *); |
198static int uftdi_reset(struct ucom_softc *, int); 199static int uftdi_set_bitmode(struct ucom_softc *, uint8_t, uint8_t); 200static int uftdi_get_bitmode(struct ucom_softc *, uint8_t *); 201static int uftdi_set_latency(struct ucom_softc *, int); 202static int uftdi_get_latency(struct ucom_softc *, int *); 203static int uftdi_set_event_char(struct ucom_softc *, int); 204static int uftdi_set_error_char(struct ucom_softc *, int); 205static int uftdi_ioctl(struct ucom_softc *, uint32_t, caddr_t, int, 206 struct thread *); |
|
187static void uftdi_start_read(struct ucom_softc *); 188static void uftdi_stop_read(struct ucom_softc *); 189static void uftdi_start_write(struct ucom_softc *); 190static void uftdi_stop_write(struct ucom_softc *); 191static void uftdi_poll(struct ucom_softc *ucom); 192 193static const struct usb_config uftdi_config[UFTDI_N_TRANSFER] = { 194 --- 18 unchanged lines hidden (view full) --- 213 214static const struct ucom_callback uftdi_callback = { 215 .ucom_cfg_get_status = &uftdi_cfg_get_status, 216 .ucom_cfg_set_dtr = &uftdi_cfg_set_dtr, 217 .ucom_cfg_set_rts = &uftdi_cfg_set_rts, 218 .ucom_cfg_set_break = &uftdi_cfg_set_break, 219 .ucom_cfg_param = &uftdi_cfg_param, 220 .ucom_cfg_open = &uftdi_cfg_open, | 207static void uftdi_start_read(struct ucom_softc *); 208static void uftdi_stop_read(struct ucom_softc *); 209static void uftdi_start_write(struct ucom_softc *); 210static void uftdi_stop_write(struct ucom_softc *); 211static void uftdi_poll(struct ucom_softc *ucom); 212 213static const struct usb_config uftdi_config[UFTDI_N_TRANSFER] = { 214 --- 18 unchanged lines hidden (view full) --- 233 234static const struct ucom_callback uftdi_callback = { 235 .ucom_cfg_get_status = &uftdi_cfg_get_status, 236 .ucom_cfg_set_dtr = &uftdi_cfg_set_dtr, 237 .ucom_cfg_set_rts = &uftdi_cfg_set_rts, 238 .ucom_cfg_set_break = &uftdi_cfg_set_break, 239 .ucom_cfg_param = &uftdi_cfg_param, 240 .ucom_cfg_open = &uftdi_cfg_open, |
241 .ucom_cfg_close = &uftdi_cfg_close, |
|
221 .ucom_pre_param = &uftdi_pre_param, | 242 .ucom_pre_param = &uftdi_pre_param, |
243 .ucom_ioctl = &uftdi_ioctl, |
|
222 .ucom_start_read = &uftdi_start_read, 223 .ucom_stop_read = &uftdi_stop_read, 224 .ucom_start_write = &uftdi_start_write, 225 .ucom_stop_write = &uftdi_stop_write, 226 .ucom_poll = &uftdi_poll, 227 .ucom_free = &uftdi_free, 228}; 229 --- 670 unchanged lines hidden (view full) --- 900 * Due to a hardware bug, a 232B chip without an eeprom reports itself as a 901 * 232A, but if the serial number is also zero we know it's really a 232B. 902 */ 903static void 904uftdi_devtype_setup(struct uftdi_softc *sc, struct usb_attach_arg *uaa) 905{ 906 struct usb_device_descriptor *dd; 907 | 244 .ucom_start_read = &uftdi_start_read, 245 .ucom_stop_read = &uftdi_stop_read, 246 .ucom_start_write = &uftdi_start_write, 247 .ucom_stop_write = &uftdi_stop_write, 248 .ucom_poll = &uftdi_poll, 249 .ucom_free = &uftdi_free, 250}; 251 --- 670 unchanged lines hidden (view full) --- 922 * Due to a hardware bug, a 232B chip without an eeprom reports itself as a 923 * 232A, but if the serial number is also zero we know it's really a 232B. 924 */ 925static void 926uftdi_devtype_setup(struct uftdi_softc *sc, struct usb_attach_arg *uaa) 927{ 928 struct usb_device_descriptor *dd; 929 |
930 sc->sc_bcdDevice = uaa->info.bcdDevice; 931 |
|
908 switch (uaa->info.bcdDevice) { 909 case 0x200: 910 dd = usbd_get_device_descriptor(sc->sc_udev); 911 if (dd->iSerialNumber == 0) { 912 sc->sc_devtype = DEVT_232B; 913 } else { 914 sc->sc_devtype = DEVT_232A; 915 } --- 165 unchanged lines hidden (view full) --- 1081uftdi_free(struct ucom_softc *ucom) 1082{ 1083 uftdi_free_softc(ucom->sc_parent); 1084} 1085 1086static void 1087uftdi_cfg_open(struct ucom_softc *ucom) 1088{ | 932 switch (uaa->info.bcdDevice) { 933 case 0x200: 934 dd = usbd_get_device_descriptor(sc->sc_udev); 935 if (dd->iSerialNumber == 0) { 936 sc->sc_devtype = DEVT_232B; 937 } else { 938 sc->sc_devtype = DEVT_232A; 939 } --- 165 unchanged lines hidden (view full) --- 1105uftdi_free(struct ucom_softc *ucom) 1106{ 1107 uftdi_free_softc(ucom->sc_parent); 1108} 1109 1110static void 1111uftdi_cfg_open(struct ucom_softc *ucom) 1112{ |
1089 struct uftdi_softc *sc = ucom->sc_parent; 1090 uint16_t wIndex = ucom->sc_portno; 1091 struct usb_device_request req; | |
1092 | 1113 |
1114 /* 1115 * This do-nothing open routine exists for the sole purpose of this 1116 * DPRINTF() so that you can see the point at which open gets called 1117 * when debugging is enabled. 1118 */ |
|
1093 DPRINTF(""); | 1119 DPRINTF(""); |
1120} |
|
1094 | 1121 |
1095 /* perform a full reset on the device */ | 1122static void 1123uftdi_cfg_close(struct ucom_softc *ucom) 1124{ |
1096 | 1125 |
1097 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 1098 req.bRequest = FTDI_SIO_RESET; 1099 USETW(req.wValue, FTDI_SIO_RESET_SIO); 1100 USETW(req.wIndex, wIndex); 1101 USETW(req.wLength, 0); 1102 ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, 1103 &req, NULL, 0, 1000); 1104 1105 /* turn on RTS/CTS flow control */ 1106 1107 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 1108 req.bRequest = FTDI_SIO_SET_FLOW_CTRL; 1109 USETW(req.wValue, 0); 1110 USETW2(req.wIndex, FTDI_SIO_RTS_CTS_HS, wIndex); 1111 USETW(req.wLength, 0); 1112 ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, 1113 &req, NULL, 0, 1000); 1114 | |
1115 /* | 1126 /* |
1116 * NOTE: with the new UCOM layer there will always be a 1117 * "uftdi_cfg_param()" call after "open()", so there is no need for 1118 * "open()" to configure anything | 1127 * This do-nothing close routine exists for the sole purpose of this 1128 * DPRINTF() so that you can see the point at which close gets called 1129 * when debugging is enabled. |
1119 */ | 1130 */ |
1131 DPRINTF(""); |
|
1120} 1121 1122static void 1123uftdi_write_callback(struct usb_xfer *xfer, usb_error_t error) 1124{ 1125 struct uftdi_softc *sc = usbd_xfer_softc(xfer); 1126 struct usb_page_cache *pc; 1127 uint32_t pktlen; --- 450 unchanged lines hidden (view full) --- 1578 1579 DPRINTF("msr=0x%02x lsr=0x%02x\n", 1580 sc->sc_msr, sc->sc_lsr); 1581 1582 *msr = sc->sc_msr; 1583 *lsr = sc->sc_lsr; 1584} 1585 | 1132} 1133 1134static void 1135uftdi_write_callback(struct usb_xfer *xfer, usb_error_t error) 1136{ 1137 struct uftdi_softc *sc = usbd_xfer_softc(xfer); 1138 struct usb_page_cache *pc; 1139 uint32_t pktlen; --- 450 unchanged lines hidden (view full) --- 1590 1591 DPRINTF("msr=0x%02x lsr=0x%02x\n", 1592 sc->sc_msr, sc->sc_lsr); 1593 1594 *msr = sc->sc_msr; 1595 *lsr = sc->sc_lsr; 1596} 1597 |
1598static int 1599uftdi_reset(struct ucom_softc *ucom, int reset_type) 1600{ 1601 struct uftdi_softc *sc = ucom->sc_parent; 1602 usb_device_request_t req; 1603 1604 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 1605 req.bRequest = FTDI_SIO_RESET; 1606 1607 USETW(req.wIndex, sc->sc_ucom.sc_portno); 1608 USETW(req.wLength, 0); 1609 USETW(req.wValue, reset_type); 1610 1611 return (usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, NULL)); 1612} 1613 1614static int 1615uftdi_set_bitmode(struct ucom_softc *ucom, uint8_t bitmode, uint8_t iomask) 1616{ 1617 struct uftdi_softc *sc = ucom->sc_parent; 1618 usb_device_request_t req; 1619 1620 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 1621 req.bRequest = FTDI_SIO_SET_BITMODE; 1622 1623 USETW(req.wIndex, sc->sc_ucom.sc_portno); 1624 USETW(req.wLength, 0); 1625 1626 if (bitmode == UFTDI_BITMODE_NONE) 1627 USETW2(req.wValue, 0, 0); 1628 else 1629 USETW2(req.wValue, (1 << bitmode), iomask); 1630 1631 return (usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, NULL)); 1632} 1633 1634static int 1635uftdi_get_bitmode(struct ucom_softc *ucom, uint8_t *iomask) 1636{ 1637 struct uftdi_softc *sc = ucom->sc_parent; 1638 usb_device_request_t req; 1639 1640 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 1641 req.bRequest = FTDI_SIO_GET_BITMODE; 1642 1643 USETW(req.wIndex, sc->sc_ucom.sc_portno); 1644 USETW(req.wLength, 1); 1645 USETW(req.wValue, 0); 1646 1647 return (usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, iomask)); 1648} 1649 1650static int 1651uftdi_set_latency(struct ucom_softc *ucom, int latency) 1652{ 1653 struct uftdi_softc *sc = ucom->sc_parent; 1654 usb_device_request_t req; 1655 1656 if (latency < 0 || latency > 255) 1657 return (USB_ERR_INVAL); 1658 1659 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 1660 req.bRequest = FTDI_SIO_SET_LATENCY; 1661 1662 USETW(req.wIndex, sc->sc_ucom.sc_portno); 1663 USETW(req.wLength, 0); 1664 USETW2(req.wValue, 0, latency); 1665 1666 return (usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, NULL)); 1667} 1668 1669static int 1670uftdi_get_latency(struct ucom_softc *ucom, int *latency) 1671{ 1672 struct uftdi_softc *sc = ucom->sc_parent; 1673 usb_device_request_t req; 1674 usb_error_t err; 1675 uint8_t buf; 1676 1677 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 1678 req.bRequest = FTDI_SIO_GET_LATENCY; 1679 1680 USETW(req.wIndex, sc->sc_ucom.sc_portno); 1681 USETW(req.wLength, 1); 1682 USETW(req.wValue, 0); 1683 1684 err = usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, &buf); 1685 *latency = buf; 1686 1687 return (err); 1688} 1689 1690static int 1691uftdi_set_event_char(struct ucom_softc *ucom, int echar) 1692{ 1693 struct uftdi_softc *sc = ucom->sc_parent; 1694 usb_device_request_t req; 1695 uint8_t enable; 1696 1697 enable = (echar == -1) ? 0 : 1; 1698 1699 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 1700 req.bRequest = FTDI_SIO_SET_EVENT_CHAR; 1701 1702 USETW(req.wIndex, sc->sc_ucom.sc_portno); 1703 USETW(req.wLength, 0); 1704 USETW2(req.wValue, enable, echar & 0xff); 1705 1706 return (usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, NULL)); 1707} 1708 1709static int 1710uftdi_set_error_char(struct ucom_softc *ucom, int echar) 1711{ 1712 struct uftdi_softc *sc = ucom->sc_parent; 1713 usb_device_request_t req; 1714 uint8_t enable; 1715 1716 enable = (echar == -1) ? 0 : 1; 1717 1718 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 1719 req.bRequest = FTDI_SIO_SET_ERROR_CHAR; 1720 1721 USETW(req.wIndex, sc->sc_ucom.sc_portno); 1722 USETW(req.wLength, 0); 1723 USETW2(req.wValue, enable, echar & 0xff); 1724 1725 return (usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, NULL)); 1726} 1727 1728static int 1729uftdi_ioctl(struct ucom_softc *ucom, uint32_t cmd, caddr_t data, 1730 int flag, struct thread *td) 1731{ 1732 struct uftdi_softc *sc = ucom->sc_parent; 1733 int err; 1734 struct uftdi_bitmode * mode; 1735 1736 DPRINTF("portno: %d cmd: %#x\n", ucom->sc_portno, cmd); 1737 1738 switch (cmd) { 1739 case UFTDIIOC_RESET_IO: 1740 case UFTDIIOC_RESET_RX: 1741 case UFTDIIOC_RESET_TX: 1742 err = uftdi_reset(ucom, 1743 cmd == UFTDIIOC_RESET_IO ? FTDI_SIO_RESET_SIO : 1744 (cmd == UFTDIIOC_RESET_RX ? FTDI_SIO_RESET_PURGE_RX : 1745 FTDI_SIO_RESET_PURGE_TX)); 1746 break; 1747 case UFTDIIOC_SET_BITMODE: 1748 mode = (struct uftdi_bitmode *)data; 1749 err = uftdi_set_bitmode(ucom, mode->mode, mode->iomask); 1750 break; 1751 case UFTDIIOC_GET_BITMODE: 1752 mode = (struct uftdi_bitmode *)data; 1753 err = uftdi_get_bitmode(ucom, &mode->iomask); 1754 break; 1755 case UFTDIIOC_SET_LATENCY: 1756 err = uftdi_set_latency(ucom, *((int *)data)); 1757 break; 1758 case UFTDIIOC_GET_LATENCY: 1759 err = uftdi_get_latency(ucom, (int *)data); 1760 break; 1761 case UFTDIIOC_SET_ERROR_CHAR: 1762 err = uftdi_set_event_char(ucom, *(int *)data); 1763 break; 1764 case UFTDIIOC_SET_EVENT_CHAR: 1765 err = uftdi_set_error_char(ucom, *(int *)data); 1766 case UFTDIIOC_GET_HWREV: 1767 *(int *)data = sc->sc_bcdDevice; 1768 err = 0; 1769 break; 1770 default: 1771 return (ENOIOCTL); 1772 } 1773 if (err != USB_ERR_NORMAL_COMPLETION) 1774 return (EIO); 1775 return (0); 1776} 1777 |
|
1586static void 1587uftdi_start_read(struct ucom_softc *ucom) 1588{ 1589 struct uftdi_softc *sc = ucom->sc_parent; 1590 1591 usbd_transfer_start(sc->sc_xfer[UFTDI_BULK_DT_RD]); 1592} 1593 --- 31 unchanged lines hidden --- | 1778static void 1779uftdi_start_read(struct ucom_softc *ucom) 1780{ 1781 struct uftdi_softc *sc = ucom->sc_parent; 1782 1783 usbd_transfer_start(sc->sc_xfer[UFTDI_BULK_DT_RD]); 1784} 1785 --- 31 unchanged lines hidden --- |