root/drivers/ide/q40ide.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. q40ide_default_irq
  2. q40_ide_setup_ports
  3. q40ide_input_data
  4. q40ide_output_data
  5. q40ide_init

   1 /*
   2  *  Q40 I/O port IDE Driver
   3  *
   4  *     (c) Richard Zidlicky
   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  *
  11  */
  12 
  13 #include <linux/types.h>
  14 #include <linux/mm.h>
  15 #include <linux/interrupt.h>
  16 #include <linux/blkdev.h>
  17 #include <linux/ide.h>
  18 #include <linux/module.h>
  19 
  20 #include <asm/ide.h>
  21 
  22     /*
  23      *  Bases of the IDE interfaces
  24      */
  25 
  26 #define Q40IDE_NUM_HWIFS        2
  27 
  28 #define PCIDE_BASE1     0x1f0
  29 #define PCIDE_BASE2     0x170
  30 #define PCIDE_BASE3     0x1e8
  31 #define PCIDE_BASE4     0x168
  32 #define PCIDE_BASE5     0x1e0
  33 #define PCIDE_BASE6     0x160
  34 
  35 static const unsigned long pcide_bases[Q40IDE_NUM_HWIFS] = {
  36     PCIDE_BASE1, PCIDE_BASE2, /* PCIDE_BASE3, PCIDE_BASE4  , PCIDE_BASE5,
  37     PCIDE_BASE6 */
  38 };
  39 
  40 static int q40ide_default_irq(unsigned long base)
  41 {
  42            switch (base) {
  43                     case 0x1f0: return 14;
  44                     case 0x170: return 15;
  45                     case 0x1e8: return 11;
  46                     default:
  47                         return 0;
  48            }
  49 }
  50 
  51 
  52 /*
  53  * Addresses are pretranslated for Q40 ISA access.
  54  */
  55 static void q40_ide_setup_ports(struct ide_hw *hw, unsigned long base, int irq)
  56 {
  57         memset(hw, 0, sizeof(*hw));
  58         /* BIG FAT WARNING: 
  59            assumption: only DATA port is ever used in 16 bit mode */
  60         hw->io_ports.data_addr = Q40_ISA_IO_W(base);
  61         hw->io_ports.error_addr = Q40_ISA_IO_B(base + 1);
  62         hw->io_ports.nsect_addr = Q40_ISA_IO_B(base + 2);
  63         hw->io_ports.lbal_addr = Q40_ISA_IO_B(base + 3);
  64         hw->io_ports.lbam_addr = Q40_ISA_IO_B(base + 4);
  65         hw->io_ports.lbah_addr = Q40_ISA_IO_B(base + 5);
  66         hw->io_ports.device_addr = Q40_ISA_IO_B(base + 6);
  67         hw->io_ports.status_addr = Q40_ISA_IO_B(base + 7);
  68         hw->io_ports.ctl_addr = Q40_ISA_IO_B(base + 0x206);
  69 
  70         hw->irq = irq;
  71 }
  72 
  73 static void q40ide_input_data(ide_drive_t *drive, struct ide_cmd *cmd,
  74                               void *buf, unsigned int len)
  75 {
  76         unsigned long data_addr = drive->hwif->io_ports.data_addr;
  77 
  78         if (drive->media == ide_disk && cmd && (cmd->tf_flags & IDE_TFLAG_FS)) {
  79                 __ide_mm_insw(data_addr, buf, (len + 1) / 2);
  80                 return;
  81         }
  82 
  83         raw_insw_swapw((u16 *)data_addr, buf, (len + 1) / 2);
  84 }
  85 
  86 static void q40ide_output_data(ide_drive_t *drive, struct ide_cmd *cmd,
  87                                void *buf, unsigned int len)
  88 {
  89         unsigned long data_addr = drive->hwif->io_ports.data_addr;
  90 
  91         if (drive->media == ide_disk && cmd && (cmd->tf_flags & IDE_TFLAG_FS)) {
  92                 __ide_mm_outsw(data_addr, buf, (len + 1) / 2);
  93                 return;
  94         }
  95 
  96         raw_outsw_swapw((u16 *)data_addr, buf, (len + 1) / 2);
  97 }
  98 
  99 /* Q40 has a byte-swapped IDE interface */
 100 static const struct ide_tp_ops q40ide_tp_ops = {
 101         .exec_command           = ide_exec_command,
 102         .read_status            = ide_read_status,
 103         .read_altstatus         = ide_read_altstatus,
 104         .write_devctl           = ide_write_devctl,
 105 
 106         .dev_select             = ide_dev_select,
 107         .tf_load                = ide_tf_load,
 108         .tf_read                = ide_tf_read,
 109 
 110         .input_data             = q40ide_input_data,
 111         .output_data            = q40ide_output_data,
 112 };
 113 
 114 static const struct ide_port_info q40ide_port_info = {
 115         .tp_ops                 = &q40ide_tp_ops,
 116         .host_flags             = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA,
 117         .irq_flags              = IRQF_SHARED,
 118         .chipset                = ide_generic,
 119 };
 120 
 121 /* 
 122  * the static array is needed to have the name reported in /proc/ioports,
 123  * hwif->name unfortunately isn't available yet
 124  */
 125 static const char *q40_ide_names[Q40IDE_NUM_HWIFS]={
 126         "ide0", "ide1"
 127 };
 128 
 129 /*
 130  *  Probe for Q40 IDE interfaces
 131  */
 132 
 133 static int __init q40ide_init(void)
 134 {
 135     int i;
 136     struct ide_hw hw[Q40IDE_NUM_HWIFS], *hws[] = { NULL, NULL };
 137 
 138     if (!MACH_IS_Q40)
 139       return -ENODEV;
 140 
 141     printk(KERN_INFO "ide: Q40 IDE controller\n");
 142 
 143     for (i = 0; i < Q40IDE_NUM_HWIFS; i++) {
 144         const char *name = q40_ide_names[i];
 145 
 146         if (!request_region(pcide_bases[i], 8, name)) {
 147                 printk("could not reserve ports %lx-%lx for %s\n",
 148                        pcide_bases[i],pcide_bases[i]+8,name);
 149                 continue;
 150         }
 151         if (!request_region(pcide_bases[i]+0x206, 1, name)) {
 152                 printk("could not reserve port %lx for %s\n",
 153                        pcide_bases[i]+0x206,name);
 154                 release_region(pcide_bases[i], 8);
 155                 continue;
 156         }
 157         q40_ide_setup_ports(&hw[i], pcide_bases[i],
 158                         q40ide_default_irq(pcide_bases[i]));
 159 
 160         hws[i] = &hw[i];
 161     }
 162 
 163     return ide_host_add(&q40ide_port_info, hws, Q40IDE_NUM_HWIFS, NULL);
 164 }
 165 
 166 module_init(q40ide_init);
 167 
 168 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */