Revision e654887f hw/usb-ehci.c

b/hw/usb-ehci.c
198 198
#define ITD_BUFPTR_MAXPKT_MASK   0x000007ff
199 199
#define ITD_BUFPTR_MAXPKT_SH     0
200 200
#define ITD_BUFPTR_MULT_MASK     0x00000003
201
#define ITD_BUFPTR_MULT_SH       0
201 202
} EHCIitd;
202 203

  
203 204
/*  EHCI spec version 1.0 Section 3.4
......
628 629

  
629 630
static void ehci_trace_itd(EHCIState *s, target_phys_addr_t addr, EHCIitd *itd)
630 631
{
631
    trace_usb_ehci_itd(addr, itd->next);
632
    trace_usb_ehci_itd(addr, itd->next,
633
                       get_field(itd->bufptr[1], ITD_BUFPTR_MAXPKT),
634
                       get_field(itd->bufptr[2], ITD_BUFPTR_MULT),
635
                       get_field(itd->bufptr[0], ITD_BUFPTR_EP),
636
                       get_field(itd->bufptr[0], ITD_BUFPTR_DEVADDR));
632 637
}
633 638

  
634 639
/* queue management */
......
1270 1275
    USBPort *port;
1271 1276
    USBDevice *dev;
1272 1277
    int ret;
1273
    int i, j;
1274
    int ptr;
1275
    int pid;
1276
    int pg;
1277
    int len;
1278
    int dir;
1279
    int devadr;
1280
    int endp;
1278
    uint32_t i, j, len, len1, len2, pid, dir, devaddr, endp;
1279
    uint32_t pg, off, ptr1, ptr2, max, mult;
1281 1280

  
1282 1281
    dir =(itd->bufptr[1] & ITD_BUFPTR_DIRECTION);
1283
    devadr = get_field(itd->bufptr[0], ITD_BUFPTR_DEVADDR);
1282
    devaddr = get_field(itd->bufptr[0], ITD_BUFPTR_DEVADDR);
1284 1283
    endp = get_field(itd->bufptr[0], ITD_BUFPTR_EP);
1285
    /* maxpkt = get_field(itd->bufptr[1], ITD_BUFPTR_MAXPKT); */
1284
    max = get_field(itd->bufptr[1], ITD_BUFPTR_MAXPKT);
1285
    mult = get_field(itd->bufptr[2], ITD_BUFPTR_MULT);
1286 1286

  
1287 1287
    for(i = 0; i < 8; i++) {
1288 1288
        if (itd->transact[i] & ITD_XACT_ACTIVE) {
1289
            DPRINTF("ISOCHRONOUS active for frame %d, interval %d\n",
1290
                    ehci->frindex >> 3, i);
1291

  
1292
            pg = get_field(itd->transact[i], ITD_XACT_PGSEL);
1293
            ptr = (itd->bufptr[pg] & ITD_BUFPTR_MASK) |
1294
                (itd->transact[i] & ITD_XACT_OFFSET_MASK);
1295
            len = get_field(itd->transact[i], ITD_XACT_LENGTH);
1289
            pg   = get_field(itd->transact[i], ITD_XACT_PGSEL);
1290
            off  = itd->transact[i] & ITD_XACT_OFFSET_MASK;
1291
            ptr1 = (itd->bufptr[pg] & ITD_BUFPTR_MASK);
1292
            ptr2 = (itd->bufptr[pg+1] & ITD_BUFPTR_MASK);
1293
            len  = get_field(itd->transact[i], ITD_XACT_LENGTH);
1294

  
1295
            if (len > max * mult) {
1296
                len = max * mult;
1297
            }
1296 1298

  
1297 1299
            if (len > BUFF_SIZE) {
1298 1300
                return USB_RET_PROCERR;
1299 1301
            }
1300 1302

  
1301
            DPRINTF("ISOCH: buffer %08X len %d\n", ptr, len);
1303
            if (off + len > 4096) {
1304
                /* transfer crosses page border */
1305
                len2 = off + len - 4096;
1306
                len1 = len - len2;
1307
            } else {
1308
                len1 = len;
1309
                len2 = 0;
1310
            }
1302 1311

  
1303 1312
            if (!dir) {
1304
                cpu_physical_memory_rw(ptr, &ehci->ibuffer[0], len, 0);
1305 1313
                pid = USB_TOKEN_OUT;
1306
            } else
1314
                trace_usb_ehci_data(0, pg, off, ptr1 + off, len1, 0);
1315
                cpu_physical_memory_rw(ptr1 + off, &ehci->ibuffer[0], len1, 0);
1316
                if (len2) {
1317
                    trace_usb_ehci_data(0, pg+1, 0, ptr2, len2, len1);
1318
                    cpu_physical_memory_rw(ptr2, &ehci->ibuffer[len1], len2, 0);
1319
                }
1320
            } else {
1307 1321
                pid = USB_TOKEN_IN;
1322
            }
1308 1323

  
1309 1324
            ret = USB_RET_NODEV;
1310 1325

  
......
1315 1330
                // TODO sometime we will also need to check if we are the port owner
1316 1331

  
1317 1332
                if (!(ehci->portsc[j] &(PORTSC_CONNECT))) {
1318
                    DPRINTF("Port %d, no exec, not connected(%08X)\n",
1319
                            j, ehci->portsc[j]);
1320 1333
                    continue;
1321 1334
                }
1322 1335

  
1323 1336
                ehci->ipacket.pid = pid;
1324
                ehci->ipacket.devaddr = devadr;
1337
                ehci->ipacket.devaddr = devaddr;
1325 1338
                ehci->ipacket.devep = endp;
1326 1339
                ehci->ipacket.data = ehci->ibuffer;
1327 1340
                ehci->ipacket.len = len;
1328 1341

  
1329
                DPRINTF("calling usb_handle_packet\n");
1330 1342
                ret = usb_handle_packet(dev, &ehci->ipacket);
1331 1343

  
1332 1344
                if (ret != USB_RET_NODEV) {
......
1334 1346
                }
1335 1347
            }
1336 1348

  
1349
#if 0
1337 1350
            /*  In isoch, there is no facility to indicate a NAK so let's
1338 1351
             *  instead just complete a zero-byte transaction.  Setting
1339 1352
             *  DBERR seems too draconian.
......
1358 1371
                DPRINTF("ISOCH: received ACK, clearing pause\n");
1359 1372
                ehci->isoch_pause = -1;
1360 1373
            }
1374
#else
1375
            if (ret == USB_RET_NAK) {
1376
                ret = 0;
1377
            }
1378
#endif
1361 1379

  
1362 1380
            if (ret >= 0) {
1363
                itd->transact[i] &= ~ITD_XACT_ACTIVE;
1381
                if (!dir) {
1382
                    /* OUT */
1383
                    set_field(&itd->transact[i], len - ret, ITD_XACT_LENGTH);
1384
                } else {
1385
                    /* IN */
1386
                    if (len1 > ret) {
1387
                        len1 = ret;
1388
                    }
1389
                    if (len2 > ret - len1) {
1390
                        len2 = ret - len1;
1391
                    }
1392
                    if (len1) {
1393
                        trace_usb_ehci_data(1, pg, off, ptr1 + off, len1, 0);
1394
                        cpu_physical_memory_rw(ptr1 + off, &ehci->ibuffer[0], len1, 1);
1395
                    }
1396
                    if (len2) {
1397
                        trace_usb_ehci_data(1, pg+1, 0, ptr2, len2, len1);
1398
                        cpu_physical_memory_rw(ptr2, &ehci->ibuffer[len1], len2, 1);
1399
                    }
1400
                    set_field(&itd->transact[i], ret, ITD_XACT_LENGTH);
1401
                }
1364 1402

  
1365 1403
                if (itd->transact[i] & ITD_XACT_IOC) {
1366 1404
                    ehci_record_interrupt(ehci, USBSTS_INT);
1367 1405
                }
1368 1406
            }
1369

  
1370
            if (ret >= 0 && dir) {
1371
                cpu_physical_memory_rw(ptr, &ehci->ibuffer[0], len, 1);
1372

  
1373
                if (ret != len) {
1374
                    DPRINTF("ISOCH IN expected %d, got %d\n",
1375
                            len, ret);
1376
                    set_field(&itd->transact[i], ret, ITD_XACT_LENGTH);
1377
                }
1378
            }
1407
            itd->transact[i] &= ~ITD_XACT_ACTIVE;
1379 1408
        }
1380 1409
    }
1381 1410
    return 0;

Also available in: Unified diff