fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 1692 lines 28 kB view raw
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}