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

1.1     ! root        1: /*
        !             2:  * QEMU USB OHCI Emulation
        !             3:  * Copyright (c) 2004 Gianni Tedesco
        !             4:  * Copyright (c) 2006 CodeSourcery
        !             5:  * Copyright (c) 2006 Openedhand Ltd.
        !             6:  *
        !             7:  * This library is free software; you can redistribute it and/or
        !             8:  * modify it under the terms of the GNU Lesser General Public
        !             9:  * License as published by the Free Software Foundation; either
        !            10:  * version 2 of the License, or (at your option) any later version.
        !            11:  *
        !            12:  * This library is distributed in the hope that it will be useful,
        !            13:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            14:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
        !            15:  * Lesser General Public License for more details.
        !            16:  *
        !            17:  * You should have received a copy of the GNU Lesser General Public
        !            18:  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
        !            19:  *
        !            20:  * TODO:
        !            21:  *  o Isochronous transfers
        !            22:  *  o Allocate bandwidth in frames properly
        !            23:  *  o Disable timers when nothing needs to be done, or remove timer usage
        !            24:  *    all together.
        !            25:  *  o Handle unrecoverable errors properly
        !            26:  *  o BIOS work to boot from USB storage
        !            27: */
        !            28: 
        !            29: #include "hw/hw.h"
        !            30: #include "qemu-timer.h"
        !            31: #include "hw/usb.h"
        !            32: #include "hw/pci.h"
        !            33: #include "hw/sysbus.h"
        !            34: #include "hw/qdev-addr.h"
        !            35: 
        !            36: //#define DEBUG_OHCI
        !            37: /* Dump packet contents.  */
        !            38: //#define DEBUG_PACKET
        !            39: //#define DEBUG_ISOCH
        !            40: /* This causes frames to occur 1000x slower */
        !            41: //#define OHCI_TIME_WARP 1
        !            42: 
        !            43: #ifdef DEBUG_OHCI
        !            44: #define DPRINTF printf
        !            45: #else
        !            46: #define DPRINTF(...)
        !            47: #endif
        !            48: 
        !            49: /* Number of Downstream Ports on the root hub.  */
        !            50: 
        !            51: #define OHCI_MAX_PORTS 15
        !            52: 
        !            53: static int64_t usb_frame_time;
        !            54: static int64_t usb_bit_time;
        !            55: 
        !            56: typedef struct OHCIPort {
        !            57:     USBPort port;
        !            58:     uint32_t ctrl;
        !            59: } OHCIPort;
        !            60: 
        !            61: typedef struct {
        !            62:     USBBus bus;
        !            63:     qemu_irq irq;
        !            64:     MemoryRegion mem;
        !            65:     int num_ports;
        !            66:     const char *name;
        !            67: 
        !            68:     QEMUTimer *eof_timer;
        !            69:     int64_t sof_time;
        !            70: 
        !            71:     /* OHCI state */
        !            72:     /* Control partition */
        !            73:     uint32_t ctl, status;
        !            74:     uint32_t intr_status;
        !            75:     uint32_t intr;
        !            76: 
        !            77:     /* memory pointer partition */
        !            78:     uint32_t hcca;
        !            79:     uint32_t ctrl_head, ctrl_cur;
        !            80:     uint32_t bulk_head, bulk_cur;
        !            81:     uint32_t per_cur;
        !            82:     uint32_t done;
        !            83:     int done_count;
        !            84: 
        !            85:     /* Frame counter partition */
        !            86:     uint32_t fsmps:15;
        !            87:     uint32_t fit:1;
        !            88:     uint32_t fi:14;
        !            89:     uint32_t frt:1;
        !            90:     uint16_t frame_number;
        !            91:     uint16_t padding;
        !            92:     uint32_t pstart;
        !            93:     uint32_t lst;
        !            94: 
        !            95:     /* Root Hub partition */
        !            96:     uint32_t rhdesc_a, rhdesc_b;
        !            97:     uint32_t rhstatus;
        !            98:     OHCIPort rhport[OHCI_MAX_PORTS];
        !            99: 
        !           100:     /* PXA27x Non-OHCI events */
        !           101:     uint32_t hstatus;
        !           102:     uint32_t hmask;
        !           103:     uint32_t hreset;
        !           104:     uint32_t htest;
        !           105: 
        !           106:     /* SM501 local memory offset */
        !           107:     target_phys_addr_t localmem_base;
        !           108: 
        !           109:     /* Active packets.  */
        !           110:     uint32_t old_ctl;
        !           111:     USBPacket usb_packet;
        !           112:     uint8_t usb_buf[8192];
        !           113:     uint32_t async_td;
        !           114:     int async_complete;
        !           115: 
        !           116: } OHCIState;
        !           117: 
        !           118: /* Host Controller Communications Area */
        !           119: struct ohci_hcca {
        !           120:     uint32_t intr[32];
        !           121:     uint16_t frame, pad;
        !           122:     uint32_t done;
        !           123: };
        !           124: #define HCCA_WRITEBACK_OFFSET   offsetof(struct ohci_hcca, frame)
        !           125: #define HCCA_WRITEBACK_SIZE     8 /* frame, pad, done */
        !           126: 
        !           127: #define ED_WBACK_OFFSET offsetof(struct ohci_ed, head)
        !           128: #define ED_WBACK_SIZE   4
        !           129: 
        !           130: static void ohci_bus_stop(OHCIState *ohci);
        !           131: static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev);
        !           132: 
        !           133: /* Bitfields for the first word of an Endpoint Desciptor.  */
        !           134: #define OHCI_ED_FA_SHIFT  0
        !           135: #define OHCI_ED_FA_MASK   (0x7f<<OHCI_ED_FA_SHIFT)
        !           136: #define OHCI_ED_EN_SHIFT  7
        !           137: #define OHCI_ED_EN_MASK   (0xf<<OHCI_ED_EN_SHIFT)
        !           138: #define OHCI_ED_D_SHIFT   11
        !           139: #define OHCI_ED_D_MASK    (3<<OHCI_ED_D_SHIFT)
        !           140: #define OHCI_ED_S         (1<<13)
        !           141: #define OHCI_ED_K         (1<<14)
        !           142: #define OHCI_ED_F         (1<<15)
        !           143: #define OHCI_ED_MPS_SHIFT 16
        !           144: #define OHCI_ED_MPS_MASK  (0x7ff<<OHCI_ED_MPS_SHIFT)
        !           145: 
        !           146: /* Flags in the head field of an Endpoint Desciptor.  */
        !           147: #define OHCI_ED_H         1
        !           148: #define OHCI_ED_C         2
        !           149: 
        !           150: /* Bitfields for the first word of a Transfer Desciptor.  */
        !           151: #define OHCI_TD_R         (1<<18)
        !           152: #define OHCI_TD_DP_SHIFT  19
        !           153: #define OHCI_TD_DP_MASK   (3<<OHCI_TD_DP_SHIFT)
        !           154: #define OHCI_TD_DI_SHIFT  21
        !           155: #define OHCI_TD_DI_MASK   (7<<OHCI_TD_DI_SHIFT)
        !           156: #define OHCI_TD_T0        (1<<24)
        !           157: #define OHCI_TD_T1        (1<<25)
        !           158: #define OHCI_TD_EC_SHIFT  26
        !           159: #define OHCI_TD_EC_MASK   (3<<OHCI_TD_EC_SHIFT)
        !           160: #define OHCI_TD_CC_SHIFT  28
        !           161: #define OHCI_TD_CC_MASK   (0xf<<OHCI_TD_CC_SHIFT)
        !           162: 
        !           163: /* Bitfields for the first word of an Isochronous Transfer Desciptor.  */
        !           164: /* CC & DI - same as in the General Transfer Desciptor */
        !           165: #define OHCI_TD_SF_SHIFT  0
        !           166: #define OHCI_TD_SF_MASK   (0xffff<<OHCI_TD_SF_SHIFT)
        !           167: #define OHCI_TD_FC_SHIFT  24
        !           168: #define OHCI_TD_FC_MASK   (7<<OHCI_TD_FC_SHIFT)
        !           169: 
        !           170: /* Isochronous Transfer Desciptor - Offset / PacketStatusWord */
        !           171: #define OHCI_TD_PSW_CC_SHIFT 12
        !           172: #define OHCI_TD_PSW_CC_MASK  (0xf<<OHCI_TD_PSW_CC_SHIFT)
        !           173: #define OHCI_TD_PSW_SIZE_SHIFT 0
        !           174: #define OHCI_TD_PSW_SIZE_MASK  (0xfff<<OHCI_TD_PSW_SIZE_SHIFT)
        !           175: 
        !           176: #define OHCI_PAGE_MASK    0xfffff000
        !           177: #define OHCI_OFFSET_MASK  0xfff
        !           178: 
        !           179: #define OHCI_DPTR_MASK    0xfffffff0
        !           180: 
        !           181: #define OHCI_BM(val, field) \
        !           182:   (((val) & OHCI_##field##_MASK) >> OHCI_##field##_SHIFT)
        !           183: 
        !           184: #define OHCI_SET_BM(val, field, newval) do { \
        !           185:     val &= ~OHCI_##field##_MASK; \
        !           186:     val |= ((newval) << OHCI_##field##_SHIFT) & OHCI_##field##_MASK; \
        !           187:     } while(0)
        !           188: 
        !           189: /* endpoint descriptor */
        !           190: struct ohci_ed {
        !           191:     uint32_t flags;
        !           192:     uint32_t tail;
        !           193:     uint32_t head;
        !           194:     uint32_t next;
        !           195: };
        !           196: 
        !           197: /* General transfer descriptor */
        !           198: struct ohci_td {
        !           199:     uint32_t flags;
        !           200:     uint32_t cbp;
        !           201:     uint32_t next;
        !           202:     uint32_t be;
        !           203: };
        !           204: 
        !           205: /* Isochronous transfer descriptor */
        !           206: struct ohci_iso_td {
        !           207:     uint32_t flags;
        !           208:     uint32_t bp;
        !           209:     uint32_t next;
        !           210:     uint32_t be;
        !           211:     uint16_t offset[8];
        !           212: };
        !           213: 
        !           214: #define USB_HZ                      12000000
        !           215: 
        !           216: /* OHCI Local stuff */
        !           217: #define OHCI_CTL_CBSR         ((1<<0)|(1<<1))
        !           218: #define OHCI_CTL_PLE          (1<<2)
        !           219: #define OHCI_CTL_IE           (1<<3)
        !           220: #define OHCI_CTL_CLE          (1<<4)
        !           221: #define OHCI_CTL_BLE          (1<<5)
        !           222: #define OHCI_CTL_HCFS         ((1<<6)|(1<<7))
        !           223: #define  OHCI_USB_RESET       0x00
        !           224: #define  OHCI_USB_RESUME      0x40
        !           225: #define  OHCI_USB_OPERATIONAL 0x80
        !           226: #define  OHCI_USB_SUSPEND     0xc0
        !           227: #define OHCI_CTL_IR           (1<<8)
        !           228: #define OHCI_CTL_RWC          (1<<9)
        !           229: #define OHCI_CTL_RWE          (1<<10)
        !           230: 
        !           231: #define OHCI_STATUS_HCR       (1<<0)
        !           232: #define OHCI_STATUS_CLF       (1<<1)
        !           233: #define OHCI_STATUS_BLF       (1<<2)
        !           234: #define OHCI_STATUS_OCR       (1<<3)
        !           235: #define OHCI_STATUS_SOC       ((1<<6)|(1<<7))
        !           236: 
        !           237: #define OHCI_INTR_SO          (1<<0) /* Scheduling overrun */
        !           238: #define OHCI_INTR_WD          (1<<1) /* HcDoneHead writeback */
        !           239: #define OHCI_INTR_SF          (1<<2) /* Start of frame */
        !           240: #define OHCI_INTR_RD          (1<<3) /* Resume detect */
        !           241: #define OHCI_INTR_UE          (1<<4) /* Unrecoverable error */
        !           242: #define OHCI_INTR_FNO         (1<<5) /* Frame number overflow */
        !           243: #define OHCI_INTR_RHSC        (1<<6) /* Root hub status change */
        !           244: #define OHCI_INTR_OC          (1<<30) /* Ownership change */
        !           245: #define OHCI_INTR_MIE         (1<<31) /* Master Interrupt Enable */
        !           246: 
        !           247: #define OHCI_HCCA_SIZE        0x100
        !           248: #define OHCI_HCCA_MASK        0xffffff00
        !           249: 
        !           250: #define OHCI_EDPTR_MASK       0xfffffff0
        !           251: 
        !           252: #define OHCI_FMI_FI           0x00003fff
        !           253: #define OHCI_FMI_FSMPS        0xffff0000
        !           254: #define OHCI_FMI_FIT          0x80000000
        !           255: 
        !           256: #define OHCI_FR_RT            (1<<31)
        !           257: 
        !           258: #define OHCI_LS_THRESH        0x628
        !           259: 
        !           260: #define OHCI_RHA_RW_MASK      0x00000000 /* Mask of supported features.  */
        !           261: #define OHCI_RHA_PSM          (1<<8)
        !           262: #define OHCI_RHA_NPS          (1<<9)
        !           263: #define OHCI_RHA_DT           (1<<10)
        !           264: #define OHCI_RHA_OCPM         (1<<11)
        !           265: #define OHCI_RHA_NOCP         (1<<12)
        !           266: #define OHCI_RHA_POTPGT_MASK  0xff000000
        !           267: 
        !           268: #define OHCI_RHS_LPS          (1<<0)
        !           269: #define OHCI_RHS_OCI          (1<<1)
        !           270: #define OHCI_RHS_DRWE         (1<<15)
        !           271: #define OHCI_RHS_LPSC         (1<<16)
        !           272: #define OHCI_RHS_OCIC         (1<<17)
        !           273: #define OHCI_RHS_CRWE         (1<<31)
        !           274: 
        !           275: #define OHCI_PORT_CCS         (1<<0)
        !           276: #define OHCI_PORT_PES         (1<<1)
        !           277: #define OHCI_PORT_PSS         (1<<2)
        !           278: #define OHCI_PORT_POCI        (1<<3)
        !           279: #define OHCI_PORT_PRS         (1<<4)
        !           280: #define OHCI_PORT_PPS         (1<<8)
        !           281: #define OHCI_PORT_LSDA        (1<<9)
        !           282: #define OHCI_PORT_CSC         (1<<16)
        !           283: #define OHCI_PORT_PESC        (1<<17)
        !           284: #define OHCI_PORT_PSSC        (1<<18)
        !           285: #define OHCI_PORT_OCIC        (1<<19)
        !           286: #define OHCI_PORT_PRSC        (1<<20)
        !           287: #define OHCI_PORT_WTC         (OHCI_PORT_CSC|OHCI_PORT_PESC|OHCI_PORT_PSSC \
        !           288:                                |OHCI_PORT_OCIC|OHCI_PORT_PRSC)
        !           289: 
        !           290: #define OHCI_TD_DIR_SETUP     0x0
        !           291: #define OHCI_TD_DIR_OUT       0x1
        !           292: #define OHCI_TD_DIR_IN        0x2
        !           293: #define OHCI_TD_DIR_RESERVED  0x3
        !           294: 
        !           295: #define OHCI_CC_NOERROR             0x0
        !           296: #define OHCI_CC_CRC                 0x1
        !           297: #define OHCI_CC_BITSTUFFING         0x2
        !           298: #define OHCI_CC_DATATOGGLEMISMATCH  0x3
        !           299: #define OHCI_CC_STALL               0x4
        !           300: #define OHCI_CC_DEVICENOTRESPONDING 0x5
        !           301: #define OHCI_CC_PIDCHECKFAILURE     0x6
        !           302: #define OHCI_CC_UNDEXPETEDPID       0x7
        !           303: #define OHCI_CC_DATAOVERRUN         0x8
        !           304: #define OHCI_CC_DATAUNDERRUN        0x9
        !           305: #define OHCI_CC_BUFFEROVERRUN       0xc
        !           306: #define OHCI_CC_BUFFERUNDERRUN      0xd
        !           307: 
        !           308: #define OHCI_HRESET_FSBIR       (1 << 0)
        !           309: 
        !           310: /* Update IRQ levels */
        !           311: static inline void ohci_intr_update(OHCIState *ohci)
        !           312: {
        !           313:     int level = 0;
        !           314: 
        !           315:     if ((ohci->intr & OHCI_INTR_MIE) &&
        !           316:         (ohci->intr_status & ohci->intr))
        !           317:         level = 1;
        !           318: 
        !           319:     qemu_set_irq(ohci->irq, level);
        !           320: }
        !           321: 
        !           322: /* Set an interrupt */
        !           323: static inline void ohci_set_interrupt(OHCIState *ohci, uint32_t intr)
        !           324: {
        !           325:     ohci->intr_status |= intr;
        !           326:     ohci_intr_update(ohci);
        !           327: }
        !           328: 
        !           329: /* Attach or detach a device on a root hub port.  */
        !           330: static void ohci_attach(USBPort *port1)
        !           331: {
        !           332:     OHCIState *s = port1->opaque;
        !           333:     OHCIPort *port = &s->rhport[port1->index];
        !           334:     uint32_t old_state = port->ctrl;
        !           335: 
        !           336:     /* set connect status */
        !           337:     port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC;
        !           338: 
        !           339:     /* update speed */
        !           340:     if (port->port.dev->speed == USB_SPEED_LOW) {
        !           341:         port->ctrl |= OHCI_PORT_LSDA;
        !           342:     } else {
        !           343:         port->ctrl &= ~OHCI_PORT_LSDA;
        !           344:     }
        !           345: 
        !           346:     /* notify of remote-wakeup */
        !           347:     if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) {
        !           348:         ohci_set_interrupt(s, OHCI_INTR_RD);
        !           349:     }
        !           350: 
        !           351:     DPRINTF("usb-ohci: Attached port %d\n", port1->index);
        !           352: 
        !           353:     if (old_state != port->ctrl) {
        !           354:         ohci_set_interrupt(s, OHCI_INTR_RHSC);
        !           355:     }
        !           356: }
        !           357: 
        !           358: static void ohci_detach(USBPort *port1)
        !           359: {
        !           360:     OHCIState *s = port1->opaque;
        !           361:     OHCIPort *port = &s->rhport[port1->index];
        !           362:     uint32_t old_state = port->ctrl;
        !           363: 
        !           364:     ohci_async_cancel_device(s, port1->dev);
        !           365: 
        !           366:     /* set connect status */
        !           367:     if (port->ctrl & OHCI_PORT_CCS) {
        !           368:         port->ctrl &= ~OHCI_PORT_CCS;
        !           369:         port->ctrl |= OHCI_PORT_CSC;
        !           370:     }
        !           371:     /* disable port */
        !           372:     if (port->ctrl & OHCI_PORT_PES) {
        !           373:         port->ctrl &= ~OHCI_PORT_PES;
        !           374:         port->ctrl |= OHCI_PORT_PESC;
        !           375:     }
        !           376:     DPRINTF("usb-ohci: Detached port %d\n", port1->index);
        !           377: 
        !           378:     if (old_state != port->ctrl) {
        !           379:         ohci_set_interrupt(s, OHCI_INTR_RHSC);
        !           380:     }
        !           381: }
        !           382: 
        !           383: static void ohci_wakeup(USBPort *port1)
        !           384: {
        !           385:     OHCIState *s = port1->opaque;
        !           386:     OHCIPort *port = &s->rhport[port1->index];
        !           387:     uint32_t intr = 0;
        !           388:     if (port->ctrl & OHCI_PORT_PSS) {
        !           389:         DPRINTF("usb-ohci: port %d: wakeup\n", port1->index);
        !           390:         port->ctrl |= OHCI_PORT_PSSC;
        !           391:         port->ctrl &= ~OHCI_PORT_PSS;
        !           392:         intr = OHCI_INTR_RHSC;
        !           393:     }
        !           394:     /* Note that the controller can be suspended even if this port is not */
        !           395:     if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) {
        !           396:         DPRINTF("usb-ohci: remote-wakeup: SUSPEND->RESUME\n");
        !           397:         /* This is the one state transition the controller can do by itself */
        !           398:         s->ctl &= ~OHCI_CTL_HCFS;
        !           399:         s->ctl |= OHCI_USB_RESUME;
        !           400:         /* In suspend mode only ResumeDetected is possible, not RHSC:
        !           401:          * see the OHCI spec 5.1.2.3.
        !           402:          */
        !           403:         intr = OHCI_INTR_RD;
        !           404:     }
        !           405:     ohci_set_interrupt(s, intr);
        !           406: }
        !           407: 
        !           408: static void ohci_child_detach(USBPort *port1, USBDevice *child)
        !           409: {
        !           410:     OHCIState *s = port1->opaque;
        !           411: 
        !           412:     ohci_async_cancel_device(s, child);
        !           413: }
        !           414: 
        !           415: static USBDevice *ohci_find_device(OHCIState *ohci, uint8_t addr)
        !           416: {
        !           417:     USBDevice *dev;
        !           418:     int i;
        !           419: 
        !           420:     for (i = 0; i < ohci->num_ports; i++) {
        !           421:         if ((ohci->rhport[i].ctrl & OHCI_PORT_PES) == 0) {
        !           422:             continue;
        !           423:         }
        !           424:         dev = usb_find_device(&ohci->rhport[i].port, addr);
        !           425:         if (dev != NULL) {
        !           426:             return dev;
        !           427:         }
        !           428:     }
        !           429:     return NULL;
        !           430: }
        !           431: 
        !           432: /* Reset the controller */
        !           433: static void ohci_reset(void *opaque)
        !           434: {
        !           435:     OHCIState *ohci = opaque;
        !           436:     OHCIPort *port;
        !           437:     int i;
        !           438: 
        !           439:     ohci_bus_stop(ohci);
        !           440:     ohci->ctl = 0;
        !           441:     ohci->old_ctl = 0;
        !           442:     ohci->status = 0;
        !           443:     ohci->intr_status = 0;
        !           444:     ohci->intr = OHCI_INTR_MIE;
        !           445: 
        !           446:     ohci->hcca = 0;
        !           447:     ohci->ctrl_head = ohci->ctrl_cur = 0;
        !           448:     ohci->bulk_head = ohci->bulk_cur = 0;
        !           449:     ohci->per_cur = 0;
        !           450:     ohci->done = 0;
        !           451:     ohci->done_count = 7;
        !           452: 
        !           453:     /* FSMPS is marked TBD in OCHI 1.0, what gives ffs?
        !           454:      * I took the value linux sets ...
        !           455:      */
        !           456:     ohci->fsmps = 0x2778;
        !           457:     ohci->fi = 0x2edf;
        !           458:     ohci->fit = 0;
        !           459:     ohci->frt = 0;
        !           460:     ohci->frame_number = 0;
        !           461:     ohci->pstart = 0;
        !           462:     ohci->lst = OHCI_LS_THRESH;
        !           463: 
        !           464:     ohci->rhdesc_a = OHCI_RHA_NPS | ohci->num_ports;
        !           465:     ohci->rhdesc_b = 0x0; /* Impl. specific */
        !           466:     ohci->rhstatus = 0;
        !           467: 
        !           468:     for (i = 0; i < ohci->num_ports; i++)
        !           469:       {
        !           470:         port = &ohci->rhport[i];
        !           471:         port->ctrl = 0;
        !           472:         if (port->port.dev && port->port.dev->attached) {
        !           473:             usb_port_reset(&port->port);
        !           474:         }
        !           475:       }
        !           476:     if (ohci->async_td) {
        !           477:         usb_cancel_packet(&ohci->usb_packet);
        !           478:         ohci->async_td = 0;
        !           479:     }
        !           480:     DPRINTF("usb-ohci: Reset %s\n", ohci->name);
        !           481: }
        !           482: 
        !           483: /* Get an array of dwords from main memory */
        !           484: static inline int get_dwords(OHCIState *ohci,
        !           485:                              uint32_t addr, uint32_t *buf, int num)
        !           486: {
        !           487:     int i;
        !           488: 
        !           489:     addr += ohci->localmem_base;
        !           490: 
        !           491:     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
        !           492:         cpu_physical_memory_read(addr, buf, sizeof(*buf));
        !           493:         *buf = le32_to_cpu(*buf);
        !           494:     }
        !           495: 
        !           496:     return 1;
        !           497: }
        !           498: 
        !           499: /* Put an array of dwords in to main memory */
        !           500: static inline int put_dwords(OHCIState *ohci,
        !           501:                              uint32_t addr, uint32_t *buf, int num)
        !           502: {
        !           503:     int i;
        !           504: 
        !           505:     addr += ohci->localmem_base;
        !           506: 
        !           507:     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
        !           508:         uint32_t tmp = cpu_to_le32(*buf);
        !           509:         cpu_physical_memory_write(addr, &tmp, sizeof(tmp));
        !           510:     }
        !           511: 
        !           512:     return 1;
        !           513: }
        !           514: 
        !           515: /* Get an array of words from main memory */
        !           516: static inline int get_words(OHCIState *ohci,
        !           517:                             uint32_t addr, uint16_t *buf, int num)
        !           518: {
        !           519:     int i;
        !           520: 
        !           521:     addr += ohci->localmem_base;
        !           522: 
        !           523:     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
        !           524:         cpu_physical_memory_read(addr, buf, sizeof(*buf));
        !           525:         *buf = le16_to_cpu(*buf);
        !           526:     }
        !           527: 
        !           528:     return 1;
        !           529: }
        !           530: 
        !           531: /* Put an array of words in to main memory */
        !           532: static inline int put_words(OHCIState *ohci,
        !           533:                             uint32_t addr, uint16_t *buf, int num)
        !           534: {
        !           535:     int i;
        !           536: 
        !           537:     addr += ohci->localmem_base;
        !           538: 
        !           539:     for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
        !           540:         uint16_t tmp = cpu_to_le16(*buf);
        !           541:         cpu_physical_memory_write(addr, &tmp, sizeof(tmp));
        !           542:     }
        !           543: 
        !           544:     return 1;
        !           545: }
        !           546: 
        !           547: static inline int ohci_read_ed(OHCIState *ohci,
        !           548:                                uint32_t addr, struct ohci_ed *ed)
        !           549: {
        !           550:     return get_dwords(ohci, addr, (uint32_t *)ed, sizeof(*ed) >> 2);
        !           551: }
        !           552: 
        !           553: static inline int ohci_read_td(OHCIState *ohci,
        !           554:                                uint32_t addr, struct ohci_td *td)
        !           555: {
        !           556:     return get_dwords(ohci, addr, (uint32_t *)td, sizeof(*td) >> 2);
        !           557: }
        !           558: 
        !           559: static inline int ohci_read_iso_td(OHCIState *ohci,
        !           560:                                    uint32_t addr, struct ohci_iso_td *td)
        !           561: {
        !           562:     return (get_dwords(ohci, addr, (uint32_t *)td, 4) &&
        !           563:             get_words(ohci, addr + 16, td->offset, 8));
        !           564: }
        !           565: 
        !           566: static inline int ohci_read_hcca(OHCIState *ohci,
        !           567:                                  uint32_t addr, struct ohci_hcca *hcca)
        !           568: {
        !           569:     cpu_physical_memory_read(addr + ohci->localmem_base, hcca, sizeof(*hcca));
        !           570:     return 1;
        !           571: }
        !           572: 
        !           573: static inline int ohci_put_ed(OHCIState *ohci,
        !           574:                               uint32_t addr, struct ohci_ed *ed)
        !           575: {
        !           576:     /* ed->tail is under control of the HCD.
        !           577:      * Since just ed->head is changed by HC, just write back this
        !           578:      */
        !           579: 
        !           580:     return put_dwords(ohci, addr + ED_WBACK_OFFSET,
        !           581:                       (uint32_t *)((char *)ed + ED_WBACK_OFFSET),
        !           582:                       ED_WBACK_SIZE >> 2);
        !           583: }
        !           584: 
        !           585: static inline int ohci_put_td(OHCIState *ohci,
        !           586:                               uint32_t addr, struct ohci_td *td)
        !           587: {
        !           588:     return put_dwords(ohci, addr, (uint32_t *)td, sizeof(*td) >> 2);
        !           589: }
        !           590: 
        !           591: static inline int ohci_put_iso_td(OHCIState *ohci,
        !           592:                                   uint32_t addr, struct ohci_iso_td *td)
        !           593: {
        !           594:     return (put_dwords(ohci, addr, (uint32_t *)td, 4) &&
        !           595:             put_words(ohci, addr + 16, td->offset, 8));
        !           596: }
        !           597: 
        !           598: static inline int ohci_put_hcca(OHCIState *ohci,
        !           599:                                 uint32_t addr, struct ohci_hcca *hcca)
        !           600: {
        !           601:     cpu_physical_memory_write(addr + ohci->localmem_base + HCCA_WRITEBACK_OFFSET,
        !           602:                               (char *)hcca + HCCA_WRITEBACK_OFFSET,
        !           603:                               HCCA_WRITEBACK_SIZE);
        !           604:     return 1;
        !           605: }
        !           606: 
        !           607: /* Read/Write the contents of a TD from/to main memory.  */
        !           608: static void ohci_copy_td(OHCIState *ohci, struct ohci_td *td,
        !           609:                          uint8_t *buf, int len, int write)
        !           610: {
        !           611:     uint32_t ptr;
        !           612:     uint32_t n;
        !           613: 
        !           614:     ptr = td->cbp;
        !           615:     n = 0x1000 - (ptr & 0xfff);
        !           616:     if (n > len)
        !           617:         n = len;
        !           618:     cpu_physical_memory_rw(ptr + ohci->localmem_base, buf, n, write);
        !           619:     if (n == len)
        !           620:         return;
        !           621:     ptr = td->be & ~0xfffu;
        !           622:     buf += n;
        !           623:     cpu_physical_memory_rw(ptr + ohci->localmem_base, buf, len - n, write);
        !           624: }
        !           625: 
        !           626: /* Read/Write the contents of an ISO TD from/to main memory.  */
        !           627: static void ohci_copy_iso_td(OHCIState *ohci,
        !           628:                              uint32_t start_addr, uint32_t end_addr,
        !           629:                              uint8_t *buf, int len, int write)
        !           630: {
        !           631:     uint32_t ptr;
        !           632:     uint32_t n;
        !           633: 
        !           634:     ptr = start_addr;
        !           635:     n = 0x1000 - (ptr & 0xfff);
        !           636:     if (n > len)
        !           637:         n = len;
        !           638:     cpu_physical_memory_rw(ptr + ohci->localmem_base, buf, n, write);
        !           639:     if (n == len)
        !           640:         return;
        !           641:     ptr = end_addr & ~0xfffu;
        !           642:     buf += n;
        !           643:     cpu_physical_memory_rw(ptr + ohci->localmem_base, buf, len - n, write);
        !           644: }
        !           645: 
        !           646: static void ohci_process_lists(OHCIState *ohci, int completion);
        !           647: 
        !           648: static void ohci_async_complete_packet(USBPort *port, USBPacket *packet)
        !           649: {
        !           650:     OHCIState *ohci = container_of(packet, OHCIState, usb_packet);
        !           651: #ifdef DEBUG_PACKET
        !           652:     DPRINTF("Async packet complete\n");
        !           653: #endif
        !           654:     ohci->async_complete = 1;
        !           655:     ohci_process_lists(ohci, 1);
        !           656: }
        !           657: 
        !           658: #define USUB(a, b) ((int16_t)((uint16_t)(a) - (uint16_t)(b)))
        !           659: 
        !           660: static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed,
        !           661:                                int completion)
        !           662: {
        !           663:     int dir;
        !           664:     size_t len = 0;
        !           665: #ifdef DEBUG_ISOCH
        !           666:     const char *str = NULL;
        !           667: #endif
        !           668:     int pid;
        !           669:     int ret;
        !           670:     int i;
        !           671:     USBDevice *dev;
        !           672:     USBEndpoint *ep;
        !           673:     struct ohci_iso_td iso_td;
        !           674:     uint32_t addr;
        !           675:     uint16_t starting_frame;
        !           676:     int16_t relative_frame_number;
        !           677:     int frame_count;
        !           678:     uint32_t start_offset, next_offset, end_offset = 0;
        !           679:     uint32_t start_addr, end_addr;
        !           680: 
        !           681:     addr = ed->head & OHCI_DPTR_MASK;
        !           682: 
        !           683:     if (!ohci_read_iso_td(ohci, addr, &iso_td)) {
        !           684:         printf("usb-ohci: ISO_TD read error at %x\n", addr);
        !           685:         return 0;
        !           686:     }
        !           687: 
        !           688:     starting_frame = OHCI_BM(iso_td.flags, TD_SF);
        !           689:     frame_count = OHCI_BM(iso_td.flags, TD_FC);
        !           690:     relative_frame_number = USUB(ohci->frame_number, starting_frame); 
        !           691: 
        !           692: #ifdef DEBUG_ISOCH
        !           693:     printf("--- ISO_TD ED head 0x%.8x tailp 0x%.8x\n"
        !           694:            "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n"
        !           695:            "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n"
        !           696:            "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n"
        !           697:            "frame_number 0x%.8x starting_frame 0x%.8x\n"
        !           698:            "frame_count  0x%.8x relative %d\n"
        !           699:            "di 0x%.8x cc 0x%.8x\n",
        !           700:            ed->head & OHCI_DPTR_MASK, ed->tail & OHCI_DPTR_MASK,
        !           701:            iso_td.flags, iso_td.bp, iso_td.next, iso_td.be,
        !           702:            iso_td.offset[0], iso_td.offset[1], iso_td.offset[2], iso_td.offset[3],
        !           703:            iso_td.offset[4], iso_td.offset[5], iso_td.offset[6], iso_td.offset[7],
        !           704:            ohci->frame_number, starting_frame, 
        !           705:            frame_count, relative_frame_number,         
        !           706:            OHCI_BM(iso_td.flags, TD_DI), OHCI_BM(iso_td.flags, TD_CC));
        !           707: #endif
        !           708: 
        !           709:     if (relative_frame_number < 0) {
        !           710:         DPRINTF("usb-ohci: ISO_TD R=%d < 0\n", relative_frame_number);
        !           711:         return 1;
        !           712:     } else if (relative_frame_number > frame_count) {
        !           713:         /* ISO TD expired - retire the TD to the Done Queue and continue with
        !           714:            the next ISO TD of the same ED */
        !           715:         DPRINTF("usb-ohci: ISO_TD R=%d > FC=%d\n", relative_frame_number, 
        !           716:                frame_count);
        !           717:         OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_DATAOVERRUN);
        !           718:         ed->head &= ~OHCI_DPTR_MASK;
        !           719:         ed->head |= (iso_td.next & OHCI_DPTR_MASK);
        !           720:         iso_td.next = ohci->done;
        !           721:         ohci->done = addr;
        !           722:         i = OHCI_BM(iso_td.flags, TD_DI);
        !           723:         if (i < ohci->done_count)
        !           724:             ohci->done_count = i;
        !           725:         ohci_put_iso_td(ohci, addr, &iso_td);
        !           726:         return 0;
        !           727:     }
        !           728: 
        !           729:     dir = OHCI_BM(ed->flags, ED_D);
        !           730:     switch (dir) {
        !           731:     case OHCI_TD_DIR_IN:
        !           732: #ifdef DEBUG_ISOCH
        !           733:         str = "in";
        !           734: #endif
        !           735:         pid = USB_TOKEN_IN;
        !           736:         break;
        !           737:     case OHCI_TD_DIR_OUT:
        !           738: #ifdef DEBUG_ISOCH
        !           739:         str = "out";
        !           740: #endif
        !           741:         pid = USB_TOKEN_OUT;
        !           742:         break;
        !           743:     case OHCI_TD_DIR_SETUP:
        !           744: #ifdef DEBUG_ISOCH
        !           745:         str = "setup";
        !           746: #endif
        !           747:         pid = USB_TOKEN_SETUP;
        !           748:         break;
        !           749:     default:
        !           750:         printf("usb-ohci: Bad direction %d\n", dir);
        !           751:         return 1;
        !           752:     }
        !           753: 
        !           754:     if (!iso_td.bp || !iso_td.be) {
        !           755:         printf("usb-ohci: ISO_TD bp 0x%.8x be 0x%.8x\n", iso_td.bp, iso_td.be);
        !           756:         return 1;
        !           757:     }
        !           758: 
        !           759:     start_offset = iso_td.offset[relative_frame_number];
        !           760:     next_offset = iso_td.offset[relative_frame_number + 1];
        !           761: 
        !           762:     if (!(OHCI_BM(start_offset, TD_PSW_CC) & 0xe) || 
        !           763:         ((relative_frame_number < frame_count) && 
        !           764:          !(OHCI_BM(next_offset, TD_PSW_CC) & 0xe))) {
        !           765:         printf("usb-ohci: ISO_TD cc != not accessed 0x%.8x 0x%.8x\n",
        !           766:                start_offset, next_offset);
        !           767:         return 1;
        !           768:     }
        !           769: 
        !           770:     if ((relative_frame_number < frame_count) && (start_offset > next_offset)) {
        !           771:         printf("usb-ohci: ISO_TD start_offset=0x%.8x > next_offset=0x%.8x\n",
        !           772:                 start_offset, next_offset);
        !           773:         return 1;
        !           774:     }
        !           775: 
        !           776:     if ((start_offset & 0x1000) == 0) {
        !           777:         start_addr = (iso_td.bp & OHCI_PAGE_MASK) |
        !           778:             (start_offset & OHCI_OFFSET_MASK);
        !           779:     } else {
        !           780:         start_addr = (iso_td.be & OHCI_PAGE_MASK) |
        !           781:             (start_offset & OHCI_OFFSET_MASK);
        !           782:     }
        !           783: 
        !           784:     if (relative_frame_number < frame_count) {
        !           785:         end_offset = next_offset - 1;
        !           786:         if ((end_offset & 0x1000) == 0) {
        !           787:             end_addr = (iso_td.bp & OHCI_PAGE_MASK) |
        !           788:                 (end_offset & OHCI_OFFSET_MASK);
        !           789:         } else {
        !           790:             end_addr = (iso_td.be & OHCI_PAGE_MASK) |
        !           791:                 (end_offset & OHCI_OFFSET_MASK);
        !           792:         }
        !           793:     } else {
        !           794:         /* Last packet in the ISO TD */
        !           795:         end_addr = iso_td.be;
        !           796:     }
        !           797: 
        !           798:     if ((start_addr & OHCI_PAGE_MASK) != (end_addr & OHCI_PAGE_MASK)) {
        !           799:         len = (end_addr & OHCI_OFFSET_MASK) + 0x1001
        !           800:             - (start_addr & OHCI_OFFSET_MASK);
        !           801:     } else {
        !           802:         len = end_addr - start_addr + 1;
        !           803:     }
        !           804: 
        !           805:     if (len && dir != OHCI_TD_DIR_IN) {
        !           806:         ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, len, 0);
        !           807:     }
        !           808: 
        !           809:     if (completion) {
        !           810:         ret = ohci->usb_packet.result;
        !           811:     } else {
        !           812:         dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
        !           813:         ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
        !           814:         usb_packet_setup(&ohci->usb_packet, pid, ep);
        !           815:         usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len);
        !           816:         ret = usb_handle_packet(dev, &ohci->usb_packet);
        !           817:         if (ret == USB_RET_ASYNC) {
        !           818:             return 1;
        !           819:         }
        !           820:     }
        !           821: 
        !           822: #ifdef DEBUG_ISOCH
        !           823:     printf("so 0x%.8x eo 0x%.8x\nsa 0x%.8x ea 0x%.8x\ndir %s len %zu ret %d\n",
        !           824:            start_offset, end_offset, start_addr, end_addr, str, len, ret);
        !           825: #endif
        !           826: 
        !           827:     /* Writeback */
        !           828:     if (dir == OHCI_TD_DIR_IN && ret >= 0 && ret <= len) {
        !           829:         /* IN transfer succeeded */
        !           830:         ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, ret, 1);
        !           831:         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
        !           832:                     OHCI_CC_NOERROR);
        !           833:         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, ret);
        !           834:     } else if (dir == OHCI_TD_DIR_OUT && ret == len) {
        !           835:         /* OUT transfer succeeded */
        !           836:         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
        !           837:                     OHCI_CC_NOERROR);
        !           838:         OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, 0);
        !           839:     } else {
        !           840:         if (ret > (ssize_t) len) {
        !           841:             printf("usb-ohci: DataOverrun %d > %zu\n", ret, len);
        !           842:             OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
        !           843:                         OHCI_CC_DATAOVERRUN);
        !           844:             OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE,
        !           845:                         len);
        !           846:         } else if (ret >= 0) {
        !           847:             printf("usb-ohci: DataUnderrun %d\n", ret);
        !           848:             OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
        !           849:                         OHCI_CC_DATAUNDERRUN);
        !           850:         } else {
        !           851:             switch (ret) {
        !           852:             case USB_RET_IOERROR:
        !           853:             case USB_RET_NODEV:
        !           854:                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
        !           855:                             OHCI_CC_DEVICENOTRESPONDING);
        !           856:                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE,
        !           857:                             0);
        !           858:                 break;
        !           859:             case USB_RET_NAK:
        !           860:             case USB_RET_STALL:
        !           861:                 printf("usb-ohci: got NAK/STALL %d\n", ret);
        !           862:                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
        !           863:                             OHCI_CC_STALL);
        !           864:                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE,
        !           865:                             0);
        !           866:                 break;
        !           867:             default:
        !           868:                 printf("usb-ohci: Bad device response %d\n", ret);
        !           869:                 OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
        !           870:                             OHCI_CC_UNDEXPETEDPID);
        !           871:                 break;
        !           872:             }
        !           873:         }
        !           874:     }
        !           875: 
        !           876:     if (relative_frame_number == frame_count) {
        !           877:         /* Last data packet of ISO TD - retire the TD to the Done Queue */
        !           878:         OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_NOERROR);
        !           879:         ed->head &= ~OHCI_DPTR_MASK;
        !           880:         ed->head |= (iso_td.next & OHCI_DPTR_MASK);
        !           881:         iso_td.next = ohci->done;
        !           882:         ohci->done = addr;
        !           883:         i = OHCI_BM(iso_td.flags, TD_DI);
        !           884:         if (i < ohci->done_count)
        !           885:             ohci->done_count = i;
        !           886:     }
        !           887:     ohci_put_iso_td(ohci, addr, &iso_td);
        !           888:     return 1;
        !           889: }
        !           890: 
        !           891: /* Service a transport descriptor.
        !           892:    Returns nonzero to terminate processing of this endpoint.  */
        !           893: 
        !           894: static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed)
        !           895: {
        !           896:     int dir;
        !           897:     size_t len = 0, pktlen = 0;
        !           898: #ifdef DEBUG_PACKET
        !           899:     const char *str = NULL;
        !           900: #endif
        !           901:     int pid;
        !           902:     int ret;
        !           903:     int i;
        !           904:     USBDevice *dev;
        !           905:     USBEndpoint *ep;
        !           906:     struct ohci_td td;
        !           907:     uint32_t addr;
        !           908:     int flag_r;
        !           909:     int completion;
        !           910: 
        !           911:     addr = ed->head & OHCI_DPTR_MASK;
        !           912:     /* See if this TD has already been submitted to the device.  */
        !           913:     completion = (addr == ohci->async_td);
        !           914:     if (completion && !ohci->async_complete) {
        !           915: #ifdef DEBUG_PACKET
        !           916:         DPRINTF("Skipping async TD\n");
        !           917: #endif
        !           918:         return 1;
        !           919:     }
        !           920:     if (!ohci_read_td(ohci, addr, &td)) {
        !           921:         fprintf(stderr, "usb-ohci: TD read error at %x\n", addr);
        !           922:         return 0;
        !           923:     }
        !           924: 
        !           925:     dir = OHCI_BM(ed->flags, ED_D);
        !           926:     switch (dir) {
        !           927:     case OHCI_TD_DIR_OUT:
        !           928:     case OHCI_TD_DIR_IN:
        !           929:         /* Same value.  */
        !           930:         break;
        !           931:     default:
        !           932:         dir = OHCI_BM(td.flags, TD_DP);
        !           933:         break;
        !           934:     }
        !           935: 
        !           936:     switch (dir) {
        !           937:     case OHCI_TD_DIR_IN:
        !           938: #ifdef DEBUG_PACKET
        !           939:         str = "in";
        !           940: #endif
        !           941:         pid = USB_TOKEN_IN;
        !           942:         break;
        !           943:     case OHCI_TD_DIR_OUT:
        !           944: #ifdef DEBUG_PACKET
        !           945:         str = "out";
        !           946: #endif
        !           947:         pid = USB_TOKEN_OUT;
        !           948:         break;
        !           949:     case OHCI_TD_DIR_SETUP:
        !           950: #ifdef DEBUG_PACKET
        !           951:         str = "setup";
        !           952: #endif
        !           953:         pid = USB_TOKEN_SETUP;
        !           954:         break;
        !           955:     default:
        !           956:         fprintf(stderr, "usb-ohci: Bad direction\n");
        !           957:         return 1;
        !           958:     }
        !           959:     if (td.cbp && td.be) {
        !           960:         if ((td.cbp & 0xfffff000) != (td.be & 0xfffff000)) {
        !           961:             len = (td.be & 0xfff) + 0x1001 - (td.cbp & 0xfff);
        !           962:         } else {
        !           963:             len = (td.be - td.cbp) + 1;
        !           964:         }
        !           965: 
        !           966:         pktlen = len;
        !           967:         if (len && dir != OHCI_TD_DIR_IN) {
        !           968:             /* The endpoint may not allow us to transfer it all now */
        !           969:             pktlen = (ed->flags & OHCI_ED_MPS_MASK) >> OHCI_ED_MPS_SHIFT;
        !           970:             if (pktlen > len) {
        !           971:                 pktlen = len;
        !           972:             }
        !           973:             if (!completion) {
        !           974:                 ohci_copy_td(ohci, &td, ohci->usb_buf, pktlen, 0);
        !           975:             }
        !           976:         }
        !           977:     }
        !           978: 
        !           979:     flag_r = (td.flags & OHCI_TD_R) != 0;
        !           980: #ifdef DEBUG_PACKET
        !           981:     DPRINTF(" TD @ 0x%.8x %" PRId64 " of %" PRId64
        !           982:             " bytes %s r=%d cbp=0x%.8x be=0x%.8x\n",
        !           983:             addr, (int64_t)pktlen, (int64_t)len, str, flag_r, td.cbp, td.be);
        !           984: 
        !           985:     if (pktlen > 0 && dir != OHCI_TD_DIR_IN) {
        !           986:         DPRINTF("  data:");
        !           987:         for (i = 0; i < pktlen; i++) {
        !           988:             printf(" %.2x", ohci->usb_buf[i]);
        !           989:         }
        !           990:         DPRINTF("\n");
        !           991:     }
        !           992: #endif
        !           993:     if (completion) {
        !           994:         ret = ohci->usb_packet.result;
        !           995:         ohci->async_td = 0;
        !           996:         ohci->async_complete = 0;
        !           997:     } else {
        !           998:         if (ohci->async_td) {
        !           999:             /* ??? The hardware should allow one active packet per
        !          1000:                endpoint.  We only allow one active packet per controller.
        !          1001:                This should be sufficient as long as devices respond in a
        !          1002:                timely manner.
        !          1003:             */
        !          1004: #ifdef DEBUG_PACKET
        !          1005:             DPRINTF("Too many pending packets\n");
        !          1006: #endif
        !          1007:             return 1;
        !          1008:         }
        !          1009:         dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
        !          1010:         ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
        !          1011:         usb_packet_setup(&ohci->usb_packet, pid, ep);
        !          1012:         usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, pktlen);
        !          1013:         ret = usb_handle_packet(dev, &ohci->usb_packet);
        !          1014: #ifdef DEBUG_PACKET
        !          1015:         DPRINTF("ret=%d\n", ret);
        !          1016: #endif
        !          1017:         if (ret == USB_RET_ASYNC) {
        !          1018:             ohci->async_td = addr;
        !          1019:             return 1;
        !          1020:         }
        !          1021:     }
        !          1022:     if (ret >= 0) {
        !          1023:         if (dir == OHCI_TD_DIR_IN) {
        !          1024:             ohci_copy_td(ohci, &td, ohci->usb_buf, ret, 1);
        !          1025: #ifdef DEBUG_PACKET
        !          1026:             DPRINTF("  data:");
        !          1027:             for (i = 0; i < ret; i++)
        !          1028:                 printf(" %.2x", ohci->usb_buf[i]);
        !          1029:             DPRINTF("\n");
        !          1030: #endif
        !          1031:         } else {
        !          1032:             ret = pktlen;
        !          1033:         }
        !          1034:     }
        !          1035: 
        !          1036:     /* Writeback */
        !          1037:     if (ret == pktlen || (dir == OHCI_TD_DIR_IN && ret >= 0 && flag_r)) {
        !          1038:         /* Transmission succeeded.  */
        !          1039:         if (ret == len) {
        !          1040:             td.cbp = 0;
        !          1041:         } else {
        !          1042:             if ((td.cbp & 0xfff) + ret > 0xfff) {
        !          1043:                 td.cbp = (td.be & ~0xfff) + ((td.cbp + ret) & 0xfff);
        !          1044:             } else {
        !          1045:                 td.cbp += ret;
        !          1046:             }
        !          1047:         }
        !          1048:         td.flags |= OHCI_TD_T1;
        !          1049:         td.flags ^= OHCI_TD_T0;
        !          1050:         OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_NOERROR);
        !          1051:         OHCI_SET_BM(td.flags, TD_EC, 0);
        !          1052: 
        !          1053:         if ((dir != OHCI_TD_DIR_IN) && (ret != len)) {
        !          1054:             /* Partial packet transfer: TD not ready to retire yet */
        !          1055:             goto exit_no_retire;
        !          1056:         }
        !          1057: 
        !          1058:         /* Setting ED_C is part of the TD retirement process */
        !          1059:         ed->head &= ~OHCI_ED_C;
        !          1060:         if (td.flags & OHCI_TD_T0)
        !          1061:             ed->head |= OHCI_ED_C;
        !          1062:     } else {
        !          1063:         if (ret >= 0) {
        !          1064:             DPRINTF("usb-ohci: Underrun\n");
        !          1065:             OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAUNDERRUN);
        !          1066:         } else {
        !          1067:             switch (ret) {
        !          1068:             case USB_RET_IOERROR:
        !          1069:             case USB_RET_NODEV:
        !          1070:                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DEVICENOTRESPONDING);
        !          1071:             case USB_RET_NAK:
        !          1072:                 DPRINTF("usb-ohci: got NAK\n");
        !          1073:                 return 1;
        !          1074:             case USB_RET_STALL:
        !          1075:                 DPRINTF("usb-ohci: got STALL\n");
        !          1076:                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_STALL);
        !          1077:                 break;
        !          1078:             case USB_RET_BABBLE:
        !          1079:                 DPRINTF("usb-ohci: got BABBLE\n");
        !          1080:                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAOVERRUN);
        !          1081:                 break;
        !          1082:             default:
        !          1083:                 fprintf(stderr, "usb-ohci: Bad device response %d\n", ret);
        !          1084:                 OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_UNDEXPETEDPID);
        !          1085:                 OHCI_SET_BM(td.flags, TD_EC, 3);
        !          1086:                 break;
        !          1087:             }
        !          1088:         }
        !          1089:         ed->head |= OHCI_ED_H;
        !          1090:     }
        !          1091: 
        !          1092:     /* Retire this TD */
        !          1093:     ed->head &= ~OHCI_DPTR_MASK;
        !          1094:     ed->head |= td.next & OHCI_DPTR_MASK;
        !          1095:     td.next = ohci->done;
        !          1096:     ohci->done = addr;
        !          1097:     i = OHCI_BM(td.flags, TD_DI);
        !          1098:     if (i < ohci->done_count)
        !          1099:         ohci->done_count = i;
        !          1100: exit_no_retire:
        !          1101:     ohci_put_td(ohci, addr, &td);
        !          1102:     return OHCI_BM(td.flags, TD_CC) != OHCI_CC_NOERROR;
        !          1103: }
        !          1104: 
        !          1105: /* Service an endpoint list.  Returns nonzero if active TD were found.  */
        !          1106: static int ohci_service_ed_list(OHCIState *ohci, uint32_t head, int completion)
        !          1107: {
        !          1108:     struct ohci_ed ed;
        !          1109:     uint32_t next_ed;
        !          1110:     uint32_t cur;
        !          1111:     int active;
        !          1112: 
        !          1113:     active = 0;
        !          1114: 
        !          1115:     if (head == 0)
        !          1116:         return 0;
        !          1117: 
        !          1118:     for (cur = head; cur; cur = next_ed) {
        !          1119:         if (!ohci_read_ed(ohci, cur, &ed)) {
        !          1120:             fprintf(stderr, "usb-ohci: ED read error at %x\n", cur);
        !          1121:             return 0;
        !          1122:         }
        !          1123: 
        !          1124:         next_ed = ed.next & OHCI_DPTR_MASK;
        !          1125: 
        !          1126:         if ((ed.head & OHCI_ED_H) || (ed.flags & OHCI_ED_K)) {
        !          1127:             uint32_t addr;
        !          1128:             /* Cancel pending packets for ED that have been paused.  */
        !          1129:             addr = ed.head & OHCI_DPTR_MASK;
        !          1130:             if (ohci->async_td && addr == ohci->async_td) {
        !          1131:                 usb_cancel_packet(&ohci->usb_packet);
        !          1132:                 ohci->async_td = 0;
        !          1133:             }
        !          1134:             continue;
        !          1135:         }
        !          1136: 
        !          1137:         while ((ed.head & OHCI_DPTR_MASK) != ed.tail) {
        !          1138: #ifdef DEBUG_PACKET
        !          1139:             DPRINTF("ED @ 0x%.8x fa=%u en=%u d=%u s=%u k=%u f=%u mps=%u "
        !          1140:                     "h=%u c=%u\n  head=0x%.8x tailp=0x%.8x next=0x%.8x\n", cur,
        !          1141:                     OHCI_BM(ed.flags, ED_FA), OHCI_BM(ed.flags, ED_EN),
        !          1142:                     OHCI_BM(ed.flags, ED_D), (ed.flags & OHCI_ED_S)!= 0,
        !          1143:                     (ed.flags & OHCI_ED_K) != 0, (ed.flags & OHCI_ED_F) != 0,
        !          1144:                     OHCI_BM(ed.flags, ED_MPS), (ed.head & OHCI_ED_H) != 0,
        !          1145:                     (ed.head & OHCI_ED_C) != 0, ed.head & OHCI_DPTR_MASK,
        !          1146:                     ed.tail & OHCI_DPTR_MASK, ed.next & OHCI_DPTR_MASK);
        !          1147: #endif
        !          1148:             active = 1;
        !          1149: 
        !          1150:             if ((ed.flags & OHCI_ED_F) == 0) {
        !          1151:                 if (ohci_service_td(ohci, &ed))
        !          1152:                     break;
        !          1153:             } else {
        !          1154:                 /* Handle isochronous endpoints */
        !          1155:                 if (ohci_service_iso_td(ohci, &ed, completion))
        !          1156:                     break;
        !          1157:             }
        !          1158:         }
        !          1159: 
        !          1160:         ohci_put_ed(ohci, cur, &ed);
        !          1161:     }
        !          1162: 
        !          1163:     return active;
        !          1164: }
        !          1165: 
        !          1166: /* Generate a SOF event, and set a timer for EOF */
        !          1167: static void ohci_sof(OHCIState *ohci)
        !          1168: {
        !          1169:     ohci->sof_time = qemu_get_clock_ns(vm_clock);
        !          1170:     qemu_mod_timer(ohci->eof_timer, ohci->sof_time + usb_frame_time);
        !          1171:     ohci_set_interrupt(ohci, OHCI_INTR_SF);
        !          1172: }
        !          1173: 
        !          1174: /* Process Control and Bulk lists.  */
        !          1175: static void ohci_process_lists(OHCIState *ohci, int completion)
        !          1176: {
        !          1177:     if ((ohci->ctl & OHCI_CTL_CLE) && (ohci->status & OHCI_STATUS_CLF)) {
        !          1178:         if (ohci->ctrl_cur && ohci->ctrl_cur != ohci->ctrl_head) {
        !          1179:             DPRINTF("usb-ohci: head %x, cur %x\n",
        !          1180:                     ohci->ctrl_head, ohci->ctrl_cur);
        !          1181:         }
        !          1182:         if (!ohci_service_ed_list(ohci, ohci->ctrl_head, completion)) {
        !          1183:             ohci->ctrl_cur = 0;
        !          1184:             ohci->status &= ~OHCI_STATUS_CLF;
        !          1185:         }
        !          1186:     }
        !          1187: 
        !          1188:     if ((ohci->ctl & OHCI_CTL_BLE) && (ohci->status & OHCI_STATUS_BLF)) {
        !          1189:         if (!ohci_service_ed_list(ohci, ohci->bulk_head, completion)) {
        !          1190:             ohci->bulk_cur = 0;
        !          1191:             ohci->status &= ~OHCI_STATUS_BLF;
        !          1192:         }
        !          1193:     }
        !          1194: }
        !          1195: 
        !          1196: /* Do frame processing on frame boundary */
        !          1197: static void ohci_frame_boundary(void *opaque)
        !          1198: {
        !          1199:     OHCIState *ohci = opaque;
        !          1200:     struct ohci_hcca hcca;
        !          1201: 
        !          1202:     ohci_read_hcca(ohci, ohci->hcca, &hcca);
        !          1203: 
        !          1204:     /* Process all the lists at the end of the frame */
        !          1205:     if (ohci->ctl & OHCI_CTL_PLE) {
        !          1206:         int n;
        !          1207: 
        !          1208:         n = ohci->frame_number & 0x1f;
        !          1209:         ohci_service_ed_list(ohci, le32_to_cpu(hcca.intr[n]), 0);
        !          1210:     }
        !          1211: 
        !          1212:     /* Cancel all pending packets if either of the lists has been disabled.  */
        !          1213:     if (ohci->async_td &&
        !          1214:         ohci->old_ctl & (~ohci->ctl) & (OHCI_CTL_BLE | OHCI_CTL_CLE)) {
        !          1215:         usb_cancel_packet(&ohci->usb_packet);
        !          1216:         ohci->async_td = 0;
        !          1217:     }
        !          1218:     ohci->old_ctl = ohci->ctl;
        !          1219:     ohci_process_lists(ohci, 0);
        !          1220: 
        !          1221:     /* Frame boundary, so do EOF stuf here */
        !          1222:     ohci->frt = ohci->fit;
        !          1223: 
        !          1224:     /* Increment frame number and take care of endianness. */
        !          1225:     ohci->frame_number = (ohci->frame_number + 1) & 0xffff;
        !          1226:     hcca.frame = cpu_to_le16(ohci->frame_number);
        !          1227: 
        !          1228:     if (ohci->done_count == 0 && !(ohci->intr_status & OHCI_INTR_WD)) {
        !          1229:         if (!ohci->done)
        !          1230:             abort();
        !          1231:         if (ohci->intr & ohci->intr_status)
        !          1232:             ohci->done |= 1;
        !          1233:         hcca.done = cpu_to_le32(ohci->done);
        !          1234:         ohci->done = 0;
        !          1235:         ohci->done_count = 7;
        !          1236:         ohci_set_interrupt(ohci, OHCI_INTR_WD);
        !          1237:     }
        !          1238: 
        !          1239:     if (ohci->done_count != 7 && ohci->done_count != 0)
        !          1240:         ohci->done_count--;
        !          1241: 
        !          1242:     /* Do SOF stuff here */
        !          1243:     ohci_sof(ohci);
        !          1244: 
        !          1245:     /* Writeback HCCA */
        !          1246:     ohci_put_hcca(ohci, ohci->hcca, &hcca);
        !          1247: }
        !          1248: 
        !          1249: /* Start sending SOF tokens across the USB bus, lists are processed in
        !          1250:  * next frame
        !          1251:  */
        !          1252: static int ohci_bus_start(OHCIState *ohci)
        !          1253: {
        !          1254:     ohci->eof_timer = qemu_new_timer_ns(vm_clock,
        !          1255:                     ohci_frame_boundary,
        !          1256:                     ohci);
        !          1257: 
        !          1258:     if (ohci->eof_timer == NULL) {
        !          1259:         fprintf(stderr, "usb-ohci: %s: qemu_new_timer_ns failed\n", ohci->name);
        !          1260:         /* TODO: Signal unrecoverable error */
        !          1261:         return 0;
        !          1262:     }
        !          1263: 
        !          1264:     DPRINTF("usb-ohci: %s: USB Operational\n", ohci->name);
        !          1265: 
        !          1266:     ohci_sof(ohci);
        !          1267: 
        !          1268:     return 1;
        !          1269: }
        !          1270: 
        !          1271: /* Stop sending SOF tokens on the bus */
        !          1272: static void ohci_bus_stop(OHCIState *ohci)
        !          1273: {
        !          1274:     if (ohci->eof_timer)
        !          1275:         qemu_del_timer(ohci->eof_timer);
        !          1276:     ohci->eof_timer = NULL;
        !          1277: }
        !          1278: 
        !          1279: /* Sets a flag in a port status register but only set it if the port is
        !          1280:  * connected, if not set ConnectStatusChange flag. If flag is enabled
        !          1281:  * return 1.
        !          1282:  */
        !          1283: static int ohci_port_set_if_connected(OHCIState *ohci, int i, uint32_t val)
        !          1284: {
        !          1285:     int ret = 1;
        !          1286: 
        !          1287:     /* writing a 0 has no effect */
        !          1288:     if (val == 0)
        !          1289:         return 0;
        !          1290: 
        !          1291:     /* If CurrentConnectStatus is cleared we set
        !          1292:      * ConnectStatusChange
        !          1293:      */
        !          1294:     if (!(ohci->rhport[i].ctrl & OHCI_PORT_CCS)) {
        !          1295:         ohci->rhport[i].ctrl |= OHCI_PORT_CSC;
        !          1296:         if (ohci->rhstatus & OHCI_RHS_DRWE) {
        !          1297:             /* TODO: CSC is a wakeup event */
        !          1298:         }
        !          1299:         return 0;
        !          1300:     }
        !          1301: 
        !          1302:     if (ohci->rhport[i].ctrl & val)
        !          1303:         ret = 0;
        !          1304: 
        !          1305:     /* set the bit */
        !          1306:     ohci->rhport[i].ctrl |= val;
        !          1307: 
        !          1308:     return ret;
        !          1309: }
        !          1310: 
        !          1311: /* Set the frame interval - frame interval toggle is manipulated by the hcd only */
        !          1312: static void ohci_set_frame_interval(OHCIState *ohci, uint16_t val)
        !          1313: {
        !          1314:     val &= OHCI_FMI_FI;
        !          1315: 
        !          1316:     if (val != ohci->fi) {
        !          1317:         DPRINTF("usb-ohci: %s: FrameInterval = 0x%x (%u)\n",
        !          1318:             ohci->name, ohci->fi, ohci->fi);
        !          1319:     }
        !          1320: 
        !          1321:     ohci->fi = val;
        !          1322: }
        !          1323: 
        !          1324: static void ohci_port_power(OHCIState *ohci, int i, int p)
        !          1325: {
        !          1326:     if (p) {
        !          1327:         ohci->rhport[i].ctrl |= OHCI_PORT_PPS;
        !          1328:     } else {
        !          1329:         ohci->rhport[i].ctrl &= ~(OHCI_PORT_PPS|
        !          1330:                     OHCI_PORT_CCS|
        !          1331:                     OHCI_PORT_PSS|
        !          1332:                     OHCI_PORT_PRS);
        !          1333:     }
        !          1334: }
        !          1335: 
        !          1336: /* Set HcControlRegister */
        !          1337: static void ohci_set_ctl(OHCIState *ohci, uint32_t val)
        !          1338: {
        !          1339:     uint32_t old_state;
        !          1340:     uint32_t new_state;
        !          1341: 
        !          1342:     old_state = ohci->ctl & OHCI_CTL_HCFS;
        !          1343:     ohci->ctl = val;
        !          1344:     new_state = ohci->ctl & OHCI_CTL_HCFS;
        !          1345: 
        !          1346:     /* no state change */
        !          1347:     if (old_state == new_state)
        !          1348:         return;
        !          1349: 
        !          1350:     switch (new_state) {
        !          1351:     case OHCI_USB_OPERATIONAL:
        !          1352:         ohci_bus_start(ohci);
        !          1353:         break;
        !          1354:     case OHCI_USB_SUSPEND:
        !          1355:         ohci_bus_stop(ohci);
        !          1356:         DPRINTF("usb-ohci: %s: USB Suspended\n", ohci->name);
        !          1357:         break;
        !          1358:     case OHCI_USB_RESUME:
        !          1359:         DPRINTF("usb-ohci: %s: USB Resume\n", ohci->name);
        !          1360:         break;
        !          1361:     case OHCI_USB_RESET:
        !          1362:         ohci_reset(ohci);
        !          1363:         DPRINTF("usb-ohci: %s: USB Reset\n", ohci->name);
        !          1364:         break;
        !          1365:     }
        !          1366: }
        !          1367: 
        !          1368: static uint32_t ohci_get_frame_remaining(OHCIState *ohci)
        !          1369: {
        !          1370:     uint16_t fr;
        !          1371:     int64_t tks;
        !          1372: 
        !          1373:     if ((ohci->ctl & OHCI_CTL_HCFS) != OHCI_USB_OPERATIONAL)
        !          1374:         return (ohci->frt << 31);
        !          1375: 
        !          1376:     /* Being in USB operational state guarnatees sof_time was
        !          1377:      * set already.
        !          1378:      */
        !          1379:     tks = qemu_get_clock_ns(vm_clock) - ohci->sof_time;
        !          1380: 
        !          1381:     /* avoid muldiv if possible */
        !          1382:     if (tks >= usb_frame_time)
        !          1383:         return (ohci->frt << 31);
        !          1384: 
        !          1385:     tks = muldiv64(1, tks, usb_bit_time);
        !          1386:     fr = (uint16_t)(ohci->fi - tks);
        !          1387: 
        !          1388:     return (ohci->frt << 31) | fr;
        !          1389: }
        !          1390: 
        !          1391: 
        !          1392: /* Set root hub status */
        !          1393: static void ohci_set_hub_status(OHCIState *ohci, uint32_t val)
        !          1394: {
        !          1395:     uint32_t old_state;
        !          1396: 
        !          1397:     old_state = ohci->rhstatus;
        !          1398: 
        !          1399:     /* write 1 to clear OCIC */
        !          1400:     if (val & OHCI_RHS_OCIC)
        !          1401:         ohci->rhstatus &= ~OHCI_RHS_OCIC;
        !          1402: 
        !          1403:     if (val & OHCI_RHS_LPS) {
        !          1404:         int i;
        !          1405: 
        !          1406:         for (i = 0; i < ohci->num_ports; i++)
        !          1407:             ohci_port_power(ohci, i, 0);
        !          1408:         DPRINTF("usb-ohci: powered down all ports\n");
        !          1409:     }
        !          1410: 
        !          1411:     if (val & OHCI_RHS_LPSC) {
        !          1412:         int i;
        !          1413: 
        !          1414:         for (i = 0; i < ohci->num_ports; i++)
        !          1415:             ohci_port_power(ohci, i, 1);
        !          1416:         DPRINTF("usb-ohci: powered up all ports\n");
        !          1417:     }
        !          1418: 
        !          1419:     if (val & OHCI_RHS_DRWE)
        !          1420:         ohci->rhstatus |= OHCI_RHS_DRWE;
        !          1421: 
        !          1422:     if (val & OHCI_RHS_CRWE)
        !          1423:         ohci->rhstatus &= ~OHCI_RHS_DRWE;
        !          1424: 
        !          1425:     if (old_state != ohci->rhstatus)
        !          1426:         ohci_set_interrupt(ohci, OHCI_INTR_RHSC);
        !          1427: }
        !          1428: 
        !          1429: /* Set root hub port status */
        !          1430: static void ohci_port_set_status(OHCIState *ohci, int portnum, uint32_t val)
        !          1431: {
        !          1432:     uint32_t old_state;
        !          1433:     OHCIPort *port;
        !          1434: 
        !          1435:     port = &ohci->rhport[portnum];
        !          1436:     old_state = port->ctrl;
        !          1437: 
        !          1438:     /* Write to clear CSC, PESC, PSSC, OCIC, PRSC */
        !          1439:     if (val & OHCI_PORT_WTC)
        !          1440:         port->ctrl &= ~(val & OHCI_PORT_WTC);
        !          1441: 
        !          1442:     if (val & OHCI_PORT_CCS)
        !          1443:         port->ctrl &= ~OHCI_PORT_PES;
        !          1444: 
        !          1445:     ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PES);
        !          1446: 
        !          1447:     if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PSS)) {
        !          1448:         DPRINTF("usb-ohci: port %d: SUSPEND\n", portnum);
        !          1449:     }
        !          1450: 
        !          1451:     if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PRS)) {
        !          1452:         DPRINTF("usb-ohci: port %d: RESET\n", portnum);
        !          1453:         usb_device_reset(port->port.dev);
        !          1454:         port->ctrl &= ~OHCI_PORT_PRS;
        !          1455:         /* ??? Should this also set OHCI_PORT_PESC.  */
        !          1456:         port->ctrl |= OHCI_PORT_PES | OHCI_PORT_PRSC;
        !          1457:     }
        !          1458: 
        !          1459:     /* Invert order here to ensure in ambiguous case, device is
        !          1460:      * powered up...
        !          1461:      */
        !          1462:     if (val & OHCI_PORT_LSDA)
        !          1463:         ohci_port_power(ohci, portnum, 0);
        !          1464:     if (val & OHCI_PORT_PPS)
        !          1465:         ohci_port_power(ohci, portnum, 1);
        !          1466: 
        !          1467:     if (old_state != port->ctrl)
        !          1468:         ohci_set_interrupt(ohci, OHCI_INTR_RHSC);
        !          1469: 
        !          1470:     return;
        !          1471: }
        !          1472: 
        !          1473: static uint64_t ohci_mem_read(void *opaque,
        !          1474:                               target_phys_addr_t addr,
        !          1475:                               unsigned size)
        !          1476: {
        !          1477:     OHCIState *ohci = opaque;
        !          1478:     uint32_t retval;
        !          1479: 
        !          1480:     /* Only aligned reads are allowed on OHCI */
        !          1481:     if (addr & 3) {
        !          1482:         fprintf(stderr, "usb-ohci: Mis-aligned read\n");
        !          1483:         return 0xffffffff;
        !          1484:     } else if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) {
        !          1485:         /* HcRhPortStatus */
        !          1486:         retval = ohci->rhport[(addr - 0x54) >> 2].ctrl | OHCI_PORT_PPS;
        !          1487:     } else {
        !          1488:         switch (addr >> 2) {
        !          1489:         case 0: /* HcRevision */
        !          1490:             retval = 0x10;
        !          1491:             break;
        !          1492: 
        !          1493:         case 1: /* HcControl */
        !          1494:             retval = ohci->ctl;
        !          1495:             break;
        !          1496: 
        !          1497:         case 2: /* HcCommandStatus */
        !          1498:             retval = ohci->status;
        !          1499:             break;
        !          1500: 
        !          1501:         case 3: /* HcInterruptStatus */
        !          1502:             retval = ohci->intr_status;
        !          1503:             break;
        !          1504: 
        !          1505:         case 4: /* HcInterruptEnable */
        !          1506:         case 5: /* HcInterruptDisable */
        !          1507:             retval = ohci->intr;
        !          1508:             break;
        !          1509: 
        !          1510:         case 6: /* HcHCCA */
        !          1511:             retval = ohci->hcca;
        !          1512:             break;
        !          1513: 
        !          1514:         case 7: /* HcPeriodCurrentED */
        !          1515:             retval = ohci->per_cur;
        !          1516:             break;
        !          1517: 
        !          1518:         case 8: /* HcControlHeadED */
        !          1519:             retval = ohci->ctrl_head;
        !          1520:             break;
        !          1521: 
        !          1522:         case 9: /* HcControlCurrentED */
        !          1523:             retval = ohci->ctrl_cur;
        !          1524:             break;
        !          1525: 
        !          1526:         case 10: /* HcBulkHeadED */
        !          1527:             retval = ohci->bulk_head;
        !          1528:             break;
        !          1529: 
        !          1530:         case 11: /* HcBulkCurrentED */
        !          1531:             retval = ohci->bulk_cur;
        !          1532:             break;
        !          1533: 
        !          1534:         case 12: /* HcDoneHead */
        !          1535:             retval = ohci->done;
        !          1536:             break;
        !          1537: 
        !          1538:         case 13: /* HcFmInterretval */
        !          1539:             retval = (ohci->fit << 31) | (ohci->fsmps << 16) | (ohci->fi);
        !          1540:             break;
        !          1541: 
        !          1542:         case 14: /* HcFmRemaining */
        !          1543:             retval = ohci_get_frame_remaining(ohci);
        !          1544:             break;
        !          1545: 
        !          1546:         case 15: /* HcFmNumber */
        !          1547:             retval = ohci->frame_number;
        !          1548:             break;
        !          1549: 
        !          1550:         case 16: /* HcPeriodicStart */
        !          1551:             retval = ohci->pstart;
        !          1552:             break;
        !          1553: 
        !          1554:         case 17: /* HcLSThreshold */
        !          1555:             retval = ohci->lst;
        !          1556:             break;
        !          1557: 
        !          1558:         case 18: /* HcRhDescriptorA */
        !          1559:             retval = ohci->rhdesc_a;
        !          1560:             break;
        !          1561: 
        !          1562:         case 19: /* HcRhDescriptorB */
        !          1563:             retval = ohci->rhdesc_b;
        !          1564:             break;
        !          1565: 
        !          1566:         case 20: /* HcRhStatus */
        !          1567:             retval = ohci->rhstatus;
        !          1568:             break;
        !          1569: 
        !          1570:         /* PXA27x specific registers */
        !          1571:         case 24: /* HcStatus */
        !          1572:             retval = ohci->hstatus & ohci->hmask;
        !          1573:             break;
        !          1574: 
        !          1575:         case 25: /* HcHReset */
        !          1576:             retval = ohci->hreset;
        !          1577:             break;
        !          1578: 
        !          1579:         case 26: /* HcHInterruptEnable */
        !          1580:             retval = ohci->hmask;
        !          1581:             break;
        !          1582: 
        !          1583:         case 27: /* HcHInterruptTest */
        !          1584:             retval = ohci->htest;
        !          1585:             break;
        !          1586: 
        !          1587:         default:
        !          1588:             fprintf(stderr, "ohci_read: Bad offset %x\n", (int)addr);
        !          1589:             retval = 0xffffffff;
        !          1590:         }
        !          1591:     }
        !          1592: 
        !          1593:     return retval;
        !          1594: }
        !          1595: 
        !          1596: static void ohci_mem_write(void *opaque,
        !          1597:                            target_phys_addr_t addr,
        !          1598:                            uint64_t val,
        !          1599:                            unsigned size)
        !          1600: {
        !          1601:     OHCIState *ohci = opaque;
        !          1602: 
        !          1603:     /* Only aligned reads are allowed on OHCI */
        !          1604:     if (addr & 3) {
        !          1605:         fprintf(stderr, "usb-ohci: Mis-aligned write\n");
        !          1606:         return;
        !          1607:     }
        !          1608: 
        !          1609:     if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) {
        !          1610:         /* HcRhPortStatus */
        !          1611:         ohci_port_set_status(ohci, (addr - 0x54) >> 2, val);
        !          1612:         return;
        !          1613:     }
        !          1614: 
        !          1615:     switch (addr >> 2) {
        !          1616:     case 1: /* HcControl */
        !          1617:         ohci_set_ctl(ohci, val);
        !          1618:         break;
        !          1619: 
        !          1620:     case 2: /* HcCommandStatus */
        !          1621:         /* SOC is read-only */
        !          1622:         val = (val & ~OHCI_STATUS_SOC);
        !          1623: 
        !          1624:         /* Bits written as '0' remain unchanged in the register */
        !          1625:         ohci->status |= val;
        !          1626: 
        !          1627:         if (ohci->status & OHCI_STATUS_HCR)
        !          1628:             ohci_reset(ohci);
        !          1629:         break;
        !          1630: 
        !          1631:     case 3: /* HcInterruptStatus */
        !          1632:         ohci->intr_status &= ~val;
        !          1633:         ohci_intr_update(ohci);
        !          1634:         break;
        !          1635: 
        !          1636:     case 4: /* HcInterruptEnable */
        !          1637:         ohci->intr |= val;
        !          1638:         ohci_intr_update(ohci);
        !          1639:         break;
        !          1640: 
        !          1641:     case 5: /* HcInterruptDisable */
        !          1642:         ohci->intr &= ~val;
        !          1643:         ohci_intr_update(ohci);
        !          1644:         break;
        !          1645: 
        !          1646:     case 6: /* HcHCCA */
        !          1647:         ohci->hcca = val & OHCI_HCCA_MASK;
        !          1648:         break;
        !          1649: 
        !          1650:     case 7: /* HcPeriodCurrentED */
        !          1651:         /* Ignore writes to this read-only register, Linux does them */
        !          1652:         break;
        !          1653: 
        !          1654:     case 8: /* HcControlHeadED */
        !          1655:         ohci->ctrl_head = val & OHCI_EDPTR_MASK;
        !          1656:         break;
        !          1657: 
        !          1658:     case 9: /* HcControlCurrentED */
        !          1659:         ohci->ctrl_cur = val & OHCI_EDPTR_MASK;
        !          1660:         break;
        !          1661: 
        !          1662:     case 10: /* HcBulkHeadED */
        !          1663:         ohci->bulk_head = val & OHCI_EDPTR_MASK;
        !          1664:         break;
        !          1665: 
        !          1666:     case 11: /* HcBulkCurrentED */
        !          1667:         ohci->bulk_cur = val & OHCI_EDPTR_MASK;
        !          1668:         break;
        !          1669: 
        !          1670:     case 13: /* HcFmInterval */
        !          1671:         ohci->fsmps = (val & OHCI_FMI_FSMPS) >> 16;
        !          1672:         ohci->fit = (val & OHCI_FMI_FIT) >> 31;
        !          1673:         ohci_set_frame_interval(ohci, val);
        !          1674:         break;
        !          1675: 
        !          1676:     case 15: /* HcFmNumber */
        !          1677:         break;
        !          1678: 
        !          1679:     case 16: /* HcPeriodicStart */
        !          1680:         ohci->pstart = val & 0xffff;
        !          1681:         break;
        !          1682: 
        !          1683:     case 17: /* HcLSThreshold */
        !          1684:         ohci->lst = val & 0xffff;
        !          1685:         break;
        !          1686: 
        !          1687:     case 18: /* HcRhDescriptorA */
        !          1688:         ohci->rhdesc_a &= ~OHCI_RHA_RW_MASK;
        !          1689:         ohci->rhdesc_a |= val & OHCI_RHA_RW_MASK;
        !          1690:         break;
        !          1691: 
        !          1692:     case 19: /* HcRhDescriptorB */
        !          1693:         break;
        !          1694: 
        !          1695:     case 20: /* HcRhStatus */
        !          1696:         ohci_set_hub_status(ohci, val);
        !          1697:         break;
        !          1698: 
        !          1699:     /* PXA27x specific registers */
        !          1700:     case 24: /* HcStatus */
        !          1701:         ohci->hstatus &= ~(val & ohci->hmask);
        !          1702: 
        !          1703:     case 25: /* HcHReset */
        !          1704:         ohci->hreset = val & ~OHCI_HRESET_FSBIR;
        !          1705:         if (val & OHCI_HRESET_FSBIR)
        !          1706:             ohci_reset(ohci);
        !          1707:         break;
        !          1708: 
        !          1709:     case 26: /* HcHInterruptEnable */
        !          1710:         ohci->hmask = val;
        !          1711:         break;
        !          1712: 
        !          1713:     case 27: /* HcHInterruptTest */
        !          1714:         ohci->htest = val;
        !          1715:         break;
        !          1716: 
        !          1717:     default:
        !          1718:         fprintf(stderr, "ohci_write: Bad offset %x\n", (int)addr);
        !          1719:         break;
        !          1720:     }
        !          1721: }
        !          1722: 
        !          1723: static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev)
        !          1724: {
        !          1725:     if (ohci->async_td &&
        !          1726:         usb_packet_is_inflight(&ohci->usb_packet) &&
        !          1727:         ohci->usb_packet.ep->dev == dev) {
        !          1728:         usb_cancel_packet(&ohci->usb_packet);
        !          1729:         ohci->async_td = 0;
        !          1730:     }
        !          1731: }
        !          1732: 
        !          1733: static const MemoryRegionOps ohci_mem_ops = {
        !          1734:     .read = ohci_mem_read,
        !          1735:     .write = ohci_mem_write,
        !          1736:     .endianness = DEVICE_LITTLE_ENDIAN,
        !          1737: };
        !          1738: 
        !          1739: static USBPortOps ohci_port_ops = {
        !          1740:     .attach = ohci_attach,
        !          1741:     .detach = ohci_detach,
        !          1742:     .child_detach = ohci_child_detach,
        !          1743:     .wakeup = ohci_wakeup,
        !          1744:     .complete = ohci_async_complete_packet,
        !          1745: };
        !          1746: 
        !          1747: static USBBusOps ohci_bus_ops = {
        !          1748: };
        !          1749: 
        !          1750: static int usb_ohci_init(OHCIState *ohci, DeviceState *dev,
        !          1751:                          int num_ports, uint32_t localmem_base,
        !          1752:                          char *masterbus, uint32_t firstport)
        !          1753: {
        !          1754:     int i;
        !          1755: 
        !          1756:     if (usb_frame_time == 0) {
        !          1757: #ifdef OHCI_TIME_WARP
        !          1758:         usb_frame_time = get_ticks_per_sec();
        !          1759:         usb_bit_time = muldiv64(1, get_ticks_per_sec(), USB_HZ/1000);
        !          1760: #else
        !          1761:         usb_frame_time = muldiv64(1, get_ticks_per_sec(), 1000);
        !          1762:         if (get_ticks_per_sec() >= USB_HZ) {
        !          1763:             usb_bit_time = muldiv64(1, get_ticks_per_sec(), USB_HZ);
        !          1764:         } else {
        !          1765:             usb_bit_time = 1;
        !          1766:         }
        !          1767: #endif
        !          1768:         DPRINTF("usb-ohci: usb_bit_time=%" PRId64 " usb_frame_time=%" PRId64 "\n",
        !          1769:                 usb_frame_time, usb_bit_time);
        !          1770:     }
        !          1771: 
        !          1772:     ohci->num_ports = num_ports;
        !          1773:     if (masterbus) {
        !          1774:         USBPort *ports[OHCI_MAX_PORTS];
        !          1775:         for(i = 0; i < num_ports; i++) {
        !          1776:             ports[i] = &ohci->rhport[i].port;
        !          1777:         }
        !          1778:         if (usb_register_companion(masterbus, ports, num_ports,
        !          1779:                 firstport, ohci, &ohci_port_ops,
        !          1780:                 USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL) != 0) {
        !          1781:             return -1;
        !          1782:         }
        !          1783:     } else {
        !          1784:         usb_bus_new(&ohci->bus, &ohci_bus_ops, dev);
        !          1785:         for (i = 0; i < num_ports; i++) {
        !          1786:             usb_register_port(&ohci->bus, &ohci->rhport[i].port,
        !          1787:                               ohci, i, &ohci_port_ops,
        !          1788:                               USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
        !          1789:         }
        !          1790:     }
        !          1791: 
        !          1792:     memory_region_init_io(&ohci->mem, &ohci_mem_ops, ohci, "ohci", 256);
        !          1793:     ohci->localmem_base = localmem_base;
        !          1794: 
        !          1795:     ohci->name = object_get_typename(OBJECT(dev));
        !          1796:     usb_packet_init(&ohci->usb_packet);
        !          1797: 
        !          1798:     ohci->async_td = 0;
        !          1799:     qemu_register_reset(ohci_reset, ohci);
        !          1800: 
        !          1801:     return 0;
        !          1802: }
        !          1803: 
        !          1804: typedef struct {
        !          1805:     PCIDevice pci_dev;
        !          1806:     OHCIState state;
        !          1807:     char *masterbus;
        !          1808:     uint32_t num_ports;
        !          1809:     uint32_t firstport;
        !          1810: } OHCIPCIState;
        !          1811: 
        !          1812: static int usb_ohci_initfn_pci(struct PCIDevice *dev)
        !          1813: {
        !          1814:     OHCIPCIState *ohci = DO_UPCAST(OHCIPCIState, pci_dev, dev);
        !          1815: 
        !          1816:     ohci->pci_dev.config[PCI_CLASS_PROG] = 0x10; /* OHCI */
        !          1817:     ohci->pci_dev.config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin A */
        !          1818: 
        !          1819:     if (usb_ohci_init(&ohci->state, &dev->qdev, ohci->num_ports, 0,
        !          1820:                       ohci->masterbus, ohci->firstport) != 0) {
        !          1821:         return -1;
        !          1822:     }
        !          1823:     ohci->state.irq = ohci->pci_dev.irq[0];
        !          1824: 
        !          1825:     /* TODO: avoid cast below by using dev */
        !          1826:     pci_register_bar(&ohci->pci_dev, 0, 0, &ohci->state.mem);
        !          1827:     return 0;
        !          1828: }
        !          1829: 
        !          1830: typedef struct {
        !          1831:     SysBusDevice busdev;
        !          1832:     OHCIState ohci;
        !          1833:     uint32_t num_ports;
        !          1834:     target_phys_addr_t dma_offset;
        !          1835: } OHCISysBusState;
        !          1836: 
        !          1837: static int ohci_init_pxa(SysBusDevice *dev)
        !          1838: {
        !          1839:     OHCISysBusState *s = FROM_SYSBUS(OHCISysBusState, dev);
        !          1840: 
        !          1841:     /* Cannot fail as we pass NULL for masterbus */
        !          1842:     usb_ohci_init(&s->ohci, &dev->qdev, s->num_ports, s->dma_offset, NULL, 0);
        !          1843:     sysbus_init_irq(dev, &s->ohci.irq);
        !          1844:     sysbus_init_mmio(dev, &s->ohci.mem);
        !          1845: 
        !          1846:     return 0;
        !          1847: }
        !          1848: 
        !          1849: static Property ohci_pci_properties[] = {
        !          1850:     DEFINE_PROP_STRING("masterbus", OHCIPCIState, masterbus),
        !          1851:     DEFINE_PROP_UINT32("num-ports", OHCIPCIState, num_ports, 3),
        !          1852:     DEFINE_PROP_UINT32("firstport", OHCIPCIState, firstport, 0),
        !          1853:     DEFINE_PROP_END_OF_LIST(),
        !          1854: };
        !          1855: 
        !          1856: static void ohci_pci_class_init(ObjectClass *klass, void *data)
        !          1857: {
        !          1858:     DeviceClass *dc = DEVICE_CLASS(klass);
        !          1859:     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
        !          1860: 
        !          1861:     k->init = usb_ohci_initfn_pci;
        !          1862:     k->vendor_id = PCI_VENDOR_ID_APPLE;
        !          1863:     k->device_id = PCI_DEVICE_ID_APPLE_IPID_USB;
        !          1864:     k->class_id = PCI_CLASS_SERIAL_USB;
        !          1865:     dc->desc = "Apple USB Controller";
        !          1866:     dc->props = ohci_pci_properties;
        !          1867: }
        !          1868: 
        !          1869: static TypeInfo ohci_pci_info = {
        !          1870:     .name          = "pci-ohci",
        !          1871:     .parent        = TYPE_PCI_DEVICE,
        !          1872:     .instance_size = sizeof(OHCIPCIState),
        !          1873:     .class_init    = ohci_pci_class_init,
        !          1874: };
        !          1875: 
        !          1876: static Property ohci_sysbus_properties[] = {
        !          1877:     DEFINE_PROP_UINT32("num-ports", OHCISysBusState, num_ports, 3),
        !          1878:     DEFINE_PROP_TADDR("dma-offset", OHCISysBusState, dma_offset, 3),
        !          1879:     DEFINE_PROP_END_OF_LIST(),
        !          1880: };
        !          1881: 
        !          1882: static void ohci_sysbus_class_init(ObjectClass *klass, void *data)
        !          1883: {
        !          1884:     DeviceClass *dc = DEVICE_CLASS(klass);
        !          1885:     SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
        !          1886: 
        !          1887:     sbc->init = ohci_init_pxa;
        !          1888:     dc->desc = "OHCI USB Controller";
        !          1889:     dc->props = ohci_sysbus_properties;
        !          1890: }
        !          1891: 
        !          1892: static TypeInfo ohci_sysbus_info = {
        !          1893:     .name          = "sysbus-ohci",
        !          1894:     .parent        = TYPE_SYS_BUS_DEVICE,
        !          1895:     .instance_size = sizeof(OHCISysBusState),
        !          1896:     .class_init    = ohci_sysbus_class_init,
        !          1897: };
        !          1898: 
        !          1899: static void ohci_register_types(void)
        !          1900: {
        !          1901:     type_register_static(&ohci_pci_info);
        !          1902:     type_register_static(&ohci_sysbus_info);
        !          1903: }
        !          1904: 
        !          1905: type_init(ohci_register_types)

unix.superglobalmegacorp.com

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