Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

m68k/q40: Replace q40ide driver with pata_falcon and falconide

This allows m68k q40 systems to switch from the deprecated IDE subsystem
to libata.

Enhance the byte-swapping falconide and pata_falcon platform drivers to
accept an irq resource, for use on q40. Atari ST-DMA IRQ arrangements seem
to co-exist with q40 IRQ arrangements without too much mess.

The new IO resources were added solely for the purpose of making
request_region() reservations identical to those made by q40ide: these
regions aren't used for actual IO.

Cc: Michael Schmitz <schmitzmic@gmail.com>
Cc: Richard Zidlicky <rz@linux-m68k.org>
Reviewed-and-tested-by: Michael Schmitz <schmitzmic@gmail.com>
Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Finn Thain <fthain@linux-m68k.org>
Link: https://lore.kernel.org/r/eefb7e9c2291e09fb4e065ce06bc105f05bb9e06.1623287706.git.fthain@linux-m68k.org
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Finn Thain and committed by
Jens Axboe
44b1fbc0 cabd10be

+147 -251
+2 -10
arch/m68k/atari/config.c
··· 875 875 #define FALCON_IDE_BASE 0xfff00000 876 876 877 877 static const struct resource atari_falconide_rsrc[] __initconst = { 878 - { 879 - .flags = IORESOURCE_MEM, 880 - .start = FALCON_IDE_BASE, 881 - .end = FALCON_IDE_BASE + 0x39, 882 - }, 883 - { 884 - .flags = IORESOURCE_IRQ, 885 - .start = IRQ_MFP_FSCSI, 886 - .end = IRQ_MFP_FSCSI, 887 - }, 878 + DEFINE_RES_MEM(FALCON_IDE_BASE, 0x38), 879 + DEFINE_RES_MEM(FALCON_IDE_BASE + 0x38, 2), 888 880 }; 889 881 890 882 int __init atari_platform_init(void)
-1
arch/m68k/configs/multi_defconfig
··· 351 351 CONFIG_BLK_DEV_GAYLE=y 352 352 CONFIG_BLK_DEV_BUDDHA=y 353 353 CONFIG_BLK_DEV_FALCON_IDE=y 354 - CONFIG_BLK_DEV_Q40IDE=y 355 354 CONFIG_RAID_ATTRS=m 356 355 CONFIG_SCSI=y 357 356 CONFIG_BLK_DEV_SD=y
+1 -1
arch/m68k/configs/q40_defconfig
··· 317 317 CONFIG_IDE=y 318 318 CONFIG_IDE_GD_ATAPI=y 319 319 CONFIG_BLK_DEV_IDECD=y 320 - CONFIG_BLK_DEV_Q40IDE=y 320 + CONFIG_BLK_DEV_FALCON_IDE=y 321 321 CONFIG_RAID_ATTRS=m 322 322 CONFIG_SCSI=y 323 323 CONFIG_BLK_DEV_SD=y
+31 -6
arch/m68k/q40/config.c
··· 286 286 return -EINVAL; 287 287 } 288 288 289 - static __init int q40_add_kbd_device(void) 290 - { 291 - struct platform_device *pdev; 289 + #define PCIDE_BASE1 0x1f0 290 + #define PCIDE_BASE2 0x170 291 + #define PCIDE_CTL 0x206 292 292 293 + static const struct resource q40_pata_rsrc_0[] __initconst = { 294 + DEFINE_RES_MEM(q40_isa_io_base + PCIDE_BASE1 * 4, 0x38), 295 + DEFINE_RES_MEM(q40_isa_io_base + (PCIDE_BASE1 + PCIDE_CTL) * 4, 2), 296 + DEFINE_RES_IO(PCIDE_BASE1, 8), 297 + DEFINE_RES_IO(PCIDE_BASE1 + PCIDE_CTL, 1), 298 + DEFINE_RES_IRQ(14), 299 + }; 300 + 301 + static const struct resource q40_pata_rsrc_1[] __initconst = { 302 + DEFINE_RES_MEM(q40_isa_io_base + PCIDE_BASE2 * 4, 0x38), 303 + DEFINE_RES_MEM(q40_isa_io_base + (PCIDE_BASE2 + PCIDE_CTL) * 4, 2), 304 + DEFINE_RES_IO(PCIDE_BASE2, 8), 305 + DEFINE_RES_IO(PCIDE_BASE2 + PCIDE_CTL, 1), 306 + DEFINE_RES_IRQ(15), 307 + }; 308 + 309 + static __init int q40_platform_init(void) 310 + { 293 311 if (!MACH_IS_Q40) 294 312 return -ENODEV; 295 313 296 - pdev = platform_device_register_simple("q40kbd", -1, NULL, 0); 297 - return PTR_ERR_OR_ZERO(pdev); 314 + platform_device_register_simple("q40kbd", -1, NULL, 0); 315 + 316 + platform_device_register_simple("atari-falcon-ide", 0, q40_pata_rsrc_0, 317 + ARRAY_SIZE(q40_pata_rsrc_0)); 318 + 319 + platform_device_register_simple("atari-falcon-ide", 1, q40_pata_rsrc_1, 320 + ARRAY_SIZE(q40_pata_rsrc_1)); 321 + 322 + return 0; 298 323 } 299 - arch_initcall(q40_add_kbd_device); 324 + arch_initcall(q40_platform_init);
+3 -3
drivers/ata/Kconfig
··· 1015 1015 If unsure, say N. 1016 1016 1017 1017 config PATA_FALCON 1018 - tristate "Atari Falcon PATA support" 1019 - depends on M68K && ATARI 1018 + tristate "Atari Falcon and Q40/Q60 PATA support" 1019 + depends on M68K && (ATARI || Q40) 1020 1020 help 1021 1021 This option enables support for the on-board IDE 1022 - interface on the Atari Falcon. 1022 + interface on the Atari Falcon and Q40/Q60. 1023 1023 1024 1024 If unsure, say N. 1025 1025
+46 -18
drivers/ata/pata_falcon.c
··· 33 33 #define DRV_NAME "pata_falcon" 34 34 #define DRV_VERSION "0.1.0" 35 35 36 - #define ATA_HD_CONTROL 0x39 37 - 38 36 static struct scsi_host_template pata_falcon_sht = { 39 37 ATA_PIO_SHT(DRV_NAME), 40 38 }; ··· 119 121 120 122 static int __init pata_falcon_init_one(struct platform_device *pdev) 121 123 { 122 - struct resource *res; 124 + struct resource *base_mem_res, *ctl_mem_res; 125 + struct resource *base_res, *ctl_res, *irq_res; 123 126 struct ata_host *host; 124 127 struct ata_port *ap; 125 128 void __iomem *base; 129 + int irq = 0; 126 130 127 - dev_info(&pdev->dev, "Atari Falcon PATA controller\n"); 131 + dev_info(&pdev->dev, "Atari Falcon and Q40/Q60 PATA controller\n"); 128 132 129 - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 130 - if (!res) 131 - return -ENODEV; 132 - 133 - if (!devm_request_mem_region(&pdev->dev, res->start, 134 - resource_size(res), DRV_NAME)) { 133 + base_res = platform_get_resource(pdev, IORESOURCE_IO, 0); 134 + if (base_res && !devm_request_region(&pdev->dev, base_res->start, 135 + resource_size(base_res), DRV_NAME)) { 135 136 dev_err(&pdev->dev, "resources busy\n"); 136 137 return -EBUSY; 137 138 } 139 + 140 + ctl_res = platform_get_resource(pdev, IORESOURCE_IO, 1); 141 + if (ctl_res && !devm_request_region(&pdev->dev, ctl_res->start, 142 + resource_size(ctl_res), DRV_NAME)) { 143 + dev_err(&pdev->dev, "resources busy\n"); 144 + return -EBUSY; 145 + } 146 + 147 + base_mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 148 + if (!base_mem_res) 149 + return -ENODEV; 150 + if (!devm_request_mem_region(&pdev->dev, base_mem_res->start, 151 + resource_size(base_mem_res), DRV_NAME)) { 152 + dev_err(&pdev->dev, "resources busy\n"); 153 + return -EBUSY; 154 + } 155 + 156 + ctl_mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 157 + if (!ctl_mem_res) 158 + return -ENODEV; 138 159 139 160 /* allocate host */ 140 161 host = ata_host_alloc(&pdev->dev, 1); ··· 164 147 ap->ops = &pata_falcon_ops; 165 148 ap->pio_mask = ATA_PIO4; 166 149 ap->flags |= ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_IORDY; 167 - ap->flags |= ATA_FLAG_PIO_POLLING; 168 150 169 - base = (void __iomem *)res->start; 170 - ap->ioaddr.data_addr = base; 151 + base = (void __iomem *)base_mem_res->start; 152 + /* N.B. this assumes data_addr will be used for word-sized I/O only */ 153 + ap->ioaddr.data_addr = base + 0 + 0 * 4; 171 154 ap->ioaddr.error_addr = base + 1 + 1 * 4; 172 155 ap->ioaddr.feature_addr = base + 1 + 1 * 4; 173 156 ap->ioaddr.nsect_addr = base + 1 + 2 * 4; ··· 178 161 ap->ioaddr.status_addr = base + 1 + 7 * 4; 179 162 ap->ioaddr.command_addr = base + 1 + 7 * 4; 180 163 181 - ap->ioaddr.altstatus_addr = base + ATA_HD_CONTROL; 182 - ap->ioaddr.ctl_addr = base + ATA_HD_CONTROL; 164 + base = (void __iomem *)ctl_mem_res->start; 165 + ap->ioaddr.altstatus_addr = base + 1; 166 + ap->ioaddr.ctl_addr = base + 1; 183 167 184 - ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", (unsigned long)base, 185 - (unsigned long)base + ATA_HD_CONTROL); 168 + ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", 169 + (unsigned long)base_mem_res->start, 170 + (unsigned long)ctl_mem_res->start); 171 + 172 + irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 173 + if (irq_res && irq_res->start > 0) { 174 + irq = irq_res->start; 175 + } else { 176 + ap->flags |= ATA_FLAG_PIO_POLLING; 177 + ata_port_desc(ap, "no IRQ, using PIO polling"); 178 + } 186 179 187 180 /* activate */ 188 - return ata_host_activate(host, 0, NULL, 0, &pata_falcon_sht); 181 + return ata_host_activate(host, irq, irq ? ata_sff_interrupt : NULL, 182 + IRQF_SHARED, &pata_falcon_sht); 189 183 } 190 184 191 185 static int __exit pata_falcon_remove_one(struct platform_device *pdev)
+5 -13
drivers/ide/Kconfig
··· 731 731 to one of its IDE interfaces. 732 732 733 733 config BLK_DEV_FALCON_IDE 734 - tristate "Falcon IDE interface support" 735 - depends on ATARI 734 + tristate "Falcon and Q40/Q60 IDE interface support" 735 + depends on ATARI || Q40 736 736 help 737 737 This is the IDE driver for the on-board IDE interface on the Atari 738 - Falcon. Say Y if you have a Falcon and want to use IDE devices (hard 739 - disks, CD-ROM drives, etc.) that are connected to the on-board IDE 740 - interface. 741 - 742 - config BLK_DEV_Q40IDE 743 - tristate "Q40/Q60 IDE interface support" 744 - depends on Q40 745 - help 746 - Enable the on-board IDE controller in the Q40/Q60. This should 747 - normally be on; disable it only if you are running a custom hard 748 - drive subsystem through an expansion card. 738 + Falcon and Q40/Q60. Say Y if you have such a machine and want to use 739 + IDE devices (hard disks, CD-ROM drives, etc.) that are connected to 740 + the on-board IDE interface. 749 741 750 742 config BLK_DEV_PALMCHIP_BK3710 751 743 tristate "Palmchip bk3710 IDE controller support"
-1
drivers/ide/Makefile
··· 29 29 30 30 obj-$(CONFIG_BLK_DEV_GAYLE) += gayle.o 31 31 obj-$(CONFIG_BLK_DEV_FALCON_IDE) += falconide.o 32 - obj-$(CONFIG_BLK_DEV_Q40IDE) += q40ide.o 33 32 obj-$(CONFIG_BLK_DEV_BUDDHA) += buddha.o 34 33 35 34 obj-$(CONFIG_BLK_DEV_AEC62XX) += aec62xx.o
+59 -30
drivers/ide/falconide.c
··· 25 25 26 26 #define DRV_NAME "falconide" 27 27 28 - /* 29 - * Offsets from base address 30 - */ 31 - 32 - #define ATA_HD_CONTROL 0x39 33 - 28 + #ifdef CONFIG_ATARI 34 29 /* 35 30 * falconide_intr_lock is used to obtain access to the IDE interrupt, 36 31 * which is shared between several drivers. ··· 50 55 falconide_intr_lock = 1; 51 56 } 52 57 } 58 + #endif 53 59 54 60 static void falconide_input_data(ide_drive_t *drive, struct ide_cmd *cmd, 55 61 void *buf, unsigned int len) ··· 94 98 }; 95 99 96 100 static const struct ide_port_info falconide_port_info = { 101 + #ifdef CONFIG_ATARI 97 102 .get_lock = falconide_get_lock, 98 103 .release_lock = falconide_release_lock, 104 + #endif 99 105 .tp_ops = &falconide_tp_ops, 100 106 .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_SERIALIZE | 101 107 IDE_HFLAG_NO_DMA, ··· 105 107 .chipset = ide_generic, 106 108 }; 107 109 108 - static void __init falconide_setup_ports(struct ide_hw *hw, unsigned long base) 110 + static void __init falconide_setup_ports(struct ide_hw *hw, unsigned long base, 111 + unsigned long ctl, int irq) 109 112 { 110 113 int i; 111 114 ··· 117 118 for (i = 1; i < 8; i++) 118 119 hw->io_ports_array[i] = base + 1 + i * 4; 119 120 120 - hw->io_ports.ctl_addr = base + ATA_HD_CONTROL; 121 + hw->io_ports.ctl_addr = ctl + 1; 121 122 122 - hw->irq = IRQ_MFP_IDE; 123 + hw->irq = irq; 123 124 } 124 125 125 126 /* ··· 128 129 129 130 static int __init falconide_init(struct platform_device *pdev) 130 131 { 131 - struct resource *res; 132 + struct resource *base_mem_res, *ctl_mem_res; 133 + struct resource *base_res, *ctl_res, *irq_res; 132 134 struct ide_host *host; 133 135 struct ide_hw hw, *hws[] = { &hw }; 134 - unsigned long base; 135 136 int rc; 137 + int irq; 136 138 137 - dev_info(&pdev->dev, "Atari Falcon IDE controller\n"); 139 + dev_info(&pdev->dev, "Atari Falcon and Q40/Q60 IDE controller\n"); 138 140 139 - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 140 - if (!res) 141 - return -ENODEV; 142 - 143 - if (!devm_request_mem_region(&pdev->dev, res->start, 144 - resource_size(res), DRV_NAME)) { 141 + base_res = platform_get_resource(pdev, IORESOURCE_IO, 0); 142 + if (base_res && !devm_request_region(&pdev->dev, base_res->start, 143 + resource_size(base_res), DRV_NAME)) { 145 144 dev_err(&pdev->dev, "resources busy\n"); 146 145 return -EBUSY; 147 146 } 148 147 149 - base = (unsigned long)res->start; 150 - 151 - falconide_setup_ports(&hw, base); 152 - 153 - host = ide_host_alloc(&falconide_port_info, hws, 1); 154 - if (host == NULL) { 155 - rc = -ENOMEM; 156 - goto err; 148 + ctl_res = platform_get_resource(pdev, IORESOURCE_IO, 0); 149 + if (ctl_res && !devm_request_region(&pdev->dev, ctl_res->start, 150 + resource_size(ctl_res), DRV_NAME)) { 151 + dev_err(&pdev->dev, "resources busy\n"); 152 + return -EBUSY; 157 153 } 158 154 159 - falconide_get_lock(NULL, NULL); 155 + base_mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 156 + if (!base_mem_res) 157 + return -ENODEV; 158 + 159 + if (!devm_request_mem_region(&pdev->dev, base_mem_res->start, 160 + resource_size(base_mem_res), DRV_NAME)) { 161 + dev_err(&pdev->dev, "resources busy\n"); 162 + return -EBUSY; 163 + } 164 + 165 + ctl_mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 166 + if (!ctl_mem_res) 167 + return -ENODEV; 168 + 169 + if (MACH_IS_ATARI) { 170 + irq = IRQ_MFP_IDE; 171 + } else { 172 + irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 173 + if (irq_res && irq_res->start > 0) 174 + irq = irq_res->start; 175 + else 176 + return -ENODEV; 177 + } 178 + 179 + falconide_setup_ports(&hw, base_mem_res->start, ctl_mem_res->start, irq); 180 + 181 + host = ide_host_alloc(&falconide_port_info, hws, 1); 182 + if (!host) 183 + return -ENOMEM; 184 + 185 + if (!MACH_IS_ATARI) { 186 + host->get_lock = NULL; 187 + host->release_lock = NULL; 188 + } 189 + 190 + if (host->get_lock) 191 + host->get_lock(NULL, NULL); 160 192 rc = ide_host_register(host, &falconide_port_info, hws); 161 - falconide_release_lock(); 193 + if (host->release_lock) 194 + host->release_lock(); 162 195 163 196 if (rc) 164 197 goto err_free; ··· 199 168 return 0; 200 169 err_free: 201 170 ide_host_free(host); 202 - err: 203 - release_mem_region(res->start, resource_size(res)); 204 171 return rc; 205 172 } 206 173
-168
drivers/ide/q40ide.c
··· 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");