usbser_var.h revision 7492:2387323b838f
1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21/* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26#ifndef _SYS_USB_USBSER_VAR_H 27#define _SYS_USB_USBSER_VAR_H 28 29 30/* 31 * USB-to-serial driver definitions 32 */ 33 34#include <sys/tty.h> 35#include <sys/mkdev.h> 36#include <sys/sunddi.h> 37#include <sys/note.h> 38 39#include <sys/usb/clients/usbser/usbser_dsdi.h> 40 41#ifdef __cplusplus 42extern "C" { 43#endif 44 45typedef struct usbser_state usbser_state_t; 46typedef struct usbser_port usbser_port_t; 47 48/* 49 * because put() and srv() routines are not allowed to block, usbser 50 * provides each port with two threads: for read and write processing 51 * this structure describes the data associated with a usbser thread 52 */ 53typedef struct usbser_thread { 54 kcondvar_t thr_cv; /* cv for request wait */ 55 uint_t thr_flags; /* state flags */ 56 usbser_port_t *thr_port; /* port owner of this thread */ 57 void (*thr_func)(void *); /* function to be run */ 58 void *thr_arg; /* function argument */ 59} usbser_thread_t; 60 61/* 62 * thr_flags 63 */ 64enum { 65 USBSER_THR_RUNNING = 0x01, /* thread is running */ 66 USBSER_THR_WAKE = 0x02, /* wake requested */ 67 USBSER_THR_EXITED = 0x04 /* thread exited */ 68}; 69 70/* 71 * additional device state 72 */ 73#define USBSER_DEV_INIT 0x80 /* device is being initialized */ 74 75/* 76 * per instance data 77 */ 78struct usbser_state { 79 struct usbser_state *us_next; /* linked list */ 80 dev_info_t *us_dip; /* device information */ 81 kmutex_t us_mutex; /* structure lock */ 82 void *us_statep; /* soft state anchor */ 83 int us_instance; /* instance number */ 84 ds_ops_t *us_ds_ops; /* DSD operations */ 85 ds_hdl_t us_ds_hdl; /* DSD device handle */ 86 uint_t us_port_cnt; /* port count */ 87 usbser_port_t *us_ports; /* array of port structs */ 88 uint_t us_dev_state; /* USB device state */ 89 usb_log_handle_t us_lh; /* USB log handle */ 90 ddi_taskq_t *us_taskq; /* taskq for command handling */ 91}; 92 93_NOTE(MUTEX_PROTECTS_DATA(usbser_state::us_mutex, usbser_state::us_dev_state)) 94 95/* 96 * per port data 97 */ 98struct usbser_port { 99 kmutex_t port_mutex; /* structure lock */ 100 usbser_state_t *port_usp; /* back pointer to state */ 101 char port_lh_name[16]; /* log handle name */ 102 usb_log_handle_t port_lh; /* log handle */ 103 ds_ops_t *port_ds_ops; /* copy from usbser_state */ 104 ds_hdl_t port_ds_hdl; /* copy from usbser_state */ 105 uint_t port_num; /* port number */ 106 uint_t port_state; /* port state */ 107 uint_t port_act; /* current activities on port */ 108 uint_t port_flags; /* port flags */ 109 kcondvar_t port_state_cv; /* port state cv */ 110 kcondvar_t port_act_cv; /* port activity cv */ 111 kcondvar_t port_car_cv; /* port carrier cv */ 112 uint_t port_wq_data_cnt; /* amount of unsent data */ 113 usbser_thread_t port_wq_thread; /* wq thread */ 114 usbser_thread_t port_rq_thread; /* rq thread */ 115 tty_common_t port_ttycommon; /* tty driver common data */ 116 uchar_t port_flowc; /* flow control char */ 117 timeout_id_t port_delay_id; /* delay/break timeout id */ 118}; 119 120_NOTE(MUTEX_PROTECTS_DATA(usbser_port::port_mutex, usbser_port)) 121_NOTE(DATA_READABLE_WITHOUT_LOCK(usbser_port::{ 122 port_usp 123 port_lh 124 port_ds_ops 125 port_ds_hdl 126 port_num 127 port_ttycommon.t_{readq writeq} 128})) 129 130_NOTE(LOCK_ORDER(usbser_state::us_mutex usbser_port::port_mutex)) 131 132/* 133 * port_state: 134 * 135 * USBSER_PORT_NOT_INIT 136 * | ^ 137 * | | 138 * attach detach 139 * | | 140 * | | +----open[1]----> USBSER_PORT_OPENING_TTY ------+ 141 * | | | | | | 142 * v | | | | | 143 * USBSER_PORT_CLOSED <---device error---< overtake[2] | 144 * | | | | v 145 * | | | v | 146 * | +----open[1]----> USBSER_PORT_OPENING_OUT | 147 * | | | 148 * | | +-------------------+ 149 * | | | 150 * | v v 151 * USBSER_PORT_CLOSING <-----close----- USBSER_PORT_OPEN <-----------+ 152 * ^ | ^ --------+ | 153 * | | | | | 154 * | | | | | 155 * | v | v | 156 * +------close----- USBSER_PORT_DISCONNECTED USBSER_PORT_SUSPENDED 157 * 158 * Notes: 159 * 160 * [1] for each physical port N two device nodes are created: 161 * 162 * /dev/term/N (tty mode) 163 * /dev/cua/N (dial-out mode) 164 * 165 * the port can only be opened in one of these modes at a time. 166 * difference between the two is that in tty mode the driver 167 * will block in open(9E) until the CD (Carrier Detect) pin comes up, 168 * while in dial-out mode CD is ignored. opening and closing states 169 * help to avoid race conditions between two threads trying to open/close 170 * one physical port in two different modes simultaneously. 171 * 172 * [2] tty mode open may be blocked waiting for carrier. 173 * if dial-out mode open happens at this time, it is allowed 174 * for it to overtake the port; from zs(7D) man page: 175 * 176 * This allows a modem to be attached to /dev/term/[n] 177 * and used for dial-in (by enabling the line for login in /etc/inittab) 178 * and also used for dial-out (by tip(1) or uucp(1C)) as /dev/cua/[n] 179 * when no one is logged in on the line. 180 */ 181enum { 182 USBSER_PORT_NOT_INIT = 0, /* port not initialized */ 183 USBSER_PORT_CLOSED, /* port is closed */ 184 USBSER_PORT_OPENING_TTY, /* tty open in progress */ 185 USBSER_PORT_OPENING_OUT, /* dial-out open in progress */ 186 USBSER_PORT_OPEN, /* port is open */ 187 USBSER_PORT_SUSPENDED, /* port is suspended */ 188 USBSER_PORT_DISCONNECTED, /* port is disconnected */ 189 USBSER_PORT_CLOSING /* close() is in progress */ 190}; 191 192/* constants used by state machine implementation */ 193enum { 194 USBSER_CONTINUE = -1, 195 USBSER_COMPLETE = 0 196}; 197 198/* 199 * port_act: current activities on the port. 200 * only one activity of each type is allowed at a time. 201 */ 202enum { 203 USBSER_ACT_TX = 0x0001, /* transmitting data */ 204 USBSER_ACT_RX = 0x0002, /* receiving data */ 205 USBSER_ACT_CTL = 0x0004, /* controlling the device */ 206 USBSER_ACT_BREAK = 0x0010, /* doing break */ 207 USBSER_ACT_DELAY = 0x0020, /* doing delay */ 208 USBSER_ACT_ALL = 0xffff /* all actions (must be >0) */ 209}; 210 211/* 212 * port_flags 213 */ 214enum { 215 USBSER_FL_OUT = 0x0001, /* dial-out */ 216 USBSER_FL_WOPEN = 0x0002, /* waiting in open() */ 217 USBSER_FL_CARR_ON = 0x0004, /* carrier is on */ 218 USBSER_FL_TX_STOPPED = 0x0008, /* output stopped */ 219 USBSER_FL_RX_STOPPED = 0x0010, /* input stopped */ 220 USBSER_FL_HUNGUP = 0x0020, /* stream is hung up */ 221 USBSER_FL_DSD_OPEN = 0x0040, /* DSD is open */ 222 USBSER_FL_STATUS_CB = 0x0080, /* status callback pending */ 223 USBSER_FL_IGNORE_CD = 0x0100, /* ignore carrier detect */ 224 USBSER_FL_PRESERVE = USBSER_FL_IGNORE_CD 225 /* flags that need to */ 226 /* be preserved across opens */ 227}; 228 229/* 230 * current sun compiler does not seem to inline static leaf routines at O3 231 * so we have to use preprocessor macros to make up for compiler disability 232 * 233 * can we access the port? 234 */ 235#define USBSER_PORT_ACCESS_OK(pp) ((pp)->port_state == USBSER_PORT_OPEN) 236 237/* 238 * is port doing something? 239 */ 240#define USBSER_PORT_IS_BUSY(pp) ((pp)->port_act != 0) 241 242/* 243 * is the port opening? 244 */ 245#define USBSER_IS_OPENING(pp) \ 246 (((pp)->port_state == USBSER_PORT_OPENING_TTY) || \ 247 ((pp)->port_state == USBSER_PORT_OPENING_OUT)) 248 249/* 250 * determine, while we are trying to open the port, 251 * whether it is currently being open in the opposite mode 252 */ 253#define USBSER_NO_OTHER_OPEN(pp, minor) \ 254 ((((minor) & OUTLINE) && \ 255 ((pp)->port_state == USBSER_PORT_OPENING_OUT)) || \ 256 (!((minor) & OUTLINE) && ((pp)->port_state == USBSER_PORT_OPENING_TTY))) 257 258/* 259 * determine, while we are trying to open the port, 260 * whether it is already open in the opposite mode 261 */ 262#define USBSER_OPEN_IN_OTHER_MODE(pp, minor) \ 263 ((((minor) & OUTLINE) && !((pp)->port_flags & USBSER_FL_OUT)) || \ 264 (!((minor) & OUTLINE) && ((pp)->port_flags & USBSER_FL_OUT))) 265 266/* 267 * minor number manipulation 268 */ 269enum { 270 MAXPORTS_PER_DEVICE_SHIFT = 4, 271 MAXPORTS_PER_DEVICE = (1 << MAXPORTS_PER_DEVICE_SHIFT), 272 MAXPORTS_PER_DEVICE_MASK = (MAXPORTS_PER_DEVICE - 1), 273 OUTLINE = (1 << (NBITSMINOR32 - 1)) 274}; 275 276#define USBSER_MAKEMINOR(instance, port, outline) \ 277 ((port) | ((instance) << MAXPORTS_PER_DEVICE_SHIFT) | (outline)) 278 279#define USBSER_MINOR2INST(minor) \ 280 (((minor) & ~(OUTLINE | MAXPORTS_PER_DEVICE_MASK)) \ 281 >> MAXPORTS_PER_DEVICE_SHIFT) 282 283#define USBSER_MINOR2PORT(minor) ((minor) & MAXPORTS_PER_DEVICE_MASK) 284 285/* 286 * various tunables 287 * 288 * timeouts are in seconds 289 */ 290enum { 291 USBSER_TX_FIFO_DRAIN_TIMEOUT = 5, /* tx fifo drain timeout */ 292 USBSER_WQ_DRAIN_TIMEOUT = 2, /* wq drain timeout */ 293 USBSER_SUSPEND_TIMEOUT = 10 /* cpr suspend timeout */ 294}; 295 296/* 297 * debug printing masks 298 */ 299#define DPRINT_ATTACH 0x00000001 300#define DPRINT_DETACH 0x00000002 301#define DPRINT_OPEN 0x00000004 302#define DPRINT_CLOSE 0x00000008 303#define DPRINT_WQ 0x00000010 304#define DPRINT_RQ 0x00000020 305#define DPRINT_IOCTL 0x00000040 306#define DPRINT_RX_CB 0x00000100 307#define DPRINT_TX_CB 0x00000200 308#define DPRINT_STATUS_CB 0x00000400 309#define DPRINT_EVENTS 0x00001000 310#define DPRINT_CPR 0x00002000 311#define DPRINT_MASK_ALL 0xFFFFFFFF 312 313/* 314 * misc macros 315 */ 316#define NELEM(a) (sizeof (a) / sizeof (*(a))) 317 318/* 319 * shortcuts to DSD operations 320 */ 321#define USBSER_DS_ATTACH(usp, aip) usp->us_ds_ops->ds_attach(aip) 322 323#define USBSER_DS_DETACH(usp) usp->us_ds_ops->ds_detach(usp->us_ds_hdl) 324 325#define USBSER_DS_OPEN_PORT(usp, port_num) \ 326 usp->us_ds_ops->ds_open_port(usp->us_ds_hdl, port_num) 327 328#define USBSER_DS_CLOSE_PORT(usp, port_num) \ 329 usp->us_ds_ops->ds_close_port(usp->us_ds_hdl, port_num) 330 331#define USBSER_DS_REGISTER_CB(usp, port_num, cb) \ 332 usp->us_ds_ops->ds_register_cb(usp->us_ds_hdl, port_num, cb) 333 334#define USBSER_DS_UNREGISTER_CB(usp, port_num) \ 335 usp->us_ds_ops->ds_unregister_cb(usp->us_ds_hdl, port_num) 336 337/* power management */ 338#define USBSER_DS_USB_POWER(usp, comp, level, new_statep) \ 339 usp->us_ds_ops->ds_usb_power(usp->us_ds_hdl, comp, level, new_statep) 340 341#define USBSER_DS_SUSPEND(usp) usp->us_ds_ops->ds_suspend(usp->us_ds_hdl) 342 343#define USBSER_DS_RESUME(usp) usp->us_ds_ops->ds_resume(usp->us_ds_hdl) 344 345#define USBSER_DS_DISCONNECT(usp) usp->us_ds_ops->ds_disconnect(usp->us_ds_hdl) 346 347#define USBSER_DS_RECONNECT(usp) usp->us_ds_ops->ds_reconnect(usp->us_ds_hdl) 348 349/* standard UART operations */ 350#define USBSER_DS_SET_PORT_PARAMS(pp, params) \ 351 pp->port_ds_ops->ds_set_port_params(pp->port_ds_hdl, pp->port_num, \ 352 params) 353 354#define USBSER_DS_SET_MODEM_CTL(pp, mask, val) \ 355 pp->port_ds_ops->ds_set_modem_ctl(pp->port_ds_hdl, pp->port_num, mask, \ 356 val) 357 358#define USBSER_DS_GET_MODEM_CTL(pp, mask, valp) \ 359 pp->port_ds_ops->ds_get_modem_ctl(pp->port_ds_hdl, pp->port_num, \ 360 mask, valp) 361 362#define USBSER_DS_BREAK_CTL(pp, val) \ 363 pp->port_ds_ops->ds_break_ctl(pp->port_ds_hdl, pp->port_num, val) 364 365#define USBSER_DS_LOOPBACK(pp, val) \ 366 pp->port_ds_ops->ds_loopback(pp->port_ds_hdl, pp->port_num, val) 367 368/* data xfer */ 369#define USBSER_DS_TX(pp, mp) \ 370 pp->port_ds_ops->ds_tx(pp->port_ds_hdl, pp->port_num, mp) 371 372#define USBSER_DS_RX(pp) \ 373 pp->port_ds_ops->ds_rx(pp->port_ds_hdl, pp->port_num) 374 375#define USBSER_DS_STOP(pp, dir) \ 376 pp->port_ds_ops->ds_stop(pp->port_ds_hdl, pp->port_num, dir) 377 378#define USBSER_DS_START(pp, dir) \ 379 pp->port_ds_ops->ds_start(pp->port_ds_hdl, pp->port_num, dir) 380 381/* fifos */ 382#define USBSER_DS_FIFO_FLUSH(pp, mask) \ 383 pp->port_ds_ops->ds_fifo_flush(pp->port_ds_hdl, pp->port_num, mask) 384 385#define USBSER_DS_FIFO_DRAIN(pp, tmout) \ 386 pp->port_ds_ops->ds_fifo_drain(pp->port_ds_hdl, pp->port_num, tmout) 387 388 389/* check for supported operations */ 390#define USBSER_DS_LOOPBACK_SUPPORTED(pp) (pp->port_ds_ops->ds_loopback != 0) 391 392#ifdef __cplusplus 393} 394#endif 395 396#endif /* _SYS_USB_USBSER_VAR_H */ 397