⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hfc_usb.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
						PH_DATA_E | INDICATION,						fifo->skbuff);			} else				fifo->hif->l1l2(fifo->hif,						PH_DATA | INDICATION,						fifo->skbuff);			fifo->skbuff = NULL;	/* buffer was freed from upper layer */		} else {			if (fifo->skbuff->len > 3) {				printk(KERN_INFO				       "HFC-S USB: got frame %d bytes but CRC ERROR on fifo:%d!!!\n",				       fifo->skbuff->len, fifon);#ifdef CONFIG_HISAX_DEBUG				if (debug > 1) {					printk(KERN_INFO "HFC-S USB: ");					for (i = 0; i < 15; i++)						printk("%.2x ",						       fifo->skbuff->						       data[fifo->skbuff->							    len - 15 + i]);					printk("\n");				}#endif			}#ifdef CONFIG_HISAX_DEBUG			else {				printk(KERN_INFO				       "HFC-S USB: frame to small (%d bytes)!!!\n",				       fifo->skbuff->len);			}#endif			skb_trim(fifo->skbuff, 0);		}	}}/***********************************************//* receive completion routine for all rx fifos *//***********************************************/static voidrx_complete(struct urb *urb, struct pt_regs *regs){	int len;	int status;	__u8 *buf, maxlen, fifon;	usb_fifo *fifo = (usb_fifo *) urb->context;	hfcusb_data *hfc = fifo->hfc;	static __u8 eof[8];#ifdef CONFIG_HISAX_DEBUG	__u8 i;#endif	urb->dev = hfc->dev;	/* security init */	fifon = fifo->fifonum;	if ((!fifo->active) || (urb->status)) {#ifdef CONFIG_HISAX_DEBUG		DBG(USB_DBG, "HFC-S USB: RX-Fifo %i is going down (%i)",		    fifon, urb->status);#endif		fifo->urb->interval = 0;	/* cancel automatic rescheduling */		if (fifo->skbuff) {			dev_kfree_skb_any(fifo->skbuff);			fifo->skbuff = NULL;		}		return;	}	len = urb->actual_length;	buf = fifo->buffer;	maxlen = fifo->usb_packet_maxlen;#ifdef CONFIG_HISAX_DEBUG	if ((fifon == 5) && (debug > 1)) {		printk(KERN_INFO		       "HFC-S USB: INT-D-RX lst_urblen:%2d act_urblen:%2d max-urblen:%2d EOF:0x%0x DATA: ",		       fifo->last_urblen, len, maxlen, eof[5]);		for (i = 0; i < len; i++)			printk("%.2x ", buf[i]);		printk("\n");	}#endif	if (fifo->last_urblen != fifo->usb_packet_maxlen) {		/* the threshold mask is in the 2nd status byte */		hfc->threshold_mask = buf[1];		/* the S0 state is in the upper half of the 1st status byte */		state_handler(hfc, buf[0] >> 4);		eof[fifon] = buf[0] & 1;		/* if we have more than the 2 status bytes -> collect data */		if (len > 2)			collect_rx_frame(fifo, buf + 2,					 urb->actual_length - 2,					 (len < maxlen) ? eof[fifon] : 0);	} else {		collect_rx_frame(fifo, buf, urb->actual_length,				 (len < maxlen) ? eof[fifon] : 0);	}	fifo->last_urblen = urb->actual_length;	status = usb_submit_urb(urb, GFP_ATOMIC);	if (status) {		printk(KERN_INFO		       "HFC-S USB: error resubmitting URN at rx_complete...\n");	}}				/* rx_complete *//***************************************************//* start the interrupt transfer for the given fifo *//***************************************************/static voidstart_int_fifo(usb_fifo * fifo){	int errcode;	printk(KERN_INFO "HFC-S USB: starting intr IN fifo:%d\n",	       fifo->fifonum);	if (!fifo->urb) {		fifo->urb = usb_alloc_urb(0, GFP_KERNEL);		if (!fifo->urb)			return;	}	usb_fill_int_urb(fifo->urb, fifo->hfc->dev, fifo->pipe,			 fifo->buffer, fifo->usb_packet_maxlen,			 rx_complete, fifo, fifo->intervall);	fifo->active = 1;	/* must be marked active */	errcode = usb_submit_urb(fifo->urb, GFP_KERNEL);	if (errcode) {		printk(KERN_INFO		       "HFC-S USB: submit URB error(start_int_info): status:%i\n",		       errcode);		fifo->active = 0;		fifo->skbuff = NULL;	}}				/* start_int_fifo *//*****************************//* set the B-channel mode    *//*****************************/static voidset_hfcmode(hfcusb_data * hfc, int channel, int mode){	__u8 val, idx_table[2] = { 0, 2 };	if (hfc->disc_flag) {		return;	}#ifdef CONFIG_HISAX_DEBUG	DBG(ISDN_DBG, "HFC-S USB: setting channel %d to mode %d", channel,	    mode);#endif	hfc->b_mode[channel] = mode;	/* setup CON_HDLC */	val = 0;	if (mode != L1_MODE_NULL)		val = 8;	/* enable fifo? */	if (mode == L1_MODE_TRANS)		val |= 2;	/* set transparent bit */	/* set FIFO to transmit register */	queue_control_request(hfc, HFCUSB_FIFO, idx_table[channel], 1);	queue_control_request(hfc, HFCUSB_CON_HDLC, val, 1);	/* reset fifo */	queue_control_request(hfc, HFCUSB_INC_RES_F, 2, 1);	/* set FIFO to receive register */	queue_control_request(hfc, HFCUSB_FIFO, idx_table[channel] + 1, 1);	queue_control_request(hfc, HFCUSB_CON_HDLC, val, 1);	/* reset fifo */	queue_control_request(hfc, HFCUSB_INC_RES_F, 2, 1);	val = 0x40;	if (hfc->b_mode[0])		val |= 1;	if (hfc->b_mode[1])		val |= 2;	queue_control_request(hfc, HFCUSB_SCTRL, val, 1);	val = 0;	if (hfc->b_mode[0])		val |= 1;	if (hfc->b_mode[1])		val |= 2;	queue_control_request(hfc, HFCUSB_SCTRL_R, val, 1);	if (mode == L1_MODE_NULL) {		if (channel)			handle_led(hfc, LED_B2_OFF);		else			handle_led(hfc, LED_B1_OFF);	} else {		if (channel)			handle_led(hfc, LED_B2_ON);		else			handle_led(hfc, LED_B1_ON);	}}static voidhfc_usb_l2l1(struct hisax_if *my_hisax_if, int pr, void *arg){	usb_fifo *fifo = my_hisax_if->priv;	hfcusb_data *hfc = fifo->hfc;	switch (pr) {		case PH_ACTIVATE | REQUEST:			if (fifo->fifonum == HFCUSB_D_TX) {#ifdef CONFIG_HISAX_DEBUG				DBG(ISDN_DBG,				    "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_ACTIVATE | REQUEST");#endif				if (hfc->l1_state != 3				    && hfc->l1_state != 7) {					hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,							   PH_DEACTIVATE |							   INDICATION,							   NULL);#ifdef CONFIG_HISAX_DEBUG					DBG(ISDN_DBG,					    "HFC-S USB: PH_DEACTIVATE | INDICATION sent (not state 3 or 7)");#endif				} else {					if (hfc->l1_state == 7) {	/* l1 already active */						hfc->d_if.ifc.l1l2(&hfc->								   d_if.								   ifc,								   PH_ACTIVATE								   |								   INDICATION,								   NULL);#ifdef CONFIG_HISAX_DEBUG						DBG(ISDN_DBG,						    "HFC-S USB: PH_ACTIVATE | INDICATION sent again ;)");#endif					} else {						/* force sending sending INFO1 */						queue_control_request(hfc,								      HFCUSB_STATES,								      0x14,								      1);						mdelay(1);						/* start l1 activation */						queue_control_request(hfc,								      HFCUSB_STATES,								      0x04,								      1);						if (!timer_pending						    (&hfc->t3_timer)) {							hfc->t3_timer.							    expires =							    jiffies +							    (HFC_TIMER_T3 *							     HZ) / 1000;							add_timer(&hfc->								  t3_timer);						}					}				}			} else {#ifdef CONFIG_HISAX_DEBUG				DBG(ISDN_DBG,				    "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_ACTIVATE | REQUEST");#endif				set_hfcmode(hfc,					    (fifo->fifonum ==					     HFCUSB_B1_TX) ? 0 : 1,					    (int) arg);				fifo->hif->l1l2(fifo->hif,						PH_ACTIVATE | INDICATION,						NULL);			}			break;		case PH_DEACTIVATE | REQUEST:			if (fifo->fifonum == HFCUSB_D_TX) {#ifdef CONFIG_HISAX_DEBUG				DBG(ISDN_DBG,				    "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_DEACTIVATE | REQUEST");#endif				printk(KERN_INFO				       "HFC-S USB: ISDN TE device should not deativate...\n");			} else {#ifdef CONFIG_HISAX_DEBUG				DBG(ISDN_DBG,				    "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_DEACTIVATE | REQUEST");#endif				set_hfcmode(hfc,					    (fifo->fifonum ==					     HFCUSB_B1_TX) ? 0 : 1,					    (int) L1_MODE_NULL);				fifo->hif->l1l2(fifo->hif,						PH_DEACTIVATE | INDICATION,						NULL);			}			break;		case PH_DATA | REQUEST:			if (fifo->skbuff && fifo->delete_flg) {				dev_kfree_skb_any(fifo->skbuff);				fifo->skbuff = NULL;				fifo->delete_flg = FALSE;			}			fifo->skbuff = arg;	/* we have a new buffer */			break;		default:			printk(KERN_INFO			       "HFC_USB: hfc_usb_d_l2l1: unkown state : %#x\n",			       pr);			break;	}}/***************************************************************************//* usb_init is called once when a new matching device is detected to setup *//* main parameters. It registers the driver at the main hisax module.      *//* on success 0 is returned.                                               *//***************************************************************************/static intusb_init(hfcusb_data * hfc){	usb_fifo *fifo;	int i, err;	u_char b;	struct hisax_b_if *p_b_if[2];	/* check the chip id */	if (read_usb(hfc, HFCUSB_CHIP_ID, &b) != 1) {		printk(KERN_INFO "HFC-USB: cannot read chip id\n");		return (1);	}	if (b != HFCUSB_CHIPID) {		printk(KERN_INFO "HFC-S USB: Invalid chip id 0x%02x\n", b);		return (1);	}	/* first set the needed config, interface and alternate */	err = usb_set_interface(hfc->dev, hfc->if_used, hfc->alt_used);	/* do Chip reset */	write_usb(hfc, HFCUSB_CIRM, 8);	/* aux = output, reset off */	write_usb(hfc, HFCUSB_CIRM, 0x10);	/* set USB_SIZE to match the the wMaxPacketSize for INT or BULK transfers */	write_usb(hfc, HFCUSB_USB_SIZE,		  (hfc->packet_size / 8) | ((hfc->packet_size / 8) << 4));	/* set USB_SIZE_I to match the the wMaxPacketSize for ISO transfers */	write_usb(hfc, HFCUSB_USB_SIZE_I, hfc->iso_packet_size);	/* enable PCM/GCI master mode */	write_usb(hfc, HFCUSB_MST_MODE1, 0);	/* set default values */	write_usb(hfc, HFCUSB_MST_MODE0, 1);	/* enable master mode */	/* init the fifos */	write_usb(hfc, HFCUSB_F_THRES,		  (HFCUSB_TX_THRESHOLD /		   8) | ((HFCUSB_RX_THRESHOLD / 8) << 4));	fifo = hfc->fifos;	for (i = 0; i < HFCUSB_NUM_FIFOS; i++) {		write_usb(hfc, HFCUSB_FIFO, i);	/* select the desired fifo */		fifo[i].skbuff = NULL;	/* init buffer pointer */		fifo[i].max_size =		    (i <= HFCUSB_B2_RX) ? MAX_BCH_SIZE : MAX_DFRAME_LEN;		fifo[i].last_urblen = 0;		/* set 2 bit for D- & E-channel */		write_usb(hfc, HFCUSB_HDLC_PAR,			  ((i <= HFCUSB_B2_RX) ? 0 : 2));		/* rx hdlc, enable IFF for D-channel */		write_usb(hfc, HFCUSB_CON_HDLC,			  ((i == HFCUSB_D_TX) ? 0x09 : 0x08));		write_usb(hfc, HFCUSB_INC_RES_F, 2);	/* reset the fifo */	}	write_usb(hfc, HFCUSB_CLKDEL, 0x0f);	/* clock delay value */	write_usb(hfc, HFCUSB_STATES, 3 | 0x10);	/* set deactivated mode */	write_usb(hfc, HFCUSB_STATES, 3);	/* enable state machine */	write_usb(hfc, HFCUSB_SCTRL_R, 0);	/* disable both B receivers */	write_usb(hfc, HFCUSB_SCTRL, 0x40);	/* disable B transmitters + capacitive mode */	/* set both B-channel to not connected */	hfc->b_mode[0] = L1_MODE_NULL;	hfc->b_mode[1] = L1_MODE_NULL;	hfc->l1_activated = FALSE;	hfc->disc_flag = FALSE;	hfc->led_state = 0;	hfc->led_new_data = 0;	hfc->old_led_state = 0;	/* init the t3 timer */	init_timer(&hfc->t3_timer);	hfc->t3_timer.data = (long) hfc;	hfc->t3_timer.function = (void *) l1_timer_expire_t3;	/* init the t4 timer */	init_timer(&hfc->t4_timer);	hfc->t4_timer.data = (long) hfc;	hfc->t4_timer.function = (void *) l1_timer_expire_t4;	/* init the background machinery for control requests */	hfc->ctrl_read.bRequestType = 0xc0;	hfc->ctrl_read.bRequest = 1;	hfc->ctrl_read.wLength = 1;	hfc->ctrl_write.bRequestType = 0x40;	hfc->ctrl_write.bRequest = 0;	hfc->ctrl_write.wLength = 0;	usb_fill_control_urb(hfc->ctrl_urb,			     hfc->dev,			     hfc->ctrl_out_pipe,			     (u_char *) & hfc->ctrl_write,			     NULL, 0, ctrl_complete, hfc);	/* Init All Fifos */	for (i = 0; i < HFCUSB_NUM_FIFOS; i++) {		hfc->fifos[i].iso[0].purb = NULL;		hfc->fifos[i].iso[1].purb = NULL;		hfc->fifos[i].active = 0;	}	/* register Modul to upper Hisax Layers */	hfc->d_if.owner = THIS_MODULE;	hfc->d_if.ifc.priv = &hfc->fifos[HFCUSB_D_TX];	hfc->d_if.ifc.l2l1 = hfc_usb_l2l1;	for (i = 0; i < 2; i++) {		hfc->b_if[i].ifc.priv = &hfc->fifos[HFCUSB_B1_TX + i * 2];		hfc->b_if[i].ifc.l2l1 = hfc_usb_l2l1;		p_b_if[i] = &hfc->b_if[i];	}	/* default Prot: EURO ISDN, should be a module_param */	hfc->protocol = 2;	hisax_register(&hfc->d_if, p_b_if, "hfc_usb", hfc->protocol);#ifdef CONFIG_HISAX_DEBUG	hfc_debug = debug;#endif	for (i = 0; i < 4; i++)		hfc->fifos[i].hif = &p_b_if[i / 2]->ifc;	for (i = 4; i < 8; i++)		hfc->fifos[i].hif = &hfc->d_if.ifc;	/* 3 (+1) INT IN + 3 ISO OUT */	if (hfc->cfg_used == CNF_3INT3ISO || hfc->cfg_used == CNF_4INT3ISO) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -