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

📄 m8xxhci.c

📁 linux2.4.20下的针对三星公司的s3c2410的usb模块驱动代码
💻 C
📖 第 1 页 / 共 5 页
字号:
static intendpoint_hung(struct m8xxhci_qe *qe){        struct m8xxhci_device *dev;        int io, ep;        dev = qe->dev ? usb_to_m8xxhci(qe->dev) : NULL;        if (dev) {                io = usb_pipein(qe->pipe) ? 0 : 1;                ep = usb_pipeendpoint(qe->pipe);                if (dev->busy[io][ep] &&                    dev->busy_count[io][ep] > MAX_EP_BUSYS)                {                        return 1;                }        }        return 0;}static voidmark_endpoint_busy(struct m8xxhci_qe *qe){        struct m8xxhci_device *dev;        int io, ep;        dev = qe->dev ? usb_to_m8xxhci(qe->dev) : NULL;        if (dev) {                io = usb_pipein(qe->pipe) ? 0 : 1;                ep = usb_pipeendpoint(qe->pipe);                if (1) {                        log_event(3, "mark dev busy dev", (int)dev);                        log_event(3, "mark dev busy io", io);                }                dev->busy[io][ep]++;        }}static voidmark_endpoint_idle(struct m8xxhci_qe *qe){        struct m8xxhci_device *dev;        int io, ep;        dev = qe->dev ? usb_to_m8xxhci(qe->dev) : NULL;        if (dev) {                io = usb_pipein(qe->pipe) ? 0 : 1;                ep = usb_pipeendpoint(qe->pipe);                if (1) {                        log_event(3, "mark dev idle dev", (int)dev);                        log_event(3, "mark dev idle io", io);                }                dev->busy[io][ep]--;                if (dev->busy[io][ep] == 0)                        dev->busy_count[io][ep] = 0;        }}/* * scan the pending work list, looking for qe's for idle endpoints * add them to the current frame's qe list and mark the device endpoint busy */static voidrun_queues(void){        struct m8xxhci_private *hp = (struct m8xxhci_private *)m8xxhci_ptr;        struct list_head *head, *l, *next;        struct m8xxhci_qe *qe;        int i, j, prev_classes;        /* if we can't lock, exit */        if (lock_queues(hp))                return;        for (i = 0; i < MAX_Q_TYPES; i++) {                /* calculate bytes in higher priority classes */                prev_classes = 0;                for (j = 0; j <= i; j++)                        prev_classes += hp->current_frame->bytes[i];                if (0) printk("run_queues() [%d] next %p, head %p\n",                              i, hp->qe_list[i].next, &hp->qe_list[i]);                head = &hp->qe_list[i];                /* scan pending qe's */                for (l = head->next; l != head; l = next)                {                        qe = list_entry(l, struct m8xxhci_qe, qe_list);                        next = l->next;                        if (0) printk("top: head %p, l %p, qe %p\n",                                      &hp->qe_list[i], l, qe);                        log_event(3, "run_queues qe", (int)qe);                        /* find ones for device endpoints which are not busy */                        if (endpoint_busy(qe)) {                                log_event(3, "dev ep busy qe", (int)qe);                                log_event(3, "qstate", qe->qstate);                                /* if endpoint is hung, abort this qe */                                if (endpoint_hung(qe)) {                                        list_del(&qe->qe_list);                                        INIT_LIST_HEAD(&qe->qe_list);                                        abort_qe(qe, USB_ST_NORESPONSE);                                }                                continue;                        }                        /* don't exceed a single frame */                        if (hp->current_frame->total_bytes +                            qe->data_len > 1400)                        {                                log_event(2, "frame full qe", (int)qe);                                goto done;                        }                        /*                         * keep iso and interrupt from exceeding 90%,                         * give remaining 10% to control and anything left                         * to bulk.                         *                         * pretty simplistic but it's a start...                         */                        if ((prev_classes + qe->data_len) >                            frame_cumul_class_quota[qe->qtype])                        {                                log_event(2, "type over quota qe", (int)qe);                                break;                        }                        /* ok, commit. mark ep busy and remove from list */                        mark_endpoint_busy(qe);                        list_del(&qe->qe_list);                        INIT_LIST_HEAD(&qe->qe_list);                        if (0) log_event(3, "adding qe", (int)qe);                        /* and start the qe */                        add_to_current_frame(qe);                }        } done:        unlock_queues(hp);}static voiddump_delay_qe_list(void){        struct m8xxhci_private *hp = (struct m8xxhci_private *)m8xxhci_ptr;        struct m8xxhci_qe *qe;        printk("active_qe %p\n", hp->active_qe);        printk("delay_qe_list %p\n", delay_qe_list);        for (qe = delay_qe_list; qe; qe = qe->next) {                printk("qe %p, delta %d\n", qe, qe->delta);        }}/* put current qe on next frame and reset active to nil */static voidpace_qe(struct m8xxhci_qe *qe){        log_event(3, "pace qe", (int)qe);        /* turn off active but don't mark ep idle - we're still using it */        make_inactive_qe(qe);        add_to_next_frame(qe);}static intservice_delay_qe_list(void){        struct m8xxhci_qe *qe;        /* while top one is ready, add to frame's work */        while ((qe = delay_qe_list) && qe->delta <= 0) {                /* if endpoint is busy in this frame, don't */                if (endpoint_busy(qe)) {                        /* if endpoint is hung, abort this qe */                        if (endpoint_hung(qe)) {                                abort_qe(qe, USB_ST_NORESPONSE);                                continue;                        }                        break;                }                /* mark endpoint busy and remove from list */                mark_endpoint_busy(qe);                /* take off list */                delay_qe_list = qe->next;                qe->next = 0;                log_event(3, "put delay on current qe", (int)qe);                /* ok, we assume this is an interrupt transaction... */                qe->qstate = QS_INTR;                add_to_current_frame(qe);        }        return 0;}/*   put qe on delay list and reset active to nil   keep a time ordered list of qe's, sorted by their period (in ms)   the 'delta' is the period from the last qe to the next one*/static voidreschedule_qe(struct m8xxhci_qe *qe){        struct m8xxhci_qe *qe2, *prev;        int odelta, cum;        struct urb *urb = qe->urb;        int period = urb->interval;        log_event(1, "reschedule qe", (int)qe);        log_event(4, "delay ms", period);        if (qdbg) printk("reschedule qe %p\n", qe);        qe->busys = 0;        /* if list is empty, start the list */        if (delay_qe_list == NULL){                if (qdbg) printk("first\n");                if (0) log_event(1, "first", period);                delay_qe_list = qe;                qe->next = 0;                qe->delta = period;        } else {                /* find where to put this in time order */                for (qe2 = delay_qe_list, prev = 0, cum = 0;                     qe2; qe2 = qe2->next)                {                        cum += qe2->delta;                        if (cum > period)                                break;                        prev = qe2;                }                if (qdbg) printk("after qe2 %p, prev %p\n", qe2, prev);                /* link in front of qe2 (if there is one) */                if (qe2) {                        if (prev)                                prev->next = qe;                        else                                delay_qe_list = qe;                        qe->next = qe2;                        odelta = qe2->delta;                        qe2->delta = cum - period;                        qe->delta = odelta - qe2->delta;                        if (0) log_event(1, "after, delta", qe->delta);                } else {                        prev->next = qe;                        qe->next = 0;                        qe->delta = period - cum;                        if (0) log_event(1, "end, delta", qe->delta);                }        }}static voidnak_qe(struct m8xxhci_qe *qe){        switch (qe->qtype) {        case Q_INTR:                /* an interrupt transaction got a NAK, reset xmit machine */                /* and try again next time */                make_inactive_qe_idle_endpoint(qe);                reschedule_qe(qe);                return;        case Q_ISO:                /* nak an iso IN; retry IN at next frame */                pace_qe(qe);                break;        default:                /* effectively reschedule for next frame */                log_event(1, "nak, delay qe", (int)qe);#if 0                /* pace slow devices, one IN per 1ms frame */                if (usb_pipeslow(qe->pipe)) {                        pace_qe(qe);                        return;                }#else                pace_qe(qe);#endif                break;        }}/* start the next pending qe, in transaction priority order */static voidpick_next_thing_to_send(void){        struct m8xxhci_private *hp = (struct m8xxhci_private *)m8xxhci_ptr;        struct m8xxhci_qe *qe;        int i;        /* if tx bd list is locked, bail out */        if (txbd_list_busy)                return;        /* if actively working on qe, bail out */        if (hp->active_qe != 0) {//              log_event(3, "run_frame active_qe", (int)hp->active_qe);                return;        }        /* minimalist scheduler */        for (i = 0; i < 4; i++) {                /* if we're in progress, wait */                if (hp->xmit_state[i] != XS_IDLE) {                        log_event(3, "run_frame not idle", i);                        continue;                }                while ((qe = take_from_current_frame(i))) {                        log_event(3, "run_frame qe", (int)qe);                        switch (send_qe(qe)) {                        case -1:                                /* can't ever send this - free & exit */                                abort_qe(qe, -1);                                goto done;                                break;                        case 1:                                /* send in progress, stop adding bd's */                                goto done;                                break;                        case 2:                                /* can't send this time - retry later */                                add_to_next_frame(qe);                                goto done;                                break;                        }                }        } done:        ;}static voidswitch_frames(void){        struct m8xxhci_private *hp = (struct m8xxhci_private *)m8xxhci_ptr;        struct m8xxhci_frame *tmp;        if (hp->current_frame == 0) {                hp->current_frame = &hp->frames[0];                hp->next_frame = &hp->frames[1];                return;        }#ifdef DEBUG_CHECKS        if (hp->active_qe) {                log_event(3, "switch_frames; active_qe", (int)hp->active_qe);                log_event(3, "active_qe->qstate", hp->active_qe->qstate);                if (hp->active_qe->qstate == 0) {			log_event(1, "active_qe->qstate == 0; qe",				  (int)hp->active_qe);//                        m8xxhci_dump();                }        }#endif        tmp = hp->current_frame;        hp->current_frame = hp->next_frame;        hp->next_frame = tmp;}static voidschedule_current_frame(void){        /* add any ready interrupt transactions */        service_delay_qe_list();        /* add pending who transactions */        run_queues();}#if 0/* see if we need to retransmit a failed setup */static voidretransmit_setup(void){        struct m8xxhci_private *hp = (struct m8xxhci_private *)m8xxhci_ptr;        struct m8xxhci_qe *qe;        if ((qe = hp->active_qe)) {                qe->frames++;                if (qe->frames > 2 &&                    (qe->qstate == QS_SETUP ||                     qe->qstate == QS_SETUP2))                {                        log_event(3, "retransmit setup", (int)qe);                        hp->stats.retransmit++;                        if (++(qe->retries) > MAX_QE_RETRIES) {                                abort_qe(qe, USB_ST_NORESPONSE);                        } else {                                continue_xmit();                        }                }                return;        }}

⌨️ 快捷键说明

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