mirror of
https://github.com/LIV2/lide.device.git
synced 2025-12-06 00:32:45 +00:00
poke
This commit is contained in:
parent
cdcb9b04d9
commit
ccc6d3f1ca
103
ata.c
103
ata.c
@ -1,3 +1,4 @@
|
||||
#include <devices/scsidisk.h>
|
||||
#include <exec/execbase.h>
|
||||
#include <exec/types.h>
|
||||
#include <exec/devices.h>
|
||||
@ -16,10 +17,15 @@
|
||||
#include <clib/debug_protos.h>
|
||||
#endif
|
||||
|
||||
#define NOTIMER
|
||||
|
||||
#define WAIT_TIMEOUT_MS 100
|
||||
#define WAIT_TIMEOUT_MS 500
|
||||
|
||||
/**
|
||||
* ata_wait_not_busy
|
||||
*
|
||||
* Wait with a timeout for the unit to report that it is not busy
|
||||
*
|
||||
* returns false on timeout
|
||||
*/
|
||||
bool ata_wait_not_busy(struct IDEUnit *unit) {
|
||||
#ifndef NOTIMER
|
||||
struct Device *TimerBase = unit->TimeReq->tr_node.io_Device;
|
||||
@ -40,6 +46,14 @@ bool ata_wait_not_busy(struct IDEUnit *unit) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ata_wait_ready
|
||||
*
|
||||
* Wait with a timeout for the unit to report that it is ready
|
||||
*
|
||||
* returns false on timeout
|
||||
*/
|
||||
bool ata_wait_ready(struct IDEUnit *unit) {
|
||||
#ifndef NOTIMER
|
||||
struct Device *TimerBase = unit->TimeReq->tr_node.io_Device;
|
||||
@ -59,27 +73,43 @@ bool ata_wait_ready(struct IDEUnit *unit) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_wait_drq
|
||||
*
|
||||
* Wait with a timeout for the unit to set drq
|
||||
*
|
||||
* returns false on timeout
|
||||
*/
|
||||
bool ata_wait_drq(struct IDEUnit *unit) {
|
||||
/*
|
||||
#ifndef NOTIMER
|
||||
struct Device *TimerBase = unit->TimeReq->tr_node.io_Device;
|
||||
struct timeval start, now;
|
||||
GetSysTime(&start);
|
||||
#endif
|
||||
|
||||
*/
|
||||
#if DEBUG >= 2
|
||||
KPrintF("wait_drq\n");
|
||||
#endif
|
||||
|
||||
while (1) {
|
||||
if (*(volatile BYTE *)unit->drive->status_command& ata_drq) return true;
|
||||
|
||||
/*
|
||||
#ifndef NOTIMER
|
||||
GetSysTime(&now);
|
||||
if (now.tv_micro >= (start.tv_micro + (WAIT_TIMEOUT_MS*1000))) return false;
|
||||
#endif
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_identify
|
||||
*
|
||||
* Send an IDENTIFY command to the device and place the results in the buffer
|
||||
*
|
||||
* returns fals on error
|
||||
*/
|
||||
bool ata_identify(struct IDEUnit *unit, UWORD *buffer)
|
||||
{
|
||||
#ifndef NOTIMER
|
||||
@ -97,9 +127,8 @@ bool ata_identify(struct IDEUnit *unit, UWORD *buffer)
|
||||
*unit->drive->status_command = ATA_CMD_IDENTIFY;
|
||||
volatile UBYTE *status = unit->drive->status_command;
|
||||
|
||||
UBYTE curstatus = *status;
|
||||
#if DEBUG >= 2
|
||||
KPrintF("Drive Status: %04x%04x %04x%04x\n",status, curstatus);
|
||||
KPrintF("Drive Status: %04x%04x %04x%04x\n",status, *status);
|
||||
#endif
|
||||
if (*status == 0) return false; // No drive there?
|
||||
|
||||
@ -130,6 +159,13 @@ bool ata_identify(struct IDEUnit *unit, UWORD *buffer)
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_init_unit
|
||||
*
|
||||
* Initialize a unit, check if it is there and responding
|
||||
*
|
||||
* returns false on error
|
||||
*/
|
||||
bool ata_init_unit(struct IDEUnit *unit) {
|
||||
struct ExecBase *SysBase = unit->SysBase;
|
||||
|
||||
@ -190,14 +226,29 @@ bool ata_init_unit(struct IDEUnit *unit) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_read
|
||||
*
|
||||
* Read a block from the unit
|
||||
* @param buffer Destination buffer
|
||||
* @param lba LBA Address
|
||||
* @param count Number of blocks to transfer
|
||||
* @param actual Pointer to the io reqquests io_Actual
|
||||
* @param unit Pointer to the unit structure
|
||||
*/
|
||||
BYTE ata_read(APTR *buffer, ULONG lba, UBYTE count, ULONG *actual, struct IDEUnit *unit) {
|
||||
#if DEBUG > 1
|
||||
KPrintF("ata_read");
|
||||
#endif
|
||||
|
||||
*actual = 0;
|
||||
if (count == 0) return TDERR_TooFewSecs;
|
||||
|
||||
BYTE drvSel = (unit->primary) ? 0xE0 : 0xF0;
|
||||
*unit->drive->devHead = (UBYTE)(drvSel | ((lba >> 24) & 0x0F));
|
||||
|
||||
if (!ata_wait_ready(unit))
|
||||
return TDERR_NotSpecified;
|
||||
return HFERR_BadStatus;
|
||||
|
||||
*unit->drive->sectorCount = count;
|
||||
*unit->drive->lbaLow = (UBYTE)(lba);
|
||||
@ -208,8 +259,15 @@ BYTE ata_read(APTR *buffer, ULONG lba, UBYTE count, ULONG *actual, struct IDEUni
|
||||
|
||||
UWORD offset = 0;
|
||||
for (int block = 0; block < count; block++) {
|
||||
if (!ata_wait_drq(unit) || (*unit->drive->error_features && ata_error))
|
||||
if (!ata_wait_drq(unit))
|
||||
return HFERR_BadStatus;
|
||||
|
||||
if (*unit->drive->error_features && ata_error) {
|
||||
#if DEBUG > 1
|
||||
KPrintF("ATA ERROR!!!");
|
||||
#endif
|
||||
return TDERR_NotSpecified;
|
||||
}
|
||||
|
||||
for (int i=0; i<(unit->blockSize / 2); i++) {
|
||||
((UWORD *)buffer)[offset] = *unit->drive->data;
|
||||
@ -221,14 +279,30 @@ BYTE ata_read(APTR *buffer, ULONG lba, UBYTE count, ULONG *actual, struct IDEUni
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ata_write
|
||||
*
|
||||
* Read a block from the unit
|
||||
* @param buffer Source buffer
|
||||
* @param lba LBA Address
|
||||
* @param count Number of blocks to transfer
|
||||
* @param actual Pointer to the io reqquests io_Actual
|
||||
* @param unit Pointer to the unit structure
|
||||
*/
|
||||
BYTE ata_write(APTR *buffer, ULONG lba, UBYTE count, ULONG *actual, struct IDEUnit *unit) {
|
||||
#if DEBUG > 1
|
||||
KPrintF("ata_write");
|
||||
#endif
|
||||
*actual = 0;
|
||||
|
||||
if (count == 0) return TDERR_TooFewSecs;
|
||||
|
||||
BYTE drvSel = (unit->primary) ? 0xE0 : 0xF0;
|
||||
*unit->drive->devHead = (UBYTE)(drvSel | ((lba >> 24) & 0x0F));
|
||||
|
||||
if (!ata_wait_ready(unit))
|
||||
return TDERR_NotSpecified;
|
||||
return HFERR_BadStatus;
|
||||
|
||||
*unit->drive->sectorCount = count;
|
||||
*unit->drive->lbaLow = (UBYTE)(lba);
|
||||
@ -239,8 +313,15 @@ BYTE ata_write(APTR *buffer, ULONG lba, UBYTE count, ULONG *actual, struct IDEUn
|
||||
|
||||
UWORD offset = 0;
|
||||
for (int block = 0; block < count; block++) {
|
||||
if (!ata_wait_drq(unit) || (unit->drive->error_features && ata_error))
|
||||
if (!ata_wait_drq(unit))
|
||||
return HFERR_BadStatus;
|
||||
|
||||
if (*unit->drive->error_features && ata_error) {
|
||||
#if DEBUG > 1
|
||||
KPrintF("ATA ERROR!!!");
|
||||
#endif
|
||||
return TDERR_NotSpecified;
|
||||
}
|
||||
|
||||
for (int i=0; i<(unit->blockSize / 2); i++) {
|
||||
*unit->drive->data = ((UWORD *)buffer)[offset];
|
||||
|
||||
19
device.h
19
device.h
@ -1,22 +1,27 @@
|
||||
#ifndef _DEVICE_H
|
||||
#define _DEVICE_H
|
||||
|
||||
#include <proto/exec.h>
|
||||
#include <exec/resident.h>
|
||||
#include <exec/libraries.h>
|
||||
#include <exec/devices.h>
|
||||
#include <exec/errors.h>
|
||||
#include <exec/libraries.h>
|
||||
#include <exec/ports.h>
|
||||
#include <exec/resident.h>
|
||||
#include <exec/tasks.h>
|
||||
#include <libraries/dos.h>
|
||||
#include <proto/exec.h>
|
||||
|
||||
|
||||
#define MANUF_ID 2092
|
||||
#define DEV_ID 6
|
||||
#define MAX_UNITS 4
|
||||
|
||||
|
||||
typedef struct Drive {
|
||||
/**
|
||||
* Drive struct
|
||||
*
|
||||
* Each register spaced 512 bytes apart
|
||||
* To use this code with other boards you may need to adjust these sizes
|
||||
*/
|
||||
struct Drive {
|
||||
UWORD data[256];
|
||||
UBYTE error_features[512];
|
||||
UBYTE sectorCount[512];
|
||||
@ -25,14 +30,14 @@ typedef struct Drive {
|
||||
UBYTE lbaHigh[512];
|
||||
UBYTE devHead[512];
|
||||
UBYTE status_command[512];
|
||||
} Drive;
|
||||
};
|
||||
|
||||
struct IDEUnit {
|
||||
struct Unit io_unit;
|
||||
struct ConfigDev *cd;
|
||||
struct ExecBase *SysBase;
|
||||
struct timerequest *TimeReq;
|
||||
Drive *drive;
|
||||
struct Drive *drive;
|
||||
UBYTE unitNum;
|
||||
BOOL primary;
|
||||
BOOL present;
|
||||
|
||||
158
driver.c
158
driver.c
@ -13,12 +13,13 @@
|
||||
#include <proto/exec.h>
|
||||
#include <proto/expansion.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "idetask.h"
|
||||
#include "device.h"
|
||||
#include "ata.h"
|
||||
#include "device.h"
|
||||
#include "idetask.h"
|
||||
#include "newstyle.h"
|
||||
#include "td64.h"
|
||||
|
||||
#if DEBUG
|
||||
#include <clib/debug_protos.h>
|
||||
@ -53,6 +54,12 @@ char device_name[] = DEVICE_NAME;
|
||||
const char device_id_string[] = DEVICE_ID_STRING;
|
||||
const char task_name[] = TASK_NAME;
|
||||
|
||||
|
||||
/** set_dev_name
|
||||
*
|
||||
* Try to set a unique drive name
|
||||
* will prepend 2nd/3rd/4th. etc to the beginning of device_name
|
||||
*/
|
||||
char * set_dev_name(struct DeviceBase *dev) {
|
||||
struct ExecBase *SysBase = dev->SysBase;
|
||||
|
||||
@ -66,7 +73,7 @@ char * set_dev_name(struct DeviceBase *dev) {
|
||||
*(ULONG *)devName = device_prefix[i]; // Add prefix to start of device name string in a hacky way
|
||||
} else {
|
||||
#if DEBUG > 0
|
||||
KPrintF("Device name: %s",devName);
|
||||
KPrintF("Device name: %s\n",devName);
|
||||
#endif
|
||||
return devName;
|
||||
}
|
||||
@ -77,7 +84,12 @@ char * set_dev_name(struct DeviceBase *dev) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Cleanup(struct DeviceBase *dev) {
|
||||
/**
|
||||
* Cleanup
|
||||
*
|
||||
* Free used resources back to the system
|
||||
*/
|
||||
static void Cleanup(struct DeviceBase *dev) {
|
||||
#if DEBUG > 0
|
||||
KPrintF("Cleaning up...\n");
|
||||
#endif
|
||||
@ -89,8 +101,11 @@ void Cleanup(struct DeviceBase *dev) {
|
||||
if (dev->units) FreeMem(dev->units,sizeof(struct IDEUnit) * MAX_UNITS);
|
||||
}
|
||||
|
||||
//static struct Library __attribute__((used)) * init_device(struct ExecBase *SysBase, BPTR seg_list, struct DeviceBase *dev)
|
||||
|
||||
/**
|
||||
* init_device
|
||||
*
|
||||
* Scan for drives and initialize the driver if any are found
|
||||
*/
|
||||
static struct Library __attribute__((used)) * init_device(struct ExecBase *SysBase asm("a6"), BPTR seg_list asm("a0"), struct DeviceBase *dev asm("d0"))
|
||||
{
|
||||
dev->SysBase = SysBase;
|
||||
@ -229,21 +244,38 @@ static BPTR __attribute__((used)) expunge(struct DeviceBase *dev asm("a6"))
|
||||
#if DEBUG >= 2
|
||||
KPrintF((CONST_STRPTR) "running expunge()\n");
|
||||
#endif
|
||||
/*
|
||||
|
||||
if (dev->lib.lib_OpenCnt != 0)
|
||||
{
|
||||
dev->lib.lib_Flags |= LIBF_DELEXP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dev->Task != NULL) {
|
||||
|
||||
FreeMem(dev->units,sizeof(struct IDEUnit) * MAX_UNITS);
|
||||
struct MsgPort *mp = NULL;
|
||||
struct IOStdReq *ioreq = NULL;
|
||||
|
||||
if ((mp = CreatePort(NULL,0)) == NULL)
|
||||
return 0;
|
||||
if ((ioreq = CreateStdIO(mp)) == NULL) {
|
||||
DeletePort(mp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ioreq->io_Command = CMD_DIE;
|
||||
|
||||
PutMsg(dev->TaskMP,(struct Message *)ioreq);
|
||||
WaitPort(mp);
|
||||
|
||||
if (ioreq) DeleteStdIO(ioreq);
|
||||
if (mp) DeletePort(mp);
|
||||
}
|
||||
|
||||
BPTR seg_list = dev->saved_seg_list;
|
||||
Remove(&dev->lib.lib_Node);
|
||||
FreeMem((char *)dev - dev->lib.lib_NegSize, dev->lib.lib_NegSize + dev->lib.lib_PosSize);
|
||||
return seg_list;
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* device dependent open function
|
||||
@ -255,9 +287,13 @@ static void __attribute__((used)) open(struct DeviceBase *dev asm("a6"), struct
|
||||
#if DEBUG >= 2
|
||||
KPrintF((CONST_STRPTR) "running open() for unitnum %x%x\n",unitnum);
|
||||
#endif
|
||||
|
||||
ioreq->io_Error = IOERR_OPENFAIL;
|
||||
ioreq->io_Message.mn_Node.ln_Type = NT_REPLYMSG;
|
||||
ioreq->io_Error = IOERR_OPENFAIL;
|
||||
|
||||
if (dev->Task == NULL) {
|
||||
ioreq->io_Error = IOERR_OPENFAIL;
|
||||
}
|
||||
|
||||
|
||||
if (unitnum >= MAX_UNITS || dev->units[unitnum].present == false) {
|
||||
ioreq->io_Error = TDERR_BadUnitNum;
|
||||
@ -285,32 +321,79 @@ static BPTR __attribute__((used)) close(struct DeviceBase *dev asm("a6"), struct
|
||||
KPrintF((CONST_STRPTR) "running close()\n");
|
||||
#endif
|
||||
dev->lib.lib_OpenCnt--;
|
||||
/* No Expunge yet...
|
||||
|
||||
ioreq->io_Device = NULL;
|
||||
ioreq->io_Unit = NULL;
|
||||
|
||||
|
||||
if (dev->lib.lib_OpenCnt == 0 && (dev->lib.lib_Flags & LIBF_DELEXP))
|
||||
return expunge(dev);
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* device dependent beginio function */
|
||||
|
||||
static UWORD supported_commands[] =
|
||||
{
|
||||
CMD_CLEAR,
|
||||
CMD_UPDATE,
|
||||
CMD_READ,
|
||||
CMD_WRITE,
|
||||
TD_PROTSTATUS,
|
||||
TD_CHANGENUM,
|
||||
TD_CHANGESTATE,
|
||||
TD_GETDRIVETYPE,
|
||||
TD_PROTSTATUS,
|
||||
TD_READ64,
|
||||
TD_WRITE64,
|
||||
TD_FORMAT64,
|
||||
NSCMD_DEVICEQUERY,
|
||||
NSCMD_TD_READ64,
|
||||
NSCMD_TD_WRITE64,
|
||||
NSCMD_TD_FORMAT64,
|
||||
0
|
||||
};
|
||||
|
||||
/**
|
||||
* begin_io
|
||||
*
|
||||
* Action an IO Request
|
||||
*/
|
||||
static void __attribute__((used)) begin_io(struct DeviceBase *dev asm("a6"), struct IOStdReq *ioreq asm("a1"))
|
||||
{
|
||||
#if DEBUG >= 2
|
||||
KPrintF((CONST_STRPTR) "running begin_io()\n");
|
||||
#endif
|
||||
// struct ExecBase *SysBase = dev->SysBase;
|
||||
ioreq->io_Message.mn_Node.ln_Type = NT_REPLYMSG;
|
||||
ioreq->io_Error = TDERR_NotSpecified;
|
||||
|
||||
if (dev->Task == NULL) {
|
||||
ioreq->io_Error = IOERR_OPENFAIL;
|
||||
}
|
||||
|
||||
if (ioreq == NULL || ioreq->io_Unit == 0) return;
|
||||
|
||||
switch (ioreq->io_Command) {
|
||||
case CMD_CLEAR:
|
||||
case CMD_UPDATE:
|
||||
|
||||
case TD_CHANGENUM:
|
||||
ioreq->io_Actual = 1;
|
||||
ioreq->io_Error = 0;
|
||||
break;
|
||||
case TD_CHANGESTATE:
|
||||
case TD_GETDRIVETYPE:
|
||||
case TD_PROTSTATUS:
|
||||
ioreq->io_Actual = 0;
|
||||
ioreq->io_Error = 0;
|
||||
break;
|
||||
|
||||
case HD_SCSICMD:
|
||||
case CMD_READ:
|
||||
case TD_FORMAT:
|
||||
case CMD_WRITE:
|
||||
case TD_READ64:
|
||||
case TD_WRITE64:
|
||||
case TD_FORMAT64:
|
||||
case NSCMD_TD_READ64:
|
||||
case NSCMD_TD_WRITE64:
|
||||
case NSCMD_TD_FORMAT64:
|
||||
ioreq->io_Flags &= ~IOF_QUICK;
|
||||
PutMsg(dev->TaskMP,&ioreq->io_Message);
|
||||
#if DEBUG >= 2
|
||||
@ -318,6 +401,23 @@ static void __attribute__((used)) begin_io(struct DeviceBase *dev asm("a6"), str
|
||||
#endif
|
||||
break;
|
||||
|
||||
case NSCMD_DEVICEQUERY:
|
||||
if (ioreq->io_Length >= sizeof(struct NSDeviceQueryResult))
|
||||
{
|
||||
struct NSDeviceQueryResult *result = ioreq->io_Data;
|
||||
result->DevQueryFormat = 0;
|
||||
result->SizeAvailable = sizeof(struct NSDeviceQueryResult);
|
||||
result->DeviceType = NSDEVTYPE_TRACKDISK;
|
||||
result->DeviceSubType = 0;
|
||||
result->SupportedCommands = supported_commands;
|
||||
ioreq->io_Actual = sizeof(struct NSDeviceQueryResult);
|
||||
ioreq->io_Error = 0;
|
||||
}
|
||||
else {
|
||||
ioreq->io_Error = IOERR_BADLENGTH;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
#if DEBUG >= 2
|
||||
KPrintF("Unknown command %x%x\n", ioreq->io_Command);
|
||||
@ -330,7 +430,11 @@ static void __attribute__((used)) begin_io(struct DeviceBase *dev asm("a6"), str
|
||||
|
||||
}
|
||||
|
||||
/* device dependent abortio function */
|
||||
/**
|
||||
* abort_io
|
||||
*
|
||||
* Abort io request
|
||||
*/
|
||||
static ULONG __attribute__((used)) abort_io(struct Library *dev asm("a6"), struct IOStdReq *ioreq asm("a1"))
|
||||
{
|
||||
#if DEBUG >= 2
|
||||
@ -351,13 +455,17 @@ static const ULONG device_vectors[] =
|
||||
-1 //function table end marker
|
||||
};
|
||||
|
||||
|
||||
static struct Library __attribute__((used)) * init(BPTR seg_list asm("a0"), struct ExecBase *SysPtr asm("a6"))
|
||||
/**
|
||||
* init
|
||||
*
|
||||
* Create the device and add it to the system if init_device succeeds
|
||||
*/
|
||||
static struct Library __attribute__((used)) * init(BPTR seg_list asm("a0"), struct ExecBase *sb asm("a6"))
|
||||
{
|
||||
#if DEBUG >= 1
|
||||
KPrintF("Init driver.\n");
|
||||
#endif
|
||||
SysBase = SysPtr;
|
||||
SysBase = sb;
|
||||
struct Device *mydev = (struct Device *)MakeLibrary((ULONG *)&device_vectors, // Vectors
|
||||
NULL, // InitStruct data
|
||||
(APTR)init_device, // Init function
|
||||
|
||||
174
idetask.c
174
idetask.c
@ -9,69 +9,154 @@
|
||||
#include <proto/expansion.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "device.h"
|
||||
#include "ata.h"
|
||||
#include "device.h"
|
||||
#include "idetask.h"
|
||||
#include "newstyle.h"
|
||||
#include "scsi.h"
|
||||
#include "td64.h"
|
||||
|
||||
#if DEBUG
|
||||
#include <clib/debug_protos.h>
|
||||
#endif
|
||||
|
||||
void handle_scsi_command(struct IOStdReq *ioreq) {
|
||||
/**
|
||||
* handle_scsi_command
|
||||
*
|
||||
* Handle SCSI Direct commands
|
||||
* @param ioreq IO Request
|
||||
*/
|
||||
static void handle_scsi_command(struct IOStdReq *ioreq) {
|
||||
struct SCSICmd *scsi_command = ioreq->io_Data;
|
||||
char *inquiry_data;
|
||||
struct SCSI_CDB_6 *cdb_6;
|
||||
struct SCSI_CDB_10 *cdb_10;
|
||||
struct IDEUnit *unit = (struct IDEUnit *)ioreq->io_Unit;
|
||||
APTR data = (APTR)scsi_command->scsi_Data;
|
||||
APTR command = (APTR)scsi_command->scsi_Command;
|
||||
ULONG lba;
|
||||
UWORD count;
|
||||
UBYTE error = 0;
|
||||
|
||||
#if DEBUG >= 2
|
||||
KPrintF("Command %04x%04x\n",*scsi_command->scsi_Command);
|
||||
#endif
|
||||
switch (scsi_command->scsi_Command[0]) {
|
||||
case SCSICMD_TEST_UNIT_READY:
|
||||
ioreq->io_Error = 0;
|
||||
scsi_command->scsi_Actual = 0;
|
||||
error = 0;
|
||||
break;
|
||||
|
||||
case SCSICMD_INQUIRY:
|
||||
inquiry_data = (char *)scsi_command->scsi_Data;
|
||||
inquiry_data[0] = 0;
|
||||
inquiry_data[1] = 0;
|
||||
inquiry_data[2] = 0;
|
||||
inquiry_data[3] = 2;
|
||||
inquiry_data[4] = 44-4;
|
||||
inquiry_data[6] = 0;
|
||||
inquiry_data[7] = 0;
|
||||
((struct SCSI_Inquiry *)data)->peripheral_type = 0;
|
||||
((struct SCSI_Inquiry *)data)->removable_media = 0;
|
||||
((struct SCSI_Inquiry *)data)->version = 0;
|
||||
((struct SCSI_Inquiry *)data)->response_format = 2;
|
||||
((struct SCSI_Inquiry *)data)->additional_length = (sizeof(struct SCSI_Inquiry) - 4);
|
||||
|
||||
UWORD *identity = AllocMem(512,MEMF_CLEAR|MEMF_ANY);
|
||||
if (!identity) {
|
||||
ioreq->io_Error = TDERR_NotSpecified;
|
||||
error = HFERR_BadStatus;
|
||||
break;
|
||||
}
|
||||
if (!(ata_identify((struct IDEUnit *)ioreq->io_Unit,identity))) {
|
||||
ioreq->io_Error = TDERR_NotSpecified;
|
||||
if (!(ata_identify(unit,identity))) {
|
||||
error = HFERR_BadStatus;
|
||||
break;
|
||||
}
|
||||
CopyMem(&identity[ata_identify_model],&inquiry_data[8],24);
|
||||
CopyMem(&identity[ata_identify_fw_rev],&inquiry_data[32],4);
|
||||
CopyMem(&identity[ata_identify_serial],&inquiry_data[36],8);
|
||||
CopyMem(&identity[ata_identify_model],&((struct SCSI_Inquiry *)data)->vendor,24);
|
||||
CopyMem(&identity[ata_identify_fw_rev],&((struct SCSI_Inquiry *)data)->revision,4);
|
||||
CopyMem(&identity[ata_identify_serial],&((struct SCSI_Inquiry *)data)->serial,8);
|
||||
FreeMem(identity,512);
|
||||
scsi_command->scsi_SenseActual = 0;
|
||||
scsi_command->scsi_Actual = scsi_command->scsi_Length;
|
||||
scsi_command->scsi_CmdActual = scsi_command->scsi_CmdLength;
|
||||
ioreq->io_Error = 0;
|
||||
error = 0;
|
||||
break;
|
||||
|
||||
case SCSICMD_READ_CAPACITY_10:
|
||||
if (data == NULL) {
|
||||
error = IOERR_BADADDRESS;
|
||||
break;
|
||||
}
|
||||
|
||||
((struct SCSI_CAPACITY_10 *)data)->lba = (unit->sectorsPerTrack * unit->cylinders * unit->heads);
|
||||
((struct SCSI_CAPACITY_10 *)data)->block_size = unit->blockSize;
|
||||
scsi_command->scsi_Actual = 8;
|
||||
error = 0;
|
||||
break;
|
||||
|
||||
case SCSICMD_READ_6:
|
||||
|
||||
if (data == NULL) {
|
||||
error = IOERR_BADADDRESS;
|
||||
break;
|
||||
}
|
||||
|
||||
cdb_6 = (struct SCSI_CDB_6 *)command;
|
||||
lba = (((cdb_6->lba_high & 0x1F) << 16) | cdb_6->lba_mid << 8 | cdb_6->lba_low);
|
||||
count = cdb_6->length;
|
||||
error = ata_read(data,lba,count,&scsi_command->scsi_Actual,unit);
|
||||
break;
|
||||
|
||||
case SCSICMD_READ_10:
|
||||
if (data == NULL) {
|
||||
error = IOERR_BADADDRESS;
|
||||
break;
|
||||
}
|
||||
|
||||
cdb_10 = (struct SCSI_CDB_10 *)command;
|
||||
lba = cdb_10->lba;
|
||||
count = cdb_10->length;
|
||||
error = ata_read(data,lba,count,&scsi_command->scsi_Actual,unit);
|
||||
break;
|
||||
|
||||
case SCSICMD_WRITE_6:
|
||||
if (data == NULL) {
|
||||
error = IOERR_BADADDRESS;
|
||||
break;
|
||||
}
|
||||
|
||||
cdb_6 = (struct SCSI_CDB_6 *)command;
|
||||
lba = (((cdb_6->lba_high & 0x1F) << 16) | cdb_6->lba_mid << 8 | cdb_6->lba_low);
|
||||
count = cdb_6->length;
|
||||
error = ata_write(data,lba,count,&scsi_command->scsi_Actual,unit);
|
||||
break;
|
||||
|
||||
case SCSICMD_WRITE_10:
|
||||
if (data == NULL) {
|
||||
error = IOERR_BADADDRESS;
|
||||
break;
|
||||
}
|
||||
|
||||
cdb_10 = (struct SCSI_CDB_10 *)command;
|
||||
lba = cdb_10->lba;
|
||||
count = cdb_10->length;
|
||||
error = ata_write(data,lba,count,&scsi_command->scsi_Actual,unit);
|
||||
break;
|
||||
|
||||
default:
|
||||
ioreq->io_Error = TDERR_NotSpecified;
|
||||
error = HFERR_BadStatus;
|
||||
break;
|
||||
}
|
||||
|
||||
ioreq->io_Error = error;
|
||||
scsi_command->scsi_CmdActual = scsi_command->scsi_CmdLength;
|
||||
scsi_command->scsi_SenseActual = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ide_task
|
||||
*
|
||||
* This is a task to complete IO Requests for all units
|
||||
* Requests are sent here from begin_io via the dev->TaskMP Message port
|
||||
*/
|
||||
void ide_task () {
|
||||
struct ExecBase *SysBase = *(struct ExecBase **)4UL;
|
||||
struct Task *task = FindTask(NULL);
|
||||
struct MsgPort *mp;
|
||||
struct IOStdReq *ioreq;
|
||||
struct IDEUnit *unit;
|
||||
UWORD blocksize = 512;
|
||||
ULONG lba = 0;
|
||||
ULONG count = 0;
|
||||
UWORD blocksize;
|
||||
ULONG lba;
|
||||
ULONG count;
|
||||
|
||||
#if DEBUG >= 1
|
||||
KPrintF("Task waiting for init\n");
|
||||
#endif
|
||||
@ -79,8 +164,9 @@ void ide_task () {
|
||||
|
||||
struct DeviceBase *dev = (struct DeviceBase *)task->tc_UserData;
|
||||
|
||||
// Create the MessagePort used to send us requests
|
||||
if ((mp = CreatePort(NULL,0)) == NULL) {
|
||||
dev->Task = NULL;
|
||||
dev->Task = NULL; // Failed to create MP, let the device know
|
||||
RemTask(NULL);
|
||||
Wait(0);
|
||||
}
|
||||
@ -92,42 +178,54 @@ void ide_task () {
|
||||
#if DEBUG >= 2
|
||||
KPrintF("WaitPort()\n");
|
||||
#endif
|
||||
Wait(1 << mp->mp_SigBit);
|
||||
Wait(1 << mp->mp_SigBit); // Wait for an IORequest to show up
|
||||
|
||||
while ((ioreq = (struct IOStdReq *)GetMsg(mp))) {
|
||||
unit = (struct IDEUnit *)ioreq->io_Unit;
|
||||
switch (ioreq->io_Command) {
|
||||
|
||||
case CMD_READ:
|
||||
#if DEBUG >= 2
|
||||
KPrintF("CMD_READ\n");
|
||||
#endif
|
||||
ioreq->io_Actual = 0;
|
||||
#if DEBUG >= 2
|
||||
KPrintF("Offset: %04x%04x Size:%04x%04x\n", ioreq->io_Offset,ioreq->io_Length);
|
||||
#endif
|
||||
|
||||
case TD_READ64:
|
||||
case NSCMD_TD_READ64:
|
||||
blocksize = ((struct IDEUnit *)ioreq->io_Unit)->blockSize;
|
||||
lba = (((long long)ioreq->io_Actual << 32 | ioreq->io_Offset) / (UWORD)blocksize);
|
||||
#if DEBUG >= 2
|
||||
KPrintF("LBA: %04x%04x\n", lba);
|
||||
#endif
|
||||
lba = (((long long)ioreq->io_Actual << 32 | ioreq->io_Offset) / (UWORD)blocksize);
|
||||
count = (ioreq->io_Length/(UWORD)blocksize);
|
||||
ioreq->io_Error = ata_read(ioreq->io_Data, lba, count, &ioreq->io_Actual, unit);
|
||||
break;
|
||||
|
||||
case CMD_WRITE:
|
||||
ioreq->io_Actual = 0;
|
||||
|
||||
case TD_WRITE64:
|
||||
case TD_FORMAT64:
|
||||
case NSCMD_TD_WRITE64:
|
||||
case NSCMD_TD_FORMAT64:
|
||||
blocksize = ((struct IDEUnit *)ioreq->io_Unit)->blockSize;
|
||||
lba = (((long long)ioreq->io_Actual << 32 | ioreq->io_Offset) / (UWORD)blocksize);
|
||||
count = (ioreq->io_Length/(UWORD)blocksize);
|
||||
ioreq->io_Error = ata_write(ioreq->io_Data, lba, count, &ioreq->io_Actual, unit);
|
||||
ioreq->io_Error = 0;
|
||||
break;
|
||||
|
||||
case HD_SCSICMD:
|
||||
handle_scsi_command(ioreq);
|
||||
break;
|
||||
|
||||
/* CMD_DIE: Shut down this task and clean up */
|
||||
case CMD_DIE:
|
||||
#if DEBUG > 0
|
||||
KPrintF("CMD_DIE: Shutting down IDE Task\n");
|
||||
#endif
|
||||
DeletePort(mp);
|
||||
dev->TaskMP = NULL;
|
||||
dev->Task = NULL;
|
||||
ReplyMsg(&ioreq->io_Message);
|
||||
RemTask(NULL);
|
||||
Wait(0);
|
||||
|
||||
default:
|
||||
// Unknown commands.
|
||||
ioreq->io_Error = IOERR_NOCMD;
|
||||
ioreq->io_Actual = 0;
|
||||
break;
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
#include <stdbool.h>
|
||||
#include "device.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#define TASK_NAME "idetask"
|
||||
#define TASK_PRIORITY 0
|
||||
#define TASK_STACK_SIZE 65535
|
||||
|
||||
#define CMD_DIE CMD_NONSTD+1
|
||||
|
||||
void ide_task();
|
||||
|
||||
86
newstyle.h
Normal file
86
newstyle.h
Normal file
@ -0,0 +1,86 @@
|
||||
#ifndef DEVICES_NEWSTYLE_H
|
||||
#define DEVICES_NEWSTYLE_H
|
||||
/*------------------------------------------------------------------------*/
|
||||
/*
|
||||
* $Id: newstyle.h 1.1 1997/05/15 18:53:15 heinz Exp $
|
||||
*
|
||||
* Support header for the New Style Device standard
|
||||
*
|
||||
* (C)1996-1997 by Amiga International, Inc.
|
||||
*
|
||||
*/
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* At the moment there is just a single new style general command:
|
||||
*/
|
||||
|
||||
#define NSCMD_DEVICEQUERY 0x4000
|
||||
|
||||
struct NSDeviceQueryResult {
|
||||
/*
|
||||
** Standard information, must be reset for every query
|
||||
*/
|
||||
ULONG DevQueryFormat; /* this is type 0 */
|
||||
ULONG SizeAvailable; /* bytes available */
|
||||
|
||||
/*
|
||||
** Common information (READ ONLY!)
|
||||
*/
|
||||
UWORD DeviceType; /* what the device does */
|
||||
UWORD DeviceSubType; /* depends on the main type */
|
||||
UWORD *SupportedCommands; /* 0 terminated list of cmd's */
|
||||
|
||||
/* May be extended in the future! Check SizeAvailable! */
|
||||
};
|
||||
|
||||
|
||||
#define NSDEVTYPE_UNKNOWN 0 /* No suitable category, anything */
|
||||
#define NSDEVTYPE_GAMEPORT 1 /* like gameport.device */
|
||||
#define NSDEVTYPE_TIMER 2 /* like timer.device */
|
||||
#define NSDEVTYPE_KEYBOARD 3 /* like keyboard.device */
|
||||
#define NSDEVTYPE_INPUT 4 /* like input.device */
|
||||
#define NSDEVTYPE_TRACKDISK 5 /* like trackdisk.device */
|
||||
#define NSDEVTYPE_CONSOLE 6 /* like console.device */
|
||||
#define NSDEVTYPE_SANA2 7 /* A >=SANA2R2 networking device */
|
||||
#define NSDEVTYPE_AUDIO 8 /* like audio.device */
|
||||
#define NSDEVTYPE_CLIPBOARD 9 /* like clipboard.device */
|
||||
#define NSDEVTYPE_PRINTER 10 /* like printer.device */
|
||||
#define NSDEVTYPE_SERIAL 11 /* like serial.device */
|
||||
#define NSDEVTYPE_PARALLEL 12 /* like parallel.device */
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* The following defines should really be part of device specific
|
||||
* includes. So we protect them from being redefined.
|
||||
*/
|
||||
#ifndef NSCMD_TD_READ64
|
||||
/*
|
||||
* An early new style trackdisk like device can also return this
|
||||
* new identifier for TD_GETDRIVETYPE. This should no longer
|
||||
* be the case though for newly written or updated NSD devices.
|
||||
* This identifier is ***OBSOLETE***
|
||||
*/
|
||||
|
||||
#define DRIVE_NEWSTYLE (0x4E535459L) /* 'NSTY' */
|
||||
|
||||
|
||||
/*
|
||||
* At the moment, only four new style commands in the device
|
||||
* specific range and their ETD counterparts may be implemented.
|
||||
*/
|
||||
|
||||
#define NSCMD_TD_READ64 0xC000
|
||||
#define NSCMD_TD_WRITE64 0xC001
|
||||
#define NSCMD_TD_SEEK64 0xC002
|
||||
#define NSCMD_TD_FORMAT64 0xC003
|
||||
|
||||
#define NSCMD_ETD_READ64 0xE000
|
||||
#define NSCMD_ETD_WRITE64 0xE001
|
||||
#define NSCMD_ETD_SEEK64 0xE002
|
||||
#define NSCMD_ETD_FORMAT64 0xE003
|
||||
#endif /* NSCMD_TD_READ64 */
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
#endif /* DEVICES_NEWSTYLE_H */
|
||||
190
scsi.h
190
scsi.h
@ -1,146 +1,44 @@
|
||||
enum scsi_commands {
|
||||
SCSICMD_TEST_UNIT_READY = 0x00,
|
||||
SCSICMD_REWIND = 0x01,
|
||||
SCSICMD_REQUEST_SENSE = 0x03,
|
||||
SCSICMD_FORMAT = 0x04,
|
||||
SCSICMD_READ_BLOCK_LIMITS = 0x05,
|
||||
SCSICMD_REASSIGN_BLOCKS = 0x07,
|
||||
SCSICMD_INITIALIZE_ELEMENT_STATUS = 0x07,
|
||||
SCSICMD_READ_6 = 0x08,
|
||||
SCSICMD_WRITE_6 = 0x0A,
|
||||
SCSICMD_SEEK_6 = 0x0B,
|
||||
SCSICMD_READ_REVERSE_6 = 0x0F,
|
||||
SCSICMD_WRITE_FILEMARKS_6 = 0x10,
|
||||
SCSICMD_SPACE_6 = 0x11,
|
||||
SCSICMD_INQUIRY = 0x12,
|
||||
SCSICMD_VERIFY_6 = 0x13,
|
||||
SCSICMD_RECOVER_BUFFERED_DATA = 0x14,
|
||||
SCSICMD_MODE_SELECT_6 = 0x15,
|
||||
SCSICMD_RESERVE_6 = 0x16,
|
||||
SCSICMD_RELEASE_6 = 0x17,
|
||||
SCSICMD_COPY = 0x18,
|
||||
SCSICMD_ERASE_6 = 0x19,
|
||||
SCSICMD_MODE_SENSE_6 = 0x1A,
|
||||
SCSICMD_START_STOP_UNIT = 0x1B,
|
||||
SCSICMD_LOAD_UNLOAD = 0x1B,
|
||||
SCSICMD_RECEIVE_DIAGNOSTIC_RESULTS = 0x1C,
|
||||
SCSICMD_SEND_DIAGNOSTIC = 0x1D,
|
||||
SCSICMD_PREVENT_ALLOW_MEDIUM_REMOVAL = 0x1E,
|
||||
SCSICMD_READ_FORMAT_CAPACITIES = 0x23,
|
||||
SCSICMD_READ_CAPACITY_10 = 0x25,
|
||||
SCSICMD_READ_10 = 0x28,
|
||||
SCSICMD_READ_GENERATION = 0x29,
|
||||
SCSICMD_WRITE_10 = 0x2A,
|
||||
SCSICMD_SEEK_10 = 0x2B,
|
||||
SCSICMD_LOCATE_10 = 0x2B,
|
||||
SCSICMD_ERASE_10 = 0x2C,
|
||||
SCSICMD_READ_UPDATED_BLOCK = 0x2D,
|
||||
SCSICMD_WRITE_AND_VERIFY_10 = 0x2E,
|
||||
SCSICMD_VERIFY_10 = 0x2F,
|
||||
SCSICMD_SET_LIMITS_10 = 0x33,
|
||||
SCSICMD_PREFETCH_10 = 0x34,
|
||||
SCSICMD_READ_POSITION = 0x34,
|
||||
SCSICMD_SYNCHRONIZE_CACHE_10 = 0x35,
|
||||
SCSICMD_LOCK_UNLOCK_CACHE_10 = 0x36,
|
||||
SCSICMD_READ_DEFECT_DATA_10 = 0x37,
|
||||
SCSICMD_INITIALIZE_ELEMENT_STATUS_WITH_RANGE = 0x37,
|
||||
SCSICMD_MEDIUM_SCAN = 0x38,
|
||||
SCSICMD_COMPARE = 0x39,
|
||||
SCSICMD_COPY_AND_VERIFY = 0x3A,
|
||||
SCSICMD_WRITE_BUFFER = 0x3B,
|
||||
SCSICMD_READ_BUFFER = 0x3C,
|
||||
SCSICMD_UPDATE_BLOCK = 0x3D,
|
||||
SCSICMD_READ_LONG_10 = 0x3E,
|
||||
SCSICMD_WRITE_LONG_10 = 0x3F,
|
||||
SCSICMD_CHANGE_DEFINITION = 0x40,
|
||||
SCSICMD_WRITE_SAME_10 = 0x41,
|
||||
SCSICMD_UNMAP = 0x42,
|
||||
SCSICMD_READ_TOC_PMA_ATIP = 0x43,
|
||||
SCSICMD_REPORT_DENSITY_SUPPORT = 0x44,
|
||||
SCSICMD_PLAY_AUDIO_10 = 0x45,
|
||||
SCSICMD_GET_CONFIGURATION = 0x46,
|
||||
SCSICMD_PLAY_AUDIO_MSF = 0x47,
|
||||
SCSICMD_SANITIZE = 0x48,
|
||||
SCSICMD_GET_EVENT_STATUS_NOTIFICATION = 0x4A,
|
||||
SCSICMD_PAUSE_RESUME = 0x4B,
|
||||
SCSICMD_LOG_SELECT = 0x4C,
|
||||
SCSICMD_LOG_SENSE = 0x4D,
|
||||
SCSICMD_XDWRITE_10 = 0x50,
|
||||
SCSICMD_XPWRITE_10 = 0x51,
|
||||
SCSICMD_READ_DISC_INFORMATION = 0x51,
|
||||
SCSICMD_XDREAD_10 = 0x52,
|
||||
SCSICMD_XDWRITEREAD_10 = 0x53,
|
||||
SCSICMD_SEND_OPC_INFORMATION = 0x54,
|
||||
SCSICMD_MODE_SELECT_10 = 0x55,
|
||||
SCSICMD_RESERVE_10 = 0x56,
|
||||
SCSICMD_RELEASE_10 = 0x57,
|
||||
SCSICMD_REPAIR_TRACK = 0x58,
|
||||
SCSICMD_MODE_SENSE_10 = 0x5A,
|
||||
SCSICMD_CLOSE_TRACK_SESSION = 0x5B,
|
||||
SCSICMD_READ_BUFFER_CAPACITY = 0x5C,
|
||||
SCSICMD_SEND_CUE_SHEET = 0x5D,
|
||||
SCSICMD_PERSISTENT_RESERVE_IN = 0x5E,
|
||||
SCSICMD_PERSISTENT_RESERVE_OUT = 0x5F,
|
||||
SCSICMD_EXTENDED_CDB = 0x7E,
|
||||
SCSICMD_VARIABLELENGTH_CDB = 0x7F,
|
||||
SCSICMD_XDWRITE_EXTENDED_16 = 0x80,
|
||||
SCSICMD_WRITE_FILEMARKS_16 = 0x80,
|
||||
SCSICMD_READ_REVERSE_16 = 0x81,
|
||||
SCSICMD_3RDPARTY_COPY_OUT_CMDS = 0x83,
|
||||
SCSICMD_3RDPARTY_COPY_IN_CMDS = 0x84,
|
||||
SCSICMD_ATA_PASSTHROUGH_16 = 0x85,
|
||||
SCSICMD_ACCESS_CONTROL_IN = 0x86,
|
||||
SCSICMD_ACCESS_CONTROL_OUT = 0x87,
|
||||
SCSICMD_READ_16 = 0x88,
|
||||
SCSICMD_COMPARE_AND_WRITE = 0x89,
|
||||
SCSICMD_WRITE_16 = 0x8A,
|
||||
SCSICMD_ORWRITE = 0x8B,
|
||||
SCSICMD_READ_ATTRIBUTE = 0x8C,
|
||||
SCSICMD_WRITE_ATTRIBUTE = 0x8D,
|
||||
SCSICMD_WRITE_AND_VERIFY_16 = 0x8E,
|
||||
SCSICMD_VERIFY_16 = 0x8F,
|
||||
SCSICMD_PREFETCH_16 = 0x90,
|
||||
SCSICMD_SYNCHRONIZE_CACHE_16 = 0x91,
|
||||
SCSICMD_SPACE_16 = 0x91,
|
||||
SCSICMD_LOCK_UNLOCK_CACHE_16 = 0x92,
|
||||
SCSICMD_LOCATE_16 = 0x92,
|
||||
SCSICMD_WRITE_SAME_16 = 0x93,
|
||||
SCSICMD_ERASE_16 = 0x93,
|
||||
SCSICMD_SERVICE_ACTION_BIDIRECTIONAL = 0x9D,
|
||||
SCSICMD_SERVICE_ACTION_IN_16 = 0x9E,
|
||||
SCSICMD_SERVICE_ACTION_OUT_16 = 0x9F,
|
||||
SCSICMD_REPORT_LUNS = 0xA0,
|
||||
SCSICMD_ATA_PASSTHROUGH_12 = 0xA1,
|
||||
SCSICMD_SECURITY_PROTOCOL_IN = 0xA2,
|
||||
SCSICMD_MAINTENANCE_IN = 0xA3,
|
||||
SCSICMD_MAINTENANCE_OUT = 0xA4,
|
||||
SCSICMD_REPORT_KEY = 0xA4,
|
||||
SCSICMD_MOVE_MEDIUM = 0xA5,
|
||||
SCSICMD_PLAY_AUDIO_12 = 0xA5,
|
||||
SCSICMD_EXCHANGE_MEDIUM = 0xA6,
|
||||
SCSICMD_MOVE_MEDIUM_ATTACHED = 0xA7,
|
||||
SCSICMD_READ_12 = 0xA8,
|
||||
SCSICMD_SERVICE_ACTION_OUT_12 = 0xA9,
|
||||
SCSICMD_WRITE_12 = 0xAA,
|
||||
SCSICMD_SERVICE_ACTION_IN_12 = 0xAB,
|
||||
SCSICMD_ERASE_12 = 0xAC,
|
||||
SCSICMD_READ_DVD_STRUCTURE = 0xAD,
|
||||
SCSICMD_WRITE_AND_VERIFY_12 = 0xAE,
|
||||
SCSICMD_VERIFY_12 = 0xAF,
|
||||
SCSICMD_SEARCH_DATA_HIGH_12 = 0xB0,
|
||||
SCSICMD_SEARCH_DATA_EQUAL_12 = 0xB1,
|
||||
SCSICMD_SEARCH_DATA_LOW_12 = 0xB2,
|
||||
SCSICMD_SET_LIMITS_12 = 0xB3,
|
||||
SCSICMD_READ_ELEMENT_STATUS_ATTACHED = 0xB4,
|
||||
SCSICMD_SECURITY_PROTOCOL_OUT = 0xB5,
|
||||
SCSICMD_SEND_VOLUME_TAG = 0xB6,
|
||||
SCSICMD_READ_DEFECT_DATA_12 = 0xB7,
|
||||
SCSICMD_READ_ELEMENT_STATUS = 0xB8,
|
||||
SCSICMD_READ_CD_MSF = 0xB9,
|
||||
SCSICMD_REDUNDANCY_GROUP_IN = 0xBA,
|
||||
SCSICMD_REDUNDANCY_GROUP_OUT = 0xBB,
|
||||
SCSICMD_SPARE_IN = 0xBC,
|
||||
SCSICMD_SPARE_OUT = 0xBD,
|
||||
SCSICMD_VOLUME_SET_IN = 0xBE,
|
||||
SCSICMD_VOLUME_SET_OUT = 0xBF,
|
||||
};
|
||||
#define SCSICMD_TEST_UNIT_READY 0x00
|
||||
#define SCSICMD_READ_6 0x08
|
||||
#define SCSICMD_WRITE_6 0x0A
|
||||
#define SCSICMD_INQUIRY 0x12
|
||||
#define SCSICMD_READ_CAPACITY_10 0x25
|
||||
#define SCSICMD_READ_10 0x28
|
||||
#define SCSICMD_WRITE_10 0x2A
|
||||
|
||||
|
||||
struct __attribute__((packed)) SCSI_Inquiry {
|
||||
UBYTE peripheral_type;
|
||||
UBYTE removable_media;
|
||||
UBYTE version;
|
||||
UBYTE response_format;
|
||||
UBYTE additional_length;
|
||||
UBYTE flags[3];
|
||||
UBYTE vendor[8];
|
||||
UBYTE product[16];
|
||||
UBYTE revision[4];
|
||||
UBYTE serial[8];
|
||||
};
|
||||
|
||||
struct __attribute__((packed)) SCSI_CDB_6 {
|
||||
UBYTE operation;
|
||||
UBYTE lba_high;
|
||||
UBYTE lba_mid;
|
||||
UBYTE lba_low;
|
||||
UBYTE length;
|
||||
UBYTE control;
|
||||
};
|
||||
|
||||
struct __attribute__((packed)) SCSI_CDB_10 {
|
||||
UBYTE operation;
|
||||
UBYTE flags;
|
||||
ULONG lba;
|
||||
UBYTE group;
|
||||
UWORD length;
|
||||
UBYTE control;
|
||||
};
|
||||
|
||||
struct __attribute__((packed)) SCSI_CAPACITY_10 {
|
||||
ULONG lba;
|
||||
ULONG block_size;
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user