| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Driver for ST5481 USB ISDN modem | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Author       Frode Isaksen | 
					
						
							|  |  |  |  * Copyright    2001 by Frode Isaksen      <fisaksen@bewan.com> | 
					
						
							|  |  |  |  *              2001 by Kai Germaschewski  <kai.germaschewski@gmx.de> | 
					
						
							|  |  |  |  *  | 
					
						
							|  |  |  |  * This software may be used and distributed according to the terms | 
					
						
							|  |  |  |  * of the GNU General Public License, incorporated herein by reference. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef _ST5481_H_
 | 
					
						
							|  |  |  | #define _ST5481_H_
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // USB IDs, the Product Id is in the range 0x4810-0x481F
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define ST_VENDOR_ID 0x0483
 | 
					
						
							|  |  |  | #define ST5481_PRODUCT_ID 0x4810
 | 
					
						
							|  |  |  | #define ST5481_PRODUCT_ID_MASK 0xFFF0
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ST5481 endpoints when using alternative setting 3 (2B+D).
 | 
					
						
							|  |  |  | // To get the endpoint address, OR with 0x80 for IN endpoints.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define EP_CTRL   0x00U /* Control endpoint */
 | 
					
						
							|  |  |  | #define EP_INT    0x01U /* Interrupt endpoint */
 | 
					
						
							|  |  |  | #define EP_B1_OUT 0x02U /* B1 channel out */
 | 
					
						
							|  |  |  | #define EP_B1_IN  0x03U /* B1 channel in */
 | 
					
						
							|  |  |  | #define EP_B2_OUT 0x04U /* B2 channel out */
 | 
					
						
							|  |  |  | #define EP_B2_IN  0x05U /* B2 channel in */
 | 
					
						
							|  |  |  | #define EP_D_OUT  0x06U /* D channel out */
 | 
					
						
							|  |  |  | #define EP_D_IN   0x07U /* D channel in */
 | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  | // Number of isochronous packets. With 20 packets we get
 | 
					
						
							|  |  |  | // 50 interrupts/sec for each endpoint.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define NUM_ISO_PACKETS_D      20
 | 
					
						
							|  |  |  | #define NUM_ISO_PACKETS_B      20
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Size of each isochronous packet.
 | 
					
						
							|  |  |  | // In outgoing direction we need to match ISDN data rates:
 | 
					
						
							|  |  |  | // D:  2 bytes / msec -> 16 kbit / s
 | 
					
						
							|  |  |  | // B: 16 bytes / msec -> 64 kbit / s
 | 
					
						
							|  |  |  | #define SIZE_ISO_PACKETS_D_IN  16
 | 
					
						
							|  |  |  | #define SIZE_ISO_PACKETS_D_OUT 2
 | 
					
						
							|  |  |  | #define SIZE_ISO_PACKETS_B_IN  32
 | 
					
						
							|  |  |  | #define SIZE_ISO_PACKETS_B_OUT 8
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // If we overrun/underrun, we send one packet with +/- 2 bytes
 | 
					
						
							|  |  |  | #define B_FLOW_ADJUST 2
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Registers that are written using vendor specific device request
 | 
					
						
							|  |  |  | // on endpoint 0. 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define LBA			0x02 /* S loopback */
 | 
					
						
							|  |  |  | #define SET_DEFAULT		0x06 /* Soft reset */
 | 
					
						
							|  |  |  | #define LBB			0x1D /* S maintenance loopback */
 | 
					
						
							|  |  |  | #define STT			0x1e /* S force transmission signals */
 | 
					
						
							|  |  |  | #define SDA_MIN			0x20 /* SDA-sin minimal value */
 | 
					
						
							|  |  |  | #define SDA_MAX			0x21 /* SDA-sin maximal value */
 | 
					
						
							|  |  |  | #define SDELAY_VALUE		0x22 /* Delay between Tx and Rx clock */
 | 
					
						
							|  |  |  | #define IN_D_COUNTER		0x36 /* D receive channel fifo counter */
 | 
					
						
							|  |  |  | #define OUT_D_COUNTER		0x37 /* D transmit channel fifo counter */
 | 
					
						
							|  |  |  | #define IN_B1_COUNTER		0x38 /* B1 receive channel fifo counter */
 | 
					
						
							|  |  |  | #define OUT_B1_COUNTER		0x39 /* B1 transmit channel fifo counter */
 | 
					
						
							|  |  |  | #define IN_B2_COUNTER		0x3a /* B2 receive channel fifo counter */
 | 
					
						
							|  |  |  | #define OUT_B2_COUNTER		0x3b /* B2 transmit channel fifo counter */
 | 
					
						
							|  |  |  | #define FFCTRL_IN_D		0x3C /* D receive channel fifo threshold low */
 | 
					
						
							|  |  |  | #define FFCTRH_IN_D		0x3D /* D receive channel fifo threshold high */
 | 
					
						
							|  |  |  | #define FFCTRL_OUT_D		0x3E /* D transmit channel fifo threshold low */
 | 
					
						
							|  |  |  | #define FFCTRH_OUT_D		0x3F /* D transmit channel fifo threshold high */
 | 
					
						
							|  |  |  | #define FFCTRL_IN_B1		0x40 /* B1 receive channel fifo threshold low */
 | 
					
						
							|  |  |  | #define FFCTRH_IN_B1		0x41 /* B1 receive channel fifo threshold high */
 | 
					
						
							|  |  |  | #define FFCTRL_OUT_B1		0x42 /* B1 transmit channel fifo threshold low */
 | 
					
						
							|  |  |  | #define FFCTRH_OUT_B1		0x43 /* B1 transmit channel fifo threshold high */
 | 
					
						
							|  |  |  | #define FFCTRL_IN_B2		0x44 /* B2 receive channel fifo threshold low */
 | 
					
						
							|  |  |  | #define FFCTRH_IN_B2		0x45 /* B2 receive channel fifo threshold high */
 | 
					
						
							|  |  |  | #define FFCTRL_OUT_B2		0x46 /* B2 transmit channel fifo threshold low */
 | 
					
						
							|  |  |  | #define FFCTRH_OUT_B2		0x47 /* B2 transmit channel fifo threshold high */
 | 
					
						
							|  |  |  | #define MPMSK			0x4A /* Multi purpose interrupt MASK register */
 | 
					
						
							|  |  |  | #define	FFMSK_D			0x4c /* D fifo interrupt MASK register */
 | 
					
						
							|  |  |  | #define	FFMSK_B1		0x4e /* B1 fifo interrupt MASK register */
 | 
					
						
							|  |  |  | #define	FFMSK_B2		0x50 /* B2 fifo interrupt MASK register */
 | 
					
						
							|  |  |  | #define GPIO_DIR		0x52 /* GPIO pins direction registers */
 | 
					
						
							|  |  |  | #define GPIO_OUT		0x53 /* GPIO pins output register */
 | 
					
						
							|  |  |  | #define GPIO_IN			0x54 /* GPIO pins input register */ 
 | 
					
						
							|  |  |  | #define TXCI			0x56 /* CI command to be transmitted */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Format of the interrupt packet received on endpoint 1:
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // +--------+--------+--------+--------+--------+--------+
 | 
					
						
							|  |  |  | // !MPINT   !FFINT_D !FFINT_B1!FFINT_B2!CCIST   !GPIO_INT!
 | 
					
						
							|  |  |  | // +--------+--------+--------+--------+--------+--------+
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Offsets in the interrupt packet
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define MPINT			0
 | 
					
						
							|  |  |  | #define FFINT_D			1
 | 
					
						
							|  |  |  | #define FFINT_B1		2
 | 
					
						
							|  |  |  | #define FFINT_B2		3
 | 
					
						
							|  |  |  | #define CCIST			4
 | 
					
						
							|  |  |  | #define GPIO_INT		5
 | 
					
						
							|  |  |  | #define INT_PKT_SIZE            6
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // MPINT
 | 
					
						
							|  |  |  | #define LSD_INT                 0x80 /* S line activity detected */
 | 
					
						
							|  |  |  | #define RXCI_INT		0x40 /* Indicate primitive arrived */
 | 
					
						
							|  |  |  | #define	DEN_INT			0x20 /* Signal enabling data out of D Tx fifo */
 | 
					
						
							|  |  |  | #define DCOLL_INT		0x10 /* D channel collision */
 | 
					
						
							|  |  |  | #define AMIVN_INT		0x04 /* AMI violation number reached 2 */
 | 
					
						
							|  |  |  | #define INFOI_INT		0x04 /* INFOi changed */
 | 
					
						
							|  |  |  | #define DRXON_INT               0x02 /* Reception channel active */
 | 
					
						
							|  |  |  | #define GPCHG_INT               0x01 /* GPIO pin value changed */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // FFINT_x
 | 
					
						
							|  |  |  | #define IN_OVERRUN		0x80 /* In fifo overrun */
 | 
					
						
							|  |  |  | #define OUT_UNDERRUN		0x40 /* Out fifo underrun */
 | 
					
						
							|  |  |  | #define IN_UP			0x20 /* In fifo thresholdh up-crossed */
 | 
					
						
							|  |  |  | #define IN_DOWN			0x10 /* In fifo thresholdl down-crossed */
 | 
					
						
							|  |  |  | #define OUT_UP			0x08 /* Out fifo thresholdh up-crossed */
 | 
					
						
							|  |  |  | #define OUT_DOWN		0x04 /* Out fifo thresholdl down-crossed */
 | 
					
						
							|  |  |  | #define IN_COUNTER_ZEROED	0x02 /* In down-counter reached 0 */
 | 
					
						
							|  |  |  | #define OUT_COUNTER_ZEROED	0x01 /* Out down-counter reached 0 */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define ANY_REC_INT	(IN_OVERRUN+IN_UP+IN_DOWN+IN_COUNTER_ZEROED)
 | 
					
						
							|  |  |  | #define ANY_XMIT_INT	(OUT_UNDERRUN+OUT_UP+OUT_DOWN+OUT_COUNTER_ZEROED)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Level 1 commands that are sent using the TXCI device request
 | 
					
						
							|  |  |  | #define ST5481_CMD_DR		 0x0 /* Deactivation Request */
 | 
					
						
							|  |  |  | #define ST5481_CMD_RES		 0x1 /* state machine RESet */
 | 
					
						
							|  |  |  | #define ST5481_CMD_TM1		 0x2 /* Test Mode 1 */
 | 
					
						
							|  |  |  | #define ST5481_CMD_TM2		 0x3 /* Test Mode 2 */
 | 
					
						
							|  |  |  | #define ST5481_CMD_PUP		 0x7 /* Power UP */
 | 
					
						
							|  |  |  | #define ST5481_CMD_AR8		 0x8 /* Activation Request class 1 */
 | 
					
						
							|  |  |  | #define ST5481_CMD_AR10		 0x9 /* Activation Request class 2 */
 | 
					
						
							|  |  |  | #define ST5481_CMD_ARL		 0xA /* Activation Request Loopback */
 | 
					
						
							|  |  |  | #define ST5481_CMD_PDN		 0xF /* Power DoWn */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Turn on/off the LEDs using the GPIO device request.
 | 
					
						
							|  |  |  | // To use the B LEDs, number_of_leds must be set to 4
 | 
					
						
							|  |  |  | #define B1_LED		0x10U
 | 
					
						
							|  |  |  | #define B2_LED		0x20U
 | 
					
						
							|  |  |  | #define GREEN_LED	0x40U
 | 
					
						
							|  |  |  | #define RED_LED	        0x80U
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // D channel out states
 | 
					
						
							|  |  |  | enum { | 
					
						
							|  |  |  | 	ST_DOUT_NONE, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ST_DOUT_SHORT_INIT, | 
					
						
							|  |  |  | 	ST_DOUT_SHORT_WAIT_DEN, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ST_DOUT_LONG_INIT, | 
					
						
							|  |  |  | 	ST_DOUT_LONG_WAIT_DEN, | 
					
						
							|  |  |  | 	ST_DOUT_NORMAL, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ST_DOUT_WAIT_FOR_UNDERRUN, | 
					
						
							|  |  |  |         ST_DOUT_WAIT_FOR_NOT_BUSY, | 
					
						
							|  |  |  | 	ST_DOUT_WAIT_FOR_STOP, | 
					
						
							|  |  |  | 	ST_DOUT_WAIT_FOR_RESET, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define DOUT_STATE_COUNT (ST_DOUT_WAIT_FOR_RESET + 1)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // D channel out events
 | 
					
						
							|  |  |  | enum { | 
					
						
							|  |  |  | 	EV_DOUT_START_XMIT, | 
					
						
							|  |  |  | 	EV_DOUT_COMPLETE, | 
					
						
							|  |  |  | 	EV_DOUT_DEN, | 
					
						
							|  |  |  | 	EV_DOUT_RESETED, | 
					
						
							|  |  |  | 	EV_DOUT_STOPPED, | 
					
						
							|  |  |  | 	EV_DOUT_COLL, | 
					
						
							|  |  |  | 	EV_DOUT_UNDERRUN, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define DOUT_EVENT_COUNT (EV_DOUT_UNDERRUN + 1)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ----------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | enum { | 
					
						
							|  |  |  | 	ST_L1_F3, | 
					
						
							|  |  |  | 	ST_L1_F4, | 
					
						
							|  |  |  | 	ST_L1_F6, | 
					
						
							|  |  |  | 	ST_L1_F7, | 
					
						
							|  |  |  | 	ST_L1_F8, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define L1_STATE_COUNT (ST_L1_F8+1)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // The first 16 entries match the Level 1 indications that 
 | 
					
						
							|  |  |  | // are found at offset 4 (CCIST) in the interrupt packet
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | enum { | 
					
						
							|  |  |  | 	EV_IND_DP,  // 0000 Deactivation Pending
 | 
					
						
							|  |  |  | 	EV_IND_1,   // 0001
 | 
					
						
							|  |  |  | 	EV_IND_2,   // 0010
 | 
					
						
							|  |  |  | 	EV_IND_3,   // 0011
 | 
					
						
							|  |  |  | 	EV_IND_RSY, // 0100 ReSYnchronizing
 | 
					
						
							|  |  |  | 	EV_IND_5,   // 0101
 | 
					
						
							|  |  |  | 	EV_IND_6,   // 0110
 | 
					
						
							|  |  |  | 	EV_IND_7,   // 0111
 | 
					
						
							|  |  |  | 	EV_IND_AP,  // 1000 Activation Pending
 | 
					
						
							|  |  |  | 	EV_IND_9,   // 1001
 | 
					
						
							|  |  |  | 	EV_IND_10,  // 1010
 | 
					
						
							|  |  |  | 	EV_IND_11,  // 1011
 | 
					
						
							|  |  |  | 	EV_IND_AI8, // 1100 Activation Indication class 8
 | 
					
						
							|  |  |  | 	EV_IND_AI10,// 1101 Activation Indication class 10
 | 
					
						
							|  |  |  | 	EV_IND_AIL, // 1110 Activation Indication Loopback
 | 
					
						
							|  |  |  | 	EV_IND_DI,  // 1111 Deactivation Indication
 | 
					
						
							|  |  |  | 	EV_PH_ACTIVATE_REQ, | 
					
						
							|  |  |  | 	EV_PH_DEACTIVATE_REQ, | 
					
						
							|  |  |  | 	EV_TIMER3, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define L1_EVENT_COUNT (EV_TIMER3 + 1)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define ERR(format, arg...) \
 | 
					
						
							| 
									
										
										
										
											2008-04-28 02:14:40 -07:00
										 |  |  | printk(KERN_ERR "%s:%s: " format "\n" , __FILE__,  __func__ , ## arg) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-25 01:45:52 -07:00
										 |  |  | #define WARNING(format, arg...) \
 | 
					
						
							| 
									
										
										
										
											2008-04-28 02:14:40 -07:00
										 |  |  | printk(KERN_WARNING "%s:%s: " format "\n" , __FILE__,  __func__ , ## arg) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define INFO(format, arg...) \
 | 
					
						
							| 
									
										
										
										
											2008-04-28 02:14:40 -07:00
										 |  |  | printk(KERN_INFO "%s:%s: " format "\n" , __FILE__,  __func__ , ## arg) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-08 14:21:12 +02:00
										 |  |  | #include <linux/isdn/hdlc.h>
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #include "fsm.h"
 | 
					
						
							|  |  |  | #include "hisax_if.h"
 | 
					
						
							|  |  |  | #include <linux/skbuff.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ======================================================================
 | 
					
						
							|  |  |  |  * FIFO handling | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Generic FIFO structure */ | 
					
						
							|  |  |  | struct fifo { | 
					
						
							|  |  |  | 	u_char r,w,count,size; | 
					
						
							|  |  |  | 	spinlock_t lock; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Init an FIFO | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static inline void fifo_init(struct fifo *fifo, int size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	fifo->r = fifo->w = fifo->count = 0; | 
					
						
							|  |  |  | 	fifo->size = size; | 
					
						
							|  |  |  | 	spin_lock_init(&fifo->lock); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Add an entry to the FIFO | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static inline int fifo_add(struct fifo *fifo) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned long flags; | 
					
						
							|  |  |  | 	int index; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!fifo) { | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	spin_lock_irqsave(&fifo->lock, flags); | 
					
						
							|  |  |  | 	if (fifo->count == fifo->size) { | 
					
						
							|  |  |  | 		// FIFO full
 | 
					
						
							|  |  |  | 		index = -1; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		// Return index where to get the next data to add to the FIFO
 | 
					
						
							|  |  |  | 		index = fifo->w++ & (fifo->size-1); | 
					
						
							|  |  |  | 		fifo->count++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	spin_unlock_irqrestore(&fifo->lock, flags); | 
					
						
							|  |  |  | 	return index; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Remove an entry from the FIFO with the index returned. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static inline int fifo_remove(struct fifo *fifo) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned long flags; | 
					
						
							|  |  |  | 	int index; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!fifo) { | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	spin_lock_irqsave(&fifo->lock, flags); | 
					
						
							|  |  |  | 	if (!fifo->count) { | 
					
						
							|  |  |  | 		// FIFO empty
 | 
					
						
							|  |  |  | 		index = -1; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		// Return index where to get the next data from the FIFO
 | 
					
						
							|  |  |  | 		index = fifo->r++ & (fifo->size-1); | 
					
						
							|  |  |  | 		fifo->count--; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	spin_unlock_irqrestore(&fifo->lock, flags); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return index; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ======================================================================
 | 
					
						
							|  |  |  |  * control pipe | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | typedef void (*ctrl_complete_t)(void *); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct ctrl_msg { | 
					
						
							|  |  |  | 	struct usb_ctrlrequest dr; | 
					
						
							|  |  |  | 	ctrl_complete_t complete; | 
					
						
							|  |  |  | 	void *context; | 
					
						
							|  |  |  | } ctrl_msg;  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* FIFO of ctrl messages waiting to be sent */ | 
					
						
							|  |  |  | #define MAX_EP0_MSG 16
 | 
					
						
							|  |  |  | struct ctrl_msg_fifo { | 
					
						
							|  |  |  | 	struct fifo f; | 
					
						
							|  |  |  | 	struct ctrl_msg data[MAX_EP0_MSG]; | 
					
						
							|  |  |  | };	 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define MAX_DFRAME_LEN_L1	300
 | 
					
						
							|  |  |  | #define HSCX_BUFMAX	4096
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct st5481_ctrl { | 
					
						
							|  |  |  | 	struct ctrl_msg_fifo msg_fifo; | 
					
						
							|  |  |  | 	unsigned long busy; | 
					
						
							|  |  |  | 	struct urb *urb; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct st5481_intr { | 
					
						
							|  |  |  |   //	struct evt_fifo evt_fifo;
 | 
					
						
							|  |  |  | 	struct urb *urb; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct st5481_d_out { | 
					
						
							|  |  |  | 	struct isdnhdlc_vars hdlc_state; | 
					
						
							|  |  |  | 	struct urb *urb[2]; /* double buffering */ | 
					
						
							|  |  |  | 	unsigned long busy; | 
					
						
							|  |  |  | 	struct sk_buff *tx_skb; | 
					
						
							|  |  |  | 	struct FsmInst fsm; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct st5481_b_out { | 
					
						
							|  |  |  | 	struct isdnhdlc_vars hdlc_state; | 
					
						
							|  |  |  | 	struct urb *urb[2]; /* double buffering */ | 
					
						
							|  |  |  | 	u_char flow_event; | 
					
						
							|  |  |  | 	u_long busy; | 
					
						
							|  |  |  | 	struct sk_buff *tx_skb; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct st5481_in { | 
					
						
							|  |  |  | 	struct isdnhdlc_vars hdlc_state; | 
					
						
							|  |  |  | 	struct urb *urb[2]; /* double buffering */ | 
					
						
							|  |  |  | 	int mode; | 
					
						
							|  |  |  | 	int bufsize; | 
					
						
							|  |  |  | 	unsigned int num_packets; | 
					
						
							|  |  |  | 	unsigned int packet_size; | 
					
						
							|  |  |  | 	unsigned char ep, counter; | 
					
						
							|  |  |  | 	unsigned char *rcvbuf; | 
					
						
							|  |  |  | 	struct st5481_adapter *adapter; | 
					
						
							|  |  |  | 	struct hisax_if *hisax_if; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int st5481_setup_in(struct st5481_in *in); | 
					
						
							|  |  |  | void st5481_release_in(struct st5481_in *in); | 
					
						
							|  |  |  | void st5481_in_mode(struct st5481_in *in, int mode); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct st5481_bcs { | 
					
						
							|  |  |  | 	struct hisax_b_if b_if; | 
					
						
							|  |  |  | 	struct st5481_adapter *adapter; | 
					
						
							|  |  |  | 	struct st5481_in b_in; | 
					
						
							|  |  |  | 	struct st5481_b_out b_out; | 
					
						
							|  |  |  | 	int channel; | 
					
						
							|  |  |  | 	int mode; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct st5481_adapter { | 
					
						
							|  |  |  | 	int number_of_leds; | 
					
						
							|  |  |  | 	struct usb_device *usb_dev; | 
					
						
							|  |  |  | 	struct hisax_d_if hisax_d_if; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	struct st5481_ctrl ctrl; | 
					
						
							|  |  |  | 	struct st5481_intr intr; | 
					
						
							|  |  |  | 	struct st5481_in d_in; | 
					
						
							|  |  |  | 	struct st5481_d_out d_out; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	unsigned char leds; | 
					
						
							|  |  |  | 	unsigned int led_counter; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	unsigned long event; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	struct FsmInst l1m; | 
					
						
							|  |  |  | 	struct FsmTimer timer; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	struct st5481_bcs bcs[2]; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define TIMER3_VALUE 7000
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ======================================================================
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Submit an URB with error reporting. This is a macro so | 
					
						
							| 
									
										
										
										
											2008-04-28 02:14:40 -07:00
										 |  |  |  * the __func__ returns the caller function name. | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  */ | 
					
						
							|  |  |  | #define SUBMIT_URB(urb, mem_flags) \
 | 
					
						
							|  |  |  | ({ \ | 
					
						
							|  |  |  | 	int status; \ | 
					
						
							|  |  |  | 	if ((status = usb_submit_urb(urb, mem_flags)) < 0) { \ | 
					
						
							| 
									
										
										
										
											2008-07-25 01:45:52 -07:00
										 |  |  | 		WARNING("usb_submit_urb failed,status=%d", status); \ | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	} \ | 
					
						
							|  |  |  |         status; \ | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * USB double buffering, return the URB index (0 or 1). | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static inline int get_buf_nr(struct urb *urbs[], struct urb *urb) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |         return (urbs[0]==urb ? 0 : 1);  | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ---------------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* B Channel */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int  st5481_setup_b(struct st5481_bcs *bcs); | 
					
						
							|  |  |  | void st5481_release_b(struct st5481_bcs *bcs); | 
					
						
							|  |  |  | void st5481_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* D Channel */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int  st5481_setup_d(struct st5481_adapter *adapter); | 
					
						
							|  |  |  | void st5481_release_d(struct st5481_adapter *adapter); | 
					
						
							|  |  |  | void st5481_b_l2l1(struct hisax_if *b_if, int pr, void *arg); | 
					
						
							|  |  |  | int  st5481_d_init(void); | 
					
						
							|  |  |  | void st5481_d_exit(void); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* USB */ | 
					
						
							|  |  |  | void st5481_ph_command(struct st5481_adapter *adapter, unsigned int command); | 
					
						
							|  |  |  | int st5481_setup_isocpipes(struct urb* urb[2], struct usb_device *dev,  | 
					
						
							|  |  |  | 			   unsigned int pipe, int num_packets, | 
					
						
							|  |  |  | 			   int packet_size, int buf_size, | 
					
						
							|  |  |  | 			   usb_complete_t complete, void *context); | 
					
						
							|  |  |  | void st5481_release_isocpipes(struct urb* urb[2]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void st5481_usb_pipe_reset(struct st5481_adapter *adapter, | 
					
						
							|  |  |  | 		    u_char pipe, ctrl_complete_t complete, void *context); | 
					
						
							|  |  |  | void st5481_usb_device_ctrl_msg(struct st5481_adapter *adapter, | 
					
						
							|  |  |  | 			 u8 request, u16 value, | 
					
						
							|  |  |  | 			 ctrl_complete_t complete, void *context); | 
					
						
							|  |  |  | int  st5481_setup_usb(struct st5481_adapter *adapter); | 
					
						
							|  |  |  | void st5481_release_usb(struct st5481_adapter *adapter); | 
					
						
							|  |  |  | void st5481_start(struct st5481_adapter *adapter); | 
					
						
							|  |  |  | void st5481_stop(struct st5481_adapter *adapter); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ----------------------------------------------------------------------
 | 
					
						
							|  |  |  | // debugging macros
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define __debug_variable st5481_debug
 | 
					
						
							|  |  |  | #include "hisax_debug.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extern int st5481_debug; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-09-17 23:52:42 +02:00
										 |  |  | #ifdef CONFIG_HISAX_DEBUG
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #define DBG_ISO_PACKET(level,urb) \
 | 
					
						
							| 
									
										
										
										
											2008-04-28 02:14:40 -07:00
										 |  |  |   if (level & __debug_variable) dump_iso_packet(__func__,urb) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | static void __attribute__((unused)) | 
					
						
							|  |  |  | dump_iso_packet(const char *name, struct urb *urb) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i,j; | 
					
						
							|  |  |  | 	int len,ofs; | 
					
						
							|  |  |  | 	u_char *data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	printk(KERN_DEBUG "%s: packets=%d,errors=%d\n", | 
					
						
							|  |  |  | 	       name,urb->number_of_packets,urb->error_count); | 
					
						
							|  |  |  | 	for (i = 0; i  < urb->number_of_packets; ++i) { | 
					
						
							|  |  |  | 		if (urb->pipe & USB_DIR_IN) { | 
					
						
							|  |  |  | 			len = urb->iso_frame_desc[i].actual_length; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			len = urb->iso_frame_desc[i].length; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		ofs = urb->iso_frame_desc[i].offset; | 
					
						
							|  |  |  | 		printk(KERN_DEBUG "len=%.2d,ofs=%.3d ",len,ofs); | 
					
						
							|  |  |  | 		if (len) { | 
					
						
							|  |  |  | 			data = urb->transfer_buffer+ofs; | 
					
						
							|  |  |  | 			for (j=0; j < len; j++) { | 
					
						
							|  |  |  | 				printk ("%.2x", data[j]); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		printk("\n"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline const char *ST5481_CMD_string(int evt) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	static char s[16]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch (evt) { | 
					
						
							|  |  |  | 	case ST5481_CMD_DR: return "DR"; | 
					
						
							|  |  |  | 	case ST5481_CMD_RES: return "RES"; | 
					
						
							|  |  |  | 	case ST5481_CMD_TM1: return "TM1"; | 
					
						
							|  |  |  | 	case ST5481_CMD_TM2: return "TM2"; | 
					
						
							|  |  |  | 	case ST5481_CMD_PUP: return "PUP"; | 
					
						
							|  |  |  | 	case ST5481_CMD_AR8: return "AR8"; | 
					
						
							|  |  |  | 	case ST5481_CMD_AR10: return "AR10"; | 
					
						
							|  |  |  | 	case ST5481_CMD_ARL: return "ARL"; | 
					
						
							|  |  |  | 	case ST5481_CMD_PDN: return "PDN"; | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	sprintf(s,"0x%x",evt); | 
					
						
							|  |  |  | 	return s; | 
					
						
							|  |  |  | }	 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define DBG_ISO_PACKET(level,urb) do {} while (0)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif 
 |