patch-2.4.0-test6 linux/drivers/usb/storage/scm.c
Next file: linux/drivers/usb/storage/scm.h
Previous file: linux/drivers/usb/storage/protocol.h
Back to the patch index
Back to the overall index
- Lines: 1157
- Date:
Wed Dec 31 16:00:00 1969
- Orig file:
v2.4.0-test5/linux/drivers/usb/storage/scm.c
- Orig date:
Thu Jul 27 17:38:01 2000
diff -u --recursive --new-file v2.4.0-test5/linux/drivers/usb/storage/scm.c linux/drivers/usb/storage/scm.c
@@ -1,1156 +0,0 @@
-/* Driver for SCM Microsystems USB-ATAPI cable
- *
- * $Id: scm.c,v 1.4 2000/07/24 19:19:52 mdharm Exp $
- *
- * SCM driver v0.2:
- *
- * Removed any reference to maxlen for bulk transfers.
- * Changed scm_bulk_transport to allow for transfers without commands.
- * Changed hp8200e transport to use the request_bufflen field in the
- * SCSI command for the length of the transfer, rather than calculating
- * it ourselves based on the command.
- *
- * SCM driver v0.1:
- *
- * First release - hp8200e.
- *
- * Current development and maintainance by:
- * (c) 2000 Robert Baruch (autophile@dol.net)
- *
- * 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 peripherals that I know of (as of 14 Jul 2000) that uses this
- * device is the Hewlett-Packard 8200e 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 "protocol.h"
-#include "usb.h"
-#include "debug.h"
-#include "scm.h"
-
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/malloc.h>
-
-extern int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
- u8 request, u8 requesttype, u16 value, u16 index,
- void *data, u16 size);
-extern int usb_stor_bulk_msg(struct us_data *us, void *data, int pipe,
- unsigned int len, unsigned int *act_len);
-
-/*
- * Send a control message and wait for the response.
- *
- * us - the pointer to the us_data structure for the device to use
- *
- * request - the URB Setup Packet's first 6 bytes. The first byte always
- * corresponds to the request type, and the second byte always corresponds
- * to the request. The other 4 bytes do not correspond to value and index,
- * since they are used in a custom way by the SCM protocol.
- *
- * xfer_data - a buffer from which to get, or to which to store, any data
- * that gets send or received, respectively, with the URB. Even though
- * it looks like we allocate a buffer in this code for the data, xfer_data
- * must contain enough allocated space.
- *
- * xfer_len - the number of bytes to send or receive with the URB.
- *
- */
-
-static int scm_send_control(struct us_data *us,
- unsigned char command[8],
- unsigned char *xfer_data,
- unsigned int xfer_len) {
-
- int result;
- int pipe;
- void *buffer = NULL;
-
- command[6] = xfer_len&0xFF;
- command[7] = (xfer_len>>8)&0xFF;
-
- // Get the receive or send control pipe number, based on
- // the direction indicated by the request type.
-
- if (command[0] & USB_DIR_IN)
- pipe = usb_rcvctrlpipe(us->pusb_dev,0);
- else
- pipe = usb_sndctrlpipe(us->pusb_dev,0);
-
-
- // If data is going to be sent or received with the URB,
- // then allocate a buffer for it. If data is to be sent,
- // copy the data into the buffer.
-
- if (xfer_len > 0) {
- buffer = kmalloc(xfer_len, GFP_KERNEL);
- if (!(command[0] & USB_DIR_IN))
- memcpy(buffer, xfer_data, xfer_len);
- }
-
- // Send the URB to the device and wait for a response.
-
- /* Why are request and request type reversed in this call? */
-
- result = usb_stor_control_msg(us, pipe,
- command[1], command[0],
- (((unsigned short)command[3])<<8) | command[2],
- (((unsigned short)command[5])<<8) | command[3],
- buffer,
- xfer_len);
-
-
- // If data was sent or received with the URB, free the buffer we
- // allocated earlier, but not before reading the data out of the
- // buffer if we wanted to receive data.
-
- if (xfer_len > 0) {
- if (command[0] & USB_DIR_IN)
- memcpy(xfer_data, buffer, xfer_len);
- kfree(buffer);
- }
-
- // Check the return code for the command.
-
- if (result < 0) {
- /* a stall is a fatal condition from the device */
- if (result == -EPIPE) {
- US_DEBUGP("-- Stall on control pipe. Clearing\n");
- result = usb_clear_halt(us->pusb_dev, pipe);
- US_DEBUGP("-- usb_clear_halt() returns %d\n", result);
- return USB_STOR_TRANSPORT_FAILED;
- }
-
- /* Uh oh... serious problem here */
- return USB_STOR_TRANSPORT_ERROR;
- }
-
- return USB_STOR_TRANSPORT_GOOD;
-}
-
-static int scm_raw_bulk(struct us_data *us,
- int direction,
- unsigned char *data,
- unsigned short len) {
-
- int result;
- int act_len;
- int pipe;
-
- if (direction == SCSI_DATA_READ)
- pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
- else
- pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
-
- result = usb_stor_bulk_msg(us, data, pipe, len, &act_len);
-
- /* if we stall, we need to clear it before we go on */
- if (result == -EPIPE) {
- US_DEBUGP("EPIPE: clearing endpoint halt for"
- " pipe 0x%x, stalled at %d bytes\n",
- pipe, act_len);
- usb_clear_halt(us->pusb_dev, pipe);
- }
-
- if (result) {
-
- /* NAK - that means we've retried a few times already */
- if (result == -ETIMEDOUT) {
- US_DEBUGP("scm_raw_bulk():"
- " device NAKed\n");
- return US_BULK_TRANSFER_FAILED;
- }
-
- /* -ENOENT -- we canceled this transfer */
- if (result == -ENOENT) {
- US_DEBUGP("scm_raw_bulk():"
- " transfer aborted\n");
- return US_BULK_TRANSFER_ABORTED;
- }
-
- if (result == -EPIPE) {
- US_DEBUGP("scm_raw_bulk():"
- " output pipe stalled\n");
- return USB_STOR_TRANSPORT_FAILED;
- }
-
- /* the catch-all case */
- US_DEBUGP("us_transfer_partial(): unknown error\n");
- return US_BULK_TRANSFER_FAILED;
- }
-
- if (act_len != len) {
- US_DEBUGP("Warning: Transferred only %d bytes\n",
- act_len);
- return US_BULK_TRANSFER_SHORT;
- }
-
- US_DEBUGP("Transfered %d of %d bytes\n", act_len, len);
-
- return US_BULK_TRANSFER_GOOD;
-}
-
-/*
- * Note: direction must be set if command_len == 0.
- */
-
-static int scm_bulk_transport(struct us_data *us,
- unsigned char *command,
- unsigned short command_len,
- int direction,
- unsigned char *data,
- unsigned short len,
- int use_sg) {
-
- int result = USB_STOR_TRANSPORT_GOOD;
- int transferred = 0;
- unsigned char execute[8] = {
- 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
- int i;
- struct scatterlist *sg;
- char string[64];
-
- if (command_len != 0) {
-
- /* Fix up the command's data length */
-
- command[6] = len&0xFF;
- command[7] = (len>>8)&0xFF;
-
- result = scm_send_control(us,
- execute,
- command,
- command_len);
-
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
- }
-
- if (len==0)
- return USB_STOR_TRANSPORT_GOOD;
-
-
- /* transfer the data payload for the command, if there is any */
-
-
- if (command_len != 0)
- direction = (command[0]&0x80) ? SCSI_DATA_READ :
- SCSI_DATA_WRITE;
-
- if (direction == SCSI_DATA_WRITE) {
-
- /* Debug-print the first 48 bytes of the write transfer */
-
- if (!use_sg) {
- string[0] = 0;
- for (i=0; i<len && i<48; i++) {
- sprintf(string+strlen(string), "%02X ",
- data[i]);
- if ((i%16)==15) {
- US_DEBUGP("%s\n", string);
- string[0] = 0;
- }
- }
- if (string[0]!=0)
- US_DEBUGP("%s\n", string);
- }
- }
-
-
- US_DEBUGP("SCM data %s transfer %d sg buffers %d\n",
- ( direction==SCSI_DATA_READ ? "in" : "out"),
- len, use_sg);
-
- if (!use_sg)
- result = scm_raw_bulk(us, direction, data, len);
- else {
- sg = (struct scatterlist *)data;
- for (i=0; i<use_sg && transferred<len; i++) {
- result = scm_raw_bulk(us, direction,
- sg[i].address,
- len-transferred > sg[i].length ?
- sg[i].length : len-transferred);
- if (result!=US_BULK_TRANSFER_GOOD)
- break;
- transferred += sg[i].length;
- }
- }
-
- return result;
-}
-
-int scm_read(struct us_data *us,
- unsigned char access,
- unsigned char reg,
- unsigned char *content) {
-
- int result;
- unsigned char command[8] = {
- 0xC0, access, reg, 0x00, 0x00, 0x00, 0x00, 0x00
- };
-
- result = scm_send_control(us, command, content, 1);
-
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
-
- // US_DEBUGP("SCM: Reg %d -> %02X\n", reg, *content);
-
- return result;
-}
-
-int scm_write(struct us_data *us,
- unsigned char access,
- unsigned char reg,
- unsigned char content) {
-
- int result;
- unsigned char command[8] = {
- 0x40, access|0x01, reg, content, 0x00, 0x00, 0x00, 0x00
- };
-
- result = scm_send_control(us, command, NULL, 0);
-
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
-
- // US_DEBUGP("SCM: Reg %d <- %02X\n", reg, content);
-
- return result;
-}
-
-int scm_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 = scm_bulk_transport(us, command, 8, 0, NULL, 0, 0);
-
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
-
- return result;
-}
-
-int scm_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, 0x00, 0x00
- };
-
- result = scm_bulk_transport(us,
- command, 8, 0, content, len, use_sg);
-
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
-
- // US_DEBUGP("SCM: Read data, result %d\n", result);
-
- return result;
-}
-
-/*
- * Block, waiting for an ATA device to become not busy or to report
- * an error condition.
- */
-
-int scm_wait_not_busy(struct us_data *us) {
-
- 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 15 minutes or so */
-
- for (i=0; i<500; i++) {
- result = scm_read(us, SCM_ATA, 0x17, &status);
- US_DEBUGP("SCM: Write ATA data status is %02X\n", status);
- if (result!=USB_STOR_TRANSPORT_GOOD)
- return result;
- if (status&0x01) // check condition
- return USB_STOR_TRANSPORT_FAILED;
- if (status&0x20) // device fault
- return USB_STOR_TRANSPORT_FAILED;
- if ((status&0x80)!=0x80) // not busy
- break;
- if (i<5)
- wait_ms(100);
- else if (i<20)
- wait_ms(500);
- else if (i<49)
- wait_ms(1000);
- else if (i<499)
- wait_ms(2000);
- }
-
- if (i==500)
- return USB_STOR_TRANSPORT_FAILED;
-
- return USB_STOR_TRANSPORT_GOOD;
-}
-
-int scm_write_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] = {
- 0x40, access|0x03, reg, 0x00, 0x00, 0x00, 0x00, 0x00
- };
-
- result = scm_bulk_transport(us,
- command, 8, 0, content, len, use_sg);
-
- if (result!=USB_STOR_TRANSPORT_GOOD)
- return result;
-
- return scm_wait_not_busy(us);
-}
-
-int scm_write_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 qualifier,
- unsigned char timeout,
- unsigned char *content,
- unsigned short len,
- int use_sg) {
-
- int result;
- unsigned char command[16] = {
- 0x40, access|0x07, 0x07, 0x17, 0xfc, 0xe7, 0x00, 0x00,
- 0x40, access|0x05, data_reg, status_reg,
- qualifier, timeout, 0x00, 0x00
- };
- int i;
- unsigned char data[num_registers*2];
- int transferred;
- struct scatterlist *sg;
- char string[64];
-
- command[14] = len&0xFF;
- command[15] = (len>>8)&0xFF;
-
- for (i=0; i<num_registers; i++) {
- data[i<<1] = registers[i];
- data[1+(i<<1)] = data_out[i];
- }
-
- result = scm_bulk_transport(us,
- command, 16, 0, data, num_registers*2, 0);
-
- if (result!=USB_STOR_TRANSPORT_GOOD)
- return result;
-
- transferred = 0;
-
- US_DEBUGP("Transfer out %d bytes, sg buffers %d\n",
- len, use_sg);
-
- if (!use_sg) {
-
- /* Debug-print the first 48 bytes of the transfer */
-
- string[0] = 0;
- for (i=0; i<len && i<48; i++) {
- sprintf(string+strlen(string), "%02X ",
- content[i]);
- if ((i%16)==15) {
- US_DEBUGP("%s\n", string);
- string[0] = 0;
- }
- }
- if (string[0]!=0)
- US_DEBUGP("%s\n", string);
-
- result = scm_raw_bulk(us, SCSI_DATA_WRITE, content, len);
-
- } else {
-
- sg = (struct scatterlist *)content;
- for (i=0; i<use_sg && transferred<len; i++) {
- result = scm_raw_bulk(us, SCSI_DATA_WRITE,
- sg[i].address,
- len-transferred > sg[i].length ?
- sg[i].length : len-transferred);
- if (result!=US_BULK_TRANSFER_GOOD)
- break;
- transferred += sg[i].length;
- }
- }
-
- if (result!=USB_STOR_TRANSPORT_GOOD)
- return result;
-
- return scm_wait_not_busy(us);
-}
-
-int scm_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 cmd[8] = {
- 0x40, access|0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
-
- for (i=0; i<num_registers; i++) {
- data[i<<1] = registers[i];
- data[1+(i<<1)] = data_out[i];
- }
-
- result = scm_bulk_transport(us, cmd, 8, 0, data, num_registers*2, 0);
-
- if (result!=USB_STOR_TRANSPORT_GOOD)
- return result;
-
- return scm_wait_not_busy(us);
-}
-
-static int hp_8200e_select_and_test_registers(struct us_data *us) {
-
- int result;
- int selector;
- unsigned char status;
-
- // try device = master, then device = slave.
-
- for (selector = 0xA0; selector <= 0xB0; selector += 0x10) {
-
- if ( (result = scm_write(us, SCM_ATA, 0x16, selector)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- if ( (result = scm_read(us, SCM_ATA, 0x17, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- if ( (result = scm_read(us, SCM_ATA, 0x16, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- if ( (result = scm_read(us, SCM_ATA, 0x14, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- if ( (result = scm_read(us, SCM_ATA, 0x15, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- if ( (result = scm_write(us, SCM_ATA, 0x14, 0x55)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- if ( (result = scm_write(us, SCM_ATA, 0x15, 0xAA)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- if ( (result = scm_read(us, SCM_ATA, 0x14, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- if ( (result = scm_read(us, SCM_ATA, 0x15, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
- }
-
- return result;
-}
-
-int scm_read_user_io(struct us_data *us,
- unsigned char *data_flags) {
-
- unsigned char command[8] = {
- 0xC0, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
- int result;
-
- result = scm_send_control(us, command, data_flags, 1);
-
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
-
- // US_DEBUGP("SCM: User I/O flags -> %02X\n", *data_flags);
-
- return result;
-}
-
-int scm_write_user_io(struct us_data *us,
- unsigned char enable_flags,
- unsigned char data_flags) {
-
- unsigned char command[8] = {
- 0x40, 0x82, enable_flags, data_flags, 0x00, 0x00, 0x00, 0x00
- };
- int result;
-
- result = scm_send_control(us, command, NULL, 0);
-
- if (result != USB_STOR_TRANSPORT_GOOD)
- return result;
-
- // US_DEBUGP("SCM: User I/O flags <- %02X\n", data_flags);
-
- return result;
-}
-
-static int init_sddr09(struct us_data *us) {
-
- int result;
- unsigned char data[14];
- unsigned char command[8] = {
- 0xc1, 0x01, 0, 0, 0, 0, 0, 0
- };
- unsigned char command2[8] = {
- 0x41, 0, 0, 0, 0, 0, 0, 0
- };
- unsigned char tur[12] = {
- 0x03, 0x20, 0, 0, 0x0e, 0, 0, 0, 0, 0, 0, 0
- };
-
- if ( (result = scm_send_control(us, command, data, 2)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- US_DEBUGP("SDDR09: %02X %02X\n", data[0], data[1]);
-
- command[1] = 0x08;
-
- if ( (result = scm_send_control(us, command, data, 2)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- US_DEBUGP("SDDR09: %02X %02X\n", data[0], data[1]);
-/*
- if ( (result = scm_send_control(us, command2, tur, 12)) !=
- USB_STOR_TRANSPORT_GOOD) {
- US_DEBUGP("SDDR09: request sense failed\n");
- return result;
- }
-
- if ( (result = scm_raw_bulk(
- us, SCSI_DATA_READ, data, 14)) !=
- USB_STOR_TRANSPORT_GOOD) {
- US_DEBUGP("SDDR09: request sense bulk in failed\n");
- return result;
- }
-
- US_DEBUGP("SDDR09: request sense worked\n");
-*/
- return result;
-}
-
-static int init_8200e(struct us_data *us) {
-
- int result;
- unsigned char status;
-
- // Enable peripheral control signals
-
- if ( (result = scm_write_user_io(us,
- SCM_UIO_OE1 | SCM_UIO_OE0,
- SCM_UIO_EPAD | SCM_UIO_1)) != USB_STOR_TRANSPORT_GOOD)
- return result;
-
- wait_ms(2000);
-
- if ( (result = scm_read_user_io(us, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- if ( (result = scm_read_user_io(us, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- // Reset peripheral, enable periph control signals
- // (bring reset signal up)
-
- if ( (result = scm_write_user_io(us,
- SCM_UIO_DRVRST | SCM_UIO_OE1 | SCM_UIO_OE0,
- SCM_UIO_EPAD | SCM_UIO_1)) != USB_STOR_TRANSPORT_GOOD)
- return result;
-
- // Enable periph control signals
- // (bring reset signal down)
-
- if ( (result = scm_write_user_io(us,
- SCM_UIO_OE1 | SCM_UIO_OE0,
- SCM_UIO_EPAD | SCM_UIO_1)) != USB_STOR_TRANSPORT_GOOD)
- return result;
-
- wait_ms(250);
-
- // Write 0x80 to ISA port 0x3F
-
- if ( (result = scm_write(us, SCM_ISA, 0x3F, 0x80)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- // Read ISA port 0x27
-
- if ( (result = scm_read(us, SCM_ISA, 0x27, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- if ( (result = scm_read_user_io(us, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- if ( (result = hp_8200e_select_and_test_registers(us)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- if ( (result = scm_read_user_io(us, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- // Enable periph control signals and card detect
-
- if ( (result = scm_write_user_io(us,
- SCM_UIO_ACKD |SCM_UIO_OE1 | SCM_UIO_OE0,
- SCM_UIO_EPAD | SCM_UIO_1)) != USB_STOR_TRANSPORT_GOOD)
- return result;
-
- if ( (result = scm_read_user_io(us, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- wait_ms(1400);
-
- if ( (result = scm_read_user_io(us, &status)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- if ( (result = hp_8200e_select_and_test_registers(us)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- if ( (result = scm_set_shuttle_features(us,
- 0x83, 0x00, 0x88, 0x08, 0x15, 0x14)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
-
- return result;
-}
-
-/*
- * 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];
-
- /* This table tells us:
- X = command not supported
- L = return length in cmnd[4] (8 bits).
- H = return length in cmnd[7] and cmnd[8] (16 bits).
- D = return length in cmnd[6] to cmnd[9] (32 bits).
- B = return length/blocksize in cmnd[6] to cmnd[8].
- T = return length in cmnd[6] to cmnd[8] (24 bits).
- 0-9 = fixed return length
- W = 24 bytes
- h = return length/2048 in cmnd[7-8].
- */
-
- static char *lengths =
-
- /* 0123456789ABCDEF 0123456789ABCDEF */
-
- "0XXL0XXXXXXXXXXX" "XXLXXXXXXXX0XX0X" /* 00-1F */
- "XXXXX8XXhXH0XXX0" "XXXXX0XXXXXXXXXX" /* 20-3F */
- "XXHHL0X0XXH0XX0X" "XHH00HXX0TH0H0XX" /* 40-5F */
- "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* 60-7F */
- "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* 80-9F */
- "X0XXX0XXDXDXXXXX" "XXXXXXXXX000XHBX" /* A0-BF */
- "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* C0-DF */
- "XDXXXXXXXXXXXXXX" "XXW00HXXXXXXXXXX"; /* E0-FF */
-
- if (us->flags & US_FL_NEED_INIT) {
- US_DEBUGP("8200e: initializing\n");
- init_8200e(us);
- us->flags &= ~US_FL_NEED_INIT;
- }
-
- len = srb->request_bufflen;
-
-/* if (srb->sc_data_direction == SCSI_DATA_WRITE)
- len = srb->request_bufflen;
- else {
-
- switch (lengths[srb->cmnd[0]]) {
-
- case 'L':
- len = srb->cmnd[4];
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- len = lengths[srb->cmnd[0]]-'0';
- break;
- case 'H':
- len = (((unsigned int)srb->cmnd[7])<<8) | srb->cmnd[8];
- break;
- case 'h':
- len = (((unsigned int)srb->cmnd[7])<<8) | srb->cmnd[8];
- len <<= 11; // *2048
- break;
- case 'T':
- len = (((unsigned int)srb->cmnd[6])<<16) |
- (((unsigned int)srb->cmnd[7])<<8) |
- srb->cmnd[8];
- break;
- case 'D':
- len = (((unsigned int)srb->cmnd[6])<<24) |
- (((unsigned int)srb->cmnd[7])<<16) |
- (((unsigned int)srb->cmnd[8])<<8) |
- srb->cmnd[9];
- break;
- case 'W':
- len = 24;
- break;
- case 'B':
- // Let's try using the command structure's
- // request_bufflen here
- len = srb->request_bufflen;
- break;
- default:
- US_DEBUGP("Error: UNSUPPORTED COMMAND %02X\n",
- srb->cmnd[0]);
- return USB_STOR_TRANSPORT_ERROR;
- }
- } */
-
- if (len > 0xFFFF) {
- US_DEBUGP("Error: len = %08X... what do I do now?\n",
- len);
- return USB_STOR_TRANSPORT_ERROR;
- }
-
- // US_DEBUGP("XXXXXXXXXXXXXXXX req_bufflen %d, len %d, bufflen %d\n",
- // srb->request_bufflen, len, srb->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
-
- if (srb->sc_data_direction == SCSI_DATA_WRITE) {
-
- for (i=7; i<19; i++) {
- registers[i] = 0x10;
- data[i] = (i-7 >= srb->cmd_len) ? 0 : srb->cmnd[i-7];
- }
-
- result = scm_write_block_test(us, SCM_ATA,
- registers, data, 19,
- 0x10, 0x17, 0xFD, 0x30,
- srb->request_buffer,
- len, srb->use_sg);
-
- return result;
- }
-
- if ( (result = scm_multiple_write(us,
- SCM_ATA,
- registers, data, 7)) != USB_STOR_TRANSPORT_GOOD) {
- return result;
- }
-
- // Write the 12-byte command header.
-
- if ( (result = scm_write_block(us,
- SCM_ATA, 0x10, srb->cmnd, 12, 0)) !=
- 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 ( (result = scm_read(us, SCM_ATA, 0x14, &status)) !=
- USB_STOR_TRANSPORT_GOOD) {
- return result;
- }
-
- if (len>0xFF) { // need to read cylH also
- len = status;
- if ( (result = scm_read(us, SCM_ATA, 0x15, &status)) !=
- USB_STOR_TRANSPORT_GOOD) {
- return result;
- }
- len += ((unsigned int)status)<<8;
- }
- else
- len = status;
-
-
- result = scm_read_block(us, SCM_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);
- }
- }
-
- // US_DEBUGP("Command result %d\n", result);
-
- return result;
-}
-
-
-/*
- * Transport for the Sandisk SDDR-09
- */
-int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us)
-{
- int result;
- unsigned int len;
- unsigned char send_scsi_command[8] = {
- 0x41, 0, 0, 0, 0, 0, 0, 0
- };
- int i;
- char string[64];
- unsigned char *ptr;
- unsigned char inquiry_response[36] = {
- 0x00, 0x80, 0x00, 0x02, 0x1F, 0x00, 0x00, 0x00,
- 'S', 'a', 'n', 'D', 'i', 's', 'k', ' ',
- 'I', 'm', 'a', 'g', 'e', 'M', 'a', 't',
- 'e', ' ', 'S', 'D', 'D', 'R', '0', '9',
- ' ', ' ', ' ', ' '
- };
-
- /* This table tells us:
- X = command not supported
- L = return length in cmnd[4] (8 bits).
- H = return length in cmnd[7] and cmnd[8] (16 bits).
- D = return length in cmnd[6] to cmnd[9] (32 bits).
- B = return length/blocksize in cmnd[6] to cmnd[8].
- T = return length in cmnd[6] to cmnd[8] (24 bits).
- 0-9 = fixed return length
- W = 24 bytes
- h = return length/2048 in cmnd[7-8].
- */
-
- static char *lengths =
-
- /* 0123456789ABCDEF 0123456789ABCDEF */
-
- "0XXL0XXXXXXXXXXX" "XXLXXXXXXXX0XX0X" /* 00-1F */
- "XXXXX8XXhXH0XXX0" "XXXXX0XXXXXXXXXX" /* 20-3F */
- "XXHHL0X0XXH0XX0X" "XHH00HXX0TH0H0XX" /* 40-5F */
- "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* 60-7F */
- "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* 80-9F */
- "X0XXX0XXDXDXXXXX" "XXXXXXXXX000XHBX" /* A0-BF */
- "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* C0-DF */
- "XDXXXXXXXXXXXXXX" "XXW00HXXXXXXXXXX"; /* E0-FF */
-
- if (us->flags & US_FL_NEED_INIT) {
- US_DEBUGP("SDDR-09: initializing\n");
- init_sddr09(us);
- us->flags &= ~US_FL_NEED_INIT;
- }
-
- /* if (srb->sc_data_direction == SCSI_DATA_WRITE) */
- len = srb->request_bufflen;
- /* else {
-
- switch (lengths[srb->cmnd[0]]) {
-
- case 'L':
- len = srb->cmnd[4];
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- len = lengths[srb->cmnd[0]]-'0';
- break;
- case 'H':
- len = (((unsigned int)srb->cmnd[7])<<8) | srb->cmnd[8];
- break;
- case 'h':
- len = (((unsigned int)srb->cmnd[7])<<8) | srb->cmnd[8];
- len <<= 11; // *2048
- break;
- case 'T':
- len = (((unsigned int)srb->cmnd[6])<<16) |
- (((unsigned int)srb->cmnd[7])<<8) |
- srb->cmnd[8];
- break;
- case 'D':
- len = (((unsigned int)srb->cmnd[6])<<24) |
- (((unsigned int)srb->cmnd[7])<<16) |
- (((unsigned int)srb->cmnd[8])<<8) |
- srb->cmnd[9];
- break;
- case 'W':
- len = 24;
- break;
- case 'B':
- // Let's try using the command structure's
- // request_bufflen here
- len = srb->request_bufflen;
- break;
- default:
- US_DEBUGP("Error: UNSUPPORTED COMMAND %02X\n",
- srb->cmnd[0]);
- return USB_STOR_TRANSPORT_ERROR;
- }
- } */
-
- if (srb->request_bufflen > 0xFFFF) {
- US_DEBUGP("Error: len = %08X... what do I do now?\n",
- len);
- return USB_STOR_TRANSPORT_ERROR;
- }
-
- /* Dummy up a response for INQUIRY since SDDR09 doesn't
- respond to INQUIRY commands */
-
- if (srb->cmnd[0] == INQUIRY) {
- memcpy(srb->request_buffer, inquiry_response, 36);
- return USB_STOR_TRANSPORT_GOOD;
- }
-
- for (; srb->cmd_len<12; srb->cmd_len++)
- srb->cmnd[srb->cmd_len] = 0;
-
- srb->cmnd[1] = 0x20;
-
- string[0] = 0;
- for (i=0; i<12; i++)
- sprintf(string+strlen(string), "%02X ", srb->cmnd[i]);
-
- US_DEBUGP("SDDR09: Send control for command %s\n",
- string);
-
- if ( (result = scm_send_control(us, send_scsi_command,
- srb->cmnd, 12)) != USB_STOR_TRANSPORT_GOOD)
- return result;
-
- US_DEBUGP("SDDR09: Control for command OK\n");
-
- if (srb->sc_data_direction == SCSI_DATA_WRITE ||
- srb->sc_data_direction == SCSI_DATA_READ) {
-
- US_DEBUGP("SDDR09: %s %d bytes\n",
- srb->sc_data_direction==SCSI_DATA_WRITE ?
- "sending" : "receiving",
- len);
-
- result = scm_bulk_transport(us,
- NULL, 0, srb->sc_data_direction,
- srb->request_buffer,
- len, srb->use_sg);
-
- return result;
-
- }
-
- return result;
-}
-
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)