1 // SPDX-License-Identifier: MIT
5 * Amiga ZZ9000 USB Storage Driver (ZZ9000USBStorage.device)
6 * Copyright (C) 2016-2020, Lukas F. Hartmann <lukas@mntre.com>
7 * Based on code Copyright (C) 2016, Jason S. McMullan <jason.mcmullan@gmail.com>
10 * Licensed under the MIT License:
12 * Permission is hereby granted, free of charge, to any person obtaining
13 * a copy of this software and associated documentation files (the "Software"),
14 * to deal in the Software without restriction, including without limitation
15 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 * and/or sell copies of the Software, and to permit persons to whom the
17 * Software is furnished to do so, subject to the following conditions:
19 * The above copyright notice and this permission notice shall be included
20 * in all copies or substantial portions of the Software.
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 * DEALINGS IN THE SOFTWARE.
31 #include <exec/resident.h>
32 #include <exec/errors.h>
33 #include <exec/memory.h>
34 #include <exec/lists.h>
35 #include <exec/alerts.h>
36 #include <exec/tasks.h>
38 #include <exec/execbase.h>
40 #include <libraries/expansion.h>
42 #include <devices/trackdisk.h>
43 #include <devices/timer.h>
44 #include <devices/scsidisk.h>
46 #include <dos/filehandler.h>
48 #include <proto/exec.h>
49 #include <proto/disk.h>
50 #include <proto/expansion.h>
52 #include <clib/debug_protos.h>
55 #include "../piscsi-enums.h"
57 #define WRITESHORT(cmd, val) *(unsigned short *)((unsigned long)(PISCSI_OFFSET+cmd)) = val;
58 #define WRITELONG(cmd, val) *(unsigned long *)((unsigned long)(PISCSI_OFFSET+cmd)) = val;
59 #define WRITEBYTE(cmd, val) *(unsigned char *)((unsigned long)(PISCSI_OFFSET+cmd)) = val;
61 #define READSHORT(cmd, var) var = *(volatile unsigned short *)(PISCSI_OFFSET + cmd);
62 #define READLONG(cmd, var) var = *(volatile unsigned long *)(PISCSI_OFFSET + cmd);
66 struct Device* pi_dev;
84 struct ExecBase* SysBase = NULL;
87 const char DevName[] = "scsi.device";
89 const char DevName[] = "2nd.scsi.device";
91 const char DevName[] = "pi-scsi.device";
93 const char DevIdString[] = "Pi-SCSI 0.1";
95 const UWORD DevVersion = 43;
96 const UWORD DevRevision = 10;
100 struct piscsi_base *dev_base = NULL;
102 struct WBStartup *_WBenchMsg = NULL;
108 #define debugval(...)
109 //#define debug(c, v) WRITESHORT(c, v)
110 //#define debugval(c, v) WRITELONG(c, v)
112 //#define bug(x,args...) KPrintF(x ,##args);
113 //#define debug(x,args...) bug("%s:%ld " x "\n", __func__, (unsigned long)__LINE__ ,##args)
115 uint8_t piscsi_perform_io(struct piscsi_unit *u, struct IORequest *io);
116 uint8_t piscsi_rw(struct piscsi_unit *u, struct IORequest *io, uint32_t offset, uint8_t write);
117 uint8_t piscsi_scsi(struct piscsi_unit *u, struct IORequest *io);
119 extern void* DOSBase[2];
121 uint32_t __UserDevInit(struct Device* dev) {
122 //uint8_t* registers = NULL;
123 SysBase = *(struct ExecBase **)4L;
125 KPrintF("Initializing devices.\n");
126 debug(PISCSI_DBG_MSG, DBG_INIT);
128 dev_base = AllocMem(sizeof(struct piscsi_base), MEMF_PUBLIC | MEMF_CLEAR);
129 dev_base->pi_dev = dev;
131 for (int i = 0; i < NUM_UNITS; i++) {
133 WRITESHORT(PISCSI_CMD_DRVNUM, i);
134 dev_base->units[i].regs_ptr = PISCSI_OFFSET;
135 READSHORT(PISCSI_CMD_DRVTYPE, r);
136 dev_base->units[i].enabled = r;
137 dev_base->units[i].present = r;
138 dev_base->units[i].valid = r;
139 dev_base->units[i].unit_num = i;
140 if (dev_base->units[i].present) {
141 READLONG(PISCSI_CMD_CYLS, dev_base->units[i].c);
142 READSHORT(PISCSI_CMD_HEADS, dev_base->units[i].h);
143 READSHORT(PISCSI_CMD_SECS, dev_base->units[i].s);
144 KPrintF("C/H/S: %ld / %ld / %ld\n", dev_base->units[i].c, dev_base->units[i].h, dev_base->units[i].s);
146 debugval(PISCSI_DBG_VAL1, dev_base->units[i].c);
147 debugval(PISCSI_DBG_VAL2, dev_base->units[i].h);
148 debugval(PISCSI_DBG_VAL3, dev_base->units[i].s);
149 debug(PISCSI_DBG_MSG, DBG_CHS);
151 dev_base->units[i].change_num++;
152 // Send any reset signal to the "SCSI" device here.
158 uint32_t __UserDevCleanup(void) {
159 KPrintF("Cleaning up.\n");
160 debug(PISCSI_DBG_MSG, DBG_CLEANUP);
161 FreeMem(dev_base, sizeof(struct piscsi_base));
165 uint32_t __UserDevOpen(struct IOExtTD *iotd, uint32_t num, uint32_t flags) {
166 struct Node* node = (struct Node*)iotd;
167 int io_err = IOERR_OPENFAIL;
169 //WRITESHORT(PISCSI_CMD_DEBUGME, 1);
172 WRITELONG(PISCSI_CMD_DRVNUM, num);
173 READLONG(PISCSI_CMD_DRVNUM, unit_num);
175 debugval(PISCSI_DBG_VAL1, unit_num);
176 debugval(PISCSI_DBG_VAL2, flags);
177 debugval(PISCSI_DBG_VAL3, num);
178 debug(PISCSI_DBG_MSG, DBG_OPENDEV);
179 KPrintF("Opening device %ld Flags: %ld (%lx)\n", unit_num, flags, flags);
181 if (iotd && unit_num < NUM_UNITS) {
182 if (dev_base->units[unit_num].enabled && dev_base->units[unit_num].present) {
184 iotd->iotd_Req.io_Unit = (struct Unit*)&dev_base->units[unit_num].unit;
185 iotd->iotd_Req.io_Unit->unit_flags = UNITF_ACTIVE;
186 iotd->iotd_Req.io_Unit->unit_OpenCnt = 1;
191 iotd->iotd_Req.io_Error = io_err;
196 uint32_t __UserDevClose(struct IOExtTD *iotd) {
200 void exit(int status) { }
202 ADDTABL_1(__BeginIO,a1);
203 void __BeginIO(struct IORequest *io) {
204 if (dev_base == NULL || io == NULL)
207 struct piscsi_unit *u;
208 struct Node* node = (struct Node*)io;
209 u = (struct piscsi_unit *)io->io_Unit;
211 if (node == NULL || u == NULL)
214 debugval(PISCSI_DBG_VAL1, io->io_Command);
215 debugval(PISCSI_DBG_VAL2, io->io_Flags);
216 debugval(PISCSI_DBG_VAL3, (io->io_Flags & IOF_QUICK));
217 debug(PISCSI_DBG_MSG, DBG_BEGINIO);
218 KPrintF("io_Command = %ld, io_Flags = 0x%lx quick = %lx\n", io->io_Command, io->io_Flags, (io->io_Flags & IOF_QUICK));
219 io->io_Error = piscsi_perform_io(u, io);
221 if (!(io->io_Flags & IOF_QUICK)) {
222 ReplyMsg(&io->io_Message);
226 ADDTABL_1(__AbortIO,a1);
227 void __AbortIO(struct IORequest* io) {
228 debug(PISCSI_DBG_MSG, DBG_ABORTIO);
229 KPrintF("AbortIO!\n");
231 io->io_Error = IOERR_ABORTED;
234 uint8_t piscsi_rw(struct piscsi_unit *u, struct IORequest *io, uint32_t offset, uint8_t write) {
235 struct IOStdReq *iostd = (struct IOStdReq *)io;
236 struct IOExtTD *iotd = (struct IOExtTD *)io;
239 uint32_t len, num_blocks;
240 uint32_t block, max_addr;
243 data = iotd->iotd_Req.io_Data;
244 len = iotd->iotd_Req.io_Length;
245 //uint32_t offset2 = iostd->io_Offset;
247 max_addr = 0xffffffff;
249 // well... if we had 64 bits this would make sense
250 if ((offset > max_addr) || (offset+len > max_addr))
251 return IOERR_BADADDRESS;
253 return IOERR_BADADDRESS;
254 if (len < PISCSI_BLOCK_SIZE) {
255 iostd->io_Actual = 0;
256 return IOERR_BADLENGTH;
259 //block = offset;// >> SD_SECTOR_SHIFT;
260 //num_blocks = len;// >> SD_SECTOR_SHIFT;
264 //uint32_t retries = 10;
265 //KPrintF("Write %lx -> %lx %lx\n", (uint32_t)data, offset, len);
266 WRITELONG(PISCSI_CMD_ADDR1, (offset >> 9));
267 WRITELONG(PISCSI_CMD_ADDR2, len);
268 WRITELONG(PISCSI_CMD_ADDR3, (uint32_t)data);
269 WRITESHORT(PISCSI_CMD_WRITE, u->unit_num);
271 //KPrintF("read %lx %lx -> %lx\n", offset, len, (uint32_t)data);
272 WRITELONG(PISCSI_CMD_ADDR1, (offset >> 9));
273 WRITELONG(PISCSI_CMD_ADDR2, len);
274 WRITELONG(PISCSI_CMD_ADDR3, (uint32_t)data);
275 WRITESHORT(PISCSI_CMD_READ, u->unit_num);
279 iostd->io_Actual = 0;
281 if (sderr & SCSIERR_TIMEOUT)
282 return TDERR_DiskChanged;
283 if (sderr & SCSIERR_PARAM)
284 return TDERR_SeekError;
285 if (sderr & SCSIERR_ADDRESS)
286 return TDERR_SeekError;
287 if (sderr & (SCSIERR_ERASESEQ | SCSIERR_ERASERES))
288 return TDERR_BadSecPreamble;
289 if (sderr & SCSIERR_CRC)
290 return TDERR_BadSecSum;
291 if (sderr & SCSIERR_ILLEGAL)
292 return TDERR_TooFewSecs;
293 if (sderr & SCSIERR_IDLE)
294 return TDERR_PostReset;
296 return TDERR_SeekError;
298 iostd->io_Actual = len;
304 #define PISCSI_ID_STRING "PISTORM Fake SCSI Disk 0.1 1111111111111111"
306 uint8_t piscsi_scsi(struct piscsi_unit *u, struct IORequest *io)
308 struct IOStdReq *iostd = (struct IOStdReq *)io;
309 struct SCSICmd *scsi = iostd->io_Data;
310 //uint8_t* registers = sdu->sdu_Registers;
311 uint8_t *data = (uint8_t *)scsi->scsi_Data;
312 uint32_t i, block, blocks, maxblocks;
315 KPrintF("SCSI len=%ld, cmd = %02lx %02lx %02lx ... (%ld)\n",
316 iostd->io_Length, scsi->scsi_Command[0],
317 scsi->scsi_Command[1], scsi->scsi_Command[2],
318 scsi->scsi_CmdLength);
320 debugval(PISCSI_DBG_VAL1, iostd->io_Length);
321 debugval(PISCSI_DBG_VAL2, scsi->scsi_Command[0]);
322 debugval(PISCSI_DBG_VAL3, scsi->scsi_Command[1]);
323 debugval(PISCSI_DBG_VAL4, scsi->scsi_Command[2]);
324 debugval(PISCSI_DBG_VAL5, scsi->scsi_CmdLength);
325 debug(PISCSI_DBG_MSG, DBG_SCSICMD);
327 //maxblocks = u->s * u->c * u->h;
329 if (scsi->scsi_CmdLength < 6) {
330 //KPrintF("SCSICMD BADLENGTH2");
331 return IOERR_BADLENGTH;
334 if (scsi->scsi_Command == NULL) {
335 //KPrintF("SCSICMD IOERR_BADADDRESS1");
336 return IOERR_BADADDRESS;
339 scsi->scsi_Actual = 0;
340 //iostd->io_Actual = sizeof(*scsi);
342 switch (scsi->scsi_Command[0]) {
343 case 0x00: // TEST_UNIT_READY
347 case 0x12: // INQUIRY
348 for (i = 0; i < scsi->scsi_Length; i++) {
352 case 0: // SCSI device type: direct-access device
358 case 2: // VERSION = 0
361 case 3: // NORMACA=0, HISUP = 0, RESPONSE_DATA_FORMAT = 2
362 val = (0 << 5) | (0 << 4) | 2;
364 case 4: // ADDITIONAL_LENGTH = 44 - 4
368 if (i >= 8 && i < 44)
369 val = PISCSI_ID_STRING[i - 8];
376 scsi->scsi_Actual = i;
380 case 0x08: // READ (6)
381 case 0x0a: // WRITE (6)
382 block = scsi->scsi_Command[1] & 0x1f;
383 block = (block << 8) | scsi->scsi_Command[2];
384 block = (block << 8) | scsi->scsi_Command[3];
385 blocks = scsi->scsi_Command[4];
387 READLONG(PISCSI_CMD_BLOCKS, maxblocks);
388 if (block + blocks > maxblocks) {
389 err = IOERR_BADADDRESS;
392 /*if (scsi->scsi_Length < (blocks << SD_SECTOR_SHIFT)) {
393 err = IOERR_BADLENGTH;
397 err = IOERR_BADADDRESS;
401 if (scsi->scsi_Command[0] == 0x08) {
402 //KPrintF("scsi_read %lx %lx\n",block,blocks);
403 //KPrintF("SCSI read %lx %lx -> %lx\n", block, blocks, (uint32_t)data);
404 WRITELONG(PISCSI_CMD_ADDR2, block);
405 WRITELONG(PISCSI_CMD_ADDR2, (blocks << 9));
406 WRITELONG(PISCSI_CMD_ADDR3, (uint32_t)data);
407 WRITESHORT(PISCSI_CMD_READ, u->unit_num);
410 //KPrintF("scsi_write %lx %lx\n",block,blocks);
411 //KPrintF("SCSI write %lx -> %lx %lx\n", (uint32_t)data, block, blocks);
412 WRITELONG(PISCSI_CMD_ADDR2, block);
413 WRITELONG(PISCSI_CMD_ADDR2, (blocks << 9));
414 WRITELONG(PISCSI_CMD_ADDR3, (uint32_t)data);
415 WRITESHORT(PISCSI_CMD_WRITE, u->unit_num);
418 scsi->scsi_Actual = scsi->scsi_Length;
422 case 0x25: // READ CAPACITY (10)
423 //KPrintF("SCSI command: Read Capacity.\n");
424 if (scsi->scsi_CmdLength < 10) {
425 err = HFERR_BadStatus;
429 block = *((uint32_t*)&scsi->scsi_Command[2]);
431 /*if ((scsi->scsi_Command[8] & 1) || block != 0) {
433 KPrintF("PMI not supported.\n");
434 err = HFERR_BadStatus;
438 if (scsi->scsi_Length < 8) {
439 err = IOERR_BADLENGTH;
443 READLONG(PISCSI_CMD_BLOCKS, blocks);
444 ((uint32_t*)data)[0] = blocks - 1;
445 ((uint32_t*)data)[1] = PISCSI_BLOCK_SIZE;
447 scsi->scsi_Actual = 8;
451 case 0x1a: // MODE SENSE (6)
452 //KPrintF("SCSI command: Mode Sense.\n");
453 data[0] = 3 + 8 + 0x16;
454 data[1] = 0; // MEDIUM TYPE
458 READLONG(PISCSI_CMD_BLOCKS, maxblocks);
459 (blocks = (maxblocks - 1) & 0xFFFFFF);
461 *((uint32_t *)&data[4]) = blocks;
462 *((uint32_t *)&data[8]) = PISCSI_BLOCK_SIZE;
464 switch (((UWORD)scsi->scsi_Command[2] << 8) | scsi->scsi_Command[3]) {
465 case 0x0300: { // Format Device Mode
466 KPrintF("Grabbing SCSI format device mode data.\n");
467 debug(PISCSI_DBG_MSG, DBG_SCSI_FORMATDEVICE);
468 uint8_t *datext = data + 12;
473 *((uint32_t *)&datext[4]) = 0;
474 *((uint32_t *)&datext[8]) = 0;
475 *((uint16_t *)&datext[10]) = u->s;
476 *((uint16_t *)&datext[12]) = PISCSI_BLOCK_SIZE;
479 *((uint32_t *)&datext[16]) = 0;
482 scsi->scsi_Actual = data[0] + 1;
486 case 0x0400: // Rigid Drive Geometry
487 KPrintF("Grabbing SCSI rigid drive geometry.\n");
488 debug(PISCSI_DBG_MSG, DBG_SCSI_RDG);
489 uint8_t *datext = data + 12;
491 *((uint32_t *)&datext[1]) = u->c;
495 *((uint32_t *)&datext[6]) = 0;
496 *((uint32_t *)&datext[10]) = 0;
497 *((uint32_t *)&datext[13]) = u->c;
499 *((uint32_t *)&datext[18]) = 0;
500 *((uint16_t *)&datext[20]) = 5400;
502 scsi->scsi_Actual = data[0] + 1;
507 KPrintF("[WARN] Unhandled mode sense thing: %lx\n", ((UWORD)scsi->scsi_Command[2] << 8) | scsi->scsi_Command[3]);
508 debugval(PISCSI_DBG_VAL1, (((UWORD)scsi->scsi_Command[2] << 8) | scsi->scsi_Command[3]));
509 debug(PISCSI_DBG_MSG, DBG_SCSI_UNKNOWN_MODESENSE);
510 err = HFERR_BadStatus;
515 case 0x37: // READ DEFECT DATA (10)
520 debugval(PISCSI_DBG_VAL1, scsi->scsi_Command[0]);
521 debug(PISCSI_DBG_MSG, DBG_SCSI_UNKNOWN_COMMAND);
522 KPrintF("Unknown/unhandled SCSI command %lx.\n", scsi->scsi_Command[0]);
523 err = HFERR_BadStatus;
528 debugval(PISCSI_DBG_VAL1, err);
529 debug(PISCSI_DBG_MSG, DBG_SCSIERR);
530 KPrintF("Some SCSI error occured: %ld\n", err);
531 scsi->scsi_Actual = 0;
537 #define DUMMYCMD iostd->io_Actual = 0; break;
538 uint8_t piscsi_perform_io(struct piscsi_unit *u, struct IORequest *io) {
539 struct IOStdReq *iostd = (struct IOStdReq *)io;
540 struct IOExtTD *iotd = (struct IOExtTD *)io;
545 //struct DriveGeometry *geom;
549 return IOERR_OPENFAIL;
552 data = iotd->iotd_Req.io_Data;
553 len = iotd->iotd_Req.io_Length;
555 if (io->io_Error == IOERR_ABORTED) {
559 debugval(PISCSI_DBG_VAL1, io->io_Command);
560 debugval(PISCSI_DBG_VAL2, io->io_Flags);
561 debugval(PISCSI_DBG_VAL3, iostd->io_Length);
562 debug(PISCSI_DBG_MSG, DBG_IOCMD);
563 //KPrintF("cmd: %s\n",cmd_name(io->io_Command));
564 //KPrintF("IO %lx Start, io_Flags = %ld, io_Command = %ld\n", io, io->io_Flags, io->io_Command);
566 switch (io->io_Command) {
568 /* Invalidate read buffer */
571 /* Flush write buffer */
576 iostd->io_Actual = u->change_num;
582 case TD_GETDRIVETYPE:
583 iostd->io_Actual = DG_DIRECT_ACCESS;
586 iostd->io_Actual = u->motor;
587 u->motor = iostd->io_Length ? 1 : 0;
591 offset = iotd->iotd_Req.io_Offset;
593 err = piscsi_rw(u, io, offset, 1);
596 offset = iotd->iotd_Req.io_Offset;
598 err = piscsi_rw(u, io, offset, 1);
601 offset = iotd->iotd_Req.io_Offset;
603 err = piscsi_rw(u, io, offset, 0);
607 err = piscsi_scsi(u, io);
610 int cmd = io->io_Command;
611 debug(PISCSI_DBG_MSG, DBG_IOCMD_UNHANDLED);