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

📄 usb-musb.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 3 页
字号:
        return s->ep[ep].type[1];    case MUSB_HDRC_RXINTERVAL:        return s->ep[ep].interval[1];    case (MUSB_HDRC_FIFOSIZE & ~1):        return 0x00;    case MUSB_HDRC_FIFOSIZE:        return ep ? s->ep[ep].fifosize : s->ep[ep].config;    default:        printf("%s: unknown register at %02x\n", __FUNCTION__, addr);        return 0x00;    };}static void musb_ep_writeb(void *opaque, int ep, int addr, uint8_t value){    struct musb_s *s = (struct musb_s *) opaque;    switch (addr) {    case MUSB_HDRC_TXTYPE:        s->ep[ep].type[0] = value;        break;    case MUSB_HDRC_TXINTERVAL:        s->ep[ep].interval[0] = value;        musb_ep_frame_cancel(&s->ep[ep], 0);        break;    case MUSB_HDRC_RXTYPE:        s->ep[ep].type[1] = value;        break;    case MUSB_HDRC_RXINTERVAL:        s->ep[ep].interval[1] = value;        musb_ep_frame_cancel(&s->ep[ep], 1);        break;    case (MUSB_HDRC_FIFOSIZE & ~1):        break;    case MUSB_HDRC_FIFOSIZE:        printf("%s: somebody messes with fifosize (now %i bytes)\n",                        __FUNCTION__, value);        s->ep[ep].fifosize = value;        break;    default:        printf("%s: unknown register at %02x\n", __FUNCTION__, addr);    };}static uint16_t musb_ep_readh(void *opaque, int ep, int addr){    struct musb_s *s = (struct musb_s *) opaque;    uint16_t ret;    switch (addr) {    case MUSB_HDRC_TXMAXP:        return s->ep[ep].maxp[0];    case MUSB_HDRC_TXCSR:        return s->ep[ep].csr[0];    case MUSB_HDRC_RXMAXP:        return s->ep[ep].maxp[1];    case MUSB_HDRC_RXCSR:        ret = s->ep[ep].csr[1];        /* TODO: This and other bits probably depend on         * ep->csr[1] & MGC_M_RXCSR_AUTOCLEAR.  */        if (s->ep[ep].csr[1] & MGC_M_RXCSR_AUTOCLEAR)            s->ep[ep].csr[1] &= ~MGC_M_RXCSR_RXPKTRDY;        return ret;    case MUSB_HDRC_RXCOUNT:        return s->ep[ep].rxcount;    default:        return musb_ep_readb(s, ep, addr) |                (musb_ep_readb(s, ep, addr | 1) << 8);    };}static void musb_ep_writeh(void *opaque, int ep, int addr, uint16_t value){    struct musb_s *s = (struct musb_s *) opaque;    switch (addr) {    case MUSB_HDRC_TXMAXP:        s->ep[ep].maxp[0] = value;        break;    case MUSB_HDRC_TXCSR:        if (ep) {            s->ep[ep].csr[0] &= value & 0xa6;            s->ep[ep].csr[0] |= value & 0xff59;        } else {            s->ep[ep].csr[0] &= value & 0x85;            s->ep[ep].csr[0] |= value & 0xf7a;        }        musb_ep_frame_cancel(&s->ep[ep], 0);        if ((ep && (value & MGC_M_TXCSR_FLUSHFIFO)) ||                        (!ep && (value & MGC_M_CSR0_FLUSHFIFO))) {            s->ep[ep].fifolen[0] = 0;            s->ep[ep].fifostart[0] = 0;            if (ep)                s->ep[ep].csr[0] &=                        ~(MGC_M_TXCSR_FIFONOTEMPTY | MGC_M_TXCSR_TXPKTRDY);            else                s->ep[ep].csr[0] &=                        ~(MGC_M_CSR0_TXPKTRDY | MGC_M_CSR0_RXPKTRDY);        }        if (                        (ep &&#ifdef CLEAR_NAK                         (value & MGC_M_TXCSR_TXPKTRDY) &&                         !(value & MGC_M_TXCSR_H_NAKTIMEOUT)) ||#else                         (value & MGC_M_TXCSR_TXPKTRDY)) ||#endif                        (!ep &&#ifdef CLEAR_NAK                         (value & MGC_M_CSR0_TXPKTRDY) &&                         !(value & MGC_M_CSR0_H_NAKTIMEOUT)))#else                         (value & MGC_M_CSR0_TXPKTRDY)))#endif            musb_tx_rdy(s, ep);        if (!ep &&                        (value & MGC_M_CSR0_H_REQPKT) &&#ifdef CLEAR_NAK                        !(value & (MGC_M_CSR0_H_NAKTIMEOUT |                                        MGC_M_CSR0_RXPKTRDY)))#else                        !(value & MGC_M_CSR0_RXPKTRDY))#endif            musb_rx_req(s, ep);        break;    case MUSB_HDRC_RXMAXP:        s->ep[ep].maxp[1] = value;        break;    case MUSB_HDRC_RXCSR:        /* (DMA mode only) */        if (                (value & MGC_M_RXCSR_H_AUTOREQ) &&                !(value & MGC_M_RXCSR_RXPKTRDY) &&                (s->ep[ep].csr[1] & MGC_M_RXCSR_RXPKTRDY))            value |= MGC_M_RXCSR_H_REQPKT;        s->ep[ep].csr[1] &= 0x102 | (value & 0x4d);        s->ep[ep].csr[1] |= value & 0xfeb0;        musb_ep_frame_cancel(&s->ep[ep], 1);        if (value & MGC_M_RXCSR_FLUSHFIFO) {            s->ep[ep].fifolen[1] = 0;            s->ep[ep].fifostart[1] = 0;            s->ep[ep].csr[1] &= ~(MGC_M_RXCSR_FIFOFULL | MGC_M_RXCSR_RXPKTRDY);            /* If double buffering and we have two packets ready, flush             * only the first one and set up the fifo at the second packet.  */        }#ifdef CLEAR_NAK        if ((value & MGC_M_RXCSR_H_REQPKT) && !(value & MGC_M_RXCSR_DATAERROR))#else        if (value & MGC_M_RXCSR_H_REQPKT)#endif            musb_rx_req(s, ep);        break;    case MUSB_HDRC_RXCOUNT:        s->ep[ep].rxcount = value;        break;    default:        musb_ep_writeb(s, ep, addr, value & 0xff);        musb_ep_writeb(s, ep, addr | 1, value >> 8);    };}/* Generic control */static uint32_t musb_readb(void *opaque, target_phys_addr_t addr){    struct musb_s *s = (struct musb_s *) opaque;    int ep, i;    uint8_t ret;    switch (addr) {    case MUSB_HDRC_FADDR:        return s->faddr;    case MUSB_HDRC_POWER:        return s->power;    case MUSB_HDRC_INTRUSB:        ret = s->intr;        for (i = 0; i < sizeof(ret) * 8; i ++)            if (ret & (1 << i))                musb_intr_set(s, i, 0);        return ret;    case MUSB_HDRC_INTRUSBE:        return s->mask;    case MUSB_HDRC_INDEX:        return s->idx;    case MUSB_HDRC_TESTMODE:        return 0x00;    case MUSB_HDRC_EP_IDX ... (MUSB_HDRC_EP_IDX + 0xf):        return musb_ep_readb(s, s->idx, addr & 0xf);    case MUSB_HDRC_DEVCTL:        return s->devctl;    case MUSB_HDRC_TXFIFOSZ:    case MUSB_HDRC_RXFIFOSZ:    case MUSB_HDRC_VCTRL:        /* TODO */        return 0x00;    case MUSB_HDRC_HWVERS:        return (1 << 10) | 400;    case (MUSB_HDRC_VCTRL | 1):    case (MUSB_HDRC_HWVERS | 1):    case (MUSB_HDRC_DEVCTL | 1):        return 0x00;    case MUSB_HDRC_BUSCTL ... (MUSB_HDRC_BUSCTL + 0x7f):        ep = (addr >> 3) & 0xf;        return musb_busctl_readb(s, ep, addr & 0x7);    case MUSB_HDRC_EP ... (MUSB_HDRC_EP + 0xff):        ep = (addr >> 4) & 0xf;        return musb_ep_readb(s, ep, addr & 0xf);    default:        printf("%s: unknown register at %02x\n", __FUNCTION__, (int) addr);        return 0x00;    };}static void musb_writeb(void *opaque, target_phys_addr_t addr, uint32_t value){    struct musb_s *s = (struct musb_s *) opaque;    int ep;    switch (addr) {    case MUSB_HDRC_FADDR:        s->faddr = value & 0x7f;        break;    case MUSB_HDRC_POWER:        s->power = (value & 0xef) | (s->power & 0x10);        /* MGC_M_POWER_RESET is also read-only in Peripheral Mode */        if ((value & MGC_M_POWER_RESET) && s->port.dev) {            usb_send_msg(s->port.dev, USB_MSG_RESET);            /* Negotiate high-speed operation if MGC_M_POWER_HSENAB is set.  */            if ((value & MGC_M_POWER_HSENAB) &&                            s->port.dev->speed == USB_SPEED_HIGH)                s->power |= MGC_M_POWER_HSMODE;	/* Success */            /* Restart frame counting.  */        }        if (value & MGC_M_POWER_SUSPENDM) {            /* When all transfers finish, suspend and if MGC_M_POWER_ENSUSPEND             * is set, also go into low power mode.  Frame counting stops.  */            /* XXX: Cleared when the interrupt register is read */        }        if (value & MGC_M_POWER_RESUME) {            /* Wait 20ms and signal resuming on the bus.  Frame counting             * restarts.  */        }        break;    case MUSB_HDRC_INTRUSB:        break;    case MUSB_HDRC_INTRUSBE:        s->mask = value & 0xff;        break;    case MUSB_HDRC_INDEX:        s->idx = value & 0xf;        break;    case MUSB_HDRC_TESTMODE:        break;    case MUSB_HDRC_EP_IDX ... (MUSB_HDRC_EP_IDX + 0xf):        musb_ep_writeb(s, s->idx, addr & 0xf, value);        break;    case MUSB_HDRC_DEVCTL:        s->session = !!(value & MGC_M_DEVCTL_SESSION);        musb_session_update(s,                        !!s->port.dev,                        !!(s->devctl & MGC_M_DEVCTL_SESSION));        /* It seems this is the only R/W bit in this register?  */        s->devctl &= ~MGC_M_DEVCTL_SESSION;        s->devctl |= value & MGC_M_DEVCTL_SESSION;        break;    case MUSB_HDRC_TXFIFOSZ:    case MUSB_HDRC_RXFIFOSZ:    case MUSB_HDRC_VCTRL:        /* TODO */        break;    case (MUSB_HDRC_VCTRL | 1):    case (MUSB_HDRC_DEVCTL | 1):        break;    case MUSB_HDRC_BUSCTL ... (MUSB_HDRC_BUSCTL + 0x7f):        ep = (addr >> 3) & 0xf;        musb_busctl_writeb(s, ep, addr & 0x7, value);        break;    case MUSB_HDRC_EP ... (MUSB_HDRC_EP + 0xff):        ep = (addr >> 4) & 0xf;        musb_ep_writeb(s, ep, addr & 0xf, value);        break;    default:        printf("%s: unknown register at %02x\n", __FUNCTION__, (int) addr);    };}static uint32_t musb_readh(void *opaque, target_phys_addr_t addr){    struct musb_s *s = (struct musb_s *) opaque;    int ep, i;    uint16_t ret;    switch (addr) {    case MUSB_HDRC_INTRTX:        ret = s->tx_intr;        /* Auto clear */        for (i = 0; i < sizeof(ret) * 8; i ++)            if (ret & (1 << i))                musb_tx_intr_set(s, i, 0);        return ret;    case MUSB_HDRC_INTRRX:        ret = s->rx_intr;        /* Auto clear */        for (i = 0; i < sizeof(ret) * 8; i ++)            if (ret & (1 << i))                musb_rx_intr_set(s, i, 0);        return ret;    case MUSB_HDRC_INTRTXE:        return s->tx_mask;    case MUSB_HDRC_INTRRXE:        return s->rx_mask;    case MUSB_HDRC_FRAME:        /* TODO */        return 0x0000;    case MUSB_HDRC_TXFIFOADDR:        return s->ep[s->idx].fifoaddr[0];    case MUSB_HDRC_RXFIFOADDR:        return s->ep[s->idx].fifoaddr[1];    case MUSB_HDRC_EP_IDX ... (MUSB_HDRC_EP_IDX + 0xf):        return musb_ep_readh(s, s->idx, addr & 0xf);    case MUSB_HDRC_BUSCTL ... (MUSB_HDRC_BUSCTL + 0x7f):        ep = (addr >> 3) & 0xf;        return musb_busctl_readh(s, ep, addr & 0x7);    case MUSB_HDRC_EP ... (MUSB_HDRC_EP + 0xff):        ep = (addr >> 4) & 0xf;        return musb_ep_readh(s, ep, addr & 0xf);    default:        return musb_readb(s, addr) | (musb_readb(s, addr | 1) << 8);    };}static void musb_writeh(void *opaque, target_phys_addr_t addr, uint32_t value){    struct musb_s *s = (struct musb_s *) opaque;    int ep;    switch (addr) {    case MUSB_HDRC_INTRTXE:        s->tx_mask = value;        /* XXX: the masks seem to apply on the raising edge like with         * edge-triggered interrupts, thus no need to update.  I may be         * wrong though.  */        break;    case MUSB_HDRC_INTRRXE:        s->rx_mask = value;        break;    case MUSB_HDRC_FRAME:        /* TODO */        break;    case MUSB_HDRC_TXFIFOADDR:        s->ep[s->idx].fifoaddr[0] = value;        s->ep[s->idx].buf[0] =                s->buf + ((value << 1) & (sizeof(s->buf) / 4 - 1));        break;    case MUSB_HDRC_RXFIFOADDR:        s->ep[s->idx].fifoaddr[1] = value;        s->ep[s->idx].buf[1] =                s->buf + ((value << 1) & (sizeof(s->buf) / 4 - 1));        break;    case MUSB_HDRC_EP_IDX ... (MUSB_HDRC_EP_IDX + 0xf):        musb_ep_writeh(s, s->idx, addr & 0xf, value);        break;    case MUSB_HDRC_BUSCTL ... (MUSB_HDRC_BUSCTL + 0x7f):        ep = (addr >> 3) & 0xf;        musb_busctl_writeh(s, ep, addr & 0x7, value);        break;    case MUSB_HDRC_EP ... (MUSB_HDRC_EP + 0xff):        ep = (addr >> 4) & 0xf;        musb_ep_writeh(s, ep, addr & 0xf, value);        break;    default:        musb_writeb(s, addr, value & 0xff);        musb_writeb(s, addr | 1, value >> 8);    };}static uint32_t musb_readw(void *opaque, target_phys_addr_t addr){    struct musb_s *s = (struct musb_s *) opaque;    struct musb_ep_s *ep;    int epnum;    switch (addr) {    case MUSB_HDRC_FIFO ... (MUSB_HDRC_FIFO + 0x3f):        epnum = ((addr - MUSB_HDRC_FIFO) >> 2) & 0xf;        ep = s->ep + epnum;        if (ep->fifolen[1] >= 16) {            /* We have a FIFO underrun */            printf("%s: EP%i FIFO is now empty, stop reading\n",                            __FUNCTION__, epnum);            return 0x00000000;        }        /* In DMA mode clear RXPKTRDY and set REQPKT automatically         * (if AUTOREQ is set) */        ep->csr[1] &= ~MGC_M_RXCSR_FIFOFULL;        return ep->buf[1][ep->fifostart[1] + ep->fifolen[1] ++];    default:        printf("%s: unknown register at %02x\n", __FUNCTION__, (int) addr);        return 0x00000000;    };}static void musb_writew(void *opaque, target_phys_addr_t addr, uint32_t value){    struct musb_s *s = (struct musb_s *) opaque;    struct musb_ep_s *ep;    int epnum;    switch (addr) {    case MUSB_HDRC_FIFO ... (MUSB_HDRC_FIFO + 0x3f):        epnum = ((addr - MUSB_HDRC_FIFO) >> 2) & 0xf;        ep = s->ep + epnum;        if (ep->fifolen[0] >= 16) {            /* We have a FIFO overrun */            printf("%s: EP%i FIFO exceeded 64 bytes, stop feeding data\n",                            __FUNCTION__, epnum);            break;        }        ep->buf[0][ep->fifostart[0] + ep->fifolen[0] ++] = value;        if (epnum)            ep->csr[0] |= MGC_M_TXCSR_FIFONOTEMPTY;        break;    default:        printf("%s: unknown register at %02x\n", __FUNCTION__, (int) addr);    };}CPUReadMemoryFunc *musb_read[] = {    musb_readb,    musb_readh,    musb_readw,};CPUWriteMemoryFunc *musb_write[] = {    musb_writeb,    musb_writeh,    musb_writew,};

⌨️ 快捷键说明

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