3 * Amiga ZZ9000 USB Storage Driver (ZZ9000USBStorage.device)
4 * Copyright (C) 2016-2020, Lukas F. Hartmann <lukas@mntre.com>
5 * Based on code Copyright (C) 2016, Jason S. McMullan <jason.mcmullan@gmail.com>
8 * Licensed under the MIT License:
10 * Permission is hereby granted, free of charge, to any person obtaining
11 * a copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
17 * The above copyright notice and this permission notice shall be included
18 * in all copies or substantial portions of the Software.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
29 #include <exec/resident.h>
30 #include <exec/errors.h>
31 #include <exec/memory.h>
32 #include <exec/lists.h>
33 #include <exec/alerts.h>
34 #include <exec/tasks.h>
36 #include <exec/execbase.h>
38 #include <libraries/expansion.h>
40 #include <devices/trackdisk.h>
41 #include <devices/timer.h>
42 #include <devices/scsidisk.h>
44 #include <dos/filehandler.h>
46 #include <proto/exec.h>
47 #include <proto/disk.h>
48 #include <proto/expansion.h>
50 #include <clib/debug_protos.h>
53 #include "../piscsi-enums.h"
55 #define WRITESHORT(cmd, val) *(unsigned short *)((unsigned long)(PISCSI_OFFSET+cmd)) = val;
56 #define WRITELONG(cmd, val) *(unsigned long *)((unsigned long)(PISCSI_OFFSET+cmd)) = val;
57 #define WRITEBYTE(cmd, val) *(unsigned char *)((unsigned long)(PISCSI_OFFSET+cmd)) = val;
59 #define READSHORT(cmd, var) var = *(volatile unsigned short *)(PISCSI_OFFSET + cmd);
60 #define READLONG(cmd, var) var = *(volatile unsigned long *)(PISCSI_OFFSET + cmd);
64 struct Device* pi_dev;
82 struct ExecBase* SysBase = NULL;
85 const char DevName[] = "scsi.device";
87 const char DevName[] = "2nd.scsi.device";
89 const char DevName[] = "pi-scsi.device";
91 const char DevIdString[] = "Pi-SCSI 0.1";
93 const UWORD DevVersion = 43;
94 const UWORD DevRevision = 10;
98 struct piscsi_base *dev_base = NULL;
100 struct WBStartup *_WBenchMsg = NULL;
106 #define debugval(...)
107 //#define debug(c, v) WRITESHORT(c, v)
108 //#define debugval(c, v) WRITELONG(c, v)
110 //#define bug(x,args...) KPrintF(x ,##args);
111 //#define debug(x,args...) bug("%s:%ld " x "\n", __func__, (unsigned long)__LINE__ ,##args)
113 uint8_t piscsi_perform_io(struct piscsi_unit *u, struct IORequest *io);
114 uint8_t piscsi_rw(struct piscsi_unit *u, struct IORequest *io, uint32_t offset, uint8_t write);
115 uint8_t piscsi_scsi(struct piscsi_unit *u, struct IORequest *io);
117 extern void* DOSBase[2];
119 uint32_t __UserDevInit(struct Device* dev) {
120 //uint8_t* registers = NULL;
121 SysBase = *(struct ExecBase **)4L;
123 KPrintF("Initializing devices.\n");
124 debug(PISCSI_DBG_MSG, DBG_INIT);
126 dev_base = AllocMem(sizeof(struct piscsi_base), MEMF_PUBLIC | MEMF_CLEAR);
127 dev_base->pi_dev = dev;
129 for (int i = 0; i < NUM_UNITS; i++) {
131 WRITESHORT(PISCSI_CMD_DRVNUM, i);
132 dev_base->units[i].regs_ptr = PISCSI_OFFSET;
133 READSHORT(PISCSI_CMD_DRVTYPE, r);
134 dev_base->units[i].enabled = r;
135 dev_base->units[i].present = r;
136 dev_base->units[i].valid = r;
137 dev_base->units[i].unit_num = i;
138 if (dev_base->units[i].present) {
139 READLONG(PISCSI_CMD_CYLS, dev_base->units[i].c);
140 READSHORT(PISCSI_CMD_HEADS, dev_base->units[i].h);
141 READSHORT(PISCSI_CMD_SECS, dev_base->units[i].s);
142 KPrintF("C/H/S: %ld / %ld / %ld\n", dev_base->units[i].c, dev_base->units[i].h, dev_base->units[i].s);
144 debugval(PISCSI_DBG_VAL1, dev_base->units[i].c);
145 debugval(PISCSI_DBG_VAL2, dev_base->units[i].h);
146 debugval(PISCSI_DBG_VAL3, dev_base->units[i].s);
147 debug(PISCSI_DBG_MSG, DBG_CHS);
149 dev_base->units[i].change_num++;
150 // Send any reset signal to the "SCSI" device here.
156 uint32_t __UserDevCleanup(void) {
157 KPrintF("Cleaning up.\n");
158 debug(PISCSI_DBG_MSG, DBG_CLEANUP);
159 FreeMem(dev_base, sizeof(struct piscsi_base));
163 uint32_t __UserDevOpen(struct IOExtTD *iotd, uint32_t num, uint32_t flags) {
164 struct Node* node = (struct Node*)iotd;
165 int io_err = IOERR_OPENFAIL;
167 //WRITESHORT(PISCSI_CMD_DEBUGME, 1);
170 WRITELONG(PISCSI_CMD_DRVNUM, num);
171 READLONG(PISCSI_CMD_DRVNUM, unit_num);
173 debugval(PISCSI_DBG_VAL1, unit_num);
174 debugval(PISCSI_DBG_VAL2, flags);
175 debugval(PISCSI_DBG_VAL3, num);
176 debug(PISCSI_DBG_MSG, DBG_OPENDEV);
177 KPrintF("Opening device %ld Flags: %ld (%lx)\n", unit_num, flags, flags);
179 if (iotd && unit_num < NUM_UNITS) {
180 if (dev_base->units[unit_num].enabled && dev_base->units[unit_num].present) {
182 iotd->iotd_Req.io_Unit = (struct Unit*)&dev_base->units[unit_num].unit;
183 iotd->iotd_Req.io_Unit->unit_flags = UNITF_ACTIVE;
184 iotd->iotd_Req.io_Unit->unit_OpenCnt = 1;
189 iotd->iotd_Req.io_Error = io_err;
194 uint32_t __UserDevClose(struct IOExtTD *iotd) {
198 void exit(int status) { }
200 ADDTABL_1(__BeginIO,a1);
201 void __BeginIO(struct IORequest *io) {
202 if (dev_base == NULL || io == NULL)
205 struct piscsi_unit *u;
206 struct Node* node = (struct Node*)io;
207 u = (struct piscsi_unit *)io->io_Unit;
209 if (node == NULL || u == NULL)
212 debugval(PISCSI_DBG_VAL1, io->io_Command);
213 debugval(PISCSI_DBG_VAL2, io->io_Flags);
214 debugval(PISCSI_DBG_VAL3, (io->io_Flags & IOF_QUICK));
215 debug(PISCSI_DBG_MSG, DBG_BEGINIO);
216 KPrintF("io_Command = %ld, io_Flags = 0x%lx quick = %lx\n", io->io_Command, io->io_Flags, (io->io_Flags & IOF_QUICK));
217 io->io_Error = piscsi_perform_io(u, io);
219 if (!(io->io_Flags & IOF_QUICK)) {
220 ReplyMsg(&io->io_Message);
224 ADDTABL_1(__AbortIO,a1);
225 void __AbortIO(struct IORequest* io) {
226 debug(PISCSI_DBG_MSG, DBG_ABORTIO);
227 KPrintF("AbortIO!\n");
229 io->io_Error = IOERR_ABORTED;
232 uint8_t piscsi_rw(struct piscsi_unit *u, struct IORequest *io, uint32_t offset, uint8_t write) {
233 struct IOStdReq *iostd = (struct IOStdReq *)io;
234 struct IOExtTD *iotd = (struct IOExtTD *)io;
237 uint32_t len, num_blocks;
238 uint32_t block, max_addr;
241 data = iotd->iotd_Req.io_Data;
242 len = iotd->iotd_Req.io_Length;
243 //uint32_t offset2 = iostd->io_Offset;
245 max_addr = 0xffffffff;
247 // well... if we had 64 bits this would make sense
248 if ((offset > max_addr) || (offset+len > max_addr))
249 return IOERR_BADADDRESS;
251 return IOERR_BADADDRESS;
252 if (len < PISCSI_BLOCK_SIZE) {
253 iostd->io_Actual = 0;
254 return IOERR_BADLENGTH;
257 //block = offset;// >> SD_SECTOR_SHIFT;
258 //num_blocks = len;// >> SD_SECTOR_SHIFT;
262 //uint32_t retries = 10;
263 //KPrintF("Write %lx -> %lx %lx\n", (uint32_t)data, offset, len);
264 WRITELONG(PISCSI_CMD_ADDR1, (offset >> 9));
265 WRITELONG(PISCSI_CMD_ADDR2, len);
266 WRITELONG(PISCSI_CMD_ADDR3, (uint32_t)data);
267 WRITESHORT(PISCSI_CMD_WRITE, u->unit_num);
269 //KPrintF("read %lx %lx -> %lx\n", offset, len, (uint32_t)data);
270 WRITELONG(PISCSI_CMD_ADDR1, (offset >> 9));
271 WRITELONG(PISCSI_CMD_ADDR2, len);
272 WRITELONG(PISCSI_CMD_ADDR3, (uint32_t)data);
273 WRITESHORT(PISCSI_CMD_READ, u->unit_num);
277 iostd->io_Actual = 0;
279 if (sderr & SCSIERR_TIMEOUT)
280 return TDERR_DiskChanged;
281 if (sderr & SCSIERR_PARAM)
282 return TDERR_SeekError;
283 if (sderr & SCSIERR_ADDRESS)
284 return TDERR_SeekError;
285 if (sderr & (SCSIERR_ERASESEQ | SCSIERR_ERASERES))
286 return TDERR_BadSecPreamble;
287 if (sderr & SCSIERR_CRC)
288 return TDERR_BadSecSum;
289 if (sderr & SCSIERR_ILLEGAL)
290 return TDERR_TooFewSecs;
291 if (sderr & SCSIERR_IDLE)
292 return TDERR_PostReset;
294 return TDERR_SeekError;
296 iostd->io_Actual = len;
302 #define PISCSI_ID_STRING "PISTORM Fake SCSI Disk 0.1 1111111111111111"
304 uint8_t piscsi_scsi(struct piscsi_unit *u, struct IORequest *io)
306 struct IOStdReq *iostd = (struct IOStdReq *)io;
307 struct SCSICmd *scsi = iostd->io_Data;
308 //uint8_t* registers = sdu->sdu_Registers;
309 uint8_t *data = (uint8_t *)scsi->scsi_Data;
310 uint32_t i, block, blocks, maxblocks;
313 KPrintF("SCSI len=%ld, cmd = %02lx %02lx %02lx ... (%ld)\n",
314 iostd->io_Length, scsi->scsi_Command[0],
315 scsi->scsi_Command[1], scsi->scsi_Command[2],
316 scsi->scsi_CmdLength);
318 debugval(PISCSI_DBG_VAL1, iostd->io_Length);
319 debugval(PISCSI_DBG_VAL2, scsi->scsi_Command[0]);
320 debugval(PISCSI_DBG_VAL3, scsi->scsi_Command[1]);
321 debugval(PISCSI_DBG_VAL4, scsi->scsi_Command[2]);
322 debugval(PISCSI_DBG_VAL5, scsi->scsi_CmdLength);
323 debug(PISCSI_DBG_MSG, DBG_SCSICMD);
325 //maxblocks = u->s * u->c * u->h;
327 if (scsi->scsi_CmdLength < 6) {
328 //KPrintF("SCSICMD BADLENGTH2");
329 return IOERR_BADLENGTH;
332 if (scsi->scsi_Command == NULL) {
333 //KPrintF("SCSICMD IOERR_BADADDRESS1");
334 return IOERR_BADADDRESS;
337 scsi->scsi_Actual = 0;
338 //iostd->io_Actual = sizeof(*scsi);
340 switch (scsi->scsi_Command[0]) {
341 case 0x00: // TEST_UNIT_READY
345 case 0x12: // INQUIRY
346 for (i = 0; i < scsi->scsi_Length; i++) {
350 case 0: // SCSI device type: direct-access device
356 case 2: // VERSION = 0
359 case 3: // NORMACA=0, HISUP = 0, RESPONSE_DATA_FORMAT = 2
360 val = (0 << 5) | (0 << 4) | 2;
362 case 4: // ADDITIONAL_LENGTH = 44 - 4
366 if (i >= 8 && i < 44)
367 val = PISCSI_ID_STRING[i - 8];
374 scsi->scsi_Actual = i;
378 case 0x08: // READ (6)
379 case 0x0a: // WRITE (6)
380 block = scsi->scsi_Command[1] & 0x1f;
381 block = (block << 8) | scsi->scsi_Command[2];
382 block = (block << 8) | scsi->scsi_Command[3];
383 blocks = scsi->scsi_Command[4];
385 READLONG(PISCSI_CMD_BLOCKS, maxblocks);
386 if (block + blocks > maxblocks) {
387 err = IOERR_BADADDRESS;
390 /*if (scsi->scsi_Length < (blocks << SD_SECTOR_SHIFT)) {
391 err = IOERR_BADLENGTH;
395 err = IOERR_BADADDRESS;
399 if (scsi->scsi_Command[0] == 0x08) {
400 //KPrintF("scsi_read %lx %lx\n",block,blocks);
401 //KPrintF("SCSI read %lx %lx -> %lx\n", block, blocks, (uint32_t)data);
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 //KPrintF("scsi_write %lx %lx\n",block,blocks);
409 //KPrintF("SCSI write %lx -> %lx %lx\n", (uint32_t)data, block, blocks);
410 WRITELONG(PISCSI_CMD_ADDR2, block);
411 WRITELONG(PISCSI_CMD_ADDR2, (blocks << 9));
412 WRITELONG(PISCSI_CMD_ADDR3, (uint32_t)data);
413 WRITESHORT(PISCSI_CMD_WRITE, u->unit_num);
416 scsi->scsi_Actual = scsi->scsi_Length;
420 case 0x25: // READ CAPACITY (10)
421 //KPrintF("SCSI command: Read Capacity.\n");
422 if (scsi->scsi_CmdLength < 10) {
423 err = HFERR_BadStatus;
427 block = *((uint32_t*)&scsi->scsi_Command[2]);
429 /*if ((scsi->scsi_Command[8] & 1) || block != 0) {
431 KPrintF("PMI not supported.\n");
432 err = HFERR_BadStatus;
436 if (scsi->scsi_Length < 8) {
437 err = IOERR_BADLENGTH;
441 READLONG(PISCSI_CMD_BLOCKS, blocks);
442 ((uint32_t*)data)[0] = blocks - 1;
443 ((uint32_t*)data)[1] = PISCSI_BLOCK_SIZE;
445 scsi->scsi_Actual = 8;
449 case 0x1a: // MODE SENSE (6)
450 //KPrintF("SCSI command: Mode Sense.\n");
451 data[0] = 3 + 8 + 0x16;
452 data[1] = 0; // MEDIUM TYPE
456 READLONG(PISCSI_CMD_BLOCKS, maxblocks);
457 (blocks = (maxblocks - 1) & 0xFFFFFF);
459 *((uint32_t *)&data[4]) = blocks;
460 *((uint32_t *)&data[8]) = PISCSI_BLOCK_SIZE;
462 switch (((UWORD)scsi->scsi_Command[2] << 8) | scsi->scsi_Command[3]) {
463 case 0x0300: { // Format Device Mode
464 KPrintF("Grabbing SCSI format device mode data.\n");
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]) = PISCSI_BLOCK_SIZE;
477 *((uint32_t *)&datext[16]) = 0;
480 scsi->scsi_Actual = data[0] + 1;
484 case 0x0400: // Rigid Drive Geometry
485 KPrintF("Grabbing SCSI rigid drive geometry.\n");
486 debug(PISCSI_DBG_MSG, DBG_SCSI_RDG);
487 uint8_t *datext = data + 12;
489 *((uint32_t *)&datext[1]) = u->c;
493 *((uint32_t *)&datext[6]) = 0;
494 *((uint32_t *)&datext[10]) = 0;
495 *((uint32_t *)&datext[13]) = u->c;
497 *((uint32_t *)&datext[18]) = 0;
498 *((uint16_t *)&datext[20]) = 5400;
500 scsi->scsi_Actual = data[0] + 1;
505 KPrintF("[WARN] Unhandled mode sense thing: %lx\n", ((UWORD)scsi->scsi_Command[2] << 8) | scsi->scsi_Command[3]);
506 debugval(PISCSI_DBG_VAL1, (((UWORD)scsi->scsi_Command[2] << 8) | scsi->scsi_Command[3]));
507 debug(PISCSI_DBG_MSG, DBG_SCSI_UNKNOWN_MODESENSE);
508 err = HFERR_BadStatus;
513 case 0x37: // READ DEFECT DATA (10)
518 debugval(PISCSI_DBG_VAL1, scsi->scsi_Command[0]);
519 debug(PISCSI_DBG_MSG, DBG_SCSI_UNKNOWN_COMMAND);
520 KPrintF("Unknown/unhandled SCSI command %lx.\n", scsi->scsi_Command[0]);
521 err = HFERR_BadStatus;
526 debugval(PISCSI_DBG_VAL1, err);
527 debug(PISCSI_DBG_MSG, DBG_SCSIERR);
528 KPrintF("Some SCSI error occured: %ld\n", err);
529 scsi->scsi_Actual = 0;
535 #define DUMMYCMD iostd->io_Actual = 0; break;
536 uint8_t piscsi_perform_io(struct piscsi_unit *u, struct IORequest *io) {
537 struct IOStdReq *iostd = (struct IOStdReq *)io;
538 struct IOExtTD *iotd = (struct IOExtTD *)io;
543 //struct DriveGeometry *geom;
547 return IOERR_OPENFAIL;
550 data = iotd->iotd_Req.io_Data;
551 len = iotd->iotd_Req.io_Length;
553 if (io->io_Error == IOERR_ABORTED) {
557 debugval(PISCSI_DBG_VAL1, io->io_Command);
558 debugval(PISCSI_DBG_VAL2, io->io_Flags);
559 debugval(PISCSI_DBG_VAL3, iostd->io_Length);
560 debug(PISCSI_DBG_MSG, DBG_IOCMD);
561 //KPrintF("cmd: %s\n",cmd_name(io->io_Command));
562 //KPrintF("IO %lx Start, io_Flags = %ld, io_Command = %ld\n", io, io->io_Flags, io->io_Command);
564 switch (io->io_Command) {
566 /* Invalidate read buffer */
569 /* Flush write buffer */
574 iostd->io_Actual = u->change_num;
580 case TD_GETDRIVETYPE:
581 iostd->io_Actual = DG_DIRECT_ACCESS;
584 iostd->io_Actual = u->motor;
585 u->motor = iostd->io_Length ? 1 : 0;
589 offset = iotd->iotd_Req.io_Offset;
591 err = piscsi_rw(u, io, offset, 1);
594 offset = iotd->iotd_Req.io_Offset;
596 err = piscsi_rw(u, io, offset, 1);
599 offset = iotd->iotd_Req.io_Offset;
601 err = piscsi_rw(u, io, offset, 0);
605 err = piscsi_scsi(u, io);
608 int cmd = io->io_Command;
609 debug(PISCSI_DBG_MSG, DBG_IOCMD_UNHANDLED);