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

📄 hc_isp116x.c

📁 isp1161a USB主控制芯片驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
    regval32 = READ_REG32(hci, HcRhDescriptorA);    printk("HcRhDescriptorA %lx\n", regval32);    regval32 = READ_REG32(hci, HcRhDescriptorB);    printk("HcRhDescriptorB %lx\n", regval32);    regval32 = READ_REG32(hci, HcRhStatus);    printk("HcRhStatus %lx\n", regval32);    regval32 = READ_REG32(hci, HcRhPortStatus);    printk("HcRhPortStatus[1] %lx\n", regval32);    regval16 = READ_REG16(hci, HcHardwareConfiguration);    printk("HcHardwareConfiguration %x\n", regval16);    regval16 = READ_REG16(hci, HcDMAConfiguration);    printk("HcDMAConfiguration %x\n", regval16);    regval16 = READ_REG16(hci, HcTransferCounter);    printk("HcTransferCounter %x\n", regval16);    regval16 = READ_REG16(hci, HcuPInterrupt);    printk("HcuPInterrupt %x\n", regval16);    regval16 = READ_REG16(hci, HcuPInterruptEnable);    printk("HcuPInterruptEnable %x\n", regval16);    regval16 = READ_REG16(hci, HcChipID);    printk("HcChipID %x\n", regval16);    regval16 = READ_REG16(hci, HcScratch);    printk("HcScratch %x\n", regval16);    regval16 = READ_REG16(hci, HcITLBufferLength);    printk("HcITLBufferLength %x\n", regval16);    regval16 = READ_REG16(hci, HcATLBufferLength);    printk("HcATLBufferLength %x\n", regval16);    regval16 = READ_REG16(hci, HcBufferStatus);    printk("HcBufferStatus %x\n", regval16);    regval16 = READ_REG16(hci, HcReadBackITL0Length);    printk("HcReadBackITL0Length %x\n", regval16);    regval16 = READ_REG16(hci, HcReadBackITL1Length);    printk("HcReadBackITL1Length %x\n", regval16);    regval16 = READ_REG16(hci, HcITLBufferPort);    printk("HcITLBufferPort %x\n", regval16);    regval16 = READ_REG16(hci, HcATLBufferPort);    printk("HcATLBufferPort %x\n", regval16);}/*-------------------------------------------------------------------------*//* tl functions */static inline void hc_mark_last_trans (hci_t * hci) {    hcipriv_t * hp = &hci->hp;     __u8 * ptd = hp->tl;        if (hp->tlp > 0)        *(ptd + hp->tl_last) |= (1 << 3);}static inline void hc_flush_data_cache (hci_t * hci, void * data, int len) {}/*** Function Name : hc_add_trans**  ** This function sets up the registers and transmit the USB packets.**** Called from hc_simple.c*/static inline int hc_add_trans (hci_t * hci, int len, void * data,        int toggle, int maxps, int slow, int endpoint, int address, int pid, int format, int urb_state){    hcipriv_t * hp = &hci->hp;     int last = 0;    __u8 * ptd = hp->tl;    int parts = 2;    /* just send 4 packets of each kind at a frame,     * other URBs also want some bandwitdh, and a NACK is cheaper     * with less packets */        switch (hci->active_urbs) {        case 1: parts =  8; break;        case 2: parts =  6; break;        case 3: parts =  4; break;        case 4: parts =  3; break;        case 5: parts =  2; break;        default: parts = 2;    }        if (len > maxps * parts)            len = maxps * parts;         if (hp->units_left < ((len + 8 + 3) & ~0x3))        return -1;    else        hp->units_left -= (len + 8 + 3) & ~0x3;        ptd += hp->tlp;    hp->tl_last = hp->tlp + 3;    ptd [0] = 0;    ptd [1] = (toggle << 2) | (1 << 3) | (0xf << 4);    ptd [2] = maxps;    ptd [3] = ((maxps >> 8) & 0x3) | (slow << 2) | (last << 3) | (endpoint << 4);    ptd [4] = len;    ptd [5] = ((len >> 8) & 0x3) | (pid << 2);    ptd [6] = address | (format << 7);    ptd [7] = 0;    if (pid != PID_IN && len)        memcpy (ptd + 8, data, len);    hp->tlp += ((len + 8 + 3) & ~0x3);    return len;}/************************************************************************ * Function Name : hc_parse_trans *   * This function checks the status of the transmitted or received packet * by parseing the PTD (Philips Transfer Desciptor, see page 26 of * datasheet) and copies the data from the device registers into a buffer. * * Used by hc_simple.c */static inline int hc_parse_trans (hci_t * hci, int * actbytes, __u8 * data,     int * cc, int * toggle, int length,int pid, int urb_state){    hcipriv_t * hp = &hci->hp;     int last = 0;    int totbytes;    __u8 *ptd = hp->tl + hp->tlp;    *cc = (ptd [1] >> 4) & 0xf;    last = (ptd [3] >> 3) & 0x1;    *actbytes = ((ptd [1] & 0x3) << 8) | ptd [0];    totbytes = ((ptd [5] & 0x3) << 8) | ptd [4];    pid = (ptd [5] >> 2) & 0x3;    if (*actbytes > length)        *actbytes = length;    if (pid == PID_IN && *actbytes)        memcpy (data, ptd + 8, *actbytes);        *toggle = (ptd [1] >> 2 & 1);    if (*cc > 0 && *cc < 0xE && *cc != 9)        *toggle = !*toggle;/*    *active = (ptd[1] >> 3) & 0x1;        *endpoint = ptd [3] >> 4;    *address = ptd [6] & 0x7f;    */    hp->tlp += ((totbytes + 8 + 3) & ~0x3);          /* If we have failed to send data, ease off and give the USB bus a break */    if (  (totbytes != *actbytes)        &&( (*cc == TD_CC_NOERROR) ||             (*cc == TD_CC_STALL) ||             (*cc == TD_DATAOVERRUN) ||             (*cc == TD_DATAUNDERRUN) ||             (*cc == TD_NOTACCESSED) )   )    {        delay_factor = 5;    }    return !last;}/*-------------------------------------------------------------------------*/static void hc_start_int (hci_t * hci){#ifdef HC_SWITCH_INT        int mask = SOFITLInt | ATLInt | OPR_Reg;    WRITE_REG16 (hci, mask, HcuPInterrupt);     WRITE_REG16 (hci, mask, HcuPInterruptEnable);#endif}    static void hc_stop_int (hci_t * hci){#ifdef HC_SWITCH_INT    WRITE_REG16 (hci, 0, HcuPInterruptEnable);#endif}/*** Interrupt Handler**** The ISP1161 will generate a SOF interrupt every 1ms**** It is inadvisable to put debug statements in the handler as you** will probably spend all your time in the handler doing nothing else!***/static irqreturn_t hc_interrupt (int irq, void * __hci, struct pt_regs * r){    hci_t * hci = __hci;    hcipriv_t * hp = &hci->hp;     int ints_uP, ints = 0, bstat = 0;    int isExcessNak = 0;#ifdef HC_ENABLE_ISOC    int iso_buffer_index = 0;#endif    hci->regs = r;    ints_uP = READ_REG16 (hci, HcuPInterrupt);    WRITE_REG16 (hci, ints_uP, HcuPInterrupt);    //printk(KERN_ALERT"      uPInterruptstatus=%x\n", ints_uP);    if ((ints_uP & OPR_Reg) &&         (ints = (READ_REG32 (hci, HcInterruptStatus)))) {         //printk(KERN_ALERT"           HcInterruptStatus=%x\n", ints);        if (ints & OHCI_INTR_SO) {            //dbg("USB Schedule overrun");            WRITE_REG32 (hci, OHCI_INTR_SO, HcInterruptEnable);        }        if (ints & OHCI_INTR_SF) {            WRITE_REG32 (hci, OHCI_INTR_SF, HcInterruptEnable);        }        WRITE_REG32 (hci, ints, HcInterruptStatus);        WRITE_REG32 (hci, OHCI_INTR_MIE, HcInterruptEnable);    }    hci->frame_number = GET_FRAME_NUMBER (hci);    bstat = READ_REG16 (hci, HcBufferStatus);    if (ints_uP & SOFITLInt) {                    hci->frame_number = GET_FRAME_NUMBER (hci);#ifdef HC_ENABLE_ISOC    /* read itl1 first. if there is an buffer overflow HC will stop at itl1        There will be a quirks in sh_done_list if this happens !!!!! */        if ((bstat & ITL1BufferFull) && (bstat & ITL1BufferDone)) {            hp->itl1_len = READ_REG16 (hci, HcReadBackITL1Length);            if (hp->itl1_len > 0) {                WRITE_REG16 (hci, hp->itl1_len, HcTransferCounter);                READ_REGn16 (hci, HcITLBufferPort, hp->itl1_len, hp->tl);                hp->tlp = 0;                hci->td_array = &hci->i_td_array [1];                sh_done_list (hci,&isExcessNak);            }            iso_buffer_index = 1;        }        if ((bstat & ITL0BufferFull) && (bstat & ITL0BufferDone)) {            hp->itl0_len = READ_REG16 (hci, HcReadBackITL0Length);            if (hp->itl0_len > 0) {                WRITE_REG16 (hci, hp->itl0_len, HcTransferCounter);                READ_REGn16 (hci, HcITLBufferPort, hp->itl0_len, hp->tl);                hp->tlp = 0;                hci->td_array = &hci->i_td_array [0];                sh_done_list (hci,&isExcessNak);            }            iso_buffer_index = 0;        }        hp->tlp = 0;        hci->td_array = &hci->i_td_array [iso_buffer_index];        sh_scan_iso_urb_list (hci, &hci->iso_list, hci->frame_number + 1);        if (hp->tlp >0) {            WRITE_REG16 (hci, hp->tlp, HcTransferCounter);            WRITE_REGn16 (hci, HcITLBufferPort, hp->tlp, hp->tl);        }#endif    }    if (ints_uP & ATLInt) {        if ((bstat & ATLBufferFull) && (bstat & ATLBufferDone)) {            if (hp->atl_len > 0) {                WRITE_REG16 (hci, hp->atl_len, HcTransferCounter);                READ_REGn16 (hci, HcATLBufferPort, hp->atl_len, hp->tl);                hp->tlp = 0;                hci->td_array = &hci->a_td_array;                sh_done_list (hci,&isExcessNak);            }            hp->tlp = 0;        }    }    if (  (hci->a_td_array.len == 0)        &&(hci->i_td_array[0].len == 0)        &&(hci->i_td_array[1].len == 0) )        sh_del_list (hci);    /* If we want to introduce a delay before sending any more data, don't do anything here */    if (delay_factor > 0)    {        delay_factor--;        return IRQ_HANDLED;    }    hci->td_array = &hci->a_td_array;    bstat = READ_REG16 (hci, HcBufferStatus);    if (hci->td_array->len == 0 && !(bstat & ATLBufferFull)) {        hp->units_left = hp->atl_buffer_len;        hp->tlp = 0;        sh_schedule_trans (hci,0);        hc_mark_last_trans (hci);        hp->atl_len = hp->tlp;        if (hp->atl_len > 0) {            WRITE_REG16 (hci, hp->atl_len, HcTransferCounter);            WRITE_REGn16 (hci, HcATLBufferPort, hp->atl_len, hp->tl);        }            }    return IRQ_HANDLED;}static irqreturn_t isp116x_interrupt (int irq, void * __hci, struct pt_regs * r){    int int_status;    int_status = ISP116x_INW(isp116x_ctl_stat);    //printk(KERN_ALERT"   isp116x int status=%x\n", int_status);    if (int_status & 1) {        hc_interrupt(irq, __hci, r);    }    if (int_status & 2) {    }    return IRQ_HANDLED;}/*-------------------------------------------------------------------------* * HC functions *-------------------------------------------------------------------------*//* reset the HC and BUS */static int hc_reset (hci_t * hci){    int timeout = 30;             /* Disable HC interrupts */    WRITE_REG32 (hci, OHCI_INTR_MIE, HcInterruptDisable);    dbg ("USB HC reset_hc usb-: ctrl = 0x%x ;",        READ_REG32 (hci, HcControl));      /* Reset USB (needed by some controllers) */    WRITE_REG32 (hci, 0, HcControl);    /* Write the correct reset value */    WRITE_REG16 (hci, 0xf6, HcSoftwareReset);            /* HC Reset requires max 10 us delay */    WRITE_REG32 (hci, OHCI_HCR, HcCommandStatus);    while ((READ_REG32 (hci, HcCommandStatus) & OHCI_HCR) != 0) {        if (--timeout == 0) {            err ("USB HC reset timed out!");            return -1;        }            udelay (1);    }    dbg("reset_hc done");    return 0;}/*-------------------------------------------------------------------------*//* Start an host controller, set the BUS operational * enable interrupts  * connect the virtual root hub */static int hc_alloc_trans_buffer (hci_t * hci){    hcipriv_t * hp = &hci->hp;     int maxlen;    dbg("hc_alloc_trans_buffer");        hp->itl0_len = 0;    hp->itl1_len = 0;    hp->atl_len = 0;    hp->itl_buffer_len = 1024;    hp->atl_buffer_len = 4096 - 2 * hp->itl_buffer_len; /* 2048 */    WRITE_REG16 (hci, hp->itl_buffer_len, HcITLBufferLength);    WRITE_REG16 (hci, hp->atl_buffer_len, HcATLBufferLength);    /* Enable IRQ's */    WRITE_REG16 (hci, 

⌨️ 快捷键说明

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