Annotation of qemu/hw/usb/hcd-musb.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * "Inventra" High-speed Dual-Role Controller (MUSB-HDRC), Mentor Graphics,
        !             3:  * USB2.0 OTG compliant core used in various chips.
        !             4:  *
        !             5:  * Copyright (C) 2008 Nokia Corporation
        !             6:  * Written by Andrzej Zaborowski <[email protected]>
        !             7:  *
        !             8:  * This program is free software; you can redistribute it and/or
        !             9:  * modify it under the terms of the GNU General Public License as
        !            10:  * published by the Free Software Foundation; either version 2 or
        !            11:  * (at your option) version 3 of the License.
        !            12:  *
        !            13:  * This program is distributed in the hope that it will be useful,
        !            14:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            15:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            16:  * GNU General Public License for more details.
        !            17:  *
        !            18:  * You should have received a copy of the GNU General Public License along
        !            19:  * with this program; if not, see <http://www.gnu.org/licenses/>.
        !            20:  *
        !            21:  * Only host-mode and non-DMA accesses are currently supported.
        !            22:  */
        !            23: #include "qemu-common.h"
        !            24: #include "qemu-timer.h"
        !            25: #include "hw/usb.h"
        !            26: #include "hw/irq.h"
        !            27: #include "hw/hw.h"
        !            28: 
        !            29: /* Common USB registers */
        !            30: #define MUSB_HDRC_FADDR                0x00    /* 8-bit */
        !            31: #define MUSB_HDRC_POWER                0x01    /* 8-bit */
        !            32: 
        !            33: #define MUSB_HDRC_INTRTX       0x02    /* 16-bit */
        !            34: #define MUSB_HDRC_INTRRX       0x04
        !            35: #define MUSB_HDRC_INTRTXE      0x06  
        !            36: #define MUSB_HDRC_INTRRXE      0x08  
        !            37: #define MUSB_HDRC_INTRUSB      0x0a    /* 8 bit */
        !            38: #define MUSB_HDRC_INTRUSBE     0x0b    /* 8 bit */
        !            39: #define MUSB_HDRC_FRAME                0x0c    /* 16-bit */
        !            40: #define MUSB_HDRC_INDEX                0x0e    /* 8 bit */
        !            41: #define MUSB_HDRC_TESTMODE     0x0f    /* 8 bit */
        !            42: 
        !            43: /* Per-EP registers in indexed mode */
        !            44: #define MUSB_HDRC_EP_IDX       0x10    /* 8-bit */
        !            45: 
        !            46: /* EP FIFOs */
        !            47: #define MUSB_HDRC_FIFO         0x20
        !            48: 
        !            49: /* Additional Control Registers */
        !            50: #define        MUSB_HDRC_DEVCTL        0x60    /* 8 bit */
        !            51: 
        !            52: /* These are indexed */
        !            53: #define MUSB_HDRC_TXFIFOSZ     0x62    /* 8 bit (see masks) */
        !            54: #define MUSB_HDRC_RXFIFOSZ     0x63    /* 8 bit (see masks) */
        !            55: #define MUSB_HDRC_TXFIFOADDR   0x64    /* 16 bit offset shifted right 3 */
        !            56: #define MUSB_HDRC_RXFIFOADDR   0x66    /* 16 bit offset shifted right 3 */
        !            57: 
        !            58: /* Some more registers */
        !            59: #define MUSB_HDRC_VCTRL                0x68    /* 8 bit */
        !            60: #define MUSB_HDRC_HWVERS       0x6c    /* 8 bit */
        !            61: 
        !            62: /* Added in HDRC 1.9(?) & MHDRC 1.4 */
        !            63: /* ULPI pass-through */
        !            64: #define MUSB_HDRC_ULPI_VBUSCTL 0x70
        !            65: #define MUSB_HDRC_ULPI_REGDATA 0x74
        !            66: #define MUSB_HDRC_ULPI_REGADDR 0x75
        !            67: #define MUSB_HDRC_ULPI_REGCTL  0x76
        !            68: 
        !            69: /* Extended config & PHY control */
        !            70: #define MUSB_HDRC_ENDCOUNT     0x78    /* 8 bit */
        !            71: #define MUSB_HDRC_DMARAMCFG    0x79    /* 8 bit */
        !            72: #define MUSB_HDRC_PHYWAIT      0x7a    /* 8 bit */
        !            73: #define MUSB_HDRC_PHYVPLEN     0x7b    /* 8 bit */
        !            74: #define MUSB_HDRC_HS_EOF1      0x7c    /* 8 bit, units of 546.1 us */
        !            75: #define MUSB_HDRC_FS_EOF1      0x7d    /* 8 bit, units of 533.3 ns */
        !            76: #define MUSB_HDRC_LS_EOF1      0x7e    /* 8 bit, units of 1.067 us */
        !            77: 
        !            78: /* Per-EP BUSCTL registers */
        !            79: #define MUSB_HDRC_BUSCTL       0x80
        !            80: 
        !            81: /* Per-EP registers in flat mode */
        !            82: #define MUSB_HDRC_EP           0x100
        !            83: 
        !            84: /* offsets to registers in flat model */
        !            85: #define MUSB_HDRC_TXMAXP       0x00    /* 16 bit apparently */
        !            86: #define MUSB_HDRC_TXCSR                0x02    /* 16 bit apparently */
        !            87: #define MUSB_HDRC_CSR0         MUSB_HDRC_TXCSR         /* re-used for EP0 */
        !            88: #define MUSB_HDRC_RXMAXP       0x04    /* 16 bit apparently */
        !            89: #define MUSB_HDRC_RXCSR                0x06    /* 16 bit apparently */
        !            90: #define MUSB_HDRC_RXCOUNT      0x08    /* 16 bit apparently */
        !            91: #define MUSB_HDRC_COUNT0       MUSB_HDRC_RXCOUNT       /* re-used for EP0 */
        !            92: #define MUSB_HDRC_TXTYPE       0x0a    /* 8 bit apparently */
        !            93: #define MUSB_HDRC_TYPE0                MUSB_HDRC_TXTYPE        /* re-used for EP0 */
        !            94: #define MUSB_HDRC_TXINTERVAL   0x0b    /* 8 bit apparently */
        !            95: #define MUSB_HDRC_NAKLIMIT0    MUSB_HDRC_TXINTERVAL    /* re-used for EP0 */
        !            96: #define MUSB_HDRC_RXTYPE       0x0c    /* 8 bit apparently */
        !            97: #define MUSB_HDRC_RXINTERVAL   0x0d    /* 8 bit apparently */
        !            98: #define MUSB_HDRC_FIFOSIZE     0x0f    /* 8 bit apparently */
        !            99: #define MUSB_HDRC_CONFIGDATA   MGC_O_HDRC_FIFOSIZE     /* re-used for EP0 */
        !           100: 
        !           101: /* "Bus control" registers */
        !           102: #define MUSB_HDRC_TXFUNCADDR   0x00
        !           103: #define MUSB_HDRC_TXHUBADDR    0x02
        !           104: #define MUSB_HDRC_TXHUBPORT    0x03
        !           105: 
        !           106: #define MUSB_HDRC_RXFUNCADDR   0x04
        !           107: #define MUSB_HDRC_RXHUBADDR    0x06
        !           108: #define MUSB_HDRC_RXHUBPORT    0x07
        !           109: 
        !           110: /*
        !           111:  * MUSBHDRC Register bit masks
        !           112:  */
        !           113: 
        !           114: /* POWER */
        !           115: #define MGC_M_POWER_ISOUPDATE          0x80 
        !           116: #define        MGC_M_POWER_SOFTCONN            0x40
        !           117: #define        MGC_M_POWER_HSENAB              0x20
        !           118: #define        MGC_M_POWER_HSMODE              0x10
        !           119: #define MGC_M_POWER_RESET              0x08
        !           120: #define MGC_M_POWER_RESUME             0x04
        !           121: #define MGC_M_POWER_SUSPENDM           0x02
        !           122: #define MGC_M_POWER_ENSUSPEND          0x01
        !           123: 
        !           124: /* INTRUSB */
        !           125: #define MGC_M_INTR_SUSPEND             0x01
        !           126: #define MGC_M_INTR_RESUME              0x02
        !           127: #define MGC_M_INTR_RESET               0x04
        !           128: #define MGC_M_INTR_BABBLE              0x04
        !           129: #define MGC_M_INTR_SOF                 0x08 
        !           130: #define MGC_M_INTR_CONNECT             0x10
        !           131: #define MGC_M_INTR_DISCONNECT          0x20
        !           132: #define MGC_M_INTR_SESSREQ             0x40
        !           133: #define MGC_M_INTR_VBUSERROR           0x80    /* FOR SESSION END */
        !           134: #define MGC_M_INTR_EP0                 0x01    /* FOR EP0 INTERRUPT */
        !           135: 
        !           136: /* DEVCTL */
        !           137: #define MGC_M_DEVCTL_BDEVICE           0x80   
        !           138: #define MGC_M_DEVCTL_FSDEV             0x40
        !           139: #define MGC_M_DEVCTL_LSDEV             0x20
        !           140: #define MGC_M_DEVCTL_VBUS              0x18
        !           141: #define MGC_S_DEVCTL_VBUS              3
        !           142: #define MGC_M_DEVCTL_HM                        0x04
        !           143: #define MGC_M_DEVCTL_HR                        0x02
        !           144: #define MGC_M_DEVCTL_SESSION           0x01
        !           145: 
        !           146: /* TESTMODE */
        !           147: #define MGC_M_TEST_FORCE_HOST          0x80
        !           148: #define MGC_M_TEST_FIFO_ACCESS         0x40
        !           149: #define MGC_M_TEST_FORCE_FS            0x20
        !           150: #define MGC_M_TEST_FORCE_HS            0x10
        !           151: #define MGC_M_TEST_PACKET              0x08
        !           152: #define MGC_M_TEST_K                   0x04
        !           153: #define MGC_M_TEST_J                   0x02
        !           154: #define MGC_M_TEST_SE0_NAK             0x01
        !           155: 
        !           156: /* CSR0 */
        !           157: #define        MGC_M_CSR0_FLUSHFIFO            0x0100
        !           158: #define MGC_M_CSR0_TXPKTRDY            0x0002
        !           159: #define MGC_M_CSR0_RXPKTRDY            0x0001
        !           160: 
        !           161: /* CSR0 in Peripheral mode */
        !           162: #define MGC_M_CSR0_P_SVDSETUPEND       0x0080
        !           163: #define MGC_M_CSR0_P_SVDRXPKTRDY       0x0040
        !           164: #define MGC_M_CSR0_P_SENDSTALL         0x0020
        !           165: #define MGC_M_CSR0_P_SETUPEND          0x0010
        !           166: #define MGC_M_CSR0_P_DATAEND           0x0008
        !           167: #define MGC_M_CSR0_P_SENTSTALL         0x0004
        !           168: 
        !           169: /* CSR0 in Host mode */
        !           170: #define MGC_M_CSR0_H_NO_PING           0x0800
        !           171: #define MGC_M_CSR0_H_WR_DATATOGGLE     0x0400  /* set to allow setting: */
        !           172: #define MGC_M_CSR0_H_DATATOGGLE                0x0200  /* data toggle control */
        !           173: #define        MGC_M_CSR0_H_NAKTIMEOUT         0x0080
        !           174: #define MGC_M_CSR0_H_STATUSPKT         0x0040
        !           175: #define MGC_M_CSR0_H_REQPKT            0x0020
        !           176: #define MGC_M_CSR0_H_ERROR             0x0010
        !           177: #define MGC_M_CSR0_H_SETUPPKT          0x0008
        !           178: #define MGC_M_CSR0_H_RXSTALL           0x0004
        !           179: 
        !           180: /* CONFIGDATA */
        !           181: #define MGC_M_CONFIGDATA_MPRXE         0x80    /* auto bulk pkt combining */
        !           182: #define MGC_M_CONFIGDATA_MPTXE         0x40    /* auto bulk pkt splitting */
        !           183: #define MGC_M_CONFIGDATA_BIGENDIAN     0x20
        !           184: #define MGC_M_CONFIGDATA_HBRXE         0x10    /* HB-ISO for RX */
        !           185: #define MGC_M_CONFIGDATA_HBTXE         0x08    /* HB-ISO for TX */
        !           186: #define MGC_M_CONFIGDATA_DYNFIFO       0x04    /* dynamic FIFO sizing */
        !           187: #define MGC_M_CONFIGDATA_SOFTCONE      0x02    /* SoftConnect */
        !           188: #define MGC_M_CONFIGDATA_UTMIDW                0x01    /* Width, 0 => 8b, 1 => 16b */
        !           189: 
        !           190: /* TXCSR in Peripheral and Host mode */
        !           191: #define MGC_M_TXCSR_AUTOSET            0x8000
        !           192: #define MGC_M_TXCSR_ISO                        0x4000
        !           193: #define MGC_M_TXCSR_MODE               0x2000
        !           194: #define MGC_M_TXCSR_DMAENAB            0x1000
        !           195: #define MGC_M_TXCSR_FRCDATATOG         0x0800
        !           196: #define MGC_M_TXCSR_DMAMODE            0x0400
        !           197: #define MGC_M_TXCSR_CLRDATATOG         0x0040
        !           198: #define MGC_M_TXCSR_FLUSHFIFO          0x0008
        !           199: #define MGC_M_TXCSR_FIFONOTEMPTY       0x0002
        !           200: #define MGC_M_TXCSR_TXPKTRDY           0x0001
        !           201: 
        !           202: /* TXCSR in Peripheral mode */
        !           203: #define MGC_M_TXCSR_P_INCOMPTX         0x0080
        !           204: #define MGC_M_TXCSR_P_SENTSTALL                0x0020
        !           205: #define MGC_M_TXCSR_P_SENDSTALL                0x0010
        !           206: #define MGC_M_TXCSR_P_UNDERRUN         0x0004
        !           207: 
        !           208: /* TXCSR in Host mode */
        !           209: #define MGC_M_TXCSR_H_WR_DATATOGGLE    0x0200
        !           210: #define MGC_M_TXCSR_H_DATATOGGLE       0x0100
        !           211: #define MGC_M_TXCSR_H_NAKTIMEOUT       0x0080
        !           212: #define MGC_M_TXCSR_H_RXSTALL          0x0020
        !           213: #define MGC_M_TXCSR_H_ERROR            0x0004
        !           214: 
        !           215: /* RXCSR in Peripheral and Host mode */
        !           216: #define MGC_M_RXCSR_AUTOCLEAR          0x8000
        !           217: #define MGC_M_RXCSR_DMAENAB            0x2000
        !           218: #define MGC_M_RXCSR_DISNYET            0x1000
        !           219: #define MGC_M_RXCSR_DMAMODE            0x0800
        !           220: #define MGC_M_RXCSR_INCOMPRX           0x0100
        !           221: #define MGC_M_RXCSR_CLRDATATOG         0x0080
        !           222: #define MGC_M_RXCSR_FLUSHFIFO          0x0010
        !           223: #define MGC_M_RXCSR_DATAERROR          0x0008
        !           224: #define MGC_M_RXCSR_FIFOFULL           0x0002
        !           225: #define MGC_M_RXCSR_RXPKTRDY           0x0001
        !           226: 
        !           227: /* RXCSR in Peripheral mode */
        !           228: #define MGC_M_RXCSR_P_ISO              0x4000
        !           229: #define MGC_M_RXCSR_P_SENTSTALL                0x0040
        !           230: #define MGC_M_RXCSR_P_SENDSTALL                0x0020
        !           231: #define MGC_M_RXCSR_P_OVERRUN          0x0004
        !           232: 
        !           233: /* RXCSR in Host mode */
        !           234: #define MGC_M_RXCSR_H_AUTOREQ          0x4000
        !           235: #define MGC_M_RXCSR_H_WR_DATATOGGLE    0x0400
        !           236: #define MGC_M_RXCSR_H_DATATOGGLE       0x0200
        !           237: #define MGC_M_RXCSR_H_RXSTALL          0x0040
        !           238: #define MGC_M_RXCSR_H_REQPKT           0x0020
        !           239: #define MGC_M_RXCSR_H_ERROR            0x0004
        !           240: 
        !           241: /* HUBADDR */
        !           242: #define MGC_M_HUBADDR_MULTI_TT         0x80
        !           243: 
        !           244: /* ULPI: Added in HDRC 1.9(?) & MHDRC 1.4 */
        !           245: #define MGC_M_ULPI_VBCTL_USEEXTVBUSIND 0x02
        !           246: #define MGC_M_ULPI_VBCTL_USEEXTVBUS    0x01
        !           247: #define MGC_M_ULPI_REGCTL_INT_ENABLE   0x08
        !           248: #define MGC_M_ULPI_REGCTL_READNOTWRITE 0x04
        !           249: #define MGC_M_ULPI_REGCTL_COMPLETE     0x02
        !           250: #define MGC_M_ULPI_REGCTL_REG          0x01
        !           251: 
        !           252: /* #define MUSB_DEBUG */
        !           253: 
        !           254: #ifdef MUSB_DEBUG
        !           255: #define TRACE(fmt,...) fprintf(stderr, "%s@%d: " fmt "\n", __FUNCTION__, \
        !           256:                                __LINE__, ##__VA_ARGS__)
        !           257: #else
        !           258: #define TRACE(...)
        !           259: #endif
        !           260: 
        !           261: 
        !           262: static void musb_attach(USBPort *port);
        !           263: static void musb_detach(USBPort *port);
        !           264: static void musb_child_detach(USBPort *port, USBDevice *child);
        !           265: static void musb_schedule_cb(USBPort *port, USBPacket *p);
        !           266: static void musb_async_cancel_device(MUSBState *s, USBDevice *dev);
        !           267: 
        !           268: static USBPortOps musb_port_ops = {
        !           269:     .attach = musb_attach,
        !           270:     .detach = musb_detach,
        !           271:     .child_detach = musb_child_detach,
        !           272:     .complete = musb_schedule_cb,
        !           273: };
        !           274: 
        !           275: static USBBusOps musb_bus_ops = {
        !           276: };
        !           277: 
        !           278: typedef struct MUSBPacket MUSBPacket;
        !           279: typedef struct MUSBEndPoint MUSBEndPoint;
        !           280: 
        !           281: struct MUSBPacket {
        !           282:     USBPacket p;
        !           283:     MUSBEndPoint *ep;
        !           284:     int dir;
        !           285: };
        !           286: 
        !           287: struct MUSBEndPoint {
        !           288:     uint16_t faddr[2];
        !           289:     uint8_t haddr[2];
        !           290:     uint8_t hport[2];
        !           291:     uint16_t csr[2];
        !           292:     uint16_t maxp[2];
        !           293:     uint16_t rxcount;
        !           294:     uint8_t type[2];
        !           295:     uint8_t interval[2];
        !           296:     uint8_t config;
        !           297:     uint8_t fifosize;
        !           298:     int timeout[2];    /* Always in microframes */
        !           299: 
        !           300:     uint8_t *buf[2];
        !           301:     int fifolen[2];
        !           302:     int fifostart[2];
        !           303:     int fifoaddr[2];
        !           304:     MUSBPacket packey[2];
        !           305:     int status[2];
        !           306:     int ext_size[2];
        !           307: 
        !           308:     /* For callbacks' use */
        !           309:     int epnum;
        !           310:     int interrupt[2];
        !           311:     MUSBState *musb;
        !           312:     USBCallback *delayed_cb[2];
        !           313:     QEMUTimer *intv_timer[2];
        !           314: };
        !           315: 
        !           316: struct MUSBState {
        !           317:     qemu_irq irqs[musb_irq_max];
        !           318:     USBBus bus;
        !           319:     USBPort port;
        !           320: 
        !           321:     int idx;
        !           322:     uint8_t devctl;
        !           323:     uint8_t power;
        !           324:     uint8_t faddr;
        !           325: 
        !           326:     uint8_t intr;
        !           327:     uint8_t mask;
        !           328:     uint16_t tx_intr;
        !           329:     uint16_t tx_mask;
        !           330:     uint16_t rx_intr;
        !           331:     uint16_t rx_mask;
        !           332: 
        !           333:     int setup_len;
        !           334:     int session;
        !           335: 
        !           336:     uint8_t buf[0x8000];
        !           337: 
        !           338:         /* Duplicating the world since 2008!...  probably we should have 32
        !           339:          * logical, single endpoints instead.  */
        !           340:     MUSBEndPoint ep[16];
        !           341: };
        !           342: 
        !           343: void musb_reset(MUSBState *s)
        !           344: {
        !           345:     int i;
        !           346: 
        !           347:     s->faddr = 0x00;
        !           348:     s->devctl = 0;
        !           349:     s->power = MGC_M_POWER_HSENAB;
        !           350:     s->tx_intr = 0x0000;
        !           351:     s->rx_intr = 0x0000;
        !           352:     s->tx_mask = 0xffff;
        !           353:     s->rx_mask = 0xffff;
        !           354:     s->intr = 0x00;
        !           355:     s->mask = 0x06;
        !           356:     s->idx = 0;
        !           357: 
        !           358:     s->setup_len = 0;
        !           359:     s->session = 0;
        !           360:     memset(s->buf, 0, sizeof(s->buf));
        !           361: 
        !           362:     /* TODO: _DW */
        !           363:     s->ep[0].config = MGC_M_CONFIGDATA_SOFTCONE | MGC_M_CONFIGDATA_DYNFIFO;
        !           364:     for (i = 0; i < 16; i ++) {
        !           365:         s->ep[i].fifosize = 64;
        !           366:         s->ep[i].maxp[0] = 0x40;
        !           367:         s->ep[i].maxp[1] = 0x40;
        !           368:         s->ep[i].musb = s;
        !           369:         s->ep[i].epnum = i;
        !           370:         usb_packet_init(&s->ep[i].packey[0].p);
        !           371:         usb_packet_init(&s->ep[i].packey[1].p);
        !           372:     }
        !           373: }
        !           374: 
        !           375: struct MUSBState *musb_init(DeviceState *parent_device, int gpio_base)
        !           376: {
        !           377:     MUSBState *s = g_malloc0(sizeof(*s));
        !           378:     int i;
        !           379: 
        !           380:     for (i = 0; i < musb_irq_max; i++) {
        !           381:         s->irqs[i] = qdev_get_gpio_in(parent_device, gpio_base + i);
        !           382:     }
        !           383: 
        !           384:     musb_reset(s);
        !           385: 
        !           386:     usb_bus_new(&s->bus, &musb_bus_ops, parent_device);
        !           387:     usb_register_port(&s->bus, &s->port, s, 0, &musb_port_ops,
        !           388:                       USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
        !           389: 
        !           390:     return s;
        !           391: }
        !           392: 
        !           393: static void musb_vbus_set(MUSBState *s, int level)
        !           394: {
        !           395:     if (level)
        !           396:         s->devctl |= 3 << MGC_S_DEVCTL_VBUS;
        !           397:     else
        !           398:         s->devctl &= ~MGC_M_DEVCTL_VBUS;
        !           399: 
        !           400:     qemu_set_irq(s->irqs[musb_set_vbus], level);
        !           401: }
        !           402: 
        !           403: static void musb_intr_set(MUSBState *s, int line, int level)
        !           404: {
        !           405:     if (!level) {
        !           406:         s->intr &= ~(1 << line);
        !           407:         qemu_irq_lower(s->irqs[line]);
        !           408:     } else if (s->mask & (1 << line)) {
        !           409:         s->intr |= 1 << line;
        !           410:         qemu_irq_raise(s->irqs[line]);
        !           411:     }
        !           412: }
        !           413: 
        !           414: static void musb_tx_intr_set(MUSBState *s, int line, int level)
        !           415: {
        !           416:     if (!level) {
        !           417:         s->tx_intr &= ~(1 << line);
        !           418:         if (!s->tx_intr)
        !           419:             qemu_irq_lower(s->irqs[musb_irq_tx]);
        !           420:     } else if (s->tx_mask & (1 << line)) {
        !           421:         s->tx_intr |= 1 << line;
        !           422:         qemu_irq_raise(s->irqs[musb_irq_tx]);
        !           423:     }
        !           424: }
        !           425: 
        !           426: static void musb_rx_intr_set(MUSBState *s, int line, int level)
        !           427: {
        !           428:     if (line) {
        !           429:         if (!level) {
        !           430:             s->rx_intr &= ~(1 << line);
        !           431:             if (!s->rx_intr)
        !           432:                 qemu_irq_lower(s->irqs[musb_irq_rx]);
        !           433:         } else if (s->rx_mask & (1 << line)) {
        !           434:             s->rx_intr |= 1 << line;
        !           435:             qemu_irq_raise(s->irqs[musb_irq_rx]);
        !           436:         }
        !           437:     } else
        !           438:         musb_tx_intr_set(s, line, level);
        !           439: }
        !           440: 
        !           441: uint32_t musb_core_intr_get(MUSBState *s)
        !           442: {
        !           443:     return (s->rx_intr << 15) | s->tx_intr;
        !           444: }
        !           445: 
        !           446: void musb_core_intr_clear(MUSBState *s, uint32_t mask)
        !           447: {
        !           448:     if (s->rx_intr) {
        !           449:         s->rx_intr &= mask >> 15;
        !           450:         if (!s->rx_intr)
        !           451:             qemu_irq_lower(s->irqs[musb_irq_rx]);
        !           452:     }
        !           453: 
        !           454:     if (s->tx_intr) {
        !           455:         s->tx_intr &= mask & 0xffff;
        !           456:         if (!s->tx_intr)
        !           457:             qemu_irq_lower(s->irqs[musb_irq_tx]);
        !           458:     }
        !           459: }
        !           460: 
        !           461: void musb_set_size(MUSBState *s, int epnum, int size, int is_tx)
        !           462: {
        !           463:     s->ep[epnum].ext_size[!is_tx] = size;
        !           464:     s->ep[epnum].fifostart[0] = 0;
        !           465:     s->ep[epnum].fifostart[1] = 0;
        !           466:     s->ep[epnum].fifolen[0] = 0;
        !           467:     s->ep[epnum].fifolen[1] = 0;
        !           468: }
        !           469: 
        !           470: static void musb_session_update(MUSBState *s, int prev_dev, int prev_sess)
        !           471: {
        !           472:     int detect_prev = prev_dev && prev_sess;
        !           473:     int detect = !!s->port.dev && s->session;
        !           474: 
        !           475:     if (detect && !detect_prev) {
        !           476:         /* Let's skip the ID pin sense and VBUS sense formalities and
        !           477:          * and signal a successful SRP directly.  This should work at least
        !           478:          * for the Linux driver stack.  */
        !           479:         musb_intr_set(s, musb_irq_connect, 1);
        !           480: 
        !           481:         if (s->port.dev->speed == USB_SPEED_LOW) {
        !           482:             s->devctl &= ~MGC_M_DEVCTL_FSDEV;
        !           483:             s->devctl |= MGC_M_DEVCTL_LSDEV;
        !           484:         } else {
        !           485:             s->devctl |= MGC_M_DEVCTL_FSDEV;
        !           486:             s->devctl &= ~MGC_M_DEVCTL_LSDEV;
        !           487:         }
        !           488: 
        !           489:         /* A-mode?  */
        !           490:         s->devctl &= ~MGC_M_DEVCTL_BDEVICE;
        !           491: 
        !           492:         /* Host-mode bit?  */
        !           493:         s->devctl |= MGC_M_DEVCTL_HM;
        !           494: #if 1
        !           495:         musb_vbus_set(s, 1);
        !           496: #endif
        !           497:     } else if (!detect && detect_prev) {
        !           498: #if 1
        !           499:         musb_vbus_set(s, 0);
        !           500: #endif
        !           501:     }
        !           502: }
        !           503: 
        !           504: /* Attach or detach a device on our only port.  */
        !           505: static void musb_attach(USBPort *port)
        !           506: {
        !           507:     MUSBState *s = (MUSBState *) port->opaque;
        !           508: 
        !           509:     musb_intr_set(s, musb_irq_vbus_request, 1);
        !           510:     musb_session_update(s, 0, s->session);
        !           511: }
        !           512: 
        !           513: static void musb_detach(USBPort *port)
        !           514: {
        !           515:     MUSBState *s = (MUSBState *) port->opaque;
        !           516: 
        !           517:     musb_async_cancel_device(s, port->dev);
        !           518: 
        !           519:     musb_intr_set(s, musb_irq_disconnect, 1);
        !           520:     musb_session_update(s, 1, s->session);
        !           521: }
        !           522: 
        !           523: static void musb_child_detach(USBPort *port, USBDevice *child)
        !           524: {
        !           525:     MUSBState *s = (MUSBState *) port->opaque;
        !           526: 
        !           527:     musb_async_cancel_device(s, child);
        !           528: }
        !           529: 
        !           530: static void musb_cb_tick0(void *opaque)
        !           531: {
        !           532:     MUSBEndPoint *ep = (MUSBEndPoint *) opaque;
        !           533: 
        !           534:     ep->delayed_cb[0](&ep->packey[0].p, opaque);
        !           535: }
        !           536: 
        !           537: static void musb_cb_tick1(void *opaque)
        !           538: {
        !           539:     MUSBEndPoint *ep = (MUSBEndPoint *) opaque;
        !           540: 
        !           541:     ep->delayed_cb[1](&ep->packey[1].p, opaque);
        !           542: }
        !           543: 
        !           544: #define musb_cb_tick   (dir ? musb_cb_tick1 : musb_cb_tick0)
        !           545: 
        !           546: static void musb_schedule_cb(USBPort *port, USBPacket *packey)
        !           547: {
        !           548:     MUSBPacket *p = container_of(packey, MUSBPacket, p);
        !           549:     MUSBEndPoint *ep = p->ep;
        !           550:     int dir = p->dir;
        !           551:     int timeout = 0;
        !           552: 
        !           553:     if (ep->status[dir] == USB_RET_NAK)
        !           554:         timeout = ep->timeout[dir];
        !           555:     else if (ep->interrupt[dir])
        !           556:         timeout = 8;
        !           557:     else
        !           558:         return musb_cb_tick(ep);
        !           559: 
        !           560:     if (!ep->intv_timer[dir])
        !           561:         ep->intv_timer[dir] = qemu_new_timer_ns(vm_clock, musb_cb_tick, ep);
        !           562: 
        !           563:     qemu_mod_timer(ep->intv_timer[dir], qemu_get_clock_ns(vm_clock) +
        !           564:                    muldiv64(timeout, get_ticks_per_sec(), 8000));
        !           565: }
        !           566: 
        !           567: static int musb_timeout(int ttype, int speed, int val)
        !           568: {
        !           569: #if 1
        !           570:     return val << 3;
        !           571: #endif
        !           572: 
        !           573:     switch (ttype) {
        !           574:     case USB_ENDPOINT_XFER_CONTROL:
        !           575:         if (val < 2)
        !           576:             return 0;
        !           577:         else if (speed == USB_SPEED_HIGH)
        !           578:             return 1 << (val - 1);
        !           579:         else
        !           580:             return 8 << (val - 1);
        !           581: 
        !           582:     case USB_ENDPOINT_XFER_INT:
        !           583:         if (speed == USB_SPEED_HIGH)
        !           584:             if (val < 2)
        !           585:                 return 0;
        !           586:             else
        !           587:                 return 1 << (val - 1);
        !           588:         else
        !           589:             return val << 3;
        !           590: 
        !           591:     case USB_ENDPOINT_XFER_BULK:
        !           592:     case USB_ENDPOINT_XFER_ISOC:
        !           593:         if (val < 2)
        !           594:             return 0;
        !           595:         else if (speed == USB_SPEED_HIGH)
        !           596:             return 1 << (val - 1);
        !           597:         else
        !           598:             return 8 << (val - 1);
        !           599:         /* TODO: what with low-speed Bulk and Isochronous?  */
        !           600:     }
        !           601: 
        !           602:     hw_error("bad interval\n");
        !           603: }
        !           604: 
        !           605: static void musb_packet(MUSBState *s, MUSBEndPoint *ep,
        !           606:                 int epnum, int pid, int len, USBCallback cb, int dir)
        !           607: {
        !           608:     USBDevice *dev;
        !           609:     USBEndpoint *uep;
        !           610:     int ret;
        !           611:     int idx = epnum && dir;
        !           612:     int ttype;
        !           613: 
        !           614:     /* ep->type[0,1] contains:
        !           615:      * in bits 7:6 the speed (0 - invalid, 1 - high, 2 - full, 3 - slow)
        !           616:      * in bits 5:4 the transfer type (BULK / INT)
        !           617:      * in bits 3:0 the EP num
        !           618:      */
        !           619:     ttype = epnum ? (ep->type[idx] >> 4) & 3 : 0;
        !           620: 
        !           621:     ep->timeout[dir] = musb_timeout(ttype,
        !           622:                     ep->type[idx] >> 6, ep->interval[idx]);
        !           623:     ep->interrupt[dir] = ttype == USB_ENDPOINT_XFER_INT;
        !           624:     ep->delayed_cb[dir] = cb;
        !           625: 
        !           626:     /* A wild guess on the FADDR semantics... */
        !           627:     dev = usb_find_device(&s->port, ep->faddr[idx]);
        !           628:     uep = usb_ep_get(dev, pid, ep->type[idx] & 0xf);
        !           629:     usb_packet_setup(&ep->packey[dir].p, pid, uep);
        !           630:     usb_packet_addbuf(&ep->packey[dir].p, ep->buf[idx], len);
        !           631:     ep->packey[dir].ep = ep;
        !           632:     ep->packey[dir].dir = dir;
        !           633: 
        !           634:     ret = usb_handle_packet(dev, &ep->packey[dir].p);
        !           635: 
        !           636:     if (ret == USB_RET_ASYNC) {
        !           637:         ep->status[dir] = len;
        !           638:         return;
        !           639:     }
        !           640: 
        !           641:     ep->status[dir] = ret;
        !           642:     musb_schedule_cb(&s->port, &ep->packey[dir].p);
        !           643: }
        !           644: 
        !           645: static void musb_tx_packet_complete(USBPacket *packey, void *opaque)
        !           646: {
        !           647:     /* Unfortunately we can't use packey->devep because that's the remote
        !           648:      * endpoint number and may be different than our local.  */
        !           649:     MUSBEndPoint *ep = (MUSBEndPoint *) opaque;
        !           650:     int epnum = ep->epnum;
        !           651:     MUSBState *s = ep->musb;
        !           652: 
        !           653:     ep->fifostart[0] = 0;
        !           654:     ep->fifolen[0] = 0;
        !           655: #ifdef CLEAR_NAK
        !           656:     if (ep->status[0] != USB_RET_NAK) {
        !           657: #endif
        !           658:         if (epnum)
        !           659:             ep->csr[0] &= ~(MGC_M_TXCSR_FIFONOTEMPTY | MGC_M_TXCSR_TXPKTRDY);
        !           660:         else
        !           661:             ep->csr[0] &= ~MGC_M_CSR0_TXPKTRDY;
        !           662: #ifdef CLEAR_NAK
        !           663:     }
        !           664: #endif
        !           665: 
        !           666:     /* Clear all of the error bits first */
        !           667:     if (epnum)
        !           668:         ep->csr[0] &= ~(MGC_M_TXCSR_H_ERROR | MGC_M_TXCSR_H_RXSTALL |
        !           669:                         MGC_M_TXCSR_H_NAKTIMEOUT);
        !           670:     else
        !           671:         ep->csr[0] &= ~(MGC_M_CSR0_H_ERROR | MGC_M_CSR0_H_RXSTALL |
        !           672:                         MGC_M_CSR0_H_NAKTIMEOUT | MGC_M_CSR0_H_NO_PING);
        !           673: 
        !           674:     if (ep->status[0] == USB_RET_STALL) {
        !           675:         /* Command not supported by target! */
        !           676:         ep->status[0] = 0;
        !           677: 
        !           678:         if (epnum)
        !           679:             ep->csr[0] |= MGC_M_TXCSR_H_RXSTALL;
        !           680:         else
        !           681:             ep->csr[0] |= MGC_M_CSR0_H_RXSTALL;
        !           682:     }
        !           683: 
        !           684:     if (ep->status[0] == USB_RET_NAK) {
        !           685:         ep->status[0] = 0;
        !           686: 
        !           687:         /* NAK timeouts are only generated in Bulk transfers and
        !           688:          * Data-errors in Isochronous.  */
        !           689:         if (ep->interrupt[0]) {
        !           690:             return;
        !           691:         }
        !           692: 
        !           693:         if (epnum)
        !           694:             ep->csr[0] |= MGC_M_TXCSR_H_NAKTIMEOUT;
        !           695:         else
        !           696:             ep->csr[0] |= MGC_M_CSR0_H_NAKTIMEOUT;
        !           697:     }
        !           698: 
        !           699:     if (ep->status[0] < 0) {
        !           700:         if (ep->status[0] == USB_RET_BABBLE)
        !           701:             musb_intr_set(s, musb_irq_rst_babble, 1);
        !           702: 
        !           703:         /* Pretend we've tried three times already and failed (in
        !           704:          * case of USB_TOKEN_SETUP).  */
        !           705:         if (epnum)
        !           706:             ep->csr[0] |= MGC_M_TXCSR_H_ERROR;
        !           707:         else
        !           708:             ep->csr[0] |= MGC_M_CSR0_H_ERROR;
        !           709: 
        !           710:         musb_tx_intr_set(s, epnum, 1);
        !           711:         return;
        !           712:     }
        !           713:     /* TODO: check len for over/underruns of an OUT packet?  */
        !           714: 
        !           715: #ifdef SETUPLEN_HACK
        !           716:     if (!epnum && ep->packey[0].pid == USB_TOKEN_SETUP)
        !           717:         s->setup_len = ep->packey[0].data[6];
        !           718: #endif
        !           719: 
        !           720:     /* In DMA mode: if no error, assert DMA request for this EP,
        !           721:      * and skip the interrupt.  */
        !           722:     musb_tx_intr_set(s, epnum, 1);
        !           723: }
        !           724: 
        !           725: static void musb_rx_packet_complete(USBPacket *packey, void *opaque)
        !           726: {
        !           727:     /* Unfortunately we can't use packey->devep because that's the remote
        !           728:      * endpoint number and may be different than our local.  */
        !           729:     MUSBEndPoint *ep = (MUSBEndPoint *) opaque;
        !           730:     int epnum = ep->epnum;
        !           731:     MUSBState *s = ep->musb;
        !           732: 
        !           733:     ep->fifostart[1] = 0;
        !           734:     ep->fifolen[1] = 0;
        !           735: 
        !           736: #ifdef CLEAR_NAK
        !           737:     if (ep->status[1] != USB_RET_NAK) {
        !           738: #endif
        !           739:         ep->csr[1] &= ~MGC_M_RXCSR_H_REQPKT;
        !           740:         if (!epnum)
        !           741:             ep->csr[0] &= ~MGC_M_CSR0_H_REQPKT;
        !           742: #ifdef CLEAR_NAK
        !           743:     }
        !           744: #endif
        !           745: 
        !           746:     /* Clear all of the imaginable error bits first */
        !           747:     ep->csr[1] &= ~(MGC_M_RXCSR_H_ERROR | MGC_M_RXCSR_H_RXSTALL |
        !           748:                     MGC_M_RXCSR_DATAERROR);
        !           749:     if (!epnum)
        !           750:         ep->csr[0] &= ~(MGC_M_CSR0_H_ERROR | MGC_M_CSR0_H_RXSTALL |
        !           751:                         MGC_M_CSR0_H_NAKTIMEOUT | MGC_M_CSR0_H_NO_PING);
        !           752: 
        !           753:     if (ep->status[1] == USB_RET_STALL) {
        !           754:         ep->status[1] = 0;
        !           755:         packey->result = 0;
        !           756: 
        !           757:         ep->csr[1] |= MGC_M_RXCSR_H_RXSTALL;
        !           758:         if (!epnum)
        !           759:             ep->csr[0] |= MGC_M_CSR0_H_RXSTALL;
        !           760:     }
        !           761: 
        !           762:     if (ep->status[1] == USB_RET_NAK) {
        !           763:         ep->status[1] = 0;
        !           764: 
        !           765:         /* NAK timeouts are only generated in Bulk transfers and
        !           766:          * Data-errors in Isochronous.  */
        !           767:         if (ep->interrupt[1])
        !           768:             return musb_packet(s, ep, epnum, USB_TOKEN_IN,
        !           769:                             packey->iov.size, musb_rx_packet_complete, 1);
        !           770: 
        !           771:         ep->csr[1] |= MGC_M_RXCSR_DATAERROR;
        !           772:         if (!epnum)
        !           773:             ep->csr[0] |= MGC_M_CSR0_H_NAKTIMEOUT;
        !           774:     }
        !           775: 
        !           776:     if (ep->status[1] < 0) {
        !           777:         if (ep->status[1] == USB_RET_BABBLE) {
        !           778:             musb_intr_set(s, musb_irq_rst_babble, 1);
        !           779:             return;
        !           780:         }
        !           781: 
        !           782:         /* Pretend we've tried three times already and failed (in
        !           783:          * case of a control transfer).  */
        !           784:         ep->csr[1] |= MGC_M_RXCSR_H_ERROR;
        !           785:         if (!epnum)
        !           786:             ep->csr[0] |= MGC_M_CSR0_H_ERROR;
        !           787: 
        !           788:         musb_rx_intr_set(s, epnum, 1);
        !           789:         return;
        !           790:     }
        !           791:     /* TODO: check len for over/underruns of an OUT packet?  */
        !           792:     /* TODO: perhaps make use of e->ext_size[1] here.  */
        !           793: 
        !           794:     packey->result = ep->status[1];
        !           795: 
        !           796:     if (!(ep->csr[1] & (MGC_M_RXCSR_H_RXSTALL | MGC_M_RXCSR_DATAERROR))) {
        !           797:         ep->csr[1] |= MGC_M_RXCSR_FIFOFULL | MGC_M_RXCSR_RXPKTRDY;
        !           798:         if (!epnum)
        !           799:             ep->csr[0] |= MGC_M_CSR0_RXPKTRDY;
        !           800: 
        !           801:         ep->rxcount = packey->result; /* XXX: MIN(packey->len, ep->maxp[1]); */
        !           802:         /* In DMA mode: assert DMA request for this EP */
        !           803:     }
        !           804: 
        !           805:     /* Only if DMA has not been asserted */
        !           806:     musb_rx_intr_set(s, epnum, 1);
        !           807: }
        !           808: 
        !           809: static void musb_async_cancel_device(MUSBState *s, USBDevice *dev)
        !           810: {
        !           811:     int ep, dir;
        !           812: 
        !           813:     for (ep = 0; ep < 16; ep++) {
        !           814:         for (dir = 0; dir < 2; dir++) {
        !           815:             if (!usb_packet_is_inflight(&s->ep[ep].packey[dir].p) ||
        !           816:                 s->ep[ep].packey[dir].p.ep->dev != dev) {
        !           817:                 continue;
        !           818:             }
        !           819:             usb_cancel_packet(&s->ep[ep].packey[dir].p);
        !           820:             /* status updates needed here? */
        !           821:         }
        !           822:     }
        !           823: }
        !           824: 
        !           825: static void musb_tx_rdy(MUSBState *s, int epnum)
        !           826: {
        !           827:     MUSBEndPoint *ep = s->ep + epnum;
        !           828:     int pid;
        !           829:     int total, valid = 0;
        !           830:     TRACE("start %d, len %d",  ep->fifostart[0], ep->fifolen[0] );
        !           831:     ep->fifostart[0] += ep->fifolen[0];
        !           832:     ep->fifolen[0] = 0;
        !           833: 
        !           834:     /* XXX: how's the total size of the packet retrieved exactly in
        !           835:      * the generic case?  */
        !           836:     total = ep->maxp[0] & 0x3ff;
        !           837: 
        !           838:     if (ep->ext_size[0]) {
        !           839:         total = ep->ext_size[0];
        !           840:         ep->ext_size[0] = 0;
        !           841:         valid = 1;
        !           842:     }
        !           843: 
        !           844:     /* If the packet is not fully ready yet, wait for a next segment.  */
        !           845:     if (epnum && (ep->fifostart[0]) < total)
        !           846:         return;
        !           847: 
        !           848:     if (!valid)
        !           849:         total = ep->fifostart[0];
        !           850: 
        !           851:     pid = USB_TOKEN_OUT;
        !           852:     if (!epnum && (ep->csr[0] & MGC_M_CSR0_H_SETUPPKT)) {
        !           853:         pid = USB_TOKEN_SETUP;
        !           854:         if (total != 8) {
        !           855:             TRACE("illegal SETUPPKT length of %i bytes", total);
        !           856:         }
        !           857:         /* Controller should retry SETUP packets three times on errors
        !           858:          * but it doesn't make sense for us to do that.  */
        !           859:     }
        !           860: 
        !           861:     return musb_packet(s, ep, epnum, pid,
        !           862:                     total, musb_tx_packet_complete, 0);
        !           863: }
        !           864: 
        !           865: static void musb_rx_req(MUSBState *s, int epnum)
        !           866: {
        !           867:     MUSBEndPoint *ep = s->ep + epnum;
        !           868:     int total;
        !           869: 
        !           870:     /* If we already have a packet, which didn't fit into the
        !           871:      * 64 bytes of the FIFO, only move the FIFO start and return. (Obsolete) */
        !           872:     if (ep->packey[1].p.pid == USB_TOKEN_IN && ep->status[1] >= 0 &&
        !           873:                     (ep->fifostart[1]) + ep->rxcount <
        !           874:                     ep->packey[1].p.iov.size) {
        !           875:         TRACE("0x%08x, %d",  ep->fifostart[1], ep->rxcount );
        !           876:         ep->fifostart[1] += ep->rxcount;
        !           877:         ep->fifolen[1] = 0;
        !           878: 
        !           879:         ep->rxcount = MIN(ep->packey[0].p.iov.size - (ep->fifostart[1]),
        !           880:                         ep->maxp[1]);
        !           881: 
        !           882:         ep->csr[1] &= ~MGC_M_RXCSR_H_REQPKT;
        !           883:         if (!epnum)
        !           884:             ep->csr[0] &= ~MGC_M_CSR0_H_REQPKT;
        !           885: 
        !           886:         /* Clear all of the error bits first */
        !           887:         ep->csr[1] &= ~(MGC_M_RXCSR_H_ERROR | MGC_M_RXCSR_H_RXSTALL |
        !           888:                         MGC_M_RXCSR_DATAERROR);
        !           889:         if (!epnum)
        !           890:             ep->csr[0] &= ~(MGC_M_CSR0_H_ERROR | MGC_M_CSR0_H_RXSTALL |
        !           891:                             MGC_M_CSR0_H_NAKTIMEOUT | MGC_M_CSR0_H_NO_PING);
        !           892: 
        !           893:         ep->csr[1] |= MGC_M_RXCSR_FIFOFULL | MGC_M_RXCSR_RXPKTRDY;
        !           894:         if (!epnum)
        !           895:             ep->csr[0] |= MGC_M_CSR0_RXPKTRDY;
        !           896:         musb_rx_intr_set(s, epnum, 1);
        !           897:         return;
        !           898:     }
        !           899: 
        !           900:     /* The driver sets maxp[1] to 64 or less because it knows the hardware
        !           901:      * FIFO is this deep.  Bigger packets get split in
        !           902:      * usb_generic_handle_packet but we can also do the splitting locally
        !           903:      * for performance.  It turns out we can also have a bigger FIFO and
        !           904:      * ignore the limit set in ep->maxp[1].  The Linux MUSB driver deals
        !           905:      * OK with single packets of even 32KB and we avoid splitting, however
        !           906:      * usb_msd.c sometimes sends a packet bigger than what Linux expects
        !           907:      * (e.g. 8192 bytes instead of 4096) and we get an OVERRUN.  Splitting
        !           908:      * hides this overrun from Linux.  Up to 4096 everything is fine
        !           909:      * though.  Currently this is disabled.
        !           910:      *
        !           911:      * XXX: mind ep->fifosize.  */
        !           912:     total = MIN(ep->maxp[1] & 0x3ff, sizeof(s->buf));
        !           913: 
        !           914: #ifdef SETUPLEN_HACK
        !           915:     /* Why should *we* do that instead of Linux?  */
        !           916:     if (!epnum) {
        !           917:         if (ep->packey[0].p.devaddr == 2) {
        !           918:             total = MIN(s->setup_len, 8);
        !           919:         } else {
        !           920:             total = MIN(s->setup_len, 64);
        !           921:         }
        !           922:         s->setup_len -= total;
        !           923:     }
        !           924: #endif
        !           925: 
        !           926:     return musb_packet(s, ep, epnum, USB_TOKEN_IN,
        !           927:                     total, musb_rx_packet_complete, 1);
        !           928: }
        !           929: 
        !           930: static uint8_t musb_read_fifo(MUSBEndPoint *ep)
        !           931: {
        !           932:     uint8_t value;
        !           933:     if (ep->fifolen[1] >= 64) {
        !           934:         /* We have a FIFO underrun */
        !           935:         TRACE("EP%d FIFO is now empty, stop reading", ep->epnum);
        !           936:         return 0x00000000;
        !           937:     }
        !           938:     /* In DMA mode clear RXPKTRDY and set REQPKT automatically
        !           939:      * (if AUTOREQ is set) */
        !           940: 
        !           941:     ep->csr[1] &= ~MGC_M_RXCSR_FIFOFULL;
        !           942:     value=ep->buf[1][ep->fifostart[1] + ep->fifolen[1] ++];
        !           943:     TRACE("EP%d 0x%02x, %d", ep->epnum, value, ep->fifolen[1] );
        !           944:     return value;
        !           945: }
        !           946: 
        !           947: static void musb_write_fifo(MUSBEndPoint *ep, uint8_t value)
        !           948: {
        !           949:     TRACE("EP%d = %02x", ep->epnum, value);
        !           950:     if (ep->fifolen[0] >= 64) {
        !           951:         /* We have a FIFO overrun */
        !           952:         TRACE("EP%d FIFO exceeded 64 bytes, stop feeding data", ep->epnum);
        !           953:         return;
        !           954:      }
        !           955: 
        !           956:      ep->buf[0][ep->fifostart[0] + ep->fifolen[0] ++] = value;
        !           957:      ep->csr[0] |= MGC_M_TXCSR_FIFONOTEMPTY;
        !           958: }
        !           959: 
        !           960: static void musb_ep_frame_cancel(MUSBEndPoint *ep, int dir)
        !           961: {
        !           962:     if (ep->intv_timer[dir])
        !           963:         qemu_del_timer(ep->intv_timer[dir]);
        !           964: }
        !           965: 
        !           966: /* Bus control */
        !           967: static uint8_t musb_busctl_readb(void *opaque, int ep, int addr)
        !           968: {
        !           969:     MUSBState *s = (MUSBState *) opaque;
        !           970: 
        !           971:     switch (addr) {
        !           972:     /* For USB2.0 HS hubs only */
        !           973:     case MUSB_HDRC_TXHUBADDR:
        !           974:         return s->ep[ep].haddr[0];
        !           975:     case MUSB_HDRC_TXHUBPORT:
        !           976:         return s->ep[ep].hport[0];
        !           977:     case MUSB_HDRC_RXHUBADDR:
        !           978:         return s->ep[ep].haddr[1];
        !           979:     case MUSB_HDRC_RXHUBPORT:
        !           980:         return s->ep[ep].hport[1];
        !           981: 
        !           982:     default:
        !           983:         TRACE("unknown register 0x%02x", addr);
        !           984:         return 0x00;
        !           985:     };
        !           986: }
        !           987: 
        !           988: static void musb_busctl_writeb(void *opaque, int ep, int addr, uint8_t value)
        !           989: {
        !           990:     MUSBState *s = (MUSBState *) opaque;
        !           991: 
        !           992:     switch (addr) {
        !           993:     case MUSB_HDRC_TXFUNCADDR:
        !           994:         s->ep[ep].faddr[0] = value;
        !           995:         break;
        !           996:     case MUSB_HDRC_RXFUNCADDR:
        !           997:         s->ep[ep].faddr[1] = value;
        !           998:         break;
        !           999:     case MUSB_HDRC_TXHUBADDR:
        !          1000:         s->ep[ep].haddr[0] = value;
        !          1001:         break;
        !          1002:     case MUSB_HDRC_TXHUBPORT:
        !          1003:         s->ep[ep].hport[0] = value;
        !          1004:         break;
        !          1005:     case MUSB_HDRC_RXHUBADDR:
        !          1006:         s->ep[ep].haddr[1] = value;
        !          1007:         break;
        !          1008:     case MUSB_HDRC_RXHUBPORT:
        !          1009:         s->ep[ep].hport[1] = value;
        !          1010:         break;
        !          1011: 
        !          1012:     default:
        !          1013:         TRACE("unknown register 0x%02x", addr);
        !          1014:         break;
        !          1015:     };
        !          1016: }
        !          1017: 
        !          1018: static uint16_t musb_busctl_readh(void *opaque, int ep, int addr)
        !          1019: {
        !          1020:     MUSBState *s = (MUSBState *) opaque;
        !          1021: 
        !          1022:     switch (addr) {
        !          1023:     case MUSB_HDRC_TXFUNCADDR:
        !          1024:         return s->ep[ep].faddr[0];
        !          1025:     case MUSB_HDRC_RXFUNCADDR:
        !          1026:         return s->ep[ep].faddr[1];
        !          1027: 
        !          1028:     default:
        !          1029:         return musb_busctl_readb(s, ep, addr) |
        !          1030:                 (musb_busctl_readb(s, ep, addr | 1) << 8);
        !          1031:     };
        !          1032: }
        !          1033: 
        !          1034: static void musb_busctl_writeh(void *opaque, int ep, int addr, uint16_t value)
        !          1035: {
        !          1036:     MUSBState *s = (MUSBState *) opaque;
        !          1037: 
        !          1038:     switch (addr) {
        !          1039:     case MUSB_HDRC_TXFUNCADDR:
        !          1040:         s->ep[ep].faddr[0] = value;
        !          1041:         break;
        !          1042:     case MUSB_HDRC_RXFUNCADDR:
        !          1043:         s->ep[ep].faddr[1] = value;
        !          1044:         break;
        !          1045: 
        !          1046:     default:
        !          1047:         musb_busctl_writeb(s, ep, addr, value & 0xff);
        !          1048:         musb_busctl_writeb(s, ep, addr | 1, value >> 8);
        !          1049:     };
        !          1050: }
        !          1051: 
        !          1052: /* Endpoint control */
        !          1053: static uint8_t musb_ep_readb(void *opaque, int ep, int addr)
        !          1054: {
        !          1055:     MUSBState *s = (MUSBState *) opaque;
        !          1056: 
        !          1057:     switch (addr) {
        !          1058:     case MUSB_HDRC_TXTYPE:
        !          1059:         return s->ep[ep].type[0];
        !          1060:     case MUSB_HDRC_TXINTERVAL:
        !          1061:         return s->ep[ep].interval[0];
        !          1062:     case MUSB_HDRC_RXTYPE:
        !          1063:         return s->ep[ep].type[1];
        !          1064:     case MUSB_HDRC_RXINTERVAL:
        !          1065:         return s->ep[ep].interval[1];
        !          1066:     case (MUSB_HDRC_FIFOSIZE & ~1):
        !          1067:         return 0x00;
        !          1068:     case MUSB_HDRC_FIFOSIZE:
        !          1069:         return ep ? s->ep[ep].fifosize : s->ep[ep].config;
        !          1070:     case MUSB_HDRC_RXCOUNT:
        !          1071:         return s->ep[ep].rxcount;
        !          1072: 
        !          1073:     default:
        !          1074:         TRACE("unknown register 0x%02x", addr);
        !          1075:         return 0x00;
        !          1076:     };
        !          1077: }
        !          1078: 
        !          1079: static void musb_ep_writeb(void *opaque, int ep, int addr, uint8_t value)
        !          1080: {
        !          1081:     MUSBState *s = (MUSBState *) opaque;
        !          1082: 
        !          1083:     switch (addr) {
        !          1084:     case MUSB_HDRC_TXTYPE:
        !          1085:         s->ep[ep].type[0] = value;
        !          1086:         break;
        !          1087:     case MUSB_HDRC_TXINTERVAL:
        !          1088:         s->ep[ep].interval[0] = value;
        !          1089:         musb_ep_frame_cancel(&s->ep[ep], 0);
        !          1090:         break;
        !          1091:     case MUSB_HDRC_RXTYPE:
        !          1092:         s->ep[ep].type[1] = value;
        !          1093:         break;
        !          1094:     case MUSB_HDRC_RXINTERVAL:
        !          1095:         s->ep[ep].interval[1] = value;
        !          1096:         musb_ep_frame_cancel(&s->ep[ep], 1);
        !          1097:         break;
        !          1098:     case (MUSB_HDRC_FIFOSIZE & ~1):
        !          1099:         break;
        !          1100:     case MUSB_HDRC_FIFOSIZE:
        !          1101:         TRACE("somebody messes with fifosize (now %i bytes)", value);
        !          1102:         s->ep[ep].fifosize = value;
        !          1103:         break;
        !          1104:     default:
        !          1105:         TRACE("unknown register 0x%02x", addr);
        !          1106:         break;
        !          1107:     };
        !          1108: }
        !          1109: 
        !          1110: static uint16_t musb_ep_readh(void *opaque, int ep, int addr)
        !          1111: {
        !          1112:     MUSBState *s = (MUSBState *) opaque;
        !          1113:     uint16_t ret;
        !          1114: 
        !          1115:     switch (addr) {
        !          1116:     case MUSB_HDRC_TXMAXP:
        !          1117:         return s->ep[ep].maxp[0];
        !          1118:     case MUSB_HDRC_TXCSR:
        !          1119:         return s->ep[ep].csr[0];
        !          1120:     case MUSB_HDRC_RXMAXP:
        !          1121:         return s->ep[ep].maxp[1];
        !          1122:     case MUSB_HDRC_RXCSR:
        !          1123:         ret = s->ep[ep].csr[1];
        !          1124: 
        !          1125:         /* TODO: This and other bits probably depend on
        !          1126:          * ep->csr[1] & MGC_M_RXCSR_AUTOCLEAR.  */
        !          1127:         if (s->ep[ep].csr[1] & MGC_M_RXCSR_AUTOCLEAR)
        !          1128:             s->ep[ep].csr[1] &= ~MGC_M_RXCSR_RXPKTRDY;
        !          1129: 
        !          1130:         return ret;
        !          1131:     case MUSB_HDRC_RXCOUNT:
        !          1132:         return s->ep[ep].rxcount;
        !          1133: 
        !          1134:     default:
        !          1135:         return musb_ep_readb(s, ep, addr) |
        !          1136:                 (musb_ep_readb(s, ep, addr | 1) << 8);
        !          1137:     };
        !          1138: }
        !          1139: 
        !          1140: static void musb_ep_writeh(void *opaque, int ep, int addr, uint16_t value)
        !          1141: {
        !          1142:     MUSBState *s = (MUSBState *) opaque;
        !          1143: 
        !          1144:     switch (addr) {
        !          1145:     case MUSB_HDRC_TXMAXP:
        !          1146:         s->ep[ep].maxp[0] = value;
        !          1147:         break;
        !          1148:     case MUSB_HDRC_TXCSR:
        !          1149:         if (ep) {
        !          1150:             s->ep[ep].csr[0] &= value & 0xa6;
        !          1151:             s->ep[ep].csr[0] |= value & 0xff59;
        !          1152:         } else {
        !          1153:             s->ep[ep].csr[0] &= value & 0x85;
        !          1154:             s->ep[ep].csr[0] |= value & 0xf7a;
        !          1155:         }
        !          1156: 
        !          1157:         musb_ep_frame_cancel(&s->ep[ep], 0);
        !          1158: 
        !          1159:         if ((ep && (value & MGC_M_TXCSR_FLUSHFIFO)) ||
        !          1160:                         (!ep && (value & MGC_M_CSR0_FLUSHFIFO))) {
        !          1161:             s->ep[ep].fifolen[0] = 0;
        !          1162:             s->ep[ep].fifostart[0] = 0;
        !          1163:             if (ep)
        !          1164:                 s->ep[ep].csr[0] &=
        !          1165:                         ~(MGC_M_TXCSR_FIFONOTEMPTY | MGC_M_TXCSR_TXPKTRDY);
        !          1166:             else
        !          1167:                 s->ep[ep].csr[0] &=
        !          1168:                         ~(MGC_M_CSR0_TXPKTRDY | MGC_M_CSR0_RXPKTRDY);
        !          1169:         }
        !          1170:         if (
        !          1171:                         (ep &&
        !          1172: #ifdef CLEAR_NAK
        !          1173:                          (value & MGC_M_TXCSR_TXPKTRDY) &&
        !          1174:                          !(value & MGC_M_TXCSR_H_NAKTIMEOUT)) ||
        !          1175: #else
        !          1176:                          (value & MGC_M_TXCSR_TXPKTRDY)) ||
        !          1177: #endif
        !          1178:                         (!ep &&
        !          1179: #ifdef CLEAR_NAK
        !          1180:                          (value & MGC_M_CSR0_TXPKTRDY) &&
        !          1181:                          !(value & MGC_M_CSR0_H_NAKTIMEOUT)))
        !          1182: #else
        !          1183:                          (value & MGC_M_CSR0_TXPKTRDY)))
        !          1184: #endif
        !          1185:             musb_tx_rdy(s, ep);
        !          1186:         if (!ep &&
        !          1187:                         (value & MGC_M_CSR0_H_REQPKT) &&
        !          1188: #ifdef CLEAR_NAK
        !          1189:                         !(value & (MGC_M_CSR0_H_NAKTIMEOUT |
        !          1190:                                         MGC_M_CSR0_RXPKTRDY)))
        !          1191: #else
        !          1192:                         !(value & MGC_M_CSR0_RXPKTRDY))
        !          1193: #endif
        !          1194:             musb_rx_req(s, ep);
        !          1195:         break;
        !          1196: 
        !          1197:     case MUSB_HDRC_RXMAXP:
        !          1198:         s->ep[ep].maxp[1] = value;
        !          1199:         break;
        !          1200:     case MUSB_HDRC_RXCSR:
        !          1201:         /* (DMA mode only) */
        !          1202:         if (
        !          1203:                 (value & MGC_M_RXCSR_H_AUTOREQ) &&
        !          1204:                 !(value & MGC_M_RXCSR_RXPKTRDY) &&
        !          1205:                 (s->ep[ep].csr[1] & MGC_M_RXCSR_RXPKTRDY))
        !          1206:             value |= MGC_M_RXCSR_H_REQPKT;
        !          1207: 
        !          1208:         s->ep[ep].csr[1] &= 0x102 | (value & 0x4d);
        !          1209:         s->ep[ep].csr[1] |= value & 0xfeb0;
        !          1210: 
        !          1211:         musb_ep_frame_cancel(&s->ep[ep], 1);
        !          1212: 
        !          1213:         if (value & MGC_M_RXCSR_FLUSHFIFO) {
        !          1214:             s->ep[ep].fifolen[1] = 0;
        !          1215:             s->ep[ep].fifostart[1] = 0;
        !          1216:             s->ep[ep].csr[1] &= ~(MGC_M_RXCSR_FIFOFULL | MGC_M_RXCSR_RXPKTRDY);
        !          1217:             /* If double buffering and we have two packets ready, flush
        !          1218:              * only the first one and set up the fifo at the second packet.  */
        !          1219:         }
        !          1220: #ifdef CLEAR_NAK
        !          1221:         if ((value & MGC_M_RXCSR_H_REQPKT) && !(value & MGC_M_RXCSR_DATAERROR))
        !          1222: #else
        !          1223:         if (value & MGC_M_RXCSR_H_REQPKT)
        !          1224: #endif
        !          1225:             musb_rx_req(s, ep);
        !          1226:         break;
        !          1227:     case MUSB_HDRC_RXCOUNT:
        !          1228:         s->ep[ep].rxcount = value;
        !          1229:         break;
        !          1230: 
        !          1231:     default:
        !          1232:         musb_ep_writeb(s, ep, addr, value & 0xff);
        !          1233:         musb_ep_writeb(s, ep, addr | 1, value >> 8);
        !          1234:     };
        !          1235: }
        !          1236: 
        !          1237: /* Generic control */
        !          1238: static uint32_t musb_readb(void *opaque, target_phys_addr_t addr)
        !          1239: {
        !          1240:     MUSBState *s = (MUSBState *) opaque;
        !          1241:     int ep, i;
        !          1242:     uint8_t ret;
        !          1243: 
        !          1244:     switch (addr) {
        !          1245:     case MUSB_HDRC_FADDR:
        !          1246:         return s->faddr;
        !          1247:     case MUSB_HDRC_POWER:
        !          1248:         return s->power;
        !          1249:     case MUSB_HDRC_INTRUSB:
        !          1250:         ret = s->intr;
        !          1251:         for (i = 0; i < sizeof(ret) * 8; i ++)
        !          1252:             if (ret & (1 << i))
        !          1253:                 musb_intr_set(s, i, 0);
        !          1254:         return ret;
        !          1255:     case MUSB_HDRC_INTRUSBE:
        !          1256:         return s->mask;
        !          1257:     case MUSB_HDRC_INDEX:
        !          1258:         return s->idx;
        !          1259:     case MUSB_HDRC_TESTMODE:
        !          1260:         return 0x00;
        !          1261: 
        !          1262:     case MUSB_HDRC_EP_IDX ... (MUSB_HDRC_EP_IDX + 0xf):
        !          1263:         return musb_ep_readb(s, s->idx, addr & 0xf);
        !          1264: 
        !          1265:     case MUSB_HDRC_DEVCTL:
        !          1266:         return s->devctl;
        !          1267: 
        !          1268:     case MUSB_HDRC_TXFIFOSZ:
        !          1269:     case MUSB_HDRC_RXFIFOSZ:
        !          1270:     case MUSB_HDRC_VCTRL:
        !          1271:         /* TODO */
        !          1272:         return 0x00;
        !          1273: 
        !          1274:     case MUSB_HDRC_HWVERS:
        !          1275:         return (1 << 10) | 400;
        !          1276: 
        !          1277:     case (MUSB_HDRC_VCTRL | 1):
        !          1278:     case (MUSB_HDRC_HWVERS | 1):
        !          1279:     case (MUSB_HDRC_DEVCTL | 1):
        !          1280:         return 0x00;
        !          1281: 
        !          1282:     case MUSB_HDRC_BUSCTL ... (MUSB_HDRC_BUSCTL + 0x7f):
        !          1283:         ep = (addr >> 3) & 0xf;
        !          1284:         return musb_busctl_readb(s, ep, addr & 0x7);
        !          1285: 
        !          1286:     case MUSB_HDRC_EP ... (MUSB_HDRC_EP + 0xff):
        !          1287:         ep = (addr >> 4) & 0xf;
        !          1288:         return musb_ep_readb(s, ep, addr & 0xf);
        !          1289: 
        !          1290:     case MUSB_HDRC_FIFO ... (MUSB_HDRC_FIFO + 0x3f):
        !          1291:         ep = ((addr - MUSB_HDRC_FIFO) >> 2) & 0xf;
        !          1292:         return musb_read_fifo(s->ep + ep);
        !          1293: 
        !          1294:     default:
        !          1295:         TRACE("unknown register 0x%02x", (int) addr);
        !          1296:         return 0x00;
        !          1297:     };
        !          1298: }
        !          1299: 
        !          1300: static void musb_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
        !          1301: {
        !          1302:     MUSBState *s = (MUSBState *) opaque;
        !          1303:     int ep;
        !          1304: 
        !          1305:     switch (addr) {
        !          1306:     case MUSB_HDRC_FADDR:
        !          1307:         s->faddr = value & 0x7f;
        !          1308:         break;
        !          1309:     case MUSB_HDRC_POWER:
        !          1310:         s->power = (value & 0xef) | (s->power & 0x10);
        !          1311:         /* MGC_M_POWER_RESET is also read-only in Peripheral Mode */
        !          1312:         if ((value & MGC_M_POWER_RESET) && s->port.dev) {
        !          1313:             usb_device_reset(s->port.dev);
        !          1314:             /* Negotiate high-speed operation if MGC_M_POWER_HSENAB is set.  */
        !          1315:             if ((value & MGC_M_POWER_HSENAB) &&
        !          1316:                             s->port.dev->speed == USB_SPEED_HIGH)
        !          1317:                 s->power |= MGC_M_POWER_HSMODE;        /* Success */
        !          1318:             /* Restart frame counting.  */
        !          1319:         }
        !          1320:         if (value & MGC_M_POWER_SUSPENDM) {
        !          1321:             /* When all transfers finish, suspend and if MGC_M_POWER_ENSUSPEND
        !          1322:              * is set, also go into low power mode.  Frame counting stops.  */
        !          1323:             /* XXX: Cleared when the interrupt register is read */
        !          1324:         }
        !          1325:         if (value & MGC_M_POWER_RESUME) {
        !          1326:             /* Wait 20ms and signal resuming on the bus.  Frame counting
        !          1327:              * restarts.  */
        !          1328:         }
        !          1329:         break;
        !          1330:     case MUSB_HDRC_INTRUSB:
        !          1331:         break;
        !          1332:     case MUSB_HDRC_INTRUSBE:
        !          1333:         s->mask = value & 0xff;
        !          1334:         break;
        !          1335:     case MUSB_HDRC_INDEX:
        !          1336:         s->idx = value & 0xf;
        !          1337:         break;
        !          1338:     case MUSB_HDRC_TESTMODE:
        !          1339:         break;
        !          1340: 
        !          1341:     case MUSB_HDRC_EP_IDX ... (MUSB_HDRC_EP_IDX + 0xf):
        !          1342:         musb_ep_writeb(s, s->idx, addr & 0xf, value);
        !          1343:         break;
        !          1344: 
        !          1345:     case MUSB_HDRC_DEVCTL:
        !          1346:         s->session = !!(value & MGC_M_DEVCTL_SESSION);
        !          1347:         musb_session_update(s,
        !          1348:                         !!s->port.dev,
        !          1349:                         !!(s->devctl & MGC_M_DEVCTL_SESSION));
        !          1350: 
        !          1351:         /* It seems this is the only R/W bit in this register?  */
        !          1352:         s->devctl &= ~MGC_M_DEVCTL_SESSION;
        !          1353:         s->devctl |= value & MGC_M_DEVCTL_SESSION;
        !          1354:         break;
        !          1355: 
        !          1356:     case MUSB_HDRC_TXFIFOSZ:
        !          1357:     case MUSB_HDRC_RXFIFOSZ:
        !          1358:     case MUSB_HDRC_VCTRL:
        !          1359:         /* TODO */
        !          1360:         break;
        !          1361: 
        !          1362:     case (MUSB_HDRC_VCTRL | 1):
        !          1363:     case (MUSB_HDRC_DEVCTL | 1):
        !          1364:         break;
        !          1365: 
        !          1366:     case MUSB_HDRC_BUSCTL ... (MUSB_HDRC_BUSCTL + 0x7f):
        !          1367:         ep = (addr >> 3) & 0xf;
        !          1368:         musb_busctl_writeb(s, ep, addr & 0x7, value);
        !          1369:         break;
        !          1370: 
        !          1371:     case MUSB_HDRC_EP ... (MUSB_HDRC_EP + 0xff):
        !          1372:         ep = (addr >> 4) & 0xf;
        !          1373:         musb_ep_writeb(s, ep, addr & 0xf, value);
        !          1374:         break;
        !          1375: 
        !          1376:     case MUSB_HDRC_FIFO ... (MUSB_HDRC_FIFO + 0x3f):
        !          1377:         ep = ((addr - MUSB_HDRC_FIFO) >> 2) & 0xf;
        !          1378:         musb_write_fifo(s->ep + ep, value & 0xff);
        !          1379:         break;
        !          1380: 
        !          1381:     default:
        !          1382:         TRACE("unknown register 0x%02x", (int) addr);
        !          1383:         break;
        !          1384:     };
        !          1385: }
        !          1386: 
        !          1387: static uint32_t musb_readh(void *opaque, target_phys_addr_t addr)
        !          1388: {
        !          1389:     MUSBState *s = (MUSBState *) opaque;
        !          1390:     int ep, i;
        !          1391:     uint16_t ret;
        !          1392: 
        !          1393:     switch (addr) {
        !          1394:     case MUSB_HDRC_INTRTX:
        !          1395:         ret = s->tx_intr;
        !          1396:         /* Auto clear */
        !          1397:         for (i = 0; i < sizeof(ret) * 8; i ++)
        !          1398:             if (ret & (1 << i))
        !          1399:                 musb_tx_intr_set(s, i, 0);
        !          1400:         return ret;
        !          1401:     case MUSB_HDRC_INTRRX:
        !          1402:         ret = s->rx_intr;
        !          1403:         /* Auto clear */
        !          1404:         for (i = 0; i < sizeof(ret) * 8; i ++)
        !          1405:             if (ret & (1 << i))
        !          1406:                 musb_rx_intr_set(s, i, 0);
        !          1407:         return ret;
        !          1408:     case MUSB_HDRC_INTRTXE:
        !          1409:         return s->tx_mask;
        !          1410:     case MUSB_HDRC_INTRRXE:
        !          1411:         return s->rx_mask;
        !          1412: 
        !          1413:     case MUSB_HDRC_FRAME:
        !          1414:         /* TODO */
        !          1415:         return 0x0000;
        !          1416:     case MUSB_HDRC_TXFIFOADDR:
        !          1417:         return s->ep[s->idx].fifoaddr[0];
        !          1418:     case MUSB_HDRC_RXFIFOADDR:
        !          1419:         return s->ep[s->idx].fifoaddr[1];
        !          1420: 
        !          1421:     case MUSB_HDRC_EP_IDX ... (MUSB_HDRC_EP_IDX + 0xf):
        !          1422:         return musb_ep_readh(s, s->idx, addr & 0xf);
        !          1423: 
        !          1424:     case MUSB_HDRC_BUSCTL ... (MUSB_HDRC_BUSCTL + 0x7f):
        !          1425:         ep = (addr >> 3) & 0xf;
        !          1426:         return musb_busctl_readh(s, ep, addr & 0x7);
        !          1427: 
        !          1428:     case MUSB_HDRC_EP ... (MUSB_HDRC_EP + 0xff):
        !          1429:         ep = (addr >> 4) & 0xf;
        !          1430:         return musb_ep_readh(s, ep, addr & 0xf);
        !          1431: 
        !          1432:     case MUSB_HDRC_FIFO ... (MUSB_HDRC_FIFO + 0x3f):
        !          1433:         ep = ((addr - MUSB_HDRC_FIFO) >> 2) & 0xf;
        !          1434:         return (musb_read_fifo(s->ep + ep) | musb_read_fifo(s->ep + ep) << 8);
        !          1435: 
        !          1436:     default:
        !          1437:         return musb_readb(s, addr) | (musb_readb(s, addr | 1) << 8);
        !          1438:     };
        !          1439: }
        !          1440: 
        !          1441: static void musb_writeh(void *opaque, target_phys_addr_t addr, uint32_t value)
        !          1442: {
        !          1443:     MUSBState *s = (MUSBState *) opaque;
        !          1444:     int ep;
        !          1445: 
        !          1446:     switch (addr) {
        !          1447:     case MUSB_HDRC_INTRTXE:
        !          1448:         s->tx_mask = value;
        !          1449:         /* XXX: the masks seem to apply on the raising edge like with
        !          1450:          * edge-triggered interrupts, thus no need to update.  I may be
        !          1451:          * wrong though.  */
        !          1452:         break;
        !          1453:     case MUSB_HDRC_INTRRXE:
        !          1454:         s->rx_mask = value;
        !          1455:         break;
        !          1456: 
        !          1457:     case MUSB_HDRC_FRAME:
        !          1458:         /* TODO */
        !          1459:         break;
        !          1460:     case MUSB_HDRC_TXFIFOADDR:
        !          1461:         s->ep[s->idx].fifoaddr[0] = value;
        !          1462:         s->ep[s->idx].buf[0] =
        !          1463:                 s->buf + ((value << 3) & 0x7ff );
        !          1464:         break;
        !          1465:     case MUSB_HDRC_RXFIFOADDR:
        !          1466:         s->ep[s->idx].fifoaddr[1] = value;
        !          1467:         s->ep[s->idx].buf[1] =
        !          1468:                 s->buf + ((value << 3) & 0x7ff);
        !          1469:         break;
        !          1470: 
        !          1471:     case MUSB_HDRC_EP_IDX ... (MUSB_HDRC_EP_IDX + 0xf):
        !          1472:         musb_ep_writeh(s, s->idx, addr & 0xf, value);
        !          1473:         break;
        !          1474: 
        !          1475:     case MUSB_HDRC_BUSCTL ... (MUSB_HDRC_BUSCTL + 0x7f):
        !          1476:         ep = (addr >> 3) & 0xf;
        !          1477:         musb_busctl_writeh(s, ep, addr & 0x7, value);
        !          1478:         break;
        !          1479: 
        !          1480:     case MUSB_HDRC_EP ... (MUSB_HDRC_EP + 0xff):
        !          1481:         ep = (addr >> 4) & 0xf;
        !          1482:         musb_ep_writeh(s, ep, addr & 0xf, value);
        !          1483:         break;
        !          1484: 
        !          1485:     case MUSB_HDRC_FIFO ... (MUSB_HDRC_FIFO + 0x3f):
        !          1486:         ep = ((addr - MUSB_HDRC_FIFO) >> 2) & 0xf;
        !          1487:         musb_write_fifo(s->ep + ep, value & 0xff);
        !          1488:         musb_write_fifo(s->ep + ep, (value >> 8) & 0xff);
        !          1489:         break;
        !          1490: 
        !          1491:     default:
        !          1492:         musb_writeb(s, addr, value & 0xff);
        !          1493:         musb_writeb(s, addr | 1, value >> 8);
        !          1494:     };
        !          1495: }
        !          1496: 
        !          1497: static uint32_t musb_readw(void *opaque, target_phys_addr_t addr)
        !          1498: {
        !          1499:     MUSBState *s = (MUSBState *) opaque;
        !          1500:     int ep;
        !          1501: 
        !          1502:     switch (addr) {
        !          1503:     case MUSB_HDRC_FIFO ... (MUSB_HDRC_FIFO + 0x3f):
        !          1504:         ep = ((addr - MUSB_HDRC_FIFO) >> 2) & 0xf;
        !          1505:         return ( musb_read_fifo(s->ep + ep)       |
        !          1506:                  musb_read_fifo(s->ep + ep) << 8  |
        !          1507:                  musb_read_fifo(s->ep + ep) << 16 |
        !          1508:                  musb_read_fifo(s->ep + ep) << 24 );
        !          1509:     default:
        !          1510:         TRACE("unknown register 0x%02x", (int) addr);
        !          1511:         return 0x00000000;
        !          1512:     };
        !          1513: }
        !          1514: 
        !          1515: static void musb_writew(void *opaque, target_phys_addr_t addr, uint32_t value)
        !          1516: {
        !          1517:     MUSBState *s = (MUSBState *) opaque;
        !          1518:     int ep;
        !          1519: 
        !          1520:     switch (addr) {
        !          1521:     case MUSB_HDRC_FIFO ... (MUSB_HDRC_FIFO + 0x3f):
        !          1522:         ep = ((addr - MUSB_HDRC_FIFO) >> 2) & 0xf;
        !          1523:         musb_write_fifo(s->ep + ep, value & 0xff);
        !          1524:         musb_write_fifo(s->ep + ep, (value >> 8 ) & 0xff);
        !          1525:         musb_write_fifo(s->ep + ep, (value >> 16) & 0xff);
        !          1526:         musb_write_fifo(s->ep + ep, (value >> 24) & 0xff);
        !          1527:             break;
        !          1528:     default:
        !          1529:         TRACE("unknown register 0x%02x", (int) addr);
        !          1530:         break;
        !          1531:     };
        !          1532: }
        !          1533: 
        !          1534: CPUReadMemoryFunc * const musb_read[] = {
        !          1535:     musb_readb,
        !          1536:     musb_readh,
        !          1537:     musb_readw,
        !          1538: };
        !          1539: 
        !          1540: CPUWriteMemoryFunc * const musb_write[] = {
        !          1541:     musb_writeb,
        !          1542:     musb_writeh,
        !          1543:     musb_writew,
        !          1544: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.