mirror of
https://github.com/LIV2/lide.device.git
synced 2025-12-06 00:32:45 +00:00
Compare commits
13 Commits
6d225fc48c
...
b5db233bf3
| Author | SHA1 | Date | |
|---|---|---|---|
| b5db233bf3 | |||
| e335f918cf | |||
| c40d60cde2 | |||
| 7de82869c3 | |||
| 2f25b5c1e8 | |||
| 368d716889 | |||
| 2f5549694e | |||
| 5124c1c830 | |||
| 27abd230db | |||
| 2334829164 | |||
| 588508bcb1 | |||
|
|
d13d1db81a | ||
| d774d359fe |
2
.github/workflows/coverity.yml
vendored
2
.github/workflows/coverity.yml
vendored
@ -10,7 +10,7 @@ on:
|
||||
jobs:
|
||||
coverity:
|
||||
runs-on: ubuntu-latest
|
||||
container: stefanreinauer/amiga-gcc
|
||||
container: liv2/amiga-gcc
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
|
||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@ -12,7 +12,7 @@ on:
|
||||
jobs:
|
||||
make_software:
|
||||
runs-on: ubuntu-latest
|
||||
container: liv2/amiga-gcc-amitools
|
||||
container: liv2/amiga-gcc
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
12
Makefile
12
Makefile
@ -56,6 +56,11 @@ CFLAGS+= -DSIMPLE_IDE=1
|
||||
.PHONY: $(PROJECT)
|
||||
endif
|
||||
|
||||
ifdef AMIGAPCI
|
||||
CFLAGS+= -DAMIGAPCI=1
|
||||
.PHONY: $(PROJECT)
|
||||
endif
|
||||
|
||||
.PHONY: clean all lideflash disk lha rename/renamelide lidetool/lidetool
|
||||
|
||||
all: $(ROM) \
|
||||
@ -63,7 +68,8 @@ all: $(ROM) \
|
||||
rename/renamelide \
|
||||
lide-N2630-high.rom \
|
||||
lide-N2630-low.rom \
|
||||
AIDE-$(PROJECT)
|
||||
AIDE-$(PROJECT) \
|
||||
amigapci-$(PROJECT)
|
||||
|
||||
OBJ = device.o \
|
||||
ata.o \
|
||||
@ -88,6 +94,9 @@ $(ROM): $(PROJECT)
|
||||
AIDE-$(PROJECT): $(SRCS)
|
||||
${CC} -o $@ $(CFLAGS) -DSIMPLE_IDE=1 $(SRCS) bootblock.S $(LDFLAGS)
|
||||
|
||||
amigapci-$(PROJECT): $(SRCS)
|
||||
${CC} -o $@ $(CFLAGS) -DAMIGAPCI=1 $(SRCS) bootblock.S $(LDFLAGS)
|
||||
|
||||
lideflash/lideflash:
|
||||
make -C lideflash
|
||||
|
||||
@ -148,6 +157,7 @@ lide-tk-29F040.rom: lide-tk-29F020.rom
|
||||
clean:
|
||||
-rm -f $(PROJECT)
|
||||
-rm -f AIDE-$(PROJECT)
|
||||
-rm -f amigapci-$(PROJECT)
|
||||
make -C bootrom clean
|
||||
make -C lideflash clean
|
||||
make -C lidetool clean
|
||||
|
||||
13
README.md
13
README.md
@ -102,13 +102,14 @@ There are several options for larger drive support
|
||||
Also make sure to use the "Quick Format" option when formatting such partitions
|
||||
|
||||
## Hardware implementation
|
||||
* IDECS1 is asserted when A12 is low and the IDE device's base address is decoded
|
||||
* IDECS2 is asserted as above but when A13 is low rather than A12
|
||||
* IDECS2 can instead be routed to a second IDE channel as it's IDECS1 and the driver will detect this
|
||||
* IDE interface is byte-swapped
|
||||
* Buffered interface
|
||||
* IDECS1 asserted at offset 0x1000
|
||||
* IDECS2 asserted at offset 0x2000
|
||||
* A secondary channel is supported when the second channel's IDECS1 is decoded at offset 0x2000 and IDECS2 of both primary and secondary channels is pulled high
|
||||
* D15/14 pulled up with a 10K resistor to allow detection of floating bus when no drive present.
|
||||
* IDE A0/1/2 connected to CPU A9/10/11 providing 512 Byte separation of registers to allow for MOVEM trick
|
||||
* No interrupts
|
||||
* IDE interface is byte-swapped
|
||||
* Buffered interface
|
||||
* Configure as a 128K board to permit loading CDFS from ROM **(Optional)**
|
||||
* Hardware support of programming the flash **(Optional)**
|
||||
|
||||
@ -123,7 +124,7 @@ Building this code will require the following
|
||||
The easiest way to get a working build environment is to use Docker
|
||||
You can build inside docker as follows:
|
||||
```
|
||||
docker run --rm -it -v ${PWD}:${PWD} -w ${PWD} stefanreinauer/amiga-gcc:latest make clean all
|
||||
docker run --rm -it -v ${PWD}:${PWD} -w ${PWD} liv2/amiga-gcc:latest make clean all
|
||||
```
|
||||
|
||||
If you are using VS Code you can install the "Dev containers" extension which will allow you to develop with the environment ready to go.
|
||||
|
||||
75
ata.c
75
ata.c
@ -21,9 +21,9 @@
|
||||
#include "sleep.h"
|
||||
#include "lide_alib.h"
|
||||
|
||||
static BYTE write_taskfile_lba(struct IDEUnit *unit, UBYTE command, ULONG lba, UBYTE sectorCount, UBYTE features);
|
||||
static BYTE write_taskfile_lba48(struct IDEUnit *unit, UBYTE command, ULONG lba, UBYTE sectorCount, UBYTE features);
|
||||
static BYTE write_taskfile_chs(struct IDEUnit *unit, UBYTE command, ULONG lba, UBYTE sectorCount, UBYTE features);
|
||||
static BYTE write_taskfile_lba(struct IDEUnit *unit, UBYTE command, unsigned long long lba, UBYTE sectorCount, UBYTE features);
|
||||
static BYTE write_taskfile_lba48(struct IDEUnit *unit, UBYTE command, unsigned long long, UBYTE sectorCount, UBYTE features);
|
||||
static BYTE write_taskfile_chs(struct IDEUnit *unit, UBYTE command, unsigned long long lba, UBYTE sectorCount, UBYTE features);
|
||||
|
||||
/**
|
||||
* ata_status_reg_delay
|
||||
@ -229,14 +229,14 @@ bool ata_identify(struct IDEUnit *unit, UWORD *buffer)
|
||||
|
||||
/**
|
||||
* ata_bench
|
||||
*
|
||||
*
|
||||
* Measure the amount of E Clock ticks taken to transfer 512K from the unit
|
||||
*
|
||||
*
|
||||
* @param unit Pointer to an IDEUnit struct
|
||||
* @param xfer_routine Pointer to one of the transfer routines
|
||||
* @param buffer pointer to a 512 byte buffer
|
||||
* @return tick count
|
||||
*
|
||||
*
|
||||
*/
|
||||
static ULONG ata_bench(struct IDEUnit *unit, ata_xfer_func xfer_routine, void *buffer) {
|
||||
struct ExecBase *SysBase = unit->SysBase;
|
||||
@ -269,9 +269,9 @@ static ULONG ata_bench(struct IDEUnit *unit, ata_xfer_func xfer_routine, void *b
|
||||
|
||||
/**
|
||||
* ata_autoselect_xfer
|
||||
*
|
||||
*
|
||||
* Set the transfer method for the unit based on the CPU, Board type and benchmark result
|
||||
*
|
||||
*
|
||||
* @param unit Pointer to an IDEUnit struct
|
||||
* @return transfer method
|
||||
*/
|
||||
@ -287,11 +287,11 @@ static enum xfer ata_autoselect_xfer(struct IDEUnit *unit) {
|
||||
// longword_movem will always be faster on a standard 68000
|
||||
if ((SysBase->AttnFlags & (AFF_68020 | AFF_68030 | AFF_68040 | AFF_68060)) == 0)
|
||||
return longword_movem;
|
||||
|
||||
|
||||
// ReadEClock needed by ata_bench not supported before Kick 2.0
|
||||
if (SysBase->LibNode.lib_Version < 36)
|
||||
return longword_movem;
|
||||
|
||||
|
||||
if ((buf = AllocMem(512,MEMF_ANY))) {
|
||||
enum xfer method;
|
||||
ticks = ata_bench(unit,ata_read_long_movem,buf);
|
||||
@ -309,9 +309,9 @@ static enum xfer ata_autoselect_xfer(struct IDEUnit *unit) {
|
||||
|
||||
/**
|
||||
* ata_set_xfer
|
||||
*
|
||||
*
|
||||
* Sets the transfer routine for the unit
|
||||
*
|
||||
*
|
||||
* @param unit Pointer to an IDEUnit strict
|
||||
* @param method Transfer routine
|
||||
*/
|
||||
@ -357,7 +357,7 @@ bool ata_init_unit(struct IDEUnit *unit, void *base) {
|
||||
|
||||
UWORD *buf;
|
||||
bool dev_found = false;
|
||||
|
||||
|
||||
unit->drive.data = (UWORD*) (base + ata_reg_data);
|
||||
unit->drive.error_features = (UBYTE*) (base + ata_reg_error);
|
||||
unit->drive.sectorCount = (UBYTE*) (base + ata_reg_sectorCount);
|
||||
@ -412,16 +412,14 @@ bool ata_init_unit(struct IDEUnit *unit, void *base) {
|
||||
|
||||
// Support LBA-48 but only up to 2TB
|
||||
if ((buf[ata_identify_features] & ata_feature_lba48) && unit->logicalSectors >= 0xFFFFFFF) {
|
||||
if (buf[ata_identify_lba48_sectors + 2] > 0 ||
|
||||
buf[ata_identify_lba48_sectors + 3] > 0) {
|
||||
Info("INIT: Rejecting drive larger than 2TB\n");
|
||||
goto ident_failed;
|
||||
}
|
||||
|
||||
unit->flags.lba48 = true;
|
||||
Info("INIT: Drive supports LBA48 mode \n");
|
||||
unit->logicalSectors = (buf[ata_identify_lba48_sectors + 1] << 16 |
|
||||
buf[ata_identify_lba48_sectors]);
|
||||
Info("INIT: Large drive, using LBA48 mode \n");
|
||||
unit->logicalSectors = 0;
|
||||
unit->logicalSectors |= ((unsigned long long)buf[ata_identify_lba48_sectors]) << 0;
|
||||
unit->logicalSectors |= ((unsigned long long)buf[ata_identify_lba48_sectors+1]) << 16;
|
||||
unit->logicalSectors |= ((unsigned long long)buf[ata_identify_lba48_sectors+2]) << 32;
|
||||
|
||||
unit->write_taskfile = &write_taskfile_lba48;
|
||||
|
||||
} else if (unit->flags.lba == true) {
|
||||
@ -441,15 +439,15 @@ bool ata_init_unit(struct IDEUnit *unit, void *base) {
|
||||
|
||||
if (unit->logicalSectors >= 267382800) {
|
||||
// For drives larger than 127GB fudge the geometry
|
||||
unit->heads = 63;
|
||||
unit->sectorsPerTrack = 255;
|
||||
unit->cylinders = (unit->logicalSectors / (63*255));
|
||||
unit->heads = 64;
|
||||
unit->sectorsPerTrack = 256;
|
||||
unit->cylinders = unit->logicalSectors >> 14;
|
||||
} else if (unit->logicalSectors >= 16514064) {
|
||||
// If a drive is larger than 8GB then the drive will report a geometry of 16383/16/63 (CHS)
|
||||
// In this case generate a new Cylinders value
|
||||
unit->heads = 16;
|
||||
unit->heads = 16;
|
||||
unit->sectorsPerTrack = 255;
|
||||
unit->cylinders = (unit->logicalSectors / (16*255));
|
||||
unit->cylinders = ((ULONG)unit->logicalSectors / (16*255));
|
||||
Info("INIT: Adjusting geometry, new geometry; 16/255/%ld\n",unit->cylinders);
|
||||
}
|
||||
|
||||
@ -483,7 +481,7 @@ ident_failed:
|
||||
Info("INIT: Blockshift: %ld\n",unit->blockShift);
|
||||
unit->flags.present = true;
|
||||
|
||||
Info("INIT: LBAs %ld Blocksize: %ld\n",unit->logicalSectors,unit->blockSize);
|
||||
Info("INIT: LBAs %lld Blocksize: %ld\n",unit->logicalSectors,unit->blockSize);
|
||||
|
||||
if (buf) FreeMem(buf,512);
|
||||
return true;
|
||||
@ -539,7 +537,7 @@ bool ata_set_multiple(struct IDEUnit *unit, BYTE multiple) {
|
||||
* @param unit Pointer to the unit structure
|
||||
* @returns error
|
||||
*/
|
||||
BYTE ata_read(void *buffer, ULONG lba, ULONG count, struct IDEUnit *unit) {
|
||||
BYTE ata_read(void *buffer, unsigned long long lba, ULONG count, struct IDEUnit *unit) {
|
||||
Trace("ata_read enter\n");
|
||||
Trace("ATA: Request sector count: %ld\n",count);
|
||||
|
||||
@ -627,7 +625,7 @@ BYTE ata_read(void *buffer, ULONG lba, ULONG count, struct IDEUnit *unit) {
|
||||
* @param unit Pointer to the unit structure
|
||||
* @returns error
|
||||
*/
|
||||
BYTE ata_write(void *buffer, ULONG lba, ULONG count, struct IDEUnit *unit) {
|
||||
BYTE ata_write(void *buffer, unsigned long long lba, ULONG count, struct IDEUnit *unit) {
|
||||
Trace("ata_write enter\n");
|
||||
Trace("ATA: Request sector count: %ld\n",count);
|
||||
|
||||
@ -748,10 +746,11 @@ void ata_write_unaligned_long(void *source asm("a0"), void *destination asm("a1"
|
||||
* @param unit Pointer to an IDEUnit struct
|
||||
* @param lba Pointer to the LBA variable
|
||||
*/
|
||||
static BYTE write_taskfile_chs(struct IDEUnit *unit, UBYTE command, ULONG lba, UBYTE sectorCount, UBYTE features) {
|
||||
UWORD cylinder = (lba / (unit->heads * unit->sectorsPerTrack));
|
||||
UBYTE head = ((lba / unit->sectorsPerTrack) % unit->heads) & 0xF;
|
||||
UBYTE sector = (lba % unit->sectorsPerTrack) + 1;
|
||||
static BYTE write_taskfile_chs(struct IDEUnit *unit, UBYTE command, unsigned long long lba, UBYTE sectorCount, UBYTE features) {
|
||||
|
||||
UWORD cylinder = ((ULONG)lba / (unit->heads * unit->sectorsPerTrack));
|
||||
UBYTE head = (((ULONG)lba / unit->sectorsPerTrack) % unit->heads) & 0xF;
|
||||
UBYTE sector = ((ULONG)lba % unit->sectorsPerTrack) + 1;
|
||||
|
||||
BYTE devHead;
|
||||
|
||||
@ -778,7 +777,7 @@ static BYTE write_taskfile_chs(struct IDEUnit *unit, UBYTE command, ULONG lba, U
|
||||
* @param unit Pointer to an IDEUnit struct
|
||||
* @param lba Pointer to the LBA variable
|
||||
*/
|
||||
static BYTE write_taskfile_lba(struct IDEUnit *unit, UBYTE command, ULONG lba, UBYTE sectorCount, UBYTE features) {
|
||||
static BYTE write_taskfile_lba(struct IDEUnit *unit, UBYTE command, unsigned long long lba, UBYTE sectorCount, UBYTE features) {
|
||||
BYTE devHead;
|
||||
|
||||
if (!ata_wait_ready(unit,ATA_RDY_WAIT_COUNT))
|
||||
@ -804,14 +803,14 @@ static BYTE write_taskfile_lba(struct IDEUnit *unit, UBYTE command, ULONG lba, U
|
||||
* @param unit Pointer to an IDEUnit struct
|
||||
* @param lba Pointer to the LBA variable
|
||||
*/
|
||||
static BYTE write_taskfile_lba48(struct IDEUnit *unit, UBYTE command, ULONG lba, UBYTE sectorCount, UBYTE features) {
|
||||
static BYTE write_taskfile_lba48(struct IDEUnit *unit, UBYTE command, unsigned long long lba, UBYTE sectorCount, UBYTE features) {
|
||||
|
||||
if (!ata_wait_ready(unit,ATA_RDY_WAIT_COUNT))
|
||||
return HFERR_SelTimeout;
|
||||
|
||||
*unit->drive.sectorCount = (sectorCount == 0) ? 1 : 0;
|
||||
*unit->drive.lbaHigh = 0;
|
||||
*unit->drive.lbaMid = 0;
|
||||
*unit->drive.lbaHigh = (UBYTE)(lba >> 40);
|
||||
*unit->drive.lbaMid = (UBYTE)(lba >> 32);
|
||||
*unit->drive.lbaLow = (UBYTE)(lba >> 24);
|
||||
*unit->drive.sectorCount = sectorCount; // Count value of 0 indicates to transfer 256 sectors
|
||||
*unit->drive.lbaHigh = (UBYTE)(lba >> 16);
|
||||
@ -828,7 +827,7 @@ static BYTE write_taskfile_lba48(struct IDEUnit *unit, UBYTE command, ULONG lba,
|
||||
/**
|
||||
* ata_set_pio
|
||||
*
|
||||
* @param unit Pointer t oan IDEUnit struct
|
||||
* @param unit Pointer to an IDEUnit struct
|
||||
* @param pio pio mode
|
||||
*/
|
||||
BYTE ata_set_pio(struct IDEUnit *unit, UBYTE pio) {
|
||||
|
||||
6
ata.h
6
ata.h
@ -16,8 +16,6 @@
|
||||
|
||||
#ifdef SIMPLE_IDE
|
||||
|
||||
#define NO_AUTOCONFIG
|
||||
|
||||
#define BOARD_BASE 0xEF0000
|
||||
#define CHANNEL_0 0x2000
|
||||
#define CHANNEL_1 0x1000
|
||||
@ -110,8 +108,8 @@ bool ata_identify(struct IDEUnit *, UWORD *);
|
||||
bool ata_set_multiple(struct IDEUnit *unit, BYTE multiple);
|
||||
void ata_set_xfer(struct IDEUnit *unit, enum xfer method);
|
||||
|
||||
BYTE ata_read(void *buffer, ULONG lba, ULONG count, struct IDEUnit *unit);
|
||||
BYTE ata_write(void *buffer, ULONG lba, ULONG count, struct IDEUnit *unit);
|
||||
BYTE ata_read(void *buffer, unsigned long long lba, ULONG count, struct IDEUnit *unit);
|
||||
BYTE ata_write(void *buffer, unsigned long long lba, ULONG count, struct IDEUnit *unit);
|
||||
BYTE ata_set_pio(struct IDEUnit *unit, UBYTE pio);
|
||||
BYTE scsi_ata_passthrough( struct IDEUnit *unit, struct SCSICmd *cmd);
|
||||
|
||||
|
||||
16
atapi.c
16
atapi.c
@ -79,7 +79,7 @@ static bool atapi_wait_drq_not_bsy(struct IDEUnit *unit, ULONG tries) {
|
||||
*
|
||||
* Polls the BSY bit in the status register until cleared, an error occurs, or the timeout is reached.
|
||||
*
|
||||
* For long-running commands (e.g., FORMAT UNIT, BLANK, up to 30 minutes), uses timer-based waits (1 ms per poll) to yield to other tasks, ensuring AmigaOS multitasking friendliness.
|
||||
* For long-running commands (e.g., FORMAT UNIT, BLANK, up to 30 minutes), uses timer-based waits (1 ms per poll) to yield to other tasks, ensuring AmigaOS multitasking friendliness.
|
||||
* For faster commands (e.g., READ (10), WRITE (10)), uses a ~1.4 µs delay via CIA register reads for CPU-independent timing and high throughput.
|
||||
*
|
||||
* Timeout durations:
|
||||
@ -733,7 +733,7 @@ BYTE atapi_get_capacity(struct IDEUnit *unit) {
|
||||
if ((ret = atapi_packet(cmd,unit)) == 0) {
|
||||
unit->logicalSectors = capacity.logicalSectors + 1;
|
||||
unit->blockSize = capacity.blockSize;
|
||||
|
||||
|
||||
while ((unit->blockSize >> unit->blockShift) > 1) {
|
||||
unit->blockShift++;
|
||||
}
|
||||
@ -848,7 +848,7 @@ BYTE atapi_scsi_mode_sense_6(struct SCSICmd *cmd, struct IDEUnit *unit) {
|
||||
dest[1] = buf[2]; // Medium type
|
||||
dest[2] = buf[3]; // WP/DPOFUA Flags
|
||||
dest[3] = buf[7]; // Block descriptor length
|
||||
|
||||
|
||||
// Copy the mode sense data
|
||||
for (int i = 0; i < (cmd_sense->scsi_Actual - 8); i++) {
|
||||
dest[i+4] = buf[i+8];
|
||||
@ -923,7 +923,7 @@ BYTE atapi_scsi_mode_select_6(struct SCSICmd *cmd, struct IDEUnit *unit) {
|
||||
dst[2] = src[1]; // Mediun Type
|
||||
dst[3] = src[2]; // Device specific parameter
|
||||
dst[7] = src[3]; // Block descriptor length
|
||||
|
||||
|
||||
// Copy the Mode Parameters
|
||||
len = bufSize - 8;
|
||||
CopyMem(src + 4, dst + 8, len);
|
||||
@ -1039,11 +1039,11 @@ BYTE atapi_start_stop_unit(struct IDEUnit *unit, bool start, bool loej, bool imm
|
||||
|
||||
if (loej) operation |= (1<<1);
|
||||
if (start) operation |= (1<<0);
|
||||
|
||||
|
||||
BYTE cdb[10] = {0};
|
||||
struct SCSI_FIXED_SENSE sense;
|
||||
memset(&sense,0,sizeof(struct SCSI_FIXED_SENSE));
|
||||
|
||||
|
||||
struct SCSICmd cmd = {
|
||||
.scsi_Command = (APTR)&cdb,
|
||||
.scsi_CmdActual = 0,
|
||||
@ -1340,7 +1340,7 @@ BYTE atapi_autosense(struct SCSICmd *scsi_command, struct IDEUnit *unit) {
|
||||
|
||||
if (scsi_command->scsi_SenseData == NULL || scsi_command->scsi_SenseLength == 0)
|
||||
return IOERR_BADADDRESS;
|
||||
|
||||
|
||||
struct SCSICmd *cmd = MakeSCSICmd(SZ_CDB_12);
|
||||
|
||||
if (cmd != NULL) {
|
||||
@ -1351,7 +1351,7 @@ BYTE atapi_autosense(struct SCSICmd *scsi_command, struct IDEUnit *unit) {
|
||||
cmd->scsi_Length = scsi_command->scsi_SenseLength;
|
||||
cmd->scsi_Flags = SCSIF_READ;
|
||||
cmd->scsi_CmdLength = 12;
|
||||
|
||||
|
||||
ret = atapi_packet(cmd,unit);
|
||||
scsi_command->scsi_SenseActual = cmd->scsi_Actual;
|
||||
|
||||
|
||||
@ -294,6 +294,7 @@ RomFetch
|
||||
|
||||
.RomFetchZ ; access type is Zorro
|
||||
move.l d0,d3
|
||||
moveq #0,d0
|
||||
.nextnip
|
||||
lsl.l #8,d0
|
||||
IFND BYTEWIDE
|
||||
|
||||
68
device.c
68
device.c
@ -15,6 +15,7 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "ata.h"
|
||||
#include "atapi.h"
|
||||
@ -26,7 +27,7 @@
|
||||
#include "lide_alib.h"
|
||||
#include "mounter/mounter.h"
|
||||
|
||||
#ifdef NO_AUTOCONFIG
|
||||
#ifdef FAKE_CONFIGDEV
|
||||
extern UBYTE bootblock, bootblock_end;
|
||||
#endif
|
||||
|
||||
@ -108,7 +109,7 @@ char * set_dev_name(struct DeviceBase *dev) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef NO_AUTOCONFIG
|
||||
#ifdef FAKE_CONFIGDEV
|
||||
/**
|
||||
* CreateFakeConfigDev
|
||||
* Create fake ConfigDev and DiagArea to support autoboot without requiring real autoconfig device.
|
||||
@ -200,9 +201,9 @@ static BOOL FindCDFS() {
|
||||
|
||||
/**
|
||||
* ioreq_is_valid
|
||||
*
|
||||
*
|
||||
* Check if the supplied IOReq points to a valid unit
|
||||
*
|
||||
*
|
||||
* @param dev Pointer to DeviceBase
|
||||
* @param ior The ioreq to test
|
||||
* @returns bool
|
||||
@ -268,6 +269,7 @@ static void Cleanup(struct DeviceBase *dev) {
|
||||
FreeMem((char *)dev - dev->lib.lib_NegSize, dev->lib.lib_NegSize + dev->lib.lib_PosSize);
|
||||
}
|
||||
|
||||
#ifndef ATA_CHANNELS
|
||||
/**
|
||||
* detectChannels
|
||||
*
|
||||
@ -328,6 +330,7 @@ static BYTE detectChannels(struct ConfigDev *cd) {
|
||||
return 1;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* init_device
|
||||
@ -410,12 +413,25 @@ struct Library * init_device(struct ExecBase *SysBase asm("a6"), BPTR seg_list a
|
||||
Cleanup(dev);
|
||||
return NULL;
|
||||
}
|
||||
#ifdef BOARD_MANUF_ID
|
||||
struct ConfigDev *realcd;
|
||||
|
||||
if (!(realcd = FindConfigDev(NULL,BOARD_MANUF_ID,BOARD_PROD_ID))) {
|
||||
Info("AmigaPCI IDE not found\n");
|
||||
Cleanup(dev);
|
||||
return NULL;
|
||||
}
|
||||
APTR BOARD_BASE = realcd->cd_BoardAddr;
|
||||
#endif
|
||||
cd->cd_BoardAddr = (APTR)BOARD_BASE;
|
||||
cd->cd_BoardSize = 0x1000;
|
||||
numBoards = 1;
|
||||
#endif
|
||||
#ifndef ATA_CHANNELS
|
||||
UBYTE channels = detectChannels(cd);
|
||||
|
||||
#else
|
||||
UBYTE channels = ATA_CHANNELS;
|
||||
#endif
|
||||
for (int c=0; c < channels; c++) {
|
||||
|
||||
Info("Starting IO Task %ld\n",dev->numTasks);
|
||||
@ -610,8 +626,13 @@ static void td_get_geometry(struct IOStdReq *ioreq) {
|
||||
// Clear the geometry struct beforehand to make sure reserved / unused parts are zero
|
||||
memset(geometry,0,sizeof(struct DriveGeometry));
|
||||
|
||||
if (unit->logicalSectors > ULONG_MAX) {
|
||||
geometry->dg_TotalSectors = ULONG_MAX;
|
||||
} else {
|
||||
geometry->dg_TotalSectors = unit->logicalSectors;
|
||||
}
|
||||
|
||||
geometry->dg_SectorSize = unit->blockSize;
|
||||
geometry->dg_TotalSectors = unit->logicalSectors;
|
||||
geometry->dg_Cylinders = unit->cylinders;
|
||||
geometry->dg_CylSectors = (unit->sectorsPerTrack * unit->heads);
|
||||
geometry->dg_Heads = unit->heads;
|
||||
@ -934,26 +955,31 @@ static const ULONG device_vectors[] =
|
||||
* @param checkFire If true, only modify when gameport 1 button is pressed
|
||||
* @param increment Amount to increase both device and boot node priorities
|
||||
*/
|
||||
void AdjustBootPriority(struct ExecBase *SysBase, char *bootname, struct List *MountList, bool checkFire, int increment) {
|
||||
void AdjustBootPriority(struct ExecBase *SysBase, char *deviceName, char *bootname, struct List *MountList, bool checkFire, int increment) {
|
||||
volatile struct CIA *ciaa = (struct CIA *)0x0bfe001;
|
||||
struct BootNode *bn;
|
||||
struct DeviceNode *dn;
|
||||
struct FileSysStartupMsg *fssm;
|
||||
|
||||
for (bn = (struct BootNode *)MountList->lh_Head;
|
||||
bn->bn_Node.ln_Succ;
|
||||
bn = (struct BootNode *)bn->bn_Node.ln_Succ)
|
||||
{
|
||||
dn = bn->bn_DeviceNode;
|
||||
if (dn->dn_Priority != -128)
|
||||
{
|
||||
if (L_CompareBSTR(BADDR(dn->dn_Name),bootname)) {
|
||||
if(!checkFire || (ciaa->ciapra & CIAF_GAMEPORT1)==0) {
|
||||
dn->dn_Priority+=increment;
|
||||
bn->bn_Node.ln_Pri+=increment;
|
||||
Remove((struct Node *)bn);
|
||||
Enqueue(MountList,(struct Node *)bn);
|
||||
break;
|
||||
}
|
||||
fssm = BADDR(dn->dn_Startup);
|
||||
char *bn_deviceName = (char *)BADDR(fssm->fssm_Device) + 1;
|
||||
|
||||
// Only tweak boot nodes created by this instance
|
||||
if (strcmp(bn_deviceName,deviceName) != 0)
|
||||
continue;
|
||||
|
||||
if (dn->dn_Priority != -128 && L_CompareBSTR(BADDR(dn->dn_Name),bootname)) {
|
||||
if(!checkFire || (ciaa->ciapra & CIAF_GAMEPORT1)==0) {
|
||||
dn->dn_Priority+=increment;
|
||||
bn->bn_Node.ln_Pri+=increment;
|
||||
Remove((struct Node *)bn);
|
||||
Enqueue(MountList,(struct Node *)bn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -969,7 +995,7 @@ void AdjustBootPriority(struct ExecBase *SysBase, char *bootname, struct List *M
|
||||
*
|
||||
* @param SysBase Pointer to the ExecBase system library base
|
||||
*/
|
||||
void TweakBootList(struct ExecBase *SysBase) {
|
||||
void TweakBootList(struct ExecBase *SysBase, char *deviceName) {
|
||||
struct ExpansionBase *ExpansionBase;
|
||||
|
||||
if (ExpansionBase = (struct ExpansionBase *)OpenLibrary("expansion.library",0)) {
|
||||
@ -979,12 +1005,12 @@ void TweakBootList(struct ExecBase *SysBase) {
|
||||
|
||||
Forbid();
|
||||
|
||||
AdjustBootPriority(SysBase,bootname,&ExpansionBase->MountList,true,2);
|
||||
AdjustBootPriority(SysBase,deviceName,bootname,&ExpansionBase->MountList,true,2);
|
||||
|
||||
bootname[5]=0x30+(major/10);
|
||||
bootname[6]=0x30+(major%10);
|
||||
|
||||
AdjustBootPriority(SysBase,bootname,&ExpansionBase->MountList,false,1);
|
||||
AdjustBootPriority(SysBase,deviceName,bootname,&ExpansionBase->MountList,false,1);
|
||||
|
||||
Permit();
|
||||
|
||||
@ -1031,7 +1057,7 @@ static struct Library * init(BPTR seg_list asm("a0"))
|
||||
MountDrive(&ms);
|
||||
|
||||
if (!seg_list) // Only tweak if we're in boot
|
||||
TweakBootList(SysBase);
|
||||
TweakBootList(SysBase,mydev->lib.lib_Node.ln_Name);
|
||||
}
|
||||
done:
|
||||
return (struct Library *)mydev;
|
||||
|
||||
18
device.h
18
device.h
@ -15,6 +15,20 @@
|
||||
|
||||
#define MAX_UNITS 4
|
||||
|
||||
#if AMIGAPCI
|
||||
#define NO_AUTOCONFIG 1
|
||||
// #define BOARD_MANUF_ID 5194
|
||||
// #define BOARD_PROD_ID 7
|
||||
#endif
|
||||
|
||||
#ifdef SIMPLE_IDE
|
||||
#define NO_AUTOCONFIG 1
|
||||
#endif
|
||||
|
||||
#ifdef NO_AUTOCONFIG
|
||||
#define FAKE_CONFIGDEV 1
|
||||
#endif
|
||||
|
||||
// VSCode C/C++ extension doesn't like the asm("<reg>") syntax
|
||||
#ifdef __INTELLISENSE__
|
||||
#define asm(x)
|
||||
@ -47,7 +61,7 @@ struct IDEUnit {
|
||||
struct ExecBase *SysBase;
|
||||
struct IOTask *itask;
|
||||
struct Drive drive;
|
||||
BYTE (*write_taskfile)(struct IDEUnit *, UBYTE, ULONG, UBYTE, UBYTE);
|
||||
BYTE (*write_taskfile)(struct IDEUnit *, UBYTE, unsigned long long, UBYTE, UBYTE);
|
||||
enum xfer xferMethod;
|
||||
ata_xfer_func read_fast;
|
||||
ata_xfer_func write_fast;
|
||||
@ -65,7 +79,7 @@ struct IDEUnit {
|
||||
UWORD blockSize;
|
||||
UWORD blockShift;
|
||||
ULONG cylinders;
|
||||
ULONG logicalSectors;
|
||||
unsigned long long logicalSectors;
|
||||
struct MinList changeInts;
|
||||
UBYTE multipleCount;
|
||||
struct {
|
||||
|
||||
39
iotask.c
39
iotask.c
@ -111,7 +111,7 @@ static BYTE handle_scsi_command(struct IOStdReq *ioreq) {
|
||||
UBYTE *data = (APTR)scsi_command->scsi_Data;
|
||||
UBYTE *command = (APTR)scsi_command->scsi_Command;
|
||||
|
||||
ULONG lba;
|
||||
unsigned long long lba;
|
||||
ULONG count;
|
||||
BYTE error = 0;
|
||||
scsi_command->scsi_SenseActual = 0;
|
||||
@ -144,7 +144,11 @@ static BYTE handle_scsi_command(struct IOStdReq *ioreq) {
|
||||
break;
|
||||
|
||||
case SCSI_CMD_READ_CAPACITY_10:
|
||||
error = scsi_read_capacity_emu(unit,scsi_command);
|
||||
error = scsi_read_capacity_10_emu(unit,scsi_command);
|
||||
break;
|
||||
|
||||
case SCSI_CMD_READ_CAPACITY_16:
|
||||
error = scsi_read_capacity_16_emu(unit,scsi_command);
|
||||
break;
|
||||
|
||||
case SCSI_CMD_READ_6:
|
||||
@ -158,11 +162,17 @@ static BYTE handle_scsi_command(struct IOStdReq *ioreq) {
|
||||
|
||||
case SCSI_CMD_READ_10:
|
||||
case SCSI_CMD_WRITE_10:
|
||||
lba = ((struct SCSI_CDB_10 *)command)->lba;
|
||||
count = ((struct SCSI_CDB_10 *)command)->length;
|
||||
lba = ((struct SCSI_CDB_10 *)command)->lba;
|
||||
count = ((struct SCSI_CDB_10 *)command)->length;
|
||||
goto do_scsi_transfer;
|
||||
|
||||
case SCSI_CMD_READ_16:
|
||||
case SCSI_CMD_WRITE_16:
|
||||
lba = ((struct SCSI_CDB_16 *)command)->lba;
|
||||
count = ((struct SCSI_CDB_16 *)command)->length;
|
||||
|
||||
do_scsi_transfer:
|
||||
if (data == NULL || (lba + count) >= unit->logicalSectors) {
|
||||
if (data == NULL || (lba + count) > unit->logicalSectors) {
|
||||
error = IOERR_BADADDRESS;
|
||||
fake_scsi_sense(scsi_command,lba,count,error);
|
||||
break;
|
||||
@ -373,7 +383,8 @@ static void process_ioreq(struct IOTask *itask, struct IOStdReq *ioreq) {
|
||||
struct IOExtTD *iotd;
|
||||
struct IDEUnit *unit;
|
||||
UWORD blockShift;
|
||||
ULONG lba;
|
||||
unsigned long long lba;
|
||||
ULONG lba_high, lba_low;
|
||||
ULONG count;
|
||||
BYTE error = 0;
|
||||
enum xfer_dir direction = WRITE;
|
||||
@ -473,7 +484,15 @@ transfer:
|
||||
}
|
||||
|
||||
blockShift = ((struct IDEUnit *)ioreq->io_Unit)->blockShift;
|
||||
lba = (((long long)ioreq->io_Actual << 32 | ioreq->io_Offset) >> blockShift);
|
||||
|
||||
// This looks like a lond-winded way to get the LBA doesn't it?
|
||||
// Splitting up the operation like this results in smaller code size (avoids 64-bit math from libgcc)
|
||||
lba_high = ioreq->io_Actual >> blockShift;
|
||||
lba_low = ioreq->io_Actual << (32 - blockShift);
|
||||
lba_low |= (ioreq->io_Offset >> blockShift);
|
||||
|
||||
lba = ((unsigned long long)lba_high << 32 | lba_low);
|
||||
|
||||
count = (ioreq->io_Length >> blockShift);
|
||||
|
||||
if (count == 0) {
|
||||
@ -482,13 +501,13 @@ transfer:
|
||||
}
|
||||
|
||||
if ((lba + count) > (unit->logicalSectors)) {
|
||||
Trace("Read past end of device\n");
|
||||
Trace("Access past end of device\n");
|
||||
error = IOERR_BADADDRESS;
|
||||
break;
|
||||
}
|
||||
|
||||
if (unit->flags.atapi == true) {
|
||||
error = atapi_translate(ioreq->io_Data, lba, count, &ioreq->io_Actual, unit, direction);
|
||||
error = atapi_translate(ioreq->io_Data, (ULONG)lba, count, &ioreq->io_Actual, unit, direction);
|
||||
} else {
|
||||
if (direction == READ) {
|
||||
error = ata_read(ioreq->io_Data, lba, count, unit);
|
||||
@ -594,7 +613,7 @@ void __attribute__((noreturn)) io_task () {
|
||||
RemTask(NULL);
|
||||
Wait(0);
|
||||
}
|
||||
|
||||
|
||||
signalMask |= (1 << itask->dcTimerMp->mp_SigBit);
|
||||
|
||||
run_timer(SysBase,itask->dcTimerReq,CHANGEINT_INTERVAL,0);
|
||||
|
||||
@ -33,6 +33,8 @@
|
||||
|
||||
#define CMD_XFER 0x1001
|
||||
|
||||
#define BIT(x) (1U << (x))
|
||||
|
||||
const char ver[] = VERSION_STRING;
|
||||
|
||||
struct ExecBase *SysBase;
|
||||
@ -167,7 +169,7 @@ static void DumpUnit(struct IOStdReq *req) {
|
||||
printf("Supports LBA: %s\n", (unit->flags.lba) ? "Yes" : "No");
|
||||
printf("Supports LBA48: %s\n", (unit->flags.lba48) ? "Yes" : "No");
|
||||
printf("C/H/S: %d/%d/%d\n", unit->cylinders, unit->heads, unit->sectorsPerTrack);
|
||||
printf("Logical Sectors: %ld\n", (long int)unit->logicalSectors);
|
||||
printf("Logical Sectors: %llu\n", (unsigned long long)unit->logicalSectors);
|
||||
printf("READ/WRITE Multiple: %s\n", (unit->flags.xferMultiple) ? "Yes" : "No");
|
||||
printf("Multiple count: %d\n", unit->multipleCount);
|
||||
printf("Last Error: ");
|
||||
@ -226,6 +228,84 @@ BYTE setPio(struct IOStdReq *req,int pio) {
|
||||
return error;
|
||||
}
|
||||
|
||||
static char *trim(char *str, int bytes)
|
||||
{
|
||||
char *eptr = &str[bytes - 1];
|
||||
while (eptr > str) {
|
||||
if (*eptr == ' ')
|
||||
*(eptr--) = '\0';
|
||||
else
|
||||
break;
|
||||
}
|
||||
while (*str == ' ')
|
||||
str++;
|
||||
return (str);
|
||||
}
|
||||
|
||||
/**
|
||||
* identify_decode
|
||||
*
|
||||
* Interpret the result data of an IDENTIFY DEVICE command.
|
||||
*
|
||||
* @param buf the 512-byte buffer
|
||||
*/
|
||||
static void identify_decode(UWORD *buf) {
|
||||
int bit;
|
||||
unsigned int atastd;
|
||||
for (int i=0; i<256; i++)
|
||||
buf[i] = __bswap16(buf[i]);
|
||||
|
||||
printf("ATA%s", (buf[0] & BIT(15)) ? "PI" : "");
|
||||
printf(" Model=%.40s, FwRev=%.8s, SerialNo=%.20s\n",
|
||||
trim((char *)&buf[27], 40),
|
||||
trim((char *)&buf[23], 8),
|
||||
trim((char *)&buf[10], 20));
|
||||
printf("Raw C/H/S: %u/%u/%u\n", buf[1], buf[3], buf[6]);
|
||||
printf("Cur C/H/S: %u/%u/%u\n", buf[54], buf[55], buf[56]);
|
||||
printf("LBA Capacity: %u sec\n", buf[60] | (buf[61] << 16));
|
||||
printf("Cur Capacity: %u sec\n", buf[57] | (buf[58] << 16));
|
||||
printf("MaxMultSect: %u [%s]\n", buf[59] & 0xff,
|
||||
(buf[59] & BIT(8)) ? "enabled" : "disabled");
|
||||
printf("PIO modes: ");
|
||||
for (bit = 0; bit < 8; bit++)
|
||||
if (buf[64] & BIT(bit))
|
||||
printf(" pio%u", bit);
|
||||
if ((buf[64] & 0xff) == 0)
|
||||
printf("<none>");
|
||||
printf("\nDMA modes: ");
|
||||
for (bit = 0; bit < 8; bit++)
|
||||
if (buf[63] & BIT(bit)) {
|
||||
printf(" %smdma%u%s",
|
||||
(buf[63] & BIT(8 + bit)) ? "[" : "",
|
||||
bit,
|
||||
(buf[63] & BIT(8 + bit)) ? "]" : "");
|
||||
}
|
||||
if ((buf[63] & 0xff) == 0)
|
||||
printf("<none>");
|
||||
printf("\nUDMA modes: ");
|
||||
for (bit = 0; bit < 8; bit++)
|
||||
if (buf[88] & BIT(bit)) {
|
||||
printf(" %sudma%u%s",
|
||||
(buf[88] & BIT(8 + bit)) ? "[" : "",
|
||||
bit,
|
||||
(buf[88] & BIT(8 + bit)) ? "]" : "");
|
||||
}
|
||||
if ((buf[63] & 0xff) == 0)
|
||||
printf("<none>");
|
||||
printf("\nTiming: tPIO=[min:%u,w/IORDY:%u}, tDMA={min:%u,rec:%u}\n",
|
||||
buf[67], buf[68], buf[65], buf[66]);
|
||||
atastd = buf[80];
|
||||
if ((atastd != 0x0000) && (atastd != 0xffff)) {
|
||||
printf("Standards: ");
|
||||
for (bit = 2; bit < 7; bit++)
|
||||
if (atastd & BIT(bit))
|
||||
printf(" ATA%u", bit);
|
||||
printf("\n");
|
||||
}
|
||||
printf("IORDY: %s\n",
|
||||
(buf[49] & BIT(11)) ? (buf[49] & BIT(10) ? "on/off" : "on") : "?");
|
||||
}
|
||||
|
||||
/**
|
||||
* ident
|
||||
*
|
||||
@ -277,6 +357,7 @@ BYTE identify(struct IOStdReq *req) {
|
||||
if (cmd->scsi_Status)
|
||||
printf("SCSI Status: %d\n",cmd->scsi_Status);
|
||||
|
||||
identify_decode(buf);
|
||||
FreeMem(buf,512);
|
||||
}
|
||||
DeleteSCSICmd(cmd);
|
||||
|
||||
51
scsi.c
51
scsi.c
@ -8,6 +8,7 @@
|
||||
#include <proto/alib.h>
|
||||
#include <proto/exec.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "ata.h"
|
||||
#include "debug.h"
|
||||
@ -16,7 +17,6 @@
|
||||
#include "newstyle.h"
|
||||
#include "scsi.h"
|
||||
#include "td64.h"
|
||||
|
||||
/**
|
||||
* fake_scsi_sense
|
||||
*
|
||||
@ -166,14 +166,14 @@ BYTE scsi_inquiry_emu(struct IDEUnit *unit, struct SCSICmd *scsi_command) {
|
||||
}
|
||||
|
||||
/**
|
||||
* scsi_read_capacity_emu
|
||||
* scsi_read_capacity_10_emu
|
||||
*
|
||||
* Emulate SCSI-Direct READ CAPACITY command
|
||||
* Emulate SCSI-Direct READ CAPACITY (10) command
|
||||
*
|
||||
* @param unit Pointer to an IDEUnit struct
|
||||
* @param scsi_command Pointer to a SCSICmd struct
|
||||
*/
|
||||
BYTE scsi_read_capacity_emu(struct IDEUnit *unit, struct SCSICmd *scsi_command) {
|
||||
BYTE scsi_read_capacity_10_emu(struct IDEUnit *unit, struct SCSICmd *scsi_command) {
|
||||
struct SCSI_CAPACITY_10 *data = (struct SCSI_CAPACITY_10 *)scsi_command->scsi_Data;
|
||||
BYTE error;
|
||||
|
||||
@ -187,13 +187,17 @@ BYTE scsi_read_capacity_emu(struct IDEUnit *unit, struct SCSICmd *scsi_command)
|
||||
|
||||
data->block_size = unit->blockSize;
|
||||
|
||||
if (cdb->flags & 0x01) {
|
||||
// Partial Medium Indicator - Return end of cylinder
|
||||
// Implement this so HDToolbox stops moaning about track size
|
||||
ULONG spc = unit->sectorsPerTrack * unit->heads;
|
||||
data->lba = (((cdb->lba / spc) + 1) * spc) - 1;
|
||||
if (unit->logicalSectors < ULONG_MAX) {
|
||||
if (cdb->flags & 0x01) {
|
||||
// Partial Medium Indicator - Return end of cylinder
|
||||
// Implement this so HDToolbox stops moaning about track size
|
||||
ULONG spc = unit->sectorsPerTrack * unit->heads;
|
||||
data->lba = (((cdb->lba / spc) + 1) * spc) - 1;
|
||||
} else {
|
||||
data->lba = (unit->logicalSectors) - 1;
|
||||
}
|
||||
} else {
|
||||
data->lba = (unit->logicalSectors) - 1;
|
||||
data->lba = ULONG_MAX;
|
||||
}
|
||||
|
||||
|
||||
@ -202,6 +206,33 @@ BYTE scsi_read_capacity_emu(struct IDEUnit *unit, struct SCSICmd *scsi_command)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* scsi_read_capacity_16_emu
|
||||
*
|
||||
* Emulate SCSI-Direct READ CAPACITY (16) command
|
||||
*
|
||||
* @param unit Pointer to an IDEUnit struct
|
||||
* @param scsi_command Pointer to a SCSICmd struct
|
||||
*/
|
||||
BYTE scsi_read_capacity_16_emu(struct IDEUnit *unit, struct SCSICmd *scsi_command) {
|
||||
struct SCSI_CAPACITY_16 *data = (struct SCSI_CAPACITY_16 *)scsi_command->scsi_Data;
|
||||
BYTE error;
|
||||
|
||||
if (data == NULL) {
|
||||
error = IOERR_BADADDRESS;
|
||||
fake_scsi_sense(scsi_command,0,0,error);
|
||||
return error;
|
||||
}
|
||||
|
||||
data->block_size = unit->blockSize;
|
||||
data->lba = unit->logicalSectors - 1;
|
||||
|
||||
scsi_command->scsi_Actual = 8;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* scsi_mode_sense_emu
|
||||
*
|
||||
|
||||
29
scsi.h
29
scsi.h
@ -26,6 +26,9 @@
|
||||
#define SCSI_CMD_MODE_SENSE_10 0x5A
|
||||
#define SCSI_CMD_CLOSE_TRACK_SESS 0x5B
|
||||
#define SCSI_CMD_START_STOP_UNIT 0x1B
|
||||
#define SCSI_CMD_READ_16 0x88
|
||||
#define SCSI_CMD_WRITE_16 0x8A
|
||||
#define SCSI_CMD_READ_CAPACITY_16 0x9E
|
||||
#define SCSI_CMD_BLANK 0xA1
|
||||
#define SCSI_CMD_ATA_PASSTHROUGH 0xA1
|
||||
#define SCSI_CHECK_CONDITION 0x02
|
||||
@ -68,6 +71,15 @@ struct __attribute__((packed)) SCSI_CDB_10 {
|
||||
UBYTE control;
|
||||
};
|
||||
|
||||
struct __attribute__((packed)) SCSI_CDB_16 {
|
||||
UBYTE operation;
|
||||
UBYTE flags;
|
||||
unsigned long long lba;
|
||||
ULONG length;
|
||||
UBYTE group;
|
||||
UBYTE control;
|
||||
};
|
||||
|
||||
struct __attribute__((packed)) SCSI_READ_CAPACITY_10 {
|
||||
UBYTE operation;
|
||||
UBYTE reserved1;
|
||||
@ -76,12 +88,26 @@ struct __attribute__((packed)) SCSI_READ_CAPACITY_10 {
|
||||
UBYTE flags;
|
||||
UBYTE control;
|
||||
};
|
||||
struct __attribute__((packed)) SCSI_READ_CAPACITY_16 {
|
||||
UBYTE operation;
|
||||
UBYTE serviceAction;
|
||||
unsigned long long lba;
|
||||
ULONG allocation;
|
||||
UBYTE flags;
|
||||
UBYTE control;
|
||||
};
|
||||
|
||||
struct __attribute__((packed)) SCSI_CAPACITY_10 {
|
||||
ULONG lba;
|
||||
ULONG block_size;
|
||||
};
|
||||
|
||||
struct __attribute__((packed)) SCSI_CAPACITY_16 {
|
||||
unsigned long long lba;
|
||||
ULONG block_size;
|
||||
char reserved[3];
|
||||
};
|
||||
|
||||
struct __attribute__((packed)) SCSI_FIXED_SENSE {
|
||||
UBYTE response;
|
||||
UBYTE pad;
|
||||
@ -145,7 +171,8 @@ void fake_scsi_sense(struct SCSICmd* command, ULONG info, ULONG specific, BYTE e
|
||||
struct SCSICmd * MakeSCSICmd(ULONG cdbSize);
|
||||
void DeleteSCSICmd(struct SCSICmd *cmd);
|
||||
BYTE scsi_inquiry_emu(struct IDEUnit *unit, struct SCSICmd *scsi_command);
|
||||
BYTE scsi_read_capacity_emu(struct IDEUnit *unit, struct SCSICmd *scsi_command);
|
||||
BYTE scsi_read_capacity_10_emu(struct IDEUnit *unit, struct SCSICmd *scsi_command);
|
||||
BYTE scsi_read_capacity_16_emu(struct IDEUnit *unit, struct SCSICmd *scsi_command);
|
||||
BYTE scsi_mode_sense_emu(struct IDEUnit *unit, struct SCSICmd *scsi_command);
|
||||
|
||||
#endif
|
||||
Loading…
x
Reference in New Issue
Block a user