SCSIBios V1.0 for the Atari computer
SCSIBios V1.0
(c) 1991 by Oliver Groeger
Graf-Konrad-Str. 25
8000 Muenchen 40
Contents:
- Intro
- Disclaimer
- Check the System for SCSIBios
- Functions Provided By SCSIBios
- 4.1. Common Functions
- 4.1.1 SCSIVersion
- 4.1.2 SetTimeout
- 4.2. Common SCSI Functions
- 4.2.1 Inquiry
- 4.2.2 MSelect
- 4.2.3 MSense
- 4.2.4 ReqSense
- 4.2.5 TestUnit
- 4.3. Harddisk SCSI Commands
- 4.3.1 HDCapacity
- 4.3.2 HDCopy
- 4.3.3 HDDefect
- 4.3.4 HDFormat
- 4.3.5 HDRead
- 4.3.6 HDReleas
- 4.3.7 HDReserv
- 4.3.8 HDStart
- 4.3.9 HDStop
- 4.3.10 HDWrite
- 4.4. Streamer SCSI Commands
- 4.4.1 STAppend
- 4.4.2 STErase
- 4.4.3 STLock
- 4.4.4 STPrewind
- 4.4.5 STRead
- 4.4.6 STReqAux
- 4.4.7 STRewind
- 4.4.8 STSkip
- 4.4.9 STUnlock
- 4.4.10 STWFileM
- 4.4.11 STWrite
1. Intro:
SCSIBios is an extension to the operating system of the ATARI ST, STE and TT series. It installs a new XBios handler and than waits until it will be requested by special adaptec user application. SCSIBios provides a means to handle every I/O with the ACSI and SCSI interface of ATARI Computers.
You may copy this extension freely, but the following files must be included in the copied material and no copyright notes may be changed:
- SCSIBIOS.PRG (The OS Extension for the AUTO-Folder)
- SCSIBIOS.TXT (The documentation you're just reading)
- SCSIBIOS.LIB (Binding-Library for Turbo-C V2.x)
- SCSIBIOS.H (Header to be included in your programs)
- MSCSI.C (Demonstration source for SCSIBios)
- MSCSI.PRG (Executable program of demo source)
- MSCSI.PRJ (Project file for demo program)
If you use SCSIBios frequently in you programs and/or you want to distribute SCSIBios and/or programs using SCSIBios for commercial purposes I recommend you to send me a demonstrational copy of your program and DM50,-- for the use of SCSIBios.
2. Disclaimer:
SCSIBios V1.0 is tested in certain programs and a command line inter- preter. Until now there have been no errors found. I will not take any responsilities for SCSIBios damaging any soft- or hardware. It is in the responsibility of anyone using SCSIBios to take care of his equipment.
3. Check the System for SCSIBios:
There are two ways to check if SCSIBios is installed in the system:
- a) SCSIBios installs a cookie in the cookie jar name 'SCSI'. The value of the cookie is the version of SCSIBios which is installed. The High-Word contains the major version number and the Low-Word contains the minor version number.
- b) If no cookie jar is present you may find SCSIBios by checking the exception vector #46 (XBios Trap handler) of your system. If SCSIBios is installed, you will find an 'XBRA' protocol right in front of the code pointed to by the exception vector. You can check for SCSIBios using the following code:
CheckBios:
move.l #-1, -(sp) ; Get exception vector #46
move.w #46, -(sp)
move.w #5, -(sp) ; Setexc
trap #$D
addq.l #8, SP ; clear stack
movea.l D0, A0 ; check if SCSIBios is
cmpi.l #'SCSI', -8(A0) ; already resident
beq.b ishere
clr.l D0
ishere: rts
This function returns in D0 a value not equal to zero if SCSIBios is installed.
4. Functions Provided By SCSIBios:
In the descripton of the funtion below the parameter 'pdev' is used in two ways. On ATARI ST and STE computer it represents the physical unit number to be accessed. On the ATARI TT computers 'pdev' ranging from 0 to 7 represent the ACSI-devices and 'pdev' ranging from 8 to 15 re- present the SCSI-Devices.
If you ty to access units in the TT-DMA range without running on a TT the function result will always be -1 (0xff)
This function-description is not ment to replace a complete SCSI documentation you will always have to refer to your unit data guide to get the correct parameters and to knoe how those commands are used.
4.1. Common Functions
4.1.1 SCSIVersion
Name >Get SCSIBios Version< - Return version number of SCSIBios
Definition #include <scsibios.h> long SCSIVersion(void);
Description This function returns a long value containing the version number of the installed SCSIBios. It might be useful to check this version numbers if some later releases are containing more functions.
Result The High-Word contains the major version number and the Low-Word contains the minor version number.
4.1.2 SetTimeout
Name >Get/Set Timeouts< - Get/Set the Timeouts in SCSIBios
Definition #include <scsibios.h>
SCSI_TIMEOUT *SetTimeout(SCSI_TIMEOUT *scsi_timeout);
Description This function sets the internal timeouts used in SCSIBios. As a function result you will receive a copy of the internal timeout-structure. Don't try to change the time- outs by changing the values pointed to by the structure. It is only a copy! The times specified in this struct are in 200Hz cycles according to the internal system counter. 'scsi_timeout' is a pointer to a struct looking as follows:
typedef struct
{
ULONG BeforeCommand;
ULONG AfterCommand;
ULONG ShortTimeout;
ULONG LongTimeout;
ULONG Wait4IRQ;
ULONG XtraShortTimeout;
ULONG CommandDelay;
} SCSI_TIMEOUT;
- 'BeforeCommand' is waited before sending the command. This time is additional to 'CommandDelay'. Preset is 20UL (25ms).
- 'AfterCommand' is waited after sending the command. This time is additional to 'CommandDelay'. Preset is 20UL (25ms).
- 'ShortTimeout' is used as the time to wait for response by the attached unit. It is used for commands like Inquiry. Preset is 60000UL (30s).
- 'LongTimeout' is used as the time to wait for response by the attached unit. It is used for commands like HDRead or HDWrite. Preset is 120000UL (60s).
- 'Wait4IRQ' is used as the time to wait for response by the attached unit. It is used for special long timing commands like HDFormat. Preset is 2400000UL (20min).
- 'XtraShortTimeout' is used as the time to wait for response by the attached unit. It is used for commands like TestUnit. Preset is 50UL (250ms).
- 'CommandDelay' is used as the time to pass by between sending two commands to the Unit. This timeout is necessary on TT and STE computers, because they are that fast that mose units are totaly confused.
You can get the SCSIBios timeouts without setting any new ones by passing -1L as 'scsi_timeout'.
Result This function returns a copy of the internal timeouts.
4.2. Common SCSI Functions
4.2.1 Inquiry
Name >Inquiry< - Get vendor and unit information
Definition #include <scsibios.h>
int Inquiry(int pdev, int ldev, int bytes, char *buf);
Description Inquiry is used to get information about the connected units.
- 'pdev' is the physical ID of the desired unit and
- 'ldev' the logical one. Usually ldev will be 0.
- 'bytes' indicates the number of bytes to be transferred and 'buf' is the location where the gained information will be stored.
Result Inquiry will return 0 is no error occured and a value non zero if the command failed.
4.2.2 MSelect
Name >Mode Select< - Set drive geometry and default values
Definition #include <scsibios.h>
int MSelect(int pdev, int ldev, int bytes, char *buf);
Description The Mode Select command allows the you to specify device parameters to the drive.
- 'pdev' is the physical ID of the desired unit and 'ldev' is the logical one. Usually 'ldev' will be 0.
- 'bytes' indiactes the number of bytes to be transferred and 'buf' is a pointer to the data hloding buffer.
Result MSelect will return 0 is no error occured and a value non zero if the command failed.
4.2.3 MSense
Name >Mode Sense< - Get drive geometry and default values
Definition #include <scsibios.h>
int MSense(int pdev, int ldev, int page, int bytes, char *buf);
Description The Mode Sense command allows the you to read device parameters from the drive.
- 'pdev' is the physical ID of the desired unit and 'ldev' is the logical one. Usually 'ldev' will be 0.
- 'bytes' indicates the number of bytes to be transferred and 'buf' is a pointer to the buffer which will contain the data. 'page' defines which information should be transferred.
Result MSense will return 0 is no error occured and a value non zero if the command failed.
4.2.4 ReqSense
Name >Request Sense< - Get information about last ocurred error
Definition #include <scsibios.h>
int ReqSense(int pdev, int ldev, int bytes, char *buf);
Description The ReqSense command reads information about the last occurred error on the sepcifier unit. If no error occurred, ReqSense will transferre an empty buffer.
- 'pdev' is the physical ID of the desired unit and 'ldev' is the logical one. Usually 'ldev' will be 0.
- 'bytes' indiactes the number of bytes to be transferred and 'buf' is a pointer to the buffer which will contain the data.
Result ReqSense will return 0 is no error occured and a value non zero if the command failed.
4.2.5 TestUnit
Name >Test Unit Ready< - See if a unit is ready for operation
Definition #include <scsibios.h>
int TestUnit(int pdev, int ldev);
Description The TestUnit command test a unit to be ready for operation.
- 'pdev' is the physical ID of the desired unit and 'ldev' is the logical one. Usually 'ldev' will be 0. See your SCSI-Manual for detailed information about the return values.
Result TestUnit will return 0 if the unit is ready to perform or any other value received by the unit.
4.3. Harddisk SCSI Commands
4.3.1 HDCapacity
Name >Read Capacity< - Get capacity of harddisk drive
Definition #include <scsibios.h>
int HDCapacity(int pdev, int ldev, int iface, char *buf);
Description The HDCapacity command gets the capacity in number of blocks which can be used for data storage.
- 'pdev' is the physical ID of the desired unit and 'ldev' is the logical one. Usually 'ldev' will be 0.
- 'bytes' indiactes the number of bytes to be transferred and 'buf' is a pointer to the buffer which will contain the data.
- 'iface' is the physical unit number of a connected 'STATUS'-SCSI-Interface. On TT-Computers 'iface' should be set to zero.
Result HDCapacity will return 0 is no error occured and a value non zero if the command failed.
Note: Do not use this function if you have no 'STATUS'-Interface in use and you are working with an ST/STE Computer.
Otherwise this function will not perform properly or may damage data.
4.3.2 HDCopy
Name >Copy Data< - Get capacity of harddisk drive
Definition #include <scsibios.h>
int HDCopy(int pdev, int ldev, long length, char *buf, int erase);
Description The HDCopy commands copies data from one unit to another.
- 'pdev' and 'ldev' specify the unit to perform the command.
- 'buf' contains infoermation data for the command.
- 'erase' is the corresponding bit in the command descriptor block.
Result HDCOpy will return 0 if no error occured and a value non zero if the command failed.
Note: This function will only work on TT-Computers, because it is using a re-connection phase which recommends full SCSI-standards.
4.3.3 HDDefect
Name >Read Defect Data< - Get unit defect sector information
Definition #include <scsibios.h>
int HDDefect(int pdev, int ldev, int iface, int fmt, int bytes, char *buf);
Description The HDDefect command is used to read the defect information of a physical unit.
- 'pdev' is the physical ID of the desired unit and 'ldev' is the logical one. Usually 'ldev' will be 0.
- 'bytes' indiactes the number of bytes to be transferred and 'buf' is a pointer to the buffer which will contain the data.
- 'fmt' represents byte 3 of the command descriptor block. It is passed to the unit as you pass it to the function.
- 'iface' is the physical unit number of a connected 'STATUS'-SCSI-Interface. On TT-Computers 'iface' should be set to zero.
Result HDDefect will return 0 is no error occured and a value non zero if the command failed.
Note: Do not use this function if you have no 'STATUS'-Interface in use and you are working with an ST/STE Computer.
Otherwise this function will not perform properly or may damage data.
4.3.4 HDFormat
Name >Format Unit< - Format the entire unit
Definition #include <scsibios.h>
int HDFormat(int pdev, int ldev, int interleave);
Description The HDFormat command is used to format an entire unit to prepare it for operation.
- 'pdev' is the physical ID of the desired unit and 'ldev' is the logical one. Usually 'ldev' will be 0.
- 'bytes' indiactes the number of bytes to be transferred and 'buf' is a pointer to the buffer which will contain the data.
- 'interleeave' is the interleave factor for the hard disk drive.
Result HDFormat will return 0 if no error occured and a value non zero if the command failed.
4.3.5 HDRead
Name >Read< - Read sectors from a unit
Definition #include <scsibios.h>
int HDRead(int pdev, int ldev, long start, long count, char *buf);
Description The HDRead command is used to read sectors from a unit. Usually you can't transfere more than 127 sectors via ST/STE DMA bus. We have solved this problem an are splitting the reading accesses to 127 boundaries.
- 'pdev' is the physical ID of the desired unit and 'ldev' is the logical one. Usually 'ldev' will be 0.
- 'start' describes the starting sector for reading.
- 'count' specifies the number of sectors(!!) to be read.
- 'buf' is a pointer to the buffer which will contain the data.
Result HDRead will return 0 if no error occured and a value non zero if the command failed.
4.3.6 HDReleas
Name >Release unit< - release a previously reserved unit
Definition #include <scsibios.h>
int HDReleas(int pdev, int ldev);
Description The HDRelease command will release a unit from exclusive use by one initiator. This command will usually not be used on ATARI computer due to the non-interlaced bus system.
- 'pdev' is the physical ID of the desired unit and 'ldev' is the logical one. Usually 'ldev' will be 0.
Result HDRelease will return 0 if no error occured and a value non zero if the command failed.
4.3.7 HDReserv
Name >Reserve unit< - reserve a unit for exclusive use
Definition #include <scsibios.h>
int HDReserv(int pdev, int ldev);
Description The HDReserv command will reserve a unit for exclusive use by one initiator. This command will usually not be used on ATARI computer due to the non-interlaced bus system.
- 'pdev' is the physical ID of the desired unit and 'ldev' is the logical one. Usually 'ldev' will be 0.
Result HDReserve will return 0 if no error occured and a value non zero if the command failed.
4.3.8 HDStart
Name >Start unit< - Enable a unit for operation
Definition #include <scsibios.h>
int HDStart(int pdev, int ldev);
Description The HDStart command enables a unit for operation.
On some units this might be neccessary, if the spin up phse is not initiated alone.
- 'pdev' is the physical ID of the desired unit and 'ldev' is the logical one. Usually 'ldev' will be 0.
Result HDStart will return 0 if no error occured and a value non zero if the command failed.
4.3.9 HDStop
Name >Stop unit< - Disable a unit
Definition #include <scsibios.h>
int HDStop(int pdev, int ldev, int eject);
Description The HDStop command enables you to park a unit.
If the unit has got a removeable medium, you may also eject it.
- 'pdev' is the physical ID of the desired unit and 'ldev' is the logical one. Usually 'ldev' will be 0.
If 'eject' is 1 (TRUE) the inserted medium will be released and ejected. If the Hard Disk Drive has no removeable medium the parameter should be set zero.
Result HDStop will return 0 if no error occured and a value non zero if the command failed.
4.3.10 HDWrite
Name >Write< - Write sectors to a unit
Definition #include <scsibios.h>
int HDWrite(int pdev, int ldev, long start, long count, char *buf);
Description The HDWrite command is used to write sectors to a unit.
Usually you can't transfere more than 127 sectors via ST/STE DMA bus. We have solved this problem an are splitting the writing accesses to 127 boundaries.
- 'pdev' is the physical ID of the desired unit and 'ldev' is the logical one. Usually 'ldev' will be 0.
- 'start' describes the starting sector for writing.
- 'count' specifies the number of sectors(!!) to be written.
- 'buf' is a pointer to the buffer which will contain the data.
Result HDWrite will return 0 if no error occured and a value non zero if the command failed.
4.4. Streamer SCSI Commands
4.4.1 STAppend
Name >Append Data< - prewind to end of data
Definition #include <scsibios.h>
int STAppend(int pdev, int ldev);
Description The STAppend command prewinds until the end of written information is reached.
- 'pdev' is the physical ID of the desired unit and 'ldev' is the logical one. Usually 'ldev' will be 0.
Result STAppend will return 0 if no error occured and a value non zero if the command failed.
4.4.2 STErase
Name >Erase Tape< - Erase information on a tape
Definition #include <scsibios.h>
int STErase(int pdev, int ldev, int async);
Description The STErase command erases a whole tape by writing initial data to it.
- 'pdev' is the physical ID of the desired unit and 'ldev' is the logical one. Usually 'ldev' will be 0.
An 'async' value of 1 indicates that the operation will be done in the background and the computer gains control again at once. In any other cases this value should be set to zero.
Result STErase will return 0 if no error occured and a value non zero if the command failed.
4.4.3 STLock
Name >Lock Tape< - Lock the tape inside the streamer
Definition #include <scsibios.h>
int STLock(int pdev, int ldev);
Description The STLock command causes the tape inside the streamer to be locked.
- 'pdev' is the physical ID of the desired unit and 'ldev' is the logical one. Usually 'ldev' will be 0.
Result STLock will return 0 if no error occured and a value non zero if the command failed.
4.4.4 STPrewind
Name >Prewind Tape< - prewind the tape to its end
Definition #include <scsibios.h>
int STPrewind(int pdev, int ldev, int async);
Description The STPrewind command causes streamer to prewind the tape.
- 'pdev' is the physical ID of the desired unit and 'ldev' is the logical one. Usually 'ldev' will be 0.
An 'async' value of 1 indicates that the operation will be done in the background and the computer gains control again at once. In any other cases this value should be set to zero.
Result STPrewind will return 0 if no error occured and a value non zero if the command failed.
4.4.5 STRead
Name >Read< - Read sectors from the tape
Definition #include <scsibios.h>
int STRead(int pdev, int ldev, long count, char *buf);
Description The STRead command is used to read sectors from a unit.
Usually you can't transfere more than 127 sectors via ST/STE DMA bus. We have solved this problem an are splitting the reading accesses to 127 boundaries.
- 'pdev' is the physical ID of the desired unit and 'ldev' is the logical one. Usually 'ldev' will be 0.
- 'count' specifies the number of sectors(!!) to be read.
- 'buf' is a pointer to the buffer which will contain the data.
Result STRead will return 0 if no error occured and a value non zero if the command failed.
4.4.6 STReqAux
Name >Request Auxilliary Information< - Get detailed information on streamer and inserted tape.
Definition #include <scsibios.h>
int STReqAux(int pdev, int ldev, int bytes, char *buf);
Description This command is used to get detailed information about the streamer and the inserted tape. This information contains error-codes, current tape-position and other.
- 'pdev' is the physical ID of the desired unit and 'ldev' is the logical one. Usually 'ldev' will be 0.
- 'bytes' indicates the number of bytes to be transferred and 'buf' is the location where the gained information will be stored.
Result STReqAux will return 0 if no error occured and a value non zero if the command failed.
4.4.7 STRewind
Name >Rewind Tape< - Rewind the inserted tape
Definition #include <scsibios.h>
int STRewind(int pdev, int ldev, int async);
Description The STRewind command causes streamer to rewind the tape.
- 'pdev' is the physical ID of the desired unit and 'ldev' is the logical one. Usually 'ldev' will be 0.
An 'async' value of 1 indicates that the operation will be done in the background and the computer gains control again at once. In any other cases this value should be set to zero.
Result STRewind will return 0 if no error occured and a value non zero if the command failed.
4.4.8 STSkip
Name >Skip Filemarks< - Skip a certain number of filemarks
Definition #include <scsibios.h>
int STSkip(int pdev, int ldev, int kind, int count);
Description The STSkip command is used to skip 'count' number of filemarks with type 'kind'.
- 'pdev' is the physical ID of the desired unit and 'ldev' is the logical one. Usually 'ldev' will be 0.
Result STSkip will return 0 if no error occured and a value non zero if the command failed.
4.4.9 STUnlock
Name >Unlock Tape< - Unlock the tape inside the streamer
Definition #include <scsibios.h>
int STUnlock(int pdev, int ldev);
Description The STUnlock command causes the tape inside the streamer to be unlocked.
- 'pdev' is the physical ID of the desired unit and 'ldev' is the logical one. Usually 'ldev' will be 0.
Result STUnlock will return 0 if no error occured and a value non zero if the command failed.
4.4.10 STWFileM
Name >Write Filemark< - Write Filemark of a given type
Definition #include <scsibios.h>
int STWFileM(int pdev, int ldev, int kind);
Description The STWFileM command is used to write a file mark of tape 'kind'.
- 'pdev' is the physical ID of the desired unit and 'ldev' is the logical one. Usually 'ldev' will be 0.
Result STWFileM will return 0 if no error occured and a value non zero if the command failed.
4.4.11 STWrite
Name >Write< - Write sectors to the tape
Definition #include <scsibios.h>
int STWrite(int pdev, int ldev, long count, char *buf);
Description The STWrite command is used to write sectors to a unit.
Usually you can't transfere more than 127 sectors via ST/STE DMA bus. We have solved this problem an are splitting the reading accesses to 127 boundaries.
- 'pdev' is the physical ID of the desired unit and 'ldev' is the logical one. Usually 'ldev' will be 0.
- 'count' specifies the number of sectors(!!) to be written.
- 'buf' is a pointer to the buffer which will contain the data.
Result STWrite will return 0 if no error occured and a value non zero if the command failed.
MSCSI.C
#include <stdio.h>
#include <stdlib.h>
#include <tos.h>
#include <ctype.h>
#include <string.h>
#include <portab.h>
#include "scsibios.h"
VOID status(VOID);
VOID check_units(VOID);
VOID show_sector(FILE *fp);
WORD err;
BYTE mbuf[1024];
SCSI_TIMEOUT scsi_timeout;
void main()
{
BYTE c;
WORD pdev, ldev, a, b;
LONG sec;
BYTE name[100];
FILE *fp;
BYTE *filemode;
BYTE kind;
scsi_timeout = *SetTimeout((SCSI_TIMEOUT *)-1L);
scsi_timeout.BeforeCommand = 0UL;
scsi_timeout.AfterCommand = 0UL;
scsi_timeout.CommandDelay = 10UL;
SetTimeout(&scsi_timeout);
Cconws("\033E");
do
{
Cconws("\033EY = Check, T = Test, Z = Status,\
\r\nD = Display, R = Read, W = Write,\
\r\nS = Request Sense, L = Lock, U = Unlock,\
\r\nE = Erase, M = Mode Sense Q = Quit\
\r\nA = Auxiliary Sense V = Mode Select I = Inquiry\
\r\nO = On/Off P = Prewind B = Rewind\
\r\nF = Format G = Skip H = WFM\
\r\nJ = Buffer to File\
\r\n\r\n");
Cconws("Command (? = Help): ");
c = toupper((WORD)Cconin());
Cconws("\r\n");
switch(c)
{
case 'V':
Cconws("pdev ldev bytes : ");
scanf("%d %d %d", &pdev, &ldev, &a);
err = MSelect(pdev, ldev, a, mbuf);
status();
break;
case 'J':
Cconws("Filename : ");
scanf("%s", name);
filemode = "w";
if (fp = fopen(name, "r"))
{
Cconws("File exists; append (y/n) : ");
if (toupper((WORD)Cconin()) == 'Y')
filemode = "a";
fclose(fp);
}
if (!(fp = fopen(name, filemode)))
{
fprintf(stderr, "Cannot create %s\n", name);
break;
}
show_sector(fp);
fclose(fp);
break;
case 'G':
Cconws("pdev ldev kind count : ");
scanf("%d %d %d %d", &pdev, &ldev, &a, &b);
err = STSkip(pdev, ldev, a, b);
status();
break;
case 'H':
Cconws("pdev ldev count : ");
scanf("%d %d %d", &pdev, &ldev, &b);
err = STWFileM(pdev, ldev, b);
status();
break;
case 'P':
Cconws("pdev ldev async : ");
scanf("%d %d %d", &pdev, &ldev, &b);
err = STPrewind(pdev, ldev, b);
status();
break;
case 'B':
Cconws("pdev ldev async : ");
scanf("%d %d %d", &pdev, &ldev, &b);
err = STRewind(pdev, ldev, b);
status();
break;
case 'F':
Cconws("pdev ldev ilv : ");
scanf("%d %d %d", &pdev, &ldev, &a);
err = HDFormat(pdev, ldev, a);
status();
break;
case 'O':
Cconws("pdev ldev eject : ");
scanf("%d %d %d", &pdev, &ldev, &a);
if (a == 1)
err = HDStart(pdev, ldev);
else
err = HDStop(pdev, ldev, a);
status();
break;
case 'I':
Cconws("pdev ldev : ");
scanf("%d %d", &pdev, &ldev);
memset(mbuf, 0xea, sizeof(mbuf));
if (!(err = Inquiry(pdev, ldev, 36, mbuf)))
show_sector(stdout);
status();
break;
case 'A':
Cconws("pdev ldev : ");
scanf("%d %d", &pdev, &ldev);
memset(mbuf, 0xea, sizeof(mbuf));
if (!(err = STReqAux(pdev, ldev, 36, mbuf)))
show_sector(stdout);
status();
break;
case 'Y':
check_units();
break;
case 'D':
show_sector(stdout);
break;
case 'Z':
status();
break;
case 'R':
Cconws("(H)arddisk / (S)treamer : ");
kind = Cconin();
Cconws("\r\npdev ldev sec.lx : ");
scanf("%d %d %lx", &pdev, &ldev, &sec);
memset(mbuf, 0x40, sizeof(mbuf));
if (toupper(kind) == 'S')
{
if (!(err = STRead(pdev, ldev, 1l, mbuf)))
show_sector(stdout);
}
else if (toupper(kind) == 'H')
{
if (!(err = HDRead(pdev, ldev, sec, 1l, mbuf)))
show_sector(stdout);
}
status();
break;
case 'W':
Cconws("(H)arddisk / (S)treamer : ");
kind = Cconin();
Cconws("\r\npdev ldev sec.lx : ");
scanf("%d %d %lx", &pdev, &ldev, &sec);
if (toupper(kind) == 'S')
{
if (!(err = STWrite(pdev, ldev, 1l, mbuf)))
show_sector(stdout);
}
else if (toupper(kind) == 'H')
{
if (!(err = HDWrite(pdev, ldev, sec, 1l, mbuf)))
show_sector(stdout);
}
status();
break;
case 'T':
Cconws("pdev ldev : ");
scanf("%d %d", &pdev, &ldev);
err = TestUnit(pdev, ldev);
status();
break;
case 'S':
Cconws("pdev ldev : ");
scanf( "%d %d", &pdev, &ldev);
memset(mbuf, 0xea, sizeof(mbuf));
if (!(err = ReqSense(pdev, ldev, 127, mbuf)))
show_sector(stdout);
status();
break;
case 'M':
Cconws("\r\npdev ldev bytes : ");
scanf("%d %d %d", &pdev, &ldev, &a);
memset(mbuf, 0xea, sizeof(mbuf));
if (!(err = MSense(pdev, ldev, 0, a, mbuf)))
show_sector(stdout);
status();
break;
case 'L':
Cconws("pdev ldev : ");
scanf( "%d %d", &pdev, &ldev);
err = STLock(pdev, ldev);
status();
break;
case 'U':
Cconws("pdev ldev : ");
scanf( "%d %d", &pdev, &ldev);
err = STUnlock(pdev, ldev);
status();
break;
case 'E':
Cconws("pdev ldev async : ");
scanf( "%d %d %d", &pdev, &ldev, &a);
err = STErase(pdev, ldev, a);
status();
break;
case 'Q':
Cconws("\033E");
exit(0);
break;
case '?':
printf("Schau im Source nach wennst Dich nicht auskennst\n");
Cnecin();
break;
default:
break;
}
} while (TRUE);
}
VOID status()
{
if (!err)
return;
printf("\nError = %04x\n",err);
Cnecin();
}
VOID check_units()
{
WORD a,b;
printf("\033E");
printf(" Sub-Devices\n");
printf("Unit 0 1 2 3 4 5 6 7\n");
for (a = 0; a < 16; a++)
{
printf(" %02d ",a);
for (b = 0; b < 8; b++)
printf("%c ",(TestUnit(a, b)) ? '-' : 'X');
printf("\n");
}
printf("Taste zum Weitermachen\n");
Cnecin();
}
VOID show_sector(fp)
FILE *fp;
{
REG UBYTE *p = mbuf;
REG WORD a,b;
if (fp == stdout)
fprintf(fp, "\033ESector buffer : %08lx\n", p);
for(b = 0;b < 32;b++)
{
fprintf(fp, "%04x: ",b * 16);
for(a = 0; a < 16; a++)
fprintf(fp, "%02x ",*p++);
p -= 16;
for(a = 0; a < 16; a++)
{
fprintf(fp, "%c",(*p >= ' ' && *p != 0x7f) ? *p : '.');
p++;
}
fprintf(fp, "\n");
if (fp == stdout && b == 15)
Cnecin();
}
if (fp == stdout)
Cnecin();
}
SCSIBIOS.H
typedef unsigned long ULONG;
typedef struct
{ /* These timeouts are used... */
ULONG BeforeCommand; /* ...before sending a command */
ULONG AfterCommand; /* ...after sending a command */
ULONG ShortTimeout; /* ...for quick commands */
ULONG LongTimeout; /* ...for long commands */
ULONG Wait4IRQ; /* ...for commands which can last to eternity*/
ULONG XtraShortTimeout; /* ...for very short commands like TestUnit */
ULONG CommandDelay; /* between two commands */
} SCSI_TIMEOUT;
/*
* Pre-sets for timeouts are:
* BeforeCommand : 20UL (25ms)
* AfterCommand : 20UL (25ms)
* ShortTimeout : 6000UL (30s)
* LongTimeout : 12000UL (60s)
* Wait4IRQ : 240000UL (20min)
* XtraShortTimeout: 50UL (250ms)
*/
int HDCapacity(int pdev, int ldev, int iface, char *buf);
int HDCopy(int pdev, int ldev, long length, char *buf, int erase);
int HDDefect(int pdev, int ldev, int iface, int fmt, int count, char *buf);
int HDFormat(int pdev, int ldev, int interleave);
int HDRead(int pdev, int ldev, long start, long count, char *buf);
int HDWrite(int pdev, int ldev, long start, long count, char *buf);
int Illegal(void);
int Inquiry(int pdev, int ldev, int bytes, char *buf);
int MSelect(int pdev, int ldev, int count, char *buf);
int MSense(int pdev, int ldev, int page, int bytes, char *buf);
int ReqSense(int pdev, int ldev, int count, char *buf);
long SCSIVersion(void);
SCSI_TIMEOUT *SetTimeout(SCSI_TIMEOUT *scsi_timeout);
int STLocate(int pdev, int ldev, int iface, int cp, int part, long adr);
int STReqAux(int pdev, int ldev, int bytes, char *buf);
int STRead(int pdev, int ldev, long count, char *buf);
int STWrite(int pdev, int ldev, long count, char *buf);
int STSkip(int pdev, int ldev, int kind, int count);
int HDStop(int pdev, int ldev, int eject);
int STErase(int pdev, int ldev, int async);
int STPrewind(int pdev, int ldev, int async);
int STRewind(int pdev, int ldev, int async);
int STWFileM(int pdev, int ldev, int kind);
int HDReleas(int pdev, int ldev);
int HDReserv(int pdev, int ldev);
int HDRezero(int pdev, int ldev);
int HDStart(int pdev, int ldev);
int STAppend(int pdev, int ldev);
int STLock(int pdev, int ldev);
int STUnlock(int pdev, int ldev);
int TestUnit(int pdev, int ldev);