]> git.sesse.net Git - pistorm/blob - platforms/amiga/gayle-ide/ide.c
Silence some compile warnings
[pistorm] / platforms / amiga / gayle-ide / ide.c
1 /*
2  *      IDE Emulation Layer for retro-style PIO interfaces
3  *
4  *      (c) Copyright Alan Cox, 2015-2019
5  *
6  *      IDE-emu is free software: you can redistribute it and/or modify
7  *      it under the terms of the GNU General Public License as published by
8  *      the Free Software Foundation, either version 2 of the License, or
9  *      (at your option) any later version.
10  *
11  *      IDE-emu is distributed in the hope that it will be useful,
12  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *      GNU General Public License for more details.
15  *
16  *      You should have received a copy of the GNU General Public License
17  *      along with IDE-emu.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <stdio.h>
21 #include <stdint.h>
22 #include <unistd.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <errno.h>
26 #include <time.h>
27 #include <arpa/inet.h>
28
29 #include "config_file/config_file.h"
30 #include "ide.h"
31
32 #define IDE_IDLE        0
33 #define IDE_CMD         1
34 #define IDE_DATA_IN     2
35 #define IDE_DATA_OUT    3
36
37 #define DCR_NIEN        2
38 #define DCR_SRST        4
39
40 #define DEVH_HEAD       15
41 #define DEVH_DEV        16
42 #define DEVH_LBA        64
43
44 #define ERR_AMNF        1
45 #define ERR_TKNONF      2
46 #define ERR_ABRT        4
47 #define ERR_MCR         8
48 #define ERR_IDNF        16
49 #define ERR_MC          32
50 #define ERR_UNC         64
51
52 #define ST_ERR          1
53 #define ST_IDX          2
54 #define ST_CORR         4
55 #define ST_DRQ          8
56 #define ST_DSC          16
57 #define ST_DF           32
58 #define ST_DRDY         64
59 #define ST_BSY          128
60
61 #define DCL_SRST        4
62 #define DCL_NIEN        2
63
64 #define IDE_CMD_CALIB           0x10
65 #define IDE_CMD_READ            0x20
66 #define IDE_CMD_READ_NR         0x21
67 #define IDE_CMD_WRITE           0x30
68 #define IDE_CMD_WRITE_NR        0x31
69 #define IDE_CMD_VERIFY          0x40
70 #define IDE_CMD_VERIFY_NR       0x41
71 #define IDE_CMD_SEEK            0x70
72 #define IDE_CMD_EDD             0x90
73 #define IDE_CMD_INTPARAMS       0x91
74 #define IDE_CMD_IDENTIFY        0xEC
75 #define IDE_CMD_SETFEATURES     0xEF
76
77 const uint8_t ide_magic[9] = {
78   '1','D','E','D','1','5','C','0',0x00
79 };
80 /*
81 static char *charmap(uint8_t v)
82 {
83   static char cbuf[3];
84   if (v < 32)
85     sprintf(cbuf, "^%c", '@'+v);
86   else if (v < 127)
87     sprintf(cbuf, " %c", v);
88   else if (v == 127)
89     sprintf(cbuf, "DL");
90   else if (v < 160)
91     sprintf(cbuf, ":%c", '@' + v - 128);
92   else if (v < 255)
93     sprintf(cbuf, "~%c", v - 128);
94   else
95     sprintf(cbuf, "!D");
96   return cbuf;
97 }
98
99 static void hexdump(uint8_t *bp)
100 {
101   int i,j;
102   for (i = 0; i < 512; i+= 16) {
103     for(j = 0; j < 16; j++)
104       fprintf(stderr, "%02X ", bp[i+j]);
105     fprintf(stderr, "|");
106     for(j = 0; j < 16; j++)
107       fprintf(stderr, "%2s", charmap(bp[i+j]));
108     fprintf(stderr, "\n");
109   }
110 }
111 */
112 /* FIXME: use proper endian convertors! */
113 static uint16_t le16(uint16_t v)
114 {
115   uint8_t *p = (uint8_t *)&v;
116   return p[0] | (p[1] << 8);
117 }
118
119 static void ide_xlate_errno(struct ide_taskfile *t, int len)
120 {
121   t->status |= ST_ERR;
122   if (len == -1) {
123     if (errno == EIO)
124       t->error = ERR_UNC;
125     else
126       t->error = ERR_AMNF;
127   } else
128     t->error = ERR_AMNF;
129 }
130
131 static void ide_fault(struct ide_drive *d, const char *p)
132 {
133   fprintf(stderr, "ide: %s: %d: %s\n", d->controller->name,
134                         (int)(d - d->controller->drive), p);
135 }
136
137 /* Disk translation */
138 static off_t xlate_block(struct ide_taskfile *t)
139 {
140   struct ide_drive *d = t->drive;
141   uint16_t cyl;
142
143   if (d->controller->lba4 & DEVH_LBA) {
144 /*    fprintf(stderr, "XLATE LBA %02X:%02X:%02X:%02X\n",
145       t->lba4, t->lba3, t->lba2, t->lba1);*/
146     if (d->lba)
147       return ((d->header_present) ? 2 : 0) + (((t->drive->controller->lba4 & DEVH_HEAD) << 24) | (t->drive->controller->lba3 << 16) | (t->drive->controller->lba2 << 8) | t->drive->controller->lba1);
148     ide_fault(d, "LBA on non LBA drive");
149   }
150
151   /* Some well known software asks for 0/0/0 when it means 0/0/1. Drives appear
152      to interpret sector 0 as sector 1 */
153   if (t->drive->controller->lba1 == 0) {
154     fprintf(stderr, "[Bug: request for sector offset 0].\n");
155     t->drive->controller->lba1 = 1;
156   }
157   cyl = (t->drive->controller->lba3 << 8) | t->drive->controller->lba2;
158   /* fprintf(stderr, "(H %d C %d S %d)\n", t->lba4 & DEVH_HEAD, cyl, t->lba1); */
159   if (t->drive->controller->lba1 == 0 || t->drive->controller->lba1 > d->sectors || t->drive->controller->lba4 >= d->heads || cyl >= d->cylinders) {
160     return -1;
161   }
162   /* Sector 1 is first */
163   /* Images generally go cylinder/head/sector. This also matters if we ever
164      implement more advanced geometry setting */
165   //off_t ret = ((d->header_present) ? 1 : -1) + ((cyl * d->heads) + (t->drive->controller->lba4 & DEVH_HEAD)) * d->sectors + t->drive->controller->lba1;
166   //printf("Non-LBA xlate block %lX.\n", ret);
167   //printf("Cyl: %d Heads: %d Sectors: %d\n", cyl, d->heads, d->sectors);
168   //printf("LBA1: %.2X LBA2: %.2X LBA3: %.2X LBA4: %.2X\n", t->drive->controller->lba1, t->drive->controller->lba2, t->drive->controller->lba3, t->drive->controller->lba4);
169
170   return ((d->header_present) ? 1 : -1) + ((cyl * d->heads) + (t->drive->controller->lba4 & DEVH_HEAD)) * d->sectors + t->drive->controller->lba1;
171 }
172
173 /* Indicate the drive is ready */
174 static void ready(struct ide_taskfile *tf)
175 {
176   tf->status &= ~(ST_BSY|ST_DRQ);
177   tf->status |= ST_DRDY;
178   tf->drive->state = IDE_IDLE;
179 }
180
181 /* Return to idle state, completing a command */
182 static void completed(struct ide_taskfile *tf)
183 {
184   ready(tf);
185   tf->drive->intrq = 1;
186 }
187
188 static void drive_failed(struct ide_taskfile *tf)
189 {
190   tf->status |= ST_ERR;
191   tf->error = ERR_IDNF;
192   ready(tf);
193 }
194
195 static void data_in_state(struct ide_taskfile *tf)
196 {
197   struct ide_drive *d = tf->drive;
198   d->state = IDE_DATA_IN;
199   d->dptr = d->data + 512;
200   /* We don't clear DRDY here, drives may well accept a command at this
201      point and at least one firmware for RC2014 assumes this */
202   tf->status &= ~ST_BSY;
203   tf->status |= ST_DRQ;
204   d->intrq = 1;                 /* Double check */
205 }
206
207 static void data_out_state(struct ide_taskfile *tf)
208 {
209   struct ide_drive *d = tf->drive;
210   d->state = IDE_DATA_OUT;
211   d->dptr = d->data;
212   tf->status &= ~ (ST_BSY|ST_DRDY);
213   tf->status |= ST_DRQ;
214   d->intrq = 1;                 /* Double check */
215 }
216
217 static void edd_setup(struct ide_taskfile *tf)
218 {
219   tf->error = 0x01;             /* All good */
220   tf->drive->controller->lba1 = 0x01;           /* EDD always updates drive 0 */
221   tf->drive->controller->lba2 = 0x00;
222   tf->drive->controller->lba3 = 0x00;
223   tf->drive->controller->lba4 = 0x00;
224   tf->count = 0x01;
225   ready(tf);
226 }
227
228 void ide_reset(struct ide_controller *c)
229 {
230   if (c->drive[0].present) {
231     edd_setup(&c->drive[0].taskfile);
232     /* A drive could clear busy then set DRDY up to 2 minutes later if its
233        mindnumbingly slow to start up ! We don't emulate any of that */
234     c->drive[0].taskfile.status = ST_DRDY;
235     c->drive[0].eightbit = 0;
236   }
237   if (c->drive[1].present) {
238     edd_setup(&c->drive[1].taskfile);
239     c->drive[1].taskfile.status = ST_DRDY;
240     c->drive[1].eightbit = 0;
241   }
242   if (c->selected != 0) {
243   }
244   c->selected = 0;
245 }
246
247 void ide_reset_begin(struct ide_controller *c)
248 {
249   if (c->drive[0].present)
250     c->drive[0].taskfile.status |= ST_BSY;
251   if (c->drive[1].present)
252     c->drive[1].taskfile.status |= ST_BSY;
253   /* Ought to be a time delay relative to reset or power on */
254   ide_reset(c);
255 }
256
257 static void ide_srst_begin(struct ide_controller *c)
258 {
259   ide_reset(c);
260   if (c->drive[0].present)
261     c->drive[0].taskfile.status |= ST_BSY;
262   if (c->drive[1].present)
263     c->drive[1].taskfile.status |= ST_BSY;
264 }
265
266 static void ide_srst_end(struct ide_controller *c)
267 {
268   /* Could be time delays here */
269   ready(&c->drive[0].taskfile);
270   ready(&c->drive[1].taskfile);
271 }
272
273 static void cmd_edd_complete(struct ide_taskfile *tf)
274 {
275   struct ide_controller *c = tf->drive->controller;
276   if (c->drive[0].present)
277     edd_setup(&c->drive[0].taskfile);
278   if (c->drive[1].present)
279     edd_setup(&c->drive[1].taskfile);
280   c->selected = 0;
281 }
282
283 static void cmd_identify_complete(struct ide_taskfile *tf)
284 {
285   struct ide_drive *d = tf->drive;
286   memcpy(d->data, d->identify, 512);
287   data_in_state(tf);
288   /* Arrange to copy just the identify buffer */
289   d->dptr = d->data;
290   d->length = 1;
291 }
292
293 static void cmd_initparam_complete(struct ide_taskfile *tf)
294 {
295   struct ide_drive *d = tf->drive;
296   /* We only support the current mapping */
297   if (tf->count != d->sectors || (tf->drive->controller->lba4 & DEVH_HEAD) + 1 != d->heads) {
298     tf->status |= ST_ERR;
299     tf->error |= ERR_ABRT;
300     tf->drive->failed = 1;              /* Report ID NF until fixed */
301 /*    fprintf(stderr, "geo is %d %d, asked for %d %d\n",
302       d->sectors, d->heads, tf->count, (tf->lba4 & DEVH_HEAD) + 1); */
303     ide_fault(d, "invalid geometry");
304   } else if (tf->drive->failed == 1)
305     tf->drive->failed = 0;              /* Valid translation */
306   completed(tf);
307 }
308
309 static void cmd_readsectors_complete(struct ide_taskfile *tf)
310 {
311   struct ide_drive *d = tf->drive;
312   /* Move to data xfer */
313   if (d->failed) {
314     drive_failed(tf);
315     return;
316   }
317   d->offset = xlate_block(tf);
318   /* DRDY is not guaranteed here but at least one buggy RC2014 firmware
319      expects it */
320   tf->status |= ST_DRQ | ST_DSC | ST_DRDY;
321   tf->status &= ~ST_BSY;
322   /* 0 = 256 sectors */
323   d->length = tf->count ? tf->count : 256;
324   /* fprintf(stderr, "READ %d SECTORS @ %ld\n", d->length, d->offset); */
325   if (d->offset == -1 ||  lseek(d->fd, 512 * d->offset, SEEK_SET) == -1) {
326     tf->status |= ST_ERR;
327     tf->status &= ~ST_DSC;
328     tf->error |= ERR_IDNF;
329     /* return null data */
330     completed(tf);
331     return;
332   }
333   /* do the xfer */
334   data_in_state(tf);
335 }
336
337 static void cmd_verifysectors_complete(struct ide_taskfile *tf)
338 {
339   struct ide_drive *d = tf->drive;
340   /* Move to data xfer */
341   if (d->failed) {
342     drive_failed(tf);
343     return;
344   }
345   d->offset = xlate_block(tf);
346   /* 0 = 256 sectors */
347   d->length = tf->count ? tf->count : 256;
348   if (d->offset == -1 || lseek(d->fd, 512 * (d->offset + d->length - 1), SEEK_SET) == -1) {
349     tf->status &= ~ST_DSC;
350     tf->status |= ST_ERR;
351     tf->error |= ERR_IDNF;
352   }
353   tf->status |= ST_DSC;
354   completed(tf);
355 }
356
357 static void cmd_recalibrate_complete(struct ide_taskfile *tf)
358 {
359   struct ide_drive *d = tf->drive;
360   if (d->failed)
361     drive_failed(tf);
362   if (d->offset == -1 || xlate_block(tf) != 0L) {
363     tf->status &= ~ST_DSC;
364     tf->status |= ST_ERR;
365     tf->error |= ERR_ABRT;
366   }
367   tf->status |= ST_DSC;
368   completed(tf);
369 }
370
371 static void cmd_seek_complete(struct ide_taskfile *tf)
372 {
373   struct ide_drive *d = tf->drive;
374   if (d->failed)
375     drive_failed(tf);
376   d->offset = xlate_block(tf);
377   if (d->offset == -1 || lseek(d->fd, 512 * d->offset, SEEK_SET) == -1) {
378     tf->status &= ~ST_DSC;
379     tf->status |= ST_ERR;
380     tf->error |= ERR_IDNF;
381   }
382   tf->status |= ST_DSC;
383   completed(tf);
384 }
385
386 static void cmd_setfeatures_complete(struct ide_taskfile *tf)
387 {
388   struct ide_drive *d = tf->drive;
389   switch(tf->feature) {
390     case 0x01:
391       d->eightbit = 1;
392       break;
393     case 0x03:
394       if ((tf->count & 0xF0) >= 0x20) {
395         tf->status |= ST_ERR;
396         tf->error |= ERR_ABRT;
397       }
398       /* Silently accept PIO mode settings */
399       break;
400     case 0x81:
401       d->eightbit = 0;
402       break;
403     default:
404       tf->status |= ST_ERR;
405       tf->error |= ERR_ABRT;
406   }
407   completed(tf);
408 }
409
410 static void cmd_writesectors_complete(struct ide_taskfile *tf)
411 {
412   struct ide_drive *d = tf->drive;
413   /* Move to data xfer */
414   if (d->failed) {
415     drive_failed(tf);
416     return;
417   }
418   d->offset = xlate_block(tf);
419   tf->status |= ST_DRQ;
420   /* 0 = 256 sectors */
421   d->length = tf->count ? tf->count : 256;
422 /*  fprintf(stderr, "WRITE %d SECTORS @ %ld\n", d->length, d->offset); */
423   if (d->offset == -1 ||  lseek(d->fd, 512 * d->offset, SEEK_SET) == -1) {
424     tf->status |= ST_ERR;
425     tf->error |= ERR_IDNF;
426     tf->status &= ~ST_DSC;
427     /* return null data */
428     completed(tf);
429     return;
430   }
431   /* do the xfer */
432   data_out_state(tf);
433 }
434
435 static void ide_set_error(struct ide_drive *d)
436 {
437   d->controller->lba4 &= ~DEVH_HEAD;
438
439   if (d->controller->lba4 & DEVH_LBA) {
440     d->controller->lba1 = d->offset & 0xFF;
441     d->controller->lba2 = (d->offset >> 8) & 0xFF;
442     d->controller->lba3 = (d->offset >> 16) & 0xFF;
443     d->controller->lba4 |= (d->offset >> 24) & DEVH_HEAD;
444   } else {
445     d->controller->lba1 = d->offset % d->sectors + 1;
446     d->offset /= d->sectors;
447     d->controller->lba4 |= d->offset / (d->cylinders * d->sectors);
448     d->offset %= (d->cylinders * d->sectors);
449     d->controller->lba2 = d->offset & 0xFF;
450     d->controller->lba3 = (d->offset >> 8) & 0xFF;
451   }
452   d->taskfile.count = d->length;
453   d->taskfile.status |= ST_ERR;
454   d->state = IDE_IDLE;
455   completed(&d->taskfile);
456 }
457
458 static int ide_read_sector(struct ide_drive *d)
459 {
460   int len;
461
462   d->dptr = d->data;
463   if ((len = read(d->fd, d->data, 512)) != 512) {
464     perror("ide_read_sector");
465     d->taskfile.status |= ST_ERR;
466     d->taskfile.status &= ~ST_DSC;
467     ide_xlate_errno(&d->taskfile, len);
468     return -1;
469   }
470 //  hexdump(d->data);
471   d->offset += 512;
472   return 0;
473 }
474
475 static int ide_write_sector(struct ide_drive *d)
476 {
477   int len;
478
479   d->dptr = d->data;
480   if ((len = write(d->fd, d->data, 512)) != 512) {
481     d->taskfile.status |= ST_ERR;
482     d->taskfile.status &= ~ST_DSC;
483     ide_xlate_errno(&d->taskfile, len);
484     return -1;
485   }
486 //  hexdump(d->data);
487   d->offset += 512;
488   return 0;
489 }
490
491 static uint16_t ide_data_in(struct ide_drive *d, int len)
492 {
493   uint16_t v;
494   if (d->state == IDE_DATA_IN) {
495     if (d->dptr == d->data + 512) {
496       if (ide_read_sector(d) < 0) {
497         ide_set_error(d);       /* Set the LBA or CHS etc */
498         return 0xFFFF;          /* and error bits set by read_sector */
499       }
500     }
501     v = *d->dptr;
502     if (!d->eightbit) {
503       if (len == 2)
504         v |= (d->dptr[1] << 8);
505       d->dptr+=2;
506     } else
507       d->dptr++;
508     d->taskfile.data = v;
509     if (d->dptr == d->data + 512) {
510       d->length--;
511       d->intrq = 1;             /* we don't yet emulate multimode */
512       if (d->length == 0) {
513         d->state = IDE_IDLE;
514         completed(&d->taskfile);
515       }
516     }
517   } else
518     ide_fault(d, "bad data read");
519
520   if (len == 1)
521     return d->taskfile.data & 0xFF;
522   return d->taskfile.data;
523 }
524
525 static void ide_data_out(struct ide_drive *d, uint16_t v, int len)
526 {
527   (void)len;
528   if (d->state != IDE_DATA_OUT) {
529     ide_fault(d, "bad data write");
530     d->taskfile.data = v;
531   } else {
532     if (d->eightbit)
533       v &= 0xFF;
534     *d->dptr++ = v;
535     d->taskfile.data = v;
536     if (!d->eightbit) {
537       *d->dptr++ = v >> 8;
538       d->taskfile.data = v >> 8;
539     }
540     if (d->dptr == d->data + 512) {
541       if (ide_write_sector(d) < 0) {
542         ide_set_error(d);
543         return;
544       }
545       d->length--;
546       d->intrq = 1;
547       if (d->length == 0) {
548         d->state = IDE_IDLE;
549         d->taskfile.status |= ST_DSC;
550         completed(&d->taskfile);
551       }
552     }
553   }
554 }
555
556 static void ide_issue_command(struct ide_taskfile *t)
557 {
558   t->status &= ~(ST_ERR|ST_DRDY);
559   t->status |= ST_BSY;
560   t->error = 0;
561   t->drive->state = IDE_CMD;
562
563   /* We could complete with delays but don't do so yet */
564   switch(t->command) {
565     case IDE_CMD_EDD:   /* 0x90 */
566       cmd_edd_complete(t);
567       break;
568     case IDE_CMD_IDENTIFY:      /* 0xEC */
569       cmd_identify_complete(t);
570       break;
571     case IDE_CMD_INTPARAMS:     /* 0x91 */
572       cmd_initparam_complete(t);
573       break;
574     case IDE_CMD_READ:          /* 0x20 */
575     case IDE_CMD_READ_NR:       /* 0x21 */
576       cmd_readsectors_complete(t);
577       break;
578     case IDE_CMD_SETFEATURES:   /* 0xEF */
579       cmd_setfeatures_complete(t);
580       break;
581     case IDE_CMD_VERIFY:        /* 0x40 */
582     case IDE_CMD_VERIFY_NR:     /* 0x41 */
583       cmd_verifysectors_complete(t);
584       break;
585     case IDE_CMD_WRITE:         /* 0x30 */
586     case IDE_CMD_WRITE_NR:      /* 0x31 */
587       cmd_writesectors_complete(t);
588       break;
589     default:
590       if ((t->command & 0xF0) == IDE_CMD_CALIB) /* 1x */
591         cmd_recalibrate_complete(t);
592       else if ((t->command & 0xF0) == IDE_CMD_SEEK) /* 7x */
593         cmd_seek_complete(t);
594       else {
595         /* Unknown */
596         t->status |= ST_ERR;
597         t->error |= ERR_ABRT;
598         completed(t);
599       }
600   }
601 }
602
603 /*
604  *      8bit IDE controller emulation
605  */
606
607 uint8_t ide_read8(struct ide_controller *c, uint8_t r)
608 {
609   struct ide_drive *d = &c->drive[c->selected];
610   struct ide_taskfile *t = &d->taskfile;
611   switch(r) {
612     case ide_data:
613       return ide_data_in(d, 1);
614     case ide_error_r:
615       return t->error;
616     case ide_sec_count:
617       return t->count;
618     case ide_lba_low:
619       return c->lba1;
620     case ide_lba_mid:
621       return c->lba2;
622     case ide_lba_hi:
623       return c->lba3;
624     case ide_lba_top:
625       return c->lba4 | ((c->selected) ? 0x10 : 0x00);
626     case ide_status_r:
627       d->intrq = 0;             /* Acked */
628       /* Fallthrough */
629       /* no break */
630     case ide_altst_r:
631       return t->status;
632     default:
633       ide_fault(d, "bogus register");
634       return 0xFF;
635   }
636 }
637
638 void ide_write8(struct ide_controller *c, uint8_t r, uint8_t v)
639 {
640   struct ide_drive *d = &c->drive[c->selected];
641   struct ide_taskfile *t = &d->taskfile;
642
643   if (r != ide_devctrl_w) {
644     if (t->status & ST_BSY) {
645       ide_fault(d, "command written while busy");
646       return;
647     }
648     /* Not clear this is the right emulation */
649     if (d->present == 0 && r != ide_lba_top) {
650       ide_fault(d, "not present");
651       return;
652     }
653   }
654
655 //  uint8_t ve;
656
657   switch(r) {
658     case ide_data:
659       ide_data_out(d, v, 1);
660       break;
661     case ide_feature_w:
662       t->feature = v;
663       break;
664     case ide_sec_count:
665       t->count = v;
666       break;
667     case ide_lba_low:
668       c->lba1 = v;
669       break;
670     case ide_lba_mid:
671       c->lba2 = v;
672       break;
673     case ide_lba_hi:
674       c->lba3 = v;
675       break;
676     case ide_lba_top:
677       c->selected = (v & DEVH_DEV) ? 1 : 0;
678       c->lba4 = v & (DEVH_HEAD|/*DEVH_DEV|*/DEVH_LBA);
679       break;
680     case ide_command_w:
681       t->command = v;
682       ide_issue_command(t);
683       break;
684     case ide_devctrl_w:
685       /* ATA: "When the Device Control register is written, both devices
686          respond to the write regardless of which device is selected" */
687       if ((v ^ t->devctrl) & DCL_SRST) {
688         if (v & DCL_SRST)
689           ide_srst_begin(c);
690         else
691           ide_srst_end(c);
692       }
693       c->drive[0].taskfile.devctrl = v; /* Check versus real h/w does this end up cleared */
694       c->drive[1].taskfile.devctrl = v;
695       break;
696   }
697 }
698
699 /*
700  *      16bit IDE controller emulation
701  */
702
703 uint16_t ide_read16(struct ide_controller *c, uint8_t r)
704 {
705   struct ide_drive *d = &c->drive[c->selected];
706   if (r == ide_data)
707     return htons(ide_data_in(d,2));
708   return ide_read8(c, r);
709 }
710
711 void ide_write16(struct ide_controller *c, uint8_t r, uint16_t v)
712 {
713   struct ide_drive *d = &c->drive[c->selected];
714   struct ide_taskfile *t = &d->taskfile;
715
716   if (r != ide_devctrl_w && (t->status & ST_BSY)) {
717     ide_fault(d, "command written while busy");
718     return;
719   }
720   if (r == ide_data)
721     ide_data_out(d, ntohs(v), 2);
722   else
723     ide_write8(c, r, v);
724 }
725
726 /*
727  *      Allocate a new IDE controller emulation
728  */
729 struct ide_controller *ide_allocate(const char *name)
730 {
731   struct ide_controller *c = calloc(1, sizeof(*c));
732   if (c == NULL)
733     return NULL;
734   c->name = strdup(name);
735   if (c->name == NULL) {
736     free(c);
737     return NULL;
738   }
739   c->drive[0].controller = c;
740   c->drive[1].controller = c;
741   c->drive[0].taskfile.drive = &c->drive[0];
742   c->drive[1].taskfile.drive = &c->drive[1];
743   return c;
744 }
745
746 /*
747  *      Attach a file to a device on the controller
748  */
749 int ide_attach(struct ide_controller *c, int drive, int fd)
750 {
751   struct ide_drive *d = &c->drive[drive];
752   if (d->present) {
753     ide_fault(d, "double attach");
754     return -1;
755   }
756   d->fd = fd;
757   if (read(d->fd, d->data, 512) != 512 ||
758       read(d->fd, d->identify, 512) != 512) {
759     ide_fault(d, "i/o error on attach");
760     return -1;
761   }
762   if (memcmp(d->data, ide_magic, 8)) {
763     ide_fault(d, "bad magic");
764     return -1;
765   }
766   d->fd = fd;
767   d->present = 1;
768   d->heads = d->identify[3];
769   d->sectors = d->identify[6];
770   d->cylinders = le16(d->identify[1]);
771   d->header_present = 1;
772   if (d->identify[49] & le16(1 << 9))
773     d->lba = 1;
774   else
775     d->lba = 0;
776   return 0;
777 }
778
779 // Attach a headerless HDD image to the controller
780 int ide_attach_hdf(struct ide_controller *c, int drive, int fd)
781 {
782   struct ide_drive *d = &c->drive[drive];
783   if (d->present) {
784     printf("[IDE/HDL] Drive already attached.\n");
785     return -1;
786   }
787
788   d->fd = fd;
789   d->present = 1;
790   d->lba = 0;
791
792   d->heads = 255;
793   d->sectors = 63;
794   d->header_present = 0;
795
796   uint64_t file_size = lseek(fd, 0, SEEK_END);
797   lseek(fd, 1024, SEEK_SET);
798
799   if (file_size < 504 * SIZE_MEGA) {
800     d->heads = 16;
801   }
802   else if (file_size < 1008 * SIZE_MEGA) {
803     d->heads = 32;
804   }
805   else if (file_size < 2016 * SIZE_MEGA) {
806     d->heads = 64;
807   }
808   else if (file_size < (uint64_t)4032 * SIZE_MEGA) {
809     d->heads = 128;
810   }
811
812   d->cylinders = (file_size / 512) / (d->sectors * d->heads);
813
814   printf("[IDE/HDL] Cylinders: %d Heads: %d Sectors: %d\n", d->cylinders, d->heads, d->sectors);
815
816   if (file_size >= 4 * 1000 * 1000) {
817     d->lba = 1;
818   }
819
820   ide_make_ident(d->cylinders, d->heads, d->sectors, "PISTORM HDD IMAGE v0.1", d->identify);
821
822   return 0;
823 }
824
825 /*
826  *      Detach an IDE device from the interface (not hot pluggable)
827  */
828 void ide_detach(struct ide_drive *d)
829 {
830   close(d->fd);
831   d->fd = -1;
832   d->present = 0;
833 }
834
835 /*
836  *      Free up and release and IDE controller
837  */
838 void ide_free(struct ide_controller *c)
839 {
840   if (c->drive[0].present)
841     ide_detach(&c->drive[0]);
842   if (c->drive[1].present)
843     ide_detach(&c->drive[1]);
844   free((void *)c->name);
845   free(c);
846 }
847
848 /*
849  *      Emulation interface for an 8bit controller using latches on the
850  *      data register
851  */
852 uint8_t ide_read_latched(struct ide_controller *c, uint8_t reg)
853 {
854   uint16_t v;
855   if (reg == ide_data_latch)
856     return c->data_latch;
857   v = ide_read16(c, reg);
858   if (reg == ide_data) {
859     c->data_latch = v >> 8;
860     v &= 0xFF;
861   }
862   return v;
863 }
864
865 void ide_write_latched(struct ide_controller *c, uint8_t reg, uint8_t v)
866 {
867   uint16_t d = v;
868
869   if (reg == ide_data_latch) {
870     c->data_latch = v;
871     return;
872   }
873   if (reg == ide_data)
874     d |=  (c->data_latch << 8);
875   ide_write16(c, reg, d);
876 }
877
878 static void make_ascii(uint16_t *p, const char *t, int len)
879 {
880   int i;
881   char *d = (char *)p;
882 //  strncpy(d, t, len);
883 #pragma GCC diagnostic push
884 #pragma GCC diagnostic ignored "-Wstringop-truncation"
885   strncpy(d, t, len);
886 #pragma GCC diagnostic pop
887
888   for (i = 0; i < len; i += 2) {
889     char c = *d;
890     *d = d[1];
891     d[1] = c;
892     d += 2;
893   }
894 }
895
896 static void make_serial(uint16_t *p)
897 {
898   char buf[21];
899   srand(getpid()^time(NULL));
900   snprintf(buf, 21, "%08d%08d%04d", rand(), rand(), rand());
901   make_ascii(p, buf, 20);
902 }
903
904 int ide_make_ident(uint16_t c, uint8_t h, uint8_t s, char *name, uint16_t *target)
905 {
906   uint16_t *ident = target;
907   uint32_t sectors;
908
909   memset(ident, 0, 512);
910   memcpy(ident, ide_magic, 8);
911
912   memset(ident, 0, 8);
913   ident[0] = le16((1 << 15) | (1 << 6));        /* Non removable */
914   make_serial(ident + 10);
915   ident[47] = 0; /* no read multi for now */
916   ident[51] = le16(240 /* PIO2 */ << 8);        /* PIO cycle time */
917   ident[53] = le16(1);          /* Geometry words are valid */
918
919   make_ascii(ident + 23, "A001.001", 8);
920   make_ascii(ident + 27, name, 40);
921   ident[49] = le16(1 << 9); /* LBA */
922
923   ident[1] = le16(c);
924   ident[3] = le16(h);
925   ident[6] = le16(s);
926   ident[54] = ident[1];
927   ident[55] = ident[3];
928   ident[56] = ident[6];
929   sectors = c * h * s;
930   ident[57] = le16(sectors & 0xFFFF);
931   ident[58] = le16(sectors >> 16);
932   ident[60] = ident[57];
933   ident[61] = ident[58];
934
935   return 0;
936 }
937
938 int ide_make_drive(uint8_t type, int fd)
939 {
940   uint8_t s, h;
941   uint16_t c;
942   uint32_t sectors;
943   uint16_t ident[256];
944
945   if (type < 1 || type > MAX_DRIVE_TYPE)
946     return -2;
947
948   memset(ident, 0, 512);
949   memcpy(ident, ide_magic, 8);
950   if (write(fd, ident, 512) != 512)
951     return -1;
952
953   memset(ident, 0, 8);
954   ident[0] = le16((1 << 15) | (1 << 6));        /* Non removable */
955   make_serial(ident + 10);
956   ident[47] = 0; /* no read multi for now */
957   ident[51] = le16(240 /* PIO2 */ << 8);        /* PIO cycle time */
958   ident[53] = le16(1);          /* Geometry words are valid */
959
960   switch(type) {
961     case ACME_ROADRUNNER:
962       /* 504MB drive with LBA support */
963       c = 1024;
964       h = 16;
965       s = 63;
966       make_ascii(ident + 23, "A001.001", 8);
967       make_ascii(ident + 27, "ACME ROADRUNNER v0.1", 40);
968       ident[49] = le16(1 << 9); /* LBA */
969       break;
970     case ACME_ULTRASONICUS:
971       /* 40MB drive with LBA support */
972       c = 977;
973       h = 5;
974       s = 16;
975       ident[49] = le16(1 << 9); /* LBA */
976       make_ascii(ident + 23, "A001.001", 8);
977       make_ascii(ident + 27, "ACME ULTRASONICUS AD INFINITUM v0.1", 40);
978       break;
979     case ACME_NEMESIS:
980       /* 20MB drive with LBA support */
981       c = 615;
982       h = 4;
983       s = 16;
984       ident[49] = le16(1 << 9); /* LBA */
985       make_ascii(ident + 23, "A001.001", 8);
986       make_ascii(ident + 27, "ACME NEMESIS RIDICULII v0.1", 40);
987       break;
988     case ACME_COYOTE:
989       /* 20MB drive without LBA support */
990       c = 615;
991       h = 4;
992       s = 16;
993       make_ascii(ident + 23, "A001.001", 8);
994       make_ascii(ident + 27, "ACME COYOTE v0.1", 40);
995       break;
996     case ACME_ACCELLERATTI:
997       c = 1024;
998       h = 16;
999       s = 16;
1000       ident[49] = le16(1 << 9); /* LBA */
1001       make_ascii(ident + 23, "A001.001", 8);
1002       make_ascii(ident + 27, "ACME ACCELLERATTI INCREDIBILUS v0.1", 40);
1003       break;
1004     case ACME_ZIPPIBUS:
1005       c = 1024;
1006       h = 16;
1007       s = 32;
1008       ident[49] = le16(1 << 9); /* LBA */
1009       make_ascii(ident + 23, "A001.001", 8);
1010       make_ascii(ident + 27, "ACME ZIPPIBUS v0.1", 40);
1011       break;
1012   }
1013   ident[1] = le16(c);
1014   ident[3] = le16(h);
1015   ident[6] = le16(s);
1016   ident[54] = ident[1];
1017   ident[55] = ident[3];
1018   ident[56] = ident[6];
1019   sectors = c * h * s;
1020   ident[57] = le16(sectors & 0xFFFF);
1021   ident[58] = le16(sectors >> 16);
1022   ident[60] = ident[57];
1023   ident[61] = ident[58];
1024   if (write(fd, ident, 512) != 512)
1025     return -1;
1026
1027   memset(ident, 0xE5, 512);
1028   while(sectors--)
1029     if (write(fd, ident, 512) != 512)
1030       return -1;
1031   return 0;
1032 }