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

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;
                    156:     default:
                    157:         val = 0xff;
                    158:         break;
                    159:     }
                    160:     return val;
                    161: }
                    162: 
                    163: static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
                    164: {
                    165:     UHCIState *s = opaque;
                    166:     
                    167:     addr &= 0x1f;
                    168: #ifdef DEBUG
                    169:     printf("uhci writew port=0x%04x val=0x%04x\n", addr, val);
                    170: #endif
                    171:     switch(addr) {
                    172:     case 0x00:
                    173:         if ((val & UHCI_CMD_RS) && !(s->cmd & UHCI_CMD_RS)) {
                    174:             /* start frame processing */
                    175:             qemu_mod_timer(s->frame_timer, qemu_get_clock(vm_clock));
                    176:         }
                    177:         if (val & UHCI_CMD_GRESET) {
                    178:             UHCIPort *port;
                    179:             USBDevice *dev;
                    180:             int i;
                    181: 
                    182:             /* send reset on the USB bus */
                    183:             for(i = 0; i < NB_PORTS; i++) {
                    184:                 port = &s->ports[i];
                    185:                 dev = port->port.dev;
                    186:                 if (dev) {
                    187:                     dev->handle_packet(dev, 
                    188:                                        USB_MSG_RESET, 0, 0, NULL, 0);
                    189:                 }
                    190:             }
                    191:             uhci_reset(s);
                    192:             return;
                    193:         }
                    194:         if (val & UHCI_CMD_HCRESET) {
                    195:             uhci_reset(s);
                    196:             return;
                    197:         }
                    198:         s->cmd = val;
                    199:         break;
                    200:     case 0x02:
                    201:         s->status &= ~val;
                    202:         /* XXX: the chip spec is not coherent, so we add a hidden
                    203:            register to distinguish between IOC and SPD */
                    204:         if (val & UHCI_STS_USBINT)
                    205:             s->status2 = 0;
                    206:         uhci_update_irq(s);
                    207:         break;
                    208:     case 0x04:
                    209:         s->intr = val;
                    210:         uhci_update_irq(s);
                    211:         break;
                    212:     case 0x06:
                    213:         if (s->status & UHCI_STS_HCHALTED)
                    214:             s->frnum = val & 0x7ff;
                    215:         break;
                    216:     case 0x10 ... 0x1f:
                    217:         {
                    218:             UHCIPort *port;
                    219:             USBDevice *dev;
                    220:             int n;
                    221: 
                    222:             n = (addr >> 1) & 7;
                    223:             if (n >= NB_PORTS)
                    224:                 return;
                    225:             port = &s->ports[n];
                    226:             dev = port->port.dev;
                    227:             if (dev) {
                    228:                 /* port reset */
                    229:                 if ( (val & UHCI_PORT_RESET) && 
                    230:                      !(port->ctrl & UHCI_PORT_RESET) ) {
                    231:                     dev->handle_packet(dev, 
                    232:                                        USB_MSG_RESET, 0, 0, NULL, 0);
                    233:                 }
                    234:             }
                    235:             port->ctrl = (port->ctrl & 0x01fb) | (val & ~0x01fb);
                    236:             /* some bits are reset when a '1' is written to them */
                    237:             port->ctrl &= ~(val & 0x000a);
                    238:         }
                    239:         break;
                    240:     }
                    241: }
                    242: 
                    243: static uint32_t uhci_ioport_readw(void *opaque, uint32_t addr)
                    244: {
                    245:     UHCIState *s = opaque;
                    246:     uint32_t val;
                    247: 
                    248:     addr &= 0x1f;
                    249:     switch(addr) {
                    250:     case 0x00:
                    251:         val = s->cmd;
                    252:         break;
                    253:     case 0x02:
                    254:         val = s->status;
                    255:         break;
                    256:     case 0x04:
                    257:         val = s->intr;
                    258:         break;
                    259:     case 0x06:
                    260:         val = s->frnum;
                    261:         break;
                    262:     case 0x10 ... 0x1f:
                    263:         {
                    264:             UHCIPort *port;
                    265:             int n;
                    266:             n = (addr >> 1) & 7;
                    267:             if (n >= NB_PORTS) 
                    268:                 goto read_default;
                    269:             port = &s->ports[n];
                    270:             val = port->ctrl;
                    271:         }
                    272:         break;
                    273:     default:
                    274:     read_default:
                    275:         val = 0xff7f; /* disabled port */
                    276:         break;
                    277:     }
                    278: #ifdef DEBUG
                    279:     printf("uhci readw port=0x%04x val=0x%04x\n", addr, val);
                    280: #endif
                    281:     return val;
                    282: }
                    283: 
                    284: static void uhci_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
                    285: {
                    286:     UHCIState *s = opaque;
                    287: 
                    288:     addr &= 0x1f;
                    289: #ifdef DEBUG
                    290:     printf("uhci writel port=0x%04x val=0x%08x\n", addr, val);
                    291: #endif
                    292:     switch(addr) {
                    293:     case 0x08:
                    294:         s->fl_base_addr = val & ~0xfff;
                    295:         break;
                    296:     }
                    297: }
                    298: 
                    299: static uint32_t uhci_ioport_readl(void *opaque, uint32_t addr)
                    300: {
                    301:     UHCIState *s = opaque;
                    302:     uint32_t val;
                    303: 
                    304:     addr &= 0x1f;
                    305:     switch(addr) {
                    306:     case 0x08:
                    307:         val = s->fl_base_addr;
                    308:         break;
                    309:     default:
                    310:         val = 0xffffffff;
                    311:         break;
                    312:     }
                    313:     return val;
                    314: }
                    315: 
                    316: static void uhci_attach(USBPort *port1, USBDevice *dev)
                    317: {
                    318:     UHCIState *s = port1->opaque;
                    319:     UHCIPort *port = &s->ports[port1->index];
                    320: 
                    321:     if (dev) {
                    322:         if (port->port.dev) {
                    323:             usb_attach(port1, NULL);
                    324:         }
                    325:         /* set connect status */
                    326:         if (!(port->ctrl & UHCI_PORT_CCS)) {
                    327:             port->ctrl |= UHCI_PORT_CCS | UHCI_PORT_CSC;
                    328:         }
                    329:         /* update speed */
                    330:         if (dev->speed == USB_SPEED_LOW)
                    331:             port->ctrl |= UHCI_PORT_LSDA;
                    332:         else
                    333:             port->ctrl &= ~UHCI_PORT_LSDA;
                    334:         port->port.dev = dev;
                    335:         /* send the attach message */
                    336:         dev->handle_packet(dev, 
                    337:                            USB_MSG_ATTACH, 0, 0, NULL, 0);
                    338:     } else {
                    339:         /* set connect status */
                    340:         if (!(port->ctrl & UHCI_PORT_CCS)) {
                    341:             port->ctrl |= UHCI_PORT_CCS | UHCI_PORT_CSC;
                    342:         }
                    343:         /* disable port */
                    344:         if (port->ctrl & UHCI_PORT_EN) {
                    345:             port->ctrl &= ~UHCI_PORT_EN;
                    346:             port->ctrl |= UHCI_PORT_ENC;
                    347:         }
                    348:         dev = port->port.dev;
                    349:         if (dev) {
                    350:             /* send the detach message */
                    351:             dev->handle_packet(dev, 
                    352:                                USB_MSG_DETACH, 0, 0, NULL, 0);
                    353:         }
                    354:         port->port.dev = NULL;
                    355:     }
                    356: }
                    357: 
                    358: static int uhci_broadcast_packet(UHCIState *s, uint8_t pid, 
                    359:                                  uint8_t devaddr, uint8_t devep,
                    360:                                  uint8_t *data, int len)
                    361: {
                    362:     UHCIPort *port;
                    363:     USBDevice *dev;
                    364:     int i, ret;
                    365: 
                    366: #ifdef DEBUG_PACKET
                    367:     {
                    368:         const char *pidstr;
                    369:         switch(pid) {
                    370:         case USB_TOKEN_SETUP: pidstr = "SETUP"; break;
                    371:         case USB_TOKEN_IN: pidstr = "IN"; break;
                    372:         case USB_TOKEN_OUT: pidstr = "OUT"; break;
                    373:         default: pidstr = "?"; break;
                    374:         }
                    375:         printf("frame %d: pid=%s addr=0x%02x ep=%d len=%d\n",
                    376:                s->frnum, pidstr, devaddr, devep, len);
                    377:         if (pid != USB_TOKEN_IN) {
                    378:             printf("     data_out=");
                    379:             for(i = 0; i < len; i++) {
                    380:                 printf(" %02x", data[i]);
                    381:             }
                    382:             printf("\n");
                    383:         }
                    384:     }
                    385: #endif
                    386:     for(i = 0; i < NB_PORTS; i++) {
                    387:         port = &s->ports[i];
                    388:         dev = port->port.dev;
                    389:         if (dev && (port->ctrl & UHCI_PORT_EN)) {
                    390:             ret = dev->handle_packet(dev, pid, 
                    391:                                      devaddr, devep,
                    392:                                      data, len);
                    393:             if (ret != USB_RET_NODEV) {
                    394: #ifdef DEBUG_PACKET
                    395:                 {
                    396:                     printf("     ret=%d ", ret);
                    397:                     if (pid == USB_TOKEN_IN && ret > 0) {
                    398:                         printf("data_in=");
                    399:                         for(i = 0; i < ret; i++) {
                    400:                             printf(" %02x", data[i]);
                    401:                         }
                    402:                     }
                    403:                     printf("\n");
                    404:                 }
                    405: #endif
                    406:                 return ret;
                    407:             }
                    408:         }
                    409:     }
                    410:     return USB_RET_NODEV;
                    411: }
                    412: 
                    413: /* return -1 if fatal error (frame must be stopped)
                    414:           0 if TD successful
                    415:           1 if TD unsuccessful or inactive
                    416: */
                    417: static int uhci_handle_td(UHCIState *s, UHCI_TD *td, int *int_mask)
                    418: {
                    419:     uint8_t pid;
                    420:     uint8_t buf[1280];
                    421:     int len, max_len, err, ret;
                    422: 
                    423:     if (td->ctrl & TD_CTRL_IOC) {
                    424:         *int_mask |= 0x01;
                    425:     }
                    426:     
                    427:     if (!(td->ctrl & TD_CTRL_ACTIVE))
                    428:         return 1;
                    429: 
                    430:     /* TD is active */
                    431:     max_len = ((td->token >> 21) + 1) & 0x7ff;
                    432:     pid = td->token & 0xff;
                    433:     switch(pid) {
                    434:     case USB_TOKEN_OUT:
                    435:     case USB_TOKEN_SETUP:
                    436:         cpu_physical_memory_read(td->buffer, buf, max_len);
                    437:         ret = uhci_broadcast_packet(s, pid, 
                    438:                                     (td->token >> 8) & 0x7f,
                    439:                                     (td->token >> 15) & 0xf,
                    440:                                     buf, max_len);
                    441:         len = max_len;
                    442:         break;
                    443:     case USB_TOKEN_IN:
                    444:         ret = uhci_broadcast_packet(s, pid, 
                    445:                                     (td->token >> 8) & 0x7f,
                    446:                                     (td->token >> 15) & 0xf,
                    447:                                     buf, max_len);
                    448:         if (ret >= 0) {
                    449:             len = ret;
                    450:             if (len > max_len) {
                    451:                 len = max_len;
                    452:                 ret = USB_RET_BABBLE;
                    453:             }
                    454:             if (len > 0) {
                    455:                 /* write the data back */
                    456:                 cpu_physical_memory_write(td->buffer, buf, len);
                    457:             }
                    458:         } else {
                    459:             len = 0;
                    460:         }
                    461:         break;
                    462:     default:
                    463:         /* invalid pid : frame interrupted */
                    464:         s->status |= UHCI_STS_HCPERR;
                    465:         uhci_update_irq(s);
                    466:         return -1;
                    467:     }
                    468:     if (td->ctrl & TD_CTRL_IOS)
                    469:         td->ctrl &= ~TD_CTRL_ACTIVE;
                    470:     if (ret >= 0) {
                    471:         td->ctrl = (td->ctrl & ~0x7ff) | ((len - 1) & 0x7ff);
                    472:         td->ctrl &= ~TD_CTRL_ACTIVE;
                    473:         if (pid == USB_TOKEN_IN && 
                    474:             (td->ctrl & TD_CTRL_SPD) &&
                    475:             len < max_len) {
                    476:             *int_mask |= 0x02;
                    477:             /* short packet: do not update QH */
                    478:             return 1;
                    479:         } else {
                    480:             /* success */
                    481:             return 0;
                    482:         }
                    483:     } else {
                    484:         switch(ret) {
                    485:         default:
                    486:         case USB_RET_NODEV:
                    487:         do_timeout:
                    488:             td->ctrl |= TD_CTRL_TIMEOUT;
                    489:             err = (td->ctrl >> TD_CTRL_ERROR_SHIFT) & 3;
                    490:             if (err != 0) {
                    491:                 err--;
                    492:                 if (err == 0) {
                    493:                     td->ctrl &= ~TD_CTRL_ACTIVE;
                    494:                     s->status |= UHCI_STS_USBERR;
                    495:                     uhci_update_irq(s);
                    496:                 }
                    497:             }
                    498:             td->ctrl = (td->ctrl & ~(3 << TD_CTRL_ERROR_SHIFT)) | 
                    499:                 (err << TD_CTRL_ERROR_SHIFT);
                    500:             return 1;
                    501:         case USB_RET_NAK:
                    502:             td->ctrl |= TD_CTRL_NAK;
                    503:             if (pid == USB_TOKEN_SETUP)
                    504:                 goto do_timeout;
                    505:             return 1;
                    506:         case USB_RET_STALL:
                    507:             td->ctrl |= TD_CTRL_STALL;
                    508:             td->ctrl &= ~TD_CTRL_ACTIVE;
                    509:             return 1;
                    510:         case USB_RET_BABBLE:
                    511:             td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL;
                    512:             td->ctrl &= ~TD_CTRL_ACTIVE;
                    513:             /* frame interrupted */
                    514:             return -1;
                    515:         }
                    516:     }
                    517: }
                    518: 
                    519: static void uhci_frame_timer(void *opaque)
                    520: {
                    521:     UHCIState *s = opaque;
                    522:     int64_t expire_time;
                    523:     uint32_t frame_addr, link, old_td_ctrl, val;
                    524:     int int_mask, cnt, ret;
                    525:     UHCI_TD td;
                    526:     UHCI_QH qh;
                    527: 
                    528:     if (!(s->cmd & UHCI_CMD_RS)) {
                    529:         qemu_del_timer(s->frame_timer);
                    530:         return;
                    531:     }
                    532:     frame_addr = s->fl_base_addr + ((s->frnum & 0x3ff) << 2);
                    533:     cpu_physical_memory_read(frame_addr, (uint8_t *)&link, 4);
                    534:     le32_to_cpus(&link);
                    535:     int_mask = 0;
                    536:     cnt = FRAME_MAX_LOOPS;
                    537:     while ((link & 1) == 0) {
                    538:         if (--cnt == 0)
                    539:             break;
                    540:         /* valid frame */
                    541:         if (link & 2) {
                    542:             /* QH */
                    543:             cpu_physical_memory_read(link & ~0xf, (uint8_t *)&qh, sizeof(qh));
                    544:             le32_to_cpus(&qh.link);
                    545:             le32_to_cpus(&qh.el_link);
                    546:         depth_first:
                    547:             if (qh.el_link & 1) {
                    548:                 /* no element : go to next entry */
                    549:                 link = qh.link;
                    550:             } else if (qh.el_link & 2) {
                    551:                 /* QH */
                    552:                 link = qh.el_link;
                    553:             } else {
                    554:                 /* TD */
                    555:                 if (--cnt == 0)
                    556:                     break;
                    557:                 cpu_physical_memory_read(qh.el_link & ~0xf, 
                    558:                                          (uint8_t *)&td, sizeof(td));
                    559:                 le32_to_cpus(&td.link);
                    560:                 le32_to_cpus(&td.ctrl);
                    561:                 le32_to_cpus(&td.token);
                    562:                 le32_to_cpus(&td.buffer);
                    563:                 old_td_ctrl = td.ctrl;
                    564:                 ret = uhci_handle_td(s, &td, &int_mask);
                    565:                 /* update the status bits of the TD */
                    566:                 if (old_td_ctrl != td.ctrl) {
                    567:                     val = cpu_to_le32(td.ctrl);
                    568:                     cpu_physical_memory_write((qh.el_link & ~0xf) + 4, 
                    569:                                               (const uint8_t *)&val, 
                    570:                                               sizeof(val));
                    571:                 }
                    572:                 if (ret < 0)
                    573:                     break; /* interrupted frame */
                    574:                 if (ret == 0) {
                    575:                     /* update qh element link */
                    576:                     qh.el_link = td.link;
                    577:                     val = cpu_to_le32(qh.el_link);
                    578:                     cpu_physical_memory_write((link & ~0xf) + 4, 
                    579:                                               (const uint8_t *)&val, 
                    580:                                               sizeof(val));
                    581:                     if (qh.el_link & 4) {
                    582:                         /* depth first */
                    583:                         goto depth_first;
                    584:                     }
                    585:                 }
                    586:                 /* go to next entry */
                    587:                 link = qh.link;
                    588:             }
                    589:         } else {
                    590:             /* TD */
                    591:             cpu_physical_memory_read(link & ~0xf, (uint8_t *)&td, sizeof(td));
                    592:             le32_to_cpus(&td.link);
                    593:             le32_to_cpus(&td.ctrl);
                    594:             le32_to_cpus(&td.token);
                    595:             le32_to_cpus(&td.buffer);
                    596:             old_td_ctrl = td.ctrl;
                    597:             ret = uhci_handle_td(s, &td, &int_mask);
                    598:             /* update the status bits of the TD */
                    599:             if (old_td_ctrl != td.ctrl) {
                    600:                 val = cpu_to_le32(td.ctrl);
                    601:                 cpu_physical_memory_write((link & ~0xf) + 4, 
                    602:                                           (const uint8_t *)&val, 
                    603:                                           sizeof(val));
                    604:             }
                    605:             if (ret < 0)
                    606:                 break; /* interrupted frame */
                    607:             link = td.link;
                    608:         }
                    609:     }
                    610:     s->frnum = (s->frnum + 1) & 0x7ff;
                    611:     if (int_mask) {
                    612:         s->status2 |= int_mask;
                    613:         s->status |= UHCI_STS_USBINT;
                    614:         uhci_update_irq(s);
                    615:     }
                    616:     /* prepare the timer for the next frame */
                    617:     expire_time = qemu_get_clock(vm_clock) + 
                    618:         (ticks_per_sec / FRAME_TIMER_FREQ);
                    619:     qemu_mod_timer(s->frame_timer, expire_time);
                    620: }
                    621: 
                    622: static void uhci_map(PCIDevice *pci_dev, int region_num, 
                    623:                     uint32_t addr, uint32_t size, int type)
                    624: {
                    625:     UHCIState *s = (UHCIState *)pci_dev;
                    626: 
                    627:     register_ioport_write(addr, 32, 2, uhci_ioport_writew, s);
                    628:     register_ioport_read(addr, 32, 2, uhci_ioport_readw, s);
                    629:     register_ioport_write(addr, 32, 4, uhci_ioport_writel, s);
                    630:     register_ioport_read(addr, 32, 4, uhci_ioport_readl, s);
                    631:     register_ioport_write(addr, 32, 1, uhci_ioport_writeb, s);
                    632:     register_ioport_read(addr, 32, 1, uhci_ioport_readb, s);
                    633: }
                    634: 
                    635: void usb_uhci_init(PCIBus *bus, USBPort **usb_ports)
                    636: {
                    637:     UHCIState *s;
                    638:     uint8_t *pci_conf;
                    639:     UHCIPort *port;
                    640:     int i;
                    641: 
                    642:     s = (UHCIState *)pci_register_device(bus,
                    643:                                         "USB-UHCI", sizeof(UHCIState),
                    644:                                         ((PCIDevice *)piix3_state)->devfn + 2, 
                    645:                                         NULL, NULL);
                    646:     pci_conf = s->dev.config;
                    647:     pci_conf[0x00] = 0x86;
                    648:     pci_conf[0x01] = 0x80;
                    649:     pci_conf[0x02] = 0x20;
                    650:     pci_conf[0x03] = 0x70;
                    651:     pci_conf[0x08] = 0x01; // revision number
                    652:     pci_conf[0x09] = 0x00;
                    653:     pci_conf[0x0a] = 0x03;
                    654:     pci_conf[0x0b] = 0x0c;
                    655:     pci_conf[0x0e] = 0x00; // header_type
                    656:     pci_conf[0x3d] = 4; // interrupt pin 3
                    657:     
                    658:     for(i = 0; i < NB_PORTS; i++) {
                    659:         port = &s->ports[i];
                    660:         port->port.opaque = s;
                    661:         port->port.index = i;
                    662:         port->port.attach = uhci_attach;
                    663:         usb_ports[i] = &port->port;
                    664:     }
                    665:     s->frame_timer = qemu_new_timer(vm_clock, uhci_frame_timer, s);
                    666: 
                    667:     uhci_reset(s);
                    668: 
                    669:     pci_register_io_region(&s->dev, 0, 0x20, 
                    670:                            PCI_ADDRESS_SPACE_IO, uhci_map);
                    671: }

unix.superglobalmegacorp.com

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