1 #include <exec/resident.h>
2 #include <exec/errors.h>
3 #include <exec/memory.h>
4 #include <exec/lists.h>
5 #include <exec/alerts.h>
6 #include <exec/tasks.h>
8 #include <exec/execbase.h>
10 #include <libraries/expansion.h>
12 #include <devices/trackdisk.h>
13 #include <devices/timer.h>
14 #include <devices/scsidisk.h>
16 #include <dos/filehandler.h>
18 #include <proto/exec.h>
19 #include <proto/disk.h>
20 #include <proto/expansion.h>
24 #include "../piscsi-enums.h"
28 #define XSTR(s) STR(s)
30 #define DEVICE_NAME "pi-scsi.device"
31 #define DEVICE_DATE "(3 Feb 2021)"
32 #define DEVICE_ID_STRING "PiSCSI " XSTR(DEVICE_VERSION) "." XSTR(DEVICE_REVISION) " " DEVICE_DATE
33 #define DEVICE_VERSION 43
34 #define DEVICE_REVISION 20
35 #define DEVICE_PRIORITY 0
39 struct Device* pi_dev;
57 struct ExecBase *SysBase;
58 uint8_t *saved_seg_list;
61 #define WRITESHORT(cmd, val) *(unsigned short *)((unsigned long)(PISCSI_OFFSET+cmd)) = val;
62 #define WRITELONG(cmd, val) *(unsigned long *)((unsigned long)(PISCSI_OFFSET+cmd)) = val;
63 #define WRITEBYTE(cmd, val) *(unsigned char *)((unsigned long)(PISCSI_OFFSET+cmd)) = val;
65 #define READSHORT(cmd, var) var = *(volatile unsigned short *)(PISCSI_OFFSET + cmd);
66 #define READLONG(cmd, var) var = *(volatile unsigned long *)(PISCSI_OFFSET + cmd);
68 int __attribute__((no_reorder)) _start()
74 " dc.w "XSTR(RTC_MATCHWORD)" \n"
77 " dc.b "XSTR(RTF_AUTOINIT)" \n"
78 " dc.b "XSTR(DEVICE_VERSION)" \n"
79 " dc.b "XSTR(NT_DEVICE)" \n"
80 " dc.b "XSTR(DEVICE_PRIORITY)" \n"
81 " dc.l _device_name \n"
82 " dc.l _device_id_string \n"
83 " dc.l _auto_init_tables \n"
86 char device_name[] = DEVICE_NAME;
87 char device_id_string[] = DEVICE_ID_STRING;
89 uint8_t piscsi_perform_io(struct piscsi_unit *u, struct IORequest *io);
90 uint8_t piscsi_rw(struct piscsi_unit *u, struct IORequest *io);
91 uint8_t piscsi_scsi(struct piscsi_unit *u, struct IORequest *io);
94 //#define debugval(...)
95 #define debug(c, v) WRITESHORT(c, v)
96 #define debugval(c, v) WRITELONG(c, v)
98 struct piscsi_base *dev_base = NULL;
100 static struct Library __attribute__((used)) *init_device(uint8_t *seg_list asm("a0"), struct Library *dev asm("d0"))
102 SysBase = *(struct ExecBase **)4L;
104 debug(PISCSI_DBG_MSG, DBG_INIT);
106 dev_base = AllocMem(sizeof(struct piscsi_base), MEMF_PUBLIC | MEMF_CLEAR);
107 dev_base->pi_dev = (struct Device *)dev;
109 for (int i = 0; i < NUM_UNITS; i++) {
111 WRITESHORT(PISCSI_CMD_DRVNUM, (i * 10));
112 dev_base->units[i].regs_ptr = PISCSI_OFFSET;
113 READSHORT(PISCSI_CMD_DRVTYPE, r);
114 dev_base->units[i].enabled = r;
115 dev_base->units[i].present = r;
116 dev_base->units[i].valid = r;
117 dev_base->units[i].unit_num = i;
118 if (dev_base->units[i].present) {
119 READLONG(PISCSI_CMD_CYLS, dev_base->units[i].c);
120 READSHORT(PISCSI_CMD_HEADS, dev_base->units[i].h);
121 READSHORT(PISCSI_CMD_SECS, dev_base->units[i].s);
123 debugval(PISCSI_DBG_VAL1, dev_base->units[i].c);
124 debugval(PISCSI_DBG_VAL2, dev_base->units[i].h);
125 debugval(PISCSI_DBG_VAL3, dev_base->units[i].s);
126 debug(PISCSI_DBG_MSG, DBG_CHS);
128 dev_base->units[i].change_num++;
134 static uint8_t* __attribute__((used)) expunge(struct Library *dev asm("a6"))
136 debug(PISCSI_DBG_MSG, DBG_CLEANUP);
137 /*if (dev_base->open_count)
139 FreeMem(dev_base, sizeof(struct piscsi_base));*/
143 static void __attribute__((used)) open(struct Library *dev asm("a6"), struct IOExtTD *iotd asm("a1"), uint32_t num asm("d0"), uint32_t flags asm("d1"))
145 //struct Node* node = (struct Node*)iotd;
146 int io_err = IOERR_OPENFAIL;
148 //WRITESHORT(PISCSI_CMD_DEBUGME, 1);
151 WRITELONG(PISCSI_CMD_DRVNUM, num);
152 READLONG(PISCSI_CMD_DRVNUM, unit_num);
154 debugval(PISCSI_DBG_VAL1, unit_num);
155 debugval(PISCSI_DBG_VAL2, flags);
156 debugval(PISCSI_DBG_VAL3, num);
157 debug(PISCSI_DBG_MSG, DBG_OPENDEV);
159 if (iotd && unit_num < NUM_UNITS) {
160 if (dev_base->units[unit_num].enabled && dev_base->units[unit_num].present) {
162 iotd->iotd_Req.io_Unit = (struct Unit*)&dev_base->units[unit_num].unit;
163 iotd->iotd_Req.io_Unit->unit_flags = UNITF_ACTIVE;
164 iotd->iotd_Req.io_Unit->unit_OpenCnt = 1;
168 iotd->iotd_Req.io_Error = io_err;
169 ((struct Library *)dev_base->pi_dev)->lib_OpenCnt++;
172 static uint8_t* __attribute__((used)) close(struct Library *dev asm("a6"), struct IOExtTD *iotd asm("a1"))
174 ((struct Library *)dev_base->pi_dev)->lib_OpenCnt--;
178 static void __attribute__((used)) begin_io(struct Library *dev asm("a6"), struct IORequest *io asm("a1"))
180 if (dev_base == NULL || io == NULL)
183 struct piscsi_unit *u;
184 struct Node* node = (struct Node*)io;
185 u = (struct piscsi_unit *)io->io_Unit;
187 if (node == NULL || u == NULL)
190 debugval(PISCSI_DBG_VAL1, io->io_Command);
191 debugval(PISCSI_DBG_VAL2, io->io_Flags);
192 debugval(PISCSI_DBG_VAL3, (io->io_Flags & IOF_QUICK));
193 debug(PISCSI_DBG_MSG, DBG_BEGINIO);
194 io->io_Error = piscsi_perform_io(u, io);
196 if (!(io->io_Flags & IOF_QUICK)) {
197 ReplyMsg(&io->io_Message);
201 static uint32_t __attribute__((used)) abort_io(struct Library *dev asm("a6"), struct IORequest *io asm("a1"))
203 debug(PISCSI_DBG_MSG, DBG_ABORTIO);
204 if (!io) return IOERR_NOCMD;
205 io->io_Error = IOERR_ABORTED;
207 return IOERR_ABORTED;
210 uint8_t piscsi_rw(struct piscsi_unit *u, struct IORequest *io) {
211 struct IOStdReq *iostd = (struct IOStdReq *)io;
212 struct IOExtTD *iotd = (struct IOExtTD *)io;
216 //uint32_t block, num_blocks;
219 data = iotd->iotd_Req.io_Data;
220 len = iotd->iotd_Req.io_Length;
223 return IOERR_BADADDRESS;
225 if (len < PISCSI_BLOCK_SIZE) {
226 iostd->io_Actual = 0;
227 return IOERR_BADLENGTH;
230 switch (io->io_Command) {
232 case NSCMD_TD_WRITE64:
234 case NSCMD_TD_FORMAT64:
235 WRITELONG(PISCSI_CMD_ADDR1, iostd->io_Offset);
236 WRITELONG(PISCSI_CMD_ADDR2, len);
237 WRITELONG(PISCSI_CMD_ADDR3, (uint32_t)data);
238 WRITELONG(PISCSI_CMD_ADDR4, iostd->io_Actual);
239 WRITESHORT(PISCSI_CMD_WRITE64, u->unit_num);
242 case NSCMD_TD_READ64:
243 WRITELONG(PISCSI_CMD_ADDR1, iostd->io_Offset);
244 WRITELONG(PISCSI_CMD_ADDR2, len);
245 WRITELONG(PISCSI_CMD_ADDR3, (uint32_t)data);
246 WRITELONG(PISCSI_CMD_ADDR4, iostd->io_Actual);
247 WRITESHORT(PISCSI_CMD_READ64, u->unit_num);
251 WRITELONG(PISCSI_CMD_ADDR1, (iostd->io_Offset >> 9));
252 WRITELONG(PISCSI_CMD_ADDR2, len);
253 WRITELONG(PISCSI_CMD_ADDR3, (uint32_t)data);
254 WRITESHORT(PISCSI_CMD_WRITE, u->unit_num);
257 WRITELONG(PISCSI_CMD_ADDR1, (iostd->io_Offset >> 9));
258 WRITELONG(PISCSI_CMD_ADDR2, len);
259 WRITELONG(PISCSI_CMD_ADDR3, (uint32_t)data);
260 WRITESHORT(PISCSI_CMD_READ, u->unit_num);
265 iostd->io_Actual = 0;
267 if (sderr & SCSIERR_TIMEOUT)
268 return TDERR_DiskChanged;
269 if (sderr & SCSIERR_PARAM)
270 return TDERR_SeekError;
271 if (sderr & SCSIERR_ADDRESS)
272 return TDERR_SeekError;
273 if (sderr & (SCSIERR_ERASESEQ | SCSIERR_ERASERES))
274 return TDERR_BadSecPreamble;
275 if (sderr & SCSIERR_CRC)
276 return TDERR_BadSecSum;
277 if (sderr & SCSIERR_ILLEGAL)
278 return TDERR_TooFewSecs;
279 if (sderr & SCSIERR_IDLE)
280 return TDERR_PostReset;
282 return TDERR_SeekError;
284 iostd->io_Actual = iotd->iotd_Req.io_Length;
290 #define PISCSI_ID_STRING "PISTORM Fake SCSI Disk 0.1 1111111111111111"
292 uint8_t piscsi_scsi(struct piscsi_unit *u, struct IORequest *io)
294 struct IOStdReq *iostd = (struct IOStdReq *)io;
295 struct SCSICmd *scsi = iostd->io_Data;
296 //uint8_t* registers = sdu->sdu_Registers;
297 uint8_t *data = (uint8_t *)scsi->scsi_Data;
298 uint32_t i, block = 0, blocks = 0, maxblocks = 0;
302 debugval(PISCSI_DBG_VAL1, iostd->io_Length);
303 debugval(PISCSI_DBG_VAL2, scsi->scsi_Command[0]);
304 debugval(PISCSI_DBG_VAL3, scsi->scsi_Command[1]);
305 debugval(PISCSI_DBG_VAL4, scsi->scsi_Command[2]);
306 debugval(PISCSI_DBG_VAL5, scsi->scsi_CmdLength);
307 debug(PISCSI_DBG_MSG, DBG_SCSICMD);
309 //maxblocks = u->s * u->c * u->h;
311 if (scsi->scsi_CmdLength < 6) {
312 return IOERR_BADLENGTH;
315 if (scsi->scsi_Command == NULL) {
316 return IOERR_BADADDRESS;
319 scsi->scsi_Actual = 0;
320 //iostd->io_Actual = sizeof(*scsi);
322 switch (scsi->scsi_Command[0]) {
323 case 0x00: // TEST_UNIT_READY
327 case 0x12: // INQUIRY
328 for (i = 0; i < scsi->scsi_Length; i++) {
332 case 0: // SCSI device type: direct-access device
338 case 2: // VERSION = 0
341 case 3: // NORMACA=0, HISUP = 0, RESPONSE_DATA_FORMAT = 2
342 val = (0 << 5) | (0 << 4) | 2;
344 case 4: // ADDITIONAL_LENGTH = 44 - 4
348 if (i >= 8 && i < 44)
349 val = PISCSI_ID_STRING[i - 8];
356 scsi->scsi_Actual = i;
360 case 0x08: // READ (6)
361 case 0x0a: // WRITE (6)
362 case 0x28: // READ (10)
363 case 0x2A: // WRITE (10)
364 switch (scsi->scsi_Command[0]) {
368 block = scsi->scsi_Command[1] & 0x1f;
369 block = (block << 8) | scsi->scsi_Command[2];
370 block = (block << 8) | scsi->scsi_Command[3];
371 blocks = scsi->scsi_Command[4];
376 block = scsi->scsi_Command[2];
377 block = (block << 8) | scsi->scsi_Command[3];
378 block = (block << 8) | scsi->scsi_Command[4];
379 block = (block << 8) | scsi->scsi_Command[5];
381 blocks = scsi->scsi_Command[7];
382 blocks = (blocks << 8) | scsi->scsi_Command[8];
386 WRITESHORT(PISCSI_CMD_DRVNUM, u->unit_num);
387 READLONG(PISCSI_CMD_BLOCKS, maxblocks);
388 if (block + blocks > maxblocks || blocks == 0) {
389 err = IOERR_BADADDRESS;
392 /*if (scsi->scsi_Length < (blocks << SD_SECTOR_SHIFT)) {
393 err = IOERR_BADLENGTH;
397 err = IOERR_BADADDRESS;
402 WRITELONG(PISCSI_CMD_ADDR2, block);
403 WRITELONG(PISCSI_CMD_ADDR2, (blocks << 9));
404 WRITELONG(PISCSI_CMD_ADDR3, (uint32_t)data);
405 WRITESHORT(PISCSI_CMD_READ, u->unit_num);
408 WRITELONG(PISCSI_CMD_ADDR2, block);
409 WRITELONG(PISCSI_CMD_ADDR2, (blocks << 9));
410 WRITELONG(PISCSI_CMD_ADDR3, (uint32_t)data);
411 WRITESHORT(PISCSI_CMD_WRITE, u->unit_num);
414 scsi->scsi_Actual = scsi->scsi_Length;
418 case 0x25: // READ CAPACITY (10)
419 if (scsi->scsi_CmdLength < 10) {
420 err = HFERR_BadStatus;
424 block = *((uint32_t*)&scsi->scsi_Command[2]);
426 if (scsi->scsi_Length < 8) {
427 err = IOERR_BADLENGTH;
431 WRITESHORT(PISCSI_CMD_DRVNUM, u->unit_num);
432 READLONG(PISCSI_CMD_BLOCKS, blocks);
433 ((uint32_t*)data)[0] = blocks - 1;
434 ((uint32_t*)data)[1] = PISCSI_BLOCK_SIZE;
436 scsi->scsi_Actual = 8;
440 case 0x1a: // MODE SENSE (6)
441 data[0] = 3 + 8 + 0x16;
442 data[1] = 0; // MEDIUM TYPE
446 WRITESHORT(PISCSI_CMD_DRVNUM, u->unit_num);
447 READLONG(PISCSI_CMD_BLOCKS, maxblocks);
448 (blocks = (maxblocks - 1) & 0xFFFFFF);
450 *((uint32_t *)&data[4]) = blocks;
451 *((uint32_t *)&data[8]) = PISCSI_BLOCK_SIZE;
453 switch (((UWORD)scsi->scsi_Command[2] << 8) | scsi->scsi_Command[3]) {
454 case 0x0300: { // Format Device Mode
455 debug(PISCSI_DBG_MSG, DBG_SCSI_FORMATDEVICE);
456 uint8_t *datext = data + 12;
461 *((uint32_t *)&datext[4]) = 0;
462 *((uint32_t *)&datext[8]) = 0;
463 *((uint16_t *)&datext[10]) = u->s;
464 *((uint16_t *)&datext[12]) = PISCSI_BLOCK_SIZE;
467 *((uint32_t *)&datext[16]) = 0;
470 scsi->scsi_Actual = data[0] + 1;
474 case 0x0400: // Rigid Drive Geometry
475 debug(PISCSI_DBG_MSG, DBG_SCSI_RDG);
476 uint8_t *datext = data + 12;
478 *((uint32_t *)&datext[1]) = u->c;
482 *((uint32_t *)&datext[6]) = 0;
483 *((uint32_t *)&datext[10]) = 0;
484 *((uint32_t *)&datext[13]) = u->c;
486 *((uint32_t *)&datext[18]) = 0;
487 *((uint16_t *)&datext[20]) = 5400;
489 scsi->scsi_Actual = data[0] + 1;
494 debugval(PISCSI_DBG_VAL1, (((UWORD)scsi->scsi_Command[2] << 8) | scsi->scsi_Command[3]));
495 debug(PISCSI_DBG_MSG, DBG_SCSI_UNKNOWN_MODESENSE);
496 err = HFERR_BadStatus;
501 case 0x37: // READ DEFECT DATA (10)
503 case 0x40: // CHANGE DEFINITION
507 debugval(PISCSI_DBG_VAL1, scsi->scsi_Command[0]);
508 debug(PISCSI_DBG_MSG, DBG_SCSI_UNKNOWN_COMMAND);
509 err = HFERR_BadStatus;
514 debugval(PISCSI_DBG_VAL1, err);
515 debug(PISCSI_DBG_MSG, DBG_SCSIERR);
516 scsi->scsi_Actual = 0;
522 uint16_t ns_support[] = {
551 #define DUMMYCMD iostd->io_Actual = 0; break;
552 uint8_t piscsi_perform_io(struct piscsi_unit *u, struct IORequest *io) {
553 struct IOStdReq *iostd = (struct IOStdReq *)io;
554 struct IOExtTD *iotd = (struct IOExtTD *)io;
559 //struct DriveGeometry *geom;
563 return IOERR_OPENFAIL;
566 //data = iotd->iotd_Req.io_Data;
567 //len = iotd->iotd_Req.io_Length;
569 if (io->io_Error == IOERR_ABORTED) {
573 debugval(PISCSI_DBG_VAL1, io->io_Command);
574 debugval(PISCSI_DBG_VAL2, io->io_Flags);
575 debugval(PISCSI_DBG_VAL3, iostd->io_Length);
576 debug(PISCSI_DBG_MSG, DBG_IOCMD);
578 switch (io->io_Command) {
579 case NSCMD_DEVICEQUERY: {
580 struct NSDeviceQueryResult *res = (struct NSDeviceQueryResult *)iotd->iotd_Req.io_Data;
581 res->DevQueryFormat = 0;
582 res->SizeAvailable = 16;;
583 res->DeviceType = NSDEVTYPE_TRACKDISK;
584 res->DeviceSubType = 0;
585 res->SupportedCommands = ns_support;
587 iostd->io_Actual = 16;
592 /* Invalidate read buffer */
595 /* Flush write buffer */
600 iostd->io_Actual = u->change_num;
606 case TD_GETDRIVETYPE:
607 iostd->io_Actual = DG_DIRECT_ACCESS;
610 iostd->io_Actual = u->motor;
611 u->motor = iostd->io_Length ? 1 : 0;
616 case NSCMD_TD_FORMAT64:
618 case NSCMD_TD_READ64:
620 case NSCMD_TD_WRITE64:
623 err = piscsi_rw(u, io);
627 err = piscsi_scsi(u, io);
630 //int cmd = io->io_Command;
631 debug(PISCSI_DBG_MSG, DBG_IOCMD_UNHANDLED);
641 static uint32_t device_vectors[] = {
645 0, //extFunc not used here
651 const uint32_t auto_init_tables[4] = {
652 sizeof(struct Library),
653 (uint32_t)device_vectors,
655 (uint32_t)init_device