- Timestamp:
- Nov 23, 2010 4:11:48 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/fdc.c
r33540 r34294 1 #ifdef VBOX2 1 /* $Id$ */ 3 2 /** @file … … 56 55 #include "../vl_vbox.h" 57 56 57 #define FDC_SAVESTATE_CURRENT 2 /* The new and improved saved state. */ 58 #define FDC_SAVESTATE_OLD 1 /* The original saved state. */ 59 58 60 #define MAX_FD 2 59 61 … … 64 66 ((fdrive_t *)((uintptr_t)(p) - RT_OFFSETOF(fdrive_t, IMountNotify))) 65 67 66 #endif /* VBOX */67 68 #ifndef VBOX69 #include "vl.h"70 #endif /* !VBOX */71 68 72 69 /********************************************************/ … … 109 106 /* Floppy drive emulation */ 110 107 108 #define GET_CUR_DRV(fdctrl) ((fdctrl)->cur_drv) 109 #define SET_CUR_DRV(fdctrl, drive) ((fdctrl)->cur_drv = (drive)) 110 111 111 /* Will always be a fixed parameter for us */ 112 #define FD_SECTOR_LEN 512 113 #define FD_SECTOR_SC 2 /* Sector size code */ 112 #define FD_SECTOR_LEN 512 113 #define FD_SECTOR_SC 2 /* Sector size code */ 114 #define FD_RESET_SENSEI_COUNT 4 /* Number of sense interrupts on RESET */ 114 115 115 116 /* Floppy disk drive emulation */ … … 127 128 FDRIVE_DRV_120 = 0x02, /* 1.2 MB 5"25 drive */ 128 129 FDRIVE_DRV_NONE = 0x03 /* No drive connected */ 129 #ifdef VBOX130 , FDRIVE_DRV_DUMMY = INT32_MAX131 #endif132 130 } fdrive_type_t; 133 131 134 132 typedef enum fdrive_flags_t { 135 FDRIVE_MOTOR_ON = 0x01, /* motor on/off */ 136 FDRIVE_REVALIDATE = 0x02 /* Revalidated */ 137 #ifdef VBOX 138 , FDRIVE_DUMMY = INT32_MAX 139 #endif 133 FDISK_DBL_SIDES = 0x01 140 134 } fdrive_flags_t; 141 135 142 typedef enum fdisk_flags_t {143 FDISK_DBL_SIDES = 0x01144 #ifdef VBOX145 , FDDISK_DUMMY = INT32_MAX146 #endif147 } fdisk_flags_t;148 149 #ifdef VBOX150 136 /** 151 137 * The status for one drive. … … 155 141 * @implements PDMIMOUNTNOTIFY 156 142 */ 157 #endif158 143 typedef struct fdrive_t { 159 144 #ifndef VBOX … … 179 164 /** The LED for this LUN. */ 180 165 PDMLED Led; 181 /** The Diskette present/missingflag. */182 bool fMedia Present;166 /** Media change flag. */ 167 bool fMediaChanged; 183 168 #endif 184 169 /* Drive status */ 185 170 fdrive_type_t drive; 186 fdrive_flags_t drflags;187 171 uint8_t perpendicular; /* 2.88 MB access mode */ 172 uint8_t dsk_chg; /* Disk change line */ 188 173 /* Position */ 189 174 uint8_t head; 190 175 uint8_t track; 191 176 uint8_t sect; 192 /* Last operation status */193 uint8_t dir; /* Direction */194 uint8_t rw; /* Read/write */195 177 /* Media */ 196 fd isk_flags_t flags;178 fdrive_flags_t flags; 197 179 uint8_t last_sect; /* Nb sector per track */ 198 180 uint8_t max_track; /* Nb of tracks */ … … 201 183 } fdrive_t; 202 184 203 #ifndef VBOX 204 static void fd_init (fdrive_t *drv, BlockDriverState *bs) 185 static void fd_init(fdrive_t *drv) 205 186 { 206 187 /* Drive */ 207 drv->bs = bs;208 188 drv->drive = FDRIVE_DRV_NONE; 209 drv->drflags = 0;210 189 drv->perpendicular = 0; 211 190 /* Disk */ 212 191 drv->last_sect = 0; 213 192 drv->max_track = 0; 214 } 215 #endif 216 217 static unsigned _fd_sector (uint8_t head, uint8_t track,218 uint8_t sect,uint8_t last_sect)193 drv->fMediaChanged = true; 194 } 195 196 static int fd_sector_calc(uint8_t head, uint8_t track, uint8_t sect, 197 uint8_t last_sect) 219 198 { 220 199 return (((track * 2) + head) * last_sect) + sect - 1; /* sect >= 1 */ … … 222 201 223 202 /* Returns current position, in sectors, for given drive */ 224 static unsigned fd_sector (fdrive_t *drv) 225 { 226 return _fd_sector(drv->head, drv->track, drv->sect, drv->last_sect); 227 } 228 229 static int fd_seek (fdrive_t *drv, uint8_t head, uint8_t track, uint8_t sect, 230 int enable_seek) 231 { 232 uint32_t sector; 203 static int fd_sector(fdrive_t *drv) 204 { 205 return fd_sector_calc(drv->head, drv->track, drv->sect, drv->last_sect); 206 } 207 208 /* Seek to a new position: 209 * returns 0 if already on right track 210 * returns 1 if track changed 211 * returns 2 if track is invalid 212 * returns 3 if sector is invalid 213 * returns 4 if seek is disabled 214 */ 215 static int fd_seek(fdrive_t *drv, uint8_t head, uint8_t track, uint8_t sect, 216 int enable_seek) 217 { 218 int sector; 233 219 int ret; 234 220 … … 248 234 return 3; 249 235 } 250 sector = _fd_sector(head, track, sect, drv->last_sect);236 sector = fd_sector_calc(head, track, sect, drv->last_sect); 251 237 ret = 0; 252 238 if (sector != fd_sector(drv)) { … … 269 255 270 256 /* Set drive back to track 0 */ 271 static void fd_recalibrate 257 static void fd_recalibrate(fdrive_t *drv) 272 258 { 273 259 FLOPPY_DPRINTF("recalibrate\n"); … … 275 261 drv->track = 0; 276 262 drv->sect = 1; 277 drv->dir = 1;278 drv->rw = 0;279 263 } 280 264 … … 289 273 } fd_format_t; 290 274 291 static fd_format_t fd_formats[] = {275 static const fd_format_t fd_formats[] = { 292 276 /* First entry is default format */ 293 277 /* 1.44 MB 3"1/2 floppy disks */ … … 337 321 338 322 /* Revalidate a disk drive after a disk change */ 339 static void fd_revalidate 340 { 341 fd_format_t *parse;342 int64_t nb_sectors, size;323 static void fd_revalidate(fdrive_t *drv) 324 { 325 const fd_format_t *parse; 326 uint64_t nb_sectors, size; 343 327 int i, first_match, match; 344 328 int nb_heads, max_track, last_sect, ro; 345 329 346 330 FLOPPY_DPRINTF("revalidate\n"); 347 drv->drflags &= ~FDRIVE_REVALIDATE;348 331 #ifndef VBOX 349 332 if (drv->bs != NULL && bdrv_is_inserted(drv->bs)) { … … 351 334 bdrv_get_geometry_hint(drv->bs, &nb_heads, &max_track, &last_sect); 352 335 #else /* VBOX */ 353 /** @todo */ /** @todo r=bird: todo what exactly? */354 336 if (drv->pDrvBlock 355 337 && drv->pDrvMount 356 338 && drv->pDrvMount->pfnIsMounted (drv->pDrvMount)) { 357 339 ro = drv->pDrvBlock->pfnIsReadOnly (drv->pDrvBlock); 358 nb_heads = 0; 359 max_track = 0; 360 last_sect = 0; 340 nb_heads = max_track = last_sect = 0; 361 341 #endif /* VBOX */ 362 342 if (nb_heads != 0 && max_track != 0 && last_sect != 0) { … … 367 347 bdrv_get_geometry(drv->bs, &nb_sectors); 368 348 #else /* VBOX */ 369 /* @todo */ /** @todo r=bird: todo what exactly?!?!? */370 349 { 371 350 uint64_t size2 = drv->pDrvBlock->pfnGetSize (drv->pDrvBlock); 372 nb_sectors = size2 / 512;351 nb_sectors = size2 / FD_SECTOR_LEN; 373 352 } 374 353 #endif /* VBOX */ … … 413 392 drv->last_sect = last_sect; 414 393 drv->ro = ro; 415 #ifdef VBOX416 drv->fMediaPresent = true;417 #endif418 394 } else { 419 395 FLOPPY_DPRINTF("No disk in drive\n"); … … 421 397 drv->max_track = 0; 422 398 drv->flags &= ~FDISK_DBL_SIDES; 423 #ifdef VBOX 424 drv->fMediaPresent = false; 425 #endif 426 } 427 drv->drflags |= FDRIVE_REVALIDATE; 428 } 429 430 /* Motor control */ 431 static void fd_start (fdrive_t *drv) 432 { 433 drv->drflags |= FDRIVE_MOTOR_ON; 434 } 435 436 static void fd_stop (fdrive_t *drv) 437 { 438 drv->drflags &= ~FDRIVE_MOTOR_ON; 439 } 440 441 /* Re-initialise a drives (motor off, repositioned) */ 442 static void fd_reset (fdrive_t *drv) 443 { 444 fd_stop(drv); 445 fd_recalibrate(drv); 399 } 446 400 } 447 401 … … 449 403 /* Intel 82078 floppy disk controller emulation */ 450 404 451 #define target_ulong uint32_t 452 static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq); 453 static void fdctrl_reset_fifo (fdctrl_t *fdctrl); 405 static void fdctrl_reset(fdctrl_t *fdctrl, int do_irq); 406 static void fdctrl_reset_fifo(fdctrl_t *fdctrl); 454 407 #ifndef VBOX 455 static int fdctrl_transfer_handler (void *opaque, int nchan, int dma_pos, int dma_len); 408 static int fdctrl_transfer_handler (void *opaque, int nchan, 409 int dma_pos, int dma_len); 456 410 #else /* VBOX: */ 457 411 static DECLCALLBACK(uint32_t) fdctrl_transfer_handler (PPDMDEVINS pDevIns, … … 461 415 uint32_t dma_len); 462 416 #endif /* VBOX */ 463 static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status); 417 static void fdctrl_raise_irq(fdctrl_t *fdctrl, uint8_t status0); 418 464 419 static void fdctrl_result_timer(void *opaque); 465 466 static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl); 467 static uint32_t fdctrl_read_dor (fdctrl_t *fdctrl); 468 static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value); 469 static uint32_t fdctrl_read_tape (fdctrl_t *fdctrl); 470 static void fdctrl_write_tape (fdctrl_t *fdctrl, uint32_t value); 471 static uint32_t fdctrl_read_main_status (fdctrl_t *fdctrl); 472 static void fdctrl_write_rate (fdctrl_t *fdctrl, uint32_t value); 473 static uint32_t fdctrl_read_data (fdctrl_t *fdctrl); 474 static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value); 475 static uint32_t fdctrl_read_dir (fdctrl_t *fdctrl); 476 477 enum { 478 FD_CTRL_ACTIVE = 0x01, /* XXX: suppress that */ 479 FD_CTRL_RESET = 0x02, 480 FD_CTRL_SLEEP = 0x04, /* XXX: suppress that */ 481 FD_CTRL_BUSY = 0x08, /* dma transfer in progress */ 482 FD_CTRL_INTR = 0x10 483 }; 420 static uint32_t fdctrl_read_statusA(fdctrl_t *fdctrl); 421 static uint32_t fdctrl_read_statusB(fdctrl_t *fdctrl); 422 static uint32_t fdctrl_read_dor(fdctrl_t *fdctrl); 423 static void fdctrl_write_dor(fdctrl_t *fdctrl, uint32_t value); 424 static uint32_t fdctrl_read_tape(fdctrl_t *fdctrl); 425 static void fdctrl_write_tape(fdctrl_t *fdctrl, uint32_t value); 426 static uint32_t fdctrl_read_main_status(fdctrl_t *fdctrl); 427 static void fdctrl_write_rate(fdctrl_t *fdctrl, uint32_t value); 428 static uint32_t fdctrl_read_data(fdctrl_t *fdctrl); 429 static void fdctrl_write_data(fdctrl_t *fdctrl, uint32_t value); 430 static uint32_t fdctrl_read_dir(fdctrl_t *fdctrl); 484 431 485 432 enum { … … 492 439 493 440 enum { 494 FD_STATE_CMD = 0x00, 495 FD_STATE_STATUS = 0x01, 496 FD_STATE_DATA = 0x02, 497 FD_STATE_STATE = 0x03, 498 FD_STATE_MULTI = 0x10, 499 FD_STATE_SEEK = 0x20, 500 FD_STATE_FORMAT = 0x40 441 FD_STATE_MULTI = 0x01, /* multi track flag */ 442 FD_STATE_FORMAT = 0x02, /* format flag */ 443 FD_STATE_SEEK = 0x04 /* seek flag */ 501 444 }; 502 445 503 #define FD_STATE(state) ((state) & FD_STATE_STATE) 504 #define FD_SET_STATE(state, new_state) \ 505 do { (state) = ((state) & ~FD_STATE_STATE) | (new_state); } while (0) 446 enum { 447 FD_REG_SRA = 0x00, 448 FD_REG_SRB = 0x01, 449 FD_REG_DOR = 0x02, 450 FD_REG_TDR = 0x03, 451 FD_REG_MSR = 0x04, 452 FD_REG_DSR = 0x04, 453 FD_REG_FIFO = 0x05, 454 FD_REG_DIR = 0x07 455 }; 456 457 enum { 458 FD_CMD_READ_TRACK = 0x02, 459 FD_CMD_SPECIFY = 0x03, 460 FD_CMD_SENSE_DRIVE_STATUS = 0x04, 461 FD_CMD_WRITE = 0x05, 462 FD_CMD_READ = 0x06, 463 FD_CMD_RECALIBRATE = 0x07, 464 FD_CMD_SENSE_INTERRUPT_STATUS = 0x08, 465 FD_CMD_WRITE_DELETED = 0x09, 466 FD_CMD_READ_ID = 0x0a, 467 FD_CMD_READ_DELETED = 0x0c, 468 FD_CMD_FORMAT_TRACK = 0x0d, 469 FD_CMD_DUMPREG = 0x0e, 470 FD_CMD_SEEK = 0x0f, 471 FD_CMD_VERSION = 0x10, 472 FD_CMD_SCAN_EQUAL = 0x11, 473 FD_CMD_PERPENDICULAR_MODE = 0x12, 474 FD_CMD_CONFIGURE = 0x13, 475 FD_CMD_LOCK = 0x14, 476 FD_CMD_VERIFY = 0x16, 477 FD_CMD_POWERDOWN_MODE = 0x17, 478 FD_CMD_PART_ID = 0x18, 479 FD_CMD_SCAN_LOW_OR_EQUAL = 0x19, 480 FD_CMD_SCAN_HIGH_OR_EQUAL = 0x1d, 481 FD_CMD_SAVE = 0x2e, 482 FD_CMD_OPTION = 0x33, 483 FD_CMD_RESTORE = 0x4e, 484 FD_CMD_DRIVE_SPECIFICATION_COMMAND = 0x8e, 485 FD_CMD_RELATIVE_SEEK_OUT = 0x8f, 486 FD_CMD_FORMAT_AND_WRITE = 0xcd, 487 FD_CMD_RELATIVE_SEEK_IN = 0xcf 488 }; 489 490 enum { 491 FD_CONFIG_PRETRK = 0xff, /* Pre-compensation set to track 0 */ 492 FD_CONFIG_FIFOTHR = 0x0f, /* FIFO threshold set to 1 byte */ 493 FD_CONFIG_POLL = 0x10, /* Poll enabled */ 494 FD_CONFIG_EFIFO = 0x20, /* FIFO disabled */ 495 FD_CONFIG_EIS = 0x40 /* No implied seeks */ 496 }; 497 498 enum { 499 FD_SR0_EQPMT = 0x10, 500 FD_SR0_SEEK = 0x20, 501 FD_SR0_ABNTERM = 0x40, 502 FD_SR0_INVCMD = 0x80, 503 FD_SR0_RDYCHG = 0xc0 504 }; 505 506 enum { 507 FD_SR1_EC = 0x80 /* End of cylinder */ 508 }; 509 510 enum { 511 FD_SR2_SNS = 0x04, /* Scan not satisfied */ 512 FD_SR2_SEH = 0x08 /* Scan equal hit */ 513 }; 514 515 enum { 516 FD_SRA_DIR = 0x01, 517 FD_SRA_nWP = 0x02, 518 FD_SRA_nINDX = 0x04, 519 FD_SRA_HDSEL = 0x08, 520 FD_SRA_nTRK0 = 0x10, 521 FD_SRA_STEP = 0x20, 522 FD_SRA_nDRV2 = 0x40, 523 FD_SRA_INTPEND = 0x80 524 }; 525 526 enum { 527 FD_SRB_MTR0 = 0x01, 528 FD_SRB_MTR1 = 0x02, 529 FD_SRB_WGATE = 0x04, 530 FD_SRB_RDATA = 0x08, 531 FD_SRB_WDATA = 0x10, 532 FD_SRB_DR0 = 0x20 533 }; 534 535 enum { 536 #if MAX_FD == 4 537 FD_DOR_SELMASK = 0x03, 538 #else 539 FD_DOR_SELMASK = 0x01, 540 #endif 541 FD_DOR_nRESET = 0x04, 542 FD_DOR_DMAEN = 0x08, 543 FD_DOR_MOTEN0 = 0x10, 544 FD_DOR_MOTEN1 = 0x20, 545 FD_DOR_MOTEN2 = 0x40, 546 FD_DOR_MOTEN3 = 0x80 547 }; 548 549 enum { 550 #if MAX_FD == 4 551 FD_TDR_BOOTSEL = 0x0c 552 #else 553 FD_TDR_BOOTSEL = 0x04 554 #endif 555 }; 556 557 enum { 558 FD_DSR_DRATEMASK= 0x03, 559 FD_DSR_PWRDOWN = 0x40, 560 FD_DSR_SWRESET = 0x80 561 }; 562 563 enum { 564 FD_MSR_DRV0BUSY = 0x01, 565 FD_MSR_DRV1BUSY = 0x02, 566 FD_MSR_DRV2BUSY = 0x04, 567 FD_MSR_DRV3BUSY = 0x08, 568 FD_MSR_CMDBUSY = 0x10, 569 FD_MSR_NONDMA = 0x20, 570 FD_MSR_DIO = 0x40, 571 FD_MSR_RQM = 0x80 572 }; 573 574 enum { 575 FD_DIR_DSKCHG = 0x80 576 }; 577 506 578 #define FD_MULTI_TRACK(state) ((state) & FD_STATE_MULTI) 507 579 #define FD_DID_SEEK(state) ((state) & FD_STATE_SEEK) … … 523 595 /* HW */ 524 596 #ifndef VBOX 525 int irq _lvl;597 int irq; 526 598 int dma_chann; 527 599 #else … … 532 604 /* Controller state */ 533 605 QEMUTimer *result_timer; 534 uint8_t state; 535 uint8_t dma_en; 606 uint8_t sra; 607 uint8_t srb; 608 uint8_t dor; 609 uint8_t tdr; 610 uint8_t dsr; 611 uint8_t msr; 536 612 uint8_t cur_drv; 537 uint8_t bootsel; 613 uint8_t status0; 614 uint8_t status1; 615 uint8_t status2; 538 616 /* Command FIFO */ 539 617 uint8_t fifo[FD_SECTOR_LEN]; … … 542 620 uint8_t data_state; 543 621 uint8_t data_dir; 544 uint8_t int_status;545 622 uint8_t eot; /* last wanted sector */ 546 623 /* States kept only to be returned back */ … … 555 632 uint8_t pwrd; 556 633 /* Floppy drives */ 557 fdrive_t drives[2]; 634 uint8_t num_floppies; 635 fdrive_t drives[MAX_FD]; 636 uint8_t reset_sensei; 558 637 #ifdef VBOX 559 638 /** Pointer to device instance. */ … … 574 653 uint32_t retval; 575 654 576 switch (reg & 0x07) { 577 case 0x01: 655 switch (reg) { 656 case FD_REG_SRA: 657 retval = fdctrl_read_statusA(fdctrl); 658 break; 659 case FD_REG_SRB: 578 660 retval = fdctrl_read_statusB(fdctrl); 579 661 break; 580 case 0x02:662 case FD_REG_DOR: 581 663 retval = fdctrl_read_dor(fdctrl); 582 664 break; 583 case 0x03:665 case FD_REG_TDR: 584 666 retval = fdctrl_read_tape(fdctrl); 585 667 break; 586 case 0x04:668 case FD_REG_MSR: 587 669 retval = fdctrl_read_main_status(fdctrl); 588 670 break; 589 case 0x05:671 case FD_REG_FIFO: 590 672 retval = fdctrl_read_data(fdctrl); 591 673 break; 592 case 0x07:674 case FD_REG_DIR: 593 675 retval = fdctrl_read_dir(fdctrl); 594 676 break; … … 608 690 FLOPPY_DPRINTF("write reg%d: 0x%02x\n", reg & 7, value); 609 691 610 switch (reg & 0x07) {611 case 0x02:692 switch (reg) { 693 case FD_REG_DOR: 612 694 fdctrl_write_dor(fdctrl, value); 613 695 break; 614 case 0x03:696 case FD_REG_TDR: 615 697 fdctrl_write_tape(fdctrl, value); 616 698 break; 617 case 0x04:699 case FD_REG_DSR: 618 700 fdctrl_write_rate(fdctrl, value); 619 701 break; 620 case 0x05:702 case FD_REG_FIFO: 621 703 fdctrl_write_data(fdctrl, value); 622 704 break; … … 626 708 } 627 709 628 #ifndef VBOX 629 static void fd_change_cb (void *opaque) 630 { 631 fdrive_t *drv = opaque; 632 633 FLOPPY_DPRINTF("disk change\n"); 634 fd_revalidate(drv); 635 #if 0 636 fd_recalibrate(drv); 637 fdctrl_reset_fifo(drv->fdctrl); 638 fdctrl_raise_irq(drv->fdctrl, 0x20); 639 #endif 640 } 641 642 #else /* VBOX */ 710 #ifdef VBOX 643 711 /** 644 * Called when a medi ais mounted.712 * Called when a medium is mounted. 645 713 * 646 714 * @param pInterface Pointer to the interface structure … … 651 719 fdrive_t *drv = PDMIMOUNTNOTIFY_2_FDRIVE (pInterface); 652 720 LogFlow(("fdMountNotify:\n")); 653 fd_revalidate (drv);721 drv->fMediaChanged = true; 654 722 } 655 723 656 724 /** 657 * Called when a media is unmounted 658 * @param pInterface Pointer to the interface structure containing the called function pointer. 725 * Called when a medium is unmounted. 726 * @param pInterface Pointer to the interface structure 727 * containing the called function pointer. 659 728 */ 660 729 static DECLCALLBACK(void) fdUnmountNotify(PPDMIMOUNTNOTIFY pInterface) … … 662 731 fdrive_t *drv = PDMIMOUNTNOTIFY_2_FDRIVE (pInterface); 663 732 LogFlow(("fdUnmountNotify:\n")); 664 fd_revalidate (drv); 665 } 666 #endif 667 668 #ifndef VBOX 669 fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped, 670 uint32_t io_base, 671 BlockDriverState **fds) 672 { 673 fdctrl_t *fdctrl; 674 /* // int io_mem; */ 675 int i; 676 677 FLOPPY_DPRINTF("init controller\n"); 678 fdctrl = qemu_mallocz(sizeof(fdctrl_t)); 679 if (!fdctrl) 680 return NULL; 681 fdctrl->result_timer = qemu_new_timer(vm_clock, 682 fdctrl_result_timer, fdctrl); 683 684 fdctrl->version = 0x90; /* Intel 82078 controller */ 685 fdctrl->irq_lvl = irq_lvl; 686 fdctrl->dma_chann = dma_chann; 687 fdctrl->io_base = io_base; 688 fdctrl->config = 0x60; /* Implicit seek, polling & FIFO enabled */ 689 if (fdctrl->dma_chann != -1) { 690 fdctrl->dma_en = 1; 691 DMA_register_channel(dma_chann, &fdctrl_transfer_handler, fdctrl); 692 } else { 693 fdctrl->dma_en = 0; 694 } 695 for (i = 0; i < 2; i++) { 696 fd_init(&fdctrl->drives[i], fds[i]); 697 if (fds[i]) { 698 bdrv_set_change_cb(fds[i], 699 &fd_change_cb, &fdctrl->drives[i]); 700 } 701 } 702 fdctrl_reset(fdctrl, 0); 703 fdctrl->state = FD_CTRL_ACTIVE; 704 if (mem_mapped) { 705 FLOPPY_ERROR("memory mapped floppy not supported by now !\n"); 706 #if 0 707 io_mem = cpu_register_io_memory(0, fdctrl_mem_read, fdctrl_mem_write); 708 cpu_register_physical_memory(base, 0x08, io_mem); 709 #endif 710 } else { 711 register_ioport_read(io_base + 0x01, 5, 1, &fdctrl_read, fdctrl); 712 register_ioport_read(io_base + 0x07, 1, 1, &fdctrl_read, fdctrl); 713 register_ioport_write(io_base + 0x01, 5, 1, &fdctrl_write, fdctrl); 714 register_ioport_write(io_base + 0x07, 1, 1, &fdctrl_write, fdctrl); 715 } 716 for (i = 0; i < 2; i++) { 717 fd_revalidate(&fdctrl->drives[i]); 718 } 719 720 return fdctrl; 721 } 722 723 /* XXX: may change if moved to bdrv */ 724 int fdctrl_get_drive_type(fdctrl_t *fdctrl, int drive_num) 725 { 726 return fdctrl->drives[drive_num].drive; 733 drv->fMediaChanged = true; 727 734 } 728 735 #endif 729 736 730 737 /* Change IRQ state */ 731 static void fdctrl_reset_irq (fdctrl_t *fdctrl) 732 { 738 static void fdctrl_reset_irq(fdctrl_t *fdctrl) 739 { 740 if (!(fdctrl->sra & FD_SRA_INTPEND)) 741 return; 733 742 FLOPPY_DPRINTF("Reset interrupt\n"); 734 743 #ifdef VBOX 735 744 PDMDevHlpISASetIrq (fdctrl->pDevIns, fdctrl->irq_lvl, 0); 736 745 #else 737 pic_set_irq(fdctrl->irq_lvl, 0);738 #endif 739 fdctrl->s tate &= ~FD_CTRL_INTR;740 } 741 742 static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status)743 { 744 if ( ~(fdctrl->state & FD_CTRL_INTR)) {746 qemu_set_irq(fdctrl->irq, 0); 747 #endif 748 fdctrl->sra &= ~FD_SRA_INTPEND; 749 } 750 751 static void fdctrl_raise_irq(fdctrl_t *fdctrl, uint8_t status0) 752 { 753 if (!(fdctrl->sra & FD_SRA_INTPEND)) { 745 754 #ifdef VBOX 746 755 PDMDevHlpISASetIrq (fdctrl->pDevIns, fdctrl->irq_lvl, 1); 747 756 #else 748 pic_set_irq(fdctrl->irq_lvl, 1); 749 #endif 750 fdctrl->state |= FD_CTRL_INTR; 751 } 752 FLOPPY_DPRINTF("Set interrupt status to 0x%02x\n", status); 753 fdctrl->int_status = status; 757 qemu_set_irq(fdctrl->irq, 1); 758 #endif 759 fdctrl->sra |= FD_SRA_INTPEND; 760 } 761 fdctrl->reset_sensei = 0; 762 fdctrl->status0 = status0; 763 FLOPPY_DPRINTF("Set interrupt status to 0x%02x\n", fdctrl->status0); 754 764 } 755 765 756 766 /* Reset controller */ 757 static void fdctrl_reset 767 static void fdctrl_reset(fdctrl_t *fdctrl, int do_irq) 758 768 { 759 769 int i; … … 762 772 fdctrl_reset_irq(fdctrl); 763 773 /* Initialise controller */ 774 fdctrl->sra = 0; 775 fdctrl->srb = 0xc0; 776 #ifdef VBOX 777 if (!fdctrl->drives[1].pDrvBlock) 778 #else 779 if (!fdctrl->drives[1].bs) 780 #endif 781 fdctrl->sra |= FD_SRA_nDRV2; 764 782 fdctrl->cur_drv = 0; 783 fdctrl->dor = FD_DOR_nRESET; 784 fdctrl->dor |= (fdctrl->dma_chann != 0xff) ? FD_DOR_DMAEN : 0; 785 fdctrl->msr = FD_MSR_RQM; 765 786 /* FIFO state */ 766 787 fdctrl->data_pos = 0; 767 788 fdctrl->data_len = 0; 768 fdctrl->data_state = FD_STATE_CMD;789 fdctrl->data_state = 0; 769 790 fdctrl->data_dir = FD_DIR_WRITE; 770 791 for (i = 0; i < MAX_FD; i++) 771 fd_re set(&fdctrl->drives[i]);792 fd_recalibrate(&fdctrl->drives[i]); 772 793 fdctrl_reset_fifo(fdctrl); 773 if (do_irq) 774 fdctrl_raise_irq(fdctrl, 0xc0); 775 } 776 777 static inline fdrive_t *drv0 (fdctrl_t *fdctrl) 778 { 779 return &fdctrl->drives[fdctrl->bootsel]; 780 } 781 782 static inline fdrive_t *drv1 (fdctrl_t *fdctrl) 783 { 784 return &fdctrl->drives[1 - fdctrl->bootsel]; 785 } 786 787 static fdrive_t *get_cur_drv (fdctrl_t *fdctrl) 788 { 789 return fdctrl->cur_drv == 0 ? drv0(fdctrl) : drv1(fdctrl); 794 if (do_irq) { 795 fdctrl_raise_irq(fdctrl, FD_SR0_RDYCHG); 796 fdctrl->reset_sensei = FD_RESET_SENSEI_COUNT; 797 } 798 } 799 800 static inline fdrive_t *drv0(fdctrl_t *fdctrl) 801 { 802 return &fdctrl->drives[(fdctrl->tdr & FD_TDR_BOOTSEL) >> 2]; 803 } 804 805 static inline fdrive_t *drv1(fdctrl_t *fdctrl) 806 { 807 if ((fdctrl->tdr & FD_TDR_BOOTSEL) < (1 << 2)) 808 return &fdctrl->drives[1]; 809 else 810 return &fdctrl->drives[0]; 811 } 812 813 #if MAX_FD == 4 814 static inline fdrive_t *drv2(fdctrl_t *fdctrl) 815 { 816 if ((fdctrl->tdr & FD_TDR_BOOTSEL) < (2 << 2)) 817 return &fdctrl->drives[2]; 818 else 819 return &fdctrl->drives[1]; 820 } 821 822 static inline fdrive_t *drv3(fdctrl_t *fdctrl) 823 { 824 if ((fdctrl->tdr & FD_TDR_BOOTSEL) < (3 << 2)) 825 return &fdctrl->drives[3]; 826 else 827 return &fdctrl->drives[2]; 828 } 829 #endif 830 831 static fdrive_t *get_cur_drv(fdctrl_t *fdctrl) 832 { 833 switch (fdctrl->cur_drv) { 834 case 0: return drv0(fdctrl); 835 case 1: return drv1(fdctrl); 836 #if MAX_FD == 4 837 case 2: return drv2(fdctrl); 838 case 3: return drv3(fdctrl); 839 #endif 840 default: return NULL; 841 } 842 } 843 844 /* Status A register : 0x00 (read-only) */ 845 static uint32_t fdctrl_read_statusA(fdctrl_t *fdctrl) 846 { 847 uint32_t retval = fdctrl->sra; 848 849 FLOPPY_DPRINTF("status register A: 0x%02x\n", retval); 850 851 return retval; 790 852 } 791 853 792 854 /* Status B register : 0x01 (read-only) */ 793 static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl) 794 { 795 FLOPPY_DPRINTF("status register: 0x00\n"); 796 return 0; 855 static uint32_t fdctrl_read_statusB(fdctrl_t *fdctrl) 856 { 857 uint32_t retval = fdctrl->srb; 858 859 FLOPPY_DPRINTF("status register B: 0x%02x\n", retval); 860 861 return retval; 797 862 } 798 863 799 864 /* Digital output register : 0x02 */ 800 static uint32_t fdctrl_read_dor (fdctrl_t *fdctrl) 801 { 802 uint32_t retval = 0; 803 804 /* Drive motors state indicators */ 805 #ifndef VBOX 806 if (drv0(fdctrl)->drflags & FDRIVE_MOTOR_ON) 807 retval |= 1 << 5; 808 if (drv1(fdctrl)->drflags & FDRIVE_MOTOR_ON) 809 retval |= 1 << 4; 810 #else 811 /* bit4: 0 = drive 0 motor off/1 = on */ 812 if (drv0(fdctrl)->drflags & FDRIVE_MOTOR_ON) 813 retval |= RT_BIT(4); 814 /* bit5: 0 = drive 1 motor off/1 = on */ 815 if (drv1(fdctrl)->drflags & FDRIVE_MOTOR_ON) 816 retval |= RT_BIT(5); 817 #endif 818 /* DMA enable */ 819 retval |= fdctrl->dma_en << 3; 820 /* Reset indicator */ 821 retval |= (fdctrl->state & FD_CTRL_RESET) == 0 ? 0x04 : 0; 865 static uint32_t fdctrl_read_dor(fdctrl_t *fdctrl) 866 { 867 uint32_t retval = fdctrl->dor; 868 822 869 /* Selected drive */ 823 870 retval |= fdctrl->cur_drv; … … 827 874 } 828 875 829 static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value) 830 { 831 /* Reset mode */ 832 if (fdctrl->state & FD_CTRL_RESET) { 833 if (!(value & 0x04)) { 834 FLOPPY_DPRINTF("Floppy controller in RESET state !\n"); 835 return; 836 } 837 } 876 static void fdctrl_write_dor(fdctrl_t *fdctrl, uint32_t value) 877 { 838 878 FLOPPY_DPRINTF("digital output register set to 0x%02x\n", value); 839 /* Drive motors state indicators */ 840 if (value & 0x20) 841 fd_start(drv1(fdctrl)); 879 880 /* Motors */ 881 if (value & FD_DOR_MOTEN0) 882 fdctrl->srb |= FD_SRB_MTR0; 842 883 else 843 fd _stop(drv1(fdctrl));844 if (value & 0x10)845 fd _start(drv0(fdctrl));884 fdctrl->srb &= ~FD_SRB_MTR0; 885 if (value & FD_DOR_MOTEN1) 886 fdctrl->srb |= FD_SRB_MTR1; 846 887 else 847 fd_stop(drv0(fdctrl)); 848 /* DMA enable */ 849 #if 0 850 if (fdctrl->dma_chann != -1) 851 fdctrl->dma_en = 1 - ((value >> 3) & 1); 852 #endif 888 fdctrl->srb &= ~FD_SRB_MTR1; 889 890 /* Drive */ 891 if (value & 1) 892 fdctrl->srb |= FD_SRB_DR0; 893 else 894 fdctrl->srb &= ~FD_SRB_DR0; 895 853 896 /* Reset */ 854 if (!(value & 0x04)) {855 if ( !(fdctrl->state & FD_CTRL_RESET)) {897 if (!(value & FD_DOR_nRESET)) { 898 if (fdctrl->dor & FD_DOR_nRESET) { 856 899 FLOPPY_DPRINTF("controller enter RESET state\n"); 857 fdctrl->state |= FD_CTRL_RESET;858 900 } 859 901 } else { 860 if ( fdctrl->state & FD_CTRL_RESET) {902 if (!(fdctrl->dor & FD_DOR_nRESET)) { 861 903 FLOPPY_DPRINTF("controller out of RESET state\n"); 862 904 fdctrl_reset(fdctrl, 1); 863 fdctrl-> state &= ~(FD_CTRL_RESET | FD_CTRL_SLEEP);905 fdctrl->dsr &= ~FD_DSR_PWRDOWN; 864 906 } 865 907 } 866 908 /* Selected drive */ 867 fdctrl->cur_drv = value & 1; 909 fdctrl->cur_drv = value & FD_DOR_SELMASK; 910 911 fdctrl->dor = value; 868 912 } 869 913 870 914 /* Tape drive register : 0x03 */ 871 static uint32_t fdctrl_read_tape (fdctrl_t *fdctrl) 872 { 873 uint32_t retval = 0; 874 875 /* Disk boot selection indicator */ 876 retval |= fdctrl->bootsel << 2; 877 /* Tape indicators: never allowed */ 915 static uint32_t fdctrl_read_tape(fdctrl_t *fdctrl) 916 { 917 uint32_t retval = fdctrl->tdr; 918 878 919 FLOPPY_DPRINTF("tape drive register: 0x%02x\n", retval); 879 920 … … 881 922 } 882 923 883 static void fdctrl_write_tape 924 static void fdctrl_write_tape(fdctrl_t *fdctrl, uint32_t value) 884 925 { 885 926 /* Reset mode */ 886 if ( fdctrl->state & FD_CTRL_RESET) {927 if (!(fdctrl->dor & FD_DOR_nRESET)) { 887 928 FLOPPY_DPRINTF("Floppy controller in RESET state !\n"); 888 929 return; … … 890 931 FLOPPY_DPRINTF("tape drive register set to 0x%02x\n", value); 891 932 /* Disk boot selection indicator */ 892 fdctrl-> bootsel = (value >> 2) & 1;933 fdctrl->tdr = value & FD_TDR_BOOTSEL; 893 934 /* Tape indicators: never allow */ 894 935 } 895 936 896 937 /* Main status register : 0x04 (read) */ 897 static uint32_t fdctrl_read_main_status (fdctrl_t *fdctrl) 898 { 899 uint32_t retval = 0; 900 901 fdctrl->state &= ~(FD_CTRL_SLEEP | FD_CTRL_RESET); 902 if (!(fdctrl->state & FD_CTRL_BUSY)) { 903 /* Data transfer allowed */ 904 retval |= 0x80; 905 /* Data transfer direction indicator */ 906 if (fdctrl->data_dir == FD_DIR_READ) 907 retval |= 0x40; 908 } 909 /* Should handle 0x20 for SPECIFY command */ 910 /* Command busy indicator */ 911 if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA || 912 FD_STATE(fdctrl->data_state) == FD_STATE_STATUS) 913 retval |= 0x10; 938 static uint32_t fdctrl_read_main_status(fdctrl_t *fdctrl) 939 { 940 uint32_t retval = fdctrl->msr; 941 942 fdctrl->dsr &= ~FD_DSR_PWRDOWN; 943 fdctrl->dor |= FD_DOR_nRESET; 944 914 945 FLOPPY_DPRINTF("main status register: 0x%02x\n", retval); 915 946 … … 918 949 919 950 /* Data select rate register : 0x04 (write) */ 920 static void fdctrl_write_rate 951 static void fdctrl_write_rate(fdctrl_t *fdctrl, uint32_t value) 921 952 { 922 953 /* Reset mode */ 923 if ( fdctrl->state & FD_CTRL_RESET) {924 925 926 954 if (!(fdctrl->dor & FD_DOR_nRESET)) { 955 FLOPPY_DPRINTF("Floppy controller in RESET state !\n"); 956 return; 957 } 927 958 FLOPPY_DPRINTF("select rate register set to 0x%02x\n", value); 928 959 /* Reset: autoclear */ 929 if (value & 0x80) {930 fdctrl-> state |= FD_CTRL_RESET;960 if (value & FD_DSR_SWRESET) { 961 fdctrl->dor &= ~FD_DOR_nRESET; 931 962 fdctrl_reset(fdctrl, 1); 932 fdctrl->state &= ~FD_CTRL_RESET; 933 } 934 if (value & 0x40) { 935 fdctrl->state |= FD_CTRL_SLEEP; 963 fdctrl->dor |= FD_DOR_nRESET; 964 } 965 if (value & FD_DSR_PWRDOWN) { 936 966 fdctrl_reset(fdctrl, 1); 937 967 } 938 /* // fdctrl.precomp = (value >> 2) & 0x07; */ 968 fdctrl->dsr = value; 969 } 970 971 static int fdctrl_media_changed(fdrive_t *drv) 972 { 973 int ret; 974 975 #ifdef VBOX 976 if (!drv->pDrvBlock) 977 return 0; 978 ret = drv->fMediaChanged; 979 drv->fMediaChanged = false; 980 #else 981 if (!drv->bs) 982 return 0; 983 ret = bdrv_media_changed(drv->bs); 984 #endif 985 if (ret) { 986 fd_revalidate(drv); 987 } 988 return ret; 939 989 } 940 990 941 991 /* Digital input register : 0x07 (read-only) */ 942 static uint32_t fdctrl_read_dir 992 static uint32_t fdctrl_read_dir(fdctrl_t *fdctrl) 943 993 { 944 994 uint32_t retval = 0; 945 995 946 #ifndef VBOX 947 if (drv0(fdctrl)->drflags & FDRIVE_REVALIDATE || 948 drv1(fdctrl)->drflags & FDRIVE_REVALIDATE) 949 #else 950 fdrive_t *cur_drv = get_cur_drv(fdctrl); 951 if ( drv0(fdctrl)->drflags & FDRIVE_REVALIDATE 952 || drv1(fdctrl)->drflags & FDRIVE_REVALIDATE 953 || !cur_drv->fMediaPresent) 954 #endif 955 retval |= 0x80; 996 if (fdctrl_media_changed(drv0(fdctrl)) 997 || fdctrl_media_changed(drv1(fdctrl)) 998 #if MAX_FD == 4 999 || fdctrl_media_changed(drv2(fdctrl)) 1000 || fdctrl_media_changed(drv3(fdctrl)) 1001 #endif 1002 ) 1003 retval |= FD_DIR_DSKCHG; 956 1004 if (retval != 0) 957 1005 FLOPPY_DPRINTF("Floppy digital input register: 0x%02x\n", retval); 958 drv0(fdctrl)->drflags &= ~FDRIVE_REVALIDATE;959 drv1(fdctrl)->drflags &= ~FDRIVE_REVALIDATE;960 1006 961 1007 return retval; … … 963 1009 964 1010 /* FIFO state control */ 965 static void fdctrl_reset_fifo 1011 static void fdctrl_reset_fifo(fdctrl_t *fdctrl) 966 1012 { 967 1013 fdctrl->data_dir = FD_DIR_WRITE; 968 1014 fdctrl->data_pos = 0; 969 FD_SET_STATE(fdctrl->data_state, FD_STATE_CMD);1015 fdctrl->msr &= ~(FD_MSR_CMDBUSY | FD_MSR_DIO); 970 1016 } 971 1017 972 1018 /* Set FIFO status for the host to read */ 973 static void fdctrl_set_fifo 1019 static void fdctrl_set_fifo(fdctrl_t *fdctrl, int fifo_len, int do_irq) 974 1020 { 975 1021 fdctrl->data_dir = FD_DIR_READ; 976 1022 fdctrl->data_len = fifo_len; 977 1023 fdctrl->data_pos = 0; 978 FD_SET_STATE(fdctrl->data_state, FD_STATE_STATUS);1024 fdctrl->msr |= FD_MSR_CMDBUSY | FD_MSR_RQM | FD_MSR_DIO; 979 1025 if (do_irq) 980 1026 fdctrl_raise_irq(fdctrl, 0x00); … … 982 1028 983 1029 /* Set an error: unimplemented/unknown command */ 984 static void fdctrl_unimplemented (fdctrl_t *fdctrl) 985 { 986 #if 0 987 fdrive_t *cur_drv; 988 989 cur_drv = get_cur_drv(fdctrl); 990 fdctrl->fifo[0] = 0x60 | (cur_drv->head << 2) | fdctrl->cur_drv; 991 fdctrl->fifo[1] = 0x00; 992 fdctrl->fifo[2] = 0x00; 993 fdctrl_set_fifo(fdctrl, 3, 1); 994 #else 995 /* // fdctrl_reset_fifo(fdctrl); */ 996 fdctrl->fifo[0] = 0x80; 1030 static void fdctrl_unimplemented(fdctrl_t *fdctrl, int direction) 1031 { 1032 FLOPPY_ERROR("unimplemented command 0x%02x\n", fdctrl->fifo[0]); 1033 fdctrl->fifo[0] = FD_SR0_INVCMD; 997 1034 fdctrl_set_fifo(fdctrl, 1, 0); 998 #endif 1035 } 1036 1037 /* Seek to next sector */ 1038 static int fdctrl_seek_to_next_sect(fdctrl_t *fdctrl, fdrive_t *cur_drv) 1039 { 1040 FLOPPY_DPRINTF("seek to next sector (%d %02x %02x => %d)\n", 1041 cur_drv->head, cur_drv->track, cur_drv->sect, 1042 fd_sector(cur_drv)); 1043 /* XXX: cur_drv->sect >= cur_drv->last_sect should be an 1044 error in fact */ 1045 if (cur_drv->sect >= cur_drv->last_sect || 1046 cur_drv->sect == fdctrl->eot) { 1047 cur_drv->sect = 1; 1048 if (FD_MULTI_TRACK(fdctrl->data_state)) { 1049 if (cur_drv->head == 0 && 1050 (cur_drv->flags & FDISK_DBL_SIDES) != 0) { 1051 cur_drv->head = 1; 1052 } else { 1053 cur_drv->head = 0; 1054 cur_drv->track++; 1055 if ((cur_drv->flags & FDISK_DBL_SIDES) == 0) 1056 return 0; 1057 } 1058 } else { 1059 cur_drv->track++; 1060 return 0; 1061 } 1062 FLOPPY_DPRINTF("seek to next track (%d %02x %02x => %d)\n", 1063 cur_drv->head, cur_drv->track, 1064 cur_drv->sect, fd_sector(cur_drv)); 1065 } else { 1066 cur_drv->sect++; 1067 } 1068 return 1; 999 1069 } 1000 1070 1001 1071 /* Callback for transfer end (stop or abort) */ 1002 static void fdctrl_stop_transfer 1003 1072 static void fdctrl_stop_transfer(fdctrl_t *fdctrl, uint8_t status0, 1073 uint8_t status1, uint8_t status2) 1004 1074 { 1005 1075 fdrive_t *cur_drv; … … 1008 1078 FLOPPY_DPRINTF("transfer status: %02x %02x %02x (%02x)\n", 1009 1079 status0, status1, status2, 1010 status0 | (cur_drv->head << 2) | fdctrl->cur_drv);1011 fdctrl->fifo[0] = status0 | (cur_drv->head << 2) | fdctrl->cur_drv;1080 status0 | (cur_drv->head << 2) | GET_CUR_DRV(fdctrl)); 1081 fdctrl->fifo[0] = status0 | (cur_drv->head << 2) | GET_CUR_DRV(fdctrl); 1012 1082 fdctrl->fifo[1] = status1; 1013 1083 fdctrl->fifo[2] = status2; … … 1017 1087 fdctrl->fifo[6] = FD_SECTOR_SC; 1018 1088 fdctrl->data_dir = FD_DIR_READ; 1019 if ( fdctrl->state & FD_CTRL_BUSY) {1089 if (!(fdctrl->msr & FD_MSR_NONDMA)) { 1020 1090 #ifdef VBOX 1021 1091 PDMDevHlpDMASetDREQ (fdctrl->pDevIns, fdctrl->dma_chann, 0); … … 1023 1093 DMA_release_DREQ(fdctrl->dma_chann); 1024 1094 #endif 1025 fdctrl->state &= ~FD_CTRL_BUSY; 1026 } 1095 } 1096 fdctrl->msr |= FD_MSR_RQM | FD_MSR_DIO; 1097 fdctrl->msr &= ~FD_MSR_NONDMA; 1027 1098 fdctrl_set_fifo(fdctrl, 7, 1); 1028 1099 } 1029 1100 1030 1101 /* Prepare a data transfer (either DMA or FIFO) */ 1031 static void fdctrl_start_transfer 1102 static void fdctrl_start_transfer(fdctrl_t *fdctrl, int direction) 1032 1103 { 1033 1104 fdrive_t *cur_drv; 1034 1105 uint8_t kh, kt, ks; 1035 int did_seek ;1036 1037 fdctrl->cur_drv = fdctrl->fifo[1] & 1;1106 int did_seek = 0; 1107 1108 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK); 1038 1109 cur_drv = get_cur_drv(fdctrl); 1039 1110 kt = fdctrl->fifo[2]; … … 1041 1112 ks = fdctrl->fifo[4]; 1042 1113 FLOPPY_DPRINTF("Start transfer at %d %d %02x %02x (%d)\n", 1043 fdctrl->cur_drv, kh, kt, ks, 1044 _fd_sector(kh, kt, ks, cur_drv->last_sect)); 1045 did_seek = 0; 1046 switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & 0x40)) { 1114 GET_CUR_DRV(fdctrl), kh, kt, ks, 1115 fd_sector_calc(kh, kt, ks, cur_drv->last_sect)); 1116 switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & FD_CONFIG_EIS)) { 1047 1117 case 2: 1048 1118 /* sect too big */ 1049 fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00);1119 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00); 1050 1120 fdctrl->fifo[3] = kt; 1051 1121 fdctrl->fifo[4] = kh; … … 1054 1124 case 3: 1055 1125 /* track too big */ 1056 fdctrl_stop_transfer(fdctrl, 0x40, 0x80, 0x00);1126 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_EC, 0x00); 1057 1127 fdctrl->fifo[3] = kt; 1058 1128 fdctrl->fifo[4] = kh; … … 1061 1131 case 4: 1062 1132 /* No seek enabled */ 1063 fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00);1133 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00); 1064 1134 fdctrl->fifo[3] = kt; 1065 1135 fdctrl->fifo[4] = kh; … … 1072 1142 break; 1073 1143 } 1144 1074 1145 /* Set the FIFO state */ 1075 1146 fdctrl->data_dir = direction; 1076 1147 fdctrl->data_pos = 0; 1077 FD_SET_STATE(fdctrl->data_state, FD_STATE_DATA); /* FIFO ready for data */1148 fdctrl->msr |= FD_MSR_CMDBUSY; 1078 1149 if (fdctrl->fifo[0] & 0x80) 1079 1150 fdctrl->data_state |= FD_STATE_MULTI; … … 1088 1159 } else { 1089 1160 int tmp; 1090 fdctrl->data_len = 128 << fdctrl->fifo[5];1091 tmp = ( cur_drv->last_sect- ks + 1);1161 fdctrl->data_len = 128 << (fdctrl->fifo[5] > 7 ? 7 : fdctrl->fifo[5]); 1162 tmp = (fdctrl->fifo[6] - ks + 1); 1092 1163 if (fdctrl->fifo[0] & 0x80) 1093 tmp += cur_drv->last_sect;1164 tmp += fdctrl->fifo[6]; 1094 1165 fdctrl->data_len *= tmp; 1095 1166 } 1096 1167 fdctrl->eot = fdctrl->fifo[6]; 1097 if (fdctrl->d ma_en) {1168 if (fdctrl->dor & FD_DOR_DMAEN) { 1098 1169 int dma_mode; 1099 1170 /* DMA transfer are enabled. Check if DMA channel is well programmed */ … … 1113 1184 (direction == FD_DIR_READ && dma_mode == 1)) { 1114 1185 /* No access is allowed until DMA transfer has completed */ 1115 fdctrl-> state |= FD_CTRL_BUSY;1186 fdctrl->msr &= ~FD_MSR_RQM; 1116 1187 /* Now, we just have to wait for the DMA controller to 1117 1188 * recall us... … … 1130 1201 } 1131 1202 FLOPPY_DPRINTF("start non-DMA transfer\n"); 1203 fdctrl->msr |= FD_MSR_NONDMA; 1204 if (direction != FD_DIR_WRITE) 1205 fdctrl->msr |= FD_MSR_DIO; 1132 1206 /* IO based transfer: calculate len */ 1133 1207 fdctrl_raise_irq(fdctrl, 0x00); … … 1137 1211 1138 1212 /* Prepare a transfer of deleted data */ 1139 static void fdctrl_start_transfer_del (fdctrl_t *fdctrl, int direction) 1140 { 1213 static void fdctrl_start_transfer_del(fdctrl_t *fdctrl, int direction) 1214 { 1215 FLOPPY_ERROR("fdctrl_start_transfer_del() unimplemented\n"); 1216 1141 1217 /* We don't handle deleted data, 1142 1218 * so we don't return *ANYTHING* 1143 1219 */ 1144 fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00); 1145 } 1146 1147 #if 0 1148 #include <stdio.h> 1149 #include <stdlib.h> 1150 1151 static FILE * f; 1152 static void dump (void *p, size_t len) 1153 { 1154 size_t n; 1155 1156 if (!f) { 1157 f = fopen ("dump", "wb"); 1158 if (!f) 1159 exit (0); 1160 } 1161 1162 n = fwrite (p, len, 1, f); 1163 if (n != 1) { 1164 AssertMsgFailed (("failed to dump\n")); 1165 exit (0); 1166 } 1167 } 1168 #else 1169 #define dump(a,b) do { } while (0) 1220 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00); 1221 } 1222 1223 #ifdef VBOX 1224 /* Block driver read/write wrappers. */ 1225 1226 static int blk_write(fdrive_t *drv, int64_t sector_num, const uint8_t *buf, int nb_sectors) 1227 { 1228 int rc; 1229 1230 drv->Led.Asserted.s.fWriting = drv->Led.Actual.s.fWriting = 1; 1231 1232 rc = drv->pDrvBlock->pfnWrite(drv->pDrvBlock, sector_num * FD_SECTOR_LEN, 1233 buf, nb_sectors * FD_SECTOR_LEN); 1234 1235 drv->Led.Actual.s.fWriting = 0; 1236 if (RT_FAILURE(rc)) 1237 AssertMsgFailed(("Floppy: Failure to read sector %d. rc=%Rrc", sector_num, rc)); 1238 1239 return rc; 1240 } 1241 1242 static int blk_read(fdrive_t *drv, int64_t sector_num, uint8_t *buf, int nb_sectors) 1243 { 1244 int rc; 1245 1246 drv->Led.Asserted.s.fReading = drv->Led.Actual.s.fReading = 1; 1247 1248 rc = drv->pDrvBlock->pfnRead(drv->pDrvBlock, sector_num * FD_SECTOR_LEN, 1249 buf, nb_sectors * FD_SECTOR_LEN); 1250 1251 drv->Led.Actual.s.fReading = 0; 1252 1253 if (RT_FAILURE(rc)) 1254 AssertMsgFailed(("Floppy: Failure to read sector %d. rc=%Rrc", sector_num, rc)); 1255 1256 return rc; 1257 } 1258 1170 1259 #endif 1171 1260 … … 1193 1282 1194 1283 fdctrl = opaque; 1195 if ( !(fdctrl->state & FD_CTRL_BUSY)) {1284 if (fdctrl->msr & FD_MSR_RQM) { 1196 1285 FLOPPY_DPRINTF("Not in DMA transfer mode !\n"); 1197 1286 return 0; … … 1200 1289 if (fdctrl->data_dir == FD_DIR_SCANE || fdctrl->data_dir == FD_DIR_SCANL || 1201 1290 fdctrl->data_dir == FD_DIR_SCANH) 1202 status2 = 0x04;1291 status2 = FD_SR2_SNS; 1203 1292 if (dma_len > fdctrl->data_len) 1204 1293 dma_len = fdctrl->data_len; 1205 1294 #ifndef VBOX 1206 if (cur_drv->bs == NULL) {1295 if (cur_drv->bs == NULL) 1207 1296 #else /* !VBOX */ 1208 if (cur_drv->pDrvBlock == NULL) { 1209 #endif 1297 if (cur_drv->pDrvBlock == NULL) 1298 #endif 1299 { 1210 1300 if (fdctrl->data_dir == FD_DIR_WRITE) 1211 fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00);1301 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00); 1212 1302 else 1213 fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00);1303 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00); 1214 1304 len = 0; 1215 1305 goto transfer_error; … … 1222 1312 FLOPPY_DPRINTF("copy %d bytes (%d %d %d) %d pos %d %02x " 1223 1313 "(%d-0x%08x 0x%08x)\n", len, dma_len, fdctrl->data_pos, 1224 fdctrl->data_len, fdctrl->cur_drv, cur_drv->head,1314 fdctrl->data_len, GET_CUR_DRV(fdctrl), cur_drv->head, 1225 1315 cur_drv->track, cur_drv->sect, fd_sector(cur_drv), 1226 fd_sector(cur_drv) * 512);1316 fd_sector(cur_drv) * FD_SECTOR_LEN); 1227 1317 if (fdctrl->data_dir != FD_DIR_WRITE || 1228 1318 len < FD_SECTOR_LEN || rel_pos != 0) { 1229 1319 /* READ & SCAN commands and realign to a sector for WRITE */ 1230 #ifndef VBOX 1320 #ifdef VBOX 1321 rc = blk_read(cur_drv, fd_sector(cur_drv), fdctrl->fifo, 1); 1322 if (RT_FAILURE(rc)) 1323 #else 1231 1324 if (bdrv_read(cur_drv->bs, fd_sector(cur_drv), 1232 fdctrl->fifo, 1) < 0) { 1325 fdctrl->fifo, 1) < 0) 1326 #endif 1327 { 1233 1328 FLOPPY_DPRINTF("Floppy: error getting sector %d\n", 1234 1329 fd_sector(cur_drv)); … … 1236 1331 memset(fdctrl->fifo, 0, FD_SECTOR_LEN); 1237 1332 } 1238 #else1239 cur_drv->Led.Asserted.s.fReading1240 = cur_drv->Led.Actual.s.fReading = 1;1241 1242 rc = cur_drv->pDrvBlock->pfnRead (1243 cur_drv->pDrvBlock,1244 fd_sector (cur_drv) * 512,1245 fdctrl->fifo,1246 1 * 5121247 );1248 1249 cur_drv->Led.Actual.s.fReading = 0;1250 1251 if (RT_FAILURE (rc)) {1252 AssertMsgFailed (1253 ("Floppy: error getting sector %d, rc = %Rrc",1254 fd_sector (cur_drv), rc));1255 memset(fdctrl->fifo, 0, FD_SECTOR_LEN);1256 }1257 #endif1258 1333 } 1259 1334 switch (fdctrl->data_dir) { … … 1267 1342 fdctrl->data_pos, 1268 1343 len, &read); 1269 dump (fdctrl->fifo + rel_pos, len);1270 1344 AssertMsgRC (rc2, ("DMAWriteMemory -> %Rrc\n", rc2)); 1271 1345 } … … 1285 1359 * LED or attempt any writes. A real floppy doesn't attempt 1286 1360 * to write to readonly media either. */ 1287 fdctrl_stop_transfer (fdctrl, 0x60, 0x00 | (cur_drv->ro << 1),1288 1361 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, cur_drv->ro << 1, 1362 0x00); 1289 1363 goto transfer_error; 1290 1364 } … … 1299 1373 } 1300 1374 1301 cur_drv->Led.Asserted.s.fWriting 1302 = cur_drv->Led.Actual.s.fWriting = 1; 1303 1304 rc = cur_drv->pDrvBlock->pfnWrite ( 1305 cur_drv->pDrvBlock, 1306 fd_sector (cur_drv) * 512, 1307 fdctrl->fifo, 1308 1 * 512 1309 ); 1310 1311 cur_drv->Led.Actual.s.fWriting = 0; 1312 1313 if (RT_FAILURE (rc)) { 1314 AssertMsgFailed(("Floppy: error writing sector %d. rc=%Rrc", 1315 fd_sector (cur_drv), rc)); 1316 fdctrl_stop_transfer (fdctrl, 0x60, 0x00 | (cur_drv->ro << 1), 1317 0x00); 1318 goto transfer_error; 1319 } 1375 rc = blk_write(cur_drv, fd_sector(cur_drv), fdctrl->fifo, 1); 1376 if (RT_FAILURE(rc)) 1320 1377 #else 1321 1378 DMA_read_memory (nchan, fdctrl->fifo + rel_pos, 1322 1379 fdctrl->data_pos, len); 1323 /* cpu_physical_memory_read(addr + fdctrl->data_pos, */1324 /* fdctrl->fifo + rel_pos, len); */1325 1380 if (bdrv_write(cur_drv->bs, fd_sector(cur_drv), 1326 fdctrl->fifo, 1) < 0) { 1327 FLOPPY_ERROR("writting sector %d\n", fd_sector(cur_drv)); 1328 fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00); 1381 fdctrl->fifo, 1) < 0) 1382 #endif 1383 { 1384 FLOPPY_ERROR("writing sector %d\n", fd_sector(cur_drv)); 1385 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00); 1329 1386 goto transfer_error; 1330 1387 } 1331 #endif1332 1388 break; 1333 1389 default: … … 1344 1400 DMA_read_memory (nchan, tmpbuf, fdctrl->data_pos, len); 1345 1401 #endif 1346 /* cpu_physical_memory_read(addr + fdctrl->data_pos, */1347 /* tmpbuf, len); */1348 1402 ret = memcmp(tmpbuf, fdctrl->fifo + rel_pos, len); 1349 1403 if (ret == 0) { 1350 status2 = 0x08;1404 status2 = FD_SR2_SEH; 1351 1405 goto end_transfer; 1352 1406 } … … 1363 1417 if (rel_pos == 0) { 1364 1418 /* Seek to next sector */ 1365 FLOPPY_DPRINTF("seek to next sector (%d %02x %02x => %d) (%d)\n", 1366 cur_drv->head, cur_drv->track, cur_drv->sect, 1367 fd_sector(cur_drv), 1368 fdctrl->data_pos - len); 1369 /* XXX: cur_drv->sect >= cur_drv->last_sect should be an 1370 error in fact */ 1371 if (cur_drv->sect >= cur_drv->last_sect || 1372 cur_drv->sect == fdctrl->eot) { 1373 cur_drv->sect = 1; 1374 if (FD_MULTI_TRACK(fdctrl->data_state)) { 1375 if (cur_drv->head == 0 && 1376 (cur_drv->flags & FDISK_DBL_SIDES) != 0) { 1377 cur_drv->head = 1; 1378 } else { 1379 cur_drv->head = 0; 1380 cur_drv->track++; 1381 if ((cur_drv->flags & FDISK_DBL_SIDES) == 0) 1382 break; 1383 } 1384 } else { 1385 cur_drv->track++; 1386 break; 1387 } 1388 FLOPPY_DPRINTF("seek to next track (%d %02x %02x => %d)\n", 1389 cur_drv->head, cur_drv->track, 1390 cur_drv->sect, fd_sector(cur_drv)); 1391 } else { 1392 cur_drv->sect++; 1393 } 1419 if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv)) 1420 break; 1394 1421 } 1395 1422 } … … 1401 1428 fdctrl->data_dir == FD_DIR_SCANL || 1402 1429 fdctrl->data_dir == FD_DIR_SCANH) 1403 status2 = 0x08;1430 status2 = FD_SR2_SEH; 1404 1431 if (FD_DID_SEEK(fdctrl->data_state)) 1405 status0 |= 0x20;1432 status0 |= FD_SR0_SEEK; 1406 1433 fdctrl->data_len -= len; 1407 /* if (fdctrl->data_len == 0) */1408 1434 fdctrl_stop_transfer(fdctrl, status0, status1, status2); 1409 1435 transfer_error: … … 1412 1438 } 1413 1439 1414 #if 0 1415 { 1416 fdctrl_t *fdctrl; 1440 /* Data register : 0x05 */ 1441 static uint32_t fdctrl_read_data(fdctrl_t *fdctrl) 1442 { 1417 1443 fdrive_t *cur_drv; 1418 int len, start_pos, rel_pos; 1419 uint8_t status0 = 0x00, status1 = 0x00, status2 = 0x00; 1420 1421 fdctrl = opaque; 1422 if (!(fdctrl->state & FD_CTRL_BUSY)) { 1423 FLOPPY_DPRINTF("Not in DMA transfer mode !\n"); 1444 uint32_t retval = 0; 1445 unsigned pos; 1446 #ifdef VBOX 1447 int rc; 1448 #endif 1449 1450 cur_drv = get_cur_drv(fdctrl); 1451 fdctrl->dsr &= ~FD_DSR_PWRDOWN; 1452 if (!(fdctrl->msr & FD_MSR_RQM) || !(fdctrl->msr & FD_MSR_DIO)) { 1453 FLOPPY_ERROR("controller not ready for reading\n"); 1424 1454 return 0; 1425 1455 } 1426 cur_drv = get_cur_drv(fdctrl); 1427 if (fdctrl->data_dir == FD_DIR_SCANE || fdctrl->data_dir == FD_DIR_SCANL || 1428 fdctrl->data_dir == FD_DIR_SCANH) 1429 status2 = 0x04; 1430 if (size > fdctrl->data_len) 1431 size = fdctrl->data_len; 1432 #ifndef VBOX 1433 if (cur_drv->bs == NULL) { 1456 pos = fdctrl->data_pos; 1457 if (fdctrl->msr & FD_MSR_NONDMA) { 1458 pos %= FD_SECTOR_LEN; 1459 if (pos == 0) { 1460 if (fdctrl->data_pos != 0) 1461 if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv)) { 1462 FLOPPY_DPRINTF("error seeking to next sector %d\n", 1463 fd_sector(cur_drv)); 1464 return 0; 1465 } 1466 #ifdef VBOX 1467 rc = blk_read(cur_drv, fd_sector(cur_drv), fdctrl->fifo, 1); 1468 if (RT_FAILURE(rc)) 1434 1469 #else 1435 if (cur_drv->pDrvBase == NULL) { 1436 #endif 1437 if (fdctrl->data_dir == FD_DIR_WRITE) 1438 fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00); 1439 else 1440 fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00); 1441 len = 0; 1442 goto transfer_error; 1443 } 1444 rel_pos = fdctrl->data_pos % FD_SECTOR_LEN; 1445 for (start_pos = fdctrl->data_pos; fdctrl->data_pos < size;) { 1446 len = size - fdctrl->data_pos; 1447 if (len + rel_pos > FD_SECTOR_LEN) 1448 len = FD_SECTOR_LEN - rel_pos; 1449 FLOPPY_DPRINTF("copy %d bytes (%d %d %d) %d pos %d %02x %02x " 1450 "(%d-0x%08x 0x%08x)\n", len, size, fdctrl->data_pos, 1451 fdctrl->data_len, fdctrl->cur_drv, cur_drv->head, 1452 cur_drv->track, cur_drv->sect, fd_sector(cur_drv), 1453 fd_sector(cur_drv) * 512, addr); 1454 if (fdctrl->data_dir != FD_DIR_WRITE || 1455 len < FD_SECTOR_LEN || rel_pos != 0) { 1456 /* READ & SCAN commands and realign to a sector for WRITE */ 1457 #ifndef VBOX 1458 if (bdrv_read(cur_drv->bs, fd_sector(cur_drv), 1459 fdctrl->fifo, 1) < 0) { 1460 FLOPPY_DPRINTF("Floppy: error getting sector %d\n", 1470 if (bdrv_read(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1) < 0) 1471 #endif 1472 { 1473 FLOPPY_DPRINTF("error getting sector %d\n", 1461 1474 fd_sector(cur_drv)); 1462 1475 /* Sure, image size is too small... */ 1463 1476 memset(fdctrl->fifo, 0, FD_SECTOR_LEN); 1464 1477 } 1465 #else1466 int rc;1467 1468 cur_drv->Led.Asserted.s.fReading1469 = cur_drv->Led.Actual.s.fReading = 1;1470 1471 rc = cur_drv->pDrvBlock->pfnRead (1472 cur_drv->pDrvBlock,1473 fd_sector (cur_drv) * 512,1474 fdctrl->fifo,1475 1 * 5121476 );1477 1478 cur_drv->Led.Actual.s.fReading = 0;1479 1480 if (RT_FAILURE (rc)) {1481 AssertMsgFailed (1482 ("Floppy: error getting sector %d. rc=%Rrc\n",1483 fd_sector(cur_drv), rc));1484 /* Sure, image size is too small... */1485 memset(fdctrl->fifo, 0, FD_SECTOR_LEN);1486 }1487 /* *p_fd_activity = 1; */1488 #endif1489 }1490 switch (fdctrl->data_dir) {1491 case FD_DIR_READ:1492 /* READ commands */1493 #ifdef VBOX1494 PDMDevHlpPhysWrite (fdctrl->pDevIns, addr + fdctrl->data_pos,1495 fdctrl->fifo + rel_pos, len);1496 #else1497 cpu_physical_memory_write(addr + fdctrl->data_pos,1498 fdctrl->fifo + rel_pos, len);1499 #endif1500 break;1501 case FD_DIR_WRITE:1502 /* WRITE commands */1503 #ifdef VBOX1504 {1505 int rc;1506 1507 PDMDevHlpPhysRead (fdctrl->pDevIns, addr + fdctrl->data_pos,1508 fdctrl->fifo + rel_pos, len);1509 1510 cur_drv->Led.Asserted.s.fWriting1511 = cur_drv->Led.Actual.s.fWriting = 1;1512 1513 rc = cur_drv->pDrvBlock->pfnWrite (1514 cur_drv->pDrvBlock,1515 fd_sector (cur_drv) * 512,1516 fdctrl->fifo,1517 1 * 5121518 );1519 1520 cur_drv->Led.Actual.s.fWriting = 0;1521 1522 if (RT_FAILURE (rc)) {1523 AssertMsgFailed (1524 ("Floppy: error writting sector %d. rc=%Rrc\n",1525 fd_sector(cur_drv), rc));1526 fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00);1527 goto transfer_error;1528 }1529 }1530 /* *p_fd_activity = 2; */1531 #else /* !VBOX */1532 cpu_physical_memory_read(addr + fdctrl->data_pos,1533 fdctrl->fifo + rel_pos, len);1534 if (bdrv_write(cur_drv->bs, fd_sector(cur_drv),1535 fdctrl->fifo, 1) < 0) {1536 FLOPPY_ERROR("writting sector %d\n", fd_sector(cur_drv));1537 fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00);1538 goto transfer_error;1539 }1540 #endif1541 break;1542 default:1543 /* SCAN commands */1544 {1545 uint8_t tmpbuf[FD_SECTOR_LEN];1546 int ret;1547 #ifdef VBOX1548 PDMDevHlpPhysRead (fdctrl->pDevIns, addr + fdctrl->data_pos,1549 tmpbuf, len);1550 #else1551 cpu_physical_memory_read(addr + fdctrl->data_pos,1552 tmpbuf, len);1553 #endif1554 ret = memcmp(tmpbuf, fdctrl->fifo + rel_pos, len);1555 if (ret == 0) {1556 status2 = 0x08;1557 goto end_transfer;1558 }1559 if ((ret < 0 && fdctrl->data_dir == FD_DIR_SCANL) ||1560 (ret > 0 && fdctrl->data_dir == FD_DIR_SCANH)) {1561 status2 = 0x00;1562 goto end_transfer;1563 }1564 }1565 break;1566 }1567 fdctrl->data_pos += len;1568 rel_pos = fdctrl->data_pos % FD_SECTOR_LEN;1569 if (rel_pos == 0) {1570 /* Seek to next sector */1571 FLOPPY_DPRINTF("seek to next sector (%d %02x %02x => %d) (%d)\n",1572 cur_drv->head, cur_drv->track, cur_drv->sect,1573 fd_sector(cur_drv),1574 fdctrl->data_pos - size);1575 /* XXX: cur_drv->sect >= cur_drv->last_sect should be an1576 error in fact */1577 if (cur_drv->sect >= cur_drv->last_sect ||1578 cur_drv->sect == fdctrl->eot) {1579 cur_drv->sect = 1;1580 if (FD_MULTI_TRACK(fdctrl->data_state)) {1581 if (cur_drv->head == 0 &&1582 (cur_drv->flags & FDISK_DBL_SIDES) != 0) {1583 cur_drv->head = 1;1584 } else {1585 cur_drv->head = 0;1586 cur_drv->track++;1587 if ((cur_drv->flags & FDISK_DBL_SIDES) == 0)1588 break;1589 }1590 } else {1591 cur_drv->track++;1592 break;1593 }1594 FLOPPY_DPRINTF("seek to next track (%d %02x %02x => %d)\n",1595 cur_drv->head, cur_drv->track,1596 cur_drv->sect, fd_sector(cur_drv));1597 } else {1598 cur_drv->sect++;1599 }1600 }1601 }1602 end_transfer:1603 len = fdctrl->data_pos - start_pos;1604 FLOPPY_DPRINTF("end transfer %d %d %d\n",1605 fdctrl->data_pos, len, fdctrl->data_len);1606 if (fdctrl->data_dir == FD_DIR_SCANE ||1607 fdctrl->data_dir == FD_DIR_SCANL ||1608 fdctrl->data_dir == FD_DIR_SCANH)1609 status2 = 0x08;1610 if (FD_DID_SEEK(fdctrl->data_state))1611 status0 |= 0x20;1612 fdctrl->data_len -= len;1613 /* // if (fdctrl->data_len == 0) */1614 fdctrl_stop_transfer(fdctrl, status0, status1, status2);1615 transfer_error:1616 1617 return len;1618 }1619 #endif1620 1621 /* Data register : 0x05 */1622 static uint32_t fdctrl_read_data (fdctrl_t *fdctrl)1623 {1624 fdrive_t *cur_drv;1625 uint32_t retval = 0;1626 unsigned pos, len;1627 #ifdef VBOX1628 int rc;1629 #endif1630 1631 cur_drv = get_cur_drv(fdctrl);1632 fdctrl->state &= ~FD_CTRL_SLEEP;1633 if (FD_STATE(fdctrl->data_state) == FD_STATE_CMD) {1634 FLOPPY_ERROR("can't read data in CMD state\n");1635 return 0;1636 }1637 pos = fdctrl->data_pos;1638 if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA) {1639 pos %= FD_SECTOR_LEN;1640 if (pos == 0) {1641 len = fdctrl->data_len - fdctrl->data_pos;1642 if (len > FD_SECTOR_LEN)1643 len = FD_SECTOR_LEN;1644 #ifdef VBOX1645 cur_drv->Led.Asserted.s.fReading1646 = cur_drv->Led.Actual.s.fReading = 1;1647 1648 Assert(len <= sizeof(fdctrl->fifo));1649 rc = cur_drv->pDrvBlock->pfnRead (1650 cur_drv->pDrvBlock,1651 fd_sector (cur_drv) * 512,1652 fdctrl->fifo,1653 len1654 );1655 1656 cur_drv->Led.Actual.s.fReading = 0;1657 1658 if (RT_FAILURE (rc)) {1659 AssertMsgFailed (1660 ("Floppy: Failure to read sector %d. rc=%Rrc",1661 fd_sector (cur_drv), rc));1662 }1663 #else1664 bdrv_read(cur_drv->bs, fd_sector(cur_drv),1665 fdctrl->fifo, len);1666 #endif1667 1478 } 1668 1479 } … … 1673 1484 * then from status mode to command mode 1674 1485 */ 1675 if ( FD_STATE(fdctrl->data_state) == FD_STATE_DATA) {1676 fdctrl_stop_transfer(fdctrl, 0x20, 0x00, 0x00);1486 if (fdctrl->msr & FD_MSR_NONDMA) { 1487 fdctrl_stop_transfer(fdctrl, FD_SR0_SEEK, 0x00, 0x00); 1677 1488 } else { 1678 1489 fdctrl_reset_fifo(fdctrl); … … 1685 1496 } 1686 1497 1687 static void fdctrl_format_sector 1498 static void fdctrl_format_sector(fdctrl_t *fdctrl) 1688 1499 { 1689 1500 fdrive_t *cur_drv; 1690 1501 uint8_t kh, kt, ks; 1691 int did_seek;1692 1502 #ifdef VBOX 1693 1503 int ok = 0, rc; 1694 1504 #endif 1695 1505 1696 fdctrl->cur_drv = fdctrl->fifo[1] & 1;1506 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK); 1697 1507 cur_drv = get_cur_drv(fdctrl); 1698 1508 kt = fdctrl->fifo[6]; … … 1700 1510 ks = fdctrl->fifo[8]; 1701 1511 FLOPPY_DPRINTF("format sector at %d %d %02x %02x (%d)\n", 1702 fdctrl->cur_drv, kh, kt, ks, 1703 _fd_sector(kh, kt, ks, cur_drv->last_sect)); 1704 did_seek = 0; 1705 switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & 0x40)) { 1512 GET_CUR_DRV(fdctrl), kh, kt, ks, 1513 fd_sector_calc(kh, kt, ks, cur_drv->last_sect)); 1514 switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & FD_CONFIG_EIS)) { 1706 1515 case 2: 1707 1516 /* sect too big */ 1708 fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00);1517 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00); 1709 1518 fdctrl->fifo[3] = kt; 1710 1519 fdctrl->fifo[4] = kh; … … 1713 1522 case 3: 1714 1523 /* track too big */ 1715 fdctrl_stop_transfer(fdctrl, 0x40, 0x80, 0x00);1524 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_EC, 0x00); 1716 1525 fdctrl->fifo[3] = kt; 1717 1526 fdctrl->fifo[4] = kh; … … 1720 1529 case 4: 1721 1530 /* No seek enabled */ 1722 fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00);1531 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00); 1723 1532 fdctrl->fifo[3] = kt; 1724 1533 fdctrl->fifo[4] = kh; … … 1726 1535 return; 1727 1536 case 1: 1728 did_seek = 1;1729 1537 fdctrl->data_state |= FD_STATE_SEEK; 1730 1538 break; … … 1734 1542 memset(fdctrl->fifo, 0, FD_SECTOR_LEN); 1735 1543 #ifdef VBOX 1736 /* *p_fd_activity = 2; */1737 1544 if (cur_drv->pDrvBlock) { 1738 cur_drv->Led.Asserted.s.fWriting = cur_drv->Led.Actual.s.fWriting = 1; 1739 1740 rc = cur_drv->pDrvBlock->pfnWrite ( 1741 cur_drv->pDrvBlock, 1742 fd_sector (cur_drv) * 512, 1743 fdctrl->fifo, 1744 1 * 512 1745 ); 1746 1747 cur_drv->Led.Actual.s.fWriting = 0; 1748 1545 rc = blk_write(cur_drv, fd_sector(cur_drv), fdctrl->fifo, 1); 1749 1546 if (RT_FAILURE (rc)) { 1750 AssertMsgFailed (("Floppy: error formating sector %d. rc=%Rrc\n", 1751 fd_sector (cur_drv), rc)); 1752 fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00); 1753 } 1754 else { 1547 FLOPPY_ERROR("formatting sector %d\n", fd_sector(cur_drv)); 1548 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00); 1549 } else { 1755 1550 ok = 1; 1756 1551 } … … 1760 1555 if (cur_drv->bs == NULL || 1761 1556 bdrv_write(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1) < 0) { 1762 FLOPPY_ERROR("format ing sector %d\n", fd_sector(cur_drv));1763 fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00);1557 FLOPPY_ERROR("formatting sector %d\n", fd_sector(cur_drv)); 1558 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00); 1764 1559 } else { 1765 1560 #endif … … 1768 1563 /* Last sector done */ 1769 1564 if (FD_DID_SEEK(fdctrl->data_state)) 1770 fdctrl_stop_transfer(fdctrl, 0x20, 0x00, 0x00);1565 fdctrl_stop_transfer(fdctrl, FD_SR0_SEEK, 0x00, 0x00); 1771 1566 else 1772 1567 fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00); … … 1779 1574 } 1780 1575 1781 static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value) 1576 static void fdctrl_handle_lock(fdctrl_t *fdctrl, int direction) 1577 { 1578 fdctrl->lock = (fdctrl->fifo[0] & 0x80) ? 1 : 0; 1579 fdctrl->fifo[0] = fdctrl->lock << 4; 1580 fdctrl_set_fifo(fdctrl, 1, fdctrl->lock); 1581 } 1582 1583 static void fdctrl_handle_dumpreg(fdctrl_t *fdctrl, int direction) 1584 { 1585 fdrive_t *cur_drv = get_cur_drv(fdctrl); 1586 1587 /* Drives position */ 1588 fdctrl->fifo[0] = drv0(fdctrl)->track; 1589 fdctrl->fifo[1] = drv1(fdctrl)->track; 1590 #if MAX_FD == 4 1591 fdctrl->fifo[2] = drv2(fdctrl)->track; 1592 fdctrl->fifo[3] = drv3(fdctrl)->track; 1593 #else 1594 fdctrl->fifo[2] = 0; 1595 fdctrl->fifo[3] = 0; 1596 #endif 1597 /* timers */ 1598 fdctrl->fifo[4] = fdctrl->timer0; 1599 fdctrl->fifo[5] = (fdctrl->timer1 << 1) | (fdctrl->dor & FD_DOR_DMAEN ? 1 : 0); 1600 fdctrl->fifo[6] = cur_drv->last_sect; 1601 fdctrl->fifo[7] = (fdctrl->lock << 7) | 1602 (cur_drv->perpendicular << 2); 1603 fdctrl->fifo[8] = fdctrl->config; 1604 fdctrl->fifo[9] = fdctrl->precomp_trk; 1605 fdctrl_set_fifo(fdctrl, 10, 0); 1606 } 1607 1608 static void fdctrl_handle_version(fdctrl_t *fdctrl, int direction) 1609 { 1610 /* Controller's version */ 1611 fdctrl->fifo[0] = fdctrl->version; 1612 fdctrl_set_fifo(fdctrl, 1, 1); 1613 } 1614 1615 static void fdctrl_handle_partid(fdctrl_t *fdctrl, int direction) 1616 { 1617 fdctrl->fifo[0] = 0x41; /* Stepping 1 */ 1618 fdctrl_set_fifo(fdctrl, 1, 0); 1619 } 1620 1621 static void fdctrl_handle_restore(fdctrl_t *fdctrl, int direction) 1622 { 1623 fdrive_t *cur_drv = get_cur_drv(fdctrl); 1624 1625 /* Drives position */ 1626 drv0(fdctrl)->track = fdctrl->fifo[3]; 1627 drv1(fdctrl)->track = fdctrl->fifo[4]; 1628 #if MAX_FD == 4 1629 drv2(fdctrl)->track = fdctrl->fifo[5]; 1630 drv3(fdctrl)->track = fdctrl->fifo[6]; 1631 #endif 1632 /* timers */ 1633 fdctrl->timer0 = fdctrl->fifo[7]; 1634 fdctrl->timer1 = fdctrl->fifo[8]; 1635 cur_drv->last_sect = fdctrl->fifo[9]; 1636 fdctrl->lock = fdctrl->fifo[10] >> 7; 1637 cur_drv->perpendicular = (fdctrl->fifo[10] >> 2) & 0xF; 1638 fdctrl->config = fdctrl->fifo[11]; 1639 fdctrl->precomp_trk = fdctrl->fifo[12]; 1640 fdctrl->pwrd = fdctrl->fifo[13]; 1641 fdctrl_reset_fifo(fdctrl); 1642 } 1643 1644 static void fdctrl_handle_save(fdctrl_t *fdctrl, int direction) 1645 { 1646 fdrive_t *cur_drv = get_cur_drv(fdctrl); 1647 1648 fdctrl->fifo[0] = 0; 1649 fdctrl->fifo[1] = 0; 1650 /* Drives position */ 1651 fdctrl->fifo[2] = drv0(fdctrl)->track; 1652 fdctrl->fifo[3] = drv1(fdctrl)->track; 1653 #if MAX_FD == 4 1654 fdctrl->fifo[4] = drv2(fdctrl)->track; 1655 fdctrl->fifo[5] = drv3(fdctrl)->track; 1656 #else 1657 fdctrl->fifo[4] = 0; 1658 fdctrl->fifo[5] = 0; 1659 #endif 1660 /* timers */ 1661 fdctrl->fifo[6] = fdctrl->timer0; 1662 fdctrl->fifo[7] = fdctrl->timer1; 1663 fdctrl->fifo[8] = cur_drv->last_sect; 1664 fdctrl->fifo[9] = (fdctrl->lock << 7) | 1665 (cur_drv->perpendicular << 2); 1666 fdctrl->fifo[10] = fdctrl->config; 1667 fdctrl->fifo[11] = fdctrl->precomp_trk; 1668 fdctrl->fifo[12] = fdctrl->pwrd; 1669 fdctrl->fifo[13] = 0; 1670 fdctrl->fifo[14] = 0; 1671 fdctrl_set_fifo(fdctrl, 15, 1); 1672 } 1673 1674 static void fdctrl_handle_readid(fdctrl_t *fdctrl, int direction) 1675 { 1676 fdrive_t *cur_drv = get_cur_drv(fdctrl); 1677 1678 /* XXX: should set main status register to busy */ 1679 cur_drv->head = (fdctrl->fifo[1] >> 2) & 1; 1680 #ifdef VBOX 1681 TMTimerSetMillies(fdctrl->result_timer, 1000 / 50); 1682 #else 1683 qemu_mod_timer(fdctrl->result_timer, 1684 qemu_get_clock(vm_clock) + (get_ticks_per_sec() / 50)); 1685 #endif 1686 } 1687 1688 static void fdctrl_handle_format_track(fdctrl_t *fdctrl, int direction) 1782 1689 { 1783 1690 fdrive_t *cur_drv; 1691 1692 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK); 1693 cur_drv = get_cur_drv(fdctrl); 1694 fdctrl->data_state |= FD_STATE_FORMAT; 1695 if (fdctrl->fifo[0] & 0x80) 1696 fdctrl->data_state |= FD_STATE_MULTI; 1697 else 1698 fdctrl->data_state &= ~FD_STATE_MULTI; 1699 fdctrl->data_state &= ~FD_STATE_SEEK; 1700 cur_drv->bps = 1701 fdctrl->fifo[2] > 7 ? 16384 : 128 << fdctrl->fifo[2]; 1702 #if 0 1703 cur_drv->last_sect = 1704 cur_drv->flags & FDISK_DBL_SIDES ? fdctrl->fifo[3] : 1705 fdctrl->fifo[3] / 2; 1706 #else 1707 cur_drv->last_sect = fdctrl->fifo[3]; 1708 #endif 1709 /* TODO: implement format using DMA expected by the Bochs BIOS 1710 * and Linux fdformat (read 3 bytes per sector via DMA and fill 1711 * the sector with the specified fill byte 1712 */ 1713 fdctrl->data_state &= ~FD_STATE_FORMAT; 1714 fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00); 1715 } 1716 1717 static void fdctrl_handle_specify(fdctrl_t *fdctrl, int direction) 1718 { 1719 fdctrl->timer0 = (fdctrl->fifo[1] >> 4) & 0xF; 1720 fdctrl->timer1 = fdctrl->fifo[2] >> 1; 1721 if (fdctrl->fifo[2] & 1) 1722 fdctrl->dor &= ~FD_DOR_DMAEN; 1723 else 1724 fdctrl->dor |= FD_DOR_DMAEN; 1725 /* No result back */ 1726 fdctrl_reset_fifo(fdctrl); 1727 } 1728 1729 static void fdctrl_handle_sense_drive_status(fdctrl_t *fdctrl, int direction) 1730 { 1731 fdrive_t *cur_drv; 1732 1733 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK); 1734 cur_drv = get_cur_drv(fdctrl); 1735 cur_drv->head = (fdctrl->fifo[1] >> 2) & 1; 1736 /* 1 Byte status back */ 1737 fdctrl->fifo[0] = (cur_drv->ro << 6) | 1738 (cur_drv->track == 0 ? 0x10 : 0x00) | 1739 (cur_drv->head << 2) | 1740 GET_CUR_DRV(fdctrl) | 1741 0x28; 1742 fdctrl_set_fifo(fdctrl, 1, 0); 1743 } 1744 1745 static void fdctrl_handle_recalibrate(fdctrl_t *fdctrl, int direction) 1746 { 1747 fdrive_t *cur_drv; 1748 1749 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK); 1750 cur_drv = get_cur_drv(fdctrl); 1751 fd_recalibrate(cur_drv); 1752 fdctrl_reset_fifo(fdctrl); 1753 /* Raise Interrupt */ 1754 fdctrl_raise_irq(fdctrl, FD_SR0_SEEK); 1755 } 1756 1757 static void fdctrl_handle_sense_interrupt_status(fdctrl_t *fdctrl, int direction) 1758 { 1759 fdrive_t *cur_drv = get_cur_drv(fdctrl); 1760 1761 if(fdctrl->reset_sensei > 0) { 1762 fdctrl->fifo[0] = 1763 FD_SR0_RDYCHG + FD_RESET_SENSEI_COUNT - fdctrl->reset_sensei; 1764 fdctrl->reset_sensei--; 1765 } else { 1766 /* XXX: status0 handling is broken for read/write 1767 commands, so we do this hack. It should be suppressed 1768 ASAP */ 1769 fdctrl->fifo[0] = 1770 FD_SR0_SEEK | (cur_drv->head << 2) | GET_CUR_DRV(fdctrl); 1771 } 1772 1773 fdctrl->fifo[1] = cur_drv->track; 1774 fdctrl_set_fifo(fdctrl, 2, 0); 1775 fdctrl_reset_irq(fdctrl); 1776 fdctrl->status0 = FD_SR0_RDYCHG; 1777 } 1778 1779 static void fdctrl_handle_seek(fdctrl_t *fdctrl, int direction) 1780 { 1781 fdrive_t *cur_drv; 1782 1783 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK); 1784 cur_drv = get_cur_drv(fdctrl); 1785 fdctrl_reset_fifo(fdctrl); 1786 if (cur_drv->max_track && fdctrl->fifo[2] > cur_drv->max_track) { 1787 fdctrl_raise_irq(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK); 1788 } else { 1789 cur_drv->track = fdctrl->fifo[2]; 1790 /* Raise Interrupt */ 1791 fdctrl_raise_irq(fdctrl, FD_SR0_SEEK); 1792 } 1793 } 1794 1795 static void fdctrl_handle_perpendicular_mode(fdctrl_t *fdctrl, int direction) 1796 { 1797 fdrive_t *cur_drv = get_cur_drv(fdctrl); 1798 1799 if (fdctrl->fifo[1] & 0x80) 1800 cur_drv->perpendicular = fdctrl->fifo[1] & 0x7; 1801 /* No result back */ 1802 fdctrl_reset_fifo(fdctrl); 1803 } 1804 1805 static void fdctrl_handle_configure(fdctrl_t *fdctrl, int direction) 1806 { 1807 fdctrl->config = fdctrl->fifo[2]; 1808 fdctrl->precomp_trk = fdctrl->fifo[3]; 1809 /* No result back */ 1810 fdctrl_reset_fifo(fdctrl); 1811 } 1812 1813 static void fdctrl_handle_powerdown_mode(fdctrl_t *fdctrl, int direction) 1814 { 1815 fdctrl->pwrd = fdctrl->fifo[1]; 1816 fdctrl->fifo[0] = fdctrl->fifo[1]; 1817 fdctrl_set_fifo(fdctrl, 1, 1); 1818 } 1819 1820 static void fdctrl_handle_option(fdctrl_t *fdctrl, int direction) 1821 { 1822 /* No result back */ 1823 fdctrl_reset_fifo(fdctrl); 1824 } 1825 1826 static void fdctrl_handle_drive_specification_command(fdctrl_t *fdctrl, int direction) 1827 { 1828 fdrive_t *cur_drv = get_cur_drv(fdctrl); 1829 1830 if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x80) { 1831 /* Command parameters done */ 1832 if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x40) { 1833 fdctrl->fifo[0] = fdctrl->fifo[1]; 1834 fdctrl->fifo[2] = 0; 1835 fdctrl->fifo[3] = 0; 1836 fdctrl_set_fifo(fdctrl, 4, 1); 1837 } else { 1838 fdctrl_reset_fifo(fdctrl); 1839 } 1840 } else if (fdctrl->data_len > 7) { 1841 /* ERROR */ 1842 fdctrl->fifo[0] = 0x80 | 1843 (cur_drv->head << 2) | GET_CUR_DRV(fdctrl); 1844 fdctrl_set_fifo(fdctrl, 1, 1); 1845 } 1846 } 1847 1848 static void fdctrl_handle_relative_seek_out(fdctrl_t *fdctrl, int direction) 1849 { 1850 fdrive_t *cur_drv; 1851 1852 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK); 1853 cur_drv = get_cur_drv(fdctrl); 1854 if (fdctrl->fifo[2] + cur_drv->track >= cur_drv->max_track) { 1855 cur_drv->track = cur_drv->max_track - 1; 1856 } else { 1857 cur_drv->track += fdctrl->fifo[2]; 1858 } 1859 fdctrl_reset_fifo(fdctrl); 1860 /* Raise Interrupt */ 1861 fdctrl_raise_irq(fdctrl, FD_SR0_SEEK); 1862 } 1863 1864 static void fdctrl_handle_relative_seek_in(fdctrl_t *fdctrl, int direction) 1865 { 1866 fdrive_t *cur_drv; 1867 1868 SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK); 1869 cur_drv = get_cur_drv(fdctrl); 1870 if (fdctrl->fifo[2] > cur_drv->track) { 1871 cur_drv->track = 0; 1872 } else { 1873 cur_drv->track -= fdctrl->fifo[2]; 1874 } 1875 fdctrl_reset_fifo(fdctrl); 1876 /* Raise Interrupt */ 1877 fdctrl_raise_irq(fdctrl, FD_SR0_SEEK); 1878 } 1879 1880 static const struct { 1881 uint8_t value; 1882 uint8_t mask; 1883 const char* name; 1884 int parameters; 1885 void (*handler)(fdctrl_t *fdctrl, int direction); 1886 int direction; 1887 } handlers[] = { 1888 { FD_CMD_READ, 0x1f, "READ", 8, fdctrl_start_transfer, FD_DIR_READ }, 1889 { FD_CMD_WRITE, 0x3f, "WRITE", 8, fdctrl_start_transfer, FD_DIR_WRITE }, 1890 { FD_CMD_SEEK, 0xff, "SEEK", 2, fdctrl_handle_seek }, 1891 { FD_CMD_SENSE_INTERRUPT_STATUS, 0xff, "SENSE INTERRUPT STATUS", 0, fdctrl_handle_sense_interrupt_status }, 1892 { FD_CMD_RECALIBRATE, 0xff, "RECALIBRATE", 1, fdctrl_handle_recalibrate }, 1893 { FD_CMD_FORMAT_TRACK, 0xbf, "FORMAT TRACK", 5, fdctrl_handle_format_track }, 1894 { FD_CMD_READ_TRACK, 0xbf, "READ TRACK", 8, fdctrl_start_transfer, FD_DIR_READ }, 1895 { FD_CMD_RESTORE, 0xff, "RESTORE", 17, fdctrl_handle_restore }, /* part of READ DELETED DATA */ 1896 { FD_CMD_SAVE, 0xff, "SAVE", 0, fdctrl_handle_save }, /* part of READ DELETED DATA */ 1897 { FD_CMD_READ_DELETED, 0x1f, "READ DELETED DATA", 8, fdctrl_start_transfer_del, FD_DIR_READ }, 1898 { FD_CMD_SCAN_EQUAL, 0x1f, "SCAN EQUAL", 8, fdctrl_start_transfer, FD_DIR_SCANE }, 1899 { FD_CMD_VERIFY, 0x1f, "VERIFY", 8, fdctrl_unimplemented }, 1900 { FD_CMD_SCAN_LOW_OR_EQUAL, 0x1f, "SCAN LOW OR EQUAL", 8, fdctrl_start_transfer, FD_DIR_SCANL }, 1901 { FD_CMD_SCAN_HIGH_OR_EQUAL, 0x1f, "SCAN HIGH OR EQUAL", 8, fdctrl_start_transfer, FD_DIR_SCANH }, 1902 { FD_CMD_WRITE_DELETED, 0x3f, "WRITE DELETED DATA", 8, fdctrl_start_transfer_del, FD_DIR_WRITE }, 1903 { FD_CMD_READ_ID, 0xbf, "READ ID", 1, fdctrl_handle_readid }, 1904 { FD_CMD_SPECIFY, 0xff, "SPECIFY", 2, fdctrl_handle_specify }, 1905 { FD_CMD_SENSE_DRIVE_STATUS, 0xff, "SENSE DRIVE STATUS", 1, fdctrl_handle_sense_drive_status }, 1906 { FD_CMD_PERPENDICULAR_MODE, 0xff, "PERPENDICULAR MODE", 1, fdctrl_handle_perpendicular_mode }, 1907 { FD_CMD_CONFIGURE, 0xff, "CONFIGURE", 3, fdctrl_handle_configure }, 1908 { FD_CMD_POWERDOWN_MODE, 0xff, "POWERDOWN MODE", 2, fdctrl_handle_powerdown_mode }, 1909 { FD_CMD_OPTION, 0xff, "OPTION", 1, fdctrl_handle_option }, 1910 { FD_CMD_DRIVE_SPECIFICATION_COMMAND, 0xff, "DRIVE SPECIFICATION COMMAND", 5, fdctrl_handle_drive_specification_command }, 1911 { FD_CMD_RELATIVE_SEEK_OUT, 0xff, "RELATIVE SEEK OUT", 2, fdctrl_handle_relative_seek_out }, 1912 { FD_CMD_FORMAT_AND_WRITE, 0xff, "FORMAT AND WRITE", 10, fdctrl_unimplemented }, 1913 { FD_CMD_RELATIVE_SEEK_IN, 0xff, "RELATIVE SEEK IN", 2, fdctrl_handle_relative_seek_in }, 1914 { FD_CMD_LOCK, 0x7f, "LOCK", 0, fdctrl_handle_lock }, 1915 { FD_CMD_DUMPREG, 0xff, "DUMPREG", 0, fdctrl_handle_dumpreg }, 1916 { FD_CMD_VERSION, 0xff, "VERSION", 0, fdctrl_handle_version }, 1917 { FD_CMD_PART_ID, 0xff, "PART ID", 0, fdctrl_handle_partid }, 1918 { FD_CMD_WRITE, 0x1f, "WRITE (BeOS)", 8, fdctrl_start_transfer, FD_DIR_WRITE }, /* not in specification ; BeOS 4.5 bug */ 1919 { 0, 0, "unknown", 0, fdctrl_unimplemented }, /* default handler */ 1920 }; 1921 /* Associate command to an index in the 'handlers' array */ 1922 static uint8_t command_to_handler[256]; 1923 1924 static void fdctrl_write_data(fdctrl_t *fdctrl, uint32_t value) 1925 { 1926 fdrive_t *cur_drv; 1927 int pos; 1784 1928 1785 1929 cur_drv = get_cur_drv(fdctrl); 1786 1930 /* Reset mode */ 1787 if ( fdctrl->state & FD_CTRL_RESET) {1931 if (!(fdctrl->dor & FD_DOR_nRESET)) { 1788 1932 FLOPPY_DPRINTF("Floppy controller in RESET state !\n"); 1789 1933 return; 1790 1934 } 1791 fdctrl->state &= ~FD_CTRL_SLEEP; 1792 if (FD_STATE(fdctrl->data_state) == FD_STATE_STATUS) { 1793 FLOPPY_ERROR("can't write data in status mode\n"); 1935 if (!(fdctrl->msr & FD_MSR_RQM) || (fdctrl->msr & FD_MSR_DIO)) { 1936 FLOPPY_ERROR("controller not ready for writing\n"); 1794 1937 return; 1795 1938 } 1939 fdctrl->dsr &= ~FD_DSR_PWRDOWN; 1796 1940 /* Is it write command time ? */ 1797 if ( FD_STATE(fdctrl->data_state) == FD_STATE_DATA) {1941 if (fdctrl->msr & FD_MSR_NONDMA) { 1798 1942 /* FIFO data write */ 1799 fdctrl->fifo[fdctrl->data_pos++] = value; 1800 if (fdctrl->data_pos % FD_SECTOR_LEN == (FD_SECTOR_LEN - 1) || 1943 pos = fdctrl->data_pos++; 1944 pos %= FD_SECTOR_LEN; 1945 fdctrl->fifo[pos] = value; 1946 if (pos == FD_SECTOR_LEN - 1 || 1801 1947 fdctrl->data_pos == fdctrl->data_len) { 1802 1948 #ifdef VBOX 1803 int rc; 1804 /* *p_fd_activity = 2; */ 1805 cur_drv->Led.Asserted.s.fWriting 1806 = cur_drv->Led.Actual.s.fWriting = 1; 1807 1808 rc = cur_drv->pDrvBlock->pfnWrite ( 1809 cur_drv->pDrvBlock, 1810 fd_sector (cur_drv) * 512, 1811 fdctrl->fifo, 1812 FD_SECTOR_LEN 1813 ); 1814 1815 cur_drv->Led.Actual.s.fWriting = 0; 1816 1817 if (RT_FAILURE (rc)) { 1818 AssertMsgFailed ( 1819 ("Floppy: failed to write sector %d. rc=%Rrc\n", 1820 fd_sector (cur_drv), rc)); 1821 } 1949 blk_write(cur_drv, fd_sector(cur_drv), fdctrl->fifo, 1); 1822 1950 #else 1823 1951 bdrv_write(cur_drv->bs, fd_sector(cur_drv), 1824 fdctrl->fifo, FD_SECTOR_LEN);1952 fdctrl->fifo, 1); 1825 1953 #endif 1826 1954 } … … 1828 1956 * then from status mode to command mode 1829 1957 */ 1830 if ( FD_STATE(fdctrl->data_state) == FD_STATE_DATA)1831 fdctrl_stop_transfer(fdctrl, 0x20, 0x00, 0x00);1958 if (fdctrl->data_pos == fdctrl->data_len) 1959 fdctrl_stop_transfer(fdctrl, FD_SR0_SEEK, 0x00, 0x00); 1832 1960 return; 1833 1961 } 1834 1962 if (fdctrl->data_pos == 0) { 1835 1963 /* Command */ 1836 switch (value & 0x5F) { 1837 case 0x46: 1838 /* READ variants */ 1839 FLOPPY_DPRINTF("READ command\n"); 1840 /* 8 parameters cmd */ 1841 fdctrl->data_len = 9; 1842 goto enqueue; 1843 case 0x4C: 1844 /* READ_DELETED variants */ 1845 FLOPPY_DPRINTF("READ_DELETED command\n"); 1846 /* 8 parameters cmd */ 1847 fdctrl->data_len = 9; 1848 goto enqueue; 1849 case 0x50: 1850 /* SCAN_EQUAL variants */ 1851 FLOPPY_DPRINTF("SCAN_EQUAL command\n"); 1852 /* 8 parameters cmd */ 1853 fdctrl->data_len = 9; 1854 goto enqueue; 1855 case 0x56: 1856 /* VERIFY variants */ 1857 FLOPPY_DPRINTF("VERIFY command\n"); 1858 /* 8 parameters cmd */ 1859 fdctrl->data_len = 9; 1860 goto enqueue; 1861 case 0x59: 1862 /* SCAN_LOW_OR_EQUAL variants */ 1863 FLOPPY_DPRINTF("SCAN_LOW_OR_EQUAL command\n"); 1864 /* 8 parameters cmd */ 1865 fdctrl->data_len = 9; 1866 goto enqueue; 1867 case 0x5D: 1868 /* SCAN_HIGH_OR_EQUAL variants */ 1869 FLOPPY_DPRINTF("SCAN_HIGH_OR_EQUAL command\n"); 1870 /* 8 parameters cmd */ 1871 fdctrl->data_len = 9; 1872 goto enqueue; 1873 default: 1874 break; 1875 } 1876 switch (value & 0x7F) { 1877 case 0x45: 1878 /* WRITE variants */ 1879 FLOPPY_DPRINTF("WRITE command\n"); 1880 /* 8 parameters cmd */ 1881 fdctrl->data_len = 9; 1882 goto enqueue; 1883 case 0x49: 1884 /* WRITE_DELETED variants */ 1885 FLOPPY_DPRINTF("WRITE_DELETED command\n"); 1886 /* 8 parameters cmd */ 1887 fdctrl->data_len = 9; 1888 goto enqueue; 1889 default: 1890 break; 1891 } 1892 switch (value) { 1893 case 0x03: 1894 /* SPECIFY */ 1895 FLOPPY_DPRINTF("SPECIFY command\n"); 1896 /* 1 parameter cmd */ 1897 fdctrl->data_len = 3; 1898 goto enqueue; 1899 case 0x04: 1900 /* SENSE_DRIVE_STATUS */ 1901 FLOPPY_DPRINTF("SENSE_DRIVE_STATUS command\n"); 1902 /* 1 parameter cmd */ 1903 fdctrl->data_len = 2; 1904 goto enqueue; 1905 case 0x07: 1906 /* RECALIBRATE */ 1907 FLOPPY_DPRINTF("RECALIBRATE command\n"); 1908 /* 1 parameter cmd */ 1909 fdctrl->data_len = 2; 1910 goto enqueue; 1911 case 0x08: 1912 /* SENSE_INTERRUPT_STATUS */ 1913 FLOPPY_DPRINTF("SENSE_INTERRUPT_STATUS command (%02x)\n", 1914 fdctrl->int_status); 1915 /* No parameters cmd: returns status if no interrupt */ 1916 #if 0 1917 fdctrl->fifo[0] = 1918 fdctrl->int_status | (cur_drv->head << 2) | fdctrl->cur_drv; 1919 #else 1920 /* XXX: int_status handling is broken for read/write 1921 commands, so we do this hack. It should be suppressed 1922 ASAP */ 1923 fdctrl->fifo[0] = 1924 0x20 | (cur_drv->head << 2) | fdctrl->cur_drv; 1925 #endif 1926 fdctrl->fifo[1] = cur_drv->track; 1927 fdctrl_set_fifo(fdctrl, 2, 0); 1928 fdctrl_reset_irq(fdctrl); 1929 fdctrl->int_status = 0xC0; 1930 return; 1931 case 0x0E: 1932 /* DUMPREG */ 1933 FLOPPY_DPRINTF("DUMPREG command\n"); 1934 /* Drives position */ 1935 fdctrl->fifo[0] = drv0(fdctrl)->track; 1936 fdctrl->fifo[1] = drv1(fdctrl)->track; 1937 fdctrl->fifo[2] = 0; 1938 fdctrl->fifo[3] = 0; 1939 /* timers */ 1940 fdctrl->fifo[4] = fdctrl->timer0; 1941 fdctrl->fifo[5] = (fdctrl->timer1 << 1) | fdctrl->dma_en; 1942 fdctrl->fifo[6] = cur_drv->last_sect; 1943 fdctrl->fifo[7] = (fdctrl->lock << 7) | 1944 (cur_drv->perpendicular << 2); 1945 fdctrl->fifo[8] = fdctrl->config; 1946 fdctrl->fifo[9] = fdctrl->precomp_trk; 1947 fdctrl_set_fifo(fdctrl, 10, 0); 1948 return; 1949 case 0x0F: 1950 /* SEEK */ 1951 FLOPPY_DPRINTF("SEEK command\n"); 1952 /* 2 parameters cmd */ 1953 fdctrl->data_len = 3; 1954 goto enqueue; 1955 case 0x10: 1956 /* VERSION */ 1957 FLOPPY_DPRINTF("VERSION command\n"); 1958 /* No parameters cmd */ 1959 /* Controller's version */ 1960 fdctrl->fifo[0] = fdctrl->version; 1961 fdctrl_set_fifo(fdctrl, 1, 1); 1962 return; 1963 case 0x12: 1964 /* PERPENDICULAR_MODE */ 1965 FLOPPY_DPRINTF("PERPENDICULAR_MODE command\n"); 1966 /* 1 parameter cmd */ 1967 fdctrl->data_len = 2; 1968 goto enqueue; 1969 case 0x13: 1970 /* CONFIGURE */ 1971 FLOPPY_DPRINTF("CONFIGURE command\n"); 1972 /* 3 parameters cmd */ 1973 fdctrl->data_len = 4; 1974 goto enqueue; 1975 case 0x14: 1976 /* UNLOCK */ 1977 FLOPPY_DPRINTF("UNLOCK command\n"); 1978 /* No parameters cmd */ 1979 fdctrl->lock = 0; 1980 fdctrl->fifo[0] = 0; 1981 fdctrl_set_fifo(fdctrl, 1, 0); 1982 return; 1983 case 0x17: 1984 /* POWERDOWN_MODE */ 1985 FLOPPY_DPRINTF("POWERDOWN_MODE command\n"); 1986 /* 2 parameters cmd */ 1987 fdctrl->data_len = 3; 1988 goto enqueue; 1989 case 0x18: 1990 /* PART_ID */ 1991 FLOPPY_DPRINTF("PART_ID command\n"); 1992 /* No parameters cmd */ 1993 fdctrl->fifo[0] = 0x41; /* Stepping 1 */ 1994 fdctrl_set_fifo(fdctrl, 1, 0); 1995 return; 1996 case 0x2C: 1997 /* SAVE */ 1998 FLOPPY_DPRINTF("SAVE command\n"); 1999 /* No parameters cmd */ 2000 fdctrl->fifo[0] = 0; 2001 fdctrl->fifo[1] = 0; 2002 /* Drives position */ 2003 fdctrl->fifo[2] = drv0(fdctrl)->track; 2004 fdctrl->fifo[3] = drv1(fdctrl)->track; 2005 fdctrl->fifo[4] = 0; 2006 fdctrl->fifo[5] = 0; 2007 /* timers */ 2008 fdctrl->fifo[6] = fdctrl->timer0; 2009 fdctrl->fifo[7] = fdctrl->timer1; 2010 fdctrl->fifo[8] = cur_drv->last_sect; 2011 fdctrl->fifo[9] = (fdctrl->lock << 7) | 2012 (cur_drv->perpendicular << 2); 2013 fdctrl->fifo[10] = fdctrl->config; 2014 fdctrl->fifo[11] = fdctrl->precomp_trk; 2015 fdctrl->fifo[12] = fdctrl->pwrd; 2016 fdctrl->fifo[13] = 0; 2017 fdctrl->fifo[14] = 0; 2018 fdctrl_set_fifo(fdctrl, 15, 1); 2019 return; 2020 case 0x33: 2021 /* OPTION */ 2022 FLOPPY_DPRINTF("OPTION command\n"); 2023 /* 1 parameter cmd */ 2024 fdctrl->data_len = 2; 2025 goto enqueue; 2026 case 0x42: 2027 /* READ_TRACK */ 2028 FLOPPY_DPRINTF("READ_TRACK command\n"); 2029 /* 8 parameters cmd */ 2030 fdctrl->data_len = 9; 2031 goto enqueue; 2032 case 0x4A: 2033 /* READ_ID */ 2034 FLOPPY_DPRINTF("READ_ID command\n"); 2035 /* 1 parameter cmd */ 2036 fdctrl->data_len = 2; 2037 goto enqueue; 2038 case 0x4C: 2039 /* RESTORE */ 2040 FLOPPY_DPRINTF("RESTORE command\n"); 2041 /* 17 parameters cmd */ 2042 fdctrl->data_len = 18; 2043 goto enqueue; 2044 case 0x4D: 2045 /* FORMAT_TRACK */ 2046 FLOPPY_DPRINTF("FORMAT_TRACK command\n"); 2047 /* 5 parameters cmd */ 2048 fdctrl->data_len = 6; 2049 goto enqueue; 2050 case 0x8E: 2051 /* DRIVE_SPECIFICATION_COMMAND */ 2052 FLOPPY_DPRINTF("DRIVE_SPECIFICATION_COMMAND command\n"); 2053 /* 5 parameters cmd */ 2054 fdctrl->data_len = 6; 2055 goto enqueue; 2056 case 0x8F: 2057 /* RELATIVE_SEEK_OUT */ 2058 FLOPPY_DPRINTF("RELATIVE_SEEK_OUT command\n"); 2059 /* 2 parameters cmd */ 2060 fdctrl->data_len = 3; 2061 goto enqueue; 2062 case 0x94: 2063 /* LOCK */ 2064 FLOPPY_DPRINTF("LOCK command\n"); 2065 /* No parameters cmd */ 2066 fdctrl->lock = 1; 2067 fdctrl->fifo[0] = 0x10; 2068 fdctrl_set_fifo(fdctrl, 1, 1); 2069 return; 2070 case 0xCD: 2071 /* FORMAT_AND_WRITE */ 2072 FLOPPY_DPRINTF("FORMAT_AND_WRITE command\n"); 2073 /* 10 parameters cmd */ 2074 fdctrl->data_len = 11; 2075 goto enqueue; 2076 case 0xCF: 2077 /* RELATIVE_SEEK_IN */ 2078 FLOPPY_DPRINTF("RELATIVE_SEEK_IN command\n"); 2079 /* 2 parameters cmd */ 2080 fdctrl->data_len = 3; 2081 goto enqueue; 2082 default: 2083 /* Unknown command */ 2084 FLOPPY_ERROR("unknown command: 0x%02x\n", value); 2085 fdctrl_unimplemented(fdctrl); 2086 return; 2087 } 2088 } 2089 enqueue: 1964 pos = command_to_handler[value & 0xff]; 1965 FLOPPY_DPRINTF("%s command\n", handlers[pos].name); 1966 fdctrl->data_len = handlers[pos].parameters + 1; 1967 } 1968 2090 1969 FLOPPY_DPRINTF("%s: %02x\n", __func__, value); 2091 fdctrl->fifo[fdctrl->data_pos ] = value;2092 if ( ++fdctrl->data_pos == fdctrl->data_len) {1970 fdctrl->fifo[fdctrl->data_pos++] = value; 1971 if (fdctrl->data_pos == fdctrl->data_len) { 2093 1972 /* We now have all parameters 2094 1973 * and will be able to treat the command … … 2098 1977 return; 2099 1978 } 2100 switch (fdctrl->fifo[0] & 0x1F) { 2101 case 0x06: 2102 { 2103 /* READ variants */ 2104 FLOPPY_DPRINTF("treat READ command\n"); 2105 fdctrl_start_transfer(fdctrl, FD_DIR_READ); 2106 return; 2107 } 2108 case 0x0C: 2109 /* READ_DELETED variants */ 2110 /* // FLOPPY_DPRINTF("treat READ_DELETED command\n"); */ 2111 FLOPPY_ERROR("treat READ_DELETED command\n"); 2112 fdctrl_start_transfer_del(fdctrl, FD_DIR_READ); 2113 return; 2114 case 0x16: 2115 /* VERIFY variants */ 2116 /* // FLOPPY_DPRINTF("treat VERIFY command\n"); */ 2117 FLOPPY_ERROR("treat VERIFY command\n"); 2118 fdctrl_stop_transfer(fdctrl, 0x20, 0x00, 0x00); 2119 return; 2120 case 0x10: 2121 /* SCAN_EQUAL variants */ 2122 /* // FLOPPY_DPRINTF("treat SCAN_EQUAL command\n"); */ 2123 FLOPPY_ERROR("treat SCAN_EQUAL command\n"); 2124 fdctrl_start_transfer(fdctrl, FD_DIR_SCANE); 2125 return; 2126 case 0x19: 2127 /* SCAN_LOW_OR_EQUAL variants */ 2128 /* // FLOPPY_DPRINTF("treat SCAN_LOW_OR_EQUAL command\n"); */ 2129 FLOPPY_ERROR("treat SCAN_LOW_OR_EQUAL command\n"); 2130 fdctrl_start_transfer(fdctrl, FD_DIR_SCANL); 2131 return; 2132 case 0x1D: 2133 /* SCAN_HIGH_OR_EQUAL variants */ 2134 /* // FLOPPY_DPRINTF("treat SCAN_HIGH_OR_EQUAL command\n"); */ 2135 FLOPPY_ERROR("treat SCAN_HIGH_OR_EQUAL command\n"); 2136 fdctrl_start_transfer(fdctrl, FD_DIR_SCANH); 2137 return; 2138 default: 2139 break; 2140 } 2141 switch (fdctrl->fifo[0] & 0x3F) { 2142 case 0x05: 2143 /* WRITE variants */ 2144 FLOPPY_DPRINTF("treat WRITE command (%02x)\n", fdctrl->fifo[0]); 2145 fdctrl_start_transfer(fdctrl, FD_DIR_WRITE); 2146 return; 2147 case 0x09: 2148 /* WRITE_DELETED variants */ 2149 /* // FLOPPY_DPRINTF("treat WRITE_DELETED command\n"); */ 2150 FLOPPY_ERROR("treat WRITE_DELETED command\n"); 2151 fdctrl_start_transfer_del(fdctrl, FD_DIR_WRITE); 2152 return; 2153 default: 2154 break; 2155 } 2156 switch (fdctrl->fifo[0]) { 2157 case 0x03: 2158 /* SPECIFY */ 2159 FLOPPY_DPRINTF("treat SPECIFY command\n"); 2160 fdctrl->timer0 = (fdctrl->fifo[1] >> 4) & 0xF; 2161 fdctrl->timer1 = fdctrl->fifo[2] >> 1; 2162 fdctrl->dma_en = 1 - (fdctrl->fifo[2] & 1) ; 2163 /* No result back */ 2164 fdctrl_reset_fifo(fdctrl); 2165 break; 2166 case 0x04: 2167 /* SENSE_DRIVE_STATUS */ 2168 FLOPPY_DPRINTF("treat SENSE_DRIVE_STATUS command\n"); 2169 fdctrl->cur_drv = fdctrl->fifo[1] & 1; 2170 cur_drv = get_cur_drv(fdctrl); 2171 cur_drv->head = (fdctrl->fifo[1] >> 2) & 1; 2172 /* 1 Byte status back */ 2173 fdctrl->fifo[0] = (cur_drv->ro << 6) | 2174 (cur_drv->track == 0 ? 0x10 : 0x00) | 2175 (cur_drv->head << 2) | 2176 fdctrl->cur_drv | 2177 0x28; 2178 fdctrl_set_fifo(fdctrl, 1, 0); 2179 break; 2180 case 0x07: 2181 /* RECALIBRATE */ 2182 FLOPPY_DPRINTF("treat RECALIBRATE command\n"); 2183 fdctrl->cur_drv = fdctrl->fifo[1] & 1; 2184 cur_drv = get_cur_drv(fdctrl); 2185 fd_recalibrate(cur_drv); 2186 fdctrl_reset_fifo(fdctrl); 2187 /* Raise Interrupt */ 2188 fdctrl_raise_irq(fdctrl, 0x20); 2189 break; 2190 case 0x0F: 2191 /* SEEK */ 2192 FLOPPY_DPRINTF("treat SEEK command\n"); 2193 fdctrl->cur_drv = fdctrl->fifo[1] & 1; 2194 cur_drv = get_cur_drv(fdctrl); 2195 fd_start(cur_drv); 2196 if (fdctrl->fifo[2] <= cur_drv->track) 2197 cur_drv->dir = 1; 2198 else 2199 cur_drv->dir = 0; 2200 fdctrl_reset_fifo(fdctrl); 2201 #ifndef VBOX 2202 if (fdctrl->fifo[2] > cur_drv->max_track) { 2203 #else 2204 if ( fdctrl->fifo[2] > cur_drv->max_track 2205 && cur_drv->fMediaPresent) { 2206 #endif 2207 fdctrl_raise_irq(fdctrl, 0x60); 2208 } else { 2209 cur_drv->track = fdctrl->fifo[2]; 2210 /* Raise Interrupt */ 2211 fdctrl_raise_irq(fdctrl, 0x20); 2212 } 2213 break; 2214 case 0x12: 2215 /* PERPENDICULAR_MODE */ 2216 FLOPPY_DPRINTF("treat PERPENDICULAR_MODE command\n"); 2217 if (fdctrl->fifo[1] & 0x80) 2218 cur_drv->perpendicular = fdctrl->fifo[1] & 0x7; 2219 /* No result back */ 2220 fdctrl_reset_fifo(fdctrl); 2221 break; 2222 case 0x13: 2223 /* CONFIGURE */ 2224 FLOPPY_DPRINTF("treat CONFIGURE command\n"); 2225 fdctrl->config = fdctrl->fifo[2]; 2226 fdctrl->precomp_trk = fdctrl->fifo[3]; 2227 /* No result back */ 2228 fdctrl_reset_fifo(fdctrl); 2229 break; 2230 case 0x17: 2231 /* POWERDOWN_MODE */ 2232 FLOPPY_DPRINTF("treat POWERDOWN_MODE command\n"); 2233 fdctrl->pwrd = fdctrl->fifo[1]; 2234 fdctrl->fifo[0] = fdctrl->fifo[1]; 2235 fdctrl_set_fifo(fdctrl, 1, 1); 2236 break; 2237 case 0x33: 2238 /* OPTION */ 2239 FLOPPY_DPRINTF("treat OPTION command\n"); 2240 /* No result back */ 2241 fdctrl_reset_fifo(fdctrl); 2242 break; 2243 case 0x42: 2244 /* READ_TRACK */ 2245 /* // FLOPPY_DPRINTF("treat READ_TRACK command\n"); */ 2246 FLOPPY_ERROR("treat READ_TRACK command\n"); 2247 fdctrl_start_transfer(fdctrl, FD_DIR_READ); 2248 break; 2249 case 0x4A: 2250 /* READ_ID */ 2251 FLOPPY_DPRINTF("treat READ_ID command\n"); 2252 /* XXX: should set main status register to busy */ 2253 cur_drv->head = (fdctrl->fifo[1] >> 2) & 1; 2254 #ifdef VBOX 2255 TMTimerSetMillies(fdctrl->result_timer, 1000 / 50); 2256 #else 2257 qemu_mod_timer(fdctrl->result_timer, 2258 qemu_get_clock(vm_clock) + (ticks_per_sec / 50)); 2259 #endif 2260 break; 2261 case 0x4C: 2262 /* RESTORE */ 2263 FLOPPY_DPRINTF("treat RESTORE command\n"); 2264 /* Drives position */ 2265 drv0(fdctrl)->track = fdctrl->fifo[3]; 2266 drv1(fdctrl)->track = fdctrl->fifo[4]; 2267 /* timers */ 2268 fdctrl->timer0 = fdctrl->fifo[7]; 2269 fdctrl->timer1 = fdctrl->fifo[8]; 2270 cur_drv->last_sect = fdctrl->fifo[9]; 2271 fdctrl->lock = fdctrl->fifo[10] >> 7; 2272 cur_drv->perpendicular = (fdctrl->fifo[10] >> 2) & 0xF; 2273 fdctrl->config = fdctrl->fifo[11]; 2274 fdctrl->precomp_trk = fdctrl->fifo[12]; 2275 fdctrl->pwrd = fdctrl->fifo[13]; 2276 fdctrl_reset_fifo(fdctrl); 2277 break; 2278 case 0x4D: 2279 /* FORMAT_TRACK */ 2280 FLOPPY_DPRINTF("treat FORMAT_TRACK command\n"); 2281 fdctrl->cur_drv = fdctrl->fifo[1] & 1; 2282 cur_drv = get_cur_drv(fdctrl); 2283 fdctrl->data_state |= FD_STATE_FORMAT; 2284 if (fdctrl->fifo[0] & 0x80) 2285 fdctrl->data_state |= FD_STATE_MULTI; 2286 else 2287 fdctrl->data_state &= ~FD_STATE_MULTI; 2288 fdctrl->data_state &= ~FD_STATE_SEEK; 2289 cur_drv->bps = 2290 fdctrl->fifo[2] > 7 ? 16384 : 128 << fdctrl->fifo[2]; 2291 #if 0 2292 cur_drv->last_sect = 2293 cur_drv->flags & FDISK_DBL_SIDES ? fdctrl->fifo[3] : 2294 fdctrl->fifo[3] / 2; 2295 #else 2296 cur_drv->last_sect = fdctrl->fifo[3]; 2297 #endif 2298 /* Bochs BIOS is buggy and don't send format information 2299 * for each sector. So, pretend all's done right now... 2300 */ 2301 fdctrl->data_state &= ~FD_STATE_FORMAT; 2302 fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00); 2303 break; 2304 case 0x8E: 2305 /* DRIVE_SPECIFICATION_COMMAND */ 2306 FLOPPY_DPRINTF("treat DRIVE_SPECIFICATION_COMMAND command\n"); 2307 if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x80) { 2308 /* Command parameters done */ 2309 if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x40) { 2310 fdctrl->fifo[0] = fdctrl->fifo[1]; 2311 fdctrl->fifo[2] = 0; 2312 fdctrl->fifo[3] = 0; 2313 fdctrl_set_fifo(fdctrl, 4, 1); 2314 } else { 2315 fdctrl_reset_fifo(fdctrl); 2316 } 2317 } else if (fdctrl->data_len > 7) { 2318 /* ERROR */ 2319 fdctrl->fifo[0] = 0x80 | 2320 (cur_drv->head << 2) | fdctrl->cur_drv; 2321 fdctrl_set_fifo(fdctrl, 1, 1); 2322 } 2323 break; 2324 case 0x8F: 2325 /* RELATIVE_SEEK_OUT */ 2326 FLOPPY_DPRINTF("treat RELATIVE_SEEK_OUT command\n"); 2327 fdctrl->cur_drv = fdctrl->fifo[1] & 1; 2328 cur_drv = get_cur_drv(fdctrl); 2329 fd_start(cur_drv); 2330 cur_drv->dir = 0; 2331 if (fdctrl->fifo[2] + cur_drv->track >= cur_drv->max_track) { 2332 cur_drv->track = cur_drv->max_track - 1; 2333 } else { 2334 cur_drv->track += fdctrl->fifo[2]; 2335 } 2336 fdctrl_reset_fifo(fdctrl); 2337 fdctrl_raise_irq(fdctrl, 0x20); 2338 break; 2339 case 0xCD: 2340 /* FORMAT_AND_WRITE */ 2341 /* // FLOPPY_DPRINTF("treat FORMAT_AND_WRITE command\n"); */ 2342 FLOPPY_ERROR("treat FORMAT_AND_WRITE command\n"); 2343 fdctrl_unimplemented(fdctrl); 2344 break; 2345 case 0xCF: 2346 /* RELATIVE_SEEK_IN */ 2347 FLOPPY_DPRINTF("treat RELATIVE_SEEK_IN command\n"); 2348 fdctrl->cur_drv = fdctrl->fifo[1] & 1; 2349 cur_drv = get_cur_drv(fdctrl); 2350 fd_start(cur_drv); 2351 cur_drv->dir = 1; 2352 if (fdctrl->fifo[2] > cur_drv->track) { 2353 cur_drv->track = 0; 2354 } else { 2355 cur_drv->track -= fdctrl->fifo[2]; 2356 } 2357 fdctrl_reset_fifo(fdctrl); 2358 /* Raise Interrupt */ 2359 fdctrl_raise_irq(fdctrl, 0x20); 2360 break; 2361 } 1979 1980 pos = command_to_handler[fdctrl->fifo[0] & 0xff]; 1981 FLOPPY_DPRINTF("treat %s command\n", handlers[pos].name); 1982 (*handlers[pos].handler)(fdctrl, handlers[pos].direction); 2362 1983 } 2363 1984 } … … 2366 1987 { 2367 1988 fdctrl_t *fdctrl = opaque; 1989 fdrive_t *cur_drv = get_cur_drv(fdctrl); 1990 1991 /* Pretend we are spinning. 1992 * This is needed for Coherent, which uses READ ID to check for 1993 * sector interleaving. 1994 */ 1995 if (cur_drv->last_sect != 0) { 1996 cur_drv->sect = (cur_drv->sect % cur_drv->last_sect) + 1; 1997 } 2368 1998 fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00); 2369 1999 } 2370 2371 2000 2372 2001 #ifdef VBOX … … 2384 2013 { 2385 2014 if (cb == 1) { 2386 fdctrl_write (pvUser, Port , u32);2015 fdctrl_write (pvUser, Port & 7, u32); 2387 2016 } 2388 2017 else { … … 2399 2028 { 2400 2029 if (cb == 1) { 2401 *pu32 = fdctrl_read (pvUser, Port );2030 *pu32 = fdctrl_read (pvUser, Port & 7); 2402 2031 return VINF_SUCCESS; 2403 2032 } … … 2413 2042 unsigned int i; 2414 2043 2415 qemu_put_8s (f, &s->version); 2416 qemu_put_8s (f, &s->irq_lvl); 2417 qemu_put_8s (f, &s->dma_chann); 2418 qemu_put_be32s (f, &s->io_base); 2419 qemu_put_8s (f, &s->state); 2420 qemu_put_8s (f, &s->dma_en); 2421 qemu_put_8s (f, &s->cur_drv); 2422 qemu_put_8s (f, &s->bootsel); 2423 qemu_put_buffer (f, s->fifo, FD_SECTOR_LEN); 2424 qemu_put_be32s (f, &s->data_pos); 2425 qemu_put_be32s (f, &s->data_len); 2426 qemu_put_8s (f, &s->data_state); 2427 qemu_put_8s (f, &s->data_dir); 2428 qemu_put_8s (f, &s->int_status); 2429 qemu_put_8s (f, &s->eot); 2430 qemu_put_8s (f, &s->timer0); 2431 qemu_put_8s (f, &s->timer1); 2432 qemu_put_8s (f, &s->precomp_trk); 2433 qemu_put_8s (f, &s->config); 2434 qemu_put_8s (f, &s->lock); 2435 qemu_put_8s (f, &s->pwrd); 2436 2437 for (i = 0; i < sizeof (s->drives) / sizeof (s->drives[0]); ++i) { 2044 /* Save the FDC I/O registers... */ 2045 SSMR3PutU8(pSSMHandle, s->sra); 2046 SSMR3PutU8(pSSMHandle, s->srb); 2047 SSMR3PutU8(pSSMHandle, s->dor); 2048 SSMR3PutU8(pSSMHandle, s->tdr); 2049 SSMR3PutU8(pSSMHandle, s->dsr); 2050 SSMR3PutU8(pSSMHandle, s->msr); 2051 /* ...the status registers... */ 2052 SSMR3PutU8(pSSMHandle, s->status0); 2053 SSMR3PutU8(pSSMHandle, s->status1); 2054 SSMR3PutU8(pSSMHandle, s->status2); 2055 /* ...the command FIFO... */ 2056 SSMR3PutU32(pSSMHandle, sizeof(s->fifo)); 2057 SSMR3PutMem(pSSMHandle, &s->fifo, sizeof(s->fifo)); 2058 SSMR3PutU32(pSSMHandle, s->data_pos); 2059 SSMR3PutU32(pSSMHandle, s->data_len); 2060 SSMR3PutU8(pSSMHandle, s->data_state); 2061 SSMR3PutU8(pSSMHandle, s->data_dir); 2062 /* ...and miscellaneous internal FDC state. */ 2063 SSMR3PutU8(pSSMHandle, s->reset_sensei); 2064 SSMR3PutU8(pSSMHandle, s->eot); 2065 SSMR3PutU8(pSSMHandle, s->timer0); 2066 SSMR3PutU8(pSSMHandle, s->timer1); 2067 SSMR3PutU8(pSSMHandle, s->precomp_trk); 2068 SSMR3PutU8(pSSMHandle, s->config); 2069 SSMR3PutU8(pSSMHandle, s->lock); 2070 SSMR3PutU8(pSSMHandle, s->pwrd); 2071 SSMR3PutU8(pSSMHandle, s->version); 2072 2073 /* Save the number of drives and per-drive state. Note that the media 2074 * states will be updated in fd_revalidate() and need not be saved. 2075 */ 2076 SSMR3PutU8(pSSMHandle, s->num_floppies); 2077 Assert(RT_ELEMENTS(s->drives) == s->num_floppies); 2078 for (i = 0; i < s->num_floppies; ++i) { 2438 2079 fdrive_t *d = &s->drives[i]; 2439 2080 2440 SSMR3PutMem (pSSMHandle, &d->Led, sizeof (d->Led)); 2441 qemu_put_be32s (f, &d->drive); 2442 qemu_put_be32s (f, &d->drflags); 2443 qemu_put_8s (f, &d->perpendicular); 2444 qemu_put_8s (f, &d->head); 2445 qemu_put_8s (f, &d->track); 2446 qemu_put_8s (f, &d->sect); 2447 qemu_put_8s (f, &d->dir); 2448 qemu_put_8s (f, &d->rw); 2449 qemu_put_be32s (f, &d->flags); 2450 qemu_put_8s (f, &d->last_sect); 2451 qemu_put_8s (f, &d->max_track); 2452 qemu_put_be16s (f, &d->bps); 2453 qemu_put_8s (f, &d->ro); 2081 SSMR3PutMem(pSSMHandle, &d->Led, sizeof(d->Led)); 2082 SSMR3PutU32(pSSMHandle, d->drive); 2083 SSMR3PutU8(pSSMHandle, d->dsk_chg); 2084 SSMR3PutU8(pSSMHandle, d->perpendicular); 2085 SSMR3PutU8(pSSMHandle, d->head); 2086 SSMR3PutU8(pSSMHandle, d->track); 2087 SSMR3PutU8(pSSMHandle, d->sect); 2454 2088 } 2455 2089 return TMR3TimerSave (s->result_timer, pSSMHandle); … … 2464 2098 QEMUFile *f = pSSMHandle; 2465 2099 unsigned int i; 2466 2467 AssertMsgReturn(uVersion == 1, ("%d\n", uVersion), VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION); 2100 uint32_t val32; 2101 uint8_t val8; 2102 2103 if (uVersion > FDC_SAVESTATE_CURRENT) 2104 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION; 2468 2105 Assert(uPass == SSM_PASS_FINAL); NOREF(uPass); 2469 2106 2470 qemu_get_8s (f, &s->version); 2471 qemu_get_8s (f, &s->irq_lvl); 2472 qemu_get_8s (f, &s->dma_chann); 2473 qemu_get_be32s (f, &s->io_base); 2474 qemu_get_8s (f, &s->state); 2475 qemu_get_8s (f, &s->dma_en); 2476 qemu_get_8s (f, &s->cur_drv); 2477 qemu_get_8s (f, &s->bootsel); 2478 qemu_get_buffer (f, s->fifo, FD_SECTOR_LEN); 2479 qemu_get_be32s (f, &s->data_pos); 2480 qemu_get_be32s (f, &s->data_len); 2481 qemu_get_8s (f, &s->data_state); 2482 qemu_get_8s (f, &s->data_dir); 2483 qemu_get_8s (f, &s->int_status); 2484 qemu_get_8s (f, &s->eot); 2485 qemu_get_8s (f, &s->timer0); 2486 qemu_get_8s (f, &s->timer1); 2487 qemu_get_8s (f, &s->precomp_trk); 2488 qemu_get_8s (f, &s->config); 2489 qemu_get_8s (f, &s->lock); 2490 qemu_get_8s (f, &s->pwrd); 2491 2492 for (i = 0; i < sizeof (s->drives) / sizeof (s->drives[0]); ++i) { 2493 fdrive_t *d = &s->drives[i]; 2494 2495 SSMR3GetMem (pSSMHandle, &d->Led, sizeof (d->Led)); 2496 qemu_get_be32s (f, &d->drive); 2497 qemu_get_be32s (f, &d->drflags); 2498 qemu_get_8s (f, &d->perpendicular); 2499 qemu_get_8s (f, &d->head); 2500 qemu_get_8s (f, &d->track); 2501 qemu_get_8s (f, &d->sect); 2502 qemu_get_8s (f, &d->dir); 2503 qemu_get_8s (f, &d->rw); 2504 qemu_get_be32s (f, &d->flags); 2505 qemu_get_8s (f, &d->last_sect); 2506 qemu_get_8s (f, &d->max_track); 2507 qemu_get_be16s (f, &d->bps); 2508 qemu_get_8s (f, &d->ro); 2107 /* The old saved state was significantly different. However, we can get 2108 * back most of the controller state and fix the rest by pretending the 2109 * disk in the drive (if any) has been replaced. At any rate there should 2110 * be no difficulty unless the state was saved during a floppy operation. 2111 */ 2112 if (uVersion == FDC_SAVESTATE_OLD) 2113 { 2114 /* First verify a few assumptions. */ 2115 AssertMsgReturn(sizeof(s->fifo) == FD_SECTOR_LEN, 2116 ("The size of FIFO in saved state doesn't match!\n"), 2117 VERR_SSM_DATA_UNIT_FORMAT_CHANGED); 2118 AssertMsgReturn(RT_ELEMENTS(s->drives) == 2, 2119 ("The number of drives in old saved state doesn't match!\n"), 2120 VERR_SSM_DATA_UNIT_FORMAT_CHANGED); 2121 /* Now load the old state. */ 2122 SSMR3GetU8(pSSMHandle, &s->version); 2123 /* Toss IRQ level, DMA channel, I/O base, and state. */ 2124 SSMR3GetU8(pSSMHandle, &val8); 2125 SSMR3GetU8(pSSMHandle, &val8); 2126 SSMR3GetU32(pSSMHandle, &val32); 2127 SSMR3GetU8(pSSMHandle, &val8); 2128 /* Translate dma_en. */ 2129 SSMR3GetU8(pSSMHandle, &val8); 2130 if (val8) 2131 s->dor |= FD_DOR_DMAEN; 2132 SSMR3GetU8(pSSMHandle, &s->cur_drv); 2133 /* Translate bootsel. */ 2134 SSMR3GetU8(pSSMHandle, &val8); 2135 s->tdr |= val8 << 2; 2136 SSMR3GetMem(pSSMHandle, &s->fifo, FD_SECTOR_LEN); 2137 SSMR3GetU32(pSSMHandle, &s->data_pos); 2138 SSMR3GetU32(pSSMHandle, &s->data_len); 2139 SSMR3GetU8(pSSMHandle, &s->data_state); 2140 SSMR3GetU8(pSSMHandle, &s->data_dir); 2141 SSMR3GetU8(pSSMHandle, &s->status0); 2142 SSMR3GetU8(pSSMHandle, &s->eot); 2143 SSMR3GetU8(pSSMHandle, &s->timer0); 2144 SSMR3GetU8(pSSMHandle, &s->timer1); 2145 SSMR3GetU8(pSSMHandle, &s->precomp_trk); 2146 SSMR3GetU8(pSSMHandle, &s->config); 2147 SSMR3GetU8(pSSMHandle, &s->lock); 2148 SSMR3GetU8(pSSMHandle, &s->pwrd); 2149 2150 for (i = 0; i < 2; ++i) { 2151 fdrive_t *d = &s->drives[i]; 2152 2153 SSMR3GetMem (pSSMHandle, &d->Led, sizeof (d->Led)); 2154 SSMR3GetU32(pSSMHandle, &val32); 2155 d->drive = val32; 2156 SSMR3GetU32(pSSMHandle, &val32); /* Toss drflags */ 2157 SSMR3GetU8(pSSMHandle, &d->perpendicular); 2158 SSMR3GetU8(pSSMHandle, &d->head); 2159 SSMR3GetU8(pSSMHandle, &d->track); 2160 SSMR3GetU8(pSSMHandle, &d->sect); 2161 SSMR3GetU8(pSSMHandle, &val8); /* Toss dir, rw */ 2162 SSMR3GetU8(pSSMHandle, &val8); 2163 SSMR3GetU32(pSSMHandle, &val32); 2164 d->flags = val32; 2165 SSMR3GetU8(pSSMHandle, &d->last_sect); 2166 SSMR3GetU8(pSSMHandle, &d->max_track); 2167 SSMR3GetU16(pSSMHandle, &d->bps); 2168 SSMR3GetU8(pSSMHandle, &d->ro); 2169 } 2170 } 2171 else /* New state - straightforward. */ 2172 { 2173 Assert(uVersion == FDC_SAVESTATE_CURRENT); 2174 /* Load the FDC I/O registers... */ 2175 SSMR3GetU8(pSSMHandle, &s->sra); 2176 SSMR3GetU8(pSSMHandle, &s->srb); 2177 SSMR3GetU8(pSSMHandle, &s->dor); 2178 SSMR3GetU8(pSSMHandle, &s->tdr); 2179 SSMR3GetU8(pSSMHandle, &s->dsr); 2180 SSMR3GetU8(pSSMHandle, &s->msr); 2181 /* ...the status registers... */ 2182 SSMR3GetU8(pSSMHandle, &s->status0); 2183 SSMR3GetU8(pSSMHandle, &s->status1); 2184 SSMR3GetU8(pSSMHandle, &s->status2); 2185 /* ...the command FIFO, if the size matches... */ 2186 SSMR3GetU32(pSSMHandle, &val32); 2187 AssertMsgReturn(sizeof(s->fifo) == val32, 2188 ("The size of FIFO in saved state doesn't match!\n"), 2189 VERR_SSM_DATA_UNIT_FORMAT_CHANGED); 2190 SSMR3GetMem(pSSMHandle, &s->fifo, sizeof(s->fifo)); 2191 SSMR3GetU32(pSSMHandle, &s->data_pos); 2192 SSMR3GetU32(pSSMHandle, &s->data_len); 2193 SSMR3GetU8(pSSMHandle, &s->data_state); 2194 SSMR3GetU8(pSSMHandle, &s->data_dir); 2195 /* ...and miscellaneous internal FDC state. */ 2196 SSMR3GetU8(pSSMHandle, &s->reset_sensei); 2197 SSMR3GetU8(pSSMHandle, &s->eot); 2198 SSMR3GetU8(pSSMHandle, &s->timer0); 2199 SSMR3GetU8(pSSMHandle, &s->timer1); 2200 SSMR3GetU8(pSSMHandle, &s->precomp_trk); 2201 SSMR3GetU8(pSSMHandle, &s->config); 2202 SSMR3GetU8(pSSMHandle, &s->lock); 2203 SSMR3GetU8(pSSMHandle, &s->pwrd); 2204 SSMR3GetU8(pSSMHandle, &s->version); 2205 2206 /* Validate the number of drives. */ 2207 SSMR3GetU8(pSSMHandle, &s->num_floppies); 2208 AssertMsgReturn(RT_ELEMENTS(s->drives) == s->num_floppies, 2209 ("The number of drives in saved state doesn't match!\n"), 2210 VERR_SSM_DATA_UNIT_FORMAT_CHANGED); 2211 2212 /* Load the per-drive state. */ 2213 for (i = 0; i < s->num_floppies; ++i) { 2214 fdrive_t *d = &s->drives[i]; 2215 2216 SSMR3GetMem(pSSMHandle, &d->Led, sizeof(d->Led)); 2217 SSMR3GetU32(pSSMHandle, &val32); 2218 d->drive = val32; 2219 SSMR3GetU8(pSSMHandle, &d->dsk_chg); 2220 SSMR3GetU8(pSSMHandle, &d->perpendicular); 2221 SSMR3GetU8(pSSMHandle, &d->head); 2222 SSMR3GetU8(pSSMHandle, &d->track); 2223 SSMR3GetU8(pSSMHandle, &d->sect); 2224 } 2509 2225 } 2510 2226 return TMR3TimerLoad (s->result_timer, pSSMHandle); … … 2591 2307 drv->pDrvMount = PDMIBASE_QUERY_INTERFACE(drv->pDrvBase, PDMIMOUNT); 2592 2308 if (drv->pDrvMount) { 2593 /* 2594 * Init the state. 2595 */ 2596 drv->drive = FDRIVE_DRV_NONE; 2597 drv->drflags = 0; 2598 drv->perpendicular = 0; 2599 /* Disk */ 2600 drv->last_sect = 0; 2601 drv->max_track = 0; 2602 drv->fMediaPresent = false; 2309 fd_init(drv); 2603 2310 } else { 2604 2311 AssertMsgFailed (("Configuration error: LUN#%d without mountable interface!\n", drv->iLUN)); … … 2744 2451 2745 2452 fdctrl_reset(fdctrl, 0); 2746 fdctrl->state = FD_CTRL_ACTIVE;2747 2453 2748 2454 for (i = 0; i < RT_ELEMENTS(fdctrl->drives); i++) { … … 2761 2467 int rc; 2762 2468 fdctrl_t *fdctrl = PDMINS_2_DATA(pDevIns, fdctrl_t*); 2763 unsigned i; 2469 unsigned i, j; 2470 int ii; 2764 2471 bool mem_mapped; 2765 2472 uint16_t io_base; … … 2820 2527 fdctrl->dma_chann = dma_chann; 2821 2528 fdctrl->io_base = io_base; 2822 fdctrl->config = 0x60; /* Implicit seek, polling & FIFO enabled */ 2529 fdctrl->config = FD_CONFIG_EIS | FD_CONFIG_EFIFO; /* Implicit seek, polling & FIFO enabled */ 2530 fdctrl->num_floppies = MAX_FD; 2531 2532 /* Fill 'command_to_handler' lookup table */ 2533 for (ii = RT_ELEMENTS(handlers) - 1; ii >= 0; ii--) { 2534 for (j = 0; j < sizeof(command_to_handler); j++) { 2535 if ((j & handlers[ii].mask) == handlers[ii].value) { 2536 command_to_handler[j] = ii; 2537 } 2538 } 2539 } 2823 2540 2824 2541 fdctrl->IBaseStatus.pfnQueryInterface = fdcStatusQueryInterface; … … 2849 2566 */ 2850 2567 if (fdctrl->dma_chann != 0xff) { 2851 fdctrl->dma_en = 1;2852 2568 rc = PDMDevHlpDMARegister (pDevIns, dma_chann, &fdctrl_transfer_handler, fdctrl); 2853 2569 if (RT_FAILURE (rc)) 2854 2570 return rc; 2855 } else 2856 fdctrl->dma_en = 0; 2571 } 2857 2572 2858 2573 /* … … 2882 2597 * Register the saved state data unit. 2883 2598 */ 2884 rc = PDMDevHlpSSMRegister (pDevIns, 1 /*uVersion*/, sizeof(*fdctrl), fdcSaveExec, fdcLoadExec);2599 rc = PDMDevHlpSSMRegister (pDevIns, FDC_SAVESTATE_CURRENT, sizeof(*fdctrl), fdcSaveExec, fdcLoadExec); 2885 2600 if (RT_FAILURE(rc)) 2886 2601 return rc; … … 2912 2627 2913 2628 fdctrl_reset(fdctrl, 0); 2914 fdctrl->state = FD_CTRL_ACTIVE;2915 2629 2916 2630 for (i = 0; i < RT_ELEMENTS(fdctrl->drives); i++)
Note:
See TracChangeset
for help on using the changeset viewer.