fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 1363 lines 24 kB view raw
1/***************************************************************************** 2 * pce * 3 *****************************************************************************/ 4 5/***************************************************************************** 6 * File name: src/arch/macplus/iwm.c * 7 * Created: 2007-11-25 by Hampa Hug <hampa@hampa.ch> * 8 * Copyright: (C) 2007-2023 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 23#include "main.h" 24#include "iwm.h" 25#include "iwm-io.h" 26 27#include <stdio.h> 28#include <stdlib.h> 29#include <string.h> 30 31#include <drivers/block/block.h> 32#include <lib/console.h> 33 34 35#define MAC_IWM_CA0 0x01 36#define MAC_IWM_CA1 0x02 37#define MAC_IWM_CA2 0x04 38#define MAC_IWM_LSTRB 0x08 39#define MAC_IWM_ENABLE 0x10 40#define MAC_IWM_SELECT 0x20 41#define MAC_IWM_Q6 0x40 42#define MAC_IWM_Q7 0x80 43 44 45#ifndef DEBUG_IWM 46#define DEBUG_IWM 0 47#endif 48 49 50static unsigned char pwm_tab[64] = { 51 0x00, 0x2b, 0x30, 0x2a, 0x2f, 0x04, 0x35, 0x29, 52 0x2e, 0x0c, 0x3a, 0x03, 0x34, 0x19, 0x09, 0x28, 53 0x2d, 0x37, 0x0e, 0x0b, 0x39, 0x20, 0x1e, 0x02, 54 0x33, 0x1c, 0x11, 0x18, 0x08, 0x15, 0x3f, 0x27, 55 0x2c, 0x31, 0x05, 0x36, 0x0d, 0x3b, 0x1a, 0x0a, 56 0x38, 0x0f, 0x21, 0x1f, 0x1d, 0x12, 0x16, 0x01, 57 0x32, 0x06, 0x3c, 0x1b, 0x10, 0x22, 0x13, 0x17, 58 0x07, 0x3d, 0x23, 0x14, 0x3e, 0x24, 0x25, 0x26 59}; 60 61 62static 63int iwm_drv_init (mac_iwm_drive_t *drv, unsigned drive) 64{ 65 drv->drive = drive; 66 67 drv->dsks = NULL; 68 drv->diskid = drive; 69 70 drv->img = NULL; 71 drv->img_del = 0; 72 73 drv->auto_rotate = 0; 74 drv->use_pwm = 1; 75 76 drv->cylinders = MAC_IWM_CYLINDERS; 77 drv->heads = 1; 78 79 drv->step_direction = 0; 80 drv->stepping = 0; 81 drv->disk_inserted = 0; 82 drv->disk_switched = 0; 83 drv->motor_on = 0; 84 85 drv->cur_cyl = 0; 86 drv->cur_head = 0; 87 88 drv->cur_track = NULL; 89 90 drv->cur_track_pos = 0; 91 drv->cur_track_len = 0; 92 93 drv->evt = NULL; 94 95 drv->weak_mask = 0; 96 drv->weak_run = 0; 97 drv->weak_val = 0; 98 99 drv->pwm_pos = 0; 100 drv->pwm_len = 65000; 101 102 drv->read_pos = 0; 103 drv->write_pos = 0; 104 105 drv->write_cnt = 0; 106 107 drv->input_clock = MAC_CPU_CLOCK / 10; 108 drv->input_clock_cnt = 0; 109 110 drv->track_dirty = 0; 111 drv->dirty = 0; 112 113 return (0); 114} 115 116static 117void iwm_drv_free (mac_iwm_drive_t *drv) 118{ 119 if (drv->dirty) { 120 iwm_drv_save (drv); 121 } 122 123 if (drv->img_del) { 124 pri_img_del (drv->img); 125 } 126} 127 128static 129unsigned long iwm_drv_get_track_length (unsigned cyl) 130{ 131 static unsigned long length_tab[5] = { 132 74640, 68240, 62200, 55980, 49760 133 }; 134 135 if (cyl > 79) { 136 cyl = 79; 137 } 138 139 return (length_tab[cyl / 16]); 140} 141 142static 143void iwm_drv_write_end (mac_iwm_drive_t *drv) 144{ 145 if (drv->write_cnt > drv->cur_track_len) { 146 if (drv->auto_rotate) { 147 pri_trk_rotate (drv->cur_track, drv->cur_track_pos); 148 drv->cur_track_pos = 0; 149 } 150 } 151 152 drv->write_cnt = 0; 153} 154 155static 156void iwm_drv_print_status (mac_iwm_drive_t *drv) 157{ 158 char state1, state2; 159 160 if (drv->motor_on == 0) { 161 return; 162 } 163 164 state1 = drv->dirty ? '*' : ' '; 165 166 if (drv->track_dirty & 2) { 167 state2 = '+'; 168 } 169 else if (drv->track_dirty & 1) { 170 state2 = '*'; 171 } 172 else { 173 state2 = ' '; 174 } 175 176 pce_printf ("IWM: %cD%u %c%u/%u \r", 177 state1, 178 drv->drive + 1, 179 state2, 180 drv->cur_cyl, drv->cur_head 181 ); 182} 183 184static 185void iwm_drv_select_track (mac_iwm_drive_t *drv, unsigned c, unsigned h) 186{ 187 pri_trk_t *trk; 188 189 if ((c >= drv->cylinders) || (h >= drv->heads)) { 190 return; 191 } 192 193 if (drv->img == NULL) { 194 drv->img = pri_img_new(); 195 } 196 197 trk = pri_img_get_track (drv->img, c, h, 1); 198 199 if (trk == NULL) { 200 return; 201 } 202 203 if (trk->size == 0) { 204 if (pri_trk_set_size (trk, iwm_drv_get_track_length (c))) { 205 return; 206 } 207 } 208 209 if (trk->clock == 0) { 210 pri_trk_set_clock (trk, 500000); 211 } 212 213 drv->cur_cyl = c; 214 drv->cur_head = h; 215 drv->cur_track = trk; 216 drv->cur_track_len = trk->size; 217 218 if (drv->cur_track_pos >= drv->cur_track_len) { 219 drv->cur_track_pos = 0; 220 } 221 222 drv->read_pos = drv->cur_track_pos; 223 drv->write_pos = drv->cur_track_pos; 224 225 drv->evt = trk->evt; 226 227 while ((drv->evt != NULL) && (drv->evt->pos < drv->cur_track_pos)) { 228 drv->evt = drv->evt->next; 229 } 230 231 drv->weak_mask = 0; 232 drv->weak_run = 0; 233 drv->weak_val = 0; 234 235 drv->track_dirty = 0; 236 237 iwm_drv_print_status (drv); 238} 239 240static 241void iwm_drv_select_head (mac_iwm_drive_t *drv, unsigned head) 242{ 243 if (drv->cur_head == head) { 244 return; 245 } 246 247 iwm_drv_select_track (drv, drv->cur_cyl, head); 248} 249 250static 251int iwm_drv_get_step_direction (mac_iwm_drive_t *drv) 252{ 253 int val; 254 255 val = (drv->step_direction != 0); 256 257#if DEBUG_IWM >= 2 258 mac_log_deb ("iwm: get sense: d=%u: step direction == %d\n", 259 drv->drive + 1, val 260 ); 261#endif 262 263 return (val); 264} 265 266static 267int iwm_drv_get_stepping (mac_iwm_drive_t *drv) 268{ 269 int val; 270 271 val = (drv->stepping != 0); 272 273 drv->stepping = 0; 274 275#if DEBUG_IWM >= 2 276 mac_log_deb ("iwm: get sense: d=%u: stepping == %d\n", 277 drv->drive + 1, val 278 ); 279#endif 280 281 return (val); 282} 283 284static 285int iwm_drv_get_motor_on (mac_iwm_drive_t *drv) 286{ 287 int val; 288 289 val = (drv->motor_on != 0); 290 291#if DEBUG_IWM >= 2 292 mac_log_deb ("iwm: get sense: d=%u: motor on == %d\n", 293 drv->drive + 1, val 294 ); 295#endif 296 297 return (val); 298} 299 300static 301int iwm_drv_get_disk_switched (mac_iwm_drive_t *drv) 302{ 303 int val; 304 305 val = (drv->disk_switched != 0); 306 307#if DEBUG_IWM >= 2 308 mac_log_deb ("iwm: get sense: d=%u: disk switched == %d\n", 309 drv->drive + 1, val 310 ); 311#endif 312 313 return (val); 314} 315 316static 317int iwm_drv_get_head (mac_iwm_drive_t *drv, unsigned head) 318{ 319 int val; 320 321 val = 1; 322 323#if DEBUG_IWM >= 2 324 mac_log_deb ("iwm: get sense: d=%u: head %u == %d\n", 325 drv->drive + 1, head, val 326 ); 327#endif 328 329 return (val); 330} 331 332static 333int iwm_drv_get_superdrive (mac_iwm_drive_t *drv) 334{ 335 int val; 336 337 val = 0; 338 339#if DEBUG_IWM >= 2 340 mac_log_deb ("iwm: get sense: d=%u: superdrive == %d\n", 341 drv->drive + 1, val 342 ); 343#endif 344 345 return (val); 346} 347 348static 349int iwm_drv_get_sides (mac_iwm_drive_t *drv) 350{ 351 int val; 352 353 val = (drv->heads > 1); 354 355#if DEBUG_IWM >= 2 356 mac_log_deb ("iwm: get sense: d=%u: sides == %d\n", 357 drv->drive + 1, val 358 ); 359#endif 360 361 return (val); 362} 363 364static 365int iwm_drv_get_installed (mac_iwm_drive_t *drv) 366{ 367 int val; 368 369 val = 1; 370 371#if DEBUG_IWM >= 2 372 mac_log_deb ("iwm: get sense: d=%u: drive installed == %d\n", 373 drv->drive + 1, val 374 ); 375#endif 376 377 return (val); 378} 379 380static 381int iwm_drv_get_disk_inserted (mac_iwm_drive_t *drv) 382{ 383 int val; 384 385 val = (drv->disk_inserted != 0); 386 387#if DEBUG_IWM >= 2 388 mac_log_deb ("iwm: get sense: d=%u: disk inserted == %d\n", 389 drv->drive + 1, val 390 ); 391#endif 392 393 return (val); 394} 395 396static 397int iwm_drv_get_locked (mac_iwm_drive_t *drv) 398{ 399 int val; 400 disk_t *dsk; 401 402 if ((dsk = dsks_get_disk (drv->dsks, drv->diskid)) != NULL){ 403 val = dsk_get_readonly (dsk); 404 } 405 else { 406 val = 1; 407 } 408 409#if DEBUG_IWM >= 2 410 mac_log_deb ("iwm: get sense: d=%u: locked == %d\n", 411 drv->drive + 1, val 412 ); 413#endif 414 415 return (val); 416} 417 418static 419int iwm_drv_get_track0 (mac_iwm_drive_t *drv) 420{ 421 int val; 422 423 val = (drv->cur_cyl == 0); 424 425#if DEBUG_IWM >= 2 426 mac_log_deb ("iwm: get sense: d=%u: track0 == %d\n", 427 drv->drive + 1, val 428 ); 429#endif 430 431 return (val); 432} 433 434static 435int iwm_drv_get_tacho (mac_iwm_drive_t *drv) 436{ 437 int val; 438 unsigned long pwm; 439 440 if (drv->use_pwm) { 441 pwm = 65536 - drv->pwm_val; 442 443 val = ((((120 * pwm) / 32768) * drv->pwm_pos) / drv->pwm_len) & 1; 444 } 445 else { 446 val = ((120 * drv->cur_track_pos) / drv->cur_track_len) & 1; 447 } 448 449#if DEBUG_IWM >= 4 450 mac_log_deb ("iwm: get sense: d=%u: tacho == %d (%lu / %lu)\n", 451 drv->drive + 1, val, drv->cur_track_pos, drv->cur_track_len 452 ); 453#endif 454 455 return (val); 456} 457 458static 459int iwm_drv_get_ready (mac_iwm_drive_t *drv) 460{ 461 int val; 462 463 val = 1; 464 465#if DEBUG_IWM >= 2 466 mac_log_deb ("iwm: get sense: d=%u: ready == %d\n", 467 drv->drive + 1, val 468 ); 469#endif 470 471 return (val); 472} 473 474static 475int iwm_drv_get_new_if (mac_iwm_drive_t *drv) 476{ 477 int val; 478 479 val = 1; 480 481#if DEBUG_IWM >= 2 482 mac_log_deb ("iwm: get sense: d=%u: new interface == %d\n", 483 drv->drive + 1, val 484 ); 485#endif 486 487 return (val); 488} 489 490static 491void iwm_drv_set_step_direction (mac_iwm_drive_t *drv, int val) 492{ 493 drv->step_direction = (val != 0); 494 495#if DEBUG_IWM >= 2 496 mac_log_deb ("iwm: set cntrl: d=%u: step direction = %d\n", 497 drv->drive + 1, val 498 ); 499#endif 500} 501 502static 503void iwm_drv_set_step (mac_iwm_drive_t *drv) 504{ 505 if (drv->step_direction == 0) { 506 if (drv->cur_cyl > 0) { 507 drv->cur_cyl -= 1; 508 } 509 } 510 else { 511 if ((drv->cur_cyl + 1) < drv->cylinders) { 512 drv->cur_cyl += 1; 513 } 514 } 515 516 drv->stepping = 1; 517 518 iwm_drv_select_track (drv, drv->cur_cyl, drv->cur_head); 519 520#if DEBUG_IWM >= 2 521 mac_log_deb ("iwm: drive %u step to track %u\n", 522 drv->drive + 1, drv->cur_cyl 523 ); 524#endif 525} 526 527static 528void iwm_drv_set_motor_on (mac_iwm_drive_t *drv, int val) 529{ 530 if (drv->motor_on == (val != 0)) { 531 return; 532 } 533 534 drv->motor_on = (val != 0); 535 536#if DEBUG_IWM >= 1 537 mac_log_deb ("iwm: drive %u motor %s\n", 538 drv->drive + 1, val ? "on" : "off" 539 ); 540#elif DEBUG_IWM >= 2 541 mac_log_deb ("iwm: set cntrl: d=%u: motor %s\n", 542 drv->drive + 1, val ? "on" : "off" 543 ); 544#endif 545} 546 547static 548void iwm_drv_set_disk_switched (mac_iwm_drive_t *drv) 549{ 550 drv->disk_switched = 0; 551 552#if DEBUG_IWM >= 2 553 mac_log_deb ("iwm: set cntrl: d=%u: reset disk switched\n", 554 drv->drive + 1 555 ); 556#endif 557} 558 559static 560void iwm_drv_set_eject (mac_iwm_drive_t *drv) 561{ 562 drv->disk_inserted = 0; 563 564#if DEBUG_IWM >= 0 565 mac_log_deb ("iwm: drive %u eject\n", drv->drive + 1); 566#elif DEBUG_IWM >= 2 567 mac_log_deb ("iwm: set cntrl: d=%u: eject\n", drv->drive + 1); 568#endif 569 570 if (drv->dirty) { 571 iwm_drv_save (drv); 572 } 573 574 if (drv->img_del) { 575 pri_img_del (drv->img); 576 } 577 578 drv->img = NULL; 579 drv->img_del = 0; 580 581 drv->cur_track = NULL; 582 drv->evt = NULL; 583} 584 585void mac_iwm_init (mac_iwm_t *iwm) 586{ 587 unsigned i; 588 589 iwm->lines = 0; 590 iwm->head_sel = 0; 591 592 iwm->status = 0; 593 iwm->mode = 0; 594 iwm->handshake = 0x7f; 595 596 iwm->writing = 0; 597 598 iwm->shift_cnt = 0; 599 iwm->shift = 0; 600 601 iwm->read_buf = 0; 602 iwm->write_buf = 0; 603 604 iwm->read_zero_cnt = 0; 605 606 iwm->pwm_val = 0; 607 608 iwm->rand = 1; 609 610 for (i = 0; i < MAC_IWM_DRIVES; i++) { 611 iwm_drv_init (&iwm->drv[i], i); 612 } 613 614 iwm->curdrv = &iwm->drv[0]; 615 616 iwm->set_motor_val = 0; 617 iwm->set_motor_ext = NULL; 618 iwm->set_motor = NULL; 619} 620 621void mac_iwm_free (mac_iwm_t *iwm) 622{ 623 unsigned i; 624 625 for (i = 0; i < MAC_IWM_DRIVES; i++) { 626 iwm_drv_free (&iwm->drv[i]); 627 } 628} 629 630static 631int iwm_get_random (mac_iwm_t *iwm) 632{ 633 if (iwm->rand & 1) { 634 iwm->rand = (iwm->rand >> 1) ^ 0x80000057; 635 } 636 else { 637 iwm->rand = iwm->rand >> 1; 638 } 639 640 return (iwm->rand & 1); 641} 642 643void mac_iwm_set_motor_fct (mac_iwm_t *iwm, void *ext, void *fct) 644{ 645 iwm->set_motor_ext = ext; 646 iwm->set_motor = fct; 647} 648 649void mac_iwm_enable_pwm (mac_iwm_t *iwm, unsigned drive, int val) 650{ 651 if (drive < MAC_IWM_DRIVES) { 652 iwm->drv[drive].use_pwm = (val != 0); 653 } 654} 655 656int mac_iwm_set_heads (mac_iwm_t *iwm, unsigned drive, unsigned heads) 657{ 658 mac_iwm_drive_t *drv; 659 660 if (drive >= MAC_IWM_DRIVES) { 661 return (1); 662 } 663 664 if (heads > MAC_IWM_HEADS) { 665 return (1); 666 } 667 668 drv = &iwm->drv[drive]; 669 670 drv->heads = heads; 671 672 if (drv->cur_head >= drv->heads) { 673 iwm_drv_select_track (drv, drv->cur_cyl, 0); 674 } 675 676 return (0); 677} 678 679void mac_iwm_set_disks (mac_iwm_t *iwm, disks_t *dsks) 680{ 681 unsigned i; 682 683 for (i = 0; i < MAC_IWM_DRIVES; i++) { 684 iwm->drv[i].dsks = dsks; 685 } 686} 687 688void mac_iwm_set_disk_id (mac_iwm_t *iwm, unsigned drive, unsigned id) 689{ 690 if (drive < MAC_IWM_DRIVES) { 691 iwm->drv[drive].diskid = id; 692 } 693} 694 695void mac_iwm_flush_disk (mac_iwm_t *iwm, unsigned id) 696{ 697 unsigned i; 698 699 for (i = 0; i < MAC_IWM_DRIVES; i++) { 700 if (iwm->drv[i].diskid == id) { 701 iwm_drv_set_eject (iwm->drv + i); 702 } 703 } 704} 705 706void mac_iwm_insert_disk (mac_iwm_t *iwm, unsigned id) 707{ 708 unsigned i; 709 710 for (i = 0; i < MAC_IWM_DRIVES; i++) { 711 if (iwm->drv[i].diskid == id) { 712 mac_iwm_insert (iwm, i); 713 } 714 } 715} 716 717void mac_iwm_set_auto_rotate (mac_iwm_t *iwm, unsigned drive, int val) 718{ 719 if (drive >= MAC_IWM_DRIVES) { 720 return; 721 } 722 723 iwm->drv[drive].auto_rotate = (val != 0); 724} 725 726static 727void mac_iwm_select_drive (mac_iwm_t *iwm, unsigned drive) 728{ 729 if (drive >= MAC_IWM_DRIVES) { 730 drive = 0; 731 } 732 733 iwm->curdrv = &iwm->drv[drive]; 734 735 iwm_drv_select_track (iwm->curdrv, iwm->curdrv->cur_cyl, iwm->head_sel); 736} 737 738void mac_iwm_set_drive_sel (mac_iwm_t *iwm, unsigned char val) 739{ 740 val = (val != 0); 741 742 if (iwm->drive_sel == val) { 743 return; 744 } 745 746 iwm->drive_sel = val; 747 748 if ((iwm->lines & MAC_IWM_SELECT) == 0) { 749 mac_iwm_select_drive (iwm, iwm->drive_sel ? 2 : 0); 750 } 751 752#if DEBUG_IWM >= 2 753 mac_log_deb ("iwm: drive sel = %d\n", iwm->drive_sel); 754#endif 755} 756 757void mac_iwm_set_head_sel (mac_iwm_t *iwm, unsigned char val) 758{ 759 val = (val != 0); 760 761 if (iwm->head_sel == val) { 762 return; 763 } 764 765 iwm->head_sel = val; 766 767 iwm_drv_select_head (iwm->curdrv, val); 768 769#if DEBUG_IWM >= 2 770 mac_log_deb ("iwm: head sel = %d\n", iwm->head_sel); 771#endif 772} 773 774void mac_iwm_set_pwm (mac_iwm_t *iwm, const unsigned char *buf, unsigned cnt) 775{ 776 unsigned long pwm, val; 777 778 pwm = iwm->pwm_val; 779 780 while (cnt > 0) { 781 val = 1024UL * pwm_tab[*(buf++) & 0x3f]; 782 pwm = (31 * pwm + val) / 32; 783 cnt -= 1; 784 } 785 786#if DEBUG_IWM >= 2 787 if (pwm != iwm->pwm_val) { 788 mac_log_deb ("iwm: drive %u set pwm to %lu\n", 789 iwm->curdrv->drive + 1, pwm 790 ); 791 } 792#endif 793 794 iwm->pwm_val = pwm; 795 iwm->curdrv->pwm_val = pwm; 796} 797 798static 799void mac_iwm_set_motor (mac_iwm_t *iwm) 800{ 801 unsigned i; 802 unsigned char v; 803 804 v = 0; 805 806 for (i = 0; i < MAC_IWM_DRIVES; i++) { 807 if (iwm->drv[i].motor_on) { 808 v = 1; 809 break; 810 } 811 } 812 813 if (iwm->set_motor_val == v) { 814 return; 815 } 816 817 iwm->set_motor_val = v; 818 819 if (iwm->set_motor != NULL) { 820 iwm->set_motor (iwm->set_motor_ext, v); 821 } 822} 823 824void mac_iwm_insert (mac_iwm_t *iwm, unsigned drive) 825{ 826 mac_iwm_drive_t *drv; 827 828 if (drive >= MAC_IWM_DRIVES) { 829 return; 830 } 831 832 drv = &iwm->drv[drive]; 833 834 if (drv->disk_inserted) { 835 return; 836 } 837 838#if DEBUG_IWM >= 1 839 mac_log_deb ("iwm: drive %u insert\n", drive + 1); 840#endif 841 842 if (iwm_drv_load (drv) == 0) { 843 drv->disk_inserted = 1; 844 iwm_drv_select_track (drv, drv->cur_cyl, drv->cur_head); 845 } 846} 847 848static 849int mac_iwm_get_drive_status (mac_iwm_t *iwm) 850{ 851 unsigned reg; 852 mac_iwm_drive_t *drv; 853 854 reg = (iwm->lines & 7) | (iwm->head_sel ? 8 : 0); 855 drv = iwm->curdrv; 856 857 switch (reg) { 858 case 0: 859 return (iwm_drv_get_step_direction (drv) == 0); 860 861 case 1: 862 return (iwm_drv_get_stepping (drv) == 0); 863 864 case 2: 865 return (iwm_drv_get_motor_on (drv) == 0); 866 867 case 3: 868 return (iwm_drv_get_disk_switched (drv) != 0); 869 870 case 4: 871 return (iwm_drv_get_head (drv, 0) == 0); 872 873 case 5: 874 return (iwm_drv_get_superdrive (drv)); 875 876 case 6: 877 return (iwm_drv_get_sides (drv)); 878 879 case 7: 880 return (iwm_drv_get_installed (drv) == 0); 881 882 case 8: 883 return (iwm_drv_get_disk_inserted (drv) == 0); 884 885 case 9: 886 return (iwm_drv_get_locked (drv) == 0); 887 888 case 10: 889 return (iwm_drv_get_track0 (drv) == 0); 890 891 case 11: 892 return (iwm_drv_get_tacho (drv) == 0); 893 894 case 12: 895 return (iwm_drv_get_head (drv, 1) == 0); 896 897 case 13: 898 return (1); 899 900 case 14: 901 return (iwm_drv_get_ready (drv) == 0); 902 903 case 15: 904 return (iwm_drv_get_new_if (drv)); 905 906 default: 907#if DEBUG_IWM >= 1 908 mac_log_deb ("iwm: get sense: d=%u: reg 0x%02x == %d\n", 909 drv->drive + 1, reg, 0 910 ); 911#endif 912 break; 913 } 914 915 return (1); 916} 917 918static 919void mac_iwm_set_drive_control (mac_iwm_t *iwm) 920{ 921 int val; 922 unsigned reg; 923 mac_iwm_drive_t *drv; 924 925 reg = (iwm->lines & 3) | (iwm->head_sel ? 4 : 0); 926 val = ((iwm->lines & MAC_IWM_CA2) != 0); 927 drv = iwm->curdrv; 928 929 switch (reg) { 930 case 0: 931 iwm_drv_set_step_direction (drv, val == 0); 932 break; 933 934 case 1: 935 if (val == 0) { 936 iwm_drv_set_step (drv); 937 } 938 break; 939 940 case 2: 941 iwm_drv_set_motor_on (drv, val == 0); 942 mac_iwm_set_motor (iwm); 943 break; 944 945 case 3: 946 if (val) { 947 iwm_drv_set_eject (drv); 948 } 949 break; 950 951 case 4: 952 if (val) { 953 iwm_drv_set_disk_switched (drv); 954 } 955 break; 956 957 default: 958#if DEBUG_IWM >= 1 959 mac_log_deb ("iwm: set cntrl: d=%u: reg 0x%02x = %d\n", 960 drv->drive + 1, reg, val 961 ); 962#endif 963 break; 964 } 965} 966 967static 968void mac_iwm_access_uint8 (mac_iwm_t *iwm, unsigned reg) 969{ 970 switch (reg & 0x0f) { 971 case 0x00: /* ca0 low */ 972 iwm->lines &= ~MAC_IWM_CA0; 973 break; 974 975 case 0x01: /* ca0 high */ 976 iwm->lines |= MAC_IWM_CA0; 977 break; 978 979 case 0x02: /* ca1 low */ 980 iwm->lines &= ~MAC_IWM_CA1; 981 break; 982 983 case 0x03: /* ca1 high */ 984 iwm->lines |= MAC_IWM_CA1; 985 break; 986 987 case 0x04: /* ca2 low */ 988 iwm->lines &= ~MAC_IWM_CA2; 989 break; 990 991 case 0x05: /* ca2 high */ 992 iwm->lines |= MAC_IWM_CA2; 993 break; 994 995 case 0x06: /* lstrb low */ 996 iwm->lines &= ~MAC_IWM_LSTRB; 997 break; 998 999 case 0x07: /* lstrb high */ 1000 iwm->lines |= MAC_IWM_LSTRB; 1001 break; 1002 1003 case 0x08: /* enable low */ 1004 iwm->lines &= ~MAC_IWM_ENABLE; 1005 iwm->status &= ~0x20; 1006 break; 1007 1008 case 0x09: /* enable high */ 1009 iwm->lines |= MAC_IWM_ENABLE; 1010 iwm->status |= 0x20; 1011 break; 1012 1013 case 0x0a: /* select low */ 1014 iwm->lines &= ~MAC_IWM_SELECT; 1015 mac_iwm_select_drive (iwm, iwm->drive_sel ? 2 : 0); 1016 break; 1017 1018 case 0x0b: /* select high */ 1019 iwm->lines |= MAC_IWM_SELECT; 1020 mac_iwm_select_drive (iwm, 1); 1021 break; 1022 1023 case 0x0c: /* q6 low */ 1024 iwm->lines &= ~MAC_IWM_Q6; 1025 break; 1026 1027 case 0x0d: /* q6 high */ 1028 iwm->lines |= MAC_IWM_Q6; 1029 break; 1030 1031 case 0x0e: /* q7 low */ 1032 iwm->lines &= ~MAC_IWM_Q7; 1033 break; 1034 1035 case 0x0f: /* q7 high */ 1036 iwm->lines |= MAC_IWM_Q7; 1037 break; 1038 } 1039 1040 if (iwm->lines & MAC_IWM_LSTRB) { 1041 mac_iwm_set_drive_control (iwm); 1042 } 1043 1044 if ((iwm->lines & MAC_IWM_Q7) == 0) { 1045 iwm->handshake |= 0x40; 1046 1047 if (iwm->writing) { 1048 iwm->writing = 0; 1049 iwm->curdrv->track_dirty &= ~2U; 1050 iwm_drv_write_end (iwm->curdrv); 1051 iwm_drv_print_status (iwm->curdrv); 1052 } 1053 } 1054} 1055 1056unsigned char mac_iwm_get_uint8 (mac_iwm_t *iwm, unsigned long addr) 1057{ 1058 unsigned char val; 1059 1060 if ((addr & 1) == 0) { 1061 return (0); 1062 } 1063 1064 addr = (addr >> 9) & 0x0f; 1065 1066 mac_iwm_access_uint8 (iwm, addr); 1067 1068 val = 0; 1069 1070 switch (iwm->lines & (MAC_IWM_Q6 | MAC_IWM_Q7)) { 1071 case 0x00: /* read data */ 1072 if (iwm->lines & MAC_IWM_ENABLE) { 1073 val = iwm->read_buf; 1074 iwm->read_buf = 0; 1075 } 1076 else { 1077 val = 0xff; 1078 } 1079 break; 1080 1081 case MAC_IWM_Q6: /* read status */ 1082 val = (iwm->status & 0x60) | (iwm->mode & 0x1f); 1083 1084 if (mac_iwm_get_drive_status (iwm)) { 1085 val |= 0x80; 1086 } 1087#if DEBUG_IWM >= 4 1088 mac_log_deb ("iwm: read status (0x%02x)\n", val); 1089#endif 1090 break; 1091 1092 case MAC_IWM_Q7: /* read handshake */ 1093 val = iwm->handshake & 0x7f; 1094 1095 if ((iwm->write_buf & 0xff00) == 0) { 1096 val |= 0x80; 1097 } 1098 1099#if DEBUG_IWM >= 3 1100 mac_log_deb ("iwm: read handshake (0x%02x)\n", val); 1101#endif 1102 break; 1103 1104 case (MAC_IWM_Q6 | MAC_IWM_Q7): /* ? */ 1105#if DEBUG_IWM >= 2 1106 mac_log_deb ("iwm: get 8: %06lX -> 0x%02x\n", addr, val); 1107#endif 1108 break; 1109 } 1110 1111 return (val); 1112} 1113 1114void mac_iwm_set_uint8 (mac_iwm_t *iwm, unsigned long addr, unsigned char val) 1115{ 1116 if ((addr & 1) == 0) { 1117 return; 1118 } 1119 1120 addr = (addr >> 9) & 0x0f; 1121 1122 mac_iwm_access_uint8 (iwm, addr); 1123 1124 switch (iwm->lines & (MAC_IWM_Q6 | MAC_IWM_Q7)) { 1125 case (MAC_IWM_Q6 | MAC_IWM_Q7): /* mode write */ 1126 if (iwm->lines & MAC_IWM_ENABLE) { 1127 /* write data */ 1128 if (iwm->writing == 0) { 1129 iwm->writing = 1; 1130 iwm->shift_cnt = 0; 1131 iwm->curdrv->write_cnt = 0; 1132 iwm->curdrv->track_dirty |= 3; 1133 1134 iwm_drv_print_status (iwm->curdrv); 1135#if DEBUG_IWM >= 1 1136 mac_log_deb ( 1137 "iwm: drive %u writing track %u head %u\n", 1138 iwm->curdrv->drive + 1, 1139 iwm->curdrv->cur_cyl, 1140 iwm->curdrv->cur_head 1141 ); 1142#endif 1143 } 1144 1145 iwm->write_buf = val | 0xff00; 1146#if DEBUG_IWM >= 3 1147 mac_log_deb ("iwm: write data (0x%02x)\n", val); 1148#endif 1149 } 1150 else { 1151 /* write mode */ 1152 iwm->mode = val; 1153#if DEBUG_IWM >= 2 1154 mac_log_deb ("iwm: write mode (0x%02x)\n", val); 1155#endif 1156 } 1157 break; 1158 1159 default: 1160#if DEBUG_IWM >= 2 1161 mac_log_deb ("iwm: set 8: %04lX <- %02X\n", addr, val); 1162#endif 1163 break; 1164 } 1165} 1166 1167static 1168void mac_iwm_read (mac_iwm_t *iwm, mac_iwm_drive_t *drv) 1169{ 1170 unsigned long p; 1171 unsigned char m; 1172 unsigned char *data; 1173 1174 if ((drv->cur_track == NULL) || (drv->cur_track_len == 0)) { 1175 return; 1176 } 1177 1178 p = drv->read_pos / 8; 1179 m = 0x80 >> (drv->read_pos & 7); 1180 1181 data = drv->cur_track->data; 1182 1183 while (drv->read_pos != drv->cur_track_pos) { 1184 while ((drv->evt != NULL) && (drv->evt->pos == drv->read_pos)) { 1185 if (drv->evt->type == PRI_EVENT_WEAK) { 1186 drv->weak_mask |= drv->evt->val & 0xffffffff; 1187 } 1188 1189 drv->evt = drv->evt->next; 1190 } 1191 1192 iwm->shift = (iwm->shift << 1) | ((data[p] & m) != 0); 1193 1194 if (iwm->shift & 1) { 1195 iwm->read_zero_cnt = 0; 1196 } 1197 else { 1198 iwm->read_zero_cnt += 1; 1199 } 1200 1201 if ((drv->weak_run != 0) || (drv->weak_mask != 0)) { 1202 if (drv->weak_run > 0) { 1203 iwm->shift &= ~1U; 1204 iwm->shift |= drv->weak_val & 1; 1205 drv->weak_val >>= 1; 1206 drv->weak_run -= 1; 1207 } 1208 else if (drv->weak_mask & 0x80000000) { 1209 iwm->shift &= ~1U; 1210 iwm->shift |= iwm_get_random (iwm) & 1; 1211 } 1212 1213 if ((drv->weak_mask & 0xf0000000) == 0x60000000) { 1214 drv->weak_run = 2; 1215 drv->weak_val = 1; 1216 drv->weak_val <<= iwm_get_random (iwm) & 1; 1217 } 1218 else if ((drv->weak_mask & 0xf8000000) == 0x70000000) { 1219 drv->weak_run = 3; 1220 drv->weak_val = 1; 1221 drv->weak_val <<= iwm_get_random (iwm) & 1; 1222 drv->weak_val <<= iwm_get_random (iwm) & 1; 1223 } 1224 1225 drv->weak_mask = (drv->weak_mask << 1) & 0xffffffff; 1226 } 1227 1228 drv->read_pos += 1; 1229 1230 if (drv->read_pos >= drv->cur_track_len) { 1231 drv->read_pos = 0; 1232 p = 0; 1233 m = 0x80; 1234 drv->evt = drv->cur_track->evt; 1235 } 1236 else if (m == 1) { 1237 m = 0x80; 1238 p += 1; 1239 } 1240 else { 1241 m >>= 1; 1242 } 1243 1244 if (iwm->shift & 0x80) { 1245 iwm->read_buf = iwm->shift; 1246 iwm->shift = 0; 1247 } 1248 } 1249} 1250 1251static 1252void mac_iwm_write (mac_iwm_t *iwm, mac_iwm_drive_t *drv) 1253{ 1254 unsigned long p; 1255 unsigned char m; 1256 unsigned char *data; 1257 1258 if ((drv->cur_track == NULL) || (drv->cur_track_len == 0)) { 1259 return; 1260 } 1261 1262 p = drv->write_pos / 8; 1263 m = 0x80 >> (drv->write_pos & 7); 1264 1265 data = drv->cur_track->data; 1266 1267 while (drv->write_pos != drv->cur_track_pos) { 1268 if (iwm->shift_cnt == 0) { 1269 if ((iwm->write_buf & 0xff00) == 0) { 1270#if DEBUG_IWM >= 2 1271 mac_log_deb ("iwm: drive %u underrun\n", 1272 drv->drive + 1 1273 ); 1274#endif 1275 iwm->handshake &= ~0x40; 1276 iwm->shift_cnt = 0; 1277 iwm->writing = 0; 1278 iwm->curdrv->track_dirty &= ~2U; 1279 1280 iwm_drv_write_end (drv); 1281 1282 return; 1283 } 1284 1285 iwm->shift = iwm->write_buf & 0xff; 1286 iwm->shift_cnt = 8; 1287 iwm->write_buf = 0; 1288 } 1289 1290 if (iwm->shift & 0x80) { 1291 data[p] |= m; 1292 } 1293 else { 1294 data[p] &= ~m; 1295 } 1296 1297 drv->track_dirty |= 3; 1298 drv->dirty = 1; 1299 1300 iwm->shift = (iwm->shift << 1) & 0xff; 1301 iwm->shift_cnt -= 1; 1302 1303 drv->write_pos += 1; 1304 1305 drv->write_cnt += 1; 1306 1307 if (drv->write_pos >= drv->cur_track_len) { 1308 drv->write_pos = 0; 1309 p = 0; 1310 m = 0x80; 1311 } 1312 else if (m == 1) { 1313 m = 0x80; 1314 p += 1; 1315 } 1316 else { 1317 m >>= 1; 1318 } 1319 } 1320} 1321 1322void mac_iwm_clock (mac_iwm_t *iwm, unsigned cnt) 1323{ 1324 unsigned long clk, bit; 1325 mac_iwm_drive_t *drv; 1326 1327 drv = iwm->curdrv; 1328 1329 if (drv->motor_on == 0) { 1330 return; 1331 } 1332 1333 clk = drv->input_clock_cnt + 500000UL * cnt; 1334 bit = clk / drv->input_clock; 1335 clk = clk % drv->input_clock; 1336 drv->input_clock_cnt = clk; 1337 1338 if (drv->cur_track_len > 0) { 1339 drv->cur_track_pos += bit; 1340 1341 while (drv->cur_track_pos >= drv->cur_track_len) { 1342 drv->cur_track_pos -= drv->cur_track_len; 1343 } 1344 } 1345 1346 if (drv->pwm_len > 0) { 1347 drv->pwm_pos += bit; 1348 1349 if (drv->pwm_pos >= drv->pwm_len) { 1350 drv->pwm_pos -= drv->pwm_len; 1351 } 1352 } 1353 1354 if (iwm->writing) { 1355 mac_iwm_write (iwm, drv); 1356 } 1357 else if ((iwm->lines & (MAC_IWM_Q6 | MAC_IWM_Q7)) == 0) { 1358 mac_iwm_read (iwm, drv); 1359 } 1360 1361 drv->read_pos = drv->cur_track_pos; 1362 drv->write_pos = drv->cur_track_pos; 1363}