📄 hfc_usb.c
字号:
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 + -