Compare commits

...

8 Commits

Author SHA1 Message Date
828bdaa85f Add AmigaPCI Manuf/Prod ID 2025-10-22 22:36:28 +00:00
d439ceb016 Formatting 2025-10-22 22:32:14 +00:00
161f3da34b Detect AmigaPCI via autoconfig 2025-06-29 07:33:49 +00:00
827b64bff4 Hardcode 2 channels for AmigaPCI 2025-06-14 21:38:37 +00:00
ced23f8ff7 Add Build for AmigaPCI 2025-06-06 00:30:13 +00:00
e5bb9a06ce Fix emulated scsi read/write bounds check
This was off by one making the last sector inaccessible
2025-10-22 08:38:12 +00:00
0d78bd0989 reloc: fix RomFetch16 on Zorro 2025-10-22 08:37:23 +00:00
4207fb75a4 Remove 64-bit math
Reduces code size by ~4K
2025-10-22 03:49:33 +00:00
11 changed files with 121 additions and 84 deletions

View File

@ -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

37
ata.c
View File

@ -21,9 +21,9 @@
#include "sleep.h"
#include "lide_alib.h"
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);
static BYTE write_taskfile_lba(struct IDEUnit *unit, UBYTE command, uint64_t lba, UBYTE sectorCount, UBYTE features);
static BYTE write_taskfile_lba48(struct IDEUnit *unit, UBYTE command, uint64_t lba, UBYTE sectorCount, UBYTE features);
static BYTE write_taskfile_chs(struct IDEUnit *unit, UBYTE command, uint64_t lba, UBYTE sectorCount, UBYTE features);
/**
* ata_status_reg_delay
@ -416,9 +416,9 @@ bool ata_init_unit(struct IDEUnit *unit, void *base) {
unit->flags.lba48 = true;
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->logicalSectors |= ((uint64_t)buf[ata_identify_lba48_sectors]) << 0;
unit->logicalSectors |= ((uint64_t)buf[ata_identify_lba48_sectors+1]) << 16;
unit->logicalSectors |= ((uint64_t)buf[ata_identify_lba48_sectors+2]) << 32;
unit->write_taskfile = &write_taskfile_lba48;
@ -439,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->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);
}
@ -537,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, unsigned long long lba, ULONG count, struct IDEUnit *unit) {
BYTE ata_read(void *buffer, uint64_t lba, ULONG count, struct IDEUnit *unit) {
Trace("ata_read enter\n");
Trace("ATA: Request sector count: %ld\n",count);
@ -625,7 +625,7 @@ BYTE ata_read(void *buffer, unsigned long long lba, ULONG count, struct IDEUnit
* @param unit Pointer to the unit structure
* @returns error
*/
BYTE ata_write(void *buffer, unsigned long long lba, ULONG count, struct IDEUnit *unit) {
BYTE ata_write(void *buffer, uint64_t lba, ULONG count, struct IDEUnit *unit) {
Trace("ata_write enter\n");
Trace("ATA: Request sector count: %ld\n",count);
@ -746,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, unsigned long long 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, uint64_t 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;
@ -776,7 +777,7 @@ static BYTE write_taskfile_chs(struct IDEUnit *unit, UBYTE command, unsigned lon
* @param unit Pointer to an IDEUnit struct
* @param lba Pointer to the LBA variable
*/
static BYTE write_taskfile_lba(struct IDEUnit *unit, UBYTE command, unsigned long long lba, UBYTE sectorCount, UBYTE features) {
static BYTE write_taskfile_lba(struct IDEUnit *unit, UBYTE command, uint64_t lba, UBYTE sectorCount, UBYTE features) {
BYTE devHead;
if (!ata_wait_ready(unit,ATA_RDY_WAIT_COUNT))
@ -802,7 +803,7 @@ static BYTE write_taskfile_lba(struct IDEUnit *unit, UBYTE command, unsigned lon
* @param unit Pointer to an IDEUnit struct
* @param lba Pointer to the LBA variable
*/
static BYTE write_taskfile_lba48(struct IDEUnit *unit, UBYTE command, unsigned long long lba, UBYTE sectorCount, UBYTE features) {
static BYTE write_taskfile_lba48(struct IDEUnit *unit, UBYTE command, uint64_t lba, UBYTE sectorCount, UBYTE features) {
if (!ata_wait_ready(unit,ATA_RDY_WAIT_COUNT))
return HFERR_SelTimeout;

6
ata.h
View File

@ -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, 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_read(void *buffer, uint64_t lba, ULONG count, struct IDEUnit *unit);
BYTE ata_write(void *buffer, uint64_t 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);

View File

@ -294,6 +294,7 @@ RomFetch
.RomFetchZ ; access type is Zorro
move.l d0,d3
moveq #0,d0
.nextnip
lsl.l #8,d0
IFND BYTEWIDE

View File

@ -27,7 +27,7 @@
#include "lide_alib.h"
#include "mounter/mounter.h"
#ifdef NO_AUTOCONFIG
#ifdef FAKE_CONFIGDEV
extern UBYTE bootblock, bootblock_end;
#endif
@ -109,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.
@ -269,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
*
@ -329,6 +330,7 @@ static BYTE detectChannels(struct ConfigDev *cd) {
return 1;
}
#endif
/**
* init_device
@ -411,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);

View File

@ -15,6 +15,20 @@
#define MAX_UNITS 4
#if AMIGAPCI
// #define NO_AUTOCONFIG 1
#define BOARD_MANUF_ID 600
#define BOARD_PROD_ID 3
#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, unsigned long long, UBYTE, UBYTE);
BYTE (*write_taskfile)(struct IDEUnit *, UBYTE, uint64_t, 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;
unsigned long long logicalSectors;
uint64_t logicalSectors;
struct MinList changeInts;
UBYTE multipleCount;
struct {

View File

@ -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;
unsigned long long lba;
uint64_t lba;
ULONG count;
BYTE error = 0;
scsi_command->scsi_SenseActual = 0;
@ -172,7 +172,7 @@ static BYTE handle_scsi_command(struct IOStdReq *ioreq) {
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;
@ -383,7 +383,8 @@ static void process_ioreq(struct IOTask *itask, struct IOStdReq *ioreq) {
struct IOExtTD *iotd;
struct IDEUnit *unit;
UWORD blockShift;
unsigned long long lba;
uint64_t lba;
ULONG lba_high, lba_low;
ULONG count;
BYTE error = 0;
enum xfer_dir direction = WRITE;
@ -483,7 +484,15 @@ transfer:
}
blockShift = ((struct IDEUnit *)ioreq->io_Unit)->blockShift;
lba = (((unsigned 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 = ((uint64_t)lba_high << 32 | lba_low);
count = (ioreq->io_Length >> blockShift);
if (count == 0) {
@ -492,7 +501,7 @@ transfer:
}
if ((lba + count) > (unit->logicalSectors)) {
Trace("Read past end of device\n");
Trace("Access past end of device\n");
error = IOERR_BADADDRESS;
break;
}

View File

@ -169,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: %llu\n", (unsigned long long)unit->logicalSectors);
printf("Logical Sectors: %llu\n", (uint64_t)unit->logicalSectors);
printf("READ/WRITE Multiple: %s\n", (unit->flags.xferMultiple) ? "Yes" : "No");
printf("Multiple count: %d\n", unit->multipleCount);
printf("Last Error: ");

13
scsi.c
View File

@ -225,19 +225,8 @@ BYTE scsi_read_capacity_16_emu(struct IDEUnit *unit, struct SCSICmd *scsi_comman
return error;
}
struct SCSI_READ_CAPACITY_16 *cdb = (struct SCSI_READ_CAPACITY_16 *)scsi_command->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;
} else {
data->lba = (unit->logicalSectors) - 1;
}
data->lba = unit->logicalSectors - 1;
scsi_command->scsi_Actual = 8;

6
scsi.h
View File

@ -74,7 +74,7 @@ struct __attribute__((packed)) SCSI_CDB_10 {
struct __attribute__((packed)) SCSI_CDB_16 {
UBYTE operation;
UBYTE flags;
unsigned long long lba;
uint64_t lba;
ULONG length;
UBYTE group;
UBYTE control;
@ -91,7 +91,7 @@ struct __attribute__((packed)) SCSI_READ_CAPACITY_10 {
struct __attribute__((packed)) SCSI_READ_CAPACITY_16 {
UBYTE operation;
UBYTE serviceAction;
unsigned long long lba;
uint64_t lba;
ULONG allocation;
UBYTE flags;
UBYTE control;
@ -103,7 +103,7 @@ struct __attribute__((packed)) SCSI_CAPACITY_10 {
};
struct __attribute__((packed)) SCSI_CAPACITY_16 {
unsigned long long lba;
uint64_t lba;
ULONG block_size;
char reserved[3];
};