Subject: Re: Linux and SCSI Date: Wed, 11 Dec 1991 16:41:04 MST From: drew@anchor.cs.colorado.edu
--------
>
> Date: Tue, 10 Dec 91 12:13:59 CST
> To: drew@hazelrah.cs.Colorado.EDU
> From: johnsonm@stolaf.edu (Michael K. Johnson)
> Subject: Re: Linux and SCSI (was: hd_reset fails in 0.11)
>
>
> Return-Path: johnsonm@stolaf.edu
> Status: RO
>
> --------------------------------------------------------------------
> I am just learning unix systems programming with linux, but I have
> a SCSI hard drive and a DTC adapter, and would be very willing to
> write the device dependent stuff for it when I get to that ability
> level if no one else has done it be then. I will be taking an OS
> class next semester (starting february) so I could even use this
> as a project. So although I can't do this right now, I would like
> it if you could put me on your list to get the information, which
> I can save and then hopefully work on when I am able.
>
> Thanks a lot!
>
> michaelkjohnson
>
> Date: Tue, 10 Dec 91 12:17:07 CST
> To: Linux-activists@joker.cs.hut.fi
> From: johnsonm@stolaf.edu (Michael K. Johnson)
> Subject: DTC SCSI controllers
>
>
> Return-Path: johnsonm@stolaf.edu
> Status: RO
>
> --------------------------------------------------------------------
>
> I have a DTC SCSI controller, and would be willing to (as I become a bit
> more proficient) write the low-level driver for it. However, there is
> a catch -- I will almost assuredly, due to my schedule, not be able to
> start till february or so. Sooooo, if anyone else wants to pick this
> up, feel free:-)
>
> If anyone needs to talk to them, I have voice and BBS numbers for their
> tech support.
>
> michaelkjohnson
> johnsonm@stolaf.edu
> I do not do .sig's
>
>
>
>
> Date: Tue, 10 Dec 91 13:04:50 PST
> To: Linux-activists@joker.cs.hut.fi, drew@hazelrah.cs.Colorado.EDU,
> kronvold@sumter.cso.uiuc.edu
> From: David Darknell <david@maxwell.ucsc.edu>
> Subject: Re: Linux and SCSI (was: hd_reset fails in 0.11)
>
>
> Return-Path: david@maxwell.UCSC.EDU
> Status: RO
>
> --------------------------------------------------------------------
> YES! I am trying to write a driver for a FastCache High performance
> SCSI controller (I used to have a ST-01/02) but I am in a catch 22:
> I cannot run Linux on the drive without a driver, but cannot write the
> driver without Linux. So here is my plan: Install MFM controller and
> 40Meg drive long enough to write the SCSI driver, then dump it. I
> would
> be happy to get anything you have that might make my job easier!
--------
You don't have to compile Linux under Linux.
Another possibility is cross compiling. If you have access to another
little endian machine <The DEC-MIPS architecture fits this bill>, LSB
first, cross compiling is as easy as doing a make gcc with target machine
set to some tm-i386 file.
Depending on how the host system is set up, you may be able to use the
native ld / ar - and even if not, it is no problem to compile the
gnu binutils and have gcc/gas use them.
Anyways, here's my hosts.h file, the generic interface to the lowlevel
host specific drivers. There isn't much too it - the point here was
to keep things SIMPLE, flexible, and 100% self configuring so we aren't
recompiling just to get SCSI support.
This is pretty firm - I have one idea I may / may not want to implement
that I'll talk about in the end.
-- cut here - hosts.h --
#ifndef __HOST_H__
#define __HOSTS_H__
/*
File hosts.h
SCSI host adapter include file.
*/
#define MAX_SCSI_HOSTS 1
/*
The Scsi_Host type has all that is needed to interface with a SCSI
host in a device independant matter.
*/
typedef struct
{
/*
The name pointer is a pointer to the name of the SCSI
device detected.
*/
char *name;
/*
The detect function shall return non zero on detection,
and initialize all data necessary for this particular
SCSI driver.
*/
int (* detect)(void);
/*
The info function will return whatever useful
information the developer sees fit.
*/
char * (* info)(void);
/*
The command function shall return the SCSI return
code in the low 8 bits, a driver error in the high 8
bits. Target is the target ID, IN normal numbers - not a
bit. The cmnd is the variable length command to
be sent,
buff a pointer to the buffer which will be read from /
written to, and bufflen the length of that buffer
*/
int (* command)(unsigned char target, const void *cmnd,
void *buff, int bufflen);
/*
present contains a flag as to weather we are present -
so we don't have to call detect multiple times.
*/
unsigned char present;
} Scsi_Host;
/*
The scsi_hosts array is the array containing the data for all
possible <supported> scsi hosts.
*/
extern Scsi_Host scsi_hosts[MAX_SCSI_HOSTS];
/*
scsi_init initializes the scsi hosts.
*/
void scsi_init(void);
#endif
-- end --
And, for our return codes, useful SCSI stuff, etc, we have
scsi.h
-- scsi.h cut here --
#ifndef __SCSI_H__
#define __SCSI_H__
/*
For documentation on the OPCODES, MESSAGES, and SENSE values,
please consult the SCSI standard.
*/
/*
SCSI opcodes
*/
#define TEST_UNIT_READY 0x00
#define REZERO_UNIT 0x01
#define REQUEST_SENSE 0x03
#define FORMAT_UNIT 0x04
#define REASSIGN_BLOCKS 0x07
#define READ_6 0x08
#define WRITE_6 0x0a
#define SEEK 0x0b
#define INQUIRY 0x12
#define MODE_SELECT 0x15
#define RESERVE 0x16
#define RELEASE 0x17
#define COPY 0x18
#define MODE_SENSE 0x1a
#define START_STOP 0x1b
#define RECIEVE_DAIGNOSTIC 0x1c
#define SEND_DIAGNOSTIC 0x1d
#define ALLOW_MEDIUM_REMOVAL 0x1e
#define READ_CAPACITY 0x25
#define READ_10 0x28
#define WRITE_10 0x2a
#define SEEK_10 0x2b
#define WRITE_VERIFY 0x2e
#define VERIFY 0x2f
#define SEARCH_HIGH 0x30
#define SEARCH_EQUAL 0x31
#define SEARCH_LOW 0x32
#define SET_LIMITS 0x33
#define COMPARE 0x39
#define COPY_VERIFY 0x3a
/*
MESSAGE CODES
*/
#define COMMAND_COMPLETE 0x00
#define EXTENDED_MESSAGE 0x01
#define SAVE_POINTERS 0x02
#define RESTORE_POINTERS 0x03
#define DISCONNECT 0x04
#define INITIATOR_ERROR 0x05
#define ABORT 0x06
#define MESAGE_REJECT 0x07
#define NOP 0x08
#define MSG_PARITY_ERROR 0x09
#define LINKED_CMD_COMPLETE 0x0a
#define LINKED_FLG_CMD_COMPLETE 0x0b
#define BUS_DEVICE_RESET 0x0c
#define IDENTIFY 0x80
/*
Our errors returned by OUR driver, NOT SCSI message. Orr'd with
SCSI message passed back to driver <IF any>.
*/
/* NO error */
#define DID_OK 0x0000
/* Couldn't connect before timeout period */
#define DID_NO_CONNECT 0x0100
/* BUS stayed busy through time out period */
#define DID_BUS_BUSY 0x0200
/* TIMED OUT for other reason */
#define DID_TIME_OUT 0x0300
/* ERROR from TARGET */
#define DID_TERROR 0x0400
/* TARGET was busy */
#define DID_TBUSY 0x0500
/* TARGET disconnected prematurely */
#define DID_TDISCONNECT 0x0600
/* TARGET was off line */
#define DID_TOFFLINE 0x0700
/* TARGET wants US to send IT a message */
#defibe DID_TREQ_MSG_OUT 0x0800
/* TARGET parity error */
#define DID_TPARITY 0x0900
/* TARGET requested reselect */
#define DID_TRESELECT 0x0A00
/* TARGET was not in the range 0-6 inlclusive */
#define DID_BAD_TARGET 0x0B00
/*
SENSE KEYS
*/
#define NO_SENSE 0x00
#define RECOVERED_ERROR 0x01
#define NOT_READY 0x02
#define MEDIUM_ERROR 0x03
#define HARDWARE_ERROR 0x04
#define ILLEGAL_REQUEST 0x05
#define UNIT_ATTENTION 0x06
#define DATA_PROTECT 0x07
#define BLANK_CHECK 0x08
#define COPY_ABORTED 0x0a
#define ABORTED_COMMAND 0x0b
#define VOLUME_OVERFLOW 0x0d
#define MISCOMPARE 0x0e
/*
DEVICE TYPES
*/
#define TYPE_DISK 0x00
#define TYPE_TAPE 0x01
#define TYPE_WORM 0x04 /* Treated as ROM by our system */
#define TYPE_ROM 0x05
#define TYPE_NO_LUN 0x7f
/*
Every SCSI command starts with a one byte OP-code.
The next byte's high three bits are the LUN of the
device. Any multi-byte quantities are stored high byte
first, and may have a 5 bit MSB in the same byte
as the LUN.
*/
#endif
-- end --
I'll divert work from the low level routines <real pain> to the high &
mid level routines to have something to pass around for when people start
getting other low level drivers done.
I *REALLY* like the above interface in terms of meeting the design
criteria of simplicity, independance of the host-specific code,
and the ability for the routines to configure automatically.
The finaly interface will be almost identical to what is there now.
However, it might also be nice to be able to queue commands for use
with interrupt driven SCSI hosts that can function without the
computer controlling everything-
We may want to add a que_command call that will add a command to an internal
queue in the host specific driver. This would be something like the
command function, only it would also take a pointer to a routine
that was called on completion, like
int (*queue_command)(unsigned char target, const void *cmd,
void *buff, int bufflen, void (*complete)(int host,
int serial_no, int cmd_return));
Where it returns the serial number of the queued command, and calls the
complete function on termination <this would be called from an interrupt
service routine> with the SCSI message / return code , host # <from array>
and serial number of the command that terminated.
Other solicitations for opinions
1. Other peoples opinions on when to remap
2. What we want to do about sector sizes that are not 512 bytes
3. Currently, I use only 10 byte read/writes in my disk / tape drivers.
The rationale behind this is that 10 byte commands fall in the
same compliance level as INQUIRY and READ CAPACITY commmands,
and presumably a drive would have all.
Is this a valid ssumption? Does anybody see a reason for
me to bloat the code and check for 10 byte commmand failure,
and implement the 6 byte read/write if so?