X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fusb-msc.c;h=4a09972b5f63381aaa592df63fd31629092c8a7f;hb=4e34332fbf9b04ae9040f0f0c07b40455690e535;hp=c1fa45ddbc1af1bf1bb6853bd051d9b37106eb8a;hpb=575ffc8fd1127e3cb8fbb7f587cadfa85eb9b73d;p=seabios.git diff --git a/src/usb-msc.c b/src/usb-msc.c index c1fa45d..4a09972 100644 --- a/src/usb-msc.c +++ b/src/usb-msc.c @@ -11,7 +11,7 @@ #include "biosvar.h" // GET_GLOBAL #include "blockcmd.h" // cdb_read #include "disk.h" // DTYPE_USB -#include "boot.h" // add_bcv_internal +#include "boot.h" // boot_add_hd struct usbdrive_s { struct drive_s drive; @@ -46,43 +46,57 @@ struct csw_s { u8 bCSWStatus; } PACKED; +static int +usb_msc_send(struct usbdrive_s *udrive_g, int dir, void *buf, u32 bytes) +{ + struct usb_pipe *pipe; + if (dir == USB_DIR_OUT) + pipe = GET_GLOBAL(udrive_g->bulkout); + else + pipe = GET_GLOBAL(udrive_g->bulkin); + return usb_send_bulk(pipe, dir, buf, bytes); +} + // Low-level usb command transmit function. int usb_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize) { - dprintf(1, "usb_cmd_data id=%p write=%d count=%d bs=%d buf=%p\n" + if (!CONFIG_USB_MSC) + return 0; + + dprintf(16, "usb_cmd_data id=%p write=%d count=%d bs=%d buf=%p\n" , op->drive_g, 0, op->count, blocksize, op->buf_fl); struct usbdrive_s *udrive_g = container_of( op->drive_g, struct usbdrive_s, drive); - struct usb_pipe *bulkin = GET_GLOBAL(udrive_g->bulkin); - struct usb_pipe *bulkout = GET_GLOBAL(udrive_g->bulkout); // Setup command block wrapper. u32 bytes = blocksize * op->count; struct cbw_s cbw; memset(&cbw, 0, sizeof(cbw)); + memcpy(cbw.CBWCB, cdbcmd, USB_CDB_SIZE); cbw.dCBWSignature = CBW_SIGNATURE; cbw.dCBWTag = 999; // XXX cbw.dCBWDataTransferLength = bytes; - cbw.bmCBWFlags = USB_DIR_IN; // XXX + cbw.bmCBWFlags = (cbw.CBWCB[0] == CDB_CMD_WRITE_10) ? USB_DIR_OUT : USB_DIR_IN; cbw.bCBWLUN = 0; // XXX cbw.bCBWCBLength = USB_CDB_SIZE; - memcpy(cbw.CBWCB, cdbcmd, USB_CDB_SIZE); // Transfer cbw to device. - int ret = usb_send_bulk(bulkout, USB_DIR_OUT + int ret = usb_msc_send(udrive_g, USB_DIR_OUT , MAKE_FLATPTR(GET_SEG(SS), &cbw), sizeof(cbw)); if (ret) goto fail; - // Transfer data from device. - ret = usb_send_bulk(bulkin, USB_DIR_IN, op->buf_fl, bytes); - if (ret) - goto fail; + // Transfer data to/from device. + if (bytes) { + ret = usb_msc_send(udrive_g, cbw.bmCBWFlags, op->buf_fl, bytes); + if (ret) + goto fail; + } // Transfer csw info. struct csw_s csw; - ret = usb_send_bulk(bulkin, USB_DIR_IN + ret = usb_msc_send(udrive_g, USB_DIR_IN , MAKE_FLATPTR(GET_SEG(SS), &csw), sizeof(csw)); if (ret) goto fail; @@ -92,7 +106,8 @@ usb_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize) if (csw.bCSWStatus == 2) goto fail; - op->count -= csw.dCSWDataResidue / blocksize; + if (blocksize) + op->count -= csw.dCSWDataResidue / blocksize; return DISK_RET_EBADTRACK; fail: @@ -103,89 +118,64 @@ fail: } -/**************************************************************** - * Drive ops - ****************************************************************/ - -// 16bit command demuxer for ATAPI cdroms. -int -process_usb_op(struct disk_op_s *op) -{ - switch (op->command) { - case CMD_READ: - return cdb_read(op); - case CMD_FORMAT: - case CMD_WRITE: - return DISK_RET_EWRITEPROTECT; - case CMD_RESET: - case CMD_ISREADY: - case CMD_VERIFY: - case CMD_SEEK: - return DISK_RET_SUCCESS; - default: - op->count = 0; - return DISK_RET_EPARAM; - } -} - - /**************************************************************** * Setup ****************************************************************/ static int -setup_drive_cdrom(struct disk_op_s *op) +setup_drive_cdrom(struct drive_s *drive, char *desc) { - op->drive_g->blksize = CDROM_SECTOR_SIZE; - op->drive_g->sectors = (u64)-1; - map_cd_drive(op->drive_g); + drive->sectors = (u64)-1; + struct usb_pipe *pipe = container_of( + drive, struct usbdrive_s, drive)->bulkout; + int prio = bootprio_find_usb(pipe->cntl->pci, pipe->path); + boot_add_cd(drive, desc, prio); return 0; } static int -setup_drive_hd(struct disk_op_s *op) +setup_drive_hd(struct drive_s *drive, char *desc) { - struct cdbres_read_capacity info; - int ret = cdb_read_capacity(op, &info); - if (ret) - return ret; - // XXX - retry for some timeout? - - u32 blksize = ntohl(info.blksize), sectors = ntohl(info.sectors); - if (blksize != DISK_SECTOR_SIZE) { - if (blksize == CDROM_SECTOR_SIZE) - return setup_drive_cdrom(op); - dprintf(1, "Unsupported USB MSC block size %d\n", blksize); + if (drive->blksize != DISK_SECTOR_SIZE) { + dprintf(1, "Unsupported USB MSC block size %d\n", drive->blksize); return -1; } - op->drive_g->blksize = blksize; - op->drive_g->sectors = sectors; - dprintf(1, "USB MSC blksize=%d sectors=%d\n", blksize, sectors); - - // Setup disk geometry translation. - setup_translation(op->drive_g); // Register with bcv system. - add_bcv_internal(op->drive_g); - + struct usb_pipe *pipe = container_of( + drive, struct usbdrive_s, drive)->bulkout; + int prio = bootprio_find_usb(pipe->cntl->pci, pipe->path); + boot_add_hd(drive, desc, prio); return 0; } // Configure a usb msc device. int -usb_msc_init(u32 endp, struct usb_interface_descriptor *iface, int imax) +usb_msc_init(struct usb_pipe *pipe + , struct usb_interface_descriptor *iface, int imax) { if (!CONFIG_USB_MSC) return -1; // Verify right kind of device - if (iface->bInterfaceSubClass != US_SC_SCSI + if ((iface->bInterfaceSubClass != US_SC_SCSI && + iface->bInterfaceSubClass != US_SC_ATAPI_8070 && + iface->bInterfaceSubClass != US_SC_ATAPI_8020) || iface->bInterfaceProtocol != US_PR_BULK) { dprintf(1, "Unsupported MSC USB device (subclass=%02x proto=%02x)\n" , iface->bInterfaceSubClass, iface->bInterfaceProtocol); return -1; } + // Allocate drive structure. + struct usbdrive_s *udrive_g = malloc_fseg(sizeof(*udrive_g)); + if (!udrive_g) { + warn_noalloc(); + goto fail; + } + memset(udrive_g, 0, sizeof(*udrive_g)); + udrive_g->drive.type = DTYPE_USB; + // Find bulk in and bulk out endpoints. struct usb_endpoint_descriptor *indesc = findEndPointDesc( iface, imax, USB_ENDPOINT_XFER_BULK, USB_DIR_IN); @@ -193,59 +183,28 @@ usb_msc_init(u32 endp, struct usb_interface_descriptor *iface, int imax) iface, imax, USB_ENDPOINT_XFER_BULK, USB_DIR_OUT); if (!indesc || !outdesc) goto fail; - u32 inendp = mkendpFromDesc(endp, indesc); - struct usb_pipe *bulkin = alloc_bulk_pipe(inendp); - u32 outendp = mkendpFromDesc(endp, outdesc); - struct usb_pipe *bulkout = alloc_bulk_pipe(outendp); - if (!bulkin || !bulkout) + udrive_g->bulkin = alloc_bulk_pipe(pipe, indesc); + udrive_g->bulkout = alloc_bulk_pipe(pipe, outdesc); + if (!udrive_g->bulkin || !udrive_g->bulkout) goto fail; - // Allocate drive structure. - char *desc = malloc_tmphigh(MAXDESCSIZE); - struct usbdrive_s *udrive_g = malloc_fseg(sizeof(*udrive_g)); - if (!udrive_g || !desc) { - warn_noalloc(); - goto fail; - } - memset(udrive_g, 0, sizeof(*udrive_g)); - udrive_g->drive.type = DTYPE_USB; - udrive_g->bulkin = bulkin; - udrive_g->bulkout = bulkout; - - // Validate drive and find block size and sector count. - struct disk_op_s dop; - memset(&dop, 0, sizeof(dop)); - dop.drive_g = &udrive_g->drive; - struct cdbres_inquiry data; - int ret = cdb_get_inquiry(&dop, &data); + int ret, pdt; + char *desc = NULL; + ret = scsi_init_drive(&udrive_g->drive, "USB MSC", &pdt, &desc); if (ret) goto fail; - char vendor[sizeof(data.vendor)+1], product[sizeof(data.product)+1]; - char rev[sizeof(data.rev)+1]; - int pdt = data.pdt & 0x1f; - int removable = !!(data.removable & 0x80); - dprintf(1, "USB MSC vendor='%s' product='%s' rev='%s'" - " type=%d removable=%d\n" - , strtcpy(vendor, data.vendor, sizeof(vendor)) - , strtcpy(product, data.product, sizeof(product)) - , strtcpy(rev, data.rev, sizeof(rev)) - , pdt, removable); - udrive_g->drive.removable = removable; - - if (pdt == USB_MSC_TYPE_CDROM) - ret = setup_drive_cdrom(&dop); + + if (pdt == SCSI_TYPE_CDROM) + ret = setup_drive_cdrom(&udrive_g->drive, desc); else - ret = setup_drive_hd(&dop); + ret = setup_drive_hd(&udrive_g->drive, desc); + if (ret) goto fail; - snprintf(desc, MAXDESCSIZE, "USB Drive %s %s %s", vendor, product, rev); - udrive_g->drive.desc = desc; - return 0; fail: dprintf(1, "Unable to configure USB MSC device.\n"); - free(desc); free(udrive_g); return -1; }