mirror of
https://github.com/LIV2/lide.device.git
synced 2025-12-06 00:32:45 +00:00
Fixups
* Optimizations for size etc * Make endskip actually skip to the end * Save last ATA Error * Remove need for divide by using right shifts
This commit is contained in:
parent
2679269fc6
commit
45db8c4b21
22
Makefile
22
Makefile
@ -1,7 +1,16 @@
|
|||||||
PROJECT=liv2ride
|
PROJECT=liv2ride
|
||||||
CC=m68k-amigaos-gcc
|
CC=m68k-amigaos-gcc
|
||||||
DEBUG=0
|
CFLAGS=-nostartfiles -nostdlib -noixemul -mcpu=68000 -Wall -Wno-multichar -Wno-pointer-sign -Wno-unused-value -Og -fomit-frame-pointer -fno-delete-null-pointer-checks -msmall-code -s
|
||||||
CFLAGS=-nostartfiles -nostdlib -noixemul -mcpu=68000 -Wall -Wno-multichar -Wno-pointer-sign -DDEBUG=$(DEBUG) -O3 -fomit-frame-pointer -Wno-unused-value -fno-delete-null-pointer-checks
|
LDFLAGS=-lamiga -lgcc -lc
|
||||||
|
AS=m68k-amigaos-as
|
||||||
|
|
||||||
|
ifdef DEBUG
|
||||||
|
CFLAGS+= -DDEBUG=$(DEBUG)
|
||||||
|
LDFLAGS+= -ldebug
|
||||||
|
.PHONY: $(PROJECT)
|
||||||
|
endif
|
||||||
|
|
||||||
|
LDFLAGS+= -lnix13
|
||||||
|
|
||||||
.PHONY: clean all
|
.PHONY: clean all
|
||||||
all: $(PROJECT)
|
all: $(PROJECT)
|
||||||
@ -11,10 +20,13 @@ OBJ = driver.o \
|
|||||||
idetask.o \
|
idetask.o \
|
||||||
mounter.o
|
mounter.o
|
||||||
|
|
||||||
SRCS = $(OBJ:%.o=%.c)
|
ASMOBJ = endskip.o
|
||||||
|
|
||||||
liv2ride: $(SRCS)
|
SRCS = $(OBJ:%.o=%.c)
|
||||||
${CC} -o $@ $(CFLAGS) $(SRCS) -lamiga -lgcc -ldebug -lnix13
|
SRCS += $(ASMOBJ:%.o=%.S)
|
||||||
|
|
||||||
|
$(PROJECT): $(SRCS)
|
||||||
|
${CC} -o $@ $(CFLAGS) $(SRCS) $(LDFLAGS)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
-rm $(PROJECT)
|
-rm $(PROJECT)
|
||||||
|
|||||||
261
ata.c
261
ata.c
@ -25,7 +25,7 @@
|
|||||||
*
|
*
|
||||||
* returns false on timeout
|
* returns false on timeout
|
||||||
*/
|
*/
|
||||||
bool ata_wait_not_busy(struct IDEUnit *unit) {
|
static bool ata_wait_not_busy(struct IDEUnit *unit) {
|
||||||
#ifndef NOTIMER
|
#ifndef NOTIMER
|
||||||
struct Device *TimerBase = unit->TimeReq->tr_node.io_Device;
|
struct Device *TimerBase = unit->TimeReq->tr_node.io_Device;
|
||||||
struct timeval now, then;
|
struct timeval now, then;
|
||||||
@ -39,7 +39,7 @@ bool ata_wait_not_busy(struct IDEUnit *unit) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if ((*(volatile BYTE *)unit->drive->status_command & ata_busy) == 0) return true;
|
if ((*(volatile BYTE *)unit->drive->status_command & ata_flag_busy) == 0) return true;
|
||||||
|
|
||||||
#ifndef NOTIMER
|
#ifndef NOTIMER
|
||||||
GetSysTime(&now);
|
GetSysTime(&now);
|
||||||
@ -61,7 +61,7 @@ bool ata_wait_not_busy(struct IDEUnit *unit) {
|
|||||||
*
|
*
|
||||||
* returns false on timeout
|
* returns false on timeout
|
||||||
*/
|
*/
|
||||||
bool ata_wait_ready(struct IDEUnit *unit) {
|
static bool ata_wait_ready(struct IDEUnit *unit) {
|
||||||
#ifndef NOTIMER
|
#ifndef NOTIMER
|
||||||
struct Device *TimerBase = unit->TimeReq->tr_node.io_Device;
|
struct Device *TimerBase = unit->TimeReq->tr_node.io_Device;
|
||||||
struct timeval now, then;
|
struct timeval now, then;
|
||||||
@ -74,7 +74,7 @@ bool ata_wait_ready(struct IDEUnit *unit) {
|
|||||||
KPrintF("wait_ready_enter\n");
|
KPrintF("wait_ready_enter\n");
|
||||||
#endif
|
#endif
|
||||||
while (1) {
|
while (1) {
|
||||||
if (*(volatile BYTE *)unit->drive->status_command & ata_ready) return true;
|
if (*(volatile BYTE *)unit->drive->status_command & ata_flag_ready) return true;
|
||||||
|
|
||||||
#ifndef NOTIMER
|
#ifndef NOTIMER
|
||||||
GetSysTime(&now);
|
GetSysTime(&now);
|
||||||
@ -95,7 +95,7 @@ bool ata_wait_ready(struct IDEUnit *unit) {
|
|||||||
*
|
*
|
||||||
* returns false on timeout
|
* returns false on timeout
|
||||||
*/
|
*/
|
||||||
bool ata_wait_drq(struct IDEUnit *unit) {
|
static bool ata_wait_drq(struct IDEUnit *unit) {
|
||||||
#ifndef NOTIMER
|
#ifndef NOTIMER
|
||||||
struct Device *TimerBase = unit->TimeReq->tr_node.io_Device;
|
struct Device *TimerBase = unit->TimeReq->tr_node.io_Device;
|
||||||
struct timeval now, then;
|
struct timeval now, then;
|
||||||
@ -110,7 +110,7 @@ bool ata_wait_drq(struct IDEUnit *unit) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (*(volatile BYTE *)unit->drive->status_command& ata_drq) return true;
|
if (*(volatile BYTE *)unit->drive->status_command& ata_flag_drq) return true;
|
||||||
|
|
||||||
#ifndef NOTIMER
|
#ifndef NOTIMER
|
||||||
GetSysTime(&now);
|
GetSysTime(&now);
|
||||||
@ -149,11 +149,11 @@ bool ata_identify(struct IDEUnit *unit, UWORD *buffer)
|
|||||||
volatile UBYTE *status = unit->drive->status_command;
|
volatile UBYTE *status = unit->drive->status_command;
|
||||||
|
|
||||||
#if DEBUG >= 2
|
#if DEBUG >= 2
|
||||||
KPrintF("Drive Status: %04x%04x %04x%04x\n",status, *status);
|
KPrintF("Drive Status: %08lx %08lx\n",status, *status);
|
||||||
#endif
|
#endif
|
||||||
if (*status == 0) return false; // No drive there?
|
if (*status == 0) return false; // No drive there?
|
||||||
|
|
||||||
while ((*status & (ata_drq | ata_error)) == 0) {
|
while ((*status & (ata_flag_drq | ata_flag_error)) == 0) {
|
||||||
// Wait until ready to transfer or error condition
|
// Wait until ready to transfer or error condition
|
||||||
#ifndef NOTIMER
|
#ifndef NOTIMER
|
||||||
GetSysTime(&now);
|
GetSysTime(&now);
|
||||||
@ -161,10 +161,16 @@ bool ata_identify(struct IDEUnit *unit, UWORD *buffer)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*status & ata_error) {
|
if (*status & ata_flag_error) {
|
||||||
#if DEBUG >= 1
|
#if DEBUG >= 1
|
||||||
KPrintF("IDENTIFY Status: Error\n");
|
KPrintF("IDENTIFY Status: Error\n");
|
||||||
|
KPrintF("last_error: %08lx\n",&unit->last_error[0]);
|
||||||
#endif
|
#endif
|
||||||
|
unit->last_error[0] = *unit->drive->error_features;
|
||||||
|
unit->last_error[1] = *unit->drive->lbaHigh;
|
||||||
|
unit->last_error[2] = *unit->drive->lbaMid;
|
||||||
|
unit->last_error[3] = *unit->drive->lbaLow;
|
||||||
|
unit->last_error[4] = *unit->drive->status_command;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -212,7 +218,7 @@ bool ata_init_unit(struct IDEUnit *unit) {
|
|||||||
dev_found = true;
|
dev_found = true;
|
||||||
#if DEBUG >= 1
|
#if DEBUG >= 1
|
||||||
KPrintF("Something there?\n");
|
KPrintF("Something there?\n");
|
||||||
KPrintF("Unit base: %04x%04x; Drive base %04x%04x\n",unit, unit->drive);
|
KPrintF("Unit base: %08lx; Drive base %08lx\n",unit, unit->drive);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -241,12 +247,150 @@ bool ata_init_unit(struct IDEUnit *unit) {
|
|||||||
unit->heads = *((UWORD *)buf + ata_identify_heads);
|
unit->heads = *((UWORD *)buf + ata_identify_heads);
|
||||||
unit->sectorsPerTrack = *((UWORD *)buf + ata_identify_sectors);
|
unit->sectorsPerTrack = *((UWORD *)buf + ata_identify_sectors);
|
||||||
unit->blockSize = *((UWORD *)buf + ata_identify_sectorsize);
|
unit->blockSize = *((UWORD *)buf + ata_identify_sectorsize);
|
||||||
|
unit->blockShift = 0;
|
||||||
|
|
||||||
|
// It's faster to shift than divide
|
||||||
|
// Figure out how many shifts are needed for the equivalent divide
|
||||||
|
if (unit->blockSize == 0) {
|
||||||
|
#if DEBUG >= 1
|
||||||
|
KPrintF("Error! blockSize is 0\n");
|
||||||
|
#endif
|
||||||
|
if (buf) FreeMem(buf,512);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((unit->blockSize >> unit->blockShift) > 1) {
|
||||||
|
unit->blockShift++;
|
||||||
|
}
|
||||||
|
|
||||||
unit->present = true;
|
unit->present = true;
|
||||||
|
|
||||||
if (buf) FreeMem(buf,512);
|
if (buf) FreeMem(buf,512);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ata_transfer
|
||||||
|
*
|
||||||
|
* Read/write a block from/to the unit
|
||||||
|
* @param buffer Source buffer
|
||||||
|
* @param lba LBA Address
|
||||||
|
* @param count Number of blocks to transfer
|
||||||
|
* @param actual Pointer to the io requests io_Actual
|
||||||
|
* @param unit Pointer to the unit structure
|
||||||
|
* @param direction READ/WRITE
|
||||||
|
*/
|
||||||
|
BYTE ata_transfer(void *buffer, ULONG lba, ULONG count, ULONG *actual, struct IDEUnit *unit, enum xfer_dir direction) {
|
||||||
|
#if DEBUG >= 2
|
||||||
|
if (direction == READ) {
|
||||||
|
KPrintF("ata_read");
|
||||||
|
} else {
|
||||||
|
KPrintF("ata_write");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
ULONG subcount = 0;
|
||||||
|
ULONG offset = 0;
|
||||||
|
*actual = 0;
|
||||||
|
|
||||||
|
if (count == 0) return TDERR_TooFewSecs;
|
||||||
|
|
||||||
|
BYTE drvSel = (unit->primary) ? 0xE0 : 0xF0;
|
||||||
|
*unit->drive->devHead = (UBYTE)(drvSel | ((lba >> 24) & 0x0F));
|
||||||
|
|
||||||
|
#if DEBUG >= 3
|
||||||
|
KPrintF("Request sector count: %ld\n",count);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// None of this max_transfer 1FE00 nonsense!
|
||||||
|
while (count > 0) {
|
||||||
|
if (count >= MAX_TRANSFER_SECTORS) { // Transfer 256 Sectors at a time
|
||||||
|
subcount = MAX_TRANSFER_SECTORS;
|
||||||
|
} else {
|
||||||
|
subcount = count; // Get any remainders
|
||||||
|
}
|
||||||
|
count -= subcount;
|
||||||
|
|
||||||
|
#if DEBUG >= 3
|
||||||
|
KPrintF("XFER Count: %ld, Subcount: %ld\n",count,subcount);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!ata_wait_not_busy(unit))
|
||||||
|
return HFERR_BadStatus;
|
||||||
|
|
||||||
|
*unit->drive->sectorCount = subcount; // Count value of 0 indicates to transfer 256 sectors
|
||||||
|
*unit->drive->lbaLow = (UBYTE)(lba);
|
||||||
|
*unit->drive->lbaMid = (UBYTE)(lba >> 8);
|
||||||
|
*unit->drive->lbaHigh = (UBYTE)(lba >> 16);
|
||||||
|
*unit->drive->error_features = 0;
|
||||||
|
*unit->drive->status_command = (direction == READ) ? ATA_CMD_READ : ATA_CMD_WRITE;
|
||||||
|
|
||||||
|
for (int block = 0; block < subcount; block++) {
|
||||||
|
if (!ata_wait_drq(unit))
|
||||||
|
return HFERR_BadStatus;
|
||||||
|
|
||||||
|
|
||||||
|
if (direction == READ) {
|
||||||
|
|
||||||
|
//for (int i=0; i<(unit->blockSize / 2); i++) {
|
||||||
|
// ((UWORD *)buffer)[offset] = *(UWORD *)unit->drive->data;
|
||||||
|
// offset++;
|
||||||
|
//}
|
||||||
|
read_fast((void *)(unit->drive->error_features - 48),(buffer + offset));
|
||||||
|
offset += 512;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
//for (int i=0; i<(unit->blockSize / 2); i++) {
|
||||||
|
// *(UWORD *)unit->drive->data = ((UWORD *)buffer)[offset];
|
||||||
|
// offset++;
|
||||||
|
//}
|
||||||
|
write_fast((buffer + offset),(void *)(unit->drive->error_features - 48));
|
||||||
|
offset += 512;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
*actual += unit->blockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*unit->drive->error_features & ata_flag_error) {
|
||||||
|
unit->last_error[0] = unit->drive->error_features[0];
|
||||||
|
unit->last_error[1] = unit->drive->lbaHigh[0];
|
||||||
|
unit->last_error[2] = unit->drive->lbaMid[0];
|
||||||
|
unit->last_error[3] = unit->drive->lbaLow[0];
|
||||||
|
unit->last_error[4] = unit->drive->status_command[0];
|
||||||
|
#if DEBUG
|
||||||
|
KPrintF("ATA ERROR!!!");
|
||||||
|
KPrintF("last_error: %08lx\n",unit->last_error);
|
||||||
|
KPrintF("LBA: %ld, LastLBA: %ld\n",lba,(unit->sectorsPerTrack * unit->cylinders * unit->heads));
|
||||||
|
#endif
|
||||||
|
return TDERR_NotSpecified;
|
||||||
|
}
|
||||||
|
|
||||||
|
lba += subcount;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#pragma GCC optimize ("-fomit-frame-pointer")
|
||||||
|
/**
|
||||||
|
* read_fast
|
||||||
|
*
|
||||||
|
* Fast copy of a 512-byte sector using movem
|
||||||
|
* Adapted from the open source at_apollo_device by Frédéric REQUIN
|
||||||
|
* https://github.com/fredrequin/at_apollo_device
|
||||||
|
*
|
||||||
|
* NOTE! source needs to be 48 bytes before the end of the data port!
|
||||||
|
* The 68000 does an extra memory access at the end of a movem instruction!
|
||||||
|
* Source: https://github.com/prb28/m68k-instructions-documentation/blob/master/instructions/movem.md
|
||||||
|
*
|
||||||
|
* With the src of end-48 the error reg will be harmlessly read instead.
|
||||||
|
*
|
||||||
|
* @param source Pointer to drive data port
|
||||||
|
* @param destination Pointer to source buffer
|
||||||
|
*/
|
||||||
void read_fast (void *source, void *destinaton) {
|
void read_fast (void *source, void *destinaton) {
|
||||||
asm volatile ("moveq #48,d7\n\t"
|
asm volatile ("moveq #48,d7\n\t"
|
||||||
|
|
||||||
@ -298,6 +442,16 @@ void read_fast (void *source, void *destinaton) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* write_fast
|
||||||
|
*
|
||||||
|
* Fast copy of a 512-byte sector using movem
|
||||||
|
* Adapted from the open source at_apollo_device by Frédéric REQUIN
|
||||||
|
* https://github.com/fredrequin/at_apollo_device
|
||||||
|
*
|
||||||
|
* @param source Pointer to source buffer
|
||||||
|
* @param destination Pointer to drive data port
|
||||||
|
*/
|
||||||
void write_fast (void *source, void *destinaton) {
|
void write_fast (void *source, void *destinaton) {
|
||||||
asm volatile (
|
asm volatile (
|
||||||
"movem.l (%0)+,d0-d6/a1-a4/a6\n\t"
|
"movem.l (%0)+,d0-d6/a1-a4/a6\n\t"
|
||||||
@ -338,89 +492,4 @@ void write_fast (void *source, void *destinaton) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#pragma GCC reset_options
|
||||||
* ata_transfer
|
|
||||||
*
|
|
||||||
* Read/write a block from/to the unit
|
|
||||||
* @param buffer Source buffer
|
|
||||||
* @param lba LBA Address
|
|
||||||
* @param count Number of blocks to transfer
|
|
||||||
* @param actual Pointer to the io requests io_Actual
|
|
||||||
* @param unit Pointer to the unit structure
|
|
||||||
* @param direction READ/WRITE
|
|
||||||
*/
|
|
||||||
BYTE ata_transfer(void *buffer, ULONG lba, ULONG count, ULONG *actual, struct IDEUnit *unit, enum xfer_dir direction) {
|
|
||||||
#if DEBUG >= 2
|
|
||||||
if (direction == READ) {
|
|
||||||
KPrintF("ata_read");
|
|
||||||
} else {
|
|
||||||
KPrintF("ata_write");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
ULONG subcount;
|
|
||||||
ULONG offset = 0;
|
|
||||||
*actual = 0;
|
|
||||||
|
|
||||||
if (count == 0) return TDERR_TooFewSecs;
|
|
||||||
|
|
||||||
BYTE drvSel = (unit->primary) ? 0xE0 : 0xF0;
|
|
||||||
*unit->drive->devHead = (UBYTE)(drvSel | ((lba >> 24) & 0x0F));
|
|
||||||
|
|
||||||
// None of this max_transfer 1FE00 nonsense!
|
|
||||||
while (count > 0) {
|
|
||||||
if (count >= MAX_TRANSFER_SECTORS) { // Transfer 256 Sectors at a time
|
|
||||||
subcount = MAX_TRANSFER_SECTORS;
|
|
||||||
} else {
|
|
||||||
subcount = count; // Get any remainders
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ata_wait_not_busy(unit))
|
|
||||||
return HFERR_BadStatus;
|
|
||||||
|
|
||||||
*unit->drive->sectorCount = (subcount & 0xFF); // Count value of 0 indicates to transfer 256 sectors
|
|
||||||
*unit->drive->lbaLow = (UBYTE)(lba);
|
|
||||||
*unit->drive->lbaMid = (UBYTE)(lba >> 8);
|
|
||||||
*unit->drive->lbaHigh = (UBYTE)(lba >> 16);
|
|
||||||
*unit->drive->error_features = 0;
|
|
||||||
*unit->drive->status_command = (direction == READ) ? ATA_CMD_READ : ATA_CMD_WRITE;
|
|
||||||
|
|
||||||
|
|
||||||
for (int block = 0; block < subcount; block++) {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (direction == READ) {
|
|
||||||
|
|
||||||
// for (int i=0; i<(unit->blockSize / 2); i++) {
|
|
||||||
// ((UWORD *)buffer)[offset] = *(UWORD *)unit->drive->data;
|
|
||||||
// offset++;
|
|
||||||
// }
|
|
||||||
read_fast((void *)(unit->drive->error_features - 48),(buffer + offset));
|
|
||||||
offset += 512;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
//for (int i=0; i<(unit->blockSize / 2); i++) {
|
|
||||||
// *(UWORD *)unit->drive->data = ((UWORD *)buffer)[offset];
|
|
||||||
// offset++;
|
|
||||||
//}
|
|
||||||
write_fast((buffer + offset),(void *)(unit->drive->error_features - 48));
|
|
||||||
offset += 512;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
*actual += unit->blockSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
count -= subcount;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
14
ata.h
14
ata.h
@ -27,10 +27,10 @@
|
|||||||
|
|
||||||
#define drv_sel_secondary (1<<4)
|
#define drv_sel_secondary (1<<4)
|
||||||
|
|
||||||
#define ata_busy (1<<7)
|
#define ata_flag_busy (1<<7)
|
||||||
#define ata_ready (1<<6)
|
#define ata_flag_ready (1<<6)
|
||||||
#define ata_drq (1<<3)
|
#define ata_flag_drq (1<<3)
|
||||||
#define ata_error (1<<0)
|
#define ata_flag_error (1<<0)
|
||||||
|
|
||||||
#define ATA_CMD_IDENTIFY 0xEC
|
#define ATA_CMD_IDENTIFY 0xEC
|
||||||
#define ATA_CMD_READ 0x20
|
#define ATA_CMD_READ 0x20
|
||||||
@ -56,13 +56,13 @@ enum xfer_dir {
|
|||||||
WRITE
|
WRITE
|
||||||
};
|
};
|
||||||
|
|
||||||
bool ata_wait_busy(struct IDEUnit *);
|
|
||||||
bool ata_wait_ready(struct IDEUnit *);
|
|
||||||
bool ata_wait_drq(struct IDEUnit *);
|
|
||||||
|
|
||||||
bool ata_init_unit(struct IDEUnit *);
|
bool ata_init_unit(struct IDEUnit *);
|
||||||
bool ata_identify(struct IDEUnit *, UWORD *);
|
bool ata_identify(struct IDEUnit *, UWORD *);
|
||||||
BYTE ata_transfer(void *buffer, ULONG lba, ULONG count, ULONG *actual, struct IDEUnit *unit, enum xfer_dir);
|
BYTE ata_transfer(void *buffer, ULONG lba, ULONG count, ULONG *actual, struct IDEUnit *unit, enum xfer_dir);
|
||||||
|
void read_fast (void *, void *);
|
||||||
|
void write_fast (void *, void *);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
4
device.h
4
device.h
@ -33,11 +33,13 @@ struct IDEUnit {
|
|||||||
BOOL present;
|
BOOL present;
|
||||||
UBYTE channel;
|
UBYTE channel;
|
||||||
UBYTE device_type;
|
UBYTE device_type;
|
||||||
|
ULONG change_count;
|
||||||
UWORD cylinders;
|
UWORD cylinders;
|
||||||
UWORD heads;
|
UWORD heads;
|
||||||
UWORD sectorsPerTrack;
|
UWORD sectorsPerTrack;
|
||||||
UWORD blockSize;
|
UWORD blockSize;
|
||||||
ULONG change_count;
|
UWORD blockShift;
|
||||||
|
UBYTE last_error[5];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DeviceBase {
|
struct DeviceBase {
|
||||||
|
|||||||
38
driver.c
38
driver.c
@ -37,20 +37,17 @@ int __attribute__((no_reorder)) _start()
|
|||||||
asm("romtag: \n"
|
asm("romtag: \n"
|
||||||
" dc.w "XSTR(RTC_MATCHWORD)" \n"
|
" dc.w "XSTR(RTC_MATCHWORD)" \n"
|
||||||
" dc.l romtag \n"
|
" dc.l romtag \n"
|
||||||
" dc.l endcode \n"
|
" dc.l _endskip \n"
|
||||||
" dc.b "XSTR(RTF_COLDSTART)" \n"
|
" dc.b "XSTR(RTF_COLDSTART)" \n"
|
||||||
" dc.b "XSTR(DEVICE_VERSION)" \n"
|
" dc.b "XSTR(DEVICE_VERSION)" \n"
|
||||||
" dc.b "XSTR(NT_DEVICE)" \n"
|
" dc.b "XSTR(NT_DEVICE)" \n"
|
||||||
" dc.b "XSTR(DEVICE_PRIORITY)" \n"
|
" dc.b "XSTR(DEVICE_PRIORITY)" \n"
|
||||||
" dc.l _device_name+4 \n"
|
" dc.l _device_name+4 \n"
|
||||||
" dc.l _device_id_string \n"
|
" dc.l _device_id_string \n"
|
||||||
" dc.l _init \n"
|
" dc.l _init \n");
|
||||||
"endcode: \n");
|
|
||||||
|
|
||||||
char device_name[] = DEVICE_NAME;
|
char device_name[] = DEVICE_NAME;
|
||||||
const char device_id_string[] = DEVICE_ID_STRING;
|
char const device_id_string[] = DEVICE_ID_STRING;
|
||||||
const char task_name[] = TASK_NAME;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set_dev_name
|
* set_dev_name
|
||||||
@ -87,7 +84,7 @@ char * set_dev_name(struct DeviceBase *dev) {
|
|||||||
*
|
*
|
||||||
* Free used resources back to the system
|
* Free used resources back to the system
|
||||||
*/
|
*/
|
||||||
void Cleanup(struct DeviceBase *dev) {
|
static void Cleanup(struct DeviceBase *dev) {
|
||||||
#if DEBUG > 0
|
#if DEBUG > 0
|
||||||
KPrintF("Cleaning up...\n");
|
KPrintF("Cleaning up...\n");
|
||||||
#endif
|
#endif
|
||||||
@ -115,14 +112,13 @@ struct Library __attribute__((used)) * init_device(struct ExecBase *SysBase asm(
|
|||||||
{
|
{
|
||||||
dev->SysBase = SysBase;
|
dev->SysBase = SysBase;
|
||||||
#if DEBUG >= 1
|
#if DEBUG >= 1
|
||||||
KPrintF("Init dev, base: %08x\n",dev);
|
KPrintF("Init dev, base: %08lx\n",dev);
|
||||||
#endif
|
#endif
|
||||||
struct Library *ExpansionBase = NULL;
|
struct Library *ExpansionBase = NULL;
|
||||||
|
|
||||||
char *devName;
|
char *devName;
|
||||||
|
|
||||||
if (!(devName = set_dev_name(dev))) return NULL;
|
if (!(devName = set_dev_name(dev))) return NULL;
|
||||||
|
|
||||||
/* save pointer to our loaded code (the SegList) */
|
/* save pointer to our loaded code (the SegList) */
|
||||||
dev->saved_seg_list = seg_list;
|
dev->saved_seg_list = seg_list;
|
||||||
dev->lib.lib_Node.ln_Type = NT_DEVICE;
|
dev->lib.lib_Node.ln_Type = NT_DEVICE;
|
||||||
@ -143,7 +139,7 @@ struct Library __attribute__((used)) * init_device(struct ExecBase *SysBase asm(
|
|||||||
if ((dev->units = AllocMem(sizeof(struct IDEUnit)*MAX_UNITS, (MEMF_ANY|MEMF_CLEAR))) == NULL)
|
if ((dev->units = AllocMem(sizeof(struct IDEUnit)*MAX_UNITS, (MEMF_ANY|MEMF_CLEAR))) == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
#if DEBUG >=2
|
#if DEBUG >=2
|
||||||
KPrintF("Dev->Units: %x%x\n",(ULONG)dev->units);
|
KPrintF("Dev->Units: %08lx\n",(ULONG)dev->units);
|
||||||
#endif
|
#endif
|
||||||
if (!(ExpansionBase = (struct Library *)OpenLibrary("expansion.library",0))) {
|
if (!(ExpansionBase = (struct Library *)OpenLibrary("expansion.library",0))) {
|
||||||
Cleanup(dev);
|
Cleanup(dev);
|
||||||
@ -182,7 +178,7 @@ struct Library __attribute__((used)) * init_device(struct ExecBase *SysBase asm(
|
|||||||
cd->cd_Flags &= ~(CDF_CONFIGME); // Claim the board
|
cd->cd_Flags &= ~(CDF_CONFIGME); // Claim the board
|
||||||
dev->num_boards++;
|
dev->num_boards++;
|
||||||
#if DEBUG >= 2
|
#if DEBUG >= 2
|
||||||
KPrintF("Claiming board %04x%04x\n",(ULONG)cd->cd_BoardAddr);
|
KPrintF("Claiming board %08lx\n",(ULONG)cd->cd_BoardAddr);
|
||||||
#endif
|
#endif
|
||||||
for (BYTE i=0; i<2; i++) {
|
for (BYTE i=0; i<2; i++) {
|
||||||
dev->units[i].SysBase = SysBase;
|
dev->units[i].SysBase = SysBase;
|
||||||
@ -192,8 +188,9 @@ struct Library __attribute__((used)) * init_device(struct ExecBase *SysBase asm(
|
|||||||
dev->units[i].channel = ((i%4) < 2) ? 0 : 1;
|
dev->units[i].channel = ((i%4) < 2) ? 0 : 1;
|
||||||
dev->units[i].change_count = 1;
|
dev->units[i].change_count = 1;
|
||||||
dev->units[i].device_type = DG_DIRECT_ACCESS;
|
dev->units[i].device_type = DG_DIRECT_ACCESS;
|
||||||
|
dev->units[i].present = false;
|
||||||
#if DEBUG >= 2
|
#if DEBUG >= 2
|
||||||
KPrintF("testing unit %x%x\n",i);
|
KPrintF("testing unit %08lx\n",i);
|
||||||
#endif
|
#endif
|
||||||
if (ata_init_unit(&dev->units[i])) {
|
if (ata_init_unit(&dev->units[i])) {
|
||||||
dev->num_units++;
|
dev->num_units++;
|
||||||
@ -204,7 +201,7 @@ struct Library __attribute__((used)) * init_device(struct ExecBase *SysBase asm(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG >= 1
|
#if DEBUG >= 1
|
||||||
KPrintF("Detected %x%x drives, %x%x boards\n",dev->num_units, dev->num_boards);
|
KPrintF("Detected %ld drives, %ld boards\n",dev->num_units, dev->num_boards);
|
||||||
#endif
|
#endif
|
||||||
if (dev->num_units > 0) {
|
if (dev->num_units > 0) {
|
||||||
#if DEBUG >= 1
|
#if DEBUG >= 1
|
||||||
@ -262,7 +259,7 @@ static BPTR __attribute__((used)) expunge(struct DeviceBase *dev asm("a6"))
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev->Task != NULL) {
|
if (dev->Task != NULL && dev->TaskActive == true) {
|
||||||
// Shut down ide_task
|
// Shut down ide_task
|
||||||
|
|
||||||
struct MsgPort *mp = NULL;
|
struct MsgPort *mp = NULL;
|
||||||
@ -298,12 +295,13 @@ will execute your Open at a time. */
|
|||||||
static void __attribute__((used)) open(struct DeviceBase *dev asm("a6"), struct IORequest *ioreq asm("a1"), ULONG unitnum asm("d0"), ULONG flags asm("d1"))
|
static void __attribute__((used)) open(struct DeviceBase *dev asm("a6"), struct IORequest *ioreq asm("a1"), ULONG unitnum asm("d0"), ULONG flags asm("d1"))
|
||||||
{
|
{
|
||||||
#if DEBUG >= 2
|
#if DEBUG >= 2
|
||||||
KPrintF((CONST_STRPTR) "running open() for unitnum %x%x\n",unitnum);
|
KPrintF((CONST_STRPTR) "running open() for unitnum %ld\n",unitnum);
|
||||||
#endif
|
#endif
|
||||||
ioreq->io_Error = IOERR_OPENFAIL;
|
ioreq->io_Error = IOERR_OPENFAIL;
|
||||||
|
|
||||||
if (dev->Task == NULL) {
|
if (dev->Task == NULL || dev->TaskActive == false) {
|
||||||
ioreq->io_Error = IOERR_OPENFAIL;
|
ioreq->io_Error = IOERR_OPENFAIL;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -372,6 +370,7 @@ static UWORD supported_commands[] =
|
|||||||
TD_CHANGESTATE,
|
TD_CHANGESTATE,
|
||||||
TD_GETDRIVETYPE,
|
TD_GETDRIVETYPE,
|
||||||
TD_GETGEOMETRY,
|
TD_GETGEOMETRY,
|
||||||
|
TD_MOTOR,
|
||||||
TD_PROTSTATUS,
|
TD_PROTSTATUS,
|
||||||
TD_READ64,
|
TD_READ64,
|
||||||
TD_WRITE64,
|
TD_WRITE64,
|
||||||
@ -396,7 +395,7 @@ static void __attribute__((used)) begin_io(struct DeviceBase *dev asm("a6"), str
|
|||||||
#endif
|
#endif
|
||||||
ioreq->io_Error = TDERR_NotSpecified;
|
ioreq->io_Error = TDERR_NotSpecified;
|
||||||
|
|
||||||
if (dev->Task == NULL) {
|
if (dev->Task == NULL || dev->TaskActive == false) {
|
||||||
ioreq->io_Error = IOERR_OPENFAIL;
|
ioreq->io_Error = IOERR_OPENFAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -405,6 +404,7 @@ static void __attribute__((used)) begin_io(struct DeviceBase *dev asm("a6"), str
|
|||||||
switch (ioreq->io_Command) {
|
switch (ioreq->io_Command) {
|
||||||
case CMD_CLEAR:
|
case CMD_CLEAR:
|
||||||
case CMD_UPDATE:
|
case CMD_UPDATE:
|
||||||
|
case TD_MOTOR:
|
||||||
ioreq->io_Actual = 0;
|
ioreq->io_Actual = 0;
|
||||||
ioreq->io_Error = 0;
|
ioreq->io_Error = 0;
|
||||||
break;
|
break;
|
||||||
@ -473,11 +473,11 @@ static void __attribute__((used)) begin_io(struct DeviceBase *dev asm("a6"), str
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
#if DEBUG >= 2
|
#if DEBUG >= 2
|
||||||
KPrintF("Unknown command %x%x\n", ioreq->io_Command);
|
KPrintF("Unknown command %d\n", ioreq->io_Command);
|
||||||
#endif
|
#endif
|
||||||
ioreq->io_Error = IOERR_NOCMD;
|
ioreq->io_Error = IOERR_NOCMD;
|
||||||
}
|
}
|
||||||
if (!ioreq->io_Flags & IOF_QUICK) {
|
if (ioreq && !(ioreq->io_Flags & IOF_QUICK)) {
|
||||||
ReplyMsg(&ioreq->io_Message);
|
ReplyMsg(&ioreq->io_Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
13
idetask.c
13
idetask.c
@ -35,7 +35,7 @@ static void handle_scsi_command(struct IOStdReq *ioreq) {
|
|||||||
enum xfer_dir direction = WRITE;
|
enum xfer_dir direction = WRITE;
|
||||||
|
|
||||||
#if DEBUG >= 2
|
#if DEBUG >= 2
|
||||||
KPrintF("Command %04x%04x\n",*scsi_command->scsi_Command);
|
KPrintF("Command %ld\n",*scsi_command->scsi_Command);
|
||||||
#endif
|
#endif
|
||||||
switch (scsi_command->scsi_Command[0]) {
|
switch (scsi_command->scsi_Command[0]) {
|
||||||
case SCSI_CMD_TEST_UNIT_READY:
|
case SCSI_CMD_TEST_UNIT_READY:
|
||||||
@ -178,13 +178,13 @@ do_scsi_transfer:
|
|||||||
* This is a task to complete IO Requests for all units
|
* This is a task to complete IO Requests for all units
|
||||||
* Requests are sent here from begin_io via the dev->TaskMP Message port
|
* Requests are sent here from begin_io via the dev->TaskMP Message port
|
||||||
*/
|
*/
|
||||||
void ide_task () {
|
void __attribute__((noreturn)) ide_task () {
|
||||||
struct ExecBase *SysBase = *(struct ExecBase **)4UL;
|
struct ExecBase *SysBase = *(struct ExecBase **)4UL;
|
||||||
struct Task volatile *task = FindTask(NULL);
|
struct Task volatile *task = FindTask(NULL);
|
||||||
struct MsgPort *mp;
|
struct MsgPort *mp;
|
||||||
struct IOStdReq *ioreq;
|
struct IOStdReq *ioreq;
|
||||||
struct IDEUnit *unit;
|
struct IDEUnit *unit;
|
||||||
UWORD blocksize;
|
UWORD blockShift;
|
||||||
ULONG lba;
|
ULONG lba;
|
||||||
ULONG count;
|
ULONG count;
|
||||||
enum xfer_dir direction = WRITE;
|
enum xfer_dir direction = WRITE;
|
||||||
@ -230,9 +230,9 @@ void ide_task () {
|
|||||||
case TD_FORMAT64:
|
case TD_FORMAT64:
|
||||||
case NSCMD_TD_WRITE64:
|
case NSCMD_TD_WRITE64:
|
||||||
case NSCMD_TD_FORMAT64:
|
case NSCMD_TD_FORMAT64:
|
||||||
blocksize = ((struct IDEUnit *)ioreq->io_Unit)->blockSize;
|
blockShift = ((struct IDEUnit *)ioreq->io_Unit)->blockShift;
|
||||||
lba = (((long long)ioreq->io_Actual << 32 | ioreq->io_Offset) / (UWORD)blocksize);
|
lba = (((long long)ioreq->io_Actual << 32 | ioreq->io_Offset) >> blockShift);
|
||||||
count = (ioreq->io_Length/blocksize);
|
count = (ioreq->io_Length >> blockShift);
|
||||||
ioreq->io_Error = ata_transfer(ioreq->io_Data, lba, count, &ioreq->io_Actual, unit, direction);
|
ioreq->io_Error = ata_transfer(ioreq->io_Data, lba, count, &ioreq->io_Actual, unit, direction);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -249,6 +249,7 @@ void ide_task () {
|
|||||||
DeletePort(mp);
|
DeletePort(mp);
|
||||||
dev->TaskMP = NULL;
|
dev->TaskMP = NULL;
|
||||||
dev->Task = NULL;
|
dev->Task = NULL;
|
||||||
|
dev->TaskActive = false;
|
||||||
ReplyMsg(&ioreq->io_Message);
|
ReplyMsg(&ioreq->io_Message);
|
||||||
RemTask(NULL);
|
RemTask(NULL);
|
||||||
Wait(0);
|
Wait(0);
|
||||||
|
|||||||
@ -1033,7 +1033,7 @@ int mount_drives(struct ConfigDev *cd, char *devName)
|
|||||||
|
|
||||||
dbg("Mounter:\n");
|
dbg("Mounter:\n");
|
||||||
ms.deviceName = devName;
|
ms.deviceName = devName;
|
||||||
ULONG units[] = {2,0,1};
|
ULONG units[] = {1,0};
|
||||||
ms.unitNum = &units;
|
ms.unitNum = &units;
|
||||||
ms.creatorName = NULL;
|
ms.creatorName = NULL;
|
||||||
ms.configDev = cd;
|
ms.configDev = cd;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user