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

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];
1.1.1.4 ! root       79: 
        !            80:     /* Interrupts that should be raised at the end of the current frame.  */
        !            81:     uint32_t pending_int_mask;
        !            82:     /* For simplicity of implementation we only allow a single pending USB
        !            83:        request.  This means all usb traffic on this controller is effectively
        !            84:        suspended until that transfer completes.  When the transfer completes
        !            85:        the next transfer from that queue will be processed.  However 
        !            86:        other queues will not be processed until the next frame.  The solution
        !            87:        is to allow multiple pending requests.  */
        !            88:     uint32_t async_qh;
        !            89:     USBPacket usb_packet;
        !            90:     uint8_t usb_buf[2048];
1.1       root       91: } UHCIState;
                     92: 
                     93: typedef struct UHCI_TD {
                     94:     uint32_t link;
                     95:     uint32_t ctrl; /* see TD_CTRL_xxx */
                     96:     uint32_t token;
                     97:     uint32_t buffer;
                     98: } UHCI_TD;
                     99: 
                    100: typedef struct UHCI_QH {
                    101:     uint32_t link;
                    102:     uint32_t el_link;
                    103: } UHCI_QH;
                    104: 
                    105: static void uhci_attach(USBPort *port1, USBDevice *dev);
                    106: 
                    107: static void uhci_update_irq(UHCIState *s)
                    108: {
                    109:     int level;
                    110:     if (((s->status2 & 1) && (s->intr & (1 << 2))) ||
                    111:         ((s->status2 & 2) && (s->intr & (1 << 3))) ||
                    112:         ((s->status & UHCI_STS_USBERR) && (s->intr & (1 << 0))) ||
                    113:         ((s->status & UHCI_STS_RD) && (s->intr & (1 << 1))) ||
                    114:         (s->status & UHCI_STS_HSERR) ||
                    115:         (s->status & UHCI_STS_HCPERR)) {
                    116:         level = 1;
                    117:     } else {
                    118:         level = 0;
                    119:     }
                    120:     pci_set_irq(&s->dev, 3, level);
                    121: }
                    122: 
                    123: static void uhci_reset(UHCIState *s)
                    124: {
                    125:     uint8_t *pci_conf;
                    126:     int i;
                    127:     UHCIPort *port;
                    128: 
                    129:     pci_conf = s->dev.config;
                    130: 
                    131:     pci_conf[0x6a] = 0x01; /* usb clock */
                    132:     pci_conf[0x6b] = 0x00;
                    133:     s->cmd = 0;
                    134:     s->status = 0;
                    135:     s->status2 = 0;
                    136:     s->intr = 0;
                    137:     s->fl_base_addr = 0;
                    138:     s->sof_timing = 64;
                    139:     for(i = 0; i < NB_PORTS; i++) {
                    140:         port = &s->ports[i];
                    141:         port->ctrl = 0x0080;
                    142:         if (port->port.dev)
                    143:             uhci_attach(&port->port, port->port.dev);
                    144:     }
                    145: }
                    146: 
                    147: static void uhci_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
                    148: {
                    149:     UHCIState *s = opaque;
                    150:     
                    151:     addr &= 0x1f;
                    152:     switch(addr) {
                    153:     case 0x0c:
                    154:         s->sof_timing = val;
                    155:         break;
                    156:     }
                    157: }
                    158: 
                    159: static uint32_t uhci_ioport_readb(void *opaque, uint32_t addr)
                    160: {
                    161:     UHCIState *s = opaque;
                    162:     uint32_t val;
                    163: 
                    164:     addr &= 0x1f;
                    165:     switch(addr) {
                    166:     case 0x0c:
                    167:         val = s->sof_timing;
1.1.1.2   root      168:         break;
1.1       root      169:     default:
                    170:         val = 0xff;
                    171:         break;
                    172:     }
                    173:     return val;
                    174: }
                    175: 
                    176: static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
                    177: {
                    178:     UHCIState *s = opaque;
                    179:     
                    180:     addr &= 0x1f;
                    181: #ifdef DEBUG
                    182:     printf("uhci writew port=0x%04x val=0x%04x\n", addr, val);
                    183: #endif
                    184:     switch(addr) {
                    185:     case 0x00:
                    186:         if ((val & UHCI_CMD_RS) && !(s->cmd & UHCI_CMD_RS)) {
                    187:             /* start frame processing */
                    188:             qemu_mod_timer(s->frame_timer, qemu_get_clock(vm_clock));
1.1.1.2   root      189:             s->status &= ~UHCI_STS_HCHALTED;
                    190:         } else if (!(val & UHCI_CMD_RS)) {
                    191:             s->status |= UHCI_STS_HCHALTED;
1.1       root      192:         }
                    193:         if (val & UHCI_CMD_GRESET) {
                    194:             UHCIPort *port;
                    195:             USBDevice *dev;
                    196:             int i;
                    197: 
                    198:             /* send reset on the USB bus */
                    199:             for(i = 0; i < NB_PORTS; i++) {
                    200:                 port = &s->ports[i];
                    201:                 dev = port->port.dev;
                    202:                 if (dev) {
1.1.1.4 ! root      203:                     usb_send_msg(dev, USB_MSG_RESET);
1.1       root      204:                 }
                    205:             }
                    206:             uhci_reset(s);
                    207:             return;
                    208:         }
                    209:         if (val & UHCI_CMD_HCRESET) {
                    210:             uhci_reset(s);
                    211:             return;
                    212:         }
                    213:         s->cmd = val;
                    214:         break;
                    215:     case 0x02:
                    216:         s->status &= ~val;
                    217:         /* XXX: the chip spec is not coherent, so we add a hidden
                    218:            register to distinguish between IOC and SPD */
                    219:         if (val & UHCI_STS_USBINT)
                    220:             s->status2 = 0;
                    221:         uhci_update_irq(s);
                    222:         break;
                    223:     case 0x04:
                    224:         s->intr = val;
                    225:         uhci_update_irq(s);
                    226:         break;
                    227:     case 0x06:
                    228:         if (s->status & UHCI_STS_HCHALTED)
                    229:             s->frnum = val & 0x7ff;
                    230:         break;
                    231:     case 0x10 ... 0x1f:
                    232:         {
                    233:             UHCIPort *port;
                    234:             USBDevice *dev;
                    235:             int n;
                    236: 
                    237:             n = (addr >> 1) & 7;
                    238:             if (n >= NB_PORTS)
                    239:                 return;
                    240:             port = &s->ports[n];
                    241:             dev = port->port.dev;
                    242:             if (dev) {
                    243:                 /* port reset */
                    244:                 if ( (val & UHCI_PORT_RESET) && 
                    245:                      !(port->ctrl & UHCI_PORT_RESET) ) {
1.1.1.4 ! root      246:                     usb_send_msg(dev, USB_MSG_RESET);
1.1       root      247:                 }
                    248:             }
                    249:             port->ctrl = (port->ctrl & 0x01fb) | (val & ~0x01fb);
                    250:             /* some bits are reset when a '1' is written to them */
                    251:             port->ctrl &= ~(val & 0x000a);
                    252:         }
                    253:         break;
                    254:     }
                    255: }
                    256: 
                    257: static uint32_t uhci_ioport_readw(void *opaque, uint32_t addr)
                    258: {
                    259:     UHCIState *s = opaque;
                    260:     uint32_t val;
                    261: 
                    262:     addr &= 0x1f;
                    263:     switch(addr) {
                    264:     case 0x00:
                    265:         val = s->cmd;
                    266:         break;
                    267:     case 0x02:
                    268:         val = s->status;
                    269:         break;
                    270:     case 0x04:
                    271:         val = s->intr;
                    272:         break;
                    273:     case 0x06:
                    274:         val = s->frnum;
                    275:         break;
                    276:     case 0x10 ... 0x1f:
                    277:         {
                    278:             UHCIPort *port;
                    279:             int n;
                    280:             n = (addr >> 1) & 7;
                    281:             if (n >= NB_PORTS) 
                    282:                 goto read_default;
                    283:             port = &s->ports[n];
                    284:             val = port->ctrl;
                    285:         }
                    286:         break;
                    287:     default:
                    288:     read_default:
                    289:         val = 0xff7f; /* disabled port */
                    290:         break;
                    291:     }
                    292: #ifdef DEBUG
                    293:     printf("uhci readw port=0x%04x val=0x%04x\n", addr, val);
                    294: #endif
                    295:     return val;
                    296: }
                    297: 
                    298: static void uhci_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
                    299: {
                    300:     UHCIState *s = opaque;
                    301: 
                    302:     addr &= 0x1f;
                    303: #ifdef DEBUG
                    304:     printf("uhci writel port=0x%04x val=0x%08x\n", addr, val);
                    305: #endif
                    306:     switch(addr) {
                    307:     case 0x08:
                    308:         s->fl_base_addr = val & ~0xfff;
                    309:         break;
                    310:     }
                    311: }
                    312: 
                    313: static uint32_t uhci_ioport_readl(void *opaque, uint32_t addr)
                    314: {
                    315:     UHCIState *s = opaque;
                    316:     uint32_t val;
                    317: 
                    318:     addr &= 0x1f;
                    319:     switch(addr) {
                    320:     case 0x08:
                    321:         val = s->fl_base_addr;
                    322:         break;
                    323:     default:
                    324:         val = 0xffffffff;
                    325:         break;
                    326:     }
                    327:     return val;
                    328: }
                    329: 
                    330: static void uhci_attach(USBPort *port1, USBDevice *dev)
                    331: {
                    332:     UHCIState *s = port1->opaque;
                    333:     UHCIPort *port = &s->ports[port1->index];
                    334: 
                    335:     if (dev) {
                    336:         if (port->port.dev) {
                    337:             usb_attach(port1, NULL);
                    338:         }
                    339:         /* set connect status */
1.1.1.3   root      340:         port->ctrl |= UHCI_PORT_CCS | UHCI_PORT_CSC;
                    341: 
1.1       root      342:         /* update speed */
                    343:         if (dev->speed == USB_SPEED_LOW)
                    344:             port->ctrl |= UHCI_PORT_LSDA;
                    345:         else
                    346:             port->ctrl &= ~UHCI_PORT_LSDA;
                    347:         port->port.dev = dev;
                    348:         /* send the attach message */
1.1.1.4 ! root      349:         usb_send_msg(dev, USB_MSG_ATTACH);
1.1       root      350:     } else {
                    351:         /* set connect status */
1.1.1.3   root      352:         if (port->ctrl & UHCI_PORT_CCS) {
                    353:             port->ctrl &= ~UHCI_PORT_CCS;
                    354:             port->ctrl |= UHCI_PORT_CSC;
1.1       root      355:         }
                    356:         /* disable port */
                    357:         if (port->ctrl & UHCI_PORT_EN) {
                    358:             port->ctrl &= ~UHCI_PORT_EN;
                    359:             port->ctrl |= UHCI_PORT_ENC;
                    360:         }
                    361:         dev = port->port.dev;
                    362:         if (dev) {
                    363:             /* send the detach message */
1.1.1.4 ! root      364:             usb_send_msg(dev, USB_MSG_DETACH);
1.1       root      365:         }
                    366:         port->port.dev = NULL;
                    367:     }
                    368: }
                    369: 
1.1.1.4 ! root      370: static int uhci_broadcast_packet(UHCIState *s, USBPacket *p)
1.1       root      371: {
                    372:     UHCIPort *port;
                    373:     USBDevice *dev;
                    374:     int i, ret;
                    375: 
                    376: #ifdef DEBUG_PACKET
                    377:     {
                    378:         const char *pidstr;
1.1.1.4 ! root      379:         switch(p->pid) {
1.1       root      380:         case USB_TOKEN_SETUP: pidstr = "SETUP"; break;
                    381:         case USB_TOKEN_IN: pidstr = "IN"; break;
                    382:         case USB_TOKEN_OUT: pidstr = "OUT"; break;
                    383:         default: pidstr = "?"; break;
                    384:         }
                    385:         printf("frame %d: pid=%s addr=0x%02x ep=%d len=%d\n",
1.1.1.4 ! root      386:                s->frnum, pidstr, p->devaddr, p->devep, p->len);
        !           387:         if (p->pid != USB_TOKEN_IN) {
1.1       root      388:             printf("     data_out=");
1.1.1.4 ! root      389:             for(i = 0; i < p->len; i++) {
        !           390:                 printf(" %02x", p->data[i]);
1.1       root      391:             }
                    392:             printf("\n");
                    393:         }
                    394:     }
                    395: #endif
                    396:     for(i = 0; i < NB_PORTS; i++) {
                    397:         port = &s->ports[i];
                    398:         dev = port->port.dev;
                    399:         if (dev && (port->ctrl & UHCI_PORT_EN)) {
1.1.1.4 ! root      400:             ret = dev->handle_packet(dev, p);
1.1       root      401:             if (ret != USB_RET_NODEV) {
                    402: #ifdef DEBUG_PACKET
1.1.1.4 ! root      403:                 if (ret == USB_RET_ASYNC) {
        !           404:                     printf("usb-uhci: Async packet\n");
        !           405:                 } else {
1.1       root      406:                     printf("     ret=%d ", ret);
1.1.1.4 ! root      407:                     if (p->pid == USB_TOKEN_IN && ret > 0) {
1.1       root      408:                         printf("data_in=");
                    409:                         for(i = 0; i < ret; i++) {
1.1.1.4 ! root      410:                             printf(" %02x", p->data[i]);
1.1       root      411:                         }
                    412:                     }
                    413:                     printf("\n");
                    414:                 }
                    415: #endif
                    416:                 return ret;
                    417:             }
                    418:         }
                    419:     }
                    420:     return USB_RET_NODEV;
                    421: }
                    422: 
1.1.1.4 ! root      423: static void uhci_async_complete_packet(USBPacket * packet, void *opaque);
        !           424: 
1.1       root      425: /* return -1 if fatal error (frame must be stopped)
                    426:           0 if TD successful
                    427:           1 if TD unsuccessful or inactive
                    428: */
                    429: static int uhci_handle_td(UHCIState *s, UHCI_TD *td, int *int_mask)
                    430: {
                    431:     uint8_t pid;
                    432:     int len, max_len, err, ret;
                    433: 
1.1.1.4 ! root      434:     /* ??? This is wrong for async completion.  */
1.1       root      435:     if (td->ctrl & TD_CTRL_IOC) {
                    436:         *int_mask |= 0x01;
                    437:     }
                    438:     
                    439:     if (!(td->ctrl & TD_CTRL_ACTIVE))
                    440:         return 1;
                    441: 
                    442:     /* TD is active */
                    443:     max_len = ((td->token >> 21) + 1) & 0x7ff;
                    444:     pid = td->token & 0xff;
1.1.1.4 ! root      445:     if (s->async_qh) {
        !           446:         ret = s->usb_packet.len;
1.1       root      447:         if (ret >= 0) {
                    448:             len = ret;
                    449:             if (len > max_len) {
                    450:                 len = max_len;
                    451:                 ret = USB_RET_BABBLE;
                    452:             }
                    453:             if (len > 0) {
                    454:                 /* write the data back */
1.1.1.4 ! root      455:                 cpu_physical_memory_write(td->buffer, s->usb_buf, len);
1.1       root      456:             }
                    457:         } else {
                    458:             len = 0;
                    459:         }
1.1.1.4 ! root      460:         s->async_qh = 0;
        !           461:     } else {
        !           462:         s->usb_packet.pid = pid;
        !           463:         s->usb_packet.devaddr = (td->token >> 8) & 0x7f;
        !           464:         s->usb_packet.devep = (td->token >> 15) & 0xf;
        !           465:         s->usb_packet.data = s->usb_buf;
        !           466:         s->usb_packet.len = max_len;
        !           467:         s->usb_packet.complete_cb = uhci_async_complete_packet;
        !           468:         s->usb_packet.complete_opaque = s;
        !           469:         switch(pid) {
        !           470:         case USB_TOKEN_OUT:
        !           471:         case USB_TOKEN_SETUP:
        !           472:             cpu_physical_memory_read(td->buffer, s->usb_buf, max_len);
        !           473:             ret = uhci_broadcast_packet(s, &s->usb_packet);
        !           474:             len = max_len;
        !           475:             break;
        !           476:         case USB_TOKEN_IN:
        !           477:             ret = uhci_broadcast_packet(s, &s->usb_packet);
        !           478:             if (ret >= 0) {
        !           479:                 len = ret;
        !           480:                 if (len > max_len) {
        !           481:                     len = max_len;
        !           482:                     ret = USB_RET_BABBLE;
        !           483:                 }
        !           484:                 if (len > 0) {
        !           485:                     /* write the data back */
        !           486:                     cpu_physical_memory_write(td->buffer, s->usb_buf, len);
        !           487:                 }
        !           488:             } else {
        !           489:                 len = 0;
        !           490:             }
        !           491:             break;
        !           492:         default:
        !           493:             /* invalid pid : frame interrupted */
        !           494:             s->status |= UHCI_STS_HCPERR;
        !           495:             uhci_update_irq(s);
        !           496:             return -1;
        !           497:         }
        !           498:     }
        !           499:     if (ret == USB_RET_ASYNC) {
        !           500:         return 2;
1.1       root      501:     }
                    502:     if (td->ctrl & TD_CTRL_IOS)
                    503:         td->ctrl &= ~TD_CTRL_ACTIVE;
                    504:     if (ret >= 0) {
                    505:         td->ctrl = (td->ctrl & ~0x7ff) | ((len - 1) & 0x7ff);
                    506:         td->ctrl &= ~TD_CTRL_ACTIVE;
                    507:         if (pid == USB_TOKEN_IN && 
                    508:             (td->ctrl & TD_CTRL_SPD) &&
                    509:             len < max_len) {
                    510:             *int_mask |= 0x02;
                    511:             /* short packet: do not update QH */
                    512:             return 1;
                    513:         } else {
                    514:             /* success */
                    515:             return 0;
                    516:         }
                    517:     } else {
                    518:         switch(ret) {
                    519:         default:
                    520:         case USB_RET_NODEV:
                    521:         do_timeout:
                    522:             td->ctrl |= TD_CTRL_TIMEOUT;
                    523:             err = (td->ctrl >> TD_CTRL_ERROR_SHIFT) & 3;
                    524:             if (err != 0) {
                    525:                 err--;
                    526:                 if (err == 0) {
                    527:                     td->ctrl &= ~TD_CTRL_ACTIVE;
                    528:                     s->status |= UHCI_STS_USBERR;
                    529:                     uhci_update_irq(s);
                    530:                 }
                    531:             }
                    532:             td->ctrl = (td->ctrl & ~(3 << TD_CTRL_ERROR_SHIFT)) | 
                    533:                 (err << TD_CTRL_ERROR_SHIFT);
                    534:             return 1;
                    535:         case USB_RET_NAK:
                    536:             td->ctrl |= TD_CTRL_NAK;
                    537:             if (pid == USB_TOKEN_SETUP)
                    538:                 goto do_timeout;
                    539:             return 1;
                    540:         case USB_RET_STALL:
                    541:             td->ctrl |= TD_CTRL_STALL;
                    542:             td->ctrl &= ~TD_CTRL_ACTIVE;
                    543:             return 1;
                    544:         case USB_RET_BABBLE:
                    545:             td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL;
                    546:             td->ctrl &= ~TD_CTRL_ACTIVE;
                    547:             /* frame interrupted */
                    548:             return -1;
                    549:         }
                    550:     }
                    551: }
                    552: 
1.1.1.4 ! root      553: static void uhci_async_complete_packet(USBPacket * packet, void *opaque)
        !           554: {
        !           555:     UHCIState *s = opaque;
        !           556:     UHCI_QH qh;
        !           557:     UHCI_TD td;
        !           558:     uint32_t link;
        !           559:     uint32_t old_td_ctrl;
        !           560:     uint32_t val;
        !           561:     int ret;
        !           562: 
        !           563:     link = s->async_qh;
        !           564:     if (!link) {
        !           565:         /* This should never happen. It means a TD somehow got removed
        !           566:            without cancelling the associated async IO request.  */
        !           567:         return;
        !           568:     }
        !           569:     cpu_physical_memory_read(link & ~0xf, (uint8_t *)&qh, sizeof(qh));
        !           570:     le32_to_cpus(&qh.link);
        !           571:     le32_to_cpus(&qh.el_link);
        !           572:     /* Re-process the queue containing the async packet.  */
        !           573:     while (1) {
        !           574:         cpu_physical_memory_read(qh.el_link & ~0xf, 
        !           575:                                  (uint8_t *)&td, sizeof(td));
        !           576:         le32_to_cpus(&td.link);
        !           577:         le32_to_cpus(&td.ctrl);
        !           578:         le32_to_cpus(&td.token);
        !           579:         le32_to_cpus(&td.buffer);
        !           580:         old_td_ctrl = td.ctrl;
        !           581:         ret = uhci_handle_td(s, &td, &s->pending_int_mask);
        !           582:         /* update the status bits of the TD */
        !           583:         if (old_td_ctrl != td.ctrl) {
        !           584:             val = cpu_to_le32(td.ctrl);
        !           585:             cpu_physical_memory_write((qh.el_link & ~0xf) + 4, 
        !           586:                                       (const uint8_t *)&val, 
        !           587:                                       sizeof(val));
        !           588:         }
        !           589:         if (ret < 0)
        !           590:             break; /* interrupted frame */
        !           591:         if (ret == 2) {
        !           592:             s->async_qh = link;
        !           593:             break;
        !           594:         } else if (ret == 0) {
        !           595:             /* update qh element link */
        !           596:             qh.el_link = td.link;
        !           597:             val = cpu_to_le32(qh.el_link);
        !           598:             cpu_physical_memory_write((link & ~0xf) + 4, 
        !           599:                                       (const uint8_t *)&val, 
        !           600:                                       sizeof(val));
        !           601:             if (!(qh.el_link & 4))
        !           602:                 break;
        !           603:         }
        !           604:         break;
        !           605:     }
        !           606: }
        !           607: 
1.1       root      608: static void uhci_frame_timer(void *opaque)
                    609: {
                    610:     UHCIState *s = opaque;
                    611:     int64_t expire_time;
                    612:     uint32_t frame_addr, link, old_td_ctrl, val;
                    613:     int int_mask, cnt, ret;
                    614:     UHCI_TD td;
                    615:     UHCI_QH qh;
1.1.1.4 ! root      616:     uint32_t old_async_qh;
1.1       root      617: 
                    618:     if (!(s->cmd & UHCI_CMD_RS)) {
                    619:         qemu_del_timer(s->frame_timer);
1.1.1.2   root      620:         /* set hchalted bit in status - UHCI11D 2.1.2 */
                    621:         s->status |= UHCI_STS_HCHALTED;
1.1       root      622:         return;
                    623:     }
1.1.1.4 ! root      624:     /* Complete the previous frame.  */
        !           625:     s->frnum = (s->frnum + 1) & 0x7ff;
        !           626:     if (s->pending_int_mask) {
        !           627:         s->status2 |= s->pending_int_mask;
        !           628:         s->status |= UHCI_STS_USBINT;
        !           629:         uhci_update_irq(s);
        !           630:     }
        !           631:     old_async_qh = s->async_qh;
1.1       root      632:     frame_addr = s->fl_base_addr + ((s->frnum & 0x3ff) << 2);
                    633:     cpu_physical_memory_read(frame_addr, (uint8_t *)&link, 4);
                    634:     le32_to_cpus(&link);
                    635:     int_mask = 0;
                    636:     cnt = FRAME_MAX_LOOPS;
                    637:     while ((link & 1) == 0) {
                    638:         if (--cnt == 0)
                    639:             break;
                    640:         /* valid frame */
                    641:         if (link & 2) {
                    642:             /* QH */
1.1.1.4 ! root      643:             if (link == s->async_qh) {
        !           644:                 /* We've found a previously issues packet.
        !           645:                    Nothing else to do.  */
        !           646:                 old_async_qh = 0;
        !           647:                 break;
        !           648:             }
1.1       root      649:             cpu_physical_memory_read(link & ~0xf, (uint8_t *)&qh, sizeof(qh));
                    650:             le32_to_cpus(&qh.link);
                    651:             le32_to_cpus(&qh.el_link);
                    652:         depth_first:
                    653:             if (qh.el_link & 1) {
                    654:                 /* no element : go to next entry */
                    655:                 link = qh.link;
                    656:             } else if (qh.el_link & 2) {
                    657:                 /* QH */
                    658:                 link = qh.el_link;
1.1.1.4 ! root      659:             } else if (s->async_qh) {
        !           660:                 /* We can only cope with one pending packet.  Keep looking
        !           661:                    for the previously issued packet.  */
        !           662:                 link = qh.link;
1.1       root      663:             } else {
                    664:                 /* TD */
                    665:                 if (--cnt == 0)
                    666:                     break;
                    667:                 cpu_physical_memory_read(qh.el_link & ~0xf, 
                    668:                                          (uint8_t *)&td, sizeof(td));
                    669:                 le32_to_cpus(&td.link);
                    670:                 le32_to_cpus(&td.ctrl);
                    671:                 le32_to_cpus(&td.token);
                    672:                 le32_to_cpus(&td.buffer);
                    673:                 old_td_ctrl = td.ctrl;
                    674:                 ret = uhci_handle_td(s, &td, &int_mask);
                    675:                 /* update the status bits of the TD */
                    676:                 if (old_td_ctrl != td.ctrl) {
                    677:                     val = cpu_to_le32(td.ctrl);
                    678:                     cpu_physical_memory_write((qh.el_link & ~0xf) + 4, 
                    679:                                               (const uint8_t *)&val, 
                    680:                                               sizeof(val));
                    681:                 }
                    682:                 if (ret < 0)
                    683:                     break; /* interrupted frame */
1.1.1.4 ! root      684:                 if (ret == 2) {
        !           685:                     s->async_qh = link;
        !           686:                 } else if (ret == 0) {
1.1       root      687:                     /* update qh element link */
                    688:                     qh.el_link = td.link;
                    689:                     val = cpu_to_le32(qh.el_link);
                    690:                     cpu_physical_memory_write((link & ~0xf) + 4, 
                    691:                                               (const uint8_t *)&val, 
                    692:                                               sizeof(val));
                    693:                     if (qh.el_link & 4) {
                    694:                         /* depth first */
                    695:                         goto depth_first;
                    696:                     }
                    697:                 }
                    698:                 /* go to next entry */
                    699:                 link = qh.link;
                    700:             }
                    701:         } else {
                    702:             /* TD */
                    703:             cpu_physical_memory_read(link & ~0xf, (uint8_t *)&td, sizeof(td));
                    704:             le32_to_cpus(&td.link);
                    705:             le32_to_cpus(&td.ctrl);
                    706:             le32_to_cpus(&td.token);
                    707:             le32_to_cpus(&td.buffer);
1.1.1.4 ! root      708:             /* Ignore isochonous transfers while there is an async packet
        !           709:                pending.  This is wrong, but we don't implement isochronous
        !           710:                transfers anyway.  */
        !           711:             if (s->async_qh == 0) {
        !           712:                 old_td_ctrl = td.ctrl;
        !           713:                 ret = uhci_handle_td(s, &td, &int_mask);
        !           714:                 /* update the status bits of the TD */
        !           715:                 if (old_td_ctrl != td.ctrl) {
        !           716:                     val = cpu_to_le32(td.ctrl);
        !           717:                     cpu_physical_memory_write((link & ~0xf) + 4, 
        !           718:                                               (const uint8_t *)&val, 
        !           719:                                               sizeof(val));
        !           720:                 }
        !           721:                 if (ret < 0)
        !           722:                     break; /* interrupted frame */
        !           723:                 if (ret == 2) {
        !           724:                     /* We can't handle async isochronous transfers.
        !           725:                        Cancel The packet.  */
        !           726:                     fprintf(stderr, "usb-uhci: Unimplemented async packet\n");
        !           727:                     usb_cancel_packet(&s->usb_packet);
        !           728:                 }
1.1       root      729:             }
                    730:             link = td.link;
                    731:         }
                    732:     }
1.1.1.4 ! root      733:     s->pending_int_mask = int_mask;
        !           734:     if (old_async_qh) {
        !           735:         /* A previously started transfer has disappeared from the transfer
        !           736:            list.  There's nothing useful we can do with it now, so just
        !           737:            discard the packet and hope it wasn't too important.  */
        !           738: #ifdef DEBUG
        !           739:         printf("Discarding USB packet\n");
        !           740: #endif
        !           741:         usb_cancel_packet(&s->usb_packet);
        !           742:         s->async_qh = 0;
1.1       root      743:     }
                    744:     /* prepare the timer for the next frame */
                    745:     expire_time = qemu_get_clock(vm_clock) + 
                    746:         (ticks_per_sec / FRAME_TIMER_FREQ);
                    747:     qemu_mod_timer(s->frame_timer, expire_time);
                    748: }
                    749: 
                    750: static void uhci_map(PCIDevice *pci_dev, int region_num, 
                    751:                     uint32_t addr, uint32_t size, int type)
                    752: {
                    753:     UHCIState *s = (UHCIState *)pci_dev;
                    754: 
                    755:     register_ioport_write(addr, 32, 2, uhci_ioport_writew, s);
                    756:     register_ioport_read(addr, 32, 2, uhci_ioport_readw, s);
                    757:     register_ioport_write(addr, 32, 4, uhci_ioport_writel, s);
                    758:     register_ioport_read(addr, 32, 4, uhci_ioport_readl, s);
                    759:     register_ioport_write(addr, 32, 1, uhci_ioport_writeb, s);
                    760:     register_ioport_read(addr, 32, 1, uhci_ioport_readb, s);
                    761: }
                    762: 
1.1.1.3   root      763: void usb_uhci_init(PCIBus *bus, int devfn)
1.1       root      764: {
                    765:     UHCIState *s;
                    766:     uint8_t *pci_conf;
                    767:     int i;
                    768: 
                    769:     s = (UHCIState *)pci_register_device(bus,
                    770:                                         "USB-UHCI", sizeof(UHCIState),
1.1.1.3   root      771:                                         devfn, NULL, NULL);
1.1       root      772:     pci_conf = s->dev.config;
                    773:     pci_conf[0x00] = 0x86;
                    774:     pci_conf[0x01] = 0x80;
                    775:     pci_conf[0x02] = 0x20;
                    776:     pci_conf[0x03] = 0x70;
                    777:     pci_conf[0x08] = 0x01; // revision number
                    778:     pci_conf[0x09] = 0x00;
                    779:     pci_conf[0x0a] = 0x03;
                    780:     pci_conf[0x0b] = 0x0c;
                    781:     pci_conf[0x0e] = 0x00; // header_type
                    782:     pci_conf[0x3d] = 4; // interrupt pin 3
1.1.1.2   root      783:     pci_conf[0x60] = 0x10; // release number
1.1       root      784:     
                    785:     for(i = 0; i < NB_PORTS; i++) {
1.1.1.3   root      786:         qemu_register_usb_port(&s->ports[i].port, s, i, uhci_attach);
1.1       root      787:     }
                    788:     s->frame_timer = qemu_new_timer(vm_clock, uhci_frame_timer, s);
                    789: 
                    790:     uhci_reset(s);
                    791: 
1.1.1.2   root      792:     /* Use region 4 for consistency with real hardware.  BSD guests seem
                    793:        to rely on this.  */
                    794:     pci_register_io_region(&s->dev, 4, 0x20, 
1.1       root      795:                            PCI_ADDRESS_SPACE_IO, uhci_map);
                    796: }

unix.superglobalmegacorp.com

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