1 // SPDX-License-Identifier: MIT
3 #include <exec/resident.h>
4 #include <exec/errors.h>
5 #include <exec/memory.h>
6 #include <exec/lists.h>
7 #include <exec/alerts.h>
8 #include <exec/tasks.h>
10 #include <exec/execbase.h>
12 #include <libraries/expansion.h>
14 #include <devices/trackdisk.h>
15 #include <devices/timer.h>
16 #include <devices/scsidisk.h>
18 #include <dos/filehandler.h>
20 #include <proto/exec.h>
21 #include <proto/disk.h>
22 #include <proto/expansion.h>
26 #include "../piscsi-enums.h"
30 #define XSTR(s) STR(s)
32 #define DEVICE_NAME "pi-scsi.device"
33 #define DEVICE_DATE "(3 Feb 2021)"
34 #define DEVICE_ID_STRING "PiSCSI " XSTR(DEVICE_VERSION) "." XSTR(DEVICE_REVISION) " " DEVICE_DATE
35 #define DEVICE_VERSION 43
36 #define DEVICE_REVISION 20
37 #define DEVICE_PRIORITY 0
41 struct Device* pi_dev;
60 struct ExecBase *SysBase;
61 uint8_t *saved_seg_list;
64 #define WRITESHORT(cmd, val) *(unsigned short *)((unsigned long)(PISCSI_OFFSET+cmd)) = val;
65 #define WRITELONG(cmd, val) *(unsigned long *)((unsigned long)(PISCSI_OFFSET+cmd)) = val;
66 #define WRITEBYTE(cmd, val) *(unsigned char *)((unsigned long)(PISCSI_OFFSET+cmd)) = val;
68 #define READSHORT(cmd, var) var = *(volatile unsigned short *)(PISCSI_OFFSET + cmd);
69 #define READLONG(cmd, var) var = *(volatile unsigned long *)(PISCSI_OFFSET + cmd);
71 int __attribute__((no_reorder)) _start()
77 " dc.w "XSTR(RTC_MATCHWORD)" \n"
80 " dc.b "XSTR(RTF_AUTOINIT)" \n"
81 " dc.b "XSTR(DEVICE_VERSION)" \n"
82 " dc.b "XSTR(NT_DEVICE)" \n"
83 " dc.b "XSTR(DEVICE_PRIORITY)" \n"
84 " dc.l _device_name \n"
85 " dc.l _device_id_string \n"
86 " dc.l _auto_init_tables \n"
89 char device_name[] = DEVICE_NAME;
90 char device_id_string[] = DEVICE_ID_STRING;
92 uint8_t piscsi_perform_io(struct piscsi_unit *u, struct IORequest *io);
93 uint8_t piscsi_rw(struct piscsi_unit *u, struct IORequest *io);
94 uint8_t piscsi_scsi(struct piscsi_unit *u, struct IORequest *io);
98 //#define debug(c, v) WRITESHORT(c, v)
99 //#define debugval(c, v) WRITELONG(c, v)
101 struct piscsi_base *dev_base = NULL;
103 static struct Library __attribute__((used)) *init_device(uint8_t *seg_list asm("a0"), struct Library *dev asm("d0"))
105 SysBase = *(struct ExecBase **)4L;
107 debug(PISCSI_DBG_MSG, DBG_INIT);
109 dev_base = AllocMem(sizeof(struct piscsi_base), MEMF_PUBLIC | MEMF_CLEAR);
110 dev_base->pi_dev = (struct Device *)dev;
112 for (int i = 0; i < NUM_UNITS; i++) {
114 WRITESHORT(PISCSI_CMD_DRVNUM, (i * 10));
115 dev_base->units[i].regs_ptr = PISCSI_OFFSET;
116 READSHORT(PISCSI_CMD_DRVTYPE, r);
117 dev_base->units[i].enabled = r;
118 dev_base->units[i].present = r;
119 dev_base->units[i].valid = r;
120 dev_base->units[i].unit_num = i;
121 dev_base->units[i].scsi_num = i * 10;
122 if (dev_base->units[i].present) {
123 READLONG(PISCSI_CMD_CYLS, dev_base->units[i].c);
124 READSHORT(PISCSI_CMD_HEADS, dev_base->units[i].h);
125 READSHORT(PISCSI_CMD_SECS, dev_base->units[i].s);
127 debugval(PISCSI_DBG_VAL1, dev_base->units[i].c);
128 debugval(PISCSI_DBG_VAL2, dev_base->units[i].h);
129 debugval(PISCSI_DBG_VAL3, dev_base->units[i].s);
130 debug(PISCSI_DBG_MSG, DBG_CHS);
132 dev_base->units[i].change_num++;
138 static uint8_t* __attribute__((used)) expunge(struct Library *dev asm("a6"))
140 debug(PISCSI_DBG_MSG, DBG_CLEANUP);
141 /*if (dev_base->open_count)
143 FreeMem(dev_base, sizeof(struct piscsi_base));*/
147 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"))
149 //struct Node* node = (struct Node*)iotd;
150 int io_err = IOERR_OPENFAIL;
152 //WRITESHORT(PISCSI_CMD_DEBUGME, 1);
155 WRITELONG(PISCSI_CMD_DRVNUM, num);
156 READLONG(PISCSI_CMD_DRVNUM, unit_num);
158 debugval(PISCSI_DBG_VAL1, unit_num);
159 debugval(PISCSI_DBG_VAL2, flags);
160 debugval(PISCSI_DBG_VAL3, num);
161 debug(PISCSI_DBG_MSG, DBG_OPENDEV);
163 if (iotd && unit_num < NUM_UNITS) {
164 if (dev_base->units[unit_num].enabled && dev_base->units[unit_num].present) {
166 iotd->iotd_Req.io_Unit = (struct Unit*)&dev_base->units[unit_num].unit;
167 iotd->iotd_Req.io_Unit->unit_flags = UNITF_ACTIVE;
168 iotd->iotd_Req.io_Unit->unit_OpenCnt = 1;
172 iotd->iotd_Req.io_Error = io_err;
173 ((struct Library *)dev_base->pi_dev)->lib_OpenCnt++;
176 static uint8_t* __attribute__((used)) close(struct Library *dev asm("a6"), struct IOExtTD *iotd asm("a1"))
178 ((struct Library *)dev_base->pi_dev)->lib_OpenCnt--;
182 static void __attribute__((used)) begin_io(struct Library *dev asm("a6"), struct IORequest *io asm("a1"))
184 if (dev_base == NULL || io == NULL)
187 struct piscsi_unit *u;
188 struct Node* node = (struct Node*)io;
189 u = (struct piscsi_unit *)io->io_Unit;
191 if (node == NULL || u == NULL)
194 debugval(PISCSI_DBG_VAL1, io->io_Command);
195 debugval(PISCSI_DBG_VAL2, io->io_Flags);
196 debugval(PISCSI_DBG_VAL3, (io->io_Flags & IOF_QUICK));
197 debug(PISCSI_DBG_MSG, DBG_BEGINIO);
198 io->io_Error = piscsi_perform_io(u, io);
200 if (!(io->io_Flags & IOF_QUICK)) {
201 ReplyMsg(&io->io_Message);
205 static uint32_t __attribute__((used)) abort_io(struct Library *dev asm("a6"), struct IORequest *io asm("a1"))
207 debug(PISCSI_DBG_MSG, DBG_ABORTIO);
208 if (!io) return IOERR_NOCMD;
209 io->io_Error = IOERR_ABORTED;
211 return IOERR_ABORTED;
214 uint8_t piscsi_rw(struct piscsi_unit *u, struct IORequest *io) {
215 struct IOStdReq *iostd = (struct IOStdReq *)io;
216 struct IOExtTD *iotd = (struct IOExtTD *)io;
220 //uint32_t block, num_blocks;
222 uint32_t block_size = 512;
224 data = iotd->iotd_Req.io_Data;
225 len = iotd->iotd_Req.io_Length;
227 WRITESHORT(PISCSI_CMD_DRVNUM, u->unit_num);
228 READLONG(PISCSI_CMD_BLOCKSIZE, block_size);
231 return IOERR_BADADDRESS;
233 if (len < block_size) {
234 iostd->io_Actual = 0;
235 return IOERR_BADLENGTH;
238 switch (io->io_Command) {
240 case NSCMD_TD_WRITE64:
242 case NSCMD_TD_FORMAT64:
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_WRITE64, u->unit_num);
250 case NSCMD_TD_READ64:
251 WRITELONG(PISCSI_CMD_ADDR1, iostd->io_Offset);
252 WRITELONG(PISCSI_CMD_ADDR2, len);
253 WRITELONG(PISCSI_CMD_ADDR3, (uint32_t)data);
254 WRITELONG(PISCSI_CMD_ADDR4, iostd->io_Actual);
255 WRITESHORT(PISCSI_CMD_READ64, u->unit_num);
259 WRITELONG(PISCSI_CMD_ADDR1, iostd->io_Offset);
260 WRITELONG(PISCSI_CMD_ADDR2, len);
261 WRITELONG(PISCSI_CMD_ADDR3, (uint32_t)data);
262 WRITESHORT(PISCSI_CMD_WRITEBYTES, u->unit_num);
265 WRITELONG(PISCSI_CMD_ADDR1, iostd->io_Offset);
266 WRITELONG(PISCSI_CMD_ADDR2, len);
267 WRITELONG(PISCSI_CMD_ADDR3, (uint32_t)data);
268 WRITESHORT(PISCSI_CMD_READBYTES, u->unit_num);
273 iostd->io_Actual = 0;
275 if (sderr & SCSIERR_TIMEOUT)
276 return TDERR_DiskChanged;
277 if (sderr & SCSIERR_PARAM)
278 return TDERR_SeekError;
279 if (sderr & SCSIERR_ADDRESS)
280 return TDERR_SeekError;
281 if (sderr & (SCSIERR_ERASESEQ | SCSIERR_ERASERES))
282 return TDERR_BadSecPreamble;
283 if (sderr & SCSIERR_CRC)
284 return TDERR_BadSecSum;
285 if (sderr & SCSIERR_ILLEGAL)
286 return TDERR_TooFewSecs;
287 if (sderr & SCSIERR_IDLE)
288 return TDERR_PostReset;
290 return TDERR_SeekError;
292 iostd->io_Actual = iotd->iotd_Req.io_Length;
298 #define PISCSI_ID_STRING "PISTORM Fake SCSI Disk 0.1 1111111111111111"
300 uint8_t piscsi_scsi(struct piscsi_unit *u, struct IORequest *io)
302 struct IOStdReq *iostd = (struct IOStdReq *)io;
303 struct SCSICmd *scsi = iostd->io_Data;
304 //uint8_t* registers = sdu->sdu_Registers;
305 uint8_t *data = (uint8_t *)scsi->scsi_Data;
306 uint32_t i, block = 0, blocks = 0, maxblocks = 0;
309 uint32_t block_size = 512;
311 WRITESHORT(PISCSI_CMD_DRVNUM, u->unit_num);
312 READLONG(PISCSI_CMD_BLOCKSIZE, block_size);
314 debugval(PISCSI_DBG_VAL1, iostd->io_Length);
315 debugval(PISCSI_DBG_VAL2, scsi->scsi_Command[0]);
316 debugval(PISCSI_DBG_VAL3, scsi->scsi_Command[1]);
317 debugval(PISCSI_DBG_VAL4, scsi->scsi_Command[2]);
318 debugval(PISCSI_DBG_VAL5, scsi->scsi_CmdLength);
319 debug(PISCSI_DBG_MSG, DBG_SCSICMD);
321 //maxblocks = u->s * u->c * u->h;
323 if (scsi->scsi_CmdLength < 6) {
324 return IOERR_BADLENGTH;
327 if (scsi->scsi_Command == NULL) {
328 return IOERR_BADADDRESS;
331 scsi->scsi_Actual = 0;
332 //iostd->io_Actual = sizeof(*scsi);
334 switch (scsi->scsi_Command[0]) {
335 case SCSICMD_TEST_UNIT_READY:
339 case SCSICMD_INQUIRY:
340 for (i = 0; i < scsi->scsi_Length; i++) {
344 case 0: // SCSI device type: direct-access device
350 case 2: // VERSION = 0
353 case 3: // NORMACA=0, HISUP = 0, RESPONSE_DATA_FORMAT = 2
354 val = (0 << 5) | (0 << 4) | 2;
356 case 4: // ADDITIONAL_LENGTH = 44 - 4
360 if (i >= 8 && i < 44)
361 val = PISCSI_ID_STRING[i - 8];
368 scsi->scsi_Actual = i;
372 case SCSICMD_WRITE_6:
375 //block = *(uint32_t *)(&scsi->scsi_Command[0]) & 0x001FFFFF;
376 block = scsi->scsi_Command[1] & 0x1f;
377 block = (block << 8) | scsi->scsi_Command[2];
378 block = (block << 8) | scsi->scsi_Command[3];
379 blocks = scsi->scsi_Command[4];
380 debugval(PISCSI_DBG_VAL1, (uint32_t)scsi->scsi_Command);
381 debug(PISCSI_DBG_MSG, DBG_SCSICMD_RW6);
383 case SCSICMD_WRITE_10:
385 case SCSICMD_READ_10:
386 debugval(PISCSI_DBG_VAL1, (uint32_t)scsi->scsi_Command);
387 debug(PISCSI_DBG_MSG, DBG_SCSICMD_RW10);
388 //block = *(uint32_t *)(&scsi->scsi_Command[2]);
389 block = scsi->scsi_Command[2];
390 block = (block << 8) | scsi->scsi_Command[3];
391 block = (block << 8) | scsi->scsi_Command[4];
392 block = (block << 8) | scsi->scsi_Command[5];
394 //blocks = *(uint16_t *)(&scsi->scsi_Command[7]);
395 blocks = scsi->scsi_Command[7];
396 blocks = (blocks << 8) | scsi->scsi_Command[8];
399 WRITESHORT(PISCSI_CMD_DRVNUM, (u->scsi_num));
400 READLONG(PISCSI_CMD_BLOCKS, maxblocks);
401 if (block + blocks > maxblocks || blocks == 0) {
402 err = IOERR_BADADDRESS;
406 err = IOERR_BADADDRESS;
411 WRITELONG(PISCSI_CMD_ADDR1, block);
412 WRITELONG(PISCSI_CMD_ADDR2, (blocks << 9));
413 WRITELONG(PISCSI_CMD_ADDR3, (uint32_t)data);
414 WRITESHORT(PISCSI_CMD_READ, u->unit_num);
417 WRITELONG(PISCSI_CMD_ADDR1, block);
418 WRITELONG(PISCSI_CMD_ADDR2, (blocks << 9));
419 WRITELONG(PISCSI_CMD_ADDR3, (uint32_t)data);
420 WRITESHORT(PISCSI_CMD_WRITE, u->unit_num);
423 scsi->scsi_Actual = scsi->scsi_Length;
427 case SCSICMD_READ_CAPACITY_10:
428 if (scsi->scsi_CmdLength < 10) {
429 err = HFERR_BadStatus;
433 if (scsi->scsi_Length < 8) {
434 err = IOERR_BADLENGTH;
438 WRITESHORT(PISCSI_CMD_DRVNUM, (u->scsi_num));
439 READLONG(PISCSI_CMD_BLOCKS, blocks);
440 ((uint32_t*)data)[0] = blocks - 1;
441 ((uint32_t*)data)[1] = block_size;
443 scsi->scsi_Actual = 8;
447 case SCSICMD_MODE_SENSE_6:
448 data[0] = 3 + 8 + 0x16;
449 data[1] = 0; // MEDIUM TYPE
453 debugval(PISCSI_DBG_VAL1, ((uint32_t)scsi->scsi_Command));
454 debug(PISCSI_DBG_MSG, DBG_SCSI_DEBUG_MODESENSE_6);
456 WRITESHORT(PISCSI_CMD_DRVNUM, (u->scsi_num));
457 READLONG(PISCSI_CMD_BLOCKS, maxblocks);
458 (blocks = (maxblocks - 1) & 0xFFFFFF);
460 *((uint32_t *)&data[4]) = blocks;
461 *((uint32_t *)&data[8]) = block_size;
463 switch (((UWORD)scsi->scsi_Command[2] << 8) | scsi->scsi_Command[3]) {
464 case 0x0300: { // Format Device Mode
465 debug(PISCSI_DBG_MSG, DBG_SCSI_FORMATDEVICE);
466 uint8_t *datext = data + 12;
471 *((uint32_t *)&datext[4]) = 0;
472 *((uint32_t *)&datext[8]) = 0;
473 *((uint16_t *)&datext[10]) = u->s;
474 *((uint16_t *)&datext[12]) = block_size;
477 *((uint32_t *)&datext[16]) = 0;
480 scsi->scsi_Actual = data[0] + 1;
484 case 0x0400: // Rigid Drive Geometry
485 debug(PISCSI_DBG_MSG, DBG_SCSI_RDG);
486 uint8_t *datext = data + 12;
488 *((uint32_t *)&datext[1]) = u->c;
492 *((uint32_t *)&datext[6]) = 0;
493 *((uint32_t *)&datext[10]) = 0;
494 *((uint32_t *)&datext[13]) = u->c;
496 *((uint32_t *)&datext[18]) = 0;
497 *((uint16_t *)&datext[20]) = 5400;
499 scsi->scsi_Actual = data[0] + 1;
504 debugval(PISCSI_DBG_VAL1, (((UWORD)scsi->scsi_Command[2] << 8) | scsi->scsi_Command[3]));
505 debug(PISCSI_DBG_MSG, DBG_SCSI_UNKNOWN_MODESENSE);
506 err = HFERR_BadStatus;
511 case SCSICMD_READ_DEFECT_DATA_10:
513 case SCSICMD_CHANGE_DEFINITION:
517 debugval(PISCSI_DBG_VAL1, scsi->scsi_Command[0]);
518 debug(PISCSI_DBG_MSG, DBG_SCSI_UNKNOWN_COMMAND);
519 err = HFERR_BadStatus;
524 debugval(PISCSI_DBG_VAL1, err);
525 debug(PISCSI_DBG_MSG, DBG_SCSIERR);
526 scsi->scsi_Actual = 0;
532 uint16_t ns_support[] = {
561 #define DUMMYCMD iostd->io_Actual = 0; break;
562 uint8_t piscsi_perform_io(struct piscsi_unit *u, struct IORequest *io) {
563 struct IOStdReq *iostd = (struct IOStdReq *)io;
564 struct IOExtTD *iotd = (struct IOExtTD *)io;
569 //struct DriveGeometry *geom;
573 return IOERR_OPENFAIL;
576 //data = iotd->iotd_Req.io_Data;
577 //len = iotd->iotd_Req.io_Length;
579 if (io->io_Error == IOERR_ABORTED) {
583 debugval(PISCSI_DBG_VAL1, io->io_Command);
584 debugval(PISCSI_DBG_VAL2, io->io_Flags);
585 debugval(PISCSI_DBG_VAL3, iostd->io_Length);
586 debug(PISCSI_DBG_MSG, DBG_IOCMD);
588 switch (io->io_Command) {
589 case NSCMD_DEVICEQUERY: {
590 struct NSDeviceQueryResult *res = (struct NSDeviceQueryResult *)iotd->iotd_Req.io_Data;
591 res->DevQueryFormat = 0;
592 res->SizeAvailable = 16;;
593 res->DeviceType = NSDEVTYPE_TRACKDISK;
594 res->DeviceSubType = 0;
595 res->SupportedCommands = ns_support;
597 iostd->io_Actual = 16;
602 /* Invalidate read buffer */
605 /* Flush write buffer */
610 iostd->io_Actual = u->change_num;
616 case TD_GETDRIVETYPE:
617 iostd->io_Actual = DG_DIRECT_ACCESS;
620 iostd->io_Actual = u->motor;
621 u->motor = iostd->io_Length ? 1 : 0;
626 case NSCMD_TD_FORMAT64:
628 case NSCMD_TD_READ64:
630 case NSCMD_TD_WRITE64:
633 err = piscsi_rw(u, io);
637 err = piscsi_scsi(u, io);
640 //int cmd = io->io_Command;
641 debug(PISCSI_DBG_MSG, DBG_IOCMD_UNHANDLED);
651 static uint32_t device_vectors[] = {
655 0, //extFunc not used here
661 const uint32_t auto_init_tables[4] = {
662 sizeof(struct Library),
663 (uint32_t)device_vectors,
665 (uint32_t)init_device