Commit 678803abe6d74efcf5e46a5d616849cedae247dd
1 parent
b1fa7164
FDC fix 1/12 (Hervé Poussineau):
- Adds a command lookup table, as suggested by Fabrice at http://lists.gnu.org/archive/html/qemu-devel/2008-04/msg00143.html - This also moves initialization functions at the bottom of the file to prevent multiple forward declarations. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4281 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
149 additions
and
150 deletions
hw/fdc.c
| @@ -322,7 +322,6 @@ static void fdctrl_reset_fifo (fdctrl_t *fdctrl); | @@ -322,7 +322,6 @@ static void fdctrl_reset_fifo (fdctrl_t *fdctrl); | ||
| 322 | static int fdctrl_transfer_handler (void *opaque, int nchan, | 322 | static int fdctrl_transfer_handler (void *opaque, int nchan, |
| 323 | int dma_pos, int dma_len); | 323 | int dma_pos, int dma_len); |
| 324 | static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status); | 324 | static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status); |
| 325 | -static void fdctrl_result_timer(void *opaque); | ||
| 326 | 325 | ||
| 327 | static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl); | 326 | static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl); |
| 328 | static uint32_t fdctrl_read_dor (fdctrl_t *fdctrl); | 327 | static uint32_t fdctrl_read_dor (fdctrl_t *fdctrl); |
| @@ -694,78 +693,6 @@ static void fdctrl_external_reset(void *opaque) | @@ -694,78 +693,6 @@ static void fdctrl_external_reset(void *opaque) | ||
| 694 | fdctrl_reset(s, 0); | 693 | fdctrl_reset(s, 0); |
| 695 | } | 694 | } |
| 696 | 695 | ||
| 697 | -static fdctrl_t *fdctrl_init_common (qemu_irq irq, int dma_chann, | ||
| 698 | - target_phys_addr_t io_base, | ||
| 699 | - BlockDriverState **fds) | ||
| 700 | -{ | ||
| 701 | - fdctrl_t *fdctrl; | ||
| 702 | - int i; | ||
| 703 | - | ||
| 704 | - FLOPPY_DPRINTF("init controller\n"); | ||
| 705 | - fdctrl = qemu_mallocz(sizeof(fdctrl_t)); | ||
| 706 | - if (!fdctrl) | ||
| 707 | - return NULL; | ||
| 708 | - fdctrl->fifo = qemu_memalign(512, FD_SECTOR_LEN); | ||
| 709 | - if (fdctrl->fifo == NULL) { | ||
| 710 | - qemu_free(fdctrl); | ||
| 711 | - return NULL; | ||
| 712 | - } | ||
| 713 | - fdctrl->result_timer = qemu_new_timer(vm_clock, | ||
| 714 | - fdctrl_result_timer, fdctrl); | ||
| 715 | - | ||
| 716 | - fdctrl->version = 0x90; /* Intel 82078 controller */ | ||
| 717 | - fdctrl->irq = irq; | ||
| 718 | - fdctrl->dma_chann = dma_chann; | ||
| 719 | - fdctrl->io_base = io_base; | ||
| 720 | - fdctrl->config = FD_CONFIG_EIS | FD_CONFIG_EFIFO; /* Implicit seek, polling & FIFO enabled */ | ||
| 721 | - if (fdctrl->dma_chann != -1) { | ||
| 722 | - fdctrl->dma_en = 1; | ||
| 723 | - DMA_register_channel(dma_chann, &fdctrl_transfer_handler, fdctrl); | ||
| 724 | - } else { | ||
| 725 | - fdctrl->dma_en = 0; | ||
| 726 | - } | ||
| 727 | - for (i = 0; i < MAX_FD; i++) { | ||
| 728 | - fd_init(&fdctrl->drives[i], fds[i]); | ||
| 729 | - } | ||
| 730 | - fdctrl_reset(fdctrl, 0); | ||
| 731 | - fdctrl->state = FD_CTRL_ACTIVE; | ||
| 732 | - register_savevm("fdc", io_base, 1, fdc_save, fdc_load, fdctrl); | ||
| 733 | - qemu_register_reset(fdctrl_external_reset, fdctrl); | ||
| 734 | - for (i = 0; i < MAX_FD; i++) { | ||
| 735 | - fd_revalidate(&fdctrl->drives[i]); | ||
| 736 | - } | ||
| 737 | - | ||
| 738 | - return fdctrl; | ||
| 739 | -} | ||
| 740 | - | ||
| 741 | -fdctrl_t *fdctrl_init (qemu_irq irq, int dma_chann, int mem_mapped, | ||
| 742 | - target_phys_addr_t io_base, | ||
| 743 | - BlockDriverState **fds) | ||
| 744 | -{ | ||
| 745 | - fdctrl_t *fdctrl; | ||
| 746 | - int io_mem; | ||
| 747 | - | ||
| 748 | - fdctrl = fdctrl_init_common(irq, dma_chann, io_base, fds); | ||
| 749 | - | ||
| 750 | - fdctrl->sun4m = 0; | ||
| 751 | - if (mem_mapped) { | ||
| 752 | - io_mem = cpu_register_io_memory(0, fdctrl_mem_read, fdctrl_mem_write, | ||
| 753 | - fdctrl); | ||
| 754 | - cpu_register_physical_memory(io_base, 0x08, io_mem); | ||
| 755 | - } else { | ||
| 756 | - register_ioport_read((uint32_t)io_base + 0x01, 5, 1, &fdctrl_read, | ||
| 757 | - fdctrl); | ||
| 758 | - register_ioport_read((uint32_t)io_base + 0x07, 1, 1, &fdctrl_read, | ||
| 759 | - fdctrl); | ||
| 760 | - register_ioport_write((uint32_t)io_base + 0x01, 5, 1, &fdctrl_write, | ||
| 761 | - fdctrl); | ||
| 762 | - register_ioport_write((uint32_t)io_base + 0x07, 1, 1, &fdctrl_write, | ||
| 763 | - fdctrl); | ||
| 764 | - } | ||
| 765 | - | ||
| 766 | - return fdctrl; | ||
| 767 | -} | ||
| 768 | - | ||
| 769 | static void fdctrl_handle_tc(void *opaque, int irq, int level) | 696 | static void fdctrl_handle_tc(void *opaque, int irq, int level) |
| 770 | { | 697 | { |
| 771 | //fdctrl_t *s = opaque; | 698 | //fdctrl_t *s = opaque; |
| @@ -776,23 +703,6 @@ static void fdctrl_handle_tc(void *opaque, int irq, int level) | @@ -776,23 +703,6 @@ static void fdctrl_handle_tc(void *opaque, int irq, int level) | ||
| 776 | } | 703 | } |
| 777 | } | 704 | } |
| 778 | 705 | ||
| 779 | -fdctrl_t *sun4m_fdctrl_init (qemu_irq irq, target_phys_addr_t io_base, | ||
| 780 | - BlockDriverState **fds, qemu_irq *fdc_tc) | ||
| 781 | -{ | ||
| 782 | - fdctrl_t *fdctrl; | ||
| 783 | - int io_mem; | ||
| 784 | - | ||
| 785 | - fdctrl = fdctrl_init_common(irq, 0, io_base, fds); | ||
| 786 | - fdctrl->sun4m = 1; | ||
| 787 | - io_mem = cpu_register_io_memory(0, fdctrl_mem_read_strict, | ||
| 788 | - fdctrl_mem_write_strict, | ||
| 789 | - fdctrl); | ||
| 790 | - cpu_register_physical_memory(io_base, 0x08, io_mem); | ||
| 791 | - *fdc_tc = *qemu_allocate_irqs(fdctrl_handle_tc, fdctrl, 1); | ||
| 792 | - | ||
| 793 | - return fdctrl; | ||
| 794 | -} | ||
| 795 | - | ||
| 796 | /* XXX: may change if moved to bdrv */ | 706 | /* XXX: may change if moved to bdrv */ |
| 797 | int fdctrl_get_drive_type(fdctrl_t *fdctrl, int drive_num) | 707 | int fdctrl_get_drive_type(fdctrl_t *fdctrl, int drive_num) |
| 798 | { | 708 | { |
| @@ -1730,50 +1640,54 @@ static void fdctrl_handle_relative_seek_in (fdctrl_t *fdctrl, int direction) | @@ -1730,50 +1640,54 @@ static void fdctrl_handle_relative_seek_in (fdctrl_t *fdctrl, int direction) | ||
| 1730 | fdctrl_raise_irq(fdctrl, FD_SR0_SEEK); | 1640 | fdctrl_raise_irq(fdctrl, FD_SR0_SEEK); |
| 1731 | } | 1641 | } |
| 1732 | 1642 | ||
| 1643 | +static const struct { | ||
| 1644 | + uint8_t value; | ||
| 1645 | + uint8_t mask; | ||
| 1646 | + const char* name; | ||
| 1647 | + int parameters; | ||
| 1648 | + void (*handler)(fdctrl_t *fdctrl, int direction); | ||
| 1649 | + int direction; | ||
| 1650 | +} handlers[] = { | ||
| 1651 | + { FD_CMD_READ, 0x1f, "READ", 8, fdctrl_start_transfer, FD_DIR_READ }, | ||
| 1652 | + { FD_CMD_WRITE, 0x3f, "WRITE", 8, fdctrl_start_transfer, FD_DIR_WRITE }, | ||
| 1653 | + { FD_CMD_SEEK, 0xff, "SEEK", 2, fdctrl_handle_seek }, | ||
| 1654 | + { FD_CMD_SENSE_INTERRUPT_STATUS, 0xff, "SENSE INTERRUPT STATUS", 0, fdctrl_handle_sense_interrupt_status }, | ||
| 1655 | + { FD_CMD_RECALIBRATE, 0xff, "RECALIBRATE", 1, fdctrl_handle_recalibrate }, | ||
| 1656 | + { FD_CMD_FORMAT_TRACK, 0xbf, "FORMAT TRACK", 5, fdctrl_handle_format_track }, | ||
| 1657 | + { FD_CMD_READ_TRACK, 0xbf, "READ TRACK", 8, fdctrl_start_transfer, FD_DIR_READ }, | ||
| 1658 | + { FD_CMD_RESTORE, 0xff, "RESTORE", 17, fdctrl_handle_restore }, /* part of READ DELETED DATA */ | ||
| 1659 | + { FD_CMD_SAVE, 0xff, "SAVE", 0, fdctrl_handle_save }, /* part of READ DELETED DATA */ | ||
| 1660 | + { FD_CMD_READ_DELETED, 0x1f, "READ DELETED DATA", 8, fdctrl_start_transfer_del, FD_DIR_READ }, | ||
| 1661 | + { FD_CMD_SCAN_EQUAL, 0x1f, "SCAN EQUAL", 8, fdctrl_start_transfer, FD_DIR_SCANE }, | ||
| 1662 | + { FD_CMD_VERIFY, 0x1f, "VERIFY", 8, fdctrl_unimplemented }, | ||
| 1663 | + { FD_CMD_SCAN_LOW_OR_EQUAL, 0x1f, "SCAN LOW OR EQUAL", 8, fdctrl_start_transfer, FD_DIR_SCANL }, | ||
| 1664 | + { FD_CMD_SCAN_HIGH_OR_EQUAL, 0x1f, "SCAN HIGH OR EQUAL", 8, fdctrl_start_transfer, FD_DIR_SCANH }, | ||
| 1665 | + { FD_CMD_WRITE_DELETED, 0x3f, "WRITE DELETED DATA", 8, fdctrl_start_transfer_del, FD_DIR_WRITE }, | ||
| 1666 | + { FD_CMD_READ_ID, 0xbf, "READ ID", 1, fdctrl_handle_readid }, | ||
| 1667 | + { FD_CMD_SPECIFY, 0xff, "SPECIFY", 2, fdctrl_handle_specify }, | ||
| 1668 | + { FD_CMD_SENSE_DRIVE_STATUS, 0xff, "SENSE DRIVE STATUS", 1, fdctrl_handle_sense_drive_status }, | ||
| 1669 | + { FD_CMD_PERPENDICULAR_MODE, 0xff, "PERPENDICULAR MODE", 1, fdctrl_handle_perpendicular_mode }, | ||
| 1670 | + { FD_CMD_CONFIGURE, 0xff, "CONFIGURE", 3, fdctrl_handle_configure }, | ||
| 1671 | + { FD_CMD_POWERDOWN_MODE, 0xff, "POWERDOWN MODE", 2, fdctrl_handle_powerdown_mode }, | ||
| 1672 | + { FD_CMD_OPTION, 0xff, "OPTION", 1, fdctrl_handle_option }, | ||
| 1673 | + { FD_CMD_DRIVE_SPECIFICATION_COMMAND, 0xff, "DRIVE SPECIFICATION COMMAND", 5, fdctrl_handle_drive_specification_command }, | ||
| 1674 | + { FD_CMD_RELATIVE_SEEK_OUT, 0xff, "RELATIVE SEEK OUT", 2, fdctrl_handle_relative_seek_out }, | ||
| 1675 | + { FD_CMD_FORMAT_AND_WRITE, 0xff, "FORMAT AND WRITE", 10, fdctrl_unimplemented }, | ||
| 1676 | + { FD_CMD_RELATIVE_SEEK_IN, 0xff, "RELATIVE SEEK IN", 2, fdctrl_handle_relative_seek_in }, | ||
| 1677 | + { FD_CMD_LOCK, 0x7f, "LOCK", 0, fdctrl_handle_lock }, | ||
| 1678 | + { FD_CMD_DUMPREG, 0xff, "DUMPREG", 0, fdctrl_handle_dumpreg }, | ||
| 1679 | + { FD_CMD_VERSION, 0xff, "VERSION", 0, fdctrl_handle_version }, | ||
| 1680 | + { FD_CMD_PART_ID, 0xff, "PART ID", 0, fdctrl_handle_partid }, | ||
| 1681 | + { FD_CMD_WRITE, 0x1f, "WRITE (BeOS)", 8, fdctrl_start_transfer, FD_DIR_WRITE }, /* not in specification ; BeOS 4.5 bug */ | ||
| 1682 | + { 0, 0, "unknown", 0, fdctrl_unimplemented }, /* default handler */ | ||
| 1683 | +}; | ||
| 1684 | +/* Associate command to an index in the 'handlers' array */ | ||
| 1685 | +static uint8_t command_to_handler[256]; | ||
| 1686 | + | ||
| 1733 | static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value) | 1687 | static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value) |
| 1734 | { | 1688 | { |
| 1735 | fdrive_t *cur_drv; | 1689 | fdrive_t *cur_drv; |
| 1736 | int pos; | 1690 | int pos; |
| 1737 | - static const struct { | ||
| 1738 | - uint8_t value; | ||
| 1739 | - uint8_t mask; | ||
| 1740 | - const char* name; | ||
| 1741 | - int parameters; | ||
| 1742 | - void (*handler)(fdctrl_t *fdctrl, int direction); | ||
| 1743 | - int parameter; | ||
| 1744 | - } commands[] = { | ||
| 1745 | - { FD_CMD_READ, 0x1f, "READ", 8, fdctrl_start_transfer, FD_DIR_READ }, | ||
| 1746 | - { FD_CMD_WRITE, 0x3f, "WRITE", 8, fdctrl_start_transfer, FD_DIR_WRITE }, | ||
| 1747 | - { FD_CMD_SEEK, 0xff, "SEEK", 2, fdctrl_handle_seek }, | ||
| 1748 | - { FD_CMD_SENSE_INTERRUPT_STATUS, 0xff, "SENSE INTERRUPT STATUS", 0, fdctrl_handle_sense_interrupt_status }, | ||
| 1749 | - { FD_CMD_RECALIBRATE, 0xff, "RECALIBRATE", 1, fdctrl_handle_recalibrate }, | ||
| 1750 | - { FD_CMD_FORMAT_TRACK, 0xbf, "FORMAT TRACK", 5, fdctrl_handle_format_track }, | ||
| 1751 | - { FD_CMD_READ_TRACK, 0xbf, "READ TRACK", 8, fdctrl_start_transfer, FD_DIR_READ }, | ||
| 1752 | - { FD_CMD_RESTORE, 0xff, "RESTORE", 17, fdctrl_handle_restore }, /* part of READ DELETED DATA */ | ||
| 1753 | - { FD_CMD_SAVE, 0xff, "SAVE", 0, fdctrl_handle_save }, /* part of READ DELETED DATA */ | ||
| 1754 | - { FD_CMD_READ_DELETED, 0x1f, "READ DELETED DATA", 8, fdctrl_start_transfer_del, FD_DIR_READ }, | ||
| 1755 | - { FD_CMD_SCAN_EQUAL, 0x1f, "SCAN EQUAL", 8, fdctrl_start_transfer, FD_DIR_SCANE }, | ||
| 1756 | - { FD_CMD_VERIFY, 0x1f, "VERIFY", 8, fdctrl_unimplemented }, | ||
| 1757 | - { FD_CMD_SCAN_LOW_OR_EQUAL, 0x1f, "SCAN LOW OR EQUAL", 8, fdctrl_start_transfer, FD_DIR_SCANL }, | ||
| 1758 | - { FD_CMD_SCAN_HIGH_OR_EQUAL, 0x1f, "SCAN HIGH OR EQUAL", 8, fdctrl_start_transfer, FD_DIR_SCANH }, | ||
| 1759 | - { FD_CMD_WRITE_DELETED, 0x3f, "WRITE DELETED DATA", 8, fdctrl_start_transfer_del, FD_DIR_WRITE }, | ||
| 1760 | - { FD_CMD_READ_ID, 0xbf, "READ ID", 1, fdctrl_handle_readid }, | ||
| 1761 | - { FD_CMD_SPECIFY, 0xff, "SPECIFY", 2, fdctrl_handle_specify }, | ||
| 1762 | - { FD_CMD_SENSE_DRIVE_STATUS, 0xff, "SENSE DRIVE STATUS", 1, fdctrl_handle_sense_drive_status }, | ||
| 1763 | - { FD_CMD_PERPENDICULAR_MODE, 0xff, "PERPENDICULAR MODE", 1, fdctrl_handle_perpendicular_mode }, | ||
| 1764 | - { FD_CMD_CONFIGURE, 0xff, "CONFIGURE", 3, fdctrl_handle_configure }, | ||
| 1765 | - { FD_CMD_POWERDOWN_MODE, 0xff, "POWERDOWN MODE", 2, fdctrl_handle_powerdown_mode }, | ||
| 1766 | - { FD_CMD_OPTION, 0xff, "OPTION", 1, fdctrl_handle_option }, | ||
| 1767 | - { FD_CMD_DRIVE_SPECIFICATION_COMMAND, 0xff, "DRIVE SPECIFICATION COMMAND", 5, fdctrl_handle_drive_specification_command }, | ||
| 1768 | - { FD_CMD_RELATIVE_SEEK_OUT, 0xff, "RELATIVE SEEK OUT", 2, fdctrl_handle_relative_seek_out }, | ||
| 1769 | - { FD_CMD_FORMAT_AND_WRITE, 0xff, "FORMAT AND WRITE", 10, fdctrl_unimplemented }, | ||
| 1770 | - { FD_CMD_RELATIVE_SEEK_IN, 0xff, "RELATIVE SEEK IN", 2, fdctrl_handle_relative_seek_in }, | ||
| 1771 | - { FD_CMD_LOCK, 0x7f, "LOCK", 0, fdctrl_handle_lock }, | ||
| 1772 | - { FD_CMD_DUMPREG, 0xff, "DUMPREG", 0, fdctrl_handle_dumpreg }, | ||
| 1773 | - { FD_CMD_VERSION, 0xff, "VERSION", 0, fdctrl_handle_version }, | ||
| 1774 | - { FD_CMD_PART_ID, 0xff, "PART ID", 0, fdctrl_handle_partid }, | ||
| 1775 | - { FD_CMD_WRITE, 0x1f, "WRITE (BeOS)", 8, fdctrl_start_transfer, FD_DIR_WRITE }, /* not in specification ; BeOS 4.5 bug */ | ||
| 1776 | - }; | ||
| 1777 | 1691 | ||
| 1778 | cur_drv = get_cur_drv(fdctrl); | 1692 | cur_drv = get_cur_drv(fdctrl); |
| 1779 | /* Reset mode */ | 1693 | /* Reset mode */ |
| @@ -1803,20 +1717,11 @@ static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value) | @@ -1803,20 +1717,11 @@ static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value) | ||
| 1803 | } | 1717 | } |
| 1804 | if (fdctrl->data_pos == 0) { | 1718 | if (fdctrl->data_pos == 0) { |
| 1805 | /* Command */ | 1719 | /* Command */ |
| 1806 | - for (pos = 0; pos < sizeof(commands)/sizeof(commands[0]); pos++) { | ||
| 1807 | - if ((value & commands[pos].mask) == commands[pos].value) { | ||
| 1808 | - FLOPPY_DPRINTF("%s command\n", commands[pos].name); | ||
| 1809 | - fdctrl->data_len = commands[pos].parameters + 1; | ||
| 1810 | - goto enqueue; | ||
| 1811 | - } | ||
| 1812 | - } | ||
| 1813 | - | ||
| 1814 | - /* Unknown command */ | ||
| 1815 | - FLOPPY_ERROR("unknown command: 0x%02x\n", value); | ||
| 1816 | - fdctrl_unimplemented(fdctrl, 0); | ||
| 1817 | - return; | 1720 | + pos = command_to_handler[value & 0xff]; |
| 1721 | + FLOPPY_DPRINTF("%s command\n", handlers[pos].name); | ||
| 1722 | + fdctrl->data_len = handlers[pos].parameters + 1; | ||
| 1818 | } | 1723 | } |
| 1819 | - enqueue: | 1724 | + |
| 1820 | FLOPPY_DPRINTF("%s: %02x\n", __func__, value); | 1725 | FLOPPY_DPRINTF("%s: %02x\n", __func__, value); |
| 1821 | fdctrl->fifo[fdctrl->data_pos] = value; | 1726 | fdctrl->fifo[fdctrl->data_pos] = value; |
| 1822 | if (++fdctrl->data_pos == fdctrl->data_len) { | 1727 | if (++fdctrl->data_pos == fdctrl->data_len) { |
| @@ -1828,13 +1733,9 @@ static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value) | @@ -1828,13 +1733,9 @@ static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value) | ||
| 1828 | return; | 1733 | return; |
| 1829 | } | 1734 | } |
| 1830 | 1735 | ||
| 1831 | - for (pos = 0; pos < sizeof(commands)/sizeof(commands[0]); pos++) { | ||
| 1832 | - if ((fdctrl->fifo[0] & commands[pos].mask) == commands[pos].value) { | ||
| 1833 | - FLOPPY_DPRINTF("treat %s command\n", commands[pos].name); | ||
| 1834 | - (*commands[pos].handler)(fdctrl, commands[pos].parameter); | ||
| 1835 | - break; | ||
| 1836 | - } | ||
| 1837 | - } | 1736 | + pos = command_to_handler[fdctrl->fifo[0] & 0xff]; |
| 1737 | + FLOPPY_DPRINTF("treat %s command\n", handlers[pos].name); | ||
| 1738 | + (*handlers[pos].handler)(fdctrl, handlers[pos].direction); | ||
| 1838 | } | 1739 | } |
| 1839 | } | 1740 | } |
| 1840 | 1741 | ||
| @@ -1852,3 +1753,101 @@ static void fdctrl_result_timer(void *opaque) | @@ -1852,3 +1753,101 @@ static void fdctrl_result_timer(void *opaque) | ||
| 1852 | } | 1753 | } |
| 1853 | fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00); | 1754 | fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00); |
| 1854 | } | 1755 | } |
| 1756 | + | ||
| 1757 | +/* Init functions */ | ||
| 1758 | +static fdctrl_t *fdctrl_init_common (qemu_irq irq, int dma_chann, | ||
| 1759 | + target_phys_addr_t io_base, | ||
| 1760 | + BlockDriverState **fds) | ||
| 1761 | +{ | ||
| 1762 | + fdctrl_t *fdctrl; | ||
| 1763 | + int i, j; | ||
| 1764 | + | ||
| 1765 | + /* Fill 'command_to_handler' lookup table */ | ||
| 1766 | + for (i = sizeof(handlers)/sizeof(handlers[0]) - 1; i >= 0; i--) { | ||
| 1767 | + for (j = 0; j < sizeof(command_to_handler); j++) { | ||
| 1768 | + if ((j & handlers[i].mask) == handlers[i].value) | ||
| 1769 | + command_to_handler[j] = i; | ||
| 1770 | + } | ||
| 1771 | + } | ||
| 1772 | + | ||
| 1773 | + FLOPPY_DPRINTF("init controller\n"); | ||
| 1774 | + fdctrl = qemu_mallocz(sizeof(fdctrl_t)); | ||
| 1775 | + if (!fdctrl) | ||
| 1776 | + return NULL; | ||
| 1777 | + fdctrl->fifo = qemu_memalign(512, FD_SECTOR_LEN); | ||
| 1778 | + if (fdctrl->fifo == NULL) { | ||
| 1779 | + qemu_free(fdctrl); | ||
| 1780 | + return NULL; | ||
| 1781 | + } | ||
| 1782 | + fdctrl->result_timer = qemu_new_timer(vm_clock, | ||
| 1783 | + fdctrl_result_timer, fdctrl); | ||
| 1784 | + | ||
| 1785 | + fdctrl->version = 0x90; /* Intel 82078 controller */ | ||
| 1786 | + fdctrl->irq = irq; | ||
| 1787 | + fdctrl->dma_chann = dma_chann; | ||
| 1788 | + fdctrl->io_base = io_base; | ||
| 1789 | + fdctrl->config = FD_CONFIG_EIS | FD_CONFIG_EFIFO; /* Implicit seek, polling & FIFO enabled */ | ||
| 1790 | + if (fdctrl->dma_chann != -1) { | ||
| 1791 | + fdctrl->dma_en = 1; | ||
| 1792 | + DMA_register_channel(dma_chann, &fdctrl_transfer_handler, fdctrl); | ||
| 1793 | + } else { | ||
| 1794 | + fdctrl->dma_en = 0; | ||
| 1795 | + } | ||
| 1796 | + for (i = 0; i < MAX_FD; i++) { | ||
| 1797 | + fd_init(&fdctrl->drives[i], fds[i]); | ||
| 1798 | + } | ||
| 1799 | + fdctrl_reset(fdctrl, 0); | ||
| 1800 | + fdctrl->state = FD_CTRL_ACTIVE; | ||
| 1801 | + register_savevm("fdc", io_base, 1, fdc_save, fdc_load, fdctrl); | ||
| 1802 | + qemu_register_reset(fdctrl_external_reset, fdctrl); | ||
| 1803 | + for (i = 0; i < MAX_FD; i++) { | ||
| 1804 | + fd_revalidate(&fdctrl->drives[i]); | ||
| 1805 | + } | ||
| 1806 | + | ||
| 1807 | + return fdctrl; | ||
| 1808 | +} | ||
| 1809 | + | ||
| 1810 | +fdctrl_t *fdctrl_init (qemu_irq irq, int dma_chann, int mem_mapped, | ||
| 1811 | + target_phys_addr_t io_base, | ||
| 1812 | + BlockDriverState **fds) | ||
| 1813 | +{ | ||
| 1814 | + fdctrl_t *fdctrl; | ||
| 1815 | + int io_mem; | ||
| 1816 | + | ||
| 1817 | + fdctrl = fdctrl_init_common(irq, dma_chann, io_base, fds); | ||
| 1818 | + | ||
| 1819 | + fdctrl->sun4m = 0; | ||
| 1820 | + if (mem_mapped) { | ||
| 1821 | + io_mem = cpu_register_io_memory(0, fdctrl_mem_read, fdctrl_mem_write, | ||
| 1822 | + fdctrl); | ||
| 1823 | + cpu_register_physical_memory(io_base, 0x08, io_mem); | ||
| 1824 | + } else { | ||
| 1825 | + register_ioport_read((uint32_t)io_base + 0x01, 5, 1, &fdctrl_read, | ||
| 1826 | + fdctrl); | ||
| 1827 | + register_ioport_read((uint32_t)io_base + 0x07, 1, 1, &fdctrl_read, | ||
| 1828 | + fdctrl); | ||
| 1829 | + register_ioport_write((uint32_t)io_base + 0x01, 5, 1, &fdctrl_write, | ||
| 1830 | + fdctrl); | ||
| 1831 | + register_ioport_write((uint32_t)io_base + 0x07, 1, 1, &fdctrl_write, | ||
| 1832 | + fdctrl); | ||
| 1833 | + } | ||
| 1834 | + | ||
| 1835 | + return fdctrl; | ||
| 1836 | +} | ||
| 1837 | + | ||
| 1838 | +fdctrl_t *sun4m_fdctrl_init (qemu_irq irq, target_phys_addr_t io_base, | ||
| 1839 | + BlockDriverState **fds, qemu_irq *fdc_tc) | ||
| 1840 | +{ | ||
| 1841 | + fdctrl_t *fdctrl; | ||
| 1842 | + int io_mem; | ||
| 1843 | + | ||
| 1844 | + fdctrl = fdctrl_init_common(irq, 0, io_base, fds); | ||
| 1845 | + fdctrl->sun4m = 1; | ||
| 1846 | + io_mem = cpu_register_io_memory(0, fdctrl_mem_read_strict, | ||
| 1847 | + fdctrl_mem_write_strict, | ||
| 1848 | + fdctrl); | ||
| 1849 | + cpu_register_physical_memory(io_base, 0x08, io_mem); | ||
| 1850 | + *fdc_tc = *qemu_allocate_irqs(fdctrl_handle_tc, fdctrl, 1); | ||
| 1851 | + | ||
| 1852 | + return fdctrl; | ||
| 1853 | +} |