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

1.1       root        1: /*
                      2:  * USB UHCI controller emulation
1.1.1.5   root        3:  *
1.1       root        4:  * Copyright (c) 2005 Fabrice Bellard
1.1.1.5   root        5:  *
1.1.1.6   root        6:  * Copyright (c) 2008 Max Krasnyansky
                      7:  *     Magor rewrite of the UHCI data structures parser and frame processor
                      8:  *     Support for fully async operation and multiple outstanding transactions
                      9:  *
1.1       root       10:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                     11:  * of this software and associated documentation files (the "Software"), to deal
                     12:  * in the Software without restriction, including without limitation the rights
                     13:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     14:  * copies of the Software, and to permit persons to whom the Software is
                     15:  * furnished to do so, subject to the following conditions:
                     16:  *
                     17:  * The above copyright notice and this permission notice shall be included in
                     18:  * all copies or substantial portions of the Software.
                     19:  *
                     20:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     21:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     22:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
                     23:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     24:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     25:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     26:  * THE SOFTWARE.
                     27:  */
1.1.1.5   root       28: #include "hw.h"
                     29: #include "usb.h"
                     30: #include "pci.h"
                     31: #include "qemu-timer.h"
1.1.1.8 ! root       32: #include "usb-uhci.h"
1.1       root       33: 
                     34: //#define DEBUG
1.1.1.6   root       35: //#define DEBUG_DUMP_DATA
1.1       root       36: 
1.1.1.5   root       37: #define UHCI_CMD_FGR      (1 << 4)
                     38: #define UHCI_CMD_EGSM     (1 << 3)
1.1       root       39: #define UHCI_CMD_GRESET   (1 << 2)
                     40: #define UHCI_CMD_HCRESET  (1 << 1)
                     41: #define UHCI_CMD_RS       (1 << 0)
                     42: 
                     43: #define UHCI_STS_HCHALTED (1 << 5)
                     44: #define UHCI_STS_HCPERR   (1 << 4)
                     45: #define UHCI_STS_HSERR    (1 << 3)
                     46: #define UHCI_STS_RD       (1 << 2)
                     47: #define UHCI_STS_USBERR   (1 << 1)
                     48: #define UHCI_STS_USBINT   (1 << 0)
                     49: 
                     50: #define TD_CTRL_SPD     (1 << 29)
                     51: #define TD_CTRL_ERROR_SHIFT  27
                     52: #define TD_CTRL_IOS     (1 << 25)
                     53: #define TD_CTRL_IOC     (1 << 24)
                     54: #define TD_CTRL_ACTIVE  (1 << 23)
                     55: #define TD_CTRL_STALL   (1 << 22)
                     56: #define TD_CTRL_BABBLE  (1 << 20)
                     57: #define TD_CTRL_NAK     (1 << 19)
                     58: #define TD_CTRL_TIMEOUT (1 << 18)
                     59: 
                     60: #define UHCI_PORT_RESET (1 << 9)
                     61: #define UHCI_PORT_LSDA  (1 << 8)
                     62: #define UHCI_PORT_ENC   (1 << 3)
                     63: #define UHCI_PORT_EN    (1 << 2)
                     64: #define UHCI_PORT_CSC   (1 << 1)
                     65: #define UHCI_PORT_CCS   (1 << 0)
                     66: 
                     67: #define FRAME_TIMER_FREQ 1000
                     68: 
                     69: #define FRAME_MAX_LOOPS  100
                     70: 
                     71: #define NB_PORTS 2
                     72: 
1.1.1.6   root       73: #ifdef DEBUG
                     74: #define dprintf printf
                     75: 
1.1.1.7   root       76: static const char *pid2str(int pid)
1.1.1.6   root       77: {
                     78:     switch (pid) {
                     79:     case USB_TOKEN_SETUP: return "SETUP";
                     80:     case USB_TOKEN_IN:    return "IN";
                     81:     case USB_TOKEN_OUT:   return "OUT";
                     82:     }
                     83:     return "?";
                     84: }
                     85: 
                     86: #else
                     87: #define dprintf(...)
                     88: #endif
                     89: 
                     90: #ifdef DEBUG_DUMP_DATA
                     91: static void dump_data(const uint8_t *data, int len)
                     92: {
                     93:     int i;
                     94: 
                     95:     printf("uhci: data: ");
                     96:     for(i = 0; i < len; i++)
                     97:         printf(" %02x", data[i]);
                     98:     printf("\n");
                     99: }
                    100: #else
                    101: static void dump_data(const uint8_t *data, int len) {}
                    102: #endif
                    103: 
                    104: /* 
                    105:  * Pending async transaction.
                    106:  * 'packet' must be the first field because completion
                    107:  * handler does "(UHCIAsync *) pkt" cast.
                    108:  */
                    109: typedef struct UHCIAsync {
                    110:     USBPacket packet;
                    111:     struct UHCIAsync *next;
                    112:     uint32_t  td;
                    113:     uint32_t  token;
                    114:     int8_t    valid;
                    115:     uint8_t   done;
                    116:     uint8_t   buffer[2048];
                    117: } UHCIAsync;
                    118: 
1.1       root      119: typedef struct UHCIPort {
                    120:     USBPort port;
                    121:     uint16_t ctrl;
                    122: } UHCIPort;
                    123: 
                    124: typedef struct UHCIState {
                    125:     PCIDevice dev;
1.1.1.8 ! root      126:     USBBus bus;
1.1       root      127:     uint16_t cmd; /* cmd register */
                    128:     uint16_t status;
                    129:     uint16_t intr; /* interrupt enable register */
                    130:     uint16_t frnum; /* frame number */
                    131:     uint32_t fl_base_addr; /* frame list base address */
                    132:     uint8_t sof_timing;
                    133:     uint8_t status2; /* bit 0 and 1 are used to generate UHCI_STS_USBINT */
                    134:     QEMUTimer *frame_timer;
                    135:     UHCIPort ports[NB_PORTS];
1.1.1.4   root      136: 
                    137:     /* Interrupts that should be raised at the end of the current frame.  */
                    138:     uint32_t pending_int_mask;
1.1.1.6   root      139: 
                    140:     /* Active packets */
                    141:     UHCIAsync *async_pending;
                    142:     UHCIAsync *async_pool;
1.1.1.8 ! root      143:     uint8_t num_ports_vmstate;
1.1       root      144: } UHCIState;
                    145: 
                    146: typedef struct UHCI_TD {
                    147:     uint32_t link;
                    148:     uint32_t ctrl; /* see TD_CTRL_xxx */
                    149:     uint32_t token;
                    150:     uint32_t buffer;
                    151: } UHCI_TD;
                    152: 
                    153: typedef struct UHCI_QH {
                    154:     uint32_t link;
                    155:     uint32_t el_link;
                    156: } UHCI_QH;
                    157: 
1.1.1.6   root      158: static UHCIAsync *uhci_async_alloc(UHCIState *s)
                    159: {
                    160:     UHCIAsync *async = qemu_malloc(sizeof(UHCIAsync));
                    161: 
                    162:     memset(&async->packet, 0, sizeof(async->packet));
                    163:     async->valid = 0;
                    164:     async->td    = 0;
                    165:     async->token = 0;
                    166:     async->done  = 0;
                    167:     async->next  = NULL;
                    168: 
                    169:     return async;
                    170: }
                    171: 
                    172: static void uhci_async_free(UHCIState *s, UHCIAsync *async)
                    173: {
                    174:     qemu_free(async);
                    175: }
                    176: 
                    177: static void uhci_async_link(UHCIState *s, UHCIAsync *async)
                    178: {
                    179:     async->next = s->async_pending;
                    180:     s->async_pending = async;
                    181: }
                    182: 
                    183: static void uhci_async_unlink(UHCIState *s, UHCIAsync *async)
                    184: {
                    185:     UHCIAsync *curr = s->async_pending;
                    186:     UHCIAsync **prev = &s->async_pending;
                    187: 
                    188:     while (curr) {
                    189:        if (curr == async) {
                    190:             *prev = curr->next;
                    191:             return;
                    192:         }
                    193: 
                    194:         prev = &curr->next;
                    195:         curr = curr->next;
                    196:     }
                    197: }
                    198: 
                    199: static void uhci_async_cancel(UHCIState *s, UHCIAsync *async)
                    200: {
                    201:     dprintf("uhci: cancel td 0x%x token 0x%x done %u\n",
                    202:            async->td, async->token, async->done);
                    203: 
                    204:     if (!async->done)
                    205:         usb_cancel_packet(&async->packet);
                    206:     uhci_async_free(s, async);
                    207: }
                    208: 
                    209: /*
                    210:  * Mark all outstanding async packets as invalid.
                    211:  * This is used for canceling them when TDs are removed by the HCD.
                    212:  */
                    213: static UHCIAsync *uhci_async_validate_begin(UHCIState *s)
                    214: {
                    215:     UHCIAsync *async = s->async_pending;
                    216: 
                    217:     while (async) {
                    218:         async->valid--;
                    219:         async = async->next;
                    220:     }
                    221:     return NULL;
                    222: }
                    223: 
                    224: /*
                    225:  * Cancel async packets that are no longer valid
                    226:  */
                    227: static void uhci_async_validate_end(UHCIState *s)
                    228: {
                    229:     UHCIAsync *curr = s->async_pending;
                    230:     UHCIAsync **prev = &s->async_pending;
                    231:     UHCIAsync *next;
                    232: 
                    233:     while (curr) {
                    234:         if (curr->valid > 0) {
                    235:             prev = &curr->next;
                    236:             curr = curr->next;
                    237:             continue;
                    238:         }
                    239: 
                    240:         next = curr->next;
                    241: 
                    242:         /* Unlink */
                    243:         *prev = next;
                    244: 
                    245:         uhci_async_cancel(s, curr);
                    246: 
                    247:         curr = next;
                    248:     }
                    249: }
                    250: 
                    251: static void uhci_async_cancel_all(UHCIState *s)
                    252: {
                    253:     UHCIAsync *curr = s->async_pending;
                    254:     UHCIAsync *next;
                    255: 
                    256:     while (curr) {
                    257:         next = curr->next;
                    258: 
                    259:         uhci_async_cancel(s, curr);
                    260: 
                    261:         curr = next;
                    262:     }
                    263: 
                    264:     s->async_pending = NULL;
                    265: }
                    266: 
                    267: static UHCIAsync *uhci_async_find_td(UHCIState *s, uint32_t addr, uint32_t token)
                    268: {
                    269:     UHCIAsync *async = s->async_pending;
                    270:     UHCIAsync *match = NULL;
                    271:     int count = 0;
                    272: 
                    273:     /*
                    274:      * We're looking for the best match here. ie both td addr and token.
                    275:      * Otherwise we return last good match. ie just token.
                    276:      * It's ok to match just token because it identifies the transaction
                    277:      * rather well, token includes: device addr, endpoint, size, etc.
                    278:      *
                    279:      * Also since we queue async transactions in reverse order by returning
                    280:      * last good match we restores the order.
                    281:      *
                    282:      * It's expected that we wont have a ton of outstanding transactions.
                    283:      * If we ever do we'd want to optimize this algorithm.
                    284:      */
                    285: 
                    286:     while (async) {
                    287:         if (async->token == token) {
                    288:             /* Good match */
                    289:             match = async;
                    290: 
                    291:             if (async->td == addr) {
                    292:                 /* Best match */
                    293:                 break;
                    294:             }
                    295:         }
                    296: 
                    297:         async = async->next;
                    298:         count++;
                    299:     }
                    300: 
                    301:     if (count > 64)
                    302:        fprintf(stderr, "uhci: warning lots of async transactions\n");
                    303: 
                    304:     return match;
                    305: }
                    306: 
1.1       root      307: static void uhci_attach(USBPort *port1, USBDevice *dev);
                    308: 
                    309: static void uhci_update_irq(UHCIState *s)
                    310: {
                    311:     int level;
                    312:     if (((s->status2 & 1) && (s->intr & (1 << 2))) ||
                    313:         ((s->status2 & 2) && (s->intr & (1 << 3))) ||
                    314:         ((s->status & UHCI_STS_USBERR) && (s->intr & (1 << 0))) ||
                    315:         ((s->status & UHCI_STS_RD) && (s->intr & (1 << 1))) ||
                    316:         (s->status & UHCI_STS_HSERR) ||
                    317:         (s->status & UHCI_STS_HCPERR)) {
                    318:         level = 1;
                    319:     } else {
                    320:         level = 0;
                    321:     }
1.1.1.5   root      322:     qemu_set_irq(s->dev.irq[3], level);
1.1       root      323: }
                    324: 
1.1.1.7   root      325: static void uhci_reset(void *opaque)
1.1       root      326: {
1.1.1.7   root      327:     UHCIState *s = opaque;
1.1       root      328:     uint8_t *pci_conf;
                    329:     int i;
                    330:     UHCIPort *port;
                    331: 
1.1.1.6   root      332:     dprintf("uhci: full reset\n");
                    333: 
1.1       root      334:     pci_conf = s->dev.config;
                    335: 
                    336:     pci_conf[0x6a] = 0x01; /* usb clock */
                    337:     pci_conf[0x6b] = 0x00;
                    338:     s->cmd = 0;
                    339:     s->status = 0;
                    340:     s->status2 = 0;
                    341:     s->intr = 0;
                    342:     s->fl_base_addr = 0;
                    343:     s->sof_timing = 64;
1.1.1.6   root      344: 
1.1       root      345:     for(i = 0; i < NB_PORTS; i++) {
                    346:         port = &s->ports[i];
                    347:         port->ctrl = 0x0080;
                    348:         if (port->port.dev)
                    349:             uhci_attach(&port->port, port->port.dev);
                    350:     }
1.1.1.6   root      351: 
                    352:     uhci_async_cancel_all(s);
1.1       root      353: }
                    354: 
1.1.1.8 ! root      355: static void uhci_pre_save(void *opaque)
1.1.1.5   root      356: {
                    357:     UHCIState *s = opaque;
                    358: 
1.1.1.6   root      359:     uhci_async_cancel_all(s);
1.1.1.5   root      360: }
                    361: 
1.1.1.8 ! root      362: static const VMStateDescription vmstate_uhci_port = {
        !           363:     .name = "uhci port",
        !           364:     .version_id = 1,
        !           365:     .minimum_version_id = 1,
        !           366:     .minimum_version_id_old = 1,
        !           367:     .fields      = (VMStateField []) {
        !           368:         VMSTATE_UINT16(ctrl, UHCIPort),
        !           369:         VMSTATE_END_OF_LIST()
        !           370:     }
        !           371: };
        !           372: 
        !           373: static const VMStateDescription vmstate_uhci = {
        !           374:     .name = "uhci",
        !           375:     .version_id = 1,
        !           376:     .minimum_version_id = 1,
        !           377:     .minimum_version_id_old = 1,
        !           378:     .pre_save = uhci_pre_save,
        !           379:     .fields      = (VMStateField []) {
        !           380:         VMSTATE_PCI_DEVICE(dev, UHCIState),
        !           381:         VMSTATE_UINT8_EQUAL(num_ports_vmstate, UHCIState),
        !           382:         VMSTATE_STRUCT_ARRAY(ports, UHCIState, NB_PORTS, 1,
        !           383:                              vmstate_uhci_port, UHCIPort),
        !           384:         VMSTATE_UINT16(cmd, UHCIState),
        !           385:         VMSTATE_UINT16(status, UHCIState),
        !           386:         VMSTATE_UINT16(intr, UHCIState),
        !           387:         VMSTATE_UINT16(frnum, UHCIState),
        !           388:         VMSTATE_UINT32(fl_base_addr, UHCIState),
        !           389:         VMSTATE_UINT8(sof_timing, UHCIState),
        !           390:         VMSTATE_UINT8(status2, UHCIState),
        !           391:         VMSTATE_TIMER(frame_timer, UHCIState),
        !           392:         VMSTATE_END_OF_LIST()
        !           393:     }
        !           394: };
1.1.1.5   root      395: 
1.1       root      396: static void uhci_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
                    397: {
                    398:     UHCIState *s = opaque;
1.1.1.5   root      399: 
1.1       root      400:     addr &= 0x1f;
                    401:     switch(addr) {
                    402:     case 0x0c:
                    403:         s->sof_timing = val;
                    404:         break;
                    405:     }
                    406: }
                    407: 
                    408: static uint32_t uhci_ioport_readb(void *opaque, uint32_t addr)
                    409: {
                    410:     UHCIState *s = opaque;
                    411:     uint32_t val;
                    412: 
                    413:     addr &= 0x1f;
                    414:     switch(addr) {
                    415:     case 0x0c:
                    416:         val = s->sof_timing;
1.1.1.2   root      417:         break;
1.1       root      418:     default:
                    419:         val = 0xff;
                    420:         break;
                    421:     }
                    422:     return val;
                    423: }
                    424: 
                    425: static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
                    426: {
                    427:     UHCIState *s = opaque;
1.1.1.5   root      428: 
1.1       root      429:     addr &= 0x1f;
1.1.1.6   root      430:     dprintf("uhci: writew port=0x%04x val=0x%04x\n", addr, val);
                    431: 
1.1       root      432:     switch(addr) {
                    433:     case 0x00:
                    434:         if ((val & UHCI_CMD_RS) && !(s->cmd & UHCI_CMD_RS)) {
                    435:             /* start frame processing */
                    436:             qemu_mod_timer(s->frame_timer, qemu_get_clock(vm_clock));
1.1.1.2   root      437:             s->status &= ~UHCI_STS_HCHALTED;
                    438:         } else if (!(val & UHCI_CMD_RS)) {
                    439:             s->status |= UHCI_STS_HCHALTED;
1.1       root      440:         }
                    441:         if (val & UHCI_CMD_GRESET) {
                    442:             UHCIPort *port;
                    443:             USBDevice *dev;
                    444:             int i;
                    445: 
                    446:             /* send reset on the USB bus */
                    447:             for(i = 0; i < NB_PORTS; i++) {
                    448:                 port = &s->ports[i];
                    449:                 dev = port->port.dev;
                    450:                 if (dev) {
1.1.1.4   root      451:                     usb_send_msg(dev, USB_MSG_RESET);
1.1       root      452:                 }
                    453:             }
                    454:             uhci_reset(s);
                    455:             return;
                    456:         }
                    457:         if (val & UHCI_CMD_HCRESET) {
                    458:             uhci_reset(s);
                    459:             return;
                    460:         }
                    461:         s->cmd = val;
                    462:         break;
                    463:     case 0x02:
                    464:         s->status &= ~val;
                    465:         /* XXX: the chip spec is not coherent, so we add a hidden
                    466:            register to distinguish between IOC and SPD */
                    467:         if (val & UHCI_STS_USBINT)
                    468:             s->status2 = 0;
                    469:         uhci_update_irq(s);
                    470:         break;
                    471:     case 0x04:
                    472:         s->intr = val;
                    473:         uhci_update_irq(s);
                    474:         break;
                    475:     case 0x06:
                    476:         if (s->status & UHCI_STS_HCHALTED)
                    477:             s->frnum = val & 0x7ff;
                    478:         break;
                    479:     case 0x10 ... 0x1f:
                    480:         {
                    481:             UHCIPort *port;
                    482:             USBDevice *dev;
                    483:             int n;
                    484: 
                    485:             n = (addr >> 1) & 7;
                    486:             if (n >= NB_PORTS)
                    487:                 return;
                    488:             port = &s->ports[n];
                    489:             dev = port->port.dev;
                    490:             if (dev) {
                    491:                 /* port reset */
1.1.1.5   root      492:                 if ( (val & UHCI_PORT_RESET) &&
1.1       root      493:                      !(port->ctrl & UHCI_PORT_RESET) ) {
1.1.1.4   root      494:                     usb_send_msg(dev, USB_MSG_RESET);
1.1       root      495:                 }
                    496:             }
                    497:             port->ctrl = (port->ctrl & 0x01fb) | (val & ~0x01fb);
                    498:             /* some bits are reset when a '1' is written to them */
                    499:             port->ctrl &= ~(val & 0x000a);
                    500:         }
                    501:         break;
                    502:     }
                    503: }
                    504: 
                    505: static uint32_t uhci_ioport_readw(void *opaque, uint32_t addr)
                    506: {
                    507:     UHCIState *s = opaque;
                    508:     uint32_t val;
                    509: 
                    510:     addr &= 0x1f;
                    511:     switch(addr) {
                    512:     case 0x00:
                    513:         val = s->cmd;
                    514:         break;
                    515:     case 0x02:
                    516:         val = s->status;
                    517:         break;
                    518:     case 0x04:
                    519:         val = s->intr;
                    520:         break;
                    521:     case 0x06:
                    522:         val = s->frnum;
                    523:         break;
                    524:     case 0x10 ... 0x1f:
                    525:         {
                    526:             UHCIPort *port;
                    527:             int n;
                    528:             n = (addr >> 1) & 7;
1.1.1.5   root      529:             if (n >= NB_PORTS)
1.1       root      530:                 goto read_default;
                    531:             port = &s->ports[n];
                    532:             val = port->ctrl;
                    533:         }
                    534:         break;
                    535:     default:
                    536:     read_default:
                    537:         val = 0xff7f; /* disabled port */
                    538:         break;
                    539:     }
1.1.1.6   root      540: 
                    541:     dprintf("uhci: readw port=0x%04x val=0x%04x\n", addr, val);
                    542: 
1.1       root      543:     return val;
                    544: }
                    545: 
                    546: static void uhci_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
                    547: {
                    548:     UHCIState *s = opaque;
                    549: 
                    550:     addr &= 0x1f;
1.1.1.6   root      551:     dprintf("uhci: writel port=0x%04x val=0x%08x\n", addr, val);
                    552: 
1.1       root      553:     switch(addr) {
                    554:     case 0x08:
                    555:         s->fl_base_addr = val & ~0xfff;
                    556:         break;
                    557:     }
                    558: }
                    559: 
                    560: static uint32_t uhci_ioport_readl(void *opaque, uint32_t addr)
                    561: {
                    562:     UHCIState *s = opaque;
                    563:     uint32_t val;
                    564: 
                    565:     addr &= 0x1f;
                    566:     switch(addr) {
                    567:     case 0x08:
                    568:         val = s->fl_base_addr;
                    569:         break;
                    570:     default:
                    571:         val = 0xffffffff;
                    572:         break;
                    573:     }
                    574:     return val;
                    575: }
                    576: 
1.1.1.5   root      577: /* signal resume if controller suspended */
                    578: static void uhci_resume (void *opaque)
                    579: {
                    580:     UHCIState *s = (UHCIState *)opaque;
                    581: 
                    582:     if (!s)
                    583:         return;
                    584: 
                    585:     if (s->cmd & UHCI_CMD_EGSM) {
                    586:         s->cmd |= UHCI_CMD_FGR;
                    587:         s->status |= UHCI_STS_RD;
                    588:         uhci_update_irq(s);
                    589:     }
                    590: }
                    591: 
1.1       root      592: static void uhci_attach(USBPort *port1, USBDevice *dev)
                    593: {
                    594:     UHCIState *s = port1->opaque;
                    595:     UHCIPort *port = &s->ports[port1->index];
                    596: 
                    597:     if (dev) {
                    598:         if (port->port.dev) {
                    599:             usb_attach(port1, NULL);
                    600:         }
                    601:         /* set connect status */
1.1.1.3   root      602:         port->ctrl |= UHCI_PORT_CCS | UHCI_PORT_CSC;
                    603: 
1.1       root      604:         /* update speed */
                    605:         if (dev->speed == USB_SPEED_LOW)
                    606:             port->ctrl |= UHCI_PORT_LSDA;
                    607:         else
                    608:             port->ctrl &= ~UHCI_PORT_LSDA;
1.1.1.5   root      609: 
                    610:         uhci_resume(s);
                    611: 
1.1       root      612:         port->port.dev = dev;
                    613:         /* send the attach message */
1.1.1.4   root      614:         usb_send_msg(dev, USB_MSG_ATTACH);
1.1       root      615:     } else {
                    616:         /* set connect status */
1.1.1.3   root      617:         if (port->ctrl & UHCI_PORT_CCS) {
                    618:             port->ctrl &= ~UHCI_PORT_CCS;
                    619:             port->ctrl |= UHCI_PORT_CSC;
1.1       root      620:         }
                    621:         /* disable port */
                    622:         if (port->ctrl & UHCI_PORT_EN) {
                    623:             port->ctrl &= ~UHCI_PORT_EN;
                    624:             port->ctrl |= UHCI_PORT_ENC;
                    625:         }
1.1.1.5   root      626: 
                    627:         uhci_resume(s);
                    628: 
1.1       root      629:         dev = port->port.dev;
                    630:         if (dev) {
                    631:             /* send the detach message */
1.1.1.4   root      632:             usb_send_msg(dev, USB_MSG_DETACH);
1.1       root      633:         }
                    634:         port->port.dev = NULL;
                    635:     }
                    636: }
                    637: 
1.1.1.4   root      638: static int uhci_broadcast_packet(UHCIState *s, USBPacket *p)
1.1       root      639: {
                    640:     int i, ret;
                    641: 
1.1.1.6   root      642:     dprintf("uhci: packet enter. pid %s addr 0x%02x ep %d len %d\n",
                    643:            pid2str(p->pid), p->devaddr, p->devep, p->len);
                    644:     if (p->pid == USB_TOKEN_OUT || p->pid == USB_TOKEN_SETUP)
                    645:         dump_data(p->data, p->len);
                    646: 
                    647:     ret = USB_RET_NODEV;
                    648:     for (i = 0; i < NB_PORTS && ret == USB_RET_NODEV; i++) {
                    649:         UHCIPort *port = &s->ports[i];
                    650:         USBDevice *dev = port->port.dev;
                    651: 
                    652:         if (dev && (port->ctrl & UHCI_PORT_EN))
1.1.1.8 ! root      653:             ret = dev->info->handle_packet(dev, p);
1.1       root      654:     }
1.1.1.6   root      655: 
                    656:     dprintf("uhci: packet exit. ret %d len %d\n", ret, p->len);
                    657:     if (p->pid == USB_TOKEN_IN && ret > 0)
                    658:         dump_data(p->data, ret);
                    659: 
                    660:     return ret;
1.1       root      661: }
                    662: 
1.1.1.6   root      663: static void uhci_async_complete(USBPacket * packet, void *opaque);
                    664: static void uhci_process_frame(UHCIState *s);
1.1.1.4   root      665: 
1.1       root      666: /* return -1 if fatal error (frame must be stopped)
                    667:           0 if TD successful
                    668:           1 if TD unsuccessful or inactive
                    669: */
1.1.1.6   root      670: static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_t *int_mask)
1.1       root      671: {
1.1.1.6   root      672:     int len = 0, max_len, err, ret;
1.1       root      673:     uint8_t pid;
                    674: 
1.1.1.6   root      675:     max_len = ((td->token >> 21) + 1) & 0x7ff;
                    676:     pid = td->token & 0xff;
                    677: 
                    678:     ret = async->packet.len;
                    679: 
                    680:     if (td->ctrl & TD_CTRL_IOC)
1.1       root      681:         *int_mask |= 0x01;
1.1.1.5   root      682: 
1.1.1.6   root      683:     if (td->ctrl & TD_CTRL_IOS)
                    684:         td->ctrl &= ~TD_CTRL_ACTIVE;
1.1       root      685: 
1.1.1.6   root      686:     if (ret < 0)
                    687:         goto out;
1.1.1.5   root      688: 
1.1.1.6   root      689:     len = async->packet.len;
                    690:     td->ctrl = (td->ctrl & ~0x7ff) | ((len - 1) & 0x7ff);
                    691: 
                    692:     /* The NAK bit may have been set by a previous frame, so clear it
                    693:        here.  The docs are somewhat unclear, but win2k relies on this
                    694:        behavior.  */
                    695:     td->ctrl &= ~(TD_CTRL_ACTIVE | TD_CTRL_NAK);
                    696: 
                    697:     if (pid == USB_TOKEN_IN) {
                    698:         if (len > max_len) {
1.1.1.4   root      699:             len = max_len;
1.1.1.6   root      700:             ret = USB_RET_BABBLE;
                    701:             goto out;
1.1.1.4   root      702:         }
1.1.1.5   root      703: 
1.1.1.6   root      704:         if (len > 0) {
                    705:             /* write the data back */
                    706:             cpu_physical_memory_write(td->buffer, async->buffer, len);
                    707:         }
                    708: 
                    709:         if ((td->ctrl & TD_CTRL_SPD) && len < max_len) {
1.1       root      710:             *int_mask |= 0x02;
                    711:             /* short packet: do not update QH */
1.1.1.6   root      712:             dprintf("uhci: short packet. td 0x%x token 0x%x\n", async->td, async->token);
1.1       root      713:             return 1;
                    714:         }
1.1.1.6   root      715:     }
                    716: 
                    717:     /* success */
                    718:     return 0;
                    719: 
                    720: out:
                    721:     switch(ret) {
                    722:     case USB_RET_STALL:
                    723:         td->ctrl |= TD_CTRL_STALL;
                    724:         td->ctrl &= ~TD_CTRL_ACTIVE;
                    725:         return 1;
                    726: 
                    727:     case USB_RET_BABBLE:
                    728:         td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL;
                    729:         td->ctrl &= ~TD_CTRL_ACTIVE;
                    730:         /* frame interrupted */
                    731:         return -1;
                    732: 
                    733:     case USB_RET_NAK:
                    734:         td->ctrl |= TD_CTRL_NAK;
                    735:         if (pid == USB_TOKEN_SETUP)
                    736:             break;
                    737:        return 1;
                    738: 
                    739:     case USB_RET_NODEV:
                    740:     default:
                    741:        break;
                    742:     }
                    743: 
                    744:     /* Retry the TD if error count is not zero */
                    745: 
                    746:     td->ctrl |= TD_CTRL_TIMEOUT;
                    747:     err = (td->ctrl >> TD_CTRL_ERROR_SHIFT) & 3;
                    748:     if (err != 0) {
                    749:         err--;
                    750:         if (err == 0) {
1.1       root      751:             td->ctrl &= ~TD_CTRL_ACTIVE;
1.1.1.6   root      752:             s->status |= UHCI_STS_USBERR;
                    753:             uhci_update_irq(s);
1.1       root      754:         }
                    755:     }
1.1.1.6   root      756:     td->ctrl = (td->ctrl & ~(3 << TD_CTRL_ERROR_SHIFT)) |
                    757:         (err << TD_CTRL_ERROR_SHIFT);
                    758:     return 1;
1.1       root      759: }
                    760: 
1.1.1.6   root      761: static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, uint32_t *int_mask)
                    762: {
                    763:     UHCIAsync *async;
                    764:     int len = 0, max_len;
                    765:     uint8_t pid;
                    766: 
                    767:     /* Is active ? */
                    768:     if (!(td->ctrl & TD_CTRL_ACTIVE))
                    769:         return 1;
                    770: 
                    771:     async = uhci_async_find_td(s, addr, td->token);
                    772:     if (async) {
                    773:         /* Already submitted */
                    774:         async->valid = 32;
                    775: 
                    776:         if (!async->done)
                    777:             return 1;
                    778: 
                    779:         uhci_async_unlink(s, async);
                    780:         goto done;
                    781:     }
                    782: 
                    783:     /* Allocate new packet */
                    784:     async = uhci_async_alloc(s);
                    785:     if (!async)
                    786:         return 1;
                    787: 
                    788:     async->valid = 10;
                    789:     async->td    = addr;
                    790:     async->token = td->token;
                    791: 
                    792:     max_len = ((td->token >> 21) + 1) & 0x7ff;
                    793:     pid = td->token & 0xff;
                    794: 
                    795:     async->packet.pid     = pid;
                    796:     async->packet.devaddr = (td->token >> 8) & 0x7f;
                    797:     async->packet.devep   = (td->token >> 15) & 0xf;
                    798:     async->packet.data    = async->buffer;
                    799:     async->packet.len     = max_len;
                    800:     async->packet.complete_cb     = uhci_async_complete;
                    801:     async->packet.complete_opaque = s;
                    802: 
                    803:     switch(pid) {
                    804:     case USB_TOKEN_OUT:
                    805:     case USB_TOKEN_SETUP:
                    806:         cpu_physical_memory_read(td->buffer, async->buffer, max_len);
                    807:         len = uhci_broadcast_packet(s, &async->packet);
                    808:         if (len >= 0)
                    809:             len = max_len;
                    810:         break;
                    811: 
                    812:     case USB_TOKEN_IN:
                    813:         len = uhci_broadcast_packet(s, &async->packet);
                    814:         break;
                    815: 
                    816:     default:
                    817:         /* invalid pid : frame interrupted */
                    818:         uhci_async_free(s, async);
                    819:         s->status |= UHCI_STS_HCPERR;
                    820:         uhci_update_irq(s);
                    821:         return -1;
                    822:     }
                    823:  
                    824:     if (len == USB_RET_ASYNC) {
                    825:         uhci_async_link(s, async);
                    826:         return 2;
                    827:     }
                    828: 
                    829:     async->packet.len = len;
                    830: 
                    831: done:
                    832:     len = uhci_complete_td(s, td, async, int_mask);
                    833:     uhci_async_free(s, async);
                    834:     return len;
                    835: }
                    836: 
                    837: static void uhci_async_complete(USBPacket *packet, void *opaque)
1.1.1.4   root      838: {
                    839:     UHCIState *s = opaque;
1.1.1.6   root      840:     UHCIAsync *async = (UHCIAsync *) packet;
                    841: 
                    842:     dprintf("uhci: async complete. td 0x%x token 0x%x\n", async->td, async->token);
                    843: 
                    844:     async->done = 1;
                    845: 
                    846:     uhci_process_frame(s);
                    847: }
                    848: 
                    849: static int is_valid(uint32_t link)
                    850: {
                    851:     return (link & 1) == 0;
                    852: }
                    853: 
                    854: static int is_qh(uint32_t link)
                    855: {
                    856:     return (link & 2) != 0;
                    857: }
                    858: 
                    859: static int depth_first(uint32_t link)
                    860: {
                    861:     return (link & 4) != 0;
                    862: }
                    863: 
                    864: /* QH DB used for detecting QH loops */
                    865: #define UHCI_MAX_QUEUES 128
                    866: typedef struct {
                    867:     uint32_t addr[UHCI_MAX_QUEUES];
                    868:     int      count;
                    869: } QhDb;
                    870: 
                    871: static void qhdb_reset(QhDb *db)
                    872: {
                    873:     db->count = 0;
                    874: }
                    875: 
                    876: /* Add QH to DB. Returns 1 if already present or DB is full. */
                    877: static int qhdb_insert(QhDb *db, uint32_t addr)
                    878: {
                    879:     int i;
                    880:     for (i = 0; i < db->count; i++)
                    881:         if (db->addr[i] == addr)
                    882:             return 1;
                    883: 
                    884:     if (db->count >= UHCI_MAX_QUEUES)
                    885:         return 1;
                    886: 
                    887:     db->addr[db->count++] = addr;
                    888:     return 0;
                    889: }
                    890: 
                    891: static void uhci_process_frame(UHCIState *s)
                    892: {
                    893:     uint32_t frame_addr, link, old_td_ctrl, val, int_mask;
                    894:     uint32_t curr_qh;
                    895:     int cnt, ret;
1.1.1.4   root      896:     UHCI_TD td;
1.1.1.6   root      897:     UHCI_QH qh;
                    898:     QhDb qhdb;
                    899: 
                    900:     frame_addr = s->fl_base_addr + ((s->frnum & 0x3ff) << 2);
                    901: 
                    902:     dprintf("uhci: processing frame %d addr 0x%x\n" , s->frnum, frame_addr);
                    903: 
                    904:     cpu_physical_memory_read(frame_addr, (uint8_t *)&link, 4);
                    905:     le32_to_cpus(&link);
                    906: 
                    907:     int_mask = 0;
                    908:     curr_qh  = 0;
                    909: 
                    910:     qhdb_reset(&qhdb);
                    911: 
                    912:     for (cnt = FRAME_MAX_LOOPS; is_valid(link) && cnt; cnt--) {
                    913:         if (is_qh(link)) {
                    914:             /* QH */
                    915: 
                    916:             if (qhdb_insert(&qhdb, link)) {
                    917:                 /*
                    918:                  * We're going in circles. Which is not a bug because
                    919:                  * HCD is allowed to do that as part of the BW management. 
                    920:                  * In our case though it makes no sense to spin here. Sync transations 
                    921:                  * are already done, and async completion handler will re-process 
                    922:                  * the frame when something is ready.
                    923:                  */
                    924:                 dprintf("uhci: detected loop. qh 0x%x\n", link);
                    925:                 break;
                    926:             }
                    927: 
                    928:             cpu_physical_memory_read(link & ~0xf, (uint8_t *) &qh, sizeof(qh));
                    929:             le32_to_cpus(&qh.link);
                    930:             le32_to_cpus(&qh.el_link);
                    931: 
                    932:             dprintf("uhci: QH 0x%x load. link 0x%x elink 0x%x\n",
                    933:                     link, qh.link, qh.el_link);
1.1.1.4   root      934: 
1.1.1.6   root      935:             if (!is_valid(qh.el_link)) {
                    936:                 /* QH w/o elements */
                    937:                 curr_qh = 0;
                    938:                 link = qh.link;
                    939:             } else {
                    940:                 /* QH with elements */
                    941:                curr_qh = link;
                    942:                link = qh.el_link;
                    943:             }
                    944:             continue;
                    945:         }
1.1.1.5   root      946: 
1.1.1.6   root      947:         /* TD */
                    948:         cpu_physical_memory_read(link & ~0xf, (uint8_t *) &td, sizeof(td));
1.1.1.5   root      949:         le32_to_cpus(&td.link);
                    950:         le32_to_cpus(&td.ctrl);
                    951:         le32_to_cpus(&td.token);
                    952:         le32_to_cpus(&td.buffer);
                    953: 
1.1.1.6   root      954:         dprintf("uhci: TD 0x%x load. link 0x%x ctrl 0x%x token 0x%x qh 0x%x\n", 
                    955:                 link, td.link, td.ctrl, td.token, curr_qh);
                    956: 
                    957:         old_td_ctrl = td.ctrl;
                    958:         ret = uhci_handle_td(s, link, &td, &int_mask);
1.1.1.5   root      959:         if (old_td_ctrl != td.ctrl) {
1.1.1.6   root      960:             /* update the status bits of the TD */
1.1.1.5   root      961:             val = cpu_to_le32(td.ctrl);
                    962:             cpu_physical_memory_write((link & ~0xf) + 4,
1.1.1.6   root      963:                                       (const uint8_t *)&val, sizeof(val));
1.1.1.5   root      964:         }
1.1.1.6   root      965: 
                    966:         if (ret < 0) {
                    967:             /* interrupted frame */
                    968:             break;
1.1.1.5   root      969:         }
                    970: 
1.1.1.6   root      971:         if (ret == 2 || ret == 1) {
                    972:             dprintf("uhci: TD 0x%x %s. link 0x%x ctrl 0x%x token 0x%x qh 0x%x\n",
                    973:                     link, ret == 2 ? "pend" : "skip",
                    974:                     td.link, td.ctrl, td.token, curr_qh);
1.1.1.5   root      975: 
1.1.1.6   root      976:             link = curr_qh ? qh.link : td.link;
                    977:             continue;
                    978:         }
                    979: 
                    980:         /* completed TD */
                    981: 
                    982:         dprintf("uhci: TD 0x%x done. link 0x%x ctrl 0x%x token 0x%x qh 0x%x\n", 
                    983:                 link, td.link, td.ctrl, td.token, curr_qh);
                    984: 
                    985:         link = td.link;
                    986: 
                    987:         if (curr_qh) {
                    988:            /* update QH element link */
                    989:             qh.el_link = link;
1.1.1.4   root      990:             val = cpu_to_le32(qh.el_link);
1.1.1.6   root      991:             cpu_physical_memory_write((curr_qh & ~0xf) + 4,
                    992:                                           (const uint8_t *)&val, sizeof(val));
                    993: 
                    994:             if (!depth_first(link)) {
                    995:                /* done with this QH */
                    996: 
                    997:                dprintf("uhci: QH 0x%x done. link 0x%x elink 0x%x\n",
                    998:                        curr_qh, qh.link, qh.el_link);
                    999: 
                   1000:                curr_qh = 0;
                   1001:                link    = qh.link;
                   1002:             }
1.1.1.4   root     1003:         }
1.1.1.6   root     1004: 
                   1005:         /* go to the next entry */
1.1.1.4   root     1006:     }
1.1.1.6   root     1007: 
                   1008:     s->pending_int_mask = int_mask;
1.1.1.4   root     1009: }
                   1010: 
1.1       root     1011: static void uhci_frame_timer(void *opaque)
                   1012: {
                   1013:     UHCIState *s = opaque;
                   1014:     int64_t expire_time;
                   1015: 
                   1016:     if (!(s->cmd & UHCI_CMD_RS)) {
1.1.1.6   root     1017:         /* Full stop */
1.1       root     1018:         qemu_del_timer(s->frame_timer);
1.1.1.2   root     1019:         /* set hchalted bit in status - UHCI11D 2.1.2 */
                   1020:         s->status |= UHCI_STS_HCHALTED;
1.1.1.6   root     1021: 
                   1022:         dprintf("uhci: halted\n");
1.1       root     1023:         return;
                   1024:     }
1.1.1.6   root     1025: 
                   1026:     /* Complete the previous frame */
1.1.1.4   root     1027:     if (s->pending_int_mask) {
                   1028:         s->status2 |= s->pending_int_mask;
1.1.1.6   root     1029:         s->status  |= UHCI_STS_USBINT;
1.1.1.4   root     1030:         uhci_update_irq(s);
                   1031:     }
1.1.1.5   root     1032: 
1.1.1.6   root     1033:     /* Start new frame */
                   1034:     s->frnum = (s->frnum + 1) & 0x7ff;
                   1035: 
                   1036:     dprintf("uhci: new frame #%u\n" , s->frnum);
                   1037: 
                   1038:     uhci_async_validate_begin(s);
                   1039: 
                   1040:     uhci_process_frame(s);
                   1041: 
                   1042:     uhci_async_validate_end(s);
1.1.1.5   root     1043: 
1.1       root     1044:     /* prepare the timer for the next frame */
1.1.1.5   root     1045:     expire_time = qemu_get_clock(vm_clock) +
1.1.1.8 ! root     1046:         (get_ticks_per_sec() / FRAME_TIMER_FREQ);
1.1       root     1047:     qemu_mod_timer(s->frame_timer, expire_time);
                   1048: }
                   1049: 
1.1.1.5   root     1050: static void uhci_map(PCIDevice *pci_dev, int region_num,
1.1.1.8 ! root     1051:                     pcibus_t addr, pcibus_t size, int type)
1.1       root     1052: {
                   1053:     UHCIState *s = (UHCIState *)pci_dev;
                   1054: 
                   1055:     register_ioport_write(addr, 32, 2, uhci_ioport_writew, s);
                   1056:     register_ioport_read(addr, 32, 2, uhci_ioport_readw, s);
                   1057:     register_ioport_write(addr, 32, 4, uhci_ioport_writel, s);
                   1058:     register_ioport_read(addr, 32, 4, uhci_ioport_readl, s);
                   1059:     register_ioport_write(addr, 32, 1, uhci_ioport_writeb, s);
                   1060:     register_ioport_read(addr, 32, 1, uhci_ioport_readb, s);
                   1061: }
                   1062: 
1.1.1.8 ! root     1063: static int usb_uhci_common_initfn(UHCIState *s)
1.1       root     1064: {
1.1.1.8 ! root     1065:     uint8_t *pci_conf = s->dev.config;
1.1       root     1066:     int i;
                   1067: 
                   1068:     pci_conf[0x08] = 0x01; // revision number
                   1069:     pci_conf[0x09] = 0x00;
1.1.1.6   root     1070:     pci_config_set_class(pci_conf, PCI_CLASS_SERIAL_USB);
1.1.1.7   root     1071:     pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
1.1       root     1072:     pci_conf[0x3d] = 4; // interrupt pin 3
1.1.1.2   root     1073:     pci_conf[0x60] = 0x10; // release number
1.1.1.5   root     1074: 
1.1.1.8 ! root     1075:     usb_bus_new(&s->bus, &s->dev.qdev);
1.1.1.5   root     1076:     for(i = 0; i < NB_PORTS; i++) {
1.1.1.8 ! root     1077:         usb_register_port(&s->bus, &s->ports[i].port, s, i, uhci_attach);
1.1.1.5   root     1078:     }
                   1079:     s->frame_timer = qemu_new_timer(vm_clock, uhci_frame_timer, s);
1.1.1.8 ! root     1080:     s->num_ports_vmstate = NB_PORTS;
1.1.1.5   root     1081: 
1.1.1.7   root     1082:     qemu_register_reset(uhci_reset, s);
1.1.1.5   root     1083: 
                   1084:     /* Use region 4 for consistency with real hardware.  BSD guests seem
                   1085:        to rely on this.  */
1.1.1.7   root     1086:     pci_register_bar(&s->dev, 4, 0x20,
1.1.1.8 ! root     1087:                            PCI_BASE_ADDRESS_SPACE_IO, uhci_map);
1.1.1.6   root     1088: 
1.1.1.8 ! root     1089:     return 0;
1.1.1.5   root     1090: }
                   1091: 
1.1.1.8 ! root     1092: static int usb_uhci_piix3_initfn(PCIDevice *dev)
1.1.1.5   root     1093: {
1.1.1.8 ! root     1094:     UHCIState *s = DO_UPCAST(UHCIState, dev, dev);
        !          1095:     uint8_t *pci_conf = s->dev.config;
        !          1096: 
        !          1097:     pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
        !          1098:     pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371SB_2);
        !          1099:     return usb_uhci_common_initfn(s);
        !          1100: }
        !          1101: 
        !          1102: static int usb_uhci_piix4_initfn(PCIDevice *dev)
        !          1103: {
        !          1104:     UHCIState *s = DO_UPCAST(UHCIState, dev, dev);
        !          1105:     uint8_t *pci_conf = s->dev.config;
1.1.1.5   root     1106: 
1.1.1.6   root     1107:     pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
                   1108:     pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371AB_2);
1.1.1.8 ! root     1109:     return usb_uhci_common_initfn(s);
        !          1110: }
1.1.1.5   root     1111: 
1.1.1.8 ! root     1112: static PCIDeviceInfo uhci_info[] = {
        !          1113:     {
        !          1114:         .qdev.name    = "piix3-usb-uhci",
        !          1115:         .qdev.size    = sizeof(UHCIState),
        !          1116:         .qdev.vmsd    = &vmstate_uhci,
        !          1117:         .init         = usb_uhci_piix3_initfn,
        !          1118:     },{
        !          1119:         .qdev.name    = "piix4-usb-uhci",
        !          1120:         .qdev.size    = sizeof(UHCIState),
        !          1121:         .qdev.vmsd    = &vmstate_uhci,
        !          1122:         .init         = usb_uhci_piix4_initfn,
        !          1123:     },{
        !          1124:         /* end of list */
1.1       root     1125:     }
1.1.1.8 ! root     1126: };
1.1       root     1127: 
1.1.1.8 ! root     1128: static void uhci_register(void)
        !          1129: {
        !          1130:     pci_qdev_register_many(uhci_info);
        !          1131: }
        !          1132: device_init(uhci_register);
1.1       root     1133: 
1.1.1.8 ! root     1134: void usb_uhci_piix3_init(PCIBus *bus, int devfn)
        !          1135: {
        !          1136:     pci_create_simple(bus, devfn, "piix3-usb-uhci");
        !          1137: }
1.1.1.6   root     1138: 
1.1.1.8 ! root     1139: void usb_uhci_piix4_init(PCIBus *bus, int devfn)
        !          1140: {
        !          1141:     pci_create_simple(bus, devfn, "piix4-usb-uhci");
1.1       root     1142: }

unix.superglobalmegacorp.com

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