9 #include "piscsi-enums.h"
10 #include "../../../config_file/config_file.h"
11 #include "../../../gpio/gpio.h"
13 // Comment this line to restore debug output:
16 struct piscsi_dev devs[8];
17 uint8_t piscsi_cur_drive = 0;
18 uint32_t piscsi_u32[4];
19 uint32_t piscsi_dbg[8];
20 uint32_t piscsi_rom_size = 0;
21 uint8_t *piscsi_rom_ptr;
23 extern unsigned char ac_piscsi_rom[];
25 static const char *op_type_names[4] = {
33 for (int i = 0; i < 8; i++) {
36 devs[i].c = devs[i].h = devs[i].s = 0;
39 FILE *in = fopen("./platforms/amiga/piscsi/piscsi.rom", "rb");
41 printf("[PISCSI] Could not open PISCSI Boot ROM file for reading.\n");
42 ac_piscsi_rom[20] = 0;
43 ac_piscsi_rom[21] = 0;
44 ac_piscsi_rom[22] = 0;
45 ac_piscsi_rom[23] = 0;
48 fseek(in, 0, SEEK_END);
49 piscsi_rom_size = ftell(in);
50 fseek(in, 0, SEEK_SET);
51 piscsi_rom_ptr = malloc(piscsi_rom_size);
52 fread(piscsi_rom_ptr, piscsi_rom_size, 1, in);
54 printf("[PISCSI] Loaded Boot ROM.\n");
57 void piscsi_map_drive(char *filename, uint8_t index) {
59 printf("[PISCSI] Drive index %d out of range.\nUnable to map file %s to drive.\n", index, filename);
63 int32_t tmp_fd = open(filename, O_RDWR);
65 printf("[PISCSI] Failed to open file %s, could not map drive %d.\n", filename, index);
69 struct piscsi_dev *d = &devs[index];
71 uint64_t file_size = lseek(tmp_fd, 0, SEEK_END);
72 lseek(tmp_fd, 0, SEEK_SET);
73 printf("[PISCSI] Map %d: [%s] - %llu bytes.\n", index, filename, file_size);
76 d->c = (file_size / 512) / (d->s * d->h);
77 printf("[PISCSI] CHS: %d %d %d\n", d->c, d->h, d->s);
82 void piscsi_unmap_drive(uint8_t index) {
83 if (devs[index].fd != -1) {
84 printf("[PISCSI] Unmapped drive %d.\n", index);
85 close (devs[index].fd);
90 #define TDF_EXTCOM (1<<15)
103 #define TD_MOTOR (CMD_NONSTD+0)
104 #define TD_SEEK (CMD_NONSTD+1)
105 #define TD_FORMAT (CMD_NONSTD+2)
106 #define TD_REMOVE (CMD_NONSTD+3)
107 #define TD_CHANGENUM (CMD_NONSTD+4)
108 #define TD_CHANGESTATE (CMD_NONSTD+5)
109 #define TD_PROTSTATUS (CMD_NONSTD+6)
110 #define TD_RAWREAD (CMD_NONSTD+7)
111 #define TD_RAWWRITE (CMD_NONSTD+8)
112 #define TD_GETDRIVETYPE (CMD_NONSTD+9)
113 #define TD_GETNUMTRACKS (CMD_NONSTD+10)
114 #define TD_ADDCHANGEINT (CMD_NONSTD+11)
115 #define TD_REMCHANGEINT (CMD_NONSTD+12)
116 #define TD_GETGEOMETRY (CMD_NONSTD+13)
117 #define TD_EJECT (CMD_NONSTD+14)
118 #define TD_LASTCOMM (CMD_NONSTD+15)
120 #define ETD_WRITE (CMD_WRITE|TDF_EXTCOM)
121 #define ETD_READ (CMD_READ|TDF_EXTCOM)
122 #define ETD_MOTOR (TD_MOTOR|TDF_EXTCOM)
123 #define ETD_SEEK (TD_SEEK|TDF_EXTCOM)
124 #define ETD_FORMAT (TD_FORMAT|TDF_EXTCOM)
125 #define ETD_UPDATE (CMD_UPDATE|TDF_EXTCOM)
126 #define ETD_CLEAR (CMD_CLEAR|TDF_EXTCOM)
127 #define ETD_RAWREAD (TD_RAWREAD|TDF_EXTCOM)
128 #define ETD_RAWWRITE (TD_RAWWRITE|TDF_EXTCOM)
130 #define HD_SCSICMD 28
132 char *io_cmd_name(int index) {
134 case CMD_INVALID: return "INVALID";
135 case CMD_RESET: return "RESET";
136 case CMD_READ: return "READ";
137 case CMD_WRITE: return "WRITE";
138 case CMD_UPDATE: return "UPDATE";
139 case CMD_CLEAR: return "CLEAR";
140 case CMD_STOP: return "STOP";
141 case CMD_START: return "START";
142 case CMD_FLUSH: return "FLUSH";
143 case TD_MOTOR: return "TD_MOTOR";
144 case TD_SEEK: return "SEEK";
145 case TD_FORMAT: return "FORMAT";
146 case TD_REMOVE: return "REMOVE";
147 case TD_CHANGENUM: return "CHANGENUM";
148 case TD_CHANGESTATE: return "CHANGESTATE";
149 case TD_PROTSTATUS: return "PROTSTATUS";
150 case TD_RAWREAD: return "RAWREAD";
151 case TD_RAWWRITE: return "RAWWRITE";
152 case TD_GETDRIVETYPE: return "GETDRIVETYPE";
153 case TD_GETNUMTRACKS: return "GETNUMTRACKS";
154 case TD_ADDCHANGEINT: return "ADDCHANGEINT";
155 case TD_REMCHANGEINT: return "REMCHANGEINT";
156 case TD_GETGEOMETRY: return "GETGEOMETRY";
157 case TD_EJECT: return "EJECT";
158 case TD_LASTCOMM: return "LASTCOMM";
159 case HD_SCSICMD: return "HD_SCSICMD";
161 return "!!!Unhandled IO command";
165 char *scsi_cmd_name(int index) {
167 case 0x00: return "TEST UNIT READY";
168 case 0x12: return "INQUIRY";
169 case 0x08: return "READ";
170 case 0x0A: return "WRITE";
171 case 0x25: return "READ CAPACITY";
172 case 0x1A: return "MODE SENSE";
173 case 0x37: return "READ DEFECT DATA";
175 return "!!!Unhandled SCSI command";
179 void print_piscsi_debug_message(int index) {
182 printf("[PISCSI] Initializing devices.\n");
185 printf("[PISCSI] Opening device %d (%d). Flags: %d (%.2X)\n", piscsi_dbg[0], piscsi_dbg[1], piscsi_dbg[2], piscsi_dbg[2]);
188 printf("[PISCSI] Cleaning up.\n");
191 printf("[PISCSI] C/H/S: %d / %d / %d\n", piscsi_dbg[0], piscsi_dbg[1], piscsi_dbg[2]);
194 printf("[PISCSI] BeginIO: io_Command: %d - io_Flags = %d - quick: %d\n", piscsi_dbg[0], piscsi_dbg[1], piscsi_dbg[2]);
197 printf("[PISCSI] AbortIO!\n");
200 printf("[PISCSI] SCSI Command %d (%s)\n", piscsi_dbg[1], scsi_cmd_name(piscsi_dbg[1]));
201 printf("Len: %d - %.2X %.2X %.2X - Command Length: %d\n", piscsi_dbg[0], piscsi_dbg[1], piscsi_dbg[2], piscsi_dbg[3], piscsi_dbg[4]);
203 case DBG_SCSI_UNKNOWN_MODESENSE:
204 printf("SCSI: Unknown modesense %.4X\n", piscsi_dbg[0]);
206 case DBG_SCSI_UNKNOWN_COMMAND:
207 printf("SCSI: Unknown command %.4X\n", piscsi_dbg[0]);
210 printf("SCSI: An error occured: %.4X\n", piscsi_dbg[0]);
213 printf("[PISCSI] IO Command %d (%s)\n", piscsi_dbg[0], io_cmd_name(piscsi_dbg[0]));
215 case DBG_IOCMD_UNHANDLED:
216 printf("[PISCSI] WARN: IO command %d (%s) is unhandled by driver.\n", piscsi_dbg[0], io_cmd_name(piscsi_dbg[0]));
220 extern struct emulator_config *cfg;
221 extern void stop_cpu_emulation(uint8_t disasm_cur);
223 void handle_piscsi_write(uint32_t addr, uint32_t val, uint8_t type) {
226 struct piscsi_dev *d = &devs[piscsi_cur_drive];
228 switch (addr & 0xFFFF) {
229 case PISCSI_CMD_READ:
232 printf ("[PISCSI] BUG: Attempted read from unmapped drive %d.\n", piscsi_cur_drive);
235 printf("[PISCSI] %d byte READ from block %d to address %.8X\n", piscsi_u32[1], piscsi_u32[0], piscsi_u32[2]);
236 d->lba = piscsi_u32[0];
237 r = get_mapped_item_by_address(cfg, piscsi_u32[2]);
238 if (r != -1 && cfg->map_type[r] == MAPTYPE_RAM) {
239 printf("[PISCSI] \"DMA\" Read goes to mapped range %d.\n", r);
240 lseek(d->fd, (piscsi_u32[0] * 512), SEEK_SET);
241 read(d->fd, cfg->map_data[r] + piscsi_u32[2] - cfg->map_offset[r], piscsi_u32[1]);
244 printf("[PISCSI] No mapped range found for read.\n");
246 lseek(d->fd, (piscsi_u32[0] * 512), SEEK_SET);
247 for (int i = 0; i < piscsi_u32[1]; i++) {
250 write8(piscsi_u32[2] + i, (uint32_t)c);
255 case PISCSI_CMD_WRITE:
258 printf ("[PISCSI] BUG: Attempted write to unmapped drive %d.\n", piscsi_cur_drive);
261 d->lba = piscsi_u32[0];
262 printf("[PISCSI] %d byte WRITE to block %d from address %.8X\n", piscsi_u32[1], piscsi_u32[0], piscsi_u32[2]);
263 r = get_mapped_item_by_address(cfg, piscsi_u32[2]);
265 printf("[PISCSI] \"DMA\" Write comes from mapped range %d.\n", r);
266 lseek(d->fd, (piscsi_u32[0] * 512), SEEK_SET);
267 write(d->fd, cfg->map_data[r] + piscsi_u32[2] - cfg->map_offset[r], piscsi_u32[1]);
270 printf("[PISCSI] No mapped range found for write.\n");
272 lseek(d->fd, (piscsi_u32[0] * 512), SEEK_SET);
273 for (int i = 0; i < piscsi_u32[1]; i++) {
275 c = read8(piscsi_u32[2] + i);
281 case PISCSI_CMD_ADDR1: case PISCSI_CMD_ADDR2: case PISCSI_CMD_ADDR3: case PISCSI_CMD_ADDR4: {
282 int i = ((addr & 0xFFFF) - PISCSI_CMD_ADDR1) / 4;
286 case PISCSI_CMD_DRVNUM:
288 if (val < 10) // Kludge for GiggleDisk
289 piscsi_cur_drive = val;
290 else if (val >= 10 && val % 10 != 0)
291 piscsi_cur_drive = 255;
293 piscsi_cur_drive = val / 10;
296 piscsi_cur_drive = val;
297 printf("[PISCSI] (%s) Drive number set to %d (%d)\n", op_type_names[type], piscsi_cur_drive, val);
299 case PISCSI_CMD_DEBUGME:
300 printf("[PISCSI] DebugMe triggered (%d).\n", val);
301 stop_cpu_emulation(1);
303 case PISCSI_CMD_DRIVER: {
304 printf("[PISCSI] Driver copy/patch called, destination address %.8X.\n", val);
305 int r = get_mapped_item_by_address(cfg, val);
307 uint32_t addr = val - cfg->map_offset[r];
308 uint32_t rt_offs = 0;
309 uint8_t *dst_data = cfg->map_data[r];
310 memcpy(dst_data + addr, piscsi_rom_ptr + 0x400, 0x3C00);
312 uint32_t base_offs = be32toh(*((uint32_t *)&dst_data[addr + 0x170])) + 2;
313 rt_offs = val + 0x16E;
314 printf ("Offset 1: %.8X -> %.8X\n", base_offs, rt_offs);
315 *((uint32_t *)&dst_data[addr + 0x170]) = htobe32(rt_offs);
317 uint32_t offs = be32toh(*((uint32_t *)&dst_data[addr + 0x174]));
318 printf ("Offset 2: %.8X -> %.8X\n", offs, (offs - base_offs) + rt_offs);
319 *((uint32_t *)&dst_data[addr + 0x174]) = htobe32((offs - base_offs) + rt_offs);
321 dst_data[addr + 0x178] |= 0x07;
323 offs = be32toh(*((uint32_t *)&dst_data[addr + 0x17C]));
324 printf ("Offset 3: %.8X -> %.8X\n", offs, (offs - base_offs) + rt_offs);
325 *((uint32_t *)&dst_data[addr + 0x17C]) = htobe32((offs - base_offs) + rt_offs);
327 offs = be32toh(*((uint32_t *)&dst_data[addr + 0x180]));
328 printf ("Offset 4: %.8X -> %.8X\n", offs, (offs - base_offs) + rt_offs);
329 *((uint32_t *)&dst_data[addr + 0x180]) = htobe32((offs - base_offs) + rt_offs);
331 offs = be32toh(*((uint32_t *)&dst_data[addr + 0x184]));
332 printf ("Offset 5: %.8X -> %.8X\n", offs, (offs - base_offs) + rt_offs);
333 *((uint32_t *)&dst_data[addr + 0x184]) = htobe32((offs - base_offs) + rt_offs);
337 for (int i = 0; i < 0x3C00; i++) {
338 uint8_t src = piscsi_rom_ptr[0x400 + i];
339 write8(addr + i, src);
344 case PISCSI_DBG_VAL1: case PISCSI_DBG_VAL2: case PISCSI_DBG_VAL3: case PISCSI_DBG_VAL4:
345 case PISCSI_DBG_VAL5: case PISCSI_DBG_VAL6: case PISCSI_DBG_VAL7: case PISCSI_DBG_VAL8: {
346 int i = ((addr & 0xFFFF) - PISCSI_DBG_VAL1) / 4;
351 print_piscsi_debug_message(val);
354 printf("[PISCSI] WARN: Unhandled %s register write to %.8X: %d\n", op_type_names[type], addr, val);
361 uint32_t handle_piscsi_read(uint32_t addr, uint8_t type) {
364 if ((addr & 0xFFFF) >= PISCSI_CMD_ROM) {
365 uint32_t romoffs = (addr & 0xFFFF) - PISCSI_CMD_ROM;
366 if (romoffs < (piscsi_rom_size + PIB)) {
367 printf("[PISCSI] %s read from Boot ROM @$%.4X (%.8X): ", op_type_names[type], romoffs, addr);
371 v = piscsi_rom_ptr[romoffs - PIB];
375 v = be16toh(*((uint16_t *)&piscsi_rom_ptr[romoffs - PIB]));
378 case OP_TYPE_LONGWORD:
379 v = be32toh(*((uint32_t *)&piscsi_rom_ptr[romoffs - PIB]));
388 switch (addr & 0xFFFF) {
389 case PISCSI_CMD_DRVTYPE:
390 if (devs[piscsi_cur_drive].fd == -1) {
391 printf("[PISCSI] %s Read from DRVTYPE %d, drive not attached.\n", op_type_names[type], piscsi_cur_drive);
394 printf("[PISCSI] %s Read from DRVTYPE %d, drive attached.\n", op_type_names[type], piscsi_cur_drive);
397 case PISCSI_CMD_DRVNUM:
398 return piscsi_cur_drive;
400 case PISCSI_CMD_CYLS:
401 printf("[PISCSI] %s Read from CYLS %d: %d\n", op_type_names[type], piscsi_cur_drive, devs[piscsi_cur_drive].c);
402 return devs[piscsi_cur_drive].c;
404 case PISCSI_CMD_HEADS:
405 printf("[PISCSI] %s Read from HEADS %d: %d\n", op_type_names[type], piscsi_cur_drive, devs[piscsi_cur_drive].h);
406 return devs[piscsi_cur_drive].h;
408 case PISCSI_CMD_SECS:
409 printf("[PISCSI] %s Read from SECS %d: %d\n", op_type_names[type], piscsi_cur_drive, devs[piscsi_cur_drive].s);
410 return devs[piscsi_cur_drive].s;
412 case PISCSI_CMD_BLOCKS: {
413 uint32_t blox = devs[piscsi_cur_drive].fs / 512;
414 printf("[PISCSI] %s Read from BLOCKS %d: %d\n", op_type_names[type], piscsi_cur_drive, (uint32_t)(devs[piscsi_cur_drive].fs / 512));
415 printf("fs: %lld (%d)\n", devs[piscsi_cur_drive].fs, blox);
420 printf("[PISCSI] Unhandled %s register read from %.8X\n", op_type_names[type], addr);