fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/devices/hdc.c *
7 * Created: 2011-09-11 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 2011-2013 Hampa Hug <hampa@hampa.ch> *
9 *****************************************************************************/
10
11/*****************************************************************************
12 * This program is free software. You can redistribute it and / or modify it *
13 * under the terms of the GNU General Public License version 2 as published *
14 * by the Free Software Foundation. *
15 * *
16 * This program is distributed in the hope that it will be useful, but *
17 * WITHOUT ANY WARRANTY, without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General *
19 * Public License for more details. *
20 *****************************************************************************/
21
22/* IBM XT hard disk controller */
23
24
25#include <stdlib.h>
26#include <string.h>
27
28#include <devices/hdc.h>
29#include <devices/memory.h>
30
31#include <lib/log.h>
32
33
34#ifndef DEBUG_HDC
35#define DEBUG_HDC 0
36#endif
37
38
39#define HDC_STATUS_REQ 0x01
40#define HDC_STATUS_INP 0x02
41#define HDC_STATUS_CMD 0x04
42#define HDC_STATUS_BSY 0x08
43#define HDC_STATUS_DRQ 0x10
44#define HDC_STATUS_INT 0x20
45
46#define HDC_MASK_DRQ 0x01
47#define HDC_MASK_IRQ 0x02
48
49
50#if DEBUG_HDC >= 1
51static
52void hdc_print_hex (FILE *fp, const char *tag, const unsigned char *buf, unsigned cnt)
53{
54 unsigned i;
55
56 if (tag != NULL) {
57 fputs (tag, fp);
58 }
59
60 for (i = 0; i < cnt; i++) {
61 if ((i & 7) == 0) {
62 fputs ("\n\t", fp);
63 }
64
65 fprintf (fp, " %02X", buf[i]);
66 }
67
68 fputc ('\n', fp);
69}
70#endif
71
72static
73void hdc_set_irq (hdc_t *hdc, unsigned char val)
74{
75 if ((hdc->mask & HDC_MASK_IRQ) == 0) {
76 val = 0;
77 }
78 else {
79 val = (val != 0);
80 }
81
82 if (val) {
83 hdc->status |= HDC_STATUS_INT;
84 }
85 else {
86 hdc->status &= ~HDC_STATUS_INT;
87 }
88
89 if (hdc->irq_val != val) {
90 hdc->irq_val = val;
91
92 if (hdc->irq != NULL) {
93 hdc->irq (hdc->irq_ext, val);
94 }
95 }
96}
97
98static
99void hdc_set_dreq (hdc_t *hdc, unsigned char val)
100{
101 val = (val != 0);
102
103 if (val) {
104 hdc->status |= HDC_STATUS_DRQ;
105 }
106 else {
107 hdc->status &= ~HDC_STATUS_DRQ;
108 }
109
110 if (hdc->dreq_val != val) {
111 hdc->dreq_val = val;
112
113 if ((hdc->mask & HDC_MASK_DRQ) == 0) {
114 return;
115 }
116
117 if (hdc->dreq != NULL) {
118 hdc->dreq (hdc->dreq_ext, val);
119 }
120 }
121}
122
123static
124void hdc_request_command (hdc_t *hdc)
125{
126 hdc->status |= HDC_STATUS_REQ | HDC_STATUS_BSY | HDC_STATUS_CMD;
127 hdc->status &= ~HDC_STATUS_INP;
128}
129
130static
131void hdc_request_data (hdc_t *hdc, int inp)
132{
133 hdc->status |= HDC_STATUS_REQ | HDC_STATUS_BSY;
134 hdc->status &= ~(HDC_STATUS_INP | HDC_STATUS_CMD);
135
136 if (inp) {
137 hdc->status |= HDC_STATUS_INP;
138 }
139
140 hdc_set_dreq (hdc, 1);
141}
142
143static
144void hdc_request_status (hdc_t *hdc)
145{
146 hdc->status |= HDC_STATUS_REQ | HDC_STATUS_BSY;
147 hdc->status |= HDC_STATUS_INP | HDC_STATUS_CMD;
148
149 hdc->delay = 0;
150 hdc->cont = NULL;
151
152 hdc_set_dreq (hdc, 0);
153 hdc_set_irq (hdc, 1);
154}
155
156static
157void hdc_next_id (hdc_t *hdc)
158{
159 hdc_drive_t *d;
160
161 d = &hdc->drv[hdc->id.d & 1];
162
163 hdc->id.s += 1;
164
165 if (hdc->id.s >= d->max_s) {
166 hdc->id.s = 0;
167 hdc->id.h += 1;
168
169 if (hdc->id.h >= d->max_h) {
170 hdc->id.h = 0;
171 hdc->id.c += 1;
172 }
173 }
174}
175
176static
177disk_t *hdc_get_disk (hdc_t *hdc, unsigned drv)
178{
179 unsigned d;
180 disk_t *dsk;
181
182 d = hdc->drv[drv & 1].drive;
183
184 if (d == 0xffff) {
185 return (NULL);
186 }
187
188 dsk = dsks_get_disk (hdc->dsks, d);
189
190 return (dsk);
191}
192
193static
194void hdc_set_result (hdc_t *hdc, int err, unsigned code)
195{
196 unsigned d;
197
198 d = hdc->id.d & 1;
199
200 hdc->result = d << 5;
201
202 if (err) {
203 hdc->result |= 0x02;
204 }
205
206 hdc->drv[d].sense[0] = code;
207 hdc->drv[d].sense[1] = (d << 5) | (hdc->id.h & 0x1f);
208 hdc->drv[d].sense[2] = (hdc->id.c >> 2) & 0xc0;
209 hdc->drv[d].sense[3] = hdc->id.c & 0xff;
210}
211
212/* normal command termination */
213static
214void hdc_cmd_done (hdc_t *hdc)
215{
216 hdc_request_status (hdc);
217}
218
219
220/* Command 00: test drive ready */
221
222static
223void hdc_cmd_tst_rdy (hdc_t *hdc)
224{
225 hdc->id.d = (hdc->cmd[1] >> 5) & 1;
226
227#if DEBUG_HDC >= 1
228 fprintf (stderr, "HDC: CMD=%02X D=%u test drive ready\n",
229 hdc->cmd[0], hdc->id.d
230 );
231#endif
232
233 if (hdc_get_disk (hdc, hdc->id.d) == NULL) {
234 hdc_set_result (hdc, 1, 0x20);
235 hdc->delay = 256;
236 }
237 else {
238 hdc_set_result (hdc, 0, 0x00);
239 hdc->delay = 4096;
240 }
241
242 hdc->cont = hdc_cmd_done;
243}
244
245
246/* Command 01: recalibrate */
247
248static
249void hdc_cmd_recal (hdc_t *hdc)
250{
251 hdc->id.d = (hdc->cmd[1] >> 5) & 1;
252
253#if DEBUG_HDC >= 1
254 fprintf (stderr, "HDC: CMD=%02X D=%u recalibrate\n",
255 hdc->cmd[0], hdc->id.d
256 );
257#endif
258
259 if (hdc_get_disk (hdc, hdc->id.d) == NULL) {
260 hdc_set_result (hdc, 1, 0x20);
261 hdc->delay = 512;
262 }
263 else {
264 hdc_set_result (hdc, 0, 0x00);
265 hdc->delay = 65536;
266 }
267
268 hdc->cont = hdc_cmd_done;
269}
270
271
272/* Command 03: sense */
273
274static
275void hdc_cmd_sense_cont (hdc_t *hdc)
276{
277 unsigned d;
278
279 d = (hdc->cmd[1] >> 5) & 1;
280
281 hdc->buf[0] = hdc->drv[d].sense[0];
282 hdc->buf[1] = hdc->drv[d].sense[1];
283 hdc->buf[2] = hdc->drv[d].sense[2];
284 hdc->buf[3] = hdc->drv[d].sense[3];
285
286 hdc->buf_idx = 0;
287 hdc->buf_cnt = 4;
288
289 hdc_set_result (hdc, 0, 0x00);
290
291 hdc->delay = 0;
292 hdc->cont = hdc_cmd_done;
293
294 hdc_request_data (hdc, 1);
295}
296
297static
298void hdc_cmd_sense (hdc_t *hdc)
299{
300 hdc->id.d = (hdc->cmd[1] >> 5) & 1;
301
302#if DEBUG_HDC >= 1
303 fprintf (stderr, "HDC: CMD=%02X D=%u sense\n",
304 hdc->cmd[0], hdc->id.d
305 );
306#endif
307
308 hdc->delay = 256;
309 hdc->cont = hdc_cmd_sense_cont;
310}
311
312
313/* Command 04: format drive */
314
315static
316void hdc_cmd_fmtdrv_error (hdc_t *hdc, unsigned code)
317{
318 fprintf (stderr, "hdc: format error (d=%u)\n", hdc->id.d);
319
320 hdc_set_result (hdc, hdc->id.d, code | 0x80);
321
322 hdc_cmd_done (hdc);
323}
324
325static
326void hdc_cmd_fmtdrv_cont (hdc_t *hdc)
327{
328 unsigned i, d, c, h, cn, hn, sn;
329 unsigned char buf[512];
330 disk_t *dsk;
331
332 d = hdc->id.d & 1;
333 c = hdc->id.c;
334 h = hdc->id.h;
335
336 cn = hdc->drv[d].max_c;
337 hn = hdc->drv[d].max_h;
338 sn = hdc->drv[d].max_s;
339
340 dsk = hdc_get_disk (hdc, d);
341
342 if (dsk == NULL) {
343 hdc_cmd_fmtdrv_error (hdc, 0x04);
344 return;
345 }
346
347 if (hdc->cmd[5] & 0x40) {
348 for (i = 0; i < 512; i++) {
349 buf[i] = hdc->buf[i];
350 }
351 }
352 else {
353 for (i = 0; i < 512; i++) {
354 buf[i] = 0x6c;
355 }
356 }
357
358#if DEBUG_HDC >= 2
359 fprintf (stderr, "HDC: CMD=%02X D=%u format track (c=%u h=%u n=%u)\n",
360 hdc->cmd[0], d, c, h, sn
361 );
362#endif
363
364 for (i = 0; i < sn; i++) {
365 if (dsk_write_chs (dsk, buf, c, h, i + 1, 1)) {
366 hdc_cmd_fmtdrv_error (hdc, 0x03);
367 return;
368 }
369 }
370
371 hdc->delay = 8192;
372 hdc->cont = hdc_cmd_fmtdrv_cont;
373
374 h += 1;
375
376 if (h >= hn) {
377 h = 0;
378
379 c += 1;
380
381 if (c >= cn) {
382 hdc->cont = hdc_cmd_done;
383 }
384 }
385
386 hdc->id.c = c;
387 hdc->id.h = h;
388}
389
390static
391void hdc_cmd_fmtdrv (hdc_t *hdc)
392{
393 hdc->id.d = (hdc->cmd[1] >> 5) & 1;
394 hdc->id.c = ((hdc->cmd[2] << 2) & 0x300) | hdc->cmd[3];
395 hdc->id.h = hdc->cmd[1] & 0x1f;
396 hdc->id.n = hdc->cmd[4] & 0x1f;
397
398#if DEBUG_HDC >= 1
399 fprintf (stderr, "HDC: CMD=%02X D=%u format drive (c=%u h=%u il=%u)\n",
400 hdc->cmd[0], hdc->id.d, hdc->id.c, hdc->id.h, hdc->id.n
401 );
402#endif
403
404 hdc->result = 0;
405
406 hdc->delay = 4096;
407 hdc->cont = hdc_cmd_fmtdrv_cont;
408}
409
410
411/* Command 05: verify */
412
413static
414void hdc_cmd_chk_trk (hdc_t *hdc)
415{
416 hdc->id.d = (hdc->cmd[1] >> 5) & 1;
417 hdc->id.c = ((hdc->cmd[2] << 2) & 0x300) | hdc->cmd[3];
418 hdc->id.h = hdc->cmd[1] & 0x1f;
419 hdc->id.s = hdc->cmd[2] & 0x3f;
420 hdc->id.n = hdc->cmd[4];
421
422#if DEBUG_HDC >= 1
423 fprintf (stderr, "HDC: CMD=%02X D=%u verify (chs=%u/%u/%u n=%u)\n",
424 hdc->cmd[0], hdc->id.d,
425 hdc->id.c, hdc->id.h, hdc->id.s + 1, hdc->id.n
426 );
427#endif
428
429 hdc->result = 0;
430
431 hdc->delay = 65536;
432 hdc->cont = hdc_cmd_done;
433}
434
435
436/* Command 06: format track */
437
438static
439void hdc_cmd_fmttrk_error (hdc_t *hdc, unsigned code)
440{
441 fprintf (stderr, "hdc: format track error (d=%u)\n", hdc->id.d);
442
443 hdc_set_result (hdc, hdc->id.d, code | 0x80);
444
445 hdc_cmd_done (hdc);
446}
447
448static
449void hdc_cmd_fmttrk (hdc_t *hdc)
450{
451 unsigned i, d;
452 unsigned char buf[512];
453 disk_t *dsk;
454
455 hdc->id.d = (hdc->cmd[1] >> 5) & 1;
456 hdc->id.c = ((hdc->cmd[2] << 2) & 0x300) | hdc->cmd[3];
457 hdc->id.h = hdc->cmd[1] & 0x1f;
458 hdc->id.n = hdc->cmd[4] & 0x1f;
459
460#if DEBUG_HDC >= 1
461 fprintf (stderr, "HDC: CMD=%02X D=%u format track (c=%u h=%u il=%u)\n",
462 hdc->cmd[0], hdc->id.d, hdc->id.c, hdc->id.h, hdc->id.n
463 );
464#endif
465
466 d = hdc->id.d & 1;
467
468 dsk = hdc_get_disk (hdc, d);
469
470 if (dsk == NULL) {
471 hdc_cmd_fmttrk_error (hdc, 0x04);
472 return;
473 }
474
475 if (hdc->cmd[5] & 0x40) {
476 for (i = 0; i < 512; i++) {
477 buf[i] = hdc->buf[i];
478 }
479 }
480 else {
481 for (i = 0; i < 512; i++) {
482 buf[i] = 0x6c;
483 }
484 }
485
486 for (i = 0; i < hdc->drv[d].max_s; i++) {
487 if (dsk_write_chs (dsk, buf, hdc->id.c, hdc->id.h, i + 1, 1)) {
488 hdc_cmd_fmttrk_error (hdc, 0x03);
489 return;
490 }
491 }
492
493 hdc->result = 0;
494
495 hdc->delay = 65536;
496 hdc->cont = hdc_cmd_done;
497}
498
499
500/* Command 08: read */
501
502static void hdc_cmd_read_next (hdc_t *hdc);
503
504static
505void hdc_cmd_read_error (hdc_t *hdc, unsigned code)
506{
507 fprintf (stderr, "hdc: read error (d=%u)\n", hdc->id.d);
508
509 hdc_set_result (hdc, 1, code | 0x80);
510
511 hdc_cmd_done (hdc);
512}
513
514static
515void hdc_cmd_read_delay (hdc_t *hdc)
516{
517 hdc_set_dreq (hdc, 0);
518
519 if (hdc->id.n == 0) {
520 hdc_cmd_done (hdc);
521 return;
522 }
523
524 hdc->delay = 2048;
525 hdc->cont = hdc_cmd_read_next;
526}
527
528static
529void hdc_cmd_read_next (hdc_t *hdc)
530{
531 unsigned d, c, h, s;
532 disk_t *dsk;
533
534 d = hdc->id.d & 1;
535 c = hdc->id.c;
536 h = hdc->id.h;
537 s = hdc->id.s;
538
539 dsk = hdc_get_disk (hdc, d);
540
541 if (dsk == NULL) {
542 hdc_cmd_read_error (hdc, 0x04);
543 return;
544 }
545
546#if DEBUG_HDC >= 2
547 fprintf (stderr, "HDC: CMD=%02X D=%u read sector (chs=%u/%u/%u)\n",
548 hdc->cmd[0], d, c, h, s + 1
549 );
550#endif
551
552 if (dsk_read_chs (dsk, hdc->buf, c, h, s + 1, 1)) {
553 hdc_cmd_read_error (hdc, 0x12);
554 return;
555 }
556
557 hdc->buf_idx = 0;
558 hdc->buf_cnt = 512;
559
560 hdc_next_id (hdc);
561
562 hdc->id.n -= 1;
563
564 hdc->delay = 0;
565 hdc->cont = hdc_cmd_read_delay;
566
567 hdc_request_data (hdc, 1);
568}
569
570static
571void hdc_cmd_read (hdc_t *hdc)
572{
573 hdc->id.d = (hdc->cmd[1] >> 5) & 1;
574 hdc->id.c = ((hdc->cmd[2] << 2) & 0x300) | hdc->cmd[3];
575 hdc->id.h = hdc->cmd[1] & 0x1f;
576 hdc->id.s = hdc->cmd[2] & 0x3f;
577 hdc->id.n = hdc->cmd[4];
578
579 if (hdc->id.n == 0) {
580 hdc->id.n = 256;
581 }
582
583#if DEBUG_HDC >= 1
584 fprintf (stderr, "HDC: CMD=%02X D=%u read (chs=%u/%u/%u n=%u)\n",
585 hdc->cmd[0], hdc->id.d,
586 hdc->id.c, hdc->id.h, hdc->id.s + 1, hdc->id.n
587 );
588#endif
589
590 hdc->delay = 4096;
591 hdc->cont = hdc_cmd_read_next;
592}
593
594
595/* Command 0A: write */
596
597static void hdc_cmd_write_next (hdc_t *hdc);
598
599static
600void hdc_cmd_write_error (hdc_t *hdc, unsigned code)
601{
602 fprintf (stderr, "hdc: write error (d=%u)\n", hdc->id.d);
603
604 hdc_set_result (hdc, 1, code | 0x80);
605
606 hdc_cmd_done (hdc);
607}
608
609static
610void hdc_cmd_write_delay (hdc_t *hdc)
611{
612 hdc->buf_idx = 0;
613 hdc->buf_cnt = 512;
614
615 hdc->delay = 0;
616 hdc->cont = hdc_cmd_write_next;
617
618 hdc_request_data (hdc, 0);
619}
620
621static
622void hdc_cmd_write_next (hdc_t *hdc)
623{
624 unsigned d, c, h, s;
625 disk_t *dsk;
626
627 d = hdc->id.d & 1;
628 c = hdc->id.c;
629 h = hdc->id.h;
630 s = hdc->id.s;
631
632 dsk = hdc_get_disk (hdc, d);
633
634 if (dsk == NULL) {
635 hdc_cmd_write_error (hdc, 0x04);
636 return;
637 }
638
639#if DEBUG_HDC >= 2
640 fprintf (stderr, "HDC: CMD=%02X D=%u write sector (chs=%u/%u/%u)\n",
641 hdc->cmd[0], d, c, h, s + 1
642 );
643#endif
644
645 if (dsk_write_chs (dsk, hdc->buf, c, h, s + 1, 1)) {
646 hdc_cmd_write_error (hdc, 0x12);
647 return;
648 }
649
650 hdc_next_id (hdc);
651
652 hdc->id.n -= 1;
653
654 if (hdc->id.n == 0) {
655 hdc_cmd_done (hdc);
656 return;
657 }
658
659 hdc->delay = 2048;
660 hdc->cont = hdc_cmd_write_delay;
661
662 hdc_set_dreq (hdc, 0);
663}
664
665static
666void hdc_cmd_write (hdc_t *hdc)
667{
668 hdc->id.d = (hdc->cmd[1] >> 5) & 1;
669 hdc->id.c = ((hdc->cmd[2] << 2) & 0x300) | hdc->cmd[3];
670 hdc->id.h = hdc->cmd[1] & 0x1f;
671 hdc->id.s = hdc->cmd[2] & 0x3f;
672 hdc->id.n = hdc->cmd[4];
673
674 if (hdc->id.n == 0) {
675 hdc->id.n = 256;
676 }
677
678#if DEBUG_HDC >= 1
679 fprintf (stderr, "HDC: CMD=%02X D=%u write (chs=%u/%u/%u n=%u)\n",
680 hdc->cmd[0], hdc->id.d,
681 hdc->id.c, hdc->id.h, hdc->id.s + 1, hdc->id.n
682 );
683#endif
684
685 hdc->delay = 4096;
686 hdc->cont = hdc_cmd_write_delay;
687}
688
689
690/* Command 0B: seek */
691
692static
693void hdc_cmd_seek (hdc_t *hdc)
694{
695 hdc->id.d = (hdc->cmd[1] >> 5) & 1;
696 hdc->id.c = ((hdc->cmd[2] << 2) & 0x300) | hdc->cmd[3];
697 hdc->id.h = hdc->cmd[1] & 0x1f;
698
699#if DEBUG_HDC >= 1
700 fprintf (stderr, "HDC: CMD=%02X D=%u seek (c=%u h=%u)\n",
701 hdc->cmd[0], hdc->id.d, hdc->id.c, hdc->id.h
702 );
703#endif
704
705 if (hdc_get_disk (hdc, hdc->id.d) == NULL) {
706 hdc_set_result (hdc, 1, 0x04);
707 hdc->delay = 512;
708 }
709 else {
710 hdc_set_result (hdc, 0, 0x00);
711 hdc->delay = 65536;
712 }
713
714 hdc->cont = hdc_cmd_done;
715}
716
717
718/* Command 0C: init drive */
719
720static
721void hdc_cmd_init_cont2 (hdc_t *hdc)
722{
723 unsigned d, c, h, s, rc, wp, ec;
724 unsigned long size;
725
726 d = (hdc->cmd[1] >> 5) & 1;
727 c = (hdc->buf[0] << 8) | hdc->buf[1];
728 h = hdc->buf[2];
729 s = hdc->drv[d].max_s;
730 rc = (hdc->buf[3] << 8) | hdc->buf[4];
731 wp = (hdc->buf[5] << 8) | hdc->buf[6];
732 ec = hdc->buf[7];
733
734 size = (unsigned long) c * (unsigned long) h * s;
735
736 pce_log_tag (MSG_INF,
737 "HDC:",
738 "init drive %u (c=%u h=%u s=%u rc=%u wp=%u ecc=%u size=%lu.%uK)\n",
739 d, c, h, s, rc, wp, ec, size / 2, (size & 1) ? 5 : 0
740 );
741
742#if DEBUG_HDC >= 1
743 fprintf (stderr, "HDC: CMD=%02X D=%u init (c=%u h=%u s=%u rc=%u wp=%u ecc=%u)\n",
744 hdc->cmd[0], d, c, h, s, rc, wp, ec
745 );
746#endif
747
748 hdc->drv[d].max_c = c;
749 hdc->drv[d].max_h = h;
750
751 hdc_set_result (hdc, 0, 0x00);
752
753 hdc_cmd_done (hdc);
754}
755
756static
757void hdc_cmd_init_cont1 (hdc_t *hdc)
758{
759 hdc->delay = 0;
760 hdc->cont = hdc_cmd_init_cont2;
761
762 hdc_request_data (hdc, 0);
763}
764
765static
766void hdc_cmd_init (hdc_t *hdc)
767{
768 hdc->id.d = (hdc->cmd[1] >> 5) & 1;
769
770 hdc->buf_idx = 0;
771 hdc->buf_cnt = 8;
772
773 hdc->delay = 512;
774 hdc->cont = hdc_cmd_init_cont1;
775}
776
777
778/* Command 0E: read buffer */
779
780static
781void hdc_cmd_rd_buf (hdc_t *hdc)
782{
783#if DEBUG_HDC >= 1
784 fprintf (stderr, "HDC: CMD=%02X D=* read buffer\n",
785 hdc->cmd[0]
786 );
787#endif
788
789 hdc->buf_idx = 0;
790 hdc->buf_cnt = 512;
791
792 hdc_set_result (hdc, 0, 0x00);
793
794 hdc->delay = 0;
795 hdc->cont = hdc_cmd_done;
796
797 hdc_request_data (hdc, 1);
798}
799
800
801/* Command 0F: write buffer */
802
803static
804void hdc_cmd_wr_buf_delay (hdc_t *hdc)
805{
806 hdc->buf_idx = 0;
807 hdc->buf_cnt = 512;
808
809 hdc->delay = 0;
810 hdc->cont = hdc_cmd_done;
811
812 hdc_set_result (hdc, 0, 0x00);
813
814 hdc_request_data (hdc, 0);
815}
816
817static
818void hdc_cmd_wr_buf (hdc_t *hdc)
819{
820#if DEBUG_HDC >= 1
821 fprintf (stderr, "HDC: CMD=%02X D=* write buffer\n",
822 hdc->cmd[0]
823 );
824#endif
825
826 hdc->delay = 4096;
827 hdc->cont = hdc_cmd_wr_buf_delay;
828}
829
830
831/* Command 11: unknown (Adaptec) */
832
833static
834void hdc_cmd_11 (hdc_t *hdc)
835{
836 hdc->id.d = (hdc->cmd[1] >> 5) & 1;
837
838#if DEBUG_HDC >= 1
839 fprintf (stderr, "HDC: CMD=%02X D=%u cmd_11\n",
840 hdc->cmd[0], hdc->id.d
841 );
842#endif
843
844 hdc_set_result (hdc, 0, 0x00);
845
846 hdc->delay = 4096;
847 hdc->cont = hdc_cmd_done;
848}
849
850
851/* Command 15: set mode (Adaptec) */
852
853static
854void hdc_cmd_set_mode_cont (hdc_t *hdc)
855{
856 unsigned d, c, h, s, rc, wp, ec, sr;
857 unsigned long size;
858
859#if DEBUG_HDC >= 1
860 hdc_print_hex (stderr, "mode:", hdc->buf, 12);
861#endif
862
863 d = hdc->id.d;
864 c = buf_get_uint16_be (hdc->buf, 1);
865 h = buf_get_uint8 (hdc->buf, 3);
866 s = hdc->drv[d].max_s;
867 rc = buf_get_uint16_be (hdc->buf, 4);
868 wp = buf_get_uint16_be (hdc->buf, 6);
869 ec = buf_get_uint8 (hdc->buf, 8);
870 sr = buf_get_uint8 (hdc->buf, 10);
871
872 size = (unsigned long) c * (unsigned long) h * s;
873
874 pce_log_tag (MSG_INF,
875 "HDC:",
876 "set mode drive %u (c=%u h=%u s=%u rc=%u wp=%u ecc=%u sr=%u size=%lu.%uK)\n",
877 d, c, h, s, rc, wp, ec, sr, size / 2, (size & 1) ? 5 : 0
878 );
879
880 hdc_set_result (hdc, 0, 0x00);
881
882 hdc_cmd_done (hdc);
883}
884
885static
886void hdc_cmd_set_mode_delay (hdc_t *hdc)
887{
888 hdc->buf_idx = 0;
889 hdc->buf_cnt = 12;
890
891 hdc->delay = 0;
892 hdc->cont = hdc_cmd_set_mode_cont;
893
894 hdc_request_data (hdc, 0);
895}
896
897static
898void hdc_cmd_set_mode (hdc_t *hdc)
899{
900 hdc->id.d = (hdc->cmd[1] >> 5) & 1;
901
902#if DEBUG_HDC >= 1
903 fprintf (stderr, "HDC: CMD=%02X D=%u set mode\n",
904 hdc->cmd[0], hdc->id.d
905 );
906#endif
907
908 hdc->delay = 2048;
909 hdc->cont = hdc_cmd_set_mode_delay;
910
911 hdc_set_dreq (hdc, 0);
912}
913
914
915/* Command 1A: mode sense (Adaptec) */
916
917static
918void hdc_cmd_mode_sense_cont (hdc_t *hdc)
919{
920 unsigned c, h, s;
921 disk_t *dsk;
922
923 dsk = dsks_get_disk (hdc->dsks, hdc->drv[hdc->id.d].drive);
924
925 if (dsk == NULL) {
926 c = 0;
927 h = 0;
928 s = hdc->sectors;
929 }
930 else {
931 c = dsk->c;
932 h = dsk->h;
933 s = dsk->s;
934 }
935
936 hdc->drv[hdc->id.d].max_c = c;
937 hdc->drv[hdc->id.d].max_h = h;
938 hdc->drv[hdc->id.d].max_s = s;
939
940#if DEBUG_HDC >= 1
941 fprintf (stderr, "HDC: CMD=%02X D=%u mode sense (chs=%u/%u/%u ecc=8)\n",
942 hdc->cmd[0], hdc->id.d, c, h, s
943 );
944#endif
945
946 buf_set_uint8 (hdc->buf, 0, 0x02);
947 buf_set_uint16_be (hdc->buf, 1, c);
948 buf_set_uint8 (hdc->buf, 3, h);
949 buf_set_uint16_be (hdc->buf, 4, c);
950 buf_set_uint16_be (hdc->buf, 6, c);
951 buf_set_uint8 (hdc->buf, 8, 0x08);
952 buf_set_uint8 (hdc->buf, 9, 0x00);
953 buf_set_uint8 (hdc->buf, 10, 0x03);
954 buf_set_uint8 (hdc->buf, 11, 0x01);
955
956 hdc->buf_idx = 0;
957 hdc->buf_cnt = 12;
958
959 hdc_set_result (hdc, 0, 0x00);
960
961 hdc->delay = 0;
962 hdc->cont = hdc_cmd_done;
963
964 hdc_request_data (hdc, 1);
965}
966
967static
968void hdc_cmd_mode_sense (hdc_t *hdc)
969{
970 hdc->id.d = (hdc->cmd[1] >> 5) & 1;
971
972#if DEBUG_HDC >= 2
973 fprintf (stderr, "HDC: CMD=%02X D=%u mode sense\n",
974 hdc->cmd[0], hdc->id.d
975 );
976#endif
977
978 hdc->delay = 4096;
979 hdc->cont = hdc_cmd_mode_sense_cont;
980}
981
982
983/* Command E0: ram diagnostics */
984
985static
986void hdc_cmd_ram_diag (hdc_t *hdc)
987{
988#if DEBUG_HDC >= 1
989 fprintf (stderr, "HDC: CMD=%02X D=* ram diagnostics\n",
990 hdc->cmd[0]
991 );
992#endif
993
994 hdc_set_result (hdc, 0, 0x00);
995
996 hdc->delay = 4096;
997 hdc->cont = hdc_cmd_done;
998}
999
1000
1001/* Command E4: controller diagnostics */
1002
1003static
1004void hdc_cmd_cntlr_diag (hdc_t *hdc)
1005{
1006#if DEBUG_HDC >= 1
1007 fprintf (stderr, "HDC: CMD=%02X D=* controller diagnostics\n",
1008 hdc->cmd[0]
1009 );
1010#endif
1011
1012 hdc_set_result (hdc, 0, 0x00);
1013
1014 hdc->delay = 4096;
1015 hdc->cont = hdc_cmd_done;
1016}
1017
1018
1019/* Command FB: get drive geometry */
1020
1021static
1022void hdc_cmd_getgeo_cont (hdc_t *hdc)
1023{
1024 unsigned c, h, s;
1025 disk_t *dsk;
1026
1027 dsk = dsks_get_disk (hdc->dsks, hdc->drv[hdc->id.d].drive);
1028
1029 if (dsk == NULL) {
1030 c = 0;
1031 h = 0;
1032 s = hdc->sectors;
1033 }
1034 else {
1035 c = dsk->c - 1;
1036 h = dsk->h - 1;
1037 s = dsk->s;
1038 }
1039
1040#if DEBUG_HDC >= 1
1041 fprintf (stderr, "HDC: CMD=%02X D=%u get drive geometry (c=%u h=%u s=%u)\n",
1042 hdc->cmd[0], hdc->id.d, c + 1, h + 1, s
1043 );
1044#endif
1045
1046 hdc->drv[hdc->id.d].max_s = s;
1047
1048 hdc->buf[0] = c & 0xff;
1049 hdc->buf[1] = ((c >> 2) & 0xc0) | (s & 0x3f);
1050 hdc->buf[2] = h;
1051 hdc->buf[3] = 0x00;
1052
1053 hdc->buf_idx = 0;
1054 hdc->buf_cnt = 4;
1055
1056 hdc_set_result (hdc, 0, 0x00);
1057
1058 hdc->delay = 0;
1059 hdc->cont = hdc_cmd_done;
1060
1061 hdc_request_data (hdc, 1);
1062}
1063
1064static
1065void hdc_cmd_getgeo (hdc_t *hdc)
1066{
1067 hdc->id.d = (hdc->cmd[1] >> 5) & 1;
1068
1069 hdc->delay = 4096;
1070 hdc->cont = hdc_cmd_getgeo_cont;
1071}
1072
1073
1074/* Command FC: unknown */
1075
1076static
1077void hdc_cmd_fc (hdc_t *hdc)
1078{
1079 hdc->id.d = (hdc->cmd[1] >> 5) & 1;
1080
1081#if DEBUG_HDC >= 1
1082 fprintf (stderr, "HDC: CMD=%02X D=%u cmd_fc\n",
1083 hdc->cmd[0], hdc->id.d
1084 );
1085#endif
1086
1087 hdc_set_result (hdc, 0, 0x00);
1088
1089 hdc->delay = 4096;
1090 hdc->cont = hdc_cmd_done;
1091}
1092
1093
1094/* Command FD: unknown */
1095
1096static
1097void hdc_cmd_fd (hdc_t *hdc)
1098{
1099 hdc->id.d = (hdc->cmd[1] >> 5) & 1;
1100
1101#if DEBUG_HDC >= 1
1102 fprintf (stderr, "HDC: CMD=%02X D=%u cmd_fd\n",
1103 hdc->cmd[0], hdc->id.d
1104 );
1105#endif
1106
1107 hdc_set_result (hdc, 0, 0x00);
1108
1109 hdc->delay = 4096;
1110 hdc->cont = hdc_cmd_done;
1111}
1112
1113
1114/* Command FE: set config parameters */
1115
1116static
1117void hdc_cmd_fe_cont (hdc_t *hdc)
1118{
1119#if DEBUG_HDC >= 1
1120 hdc_print_hex (stderr, "config parameters:", hdc->buf, 64);
1121#endif
1122
1123 hdc_cmd_done (hdc);
1124}
1125
1126static
1127void hdc_cmd_fe (hdc_t *hdc)
1128{
1129 hdc->id.d = (hdc->cmd[1] >> 5) & 1;
1130
1131#if DEBUG_HDC >= 1
1132 fprintf (stderr, "HDC: CMD=%02X D=%u set config parameters\n",
1133 hdc->cmd[0], hdc->id.d
1134 );
1135#endif
1136
1137 hdc->buf_idx = 0;
1138 hdc->buf_cnt = 64;
1139
1140 hdc_set_result (hdc, 0, 0x00);
1141
1142 hdc->delay = 0;
1143 hdc->cont = hdc_cmd_fe_cont;
1144
1145 hdc_request_data (hdc, 0);
1146}
1147
1148
1149/* Command FF: get config parameters */
1150
1151static
1152void hdc_cmd_ff_cont (hdc_t *hdc)
1153{
1154 unsigned c, h, s;
1155 disk_t *dsk;
1156
1157 dsk = dsks_get_disk (hdc->dsks, hdc->drv[hdc->id.d].drive);
1158
1159 if (dsk == NULL) {
1160 c = 0;
1161 h = 0;
1162 s = hdc->sectors;
1163 }
1164 else {
1165 c = dsk->c;
1166 h = dsk->h;
1167 s = dsk->s;
1168 }
1169
1170 hdc->drv[hdc->id.d].max_s = s;
1171
1172 memcpy (hdc->buf, hdc->config_params, 64);
1173
1174 buf_set_uint16_le (hdc->buf, 8, c);
1175 buf_set_uint8 (hdc->buf, 10, h);
1176 buf_set_uint16_le (hdc->buf, 11, c);
1177 buf_set_uint16_le (hdc->buf, 13, c);
1178 buf_set_uint8 (hdc->buf, 15, 5);
1179 buf_set_uint8 (hdc->buf, 22, s);
1180
1181 buf_set_uint8 (hdc->buf, 24, 0x80);
1182 buf_set_uint8 (hdc->buf, 25, 0x00);
1183 buf_set_uint8 (hdc->buf, 26, 0xff);
1184 buf_set_uint8 (hdc->buf, 27, 0xff);
1185 buf_set_uint8 (hdc->buf, 28, 0xff);
1186 buf_set_uint8 (hdc->buf, 29, 0xff);
1187 buf_set_uint8 (hdc->buf, 30, 0xff);
1188 buf_set_uint8 (hdc->buf, 31, 0xff);
1189
1190 hdc->buf_idx = 0;
1191 hdc->buf_cnt = 64;
1192
1193 hdc_set_result (hdc, 0, 0x00);
1194
1195 hdc->delay = 0;
1196 hdc->cont = hdc_cmd_done;
1197
1198 hdc_request_data (hdc, 1);
1199}
1200
1201static
1202void hdc_cmd_ff (hdc_t *hdc)
1203{
1204 hdc->id.d = (hdc->cmd[1] >> 5) & 1;
1205
1206#if DEBUG_HDC >= 1
1207 fprintf (stderr, "HDC: CMD=%02X D=%u get config parameters\n",
1208 hdc->cmd[0], hdc->id.d
1209 );
1210#endif
1211
1212 hdc->delay = 4096;
1213 hdc->cont = hdc_cmd_ff_cont;
1214}
1215
1216
1217/* Command XX: unknown command */
1218
1219static
1220void hdc_cmd_unknown (hdc_t *hdc)
1221{
1222 fprintf (stderr,
1223 "HDC: CMD=%02X D=* unknown command [%02X %02X %02X %02X %02X %02X]\n",
1224 hdc->cmd[0],
1225 hdc->cmd[0], hdc->cmd[1], hdc->cmd[2],
1226 hdc->cmd[3], hdc->cmd[4], hdc->cmd[5]
1227 );
1228
1229 hdc_set_result (hdc, 1, 0x20);
1230
1231 hdc->delay = 4096;
1232 hdc->cont = hdc_cmd_done;
1233}
1234
1235
1236static
1237unsigned char hdc_get_status (hdc_t *hdc)
1238{
1239 return (hdc->status);
1240}
1241
1242static
1243unsigned char hdc_get_config (hdc_t *hdc)
1244{
1245#if DEBUG_HDC >= 3
1246 fprintf (stderr, "hdc: get config: %02X\n", hdc->config);
1247#endif
1248
1249 return (hdc->config);
1250}
1251
1252unsigned char hdc_read_data (hdc_t *hdc)
1253{
1254 unsigned char val;
1255
1256 if ((hdc->status & HDC_STATUS_REQ) == 0) {
1257 return (0);
1258 }
1259
1260 val = 0;
1261
1262 if (hdc->status & HDC_STATUS_CMD) {
1263 val = hdc->result;
1264
1265 hdc_set_irq (hdc, 0);
1266
1267#if DEBUG_HDC >= 3
1268 fprintf (stderr, "hdc: %02X\n", val);
1269#endif
1270
1271 hdc->cmd_idx = 0;
1272 hdc->cmd_cnt = 0;
1273
1274 hdc->status &= ~(HDC_STATUS_BSY | HDC_STATUS_INP | HDC_STATUS_REQ);
1275 }
1276 else {
1277 if (hdc->buf_idx < hdc->buf_cnt) {
1278 val = hdc->buf[hdc->buf_idx++];
1279
1280 if (hdc->buf_idx >= hdc->buf_cnt) {
1281 hdc_set_dreq (hdc, 0);
1282
1283 if (hdc->cont != NULL) {
1284 hdc->cont (hdc);
1285 }
1286 }
1287 }
1288 }
1289
1290 return (val);
1291}
1292
1293
1294static
1295void hdc_select (hdc_t *hdc)
1296{
1297#if DEBUG_HDC >= 3
1298 fprintf (stderr, "hdc: select\n");
1299#endif
1300
1301 hdc->delay = 0;
1302 hdc->cont = NULL;
1303
1304 hdc_set_dreq (hdc, 0);
1305 hdc_set_irq (hdc, 0);
1306
1307 hdc->cmd_idx = 0;
1308
1309 hdc_request_command (hdc);
1310}
1311
1312static
1313void hdc_set_mask (hdc_t *hdc, unsigned char val)
1314{
1315 hdc->mask = val;
1316}
1317
1318static
1319void hdc_set_command (hdc_t *hdc, unsigned char val)
1320{
1321 if (hdc->cmd_idx == 0) {
1322 hdc->cmd_cnt = 6;
1323 }
1324
1325 hdc->cmd[hdc->cmd_idx++] = val;
1326
1327 if (hdc->cmd_idx < hdc->cmd_cnt) {
1328 return;
1329 }
1330
1331 hdc->status &= ~HDC_STATUS_REQ;
1332
1333 switch (hdc->cmd[0]) {
1334 case 0x00:
1335 hdc_cmd_tst_rdy (hdc);
1336 break;
1337
1338 case 0x01:
1339 hdc_cmd_recal (hdc);
1340 break;
1341
1342 case 0x03:
1343 hdc_cmd_sense (hdc);
1344 break;
1345
1346 case 0x04:
1347 hdc_cmd_fmtdrv (hdc);
1348 break;
1349
1350 case 0x05:
1351 hdc_cmd_chk_trk (hdc);
1352 break;
1353
1354 case 0x06:
1355 hdc_cmd_fmttrk (hdc);
1356 break;
1357
1358 case 0x08:
1359 hdc_cmd_read (hdc);
1360 break;
1361
1362 case 0x0a:
1363 hdc_cmd_write (hdc);
1364 break;
1365
1366 case 0x0b:
1367 hdc_cmd_seek (hdc);
1368 break;
1369
1370 case 0x0c:
1371 hdc_cmd_init (hdc);
1372 break;
1373
1374 case 0x0e:
1375 hdc_cmd_rd_buf (hdc);
1376 break;
1377
1378 case 0x0f:
1379 hdc_cmd_wr_buf (hdc);
1380 break;
1381
1382 case 0x11:
1383 hdc_cmd_11 (hdc);
1384 break;
1385
1386 case 0x15:
1387 hdc_cmd_set_mode (hdc);
1388 break;
1389
1390 case 0x1a:
1391 hdc_cmd_mode_sense (hdc);
1392 break;
1393
1394 case 0xe0:
1395 hdc_cmd_ram_diag (hdc);
1396 break;
1397
1398 case 0xe4:
1399 hdc_cmd_cntlr_diag (hdc);
1400 break;
1401
1402 case 0xfb:
1403 hdc_cmd_getgeo (hdc);
1404 break;
1405
1406 case 0xfc:
1407 hdc_cmd_fc (hdc);
1408 break;
1409
1410 case 0xfd:
1411 hdc_cmd_fd (hdc);
1412 break;
1413
1414 case 0xfe:
1415 hdc_cmd_fe (hdc);
1416 break;
1417
1418 case 0xff:
1419 hdc_cmd_ff (hdc);
1420 break;
1421
1422 default:
1423 hdc_cmd_unknown (hdc);
1424 break;
1425 }
1426}
1427
1428void hdc_write_data (hdc_t *hdc, unsigned char val)
1429{
1430 if ((hdc->status & HDC_STATUS_REQ) == 0) {
1431 return;
1432 }
1433
1434 if (hdc->status & HDC_STATUS_CMD) {
1435 hdc_set_command (hdc, val);
1436 return;
1437 }
1438
1439 if (hdc->buf_idx < hdc->buf_cnt) {
1440 hdc->buf[hdc->buf_idx++] = val;
1441 }
1442
1443 if (hdc->buf_idx >= hdc->buf_cnt) {
1444 hdc_set_dreq (hdc, 0);
1445
1446 if (hdc->cont != NULL) {
1447 hdc->cont (hdc);
1448 }
1449 }
1450}
1451
1452static
1453unsigned char hdc_get_uint8 (hdc_t *hdc, unsigned long addr)
1454{
1455 unsigned char val;
1456
1457 val = 0;
1458
1459 switch (addr) {
1460 case 0:
1461 val = hdc_read_data (hdc);
1462 break;
1463
1464 case 1:
1465 val = hdc_get_status (hdc);
1466 break;
1467
1468 case 2:
1469 val = hdc_get_config (hdc);
1470 break;
1471
1472 default:
1473 fprintf (stderr, "HDC: unknown read: %04lX\n", addr);
1474 break;
1475 }
1476
1477#if DEBUG_HDC >= 4
1478 fprintf (stderr, "hdc: get %04lX -> %02X\n", addr, val);
1479#endif
1480
1481 return (val);
1482}
1483
1484static
1485unsigned char hdc_get_uint16 (hdc_t *hdc, unsigned long addr)
1486{
1487 return (0);
1488}
1489
1490static
1491void hdc_set_uint8 (hdc_t *hdc, unsigned long addr, unsigned char val)
1492{
1493#if DEBUG_HDC >= 4
1494 fprintf (stderr, "hdc: set %04lX <- %02X\n", addr, val);
1495#endif
1496
1497 switch (addr) {
1498 case 0:
1499 hdc_write_data (hdc, val);
1500 break;
1501
1502 case 1:
1503 hdc_reset (hdc);
1504 break;
1505
1506 case 2:
1507 hdc_select (hdc);
1508 break;
1509
1510 case 3:
1511 hdc_set_mask (hdc, val);
1512 break;
1513 }
1514}
1515
1516static
1517void hdc_set_uint16 (hdc_t *hdc, unsigned long addr, unsigned val)
1518{
1519}
1520
1521hdc_t *hdc_new (unsigned long addr)
1522{
1523 hdc_t *hdc;
1524
1525 hdc = malloc (sizeof (hdc_t));
1526
1527 if (hdc == NULL) {
1528 return (NULL);
1529 }
1530
1531 mem_blk_init (&hdc->blk, addr, 4, 0);
1532
1533 mem_blk_set_fct (&hdc->blk, hdc,
1534 hdc_get_uint8, hdc_get_uint16, NULL,
1535 hdc_set_uint8, hdc_set_uint16, NULL
1536 );
1537
1538 hdc->config = 0;
1539
1540 memset (hdc->config_params, 0, 64);
1541
1542 hdc->sectors = 17;
1543
1544 hdc->drv[0].drive = 0xffff;
1545 hdc->drv[1].drive = 0xffff;
1546
1547 hdc->dsks = NULL;
1548
1549 hdc->delay = 0;
1550
1551 hdc->cont = NULL;
1552
1553 hdc->irq_val = 0;
1554 hdc->irq_ext = NULL;
1555 hdc->irq = NULL;
1556
1557 hdc->dreq_val = 0;
1558 hdc->dreq_ext = NULL;
1559 hdc->dreq = NULL;
1560
1561 return (hdc);
1562}
1563
1564void hdc_del (hdc_t *hdc)
1565{
1566 if (hdc != NULL) {
1567 mem_blk_free (&hdc->blk);
1568 free (hdc);
1569 }
1570}
1571
1572void hdc_mem_add_io (hdc_t *hdc, memory_t *io)
1573{
1574 mem_add_blk (io, &hdc->blk, 0);
1575}
1576
1577void hdc_mem_rmv_io (hdc_t *hdc, memory_t *io)
1578{
1579 mem_rmv_blk (io, &hdc->blk);
1580}
1581
1582void hdc_set_irq_fct (hdc_t *hdc, void *ext, void *fct)
1583{
1584 hdc->irq = fct;
1585 hdc->irq_ext = ext;
1586}
1587
1588void hdc_set_dreq_fct (hdc_t *hdc, void *ext, void *fct)
1589{
1590 hdc->dreq = fct;
1591 hdc->dreq_ext = ext;
1592}
1593
1594void hdc_set_config (hdc_t *hdc, unsigned val)
1595{
1596 hdc->config = val;
1597}
1598
1599void hdc_set_sectors (hdc_t *hdc, unsigned val)
1600{
1601 hdc->sectors = val;
1602}
1603
1604void hdc_set_disks (hdc_t *hdc, disks_t *dsks)
1605{
1606 hdc->dsks = dsks;
1607}
1608
1609void hdc_set_drive (hdc_t *hdc, unsigned hdcdrv, unsigned drive)
1610{
1611 if (hdcdrv < 2) {
1612 hdc->drv[hdcdrv].drive = drive;
1613 }
1614}
1615
1616unsigned hdc_get_drive (hdc_t *hdc, unsigned hdcdrv)
1617{
1618 if (hdcdrv < 2) {
1619 return (hdc->drv[hdcdrv].drive);
1620 }
1621
1622 return (0xffff);
1623}
1624
1625void hdc_set_config_id (hdc_t *hdc, const unsigned char *id, unsigned cnt)
1626{
1627 unsigned i;
1628
1629 memset (hdc->config_params, 0, 64);
1630
1631 if (cnt > 8) {
1632 cnt = 8;
1633 }
1634
1635 for (i = 0; i < cnt; i++) {
1636 hdc->config_params[i] = id[i];
1637 }
1638}
1639
1640void hdc_reset (hdc_t *hdc)
1641{
1642 unsigned i;
1643
1644#if DEBUG_HDC >= 1
1645 fprintf (stderr, "HDC: reset\n");
1646#endif
1647
1648 hdc->status = 0;
1649 hdc->mask = 0;
1650
1651 hdc_set_result (hdc, 0, 0x00);
1652
1653 hdc->cmd_idx = 0;
1654 hdc->cmd_cnt = 0;
1655
1656 hdc->buf_idx = 0;
1657 hdc->buf_cnt = 0;
1658
1659 for (i = 0; i < 2; i++) {
1660 hdc->drv[i].max_c = 306;
1661 hdc->drv[i].max_h = 4;
1662 hdc->drv[i].max_s = hdc->sectors;
1663
1664 hdc->drv[i].sense[0] = 0;
1665 hdc->drv[i].sense[1] = 0;
1666 hdc->drv[i].sense[2] = 0;
1667 hdc->drv[i].sense[3] = 0;
1668 }
1669
1670 hdc->delay = 0;
1671 hdc->cont = NULL;
1672
1673 hdc_set_irq (hdc, 0);
1674}
1675
1676void hdc_clock (hdc_t *hdc, unsigned long cnt)
1677{
1678 if (hdc->delay == 0) {
1679 return;
1680 }
1681
1682 if (cnt < hdc->delay) {
1683 hdc->delay -= cnt;
1684 return;
1685 }
1686
1687 hdc->delay = 0;
1688
1689 if (hdc->cont != NULL) {
1690 hdc->cont (hdc);
1691 }
1692}