gayle.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:5k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/drivers/ide/gayle.c -- Amiga Gayle IDE Driver
  3.  *
  4.  *     Created 9 Jul 1997 by Geert Uytterhoeven
  5.  *
  6.  *  This file is subject to the terms and conditions of the GNU General Public
  7.  *  License.  See the file COPYING in the main directory of this archive for
  8.  *  more details.
  9.  */
  10. #include <linux/config.h>
  11. #include <linux/types.h>
  12. #include <linux/mm.h>
  13. #include <linux/interrupt.h>
  14. #include <linux/blkdev.h>
  15. #include <linux/hdreg.h>
  16. #include <linux/ide.h>
  17. #include <linux/init.h>
  18. #include <asm/setup.h>
  19. #include <asm/amigahw.h>
  20. #include <asm/amigaints.h>
  21. #include <asm/amigayle.h>
  22.     /*
  23.      *  Bases of the IDE interfaces
  24.      */
  25. #define GAYLE_BASE_4000 0xdd2020 /* A4000/A4000T */
  26. #define GAYLE_BASE_1200 0xda0000 /* A1200/A600 */
  27.     /*
  28.      *  Offsets from one of the above bases
  29.      */
  30. #define GAYLE_DATA 0x00
  31. #define GAYLE_ERROR 0x06 /* see err-bits */
  32. #define GAYLE_NSECTOR 0x0a /* nr of sectors to read/write */
  33. #define GAYLE_SECTOR 0x0e /* starting sector */
  34. #define GAYLE_LCYL 0x12 /* starting cylinder */
  35. #define GAYLE_HCYL 0x16 /* high byte of starting cyl */
  36. #define GAYLE_SELECT 0x1a /* 101dhhhh , d=drive, hhhh=head */
  37. #define GAYLE_STATUS 0x1e /* see status-bits */
  38. #define GAYLE_CONTROL 0x101a
  39. static int gayle_offsets[IDE_NR_PORTS] __initdata = {
  40.     GAYLE_DATA, GAYLE_ERROR, GAYLE_NSECTOR, GAYLE_SECTOR, GAYLE_LCYL,
  41.     GAYLE_HCYL, GAYLE_SELECT, GAYLE_STATUS, -1, -1
  42. };
  43.     /*
  44.      *  These are at different offsets from the base
  45.      */
  46. #define GAYLE_IRQ_4000 0xdd3020 /* MSB = 1, Harddisk is source of */
  47. #define GAYLE_IRQ_1200 0xda9000 /* interrupt */
  48.     /*
  49.      *  Offset of the secondary port for IDE doublers
  50.      *  Note that GAYLE_CONTROL is NOT available then!
  51.      */
  52. #define GAYLE_NEXT_PORT 0x1000
  53. #ifndef CONFIG_BLK_DEV_IDEDOUBLER
  54. #define GAYLE_NUM_HWIFS 1
  55. #define GAYLE_NUM_PROBE_HWIFS GAYLE_NUM_HWIFS
  56. #define GAYLE_HAS_CONTROL_REG 1
  57. #define GAYLE_IDEREG_SIZE 0x2000
  58. #else /* CONFIG_BLK_DEV_IDEDOUBLER */
  59. #define GAYLE_NUM_HWIFS 2
  60. #define GAYLE_NUM_PROBE_HWIFS (ide_doubler ? GAYLE_NUM_HWIFS : 
  61.        GAYLE_NUM_HWIFS-1)
  62. #define GAYLE_HAS_CONTROL_REG (!ide_doubler)
  63. #define GAYLE_IDEREG_SIZE (ide_doubler ? 0x1000 : 0x2000)
  64. int ide_doubler = 0; /* support IDE doublers? */
  65. #endif /* CONFIG_BLK_DEV_IDEDOUBLER */
  66.     /*
  67.      *  Check and acknowledge the interrupt status
  68.      */
  69. static int gayle_ack_intr_a4000(ide_hwif_t *hwif)
  70. {
  71.     unsigned char ch;
  72.     ch = inb(hwif->io_ports[IDE_IRQ_OFFSET]);
  73.     if (!(ch & GAYLE_IRQ_IDE))
  74. return 0;
  75.     return 1;
  76. }
  77. static int gayle_ack_intr_a1200(ide_hwif_t *hwif)
  78. {
  79.     unsigned char ch;
  80.     ch = inb(hwif->io_ports[IDE_IRQ_OFFSET]);
  81.     if (!(ch & GAYLE_IRQ_IDE))
  82. return 0;
  83.     (void)inb(hwif->io_ports[IDE_STATUS_OFFSET]);
  84.     outb(0x7c, hwif->io_ports[IDE_IRQ_OFFSET]);
  85.     return 1;
  86. }
  87.     /*
  88.      *  Probe for a Gayle IDE interface (and optionally for an IDE doubler)
  89.      */
  90. void __init gayle_init(void)
  91. {
  92.     int a4000, i;
  93.     if (!MACH_IS_AMIGA)
  94. return;
  95.     if (!(a4000 = AMIGAHW_PRESENT(A4000_IDE)) && !AMIGAHW_PRESENT(A1200_IDE))
  96. return;
  97.     for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) {
  98. ide_ioreg_t base, ctrlport, irqport;
  99. ide_ack_intr_t *ack_intr;
  100. hw_regs_t hw;
  101. int index;
  102. unsigned long phys_base, res_start, res_n;
  103. if (a4000) {
  104.     phys_base = GAYLE_BASE_4000;
  105.     irqport = (ide_ioreg_t)ZTWO_VADDR(GAYLE_IRQ_4000);
  106.     ack_intr = gayle_ack_intr_a4000;
  107. } else {
  108.     phys_base = GAYLE_BASE_1200;
  109.     irqport = (ide_ioreg_t)ZTWO_VADDR(GAYLE_IRQ_1200);
  110.     ack_intr = gayle_ack_intr_a1200;
  111. }
  112. phys_base += i*GAYLE_NEXT_PORT;
  113. res_start = ((unsigned long)phys_base) & ~(GAYLE_NEXT_PORT-1);
  114. res_n = GAYLE_IDEREG_SIZE;
  115. if (!request_mem_region(res_start, res_n, "IDE"))
  116.     continue;
  117. base = (ide_ioreg_t)ZTWO_VADDR(phys_base);
  118. ctrlport = GAYLE_HAS_CONTROL_REG ? (base + GAYLE_CONTROL) : 0;
  119. ide_setup_ports(&hw, base, gayle_offsets,
  120. ctrlport, irqport, ack_intr, IRQ_AMIGA_PORTS);
  121. index = ide_register_hw(&hw, NULL);
  122. if (index != -1) {
  123.     switch (i) {
  124. case 0:
  125.     printk("ide%d: Gayle IDE interface (A%d style)n", index,
  126.    a4000 ? 4000 : 1200);
  127.     break;
  128. #ifdef CONFIG_BLK_DEV_IDEDOUBLER
  129. case 1:
  130.     printk("ide%d: IDE doublern", index);
  131.     break;
  132. #endif /* CONFIG_BLK_DEV_IDEDOUBLER */
  133.     }
  134. } else
  135.     release_mem_region(res_start, res_n);
  136. #if 1 /* TESTING */
  137. if (i == 1) {
  138.     volatile u_short *addr = (u_short *)base;
  139.     u_short data;
  140.     printk("+++ Probing for IDE doubler... ");
  141.     *addr = 0xffff;
  142.     data = *addr;
  143.     printk("probe returned 0x%02x (PLEASE REPORT THIS!!)n", data);
  144. }
  145. #endif /* TESTING */
  146.     }
  147. }