+/*
+ * Read the media capacity
+ */
+static int usbat_flash_get_sector_count(struct us_data *us,
+ struct usbat_info *info)
+{
+ unsigned char registers[3] = {
+ USBAT_ATA_SECCNT,
+ USBAT_ATA_DEVICE,
+ USBAT_ATA_CMD,
+ };
+ unsigned char command[3] = { 0x01, 0xA0, 0xEC };
+ unsigned char *reply;
+ unsigned char status;
+ int rc;
+
+ if (!us || !info)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ reply = kmalloc(512, GFP_NOIO);
+ if (!reply)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ /* ATA command : IDENTIFY DEVICE */
+ rc = usbat_multiple_write(us, registers, command, 3);
+ if (rc != USB_STOR_XFER_GOOD) {
+ US_DEBUGP("usbat_flash_get_sector_count: Gah! identify_device failed\n");
+ rc = USB_STOR_TRANSPORT_ERROR;
+ goto leave;
+ }
+
+ /* Read device status */
+ if (usbat_get_status(us, &status) != USB_STOR_XFER_GOOD) {
+ rc = USB_STOR_TRANSPORT_ERROR;
+ goto leave;
+ }
+
+ msleep(100);
+
+ /* Read the device identification data */
+ rc = usbat_read_block(us, reply, 512, 0);
+ if (rc != USB_STOR_TRANSPORT_GOOD)
+ goto leave;
+
+ info->sectors = ((u32)(reply[117]) << 24) |
+ ((u32)(reply[116]) << 16) |
+ ((u32)(reply[115]) << 8) |
+ ((u32)(reply[114]) );
+
+ rc = USB_STOR_TRANSPORT_GOOD;
+
+ leave:
+ kfree(reply);
+ return rc;
+}
+
+/*
+ * Read data from device
+ */
+static int usbat_flash_read_data(struct us_data *us,
+ struct usbat_info *info,
+ u32 sector,
+ u32 sectors)
+{
+ unsigned char registers[7] = {
+ USBAT_ATA_FEATURES,
+ USBAT_ATA_SECCNT,
+ USBAT_ATA_SECNUM,
+ USBAT_ATA_LBA_ME,
+ USBAT_ATA_LBA_HI,
+ USBAT_ATA_DEVICE,
+ USBAT_ATA_STATUS,
+ };
+ unsigned char command[7];
+ unsigned char *buffer;
+ unsigned char thistime;
+ unsigned int totallen, alloclen;
+ int len, result;
+ unsigned int sg_idx = 0, sg_offset = 0;
+
+ result = usbat_flash_check_media(us, info);
+ if (result != USB_STOR_TRANSPORT_GOOD)
+ return result;
+
+ /*
+ * we're working in LBA mode. according to the ATA spec,
+ * we can support up to 28-bit addressing. I don't know if Jumpshot
+ * supports beyond 24-bit addressing. It's kind of hard to test
+ * since it requires > 8GB CF card.
+ */
+
+ if (sector > 0x0FFFFFFF)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ totallen = sectors * info->ssize;
+
+ /*
+ * Since we don't read more than 64 KB at a time, we have to create
+ * a bounce buffer and move the data a piece at a time between the
+ * bounce buffer and the actual transfer buffer.
+ */
+
+ alloclen = min(totallen, 65536u);
+ buffer = kmalloc(alloclen, GFP_NOIO);
+ if (buffer == NULL)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ do {
+ /*
+ * loop, never allocate or transfer more than 64k at once
+ * (min(128k, 255*info->ssize) is the real limit)
+ */
+ len = min(totallen, alloclen);
+ thistime = (len / info->ssize) & 0xff;
+
+ /* ATA command 0x20 (READ SECTORS) */
+ usbat_pack_ata_sector_cmd(command, thistime, sector, 0x20);
+
+ /* Write/execute ATA read command */
+ result = usbat_multiple_write(us, registers, command, 7);
+ if (result != USB_STOR_TRANSPORT_GOOD)
+ goto leave;
+
+ /* Read the data we just requested */
+ result = usbat_read_blocks(us, buffer, len, 0);
+ if (result != USB_STOR_TRANSPORT_GOOD)
+ goto leave;
+
+ US_DEBUGP("usbat_flash_read_data: %d bytes\n", len);
+
+ /* Store the data in the transfer buffer */
+ usb_stor_access_xfer_buf(buffer, len, us->srb,
+ &sg_idx, &sg_offset, TO_XFER_BUF);
+
+ sector += thistime;
+ totallen -= len;
+ } while (totallen > 0);
+
+ kfree(buffer);
+ return USB_STOR_TRANSPORT_GOOD;
+
+leave:
+ kfree(buffer);
+ return USB_STOR_TRANSPORT_ERROR;
+}
+
+/*
+ * Write data to device
+ */
+static int usbat_flash_write_data(struct us_data *us,
+ struct usbat_info *info,
+ u32 sector,
+ u32 sectors)
+{
+ unsigned char registers[7] = {
+ USBAT_ATA_FEATURES,
+ USBAT_ATA_SECCNT,
+ USBAT_ATA_SECNUM,
+ USBAT_ATA_LBA_ME,
+ USBAT_ATA_LBA_HI,
+ USBAT_ATA_DEVICE,
+ USBAT_ATA_STATUS,
+ };
+ unsigned char command[7];
+ unsigned char *buffer;
+ unsigned char thistime;
+ unsigned int totallen, alloclen;
+ int len, result;
+ unsigned int sg_idx = 0, sg_offset = 0;
+
+ result = usbat_flash_check_media(us, info);
+ if (result != USB_STOR_TRANSPORT_GOOD)
+ return result;
+
+ /*
+ * we're working in LBA mode. according to the ATA spec,
+ * we can support up to 28-bit addressing. I don't know if the device
+ * supports beyond 24-bit addressing. It's kind of hard to test
+ * since it requires > 8GB media.
+ */
+
+ if (sector > 0x0FFFFFFF)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ totallen = sectors * info->ssize;
+
+ /*
+ * Since we don't write more than 64 KB at a time, we have to create
+ * a bounce buffer and move the data a piece at a time between the
+ * bounce buffer and the actual transfer buffer.
+ */
+
+ alloclen = min(totallen, 65536u);
+ buffer = kmalloc(alloclen, GFP_NOIO);
+ if (buffer == NULL)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ do {
+ /*
+ * loop, never allocate or transfer more than 64k at once
+ * (min(128k, 255*info->ssize) is the real limit)
+ */
+ len = min(totallen, alloclen);
+ thistime = (len / info->ssize) & 0xff;
+
+ /* Get the data from the transfer buffer */
+ usb_stor_access_xfer_buf(buffer, len, us->srb,
+ &sg_idx, &sg_offset, FROM_XFER_BUF);
+
+ /* ATA command 0x30 (WRITE SECTORS) */
+ usbat_pack_ata_sector_cmd(command, thistime, sector, 0x30);
+
+ /* Write/execute ATA write command */
+ result = usbat_multiple_write(us, registers, command, 7);
+ if (result != USB_STOR_TRANSPORT_GOOD)
+ goto leave;
+
+ /* Write the data */
+ result = usbat_write_blocks(us, buffer, len, 0);
+ if (result != USB_STOR_TRANSPORT_GOOD)
+ goto leave;
+
+ sector += thistime;
+ totallen -= len;
+ } while (totallen > 0);
+
+ kfree(buffer);
+ return result;
+
+leave:
+ kfree(buffer);
+ return USB_STOR_TRANSPORT_ERROR;
+}
+
+/*
+ * Squeeze a potentially huge (> 65535 byte) read10 command into
+ * a little ( <= 65535 byte) ATAPI pipe
+ */
+static int usbat_hp8200e_handle_read10(struct us_data *us,
+ unsigned char *registers,
+ unsigned char *data,
+ struct scsi_cmnd *srb)
+{
+ int result = USB_STOR_TRANSPORT_GOOD;
+ unsigned char *buffer;
+ unsigned int len;
+ unsigned int sector;
+ unsigned int sg_segment = 0;
+ unsigned int sg_offset = 0;
+
+ US_DEBUGP("handle_read10: transfersize %d\n",
+ srb->transfersize);
+
+ if (srb->request_bufflen < 0x10000) {
+
+ result = usbat_hp8200e_rw_block_test(us, USBAT_ATA,