Annotation of qemu/hw/usb-uhci.c, revision 1.1.1.3

1.1       root        1: /*
                      2:  * USB UHCI controller emulation
                      3:  * 
                      4:  * Copyright (c) 2005 Fabrice Bellard
                      5:  * 
                      6:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                      7:  * of this software and associated documentation files (the "Software"), to deal
                      8:  * in the Software without restriction, including without limitation the rights
                      9:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     10:  * copies of the Software, and to permit persons to whom the Software is
                     11:  * furnished to do so, subject to the following conditions:
                     12:  *
                     13:  * The above copyright notice and this permission notice shall be included in
                     14:  * all copies or substantial portions of the Software.
                     15:  *
                     16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
                     19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     21:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     22:  * THE SOFTWARE.
                     23:  */
                     24: #include "vl.h"
                     25: 
                     26: //#define DEBUG
                     27: //#define DEBUG_PACKET
                     28: 
                     29: #define UHCI_CMD_GRESET   (1 << 2)
                     30: #define UHCI_CMD_HCRESET  (1 << 1)
                     31: #define UHCI_CMD_RS       (1 << 0)
                     32: 
                     33: #define UHCI_STS_HCHALTED (1 << 5)
                     34: #define UHCI_STS_HCPERR   (1 << 4)
                     35: #define UHCI_STS_HSERR    (1 << 3)
                     36: #define UHCI_STS_RD       (1 << 2)
                     37: #define UHCI_STS_USBERR   (1 << 1)
                     38: #define UHCI_STS_USBINT   (1 << 0)
                     39: 
                     40: #define TD_CTRL_SPD     (1 << 29)
                     41: #define TD_CTRL_ERROR_SHIFT  27
                     42: #define TD_CTRL_IOS     (1 << 25)
                     43: #define TD_CTRL_IOC     (1 << 24)
                     44: #define TD_CTRL_ACTIVE  (1 << 23)
                     45: #define TD_CTRL_STALL   (1 << 22)
                     46: #define TD_CTRL_BABBLE  (1 << 20)
                     47: #define TD_CTRL_NAK     (1 << 19)
                     48: #define TD_CTRL_TIMEOUT (1 << 18)
                     49: 
                     50: #define UHCI_PORT_RESET (1 << 9)
                     51: #define UHCI_PORT_LSDA  (1 << 8)
                     52: #define UHCI_PORT_ENC   (1 << 3)
                     53: #define UHCI_PORT_EN    (1 << 2)
                     54: #define UHCI_PORT_CSC   (1 << 1)
                     55: #define UHCI_PORT_CCS   (1 << 0)
                     56: 
                     57: #define FRAME_TIMER_FREQ 1000
                     58: 
                     59: #define FRAME_MAX_LOOPS  100
                     60: 
                     61: #define NB_PORTS 2
                     62: 
                     63: typedef struct UHCIPort {
                     64:     USBPort port;
                     65:     uint16_t ctrl;
                     66: } UHCIPort;
                     67: 
                     68: typedef struct UHCIState {
                     69:     PCIDevice dev;
                     70:     uint16_t cmd; /* cmd register */
                     71:     uint16_t status;
                     72:     uint16_t intr; /* interrupt enable register */
                     73:     uint16_t frnum; /* frame number */
                     74:     uint32_t fl_base_addr; /* frame list base address */
                     75:     uint8_t sof_timing;
                     76:     uint8_t status2; /* bit 0 and 1 are used to generate UHCI_STS_USBINT */
                     77:     QEMUTimer *frame_timer;
                     78:     UHCIPort ports[NB_PORTS];
                     79: } UHCIState;
                     80: 
                     81: typedef struct UHCI_TD {
                     82:     uint32_t link;
                     83:     uint32_t ctrl; /* see TD_CTRL_xxx */
                     84:     uint32_t token;
                     85:     uint32_t buffer;
                     86: } UHCI_TD;
                     87: 
                     88: typedef struct UHCI_QH {
                     89:     uint32_t link;
                     90:     uint32_t el_link;
                     91: } UHCI_QH;
                     92: 
                     93: static void uhci_attach(USBPort *port1, USBDevice *dev);
                     94: 
                     95: static void uhci_update_irq(UHCIState *s)
                     96: {
                     97:     int level;
                     98:     if (((s->status2 & 1) && (s->intr & (1 << 2))) ||
                     99:         ((s->status2 & 2) && (s->intr & (1 << 3))) ||
                    100:         ((s->status & UHCI_STS_USBERR) && (s->intr & (1 << 0))) ||
                    101:         ((s->status & UHCI_STS_RD) && (s->intr & (1 << 1))) ||
                    102:         (s->status & UHCI_STS_HSERR) ||
                    103:         (s->status & UHCI_STS_HCPERR)) {
                    104:         level = 1;
                    105:     } else {
                    106:         level = 0;
                    107:     }
                    108:     pci_set_irq(&s->dev, 3, level);
                    109: }
                    110: 
                    111: static void uhci_reset(UHCIState *s)
                    112: {
                    113:     uint8_t *pci_conf;
                    114:     int i;
                    115:     UHCIPort *port;
                    116: 
                    117:     pci_conf = s->dev.config;
                    118: 
                    119:     pci_conf[0x6a] = 0x01; /* usb clock */
                    120:     pci_conf[0x6b] = 0x00;
                    121:     s->cmd = 0;
                    122:     s->status = 0;
                    123:     s->status2 = 0;
                    124:     s->intr = 0;
                    125:     s->fl_base_addr = 0;
                    126:     s->sof_timing = 64;
                    127:     for(i = 0; i < NB_PORTS; i++) {
                    128:         port = &s->ports[i];
                    129:         port->ctrl = 0x0080;
                    130:         if (port->port.dev)
                    131:             uhci_attach(&port->port, port->port.dev);
                    132:     }
                    133: }
                    134: 
                    135: static void uhci_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
                    136: {
                    137:     UHCIState *s = opaque;
                    138:     
                    139:     addr &= 0x1f;
                    140:     switch(addr) {
                    141:     case 0x0c:
                    142:         s->sof_timing = val;
                    143:         break;
                    144:     }
                    145: }
                    146: 
                    147: static uint32_t uhci_ioport_readb(void *opaque, uint32_t addr)
                    148: {
                    149:     UHCIState *s = opaque;
                    150:     uint32_t val;
                    151: 
                    152:     addr &= 0x1f;
                    153:     switch(addr) {
                    154:     case 0x0c:
                    155:         val = s->sof_timing;
1.1.1.2   root      156:         break;
1.1       root      157:     default:
                    158:         val = 0xff;
                    159:         break;
                    160:     }
                    161:     return val;
                    162: }
                    163: 
                    164: static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
                    165: {
                    166:     UHCIState *s = opaque;
                    167:     
                    168:     addr &= 0x1f;
                    169: #ifdef DEBUG
                    170:     printf("uhci writew port=0x%04x val=0x%04x\n", addr, val);
                    171: #endif
                    172:     switch(addr) {
                    173:     case 0x00:
                    174:         if ((val & UHCI_CMD_RS) && !(s->cmd & UHCI_CMD_RS)) {
                    175:             /* start frame processing */
                    176:             qemu_mod_timer(s->frame_timer, qemu_get_clock(vm_clock));
1.1.1.2   root      177:             s->status &= ~UHCI_STS_HCHALTED;
                    178:         } else if (!(val & UHCI_CMD_RS)) {
                    179:             s->status |= UHCI_STS_HCHALTED;
1.1       root      180:         }
                    181:         if (val & UHCI_CMD_GRESET) {
                    182:             UHCIPort *port;
                    183:             USBDevice *dev;
                    184:             int i;
                    185: 
                    186:             /* send reset on the USB bus */
                    187:             for(i = 0; i < NB_PORTS; i++) {
                    188:                 port = &s->ports[i];
                    189:                 dev = port->port.dev;
                    190:                 if (dev) {
                    191:                     dev->handle_packet(dev, 
                    192:                                        USB_MSG_RESET, 0, 0, NULL, 0);
                    193:                 }
                    194:             }
                    195:             uhci_reset(s);
                    196:             return;
                    197:         }
                    198:         if (val & UHCI_CMD_HCRESET) {
                    199:             uhci_reset(s);
                    200:             return;
                    201:         }
                    202:         s->cmd = val;
                    203:         break;
                    204:     case 0x02:
                    205:         s->status &= ~val;
                    206:         /* XXX: the chip spec is not coherent, so we add a hidden
                    207:            register to distinguish between IOC and SPD */
                    208:         if (val & UHCI_STS_USBINT)
                    209:             s->status2 = 0;
                    210:         uhci_update_irq(s);
                    211:         break;
                    212:     case 0x04:
                    213:         s->intr = val;
                    214:         uhci_update_irq(s);
                    215:         break;
                    216:     case 0x06:
                    217:         if (s->status & UHCI_STS_HCHALTED)
                    218:             s->frnum = val & 0x7ff;
                    219:         break;
                    220:     case 0x10 ... 0x1f:
                    221:         {
                    222:             UHCIPort *port;
                    223:             USBDevice *dev;
                    224:             int n;
                    225: 
                    226:             n = (addr >> 1) & 7;
                    227:             if (n >= NB_PORTS)
                    228:                 return;
                    229:             port = &s->ports[n];
                    230:             dev = port->port.dev;
                    231:             if (dev) {
                    232:                 /* port reset */
                    233:                 if ( (val & UHCI_PORT_RESET) && 
                    234:                      !(port->ctrl & UHCI_PORT_RESET) ) {
                    235:                     dev->handle_packet(dev, 
                    236:                                        USB_MSG_RESET, 0, 0, NULL, 0);
                    237:                 }
                    238:             }
                    239:             port->ctrl = (port->ctrl & 0x01fb) | (val & ~0x01fb);
                    240:             /* some bits are reset when a '1' is written to them */
                    241:             port->ctrl &= ~(val & 0x000a);
                    242:         }
                    243:         break;
                    244:     }
                    245: }
                    246: 
                    247: static uint32_t uhci_ioport_readw(void *opaque, uint32_t addr)
                    248: {
                    249:     UHCIState *s = opaque;
                    250:     uint32_t val;
                    251: 
                    252:     addr &= 0x1f;
                    253:     switch(addr) {
                    254:     case 0x00:
                    255:         val = s->cmd;
                    256:         break;
                    257:     case 0x02:
                    258:         val = s->status;
                    259:         break;
                    260:     case 0x04:
                    261:         val = s->intr;
                    262:         break;
                    263:     case 0x06:
                    264:         val = s->frnum;
                    265:         break;
                    266:     case 0x10 ... 0x1f:
                    267:         {
                    268:             UHCIPort *port;
                    269:             int n;
                    270:             n = (addr >> 1) & 7;
                    271:             if (n >= NB_PORTS) 
                    272:                 goto read_default;
                    273:             port = &s->ports[n];
                    274:             val = port->ctrl;
                    275:         }
                    276:         break;
                    277:     default:
                    278:     read_default:
                    279:         val = 0xff7f; /* disabled port */
                    280:         break;
                    281:     }
                    282: #ifdef DEBUG
                    283:     printf("uhci readw port=0x%04x val=0x%04x\n", addr, val);
                    284: #endif
                    285:     return val;
                    286: }
                    287: 
                    288: static void uhci_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
                    289: {
                    290:     UHCIState *s = opaque;
                    291: 
                    292:     addr &= 0x1f;
                    293: #ifdef DEBUG
                    294:     printf("uhci writel port=0x%04x val=0x%08x\n", addr, val);
                    295: #endif
                    296:     switch(addr) {
                    297:     case 0x08:
                    298:         s->fl_base_addr = val & ~0xfff;
                    299:         break;
                    300:     }
                    301: }
                    302: 
                    303: static uint32_t uhci_ioport_readl(void *opaque, uint32_t addr)
                    304: {
                    305:     UHCIState *s = opaque;
                    306:     uint32_t val;
                    307: 
                    308:     addr &= 0x1f;
                    309:     switch(addr) {
                    310:     case 0x08:
                    311:         val = s->fl_base_addr;
                    312:         break;
                    313:     default:
                    314:         val = 0xffffffff;
                    315:         break;
                    316:     }
                    317:     return val;
                    318: }
                    319: 
                    320: static void uhci_attach(USBPort *port1, USBDevice *dev)
                    321: {
                    322:     UHCIState *s = port1->opaque;
                    323:     UHCIPort *port = &s->ports[port1->index];
                    324: 
                    325:     if (dev) {
                    326:         if (port->port.dev) {
                    327:             usb_attach(port1, NULL);
                    328:         }
                    329:         /* set connect status */
1.1.1.3 ! root      330:         port->ctrl |= UHCI_PORT_CCS | UHCI_PORT_CSC;
        !           331: 
1.1       root      332:         /* update speed */
                    333:         if (dev->speed == USB_SPEED_LOW)
                    334:             port->ctrl |= UHCI_PORT_LSDA;
                    335:         else
                    336:             port->ctrl &= ~UHCI_PORT_LSDA;
                    337:         port->port.dev = dev;
                    338:         /* send the attach message */
                    339:         dev->handle_packet(dev, 
                    340:                            USB_MSG_ATTACH, 0, 0, NULL, 0);
                    341:     } else {
                    342:         /* set connect status */
1.1.1.3 ! root      343:         if (port->ctrl & UHCI_PORT_CCS) {
        !           344:             port->ctrl &= ~UHCI_PORT_CCS;
        !           345:             port->ctrl |= UHCI_PORT_CSC;
1.1       root      346:         }
                    347:         /* disable port */
                    348:         if (port->ctrl & UHCI_PORT_EN) {
                    349:             port->ctrl &= ~UHCI_PORT_EN;
                    350:             port->ctrl |= UHCI_PORT_ENC;
                    351:         }
                    352:         dev = port->port.dev;
                    353:         if (dev) {
                    354:             /* send the detach message */
                    355:             dev->handle_packet(dev, 
                    356:                                USB_MSG_DETACH, 0, 0, NULL, 0);
                    357:         }
                    358:         port->port.dev = NULL;
                    359:     }
                    360: }
                    361: 
                    362: static int uhci_broadcast_packet(UHCIState *s, uint8_t pid, 
                    363:                                  uint8_t devaddr, uint8_t devep,
                    364:                                  uint8_t *data, int len)
                    365: {
                    366:     UHCIPort *port;
                    367:     USBDevice *dev;
                    368:     int i, ret;
                    369: 
                    370: #ifdef DEBUG_PACKET
                    371:     {
                    372:         const char *pidstr;
                    373:         switch(pid) {
                    374:         case USB_TOKEN_SETUP: pidstr = "SETUP"; break;
                    375:         case USB_TOKEN_IN: pidstr = "IN"; break;
                    376:         case USB_TOKEN_OUT: pidstr = "OUT"; break;
                    377:         default: pidstr = "?"; break;
                    378:         }
                    379:         printf("frame %d: pid=%s addr=0x%02x ep=%d len=%d\n",
                    380:                s->frnum, pidstr, devaddr, devep, len);
                    381:         if (pid != USB_TOKEN_IN) {
                    382:             printf("     data_out=");
                    383:             for(i = 0; i < len; i++) {
                    384:                 printf(" %02x", data[i]);
                    385:             }
                    386:             printf("\n");
                    387:         }
                    388:     }
                    389: #endif
                    390:     for(i = 0; i < NB_PORTS; i++) {
                    391:         port = &s->ports[i];
                    392:         dev = port->port.dev;
                    393:         if (dev && (port->ctrl & UHCI_PORT_EN)) {
                    394:             ret = dev->handle_packet(dev, pid, 
                    395:                                      devaddr, devep,
                    396:                                      data, len);
                    397:             if (ret != USB_RET_NODEV) {
                    398: #ifdef DEBUG_PACKET
                    399:                 {
                    400:                     printf("     ret=%d ", ret);
                    401:                     if (pid == USB_TOKEN_IN && ret > 0) {
                    402:                         printf("data_in=");
                    403:                         for(i = 0; i < ret; i++) {
                    404:                             printf(" %02x", data[i]);
                    405:                         }
                    406:                     }
                    407:                     printf("\n");
                    408:                 }
                    409: #endif
                    410:                 return ret;
                    411:             }
                    412:         }
                    413:     }
                    414:     return USB_RET_NODEV;
                    415: }
                    416: 
                    417: /* return -1 if fatal error (frame must be stopped)
                    418:           0 if TD successful
                    419:           1 if TD unsuccessful or inactive
                    420: */
                    421: static int uhci_handle_td(UHCIState *s, UHCI_TD *td, int *int_mask)
                    422: {
                    423:     uint8_t pid;
                    424:     uint8_t buf[1280];
                    425:     int len, max_len, err, ret;
                    426: 
                    427:     if (td->ctrl & TD_CTRL_IOC) {
                    428:         *int_mask |= 0x01;
                    429:     }
                    430:     
                    431:     if (!(td->ctrl & TD_CTRL_ACTIVE))
                    432:         return 1;
                    433: 
                    434:     /* TD is active */
                    435:     max_len = ((td->token >> 21) + 1) & 0x7ff;
                    436:     pid = td->token & 0xff;
                    437:     switch(pid) {
                    438:     case USB_TOKEN_OUT:
                    439:     case USB_TOKEN_SETUP:
                    440:         cpu_physical_memory_read(td->buffer, buf, max_len);
                    441:         ret = uhci_broadcast_packet(s, pid, 
                    442:                                     (td->token >> 8) & 0x7f,
                    443:                                     (td->token >> 15) & 0xf,
                    444:                                     buf, max_len);
                    445:         len = max_len;
                    446:         break;
                    447:     case USB_TOKEN_IN:
                    448:         ret = uhci_broadcast_packet(s, pid, 
                    449:                                     (td->token >> 8) & 0x7f,
                    450:                                     (td->token >> 15) & 0xf,
                    451:                                     buf, max_len);
                    452:         if (ret >= 0) {
                    453:             len = ret;
                    454:             if (len > max_len) {
                    455:                 len = max_len;
                    456:                 ret = USB_RET_BABBLE;
                    457:             }
                    458:             if (len > 0) {
                    459:                 /* write the data back */
                    460:                 cpu_physical_memory_write(td->buffer, buf, len);
                    461:             }
                    462:         } else {
                    463:             len = 0;
                    464:         }
                    465:         break;
                    466:     default:
                    467:         /* invalid pid : frame interrupted */
                    468:         s->status |= UHCI_STS_HCPERR;
                    469:         uhci_update_irq(s);
                    470:         return -1;
                    471:     }
                    472:     if (td->ctrl & TD_CTRL_IOS)
                    473:         td->ctrl &= ~TD_CTRL_ACTIVE;
                    474:     if (ret >= 0) {
                    475:         td->ctrl = (td->ctrl & ~0x7ff) | ((len - 1) & 0x7ff);
                    476:         td->ctrl &= ~TD_CTRL_ACTIVE;
                    477:         if (pid == USB_TOKEN_IN && 
                    478:             (td->ctrl & TD_CTRL_SPD) &&
                    479:             len < max_len) {
                    480:             *int_mask |= 0x02;
                    481:             /* short packet: do not update QH */
                    482:             return 1;
                    483:         } else {
                    484:             /* success */
                    485:             return 0;
                    486:         }
                    487:     } else {
                    488:         switch(ret) {
                    489:         default:
                    490:         case USB_RET_NODEV:
                    491:         do_timeout:
                    492:             td->ctrl |= TD_CTRL_TIMEOUT;
                    493:             err = (td->ctrl >> TD_CTRL_ERROR_SHIFT) & 3;
                    494:             if (err != 0) {
                    495:                 err--;
                    496:                 if (err == 0) {
                    497:                     td->ctrl &= ~TD_CTRL_ACTIVE;
                    498:                     s->status |= UHCI_STS_USBERR;
                    499:                     uhci_update_irq(s);
                    500:                 }
                    501:             }
                    502:             td->ctrl = (td->ctrl & ~(3 << TD_CTRL_ERROR_SHIFT)) | 
                    503:                 (err << TD_CTRL_ERROR_SHIFT);
                    504:             return 1;
                    505:         case USB_RET_NAK:
                    506:             td->ctrl |= TD_CTRL_NAK;
                    507:             if (pid == USB_TOKEN_SETUP)
                    508:                 goto do_timeout;
                    509:             return 1;
                    510:         case USB_RET_STALL:
                    511:             td->ctrl |= TD_CTRL_STALL;
                    512:             td->ctrl &= ~TD_CTRL_ACTIVE;
                    513:             return 1;
                    514:         case USB_RET_BABBLE:
                    515:             td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL;
                    516:             td->ctrl &= ~TD_CTRL_ACTIVE;
                    517:             /* frame interrupted */
                    518:             return -1;
                    519:         }
                    520:     }
                    521: }
                    522: 
                    523: static void uhci_frame_timer(void *opaque)
                    524: {
                    525:     UHCIState *s = opaque;
                    526:     int64_t expire_time;
                    527:     uint32_t frame_addr, link, old_td_ctrl, val;
                    528:     int int_mask, cnt, ret;
                    529:     UHCI_TD td;
                    530:     UHCI_QH qh;
                    531: 
                    532:     if (!(s->cmd & UHCI_CMD_RS)) {
                    533:         qemu_del_timer(s->frame_timer);
1.1.1.2   root      534:         /* set hchalted bit in status - UHCI11D 2.1.2 */
                    535:         s->status |= UHCI_STS_HCHALTED;
1.1       root      536:         return;
                    537:     }
                    538:     frame_addr = s->fl_base_addr + ((s->frnum & 0x3ff) << 2);
                    539:     cpu_physical_memory_read(frame_addr, (uint8_t *)&link, 4);
                    540:     le32_to_cpus(&link);
                    541:     int_mask = 0;
                    542:     cnt = FRAME_MAX_LOOPS;
                    543:     while ((link & 1) == 0) {
                    544:         if (--cnt == 0)
                    545:             break;
                    546:         /* valid frame */
                    547:         if (link & 2) {
                    548:             /* QH */
                    549:             cpu_physical_memory_read(link & ~0xf, (uint8_t *)&qh, sizeof(qh));
                    550:             le32_to_cpus(&qh.link);
                    551:             le32_to_cpus(&qh.el_link);
                    552:         depth_first:
                    553:             if (qh.el_link & 1) {
                    554:                 /* no element : go to next entry */
                    555:                 link = qh.link;
                    556:             } else if (qh.el_link & 2) {
                    557:                 /* QH */
                    558:                 link = qh.el_link;
                    559:             } else {
                    560:                 /* TD */
                    561:                 if (--cnt == 0)
                    562:                     break;
                    563:                 cpu_physical_memory_read(qh.el_link & ~0xf, 
                    564:                                          (uint8_t *)&td, sizeof(td));
                    565:                 le32_to_cpus(&td.link);
                    566:                 le32_to_cpus(&td.ctrl);
                    567:                 le32_to_cpus(&td.token);
                    568:                 le32_to_cpus(&td.buffer);
                    569:                 old_td_ctrl = td.ctrl;
                    570:                 ret = uhci_handle_td(s, &td, &int_mask);
                    571:                 /* update the status bits of the TD */
                    572:                 if (old_td_ctrl != td.ctrl) {
                    573:                     val = cpu_to_le32(td.ctrl);
                    574:                     cpu_physical_memory_write((qh.el_link & ~0xf) + 4, 
                    575:                                               (const uint8_t *)&val, 
                    576:                                               sizeof(val));
                    577:                 }
                    578:                 if (ret < 0)
                    579:                     break; /* interrupted frame */
                    580:                 if (ret == 0) {
                    581:                     /* update qh element link */
                    582:                     qh.el_link = td.link;
                    583:                     val = cpu_to_le32(qh.el_link);
                    584:                     cpu_physical_memory_write((link & ~0xf) + 4, 
                    585:                                               (const uint8_t *)&val, 
                    586:                                               sizeof(val));
                    587:                     if (qh.el_link & 4) {
                    588:                         /* depth first */
                    589:                         goto depth_first;
                    590:                     }
                    591:                 }
                    592:                 /* go to next entry */
                    593:                 link = qh.link;
                    594:             }
                    595:         } else {
                    596:             /* TD */
                    597:             cpu_physical_memory_read(link & ~0xf, (uint8_t *)&td, sizeof(td));
                    598:             le32_to_cpus(&td.link);
                    599:             le32_to_cpus(&td.ctrl);
                    600:             le32_to_cpus(&td.token);
                    601:             le32_to_cpus(&td.buffer);
                    602:             old_td_ctrl = td.ctrl;
                    603:             ret = uhci_handle_td(s, &td, &int_mask);
                    604:             /* update the status bits of the TD */
                    605:             if (old_td_ctrl != td.ctrl) {
                    606:                 val = cpu_to_le32(td.ctrl);
                    607:                 cpu_physical_memory_write((link & ~0xf) + 4, 
                    608:                                           (const uint8_t *)&val, 
                    609:                                           sizeof(val));
                    610:             }
                    611:             if (ret < 0)
                    612:                 break; /* interrupted frame */
                    613:             link = td.link;
                    614:         }
                    615:     }
                    616:     s->frnum = (s->frnum + 1) & 0x7ff;
                    617:     if (int_mask) {
                    618:         s->status2 |= int_mask;
                    619:         s->status |= UHCI_STS_USBINT;
                    620:         uhci_update_irq(s);
                    621:     }
                    622:     /* prepare the timer for the next frame */
                    623:     expire_time = qemu_get_clock(vm_clock) + 
                    624:         (ticks_per_sec / FRAME_TIMER_FREQ);
                    625:     qemu_mod_timer(s->frame_timer, expire_time);
                    626: }
                    627: 
                    628: static void uhci_map(PCIDevice *pci_dev, int region_num, 
                    629:                     uint32_t addr, uint32_t size, int type)
                    630: {
                    631:     UHCIState *s = (UHCIState *)pci_dev;
                    632: 
                    633:     register_ioport_write(addr, 32, 2, uhci_ioport_writew, s);
                    634:     register_ioport_read(addr, 32, 2, uhci_ioport_readw, s);
                    635:     register_ioport_write(addr, 32, 4, uhci_ioport_writel, s);
                    636:     register_ioport_read(addr, 32, 4, uhci_ioport_readl, s);
                    637:     register_ioport_write(addr, 32, 1, uhci_ioport_writeb, s);
                    638:     register_ioport_read(addr, 32, 1, uhci_ioport_readb, s);
                    639: }
                    640: 
1.1.1.3 ! root      641: void usb_uhci_init(PCIBus *bus, int devfn)
1.1       root      642: {
                    643:     UHCIState *s;
                    644:     uint8_t *pci_conf;
                    645:     int i;
                    646: 
                    647:     s = (UHCIState *)pci_register_device(bus,
                    648:                                         "USB-UHCI", sizeof(UHCIState),
1.1.1.3 ! root      649:                                         devfn, NULL, NULL);
1.1       root      650:     pci_conf = s->dev.config;
                    651:     pci_conf[0x00] = 0x86;
                    652:     pci_conf[0x01] = 0x80;
                    653:     pci_conf[0x02] = 0x20;
                    654:     pci_conf[0x03] = 0x70;
                    655:     pci_conf[0x08] = 0x01; // revision number
                    656:     pci_conf[0x09] = 0x00;
                    657:     pci_conf[0x0a] = 0x03;
                    658:     pci_conf[0x0b] = 0x0c;
                    659:     pci_conf[0x0e] = 0x00; // header_type
                    660:     pci_conf[0x3d] = 4; // interrupt pin 3
1.1.1.2   root      661:     pci_conf[0x60] = 0x10; // release number
1.1       root      662:     
                    663:     for(i = 0; i < NB_PORTS; i++) {
1.1.1.3 ! root      664:         qemu_register_usb_port(&s->ports[i].port, s, i, uhci_attach);
1.1       root      665:     }
                    666:     s->frame_timer = qemu_new_timer(vm_clock, uhci_frame_timer, s);
                    667: 
                    668:     uhci_reset(s);
                    669: 
1.1.1.2   root      670:     /* Use region 4 for consistency with real hardware.  BSD guests seem
                    671:        to rely on this.  */
                    672:     pci_register_io_region(&s->dev, 4, 0x20, 
1.1       root      673:                            PCI_ADDRESS_SPACE_IO, uhci_map);
                    674: }

unix.superglobalmegacorp.com

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