blob: 887c97216db3a5bc3d9113a84215a82a99d62a9e [file] [log] [blame]
/* Driver for SCM Microsystems USB-ATAPI cable
*
* $Id: shuttle_usbat.c,v 1.17 2002/04/22 03:39:43 mdharm Exp $
*
* Current development and maintenance by:
* (c) 2000, 2001 Robert Baruch (autophile@starband.net)
*
* Developed with the assistance of:
* (c) 2002 Alan Stern <stern@rowland.org>
*
* Many originally ATAPI devices were slightly modified to meet the USB
* market by using some kind of translation from ATAPI to USB on the host,
* and the peripheral would translate from USB back to ATAPI.
*
* SCM Microsystems (www.scmmicro.com) makes a device, sold to OEM's only,
* which does the USB-to-ATAPI conversion. By obtaining the data sheet on
* their device under nondisclosure agreement, I have been able to write
* this driver for Linux.
*
* The chip used in the device can also be used for EPP and ISA translation
* as well. This driver is only guaranteed to work with the ATAPI
* translation.
*
* The only peripheral that I know of (as of 27 Mar 2001) that uses this
* device is the Hewlett-Packard 8200e/8210e/8230e CD-Writer Plus.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "transport.h"
#include "raw_bulk.h"
#include "protocol.h"
#include "usb.h"
#include "debug.h"
#include "shuttle_usbat.h"
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/slab.h>
#define short_pack(LSB,MSB) ( ((u16)(LSB)) | ( ((u16)(MSB))<<8 ) )
#define LSB_of(s) ((s)&0xFF)
#define MSB_of(s) ((s)>>8)
int transferred = 0;
int usbat_read(struct us_data *us,
unsigned char access,
unsigned char reg,
unsigned char *content) {
int result;
result = usb_stor_ctrl_transfer(us,
us->recv_ctrl_pipe,
access,
0xC0,
(u16)reg,
0,
content,
1);
return result;
}
int usbat_write(struct us_data *us,
unsigned char access,
unsigned char reg,
unsigned char content) {
int result;
result = usb_stor_ctrl_transfer(us,
us->send_ctrl_pipe,
access|0x01,
0x40,
short_pack(reg, content),
0,
NULL,
0);
return result;
}
int usbat_set_shuttle_features(struct us_data *us,
unsigned char external_trigger,
unsigned char epp_control,
unsigned char mask_byte,
unsigned char test_pattern,
unsigned char subcountH,
unsigned char subcountL) {
int result;
unsigned char command[8] = {
0x40, 0x81, epp_control, external_trigger,
test_pattern, mask_byte, subcountL, subcountH
};
result = usb_stor_ctrl_transfer(us,
us->send_ctrl_pipe,
0x80,
0x40,
0,
0,
command,
8);
return result;
}
int usbat_read_block(struct us_data *us,
unsigned char access,
unsigned char reg,
unsigned char *content,
unsigned short len,
int use_sg) {
int result;
unsigned char command[8] = {
0xC0, access|0x02, reg, 0x00, 0x00, 0x00,
LSB_of(len), MSB_of(len)
};
if (!len)
return USB_STOR_TRANSPORT_GOOD;
result = usb_stor_ctrl_transfer(us,
us->send_ctrl_pipe,
0x80,
0x40,
0,
0,
command,
8);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
result = usb_stor_bulk_transfer_sg(us, us->recv_bulk_pipe,
content, len, use_sg, NULL);
return (result == USB_STOR_XFER_GOOD ?
USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR);
}
/*
* Block, waiting for an ATA device to become not busy or to report
* an error condition.
*/
int usbat_wait_not_busy(struct us_data *us, int minutes) {
int i;
int result;
unsigned char status;
/* Synchronizing cache on a CDR could take a heck of a long time,
* but probably not more than 10 minutes or so. On the other hand,
* doing a full blank on a CDRW at speed 1 will take about 75
* minutes!
*/
for (i=0; i<1200+minutes*60; i++) {
result = usbat_read(us, USBAT_ATA, 0x17, &status);
if (result!=USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
if (status&0x01) { // check condition
result = usbat_read(us, USBAT_ATA, 0x10, &status);
return USB_STOR_TRANSPORT_FAILED;
}
if (status&0x20) // device fault
return USB_STOR_TRANSPORT_FAILED;
if ((status&0x80)==0x00) { // not busy
US_DEBUGP("Waited not busy for %d steps\n", i);
return USB_STOR_TRANSPORT_GOOD;
}
if (i<500)
wait_ms(10); // 5 seconds
else if (i<700)
wait_ms(50); // 10 seconds
else if (i<1200)
wait_ms(100); // 50 seconds
else
wait_ms(1000); // X minutes
}
US_DEBUGP("Waited not busy for %d minutes, timing out.\n",
minutes);
return USB_STOR_TRANSPORT_FAILED;
}
int usbat_write_block(struct us_data *us,
unsigned char access,
unsigned char reg,
unsigned char *content,
unsigned short len,
int use_sg,
int minutes) {
int result;
unsigned char command[8] = {
0x40, access|0x03, reg, 0x00, 0x00, 0x00,
LSB_of(len), MSB_of(len)
};
if (!len)
return USB_STOR_TRANSPORT_GOOD;
result = usb_stor_ctrl_transfer(us,
us->send_ctrl_pipe,
0x80,
0x40,
0,
0,
command,
8);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
result = usb_stor_bulk_transfer_sg(us, us->send_bulk_pipe,
content, len, use_sg, NULL);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
return usbat_wait_not_busy(us, minutes);
}
int usbat_rw_block_test(struct us_data *us,
unsigned char access,
unsigned char *registers,
unsigned char *data_out,
unsigned short num_registers,
unsigned char data_reg,
unsigned char status_reg,
unsigned char timeout,
unsigned char qualifier,
int direction,
unsigned char *content,
unsigned short len,
int use_sg,
int minutes) {
int result;
unsigned int pipe = (direction == SCSI_DATA_READ) ?
us->recv_bulk_pipe : us->send_bulk_pipe;
// Not really sure the 0x07, 0x17, 0xfc, 0xe7 is necessary here,
// but that's what came out of the trace every single time.
unsigned char command[16] = {
0x40, access|0x07, 0x07, 0x17, 0xfc, 0xe7,
LSB_of(num_registers*2), MSB_of(num_registers*2),
(direction==SCSI_DATA_WRITE ? 0x40 : 0xC0),
access|(direction==SCSI_DATA_WRITE ? 0x05 : 0x04),
data_reg, status_reg,
timeout, qualifier, LSB_of(len), MSB_of(len)
};
int i;
unsigned char data[num_registers*2];
unsigned char status;
for (i=0; i<num_registers; i++) {
data[i<<1] = registers[i];
data[1+(i<<1)] = data_out[i];
}
for (i=0; i<20; i++) {
/*
* The first time we send the full command, which consists
* of downloading the SCSI command followed by downloading
* the data via a write-and-test. Any other time we only
* send the command to download the data -- the SCSI command
* is still 'active' in some sense in the device.
*
* We're only going to try sending the data 10 times. After
* that, we just return a failure.
*/
result = usb_stor_ctrl_transfer(us,
us->send_ctrl_pipe,
0x80,
0x40,
0,
0,
(i==0 ? command : command+8),
(i==0 ? 16 : 8));
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
if (i==0) {
result = usb_stor_bulk_transfer_buf(us,
us->send_bulk_pipe,
data, num_registers*2, NULL);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
}
//US_DEBUGP("Transfer %s %d bytes, sg buffers %d\n",
// direction == SCSI_DATA_WRITE ? "out" : "in",
// len, use_sg);
result = usb_stor_bulk_transfer_sg(us,
pipe, content, len, use_sg, NULL);
/*
* If we get a stall on the bulk download, we'll retry
* the bulk download -- but not the SCSI command because
* in some sense the SCSI command is still 'active' and
* waiting for the data. Don't ask me why this should be;
* I'm only following what the Windoze driver did.
*
* Note that a stall for the test-and-read/write command means
* that the test failed. In this case we're testing to make
* sure that the device is error-free
* (i.e. bit 0 -- CHK -- of status is 0). The most likely
* hypothesis is that the USBAT chip somehow knows what
* the device will accept, but doesn't give the device any
* data until all data is received. Thus, the device would
* still be waiting for the first byte of data if a stall
* occurs, even if the stall implies that some data was
* transferred.
*/
if (result == USB_STOR_XFER_SHORT ||
result == USB_STOR_XFER_STALLED) {
/*
* If we're reading and we stalled, then clear
* the bulk output pipe only the first time.
*/
if (direction==SCSI_DATA_READ && i==0) {
if (usb_stor_clear_halt(us,
us->send_bulk_pipe) < 0)
return USB_STOR_TRANSPORT_ERROR;
}
/*
* Read status: is the device angry, or just busy?
*/
result = usbat_read(us, USBAT_ATA,
direction==SCSI_DATA_WRITE ? 0x17 : 0x0E,
&status);
if (result!=USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
if (status&0x01) // check condition
return USB_STOR_TRANSPORT_FAILED;
if (status&0x20) // device fault
return USB_STOR_TRANSPORT_FAILED;
US_DEBUGP("Redoing %s\n",
direction==SCSI_DATA_WRITE ? "write" : "read");
} else if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
else
return usbat_wait_not_busy(us, minutes);
}
US_DEBUGP("Bummer! %s bulk data 20 times failed.\n",
direction==SCSI_DATA_WRITE ? "Writing" : "Reading");
return USB_STOR_TRANSPORT_FAILED;
}
/*
* Write data to multiple registers at once. Not meant for large
* transfers of data!
*/
int usbat_multiple_write(struct us_data *us,
unsigned char access,
unsigned char *registers,
unsigned char *data_out,
unsigned short num_registers) {
int result;
unsigned char data[num_registers*2];
int i;
unsigned char command[8] = {
0x40, access|0x07, 0x00, 0x00, 0x00, 0x00,
LSB_of(num_registers*2), MSB_of(num_registers*2)
};
for (i=0; i<num_registers; i++) {
data[i<<1] = registers[i];
data[1+(i<<1)] = data_out[i];
}
result = usb_stor_ctrl_transfer(us,
us->send_ctrl_pipe,
0x80,
0x40,
0,
0,
command,
8);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
result = usb_stor_bulk_transfer_buf(us,
us->send_bulk_pipe, data, num_registers*2, NULL);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
return usbat_wait_not_busy(us, 0);
}
int usbat_read_user_io(struct us_data *us,
unsigned char *data_flags) {
int result;
result = usb_stor_ctrl_transfer(us,
us->recv_ctrl_pipe,
0x82,
0xC0,
0,
0,
data_flags,
1);
return result;
}
int usbat_write_user_io(struct us_data *us,
unsigned char enable_flags,
unsigned char data_flags) {
int result;
result = usb_stor_ctrl_transfer(us,
us->send_ctrl_pipe,
0x82,
0x40,
short_pack(enable_flags, data_flags),
0,
NULL,
0);
return result;
}
/*
* Squeeze a potentially huge (> 65535 byte) read10 command into
* a little ( <= 65535 byte) ATAPI pipe
*/
int usbat_handle_read10(struct us_data *us,
unsigned char *registers,
unsigned char *data,
Scsi_Cmnd *srb) {
int result = USB_STOR_TRANSPORT_GOOD;
unsigned char *buffer;
unsigned int len;
unsigned int sector;
struct scatterlist *sg = NULL;
int sg_segment = 0;
int sg_offset = 0;
US_DEBUGP("handle_read10: transfersize %d\n",
srb->transfersize);
if (srb->request_bufflen < 0x10000) {
result = usbat_rw_block_test(us, USBAT_ATA,
registers, data, 19,
0x10, 0x17, 0xFD, 0x30,
SCSI_DATA_READ,
srb->request_buffer,
srb->request_bufflen, srb->use_sg, 1);
return result;
}
/*
* Since we're requesting more data than we can handle in
* a single read command (max is 64k-1), we will perform
* multiple reads, but each read must be in multiples of
* a sector. Luckily the sector size is in srb->transfersize
* (see linux/drivers/scsi/sr.c).
*/
if (data[7+0] == GPCMD_READ_CD) {
len = short_pack(data[7+9], data[7+8]);
len <<= 16;
len |= data[7+7];
US_DEBUGP("handle_read10: GPCMD_READ_CD: len %d\n", len);
srb->transfersize = srb->request_bufflen/len;
}
if (!srb->transfersize) {
srb->transfersize = 2048; /* A guess */
US_DEBUGP("handle_read10: transfersize 0, forcing %d\n",
srb->transfersize);
}
len = (65535/srb->transfersize) * srb->transfersize;
US_DEBUGP("Max read is %d bytes\n", len);
buffer = kmalloc(len, GFP_NOIO);
if (buffer == NULL) // bloody hell!
return USB_STOR_TRANSPORT_FAILED;
sector = short_pack(data[7+3], data[7+2]);
sector <<= 16;
sector |= short_pack(data[7+5], data[7+4]);
transferred = 0;
if (srb->use_sg) {
sg = (struct scatterlist *)srb->request_buffer;
sg_segment = 0; // for keeping track of where we are in
sg_offset = 0; // the scatter/gather list
}
while (transferred != srb->request_bufflen) {
if (len > srb->request_bufflen - transferred)
len = srb->request_bufflen - transferred;
data[3] = len&0xFF; // (cylL) = expected length (L)
data[4] = (len>>8)&0xFF; // (cylH) = expected length (H)
// Fix up the SCSI command sector and num sectors
data[7+2] = MSB_of(sector>>16); // SCSI command sector
data[7+3] = LSB_of(sector>>16);
data[7+4] = MSB_of(sector&0xFFFF);
data[7+5] = LSB_of(sector&0xFFFF);
if (data[7+0] == GPCMD_READ_CD)
data[7+6] = 0;
data[7+7] = MSB_of(len / srb->transfersize); // SCSI command
data[7+8] = LSB_of(len / srb->transfersize); // num sectors
result = usbat_rw_block_test(us, USBAT_ATA,
registers, data, 19,
0x10, 0x17, 0xFD, 0x30,
SCSI_DATA_READ,
buffer,
len, 0, 1);
if (result != USB_STOR_TRANSPORT_GOOD)
break;
// Transfer the received data into the srb buffer
if (srb->use_sg)
us_copy_to_sgbuf(buffer, len, sg,
&sg_segment, &sg_offset, srb->use_sg);
else
memcpy(srb->request_buffer+transferred, buffer, len);
// Update the amount transferred and the sector number
transferred += len;
sector += len / srb->transfersize;
} // while transferred != srb->request_bufflen
kfree(buffer);
return result;
}
static int hp_8200e_select_and_test_registers(struct us_data *us) {
int selector;
unsigned char status;
// try device = master, then device = slave.
for (selector = 0xA0; selector <= 0xB0; selector += 0x10) {
if (usbat_write(us, USBAT_ATA, 0x16, selector) !=
USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
if (usbat_read(us, USBAT_ATA, 0x17, &status) !=
USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
if (usbat_read(us, USBAT_ATA, 0x16, &status) !=
USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
if (usbat_read(us, USBAT_ATA, 0x14, &status) !=
USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
if (usbat_read(us, USBAT_ATA, 0x15, &status) !=
USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
if (usbat_write(us, USBAT_ATA, 0x14, 0x55) !=
USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
if (usbat_write(us, USBAT_ATA, 0x15, 0xAA) !=
USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
if (usbat_read(us, USBAT_ATA, 0x14, &status) !=
USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
if (usbat_read(us, USBAT_ATA, 0x15, &status) !=
USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
}
return USB_STOR_TRANSPORT_GOOD;
}
int init_8200e(struct us_data *us) {
int result;
unsigned char status;
// Enable peripheral control signals
if (usbat_write_user_io(us,
USBAT_UIO_OE1 | USBAT_UIO_OE0,
USBAT_UIO_EPAD | USBAT_UIO_1) != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
US_DEBUGP("INIT 1\n");
wait_ms(2000);
if (usbat_read_user_io(us, &status) !=
USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
US_DEBUGP("INIT 2\n");
if (usbat_read_user_io(us, &status) !=
USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
US_DEBUGP("INIT 3\n");
// Reset peripheral, enable periph control signals
// (bring reset signal up)
if (usbat_write_user_io(us,
USBAT_UIO_DRVRST | USBAT_UIO_OE1 | USBAT_UIO_OE0,
USBAT_UIO_EPAD | USBAT_UIO_1) != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
US_DEBUGP("INIT 4\n");
// Enable periph control signals
// (bring reset signal down)
if (usbat_write_user_io(us,
USBAT_UIO_OE1 | USBAT_UIO_OE0,
USBAT_UIO_EPAD | USBAT_UIO_1) != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
US_DEBUGP("INIT 5\n");
wait_ms(250);
// Write 0x80 to ISA port 0x3F
if (usbat_write(us, USBAT_ISA, 0x3F, 0x80) !=
USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
US_DEBUGP("INIT 6\n");
// Read ISA port 0x27
if (usbat_read(us, USBAT_ISA, 0x27, &status) !=
USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
US_DEBUGP("INIT 7\n");
if (usbat_read_user_io(us, &status) !=
USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
US_DEBUGP("INIT 8\n");
if ( (result = hp_8200e_select_and_test_registers(us)) !=
USB_STOR_TRANSPORT_GOOD)
return result;
US_DEBUGP("INIT 9\n");
if (usbat_read_user_io(us, &status) !=
USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
US_DEBUGP("INIT 10\n");
// Enable periph control signals and card detect
if (usbat_write_user_io(us,
USBAT_UIO_ACKD |USBAT_UIO_OE1 | USBAT_UIO_OE0,
USBAT_UIO_EPAD | USBAT_UIO_1) != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
US_DEBUGP("INIT 11\n");
if (usbat_read_user_io(us, &status) !=
USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
US_DEBUGP("INIT 12\n");
wait_ms(1400);
if (usbat_read_user_io(us, &status) !=
USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
US_DEBUGP("INIT 13\n");
if ( (result = hp_8200e_select_and_test_registers(us)) !=
USB_STOR_TRANSPORT_GOOD)
return result;
US_DEBUGP("INIT 14\n");
if (usbat_set_shuttle_features(us,
0x83, 0x00, 0x88, 0x08, 0x15, 0x14) !=
USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
US_DEBUGP("INIT 15\n");
return USB_STOR_TRANSPORT_GOOD;
}
/*
* Transport for the HP 8200e
*/
int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us)
{
int result;
unsigned char status;
unsigned char registers[32];
unsigned char data[32];
unsigned int len;
int i;
char string[64];
len = srb->request_bufflen;
/* Send A0 (ATA PACKET COMMAND).
Note: I guess we're never going to get any of the ATA
commands... just ATA Packet Commands.
*/
registers[0] = 0x11;
registers[1] = 0x12;
registers[2] = 0x13;
registers[3] = 0x14;
registers[4] = 0x15;
registers[5] = 0x16;
registers[6] = 0x17;
data[0] = 0x00;
data[1] = 0x00;
data[2] = 0x00;
data[3] = len&0xFF; // (cylL) = expected length (L)
data[4] = (len>>8)&0xFF; // (cylH) = expected length (H)
data[5] = 0xB0; // (device sel) = slave
data[6] = 0xA0; // (command) = ATA PACKET COMMAND
for (i=7; i<19; i++) {
registers[i] = 0x10;
data[i] = (i-7 >= srb->cmd_len) ? 0 : srb->cmnd[i-7];
}
result = usbat_read(us, USBAT_ATA, 0x17, &status);
US_DEBUGP("Status = %02X\n", status);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
if (srb->cmnd[0] == TEST_UNIT_READY)
transferred = 0;
if (srb->sc_data_direction == SCSI_DATA_WRITE) {
result = usbat_rw_block_test(us, USBAT_ATA,
registers, data, 19,
0x10, 0x17, 0xFD, 0x30,
SCSI_DATA_WRITE,
srb->request_buffer,
len, srb->use_sg, 10);
if (result == USB_STOR_TRANSPORT_GOOD) {
transferred += len;
US_DEBUGP("Wrote %08X bytes\n", transferred);
}
return result;
} else if (srb->cmnd[0] == READ_10 ||
srb->cmnd[0] == GPCMD_READ_CD) {
return usbat_handle_read10(us, registers, data, srb);
}
if (len > 0xFFFF) {
US_DEBUGP("Error: len = %08X... what do I do now?\n",
len);
return USB_STOR_TRANSPORT_ERROR;
}
if ( (result = usbat_multiple_write(us,
USBAT_ATA,
registers, data, 7)) != USB_STOR_TRANSPORT_GOOD) {
return result;
}
// Write the 12-byte command header.
// If the command is BLANK then set the timer for 75 minutes.
// Otherwise set it for 10 minutes.
// NOTE: THE 8200 DOCUMENTATION STATES THAT BLANKING A CDRW
// AT SPEED 4 IS UNRELIABLE!!!
if ( (result = usbat_write_block(us,
USBAT_ATA, 0x10, srb->cmnd, 12, 0,
srb->cmnd[0]==GPCMD_BLANK ? 75 : 10)) !=
USB_STOR_TRANSPORT_GOOD) {
return result;
}
// If there is response data to be read in
// then do it here.
if (len != 0 && (srb->sc_data_direction == SCSI_DATA_READ)) {
// How many bytes to read in? Check cylL register
if (usbat_read(us, USBAT_ATA, 0x14, &status) !=
USB_STOR_XFER_GOOD) {
return USB_STOR_TRANSPORT_ERROR;
}
if (len > 0xFF) { // need to read cylH also
len = status;
if (usbat_read(us, USBAT_ATA, 0x15, &status) !=
USB_STOR_XFER_GOOD) {
return USB_STOR_TRANSPORT_ERROR;
}
len += ((unsigned int)status)<<8;
}
else
len = status;
result = usbat_read_block(us, USBAT_ATA, 0x10,
srb->request_buffer, len, srb->use_sg);
/* Debug-print the first 32 bytes of the transfer */
if (!srb->use_sg) {
string[0] = 0;
for (i=0; i<len && i<32; i++) {
sprintf(string+strlen(string), "%02X ",
((unsigned char *)srb->request_buffer)[i]);
if ((i%16)==15) {
US_DEBUGP("%s\n", string);
string[0] = 0;
}
}
if (string[0]!=0)
US_DEBUGP("%s\n", string);
}
}
return result;
}