Annotation of qemu/hw/usb/hcd-musb.c, revision 1.1.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.