Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Driver for ST5481 USB ISDN modem |
| 3 | * |
| 4 | * Author Frode Isaksen |
| 5 | * Copyright 2001 by Frode Isaksen <fisaksen@bewan.com> |
| 6 | * 2001 by Kai Germaschewski <kai.germaschewski@gmx.de> |
Joe Perches | 475be4d | 2012-02-19 19:52:38 -0800 | [diff] [blame] | 7 | * |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 8 | * This software may be used and distributed according to the terms |
| 9 | * of the GNU General Public License, incorporated herein by reference. |
| 10 | * |
| 11 | */ |
| 12 | |
| 13 | #ifndef _ST5481_H_ |
| 14 | #define _ST5481_H_ |
| 15 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 16 | |
| 17 | // USB IDs, the Product Id is in the range 0x4810-0x481F |
| 18 | |
| 19 | #define ST_VENDOR_ID 0x0483 |
| 20 | #define ST5481_PRODUCT_ID 0x4810 |
| 21 | #define ST5481_PRODUCT_ID_MASK 0xFFF0 |
| 22 | |
| 23 | // ST5481 endpoints when using alternative setting 3 (2B+D). |
| 24 | // To get the endpoint address, OR with 0x80 for IN endpoints. |
| 25 | |
| 26 | #define EP_CTRL 0x00U /* Control endpoint */ |
| 27 | #define EP_INT 0x01U /* Interrupt endpoint */ |
| 28 | #define EP_B1_OUT 0x02U /* B1 channel out */ |
| 29 | #define EP_B1_IN 0x03U /* B1 channel in */ |
| 30 | #define EP_B2_OUT 0x04U /* B2 channel out */ |
| 31 | #define EP_B2_IN 0x05U /* B2 channel in */ |
| 32 | #define EP_D_OUT 0x06U /* D channel out */ |
| 33 | #define EP_D_IN 0x07U /* D channel in */ |
Joe Perches | 475be4d | 2012-02-19 19:52:38 -0800 | [diff] [blame] | 34 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 35 | // Number of isochronous packets. With 20 packets we get |
| 36 | // 50 interrupts/sec for each endpoint. |
| 37 | |
| 38 | #define NUM_ISO_PACKETS_D 20 |
| 39 | #define NUM_ISO_PACKETS_B 20 |
| 40 | |
| 41 | // Size of each isochronous packet. |
| 42 | // In outgoing direction we need to match ISDN data rates: |
| 43 | // D: 2 bytes / msec -> 16 kbit / s |
| 44 | // B: 16 bytes / msec -> 64 kbit / s |
| 45 | #define SIZE_ISO_PACKETS_D_IN 16 |
| 46 | #define SIZE_ISO_PACKETS_D_OUT 2 |
| 47 | #define SIZE_ISO_PACKETS_B_IN 32 |
| 48 | #define SIZE_ISO_PACKETS_B_OUT 8 |
| 49 | |
| 50 | // If we overrun/underrun, we send one packet with +/- 2 bytes |
| 51 | #define B_FLOW_ADJUST 2 |
| 52 | |
| 53 | // Registers that are written using vendor specific device request |
Joe Perches | 475be4d | 2012-02-19 19:52:38 -0800 | [diff] [blame] | 54 | // on endpoint 0. |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 55 | |
| 56 | #define LBA 0x02 /* S loopback */ |
| 57 | #define SET_DEFAULT 0x06 /* Soft reset */ |
| 58 | #define LBB 0x1D /* S maintenance loopback */ |
| 59 | #define STT 0x1e /* S force transmission signals */ |
| 60 | #define SDA_MIN 0x20 /* SDA-sin minimal value */ |
| 61 | #define SDA_MAX 0x21 /* SDA-sin maximal value */ |
| 62 | #define SDELAY_VALUE 0x22 /* Delay between Tx and Rx clock */ |
| 63 | #define IN_D_COUNTER 0x36 /* D receive channel fifo counter */ |
| 64 | #define OUT_D_COUNTER 0x37 /* D transmit channel fifo counter */ |
| 65 | #define IN_B1_COUNTER 0x38 /* B1 receive channel fifo counter */ |
| 66 | #define OUT_B1_COUNTER 0x39 /* B1 transmit channel fifo counter */ |
| 67 | #define IN_B2_COUNTER 0x3a /* B2 receive channel fifo counter */ |
| 68 | #define OUT_B2_COUNTER 0x3b /* B2 transmit channel fifo counter */ |
| 69 | #define FFCTRL_IN_D 0x3C /* D receive channel fifo threshold low */ |
| 70 | #define FFCTRH_IN_D 0x3D /* D receive channel fifo threshold high */ |
| 71 | #define FFCTRL_OUT_D 0x3E /* D transmit channel fifo threshold low */ |
| 72 | #define FFCTRH_OUT_D 0x3F /* D transmit channel fifo threshold high */ |
| 73 | #define FFCTRL_IN_B1 0x40 /* B1 receive channel fifo threshold low */ |
| 74 | #define FFCTRH_IN_B1 0x41 /* B1 receive channel fifo threshold high */ |
| 75 | #define FFCTRL_OUT_B1 0x42 /* B1 transmit channel fifo threshold low */ |
| 76 | #define FFCTRH_OUT_B1 0x43 /* B1 transmit channel fifo threshold high */ |
| 77 | #define FFCTRL_IN_B2 0x44 /* B2 receive channel fifo threshold low */ |
| 78 | #define FFCTRH_IN_B2 0x45 /* B2 receive channel fifo threshold high */ |
| 79 | #define FFCTRL_OUT_B2 0x46 /* B2 transmit channel fifo threshold low */ |
| 80 | #define FFCTRH_OUT_B2 0x47 /* B2 transmit channel fifo threshold high */ |
| 81 | #define MPMSK 0x4A /* Multi purpose interrupt MASK register */ |
| 82 | #define FFMSK_D 0x4c /* D fifo interrupt MASK register */ |
| 83 | #define FFMSK_B1 0x4e /* B1 fifo interrupt MASK register */ |
| 84 | #define FFMSK_B2 0x50 /* B2 fifo interrupt MASK register */ |
| 85 | #define GPIO_DIR 0x52 /* GPIO pins direction registers */ |
| 86 | #define GPIO_OUT 0x53 /* GPIO pins output register */ |
Joe Perches | 475be4d | 2012-02-19 19:52:38 -0800 | [diff] [blame] | 87 | #define GPIO_IN 0x54 /* GPIO pins input register */ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 88 | #define TXCI 0x56 /* CI command to be transmitted */ |
| 89 | |
| 90 | |
| 91 | // Format of the interrupt packet received on endpoint 1: |
| 92 | // |
| 93 | // +--------+--------+--------+--------+--------+--------+ |
| 94 | // !MPINT !FFINT_D !FFINT_B1!FFINT_B2!CCIST !GPIO_INT! |
| 95 | // +--------+--------+--------+--------+--------+--------+ |
| 96 | |
| 97 | // Offsets in the interrupt packet |
| 98 | |
| 99 | #define MPINT 0 |
| 100 | #define FFINT_D 1 |
| 101 | #define FFINT_B1 2 |
| 102 | #define FFINT_B2 3 |
| 103 | #define CCIST 4 |
| 104 | #define GPIO_INT 5 |
| 105 | #define INT_PKT_SIZE 6 |
| 106 | |
| 107 | // MPINT |
| 108 | #define LSD_INT 0x80 /* S line activity detected */ |
| 109 | #define RXCI_INT 0x40 /* Indicate primitive arrived */ |
| 110 | #define DEN_INT 0x20 /* Signal enabling data out of D Tx fifo */ |
| 111 | #define DCOLL_INT 0x10 /* D channel collision */ |
| 112 | #define AMIVN_INT 0x04 /* AMI violation number reached 2 */ |
| 113 | #define INFOI_INT 0x04 /* INFOi changed */ |
| 114 | #define DRXON_INT 0x02 /* Reception channel active */ |
| 115 | #define GPCHG_INT 0x01 /* GPIO pin value changed */ |
| 116 | |
| 117 | // FFINT_x |
| 118 | #define IN_OVERRUN 0x80 /* In fifo overrun */ |
| 119 | #define OUT_UNDERRUN 0x40 /* Out fifo underrun */ |
| 120 | #define IN_UP 0x20 /* In fifo thresholdh up-crossed */ |
| 121 | #define IN_DOWN 0x10 /* In fifo thresholdl down-crossed */ |
| 122 | #define OUT_UP 0x08 /* Out fifo thresholdh up-crossed */ |
| 123 | #define OUT_DOWN 0x04 /* Out fifo thresholdl down-crossed */ |
| 124 | #define IN_COUNTER_ZEROED 0x02 /* In down-counter reached 0 */ |
| 125 | #define OUT_COUNTER_ZEROED 0x01 /* Out down-counter reached 0 */ |
| 126 | |
Joe Perches | 475be4d | 2012-02-19 19:52:38 -0800 | [diff] [blame] | 127 | #define ANY_REC_INT (IN_OVERRUN + IN_UP + IN_DOWN + IN_COUNTER_ZEROED) |
| 128 | #define ANY_XMIT_INT (OUT_UNDERRUN + OUT_UP + OUT_DOWN + OUT_COUNTER_ZEROED) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 129 | |
| 130 | |
| 131 | // Level 1 commands that are sent using the TXCI device request |
| 132 | #define ST5481_CMD_DR 0x0 /* Deactivation Request */ |
| 133 | #define ST5481_CMD_RES 0x1 /* state machine RESet */ |
| 134 | #define ST5481_CMD_TM1 0x2 /* Test Mode 1 */ |
| 135 | #define ST5481_CMD_TM2 0x3 /* Test Mode 2 */ |
| 136 | #define ST5481_CMD_PUP 0x7 /* Power UP */ |
| 137 | #define ST5481_CMD_AR8 0x8 /* Activation Request class 1 */ |
| 138 | #define ST5481_CMD_AR10 0x9 /* Activation Request class 2 */ |
| 139 | #define ST5481_CMD_ARL 0xA /* Activation Request Loopback */ |
| 140 | #define ST5481_CMD_PDN 0xF /* Power DoWn */ |
| 141 | |
| 142 | // Turn on/off the LEDs using the GPIO device request. |
| 143 | // To use the B LEDs, number_of_leds must be set to 4 |
| 144 | #define B1_LED 0x10U |
| 145 | #define B2_LED 0x20U |
| 146 | #define GREEN_LED 0x40U |
| 147 | #define RED_LED 0x80U |
| 148 | |
| 149 | // D channel out states |
| 150 | enum { |
| 151 | ST_DOUT_NONE, |
| 152 | |
| 153 | ST_DOUT_SHORT_INIT, |
| 154 | ST_DOUT_SHORT_WAIT_DEN, |
| 155 | |
| 156 | ST_DOUT_LONG_INIT, |
| 157 | ST_DOUT_LONG_WAIT_DEN, |
| 158 | ST_DOUT_NORMAL, |
| 159 | |
| 160 | ST_DOUT_WAIT_FOR_UNDERRUN, |
Joe Perches | 475be4d | 2012-02-19 19:52:38 -0800 | [diff] [blame] | 161 | ST_DOUT_WAIT_FOR_NOT_BUSY, |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 162 | ST_DOUT_WAIT_FOR_STOP, |
| 163 | ST_DOUT_WAIT_FOR_RESET, |
| 164 | }; |
| 165 | |
| 166 | #define DOUT_STATE_COUNT (ST_DOUT_WAIT_FOR_RESET + 1) |
| 167 | |
| 168 | // D channel out events |
| 169 | enum { |
| 170 | EV_DOUT_START_XMIT, |
| 171 | EV_DOUT_COMPLETE, |
| 172 | EV_DOUT_DEN, |
| 173 | EV_DOUT_RESETED, |
| 174 | EV_DOUT_STOPPED, |
| 175 | EV_DOUT_COLL, |
| 176 | EV_DOUT_UNDERRUN, |
| 177 | }; |
| 178 | |
| 179 | #define DOUT_EVENT_COUNT (EV_DOUT_UNDERRUN + 1) |
| 180 | |
| 181 | // ---------------------------------------------------------------------- |
| 182 | |
| 183 | enum { |
| 184 | ST_L1_F3, |
| 185 | ST_L1_F4, |
| 186 | ST_L1_F6, |
| 187 | ST_L1_F7, |
| 188 | ST_L1_F8, |
| 189 | }; |
| 190 | |
Joe Perches | 475be4d | 2012-02-19 19:52:38 -0800 | [diff] [blame] | 191 | #define L1_STATE_COUNT (ST_L1_F8 + 1) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 192 | |
Joe Perches | 475be4d | 2012-02-19 19:52:38 -0800 | [diff] [blame] | 193 | // The first 16 entries match the Level 1 indications that |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 194 | // are found at offset 4 (CCIST) in the interrupt packet |
| 195 | |
| 196 | enum { |
| 197 | EV_IND_DP, // 0000 Deactivation Pending |
| 198 | EV_IND_1, // 0001 |
| 199 | EV_IND_2, // 0010 |
| 200 | EV_IND_3, // 0011 |
| 201 | EV_IND_RSY, // 0100 ReSYnchronizing |
| 202 | EV_IND_5, // 0101 |
| 203 | EV_IND_6, // 0110 |
| 204 | EV_IND_7, // 0111 |
| 205 | EV_IND_AP, // 1000 Activation Pending |
| 206 | EV_IND_9, // 1001 |
| 207 | EV_IND_10, // 1010 |
| 208 | EV_IND_11, // 1011 |
| 209 | EV_IND_AI8, // 1100 Activation Indication class 8 |
| 210 | EV_IND_AI10,// 1101 Activation Indication class 10 |
| 211 | EV_IND_AIL, // 1110 Activation Indication Loopback |
| 212 | EV_IND_DI, // 1111 Deactivation Indication |
| 213 | EV_PH_ACTIVATE_REQ, |
| 214 | EV_PH_DEACTIVATE_REQ, |
| 215 | EV_TIMER3, |
| 216 | }; |
| 217 | |
| 218 | #define L1_EVENT_COUNT (EV_TIMER3 + 1) |
| 219 | |
Joe Perches | 475be4d | 2012-02-19 19:52:38 -0800 | [diff] [blame] | 220 | #define ERR(format, arg...) \ |
| 221 | printk(KERN_ERR "%s:%s: " format "\n" , __FILE__, __func__ , ## arg) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 222 | |
Joe Perches | 475be4d | 2012-02-19 19:52:38 -0800 | [diff] [blame] | 223 | #define WARNING(format, arg...) \ |
| 224 | printk(KERN_WARNING "%s:%s: " format "\n" , __FILE__, __func__ , ## arg) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 225 | |
Joe Perches | 475be4d | 2012-02-19 19:52:38 -0800 | [diff] [blame] | 226 | #define INFO(format, arg...) \ |
| 227 | printk(KERN_INFO "%s:%s: " format "\n" , __FILE__, __func__ , ## arg) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 228 | |
Karsten Keil | cb3824b | 2009-07-08 14:21:12 +0200 | [diff] [blame] | 229 | #include <linux/isdn/hdlc.h> |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 230 | #include "fsm.h" |
| 231 | #include "hisax_if.h" |
| 232 | #include <linux/skbuff.h> |
| 233 | |
| 234 | /* ====================================================================== |
| 235 | * FIFO handling |
| 236 | */ |
| 237 | |
| 238 | /* Generic FIFO structure */ |
| 239 | struct fifo { |
Joe Perches | 475be4d | 2012-02-19 19:52:38 -0800 | [diff] [blame] | 240 | u_char r, w, count, size; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 241 | spinlock_t lock; |
| 242 | }; |
| 243 | |
| 244 | /* |
| 245 | * Init an FIFO |
| 246 | */ |
| 247 | static inline void fifo_init(struct fifo *fifo, int size) |
| 248 | { |
| 249 | fifo->r = fifo->w = fifo->count = 0; |
| 250 | fifo->size = size; |
| 251 | spin_lock_init(&fifo->lock); |
| 252 | } |
| 253 | |
| 254 | /* |
| 255 | * Add an entry to the FIFO |
| 256 | */ |
| 257 | static inline int fifo_add(struct fifo *fifo) |
| 258 | { |
| 259 | unsigned long flags; |
| 260 | int index; |
| 261 | |
| 262 | if (!fifo) { |
| 263 | return -1; |
| 264 | } |
| 265 | |
| 266 | spin_lock_irqsave(&fifo->lock, flags); |
| 267 | if (fifo->count == fifo->size) { |
| 268 | // FIFO full |
| 269 | index = -1; |
| 270 | } else { |
| 271 | // Return index where to get the next data to add to the FIFO |
Joe Perches | 475be4d | 2012-02-19 19:52:38 -0800 | [diff] [blame] | 272 | index = fifo->w++ & (fifo->size - 1); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 273 | fifo->count++; |
| 274 | } |
| 275 | spin_unlock_irqrestore(&fifo->lock, flags); |
| 276 | return index; |
| 277 | } |
| 278 | |
| 279 | /* |
| 280 | * Remove an entry from the FIFO with the index returned. |
| 281 | */ |
| 282 | static inline int fifo_remove(struct fifo *fifo) |
| 283 | { |
| 284 | unsigned long flags; |
| 285 | int index; |
| 286 | |
| 287 | if (!fifo) { |
| 288 | return -1; |
| 289 | } |
| 290 | |
| 291 | spin_lock_irqsave(&fifo->lock, flags); |
| 292 | if (!fifo->count) { |
| 293 | // FIFO empty |
| 294 | index = -1; |
| 295 | } else { |
| 296 | // Return index where to get the next data from the FIFO |
Joe Perches | 475be4d | 2012-02-19 19:52:38 -0800 | [diff] [blame] | 297 | index = fifo->r++ & (fifo->size - 1); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 298 | fifo->count--; |
| 299 | } |
| 300 | spin_unlock_irqrestore(&fifo->lock, flags); |
| 301 | |
| 302 | return index; |
| 303 | } |
| 304 | |
| 305 | /* ====================================================================== |
| 306 | * control pipe |
| 307 | */ |
| 308 | typedef void (*ctrl_complete_t)(void *); |
| 309 | |
| 310 | typedef struct ctrl_msg { |
| 311 | struct usb_ctrlrequest dr; |
| 312 | ctrl_complete_t complete; |
| 313 | void *context; |
Joe Perches | 475be4d | 2012-02-19 19:52:38 -0800 | [diff] [blame] | 314 | } ctrl_msg; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 315 | |
| 316 | /* FIFO of ctrl messages waiting to be sent */ |
| 317 | #define MAX_EP0_MSG 16 |
| 318 | struct ctrl_msg_fifo { |
| 319 | struct fifo f; |
| 320 | struct ctrl_msg data[MAX_EP0_MSG]; |
Joe Perches | 475be4d | 2012-02-19 19:52:38 -0800 | [diff] [blame] | 321 | }; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 322 | |
| 323 | #define MAX_DFRAME_LEN_L1 300 |
| 324 | #define HSCX_BUFMAX 4096 |
| 325 | |
| 326 | struct st5481_ctrl { |
| 327 | struct ctrl_msg_fifo msg_fifo; |
| 328 | unsigned long busy; |
| 329 | struct urb *urb; |
| 330 | }; |
| 331 | |
| 332 | struct st5481_intr { |
Joe Perches | 475be4d | 2012-02-19 19:52:38 -0800 | [diff] [blame] | 333 | // struct evt_fifo evt_fifo; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 334 | struct urb *urb; |
| 335 | }; |
| 336 | |
| 337 | struct st5481_d_out { |
| 338 | struct isdnhdlc_vars hdlc_state; |
| 339 | struct urb *urb[2]; /* double buffering */ |
| 340 | unsigned long busy; |
| 341 | struct sk_buff *tx_skb; |
| 342 | struct FsmInst fsm; |
| 343 | }; |
| 344 | |
| 345 | struct st5481_b_out { |
| 346 | struct isdnhdlc_vars hdlc_state; |
| 347 | struct urb *urb[2]; /* double buffering */ |
| 348 | u_char flow_event; |
| 349 | u_long busy; |
| 350 | struct sk_buff *tx_skb; |
| 351 | }; |
| 352 | |
| 353 | struct st5481_in { |
| 354 | struct isdnhdlc_vars hdlc_state; |
| 355 | struct urb *urb[2]; /* double buffering */ |
| 356 | int mode; |
| 357 | int bufsize; |
| 358 | unsigned int num_packets; |
| 359 | unsigned int packet_size; |
| 360 | unsigned char ep, counter; |
| 361 | unsigned char *rcvbuf; |
| 362 | struct st5481_adapter *adapter; |
| 363 | struct hisax_if *hisax_if; |
| 364 | }; |
| 365 | |
| 366 | int st5481_setup_in(struct st5481_in *in); |
| 367 | void st5481_release_in(struct st5481_in *in); |
| 368 | void st5481_in_mode(struct st5481_in *in, int mode); |
| 369 | |
| 370 | struct st5481_bcs { |
| 371 | struct hisax_b_if b_if; |
| 372 | struct st5481_adapter *adapter; |
| 373 | struct st5481_in b_in; |
| 374 | struct st5481_b_out b_out; |
| 375 | int channel; |
| 376 | int mode; |
| 377 | }; |
| 378 | |
| 379 | struct st5481_adapter { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 380 | int number_of_leds; |
| 381 | struct usb_device *usb_dev; |
| 382 | struct hisax_d_if hisax_d_if; |
| 383 | |
| 384 | struct st5481_ctrl ctrl; |
| 385 | struct st5481_intr intr; |
| 386 | struct st5481_in d_in; |
| 387 | struct st5481_d_out d_out; |
| 388 | |
| 389 | unsigned char leds; |
| 390 | unsigned int led_counter; |
| 391 | |
| 392 | unsigned long event; |
| 393 | |
| 394 | struct FsmInst l1m; |
| 395 | struct FsmTimer timer; |
| 396 | |
| 397 | struct st5481_bcs bcs[2]; |
| 398 | }; |
| 399 | |
| 400 | #define TIMER3_VALUE 7000 |
| 401 | |
| 402 | /* ====================================================================== |
| 403 | * |
| 404 | */ |
| 405 | |
| 406 | /* |
| 407 | * Submit an URB with error reporting. This is a macro so |
Harvey Harrison | 156f1ed | 2008-04-28 02:14:40 -0700 | [diff] [blame] | 408 | * the __func__ returns the caller function name. |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 409 | */ |
Joe Perches | 475be4d | 2012-02-19 19:52:38 -0800 | [diff] [blame] | 410 | #define SUBMIT_URB(urb, mem_flags) \ |
| 411 | ({ \ |
| 412 | int status; \ |
| 413 | if ((status = usb_submit_urb(urb, mem_flags)) < 0) { \ |
| 414 | WARNING("usb_submit_urb failed,status=%d", status); \ |
| 415 | } \ |
| 416 | status; \ |
| 417 | }) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 418 | |
| 419 | /* |
| 420 | * USB double buffering, return the URB index (0 or 1). |
| 421 | */ |
| 422 | static inline int get_buf_nr(struct urb *urbs[], struct urb *urb) |
| 423 | { |
Joe Perches | 475be4d | 2012-02-19 19:52:38 -0800 | [diff] [blame] | 424 | return (urbs[0] == urb ? 0 : 1); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 425 | } |
| 426 | |
| 427 | /* ---------------------------------------------------------------------- */ |
| 428 | |
| 429 | /* B Channel */ |
| 430 | |
| 431 | int st5481_setup_b(struct st5481_bcs *bcs); |
| 432 | void st5481_release_b(struct st5481_bcs *bcs); |
| 433 | void st5481_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg); |
| 434 | |
| 435 | /* D Channel */ |
| 436 | |
| 437 | int st5481_setup_d(struct st5481_adapter *adapter); |
| 438 | void st5481_release_d(struct st5481_adapter *adapter); |
| 439 | void st5481_b_l2l1(struct hisax_if *b_if, int pr, void *arg); |
| 440 | int st5481_d_init(void); |
| 441 | void st5481_d_exit(void); |
| 442 | |
| 443 | /* USB */ |
| 444 | void st5481_ph_command(struct st5481_adapter *adapter, unsigned int command); |
Joe Perches | 475be4d | 2012-02-19 19:52:38 -0800 | [diff] [blame] | 445 | int st5481_setup_isocpipes(struct urb *urb[2], struct usb_device *dev, |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 446 | unsigned int pipe, int num_packets, |
| 447 | int packet_size, int buf_size, |
| 448 | usb_complete_t complete, void *context); |
Joe Perches | 475be4d | 2012-02-19 19:52:38 -0800 | [diff] [blame] | 449 | void st5481_release_isocpipes(struct urb *urb[2]); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 450 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 451 | void st5481_usb_pipe_reset(struct st5481_adapter *adapter, |
Joe Perches | 475be4d | 2012-02-19 19:52:38 -0800 | [diff] [blame] | 452 | u_char pipe, ctrl_complete_t complete, void *context); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 453 | void st5481_usb_device_ctrl_msg(struct st5481_adapter *adapter, |
Joe Perches | 475be4d | 2012-02-19 19:52:38 -0800 | [diff] [blame] | 454 | u8 request, u16 value, |
| 455 | ctrl_complete_t complete, void *context); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 456 | int st5481_setup_usb(struct st5481_adapter *adapter); |
| 457 | void st5481_release_usb(struct st5481_adapter *adapter); |
| 458 | void st5481_start(struct st5481_adapter *adapter); |
| 459 | void st5481_stop(struct st5481_adapter *adapter); |
| 460 | |
| 461 | // ---------------------------------------------------------------------- |
| 462 | // debugging macros |
| 463 | |
| 464 | #define __debug_variable st5481_debug |
| 465 | #include "hisax_debug.h" |
| 466 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 467 | extern int st5481_debug; |
| 468 | |
Karsten Keil | 61ffcaf | 2005-09-17 23:52:42 +0200 | [diff] [blame] | 469 | #ifdef CONFIG_HISAX_DEBUG |
| 470 | |
Joe Perches | 475be4d | 2012-02-19 19:52:38 -0800 | [diff] [blame] | 471 | #define DBG_ISO_PACKET(level, urb) \ |
| 472 | if (level & __debug_variable) dump_iso_packet(__func__, urb) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 473 | |
| 474 | static void __attribute__((unused)) |
| 475 | dump_iso_packet(const char *name, struct urb *urb) |
| 476 | { |
Joe Perches | 475be4d | 2012-02-19 19:52:38 -0800 | [diff] [blame] | 477 | int i, j; |
| 478 | int len, ofs; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 479 | u_char *data; |
| 480 | |
| 481 | printk(KERN_DEBUG "%s: packets=%d,errors=%d\n", |
Joe Perches | 475be4d | 2012-02-19 19:52:38 -0800 | [diff] [blame] | 482 | name, urb->number_of_packets, urb->error_count); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 483 | for (i = 0; i < urb->number_of_packets; ++i) { |
| 484 | if (urb->pipe & USB_DIR_IN) { |
| 485 | len = urb->iso_frame_desc[i].actual_length; |
| 486 | } else { |
| 487 | len = urb->iso_frame_desc[i].length; |
| 488 | } |
| 489 | ofs = urb->iso_frame_desc[i].offset; |
Joe Perches | 475be4d | 2012-02-19 19:52:38 -0800 | [diff] [blame] | 490 | printk(KERN_DEBUG "len=%.2d,ofs=%.3d ", len, ofs); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 491 | if (len) { |
Joe Perches | 475be4d | 2012-02-19 19:52:38 -0800 | [diff] [blame] | 492 | data = urb->transfer_buffer + ofs; |
| 493 | for (j = 0; j < len; j++) { |
| 494 | printk("%.2x", data[j]); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 495 | } |
| 496 | } |
| 497 | printk("\n"); |
| 498 | } |
| 499 | } |
| 500 | |
| 501 | static inline const char *ST5481_CMD_string(int evt) |
| 502 | { |
| 503 | static char s[16]; |
| 504 | |
| 505 | switch (evt) { |
| 506 | case ST5481_CMD_DR: return "DR"; |
| 507 | case ST5481_CMD_RES: return "RES"; |
| 508 | case ST5481_CMD_TM1: return "TM1"; |
| 509 | case ST5481_CMD_TM2: return "TM2"; |
| 510 | case ST5481_CMD_PUP: return "PUP"; |
| 511 | case ST5481_CMD_AR8: return "AR8"; |
| 512 | case ST5481_CMD_AR10: return "AR10"; |
| 513 | case ST5481_CMD_ARL: return "ARL"; |
| 514 | case ST5481_CMD_PDN: return "PDN"; |
| 515 | }; |
Joe Perches | 475be4d | 2012-02-19 19:52:38 -0800 | [diff] [blame] | 516 | |
| 517 | sprintf(s, "0x%x", evt); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 518 | return s; |
Joe Perches | 475be4d | 2012-02-19 19:52:38 -0800 | [diff] [blame] | 519 | } |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 520 | |
| 521 | #else |
| 522 | |
Joe Perches | 475be4d | 2012-02-19 19:52:38 -0800 | [diff] [blame] | 523 | #define DBG_ISO_PACKET(level, urb) do {} while (0) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 524 | |
| 525 | #endif |
| 526 | |
| 527 | |
| 528 | |
Joe Perches | 475be4d | 2012-02-19 19:52:38 -0800 | [diff] [blame] | 529 | #endif |