0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042 #include "aic79xx_osm.h"
0043 #include "aic79xx_inline.h"
0044 #include "aic79xx_pci.h"
0045
0046
0047
0048 #define ID(x) \
0049 ID2C(x), \
0050 ID2C(IDIROC(x))
0051
0052 static const struct pci_device_id ahd_linux_pci_id_table[] = {
0053
0054 ID(ID_AHA_29320A),
0055 ID(ID_AHA_29320ALP),
0056 ID(ID_AHA_29320LPE),
0057
0058 ID(ID_AHA_29320),
0059 ID(ID_AHA_29320B),
0060 ID(ID_AHA_29320LP),
0061 ID(ID_AHA_39320),
0062 ID(ID_AHA_39320_B),
0063 ID(ID_AHA_39320A),
0064 ID(ID_AHA_39320D),
0065 ID(ID_AHA_39320D_HP),
0066 ID(ID_AHA_39320D_B),
0067 ID(ID_AHA_39320D_B_HP),
0068
0069 ID16(ID_AIC7901 & ID_9005_GENERIC_MASK),
0070 ID(ID_AIC7901A & ID_DEV_VENDOR_MASK),
0071 ID16(ID_AIC7902 & ID_9005_GENERIC_MASK),
0072 { 0 }
0073 };
0074
0075 MODULE_DEVICE_TABLE(pci, ahd_linux_pci_id_table);
0076
0077 static int __maybe_unused
0078 ahd_linux_pci_dev_suspend(struct device *dev)
0079 {
0080 struct ahd_softc *ahd = dev_get_drvdata(dev);
0081 int rc;
0082
0083 if ((rc = ahd_suspend(ahd)))
0084 return rc;
0085
0086 ahd_pci_suspend(ahd);
0087
0088 return rc;
0089 }
0090
0091 static int __maybe_unused
0092 ahd_linux_pci_dev_resume(struct device *dev)
0093 {
0094 struct ahd_softc *ahd = dev_get_drvdata(dev);
0095
0096 ahd_pci_resume(ahd);
0097
0098 ahd_resume(ahd);
0099
0100 return 0;
0101 }
0102
0103 static void
0104 ahd_linux_pci_dev_remove(struct pci_dev *pdev)
0105 {
0106 struct ahd_softc *ahd = pci_get_drvdata(pdev);
0107 u_long s;
0108
0109 if (ahd->platform_data && ahd->platform_data->host)
0110 scsi_remove_host(ahd->platform_data->host);
0111
0112 ahd_lock(ahd, &s);
0113 ahd_intr_enable(ahd, FALSE);
0114 ahd_unlock(ahd, &s);
0115 ahd_free(ahd);
0116 }
0117
0118 static void
0119 ahd_linux_pci_inherit_flags(struct ahd_softc *ahd)
0120 {
0121 struct pci_dev *pdev = ahd->dev_softc, *master_pdev;
0122 unsigned int master_devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0);
0123
0124 master_pdev = pci_get_slot(pdev->bus, master_devfn);
0125 if (master_pdev) {
0126 struct ahd_softc *master = pci_get_drvdata(master_pdev);
0127 if (master) {
0128 ahd->flags &= ~AHD_BIOS_ENABLED;
0129 ahd->flags |= master->flags & AHD_BIOS_ENABLED;
0130 } else
0131 printk(KERN_ERR "aic79xx: no multichannel peer found!\n");
0132 pci_dev_put(master_pdev);
0133 }
0134 }
0135
0136 static int
0137 ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
0138 {
0139 char buf[80];
0140 struct ahd_softc *ahd;
0141 ahd_dev_softc_t pci;
0142 const struct ahd_pci_identity *entry;
0143 char *name;
0144 int error;
0145 struct device *dev = &pdev->dev;
0146
0147 pci = pdev;
0148 entry = ahd_find_pci_device(pci);
0149 if (entry == NULL)
0150 return (-ENODEV);
0151
0152
0153
0154
0155
0156
0157 sprintf(buf, "ahd_pci:%d:%d:%d",
0158 ahd_get_pci_bus(pci),
0159 ahd_get_pci_slot(pci),
0160 ahd_get_pci_function(pci));
0161 name = kstrdup(buf, GFP_ATOMIC);
0162 if (name == NULL)
0163 return (-ENOMEM);
0164 ahd = ahd_alloc(NULL, name);
0165 if (ahd == NULL)
0166 return (-ENOMEM);
0167 if (pci_enable_device(pdev)) {
0168 ahd_free(ahd);
0169 return (-ENODEV);
0170 }
0171 pci_set_master(pdev);
0172
0173 if (sizeof(dma_addr_t) > 4) {
0174 const u64 required_mask = dma_get_required_mask(dev);
0175
0176 if (required_mask > DMA_BIT_MASK(39) &&
0177 dma_set_mask(dev, DMA_BIT_MASK(64)) == 0)
0178 ahd->flags |= AHD_64BIT_ADDRESSING;
0179 else if (required_mask > DMA_BIT_MASK(32) &&
0180 dma_set_mask(dev, DMA_BIT_MASK(39)) == 0)
0181 ahd->flags |= AHD_39BIT_ADDRESSING;
0182 else
0183 dma_set_mask(dev, DMA_BIT_MASK(32));
0184 } else {
0185 dma_set_mask(dev, DMA_BIT_MASK(32));
0186 }
0187 ahd->dev_softc = pci;
0188 error = ahd_pci_config(ahd, entry);
0189 if (error != 0) {
0190 ahd_free(ahd);
0191 return (-error);
0192 }
0193
0194
0195
0196
0197
0198 if ((ahd->features & AHD_MULTI_FUNC) && PCI_FUNC(pdev->devfn) != 0)
0199 ahd_linux_pci_inherit_flags(ahd);
0200
0201 pci_set_drvdata(pdev, ahd);
0202
0203 ahd_linux_register_host(ahd, &aic79xx_driver_template);
0204 return (0);
0205 }
0206
0207 static SIMPLE_DEV_PM_OPS(ahd_linux_pci_dev_pm_ops,
0208 ahd_linux_pci_dev_suspend,
0209 ahd_linux_pci_dev_resume);
0210
0211 static struct pci_driver aic79xx_pci_driver = {
0212 .name = "aic79xx",
0213 .probe = ahd_linux_pci_dev_probe,
0214 .driver.pm = &ahd_linux_pci_dev_pm_ops,
0215 .remove = ahd_linux_pci_dev_remove,
0216 .id_table = ahd_linux_pci_id_table
0217 };
0218
0219 int
0220 ahd_linux_pci_init(void)
0221 {
0222 return pci_register_driver(&aic79xx_pci_driver);
0223 }
0224
0225 void
0226 ahd_linux_pci_exit(void)
0227 {
0228 pci_unregister_driver(&aic79xx_pci_driver);
0229 }
0230
0231 static int
0232 ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd, resource_size_t *base,
0233 resource_size_t *base2)
0234 {
0235 *base = pci_resource_start(ahd->dev_softc, 0);
0236
0237
0238
0239
0240
0241 *base2 = pci_resource_start(ahd->dev_softc, 3);
0242 if (*base == 0 || *base2 == 0)
0243 return (ENOMEM);
0244 if (!request_region(*base, 256, "aic79xx"))
0245 return (ENOMEM);
0246 if (!request_region(*base2, 256, "aic79xx")) {
0247 release_region(*base, 256);
0248 return (ENOMEM);
0249 }
0250 return (0);
0251 }
0252
0253 static int
0254 ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd,
0255 resource_size_t *bus_addr,
0256 uint8_t __iomem **maddr)
0257 {
0258 resource_size_t start;
0259 resource_size_t base_page;
0260 u_long base_offset;
0261 int error = 0;
0262
0263 if (aic79xx_allow_memio == 0)
0264 return (ENOMEM);
0265
0266 if ((ahd->bugs & AHD_PCIX_MMAPIO_BUG) != 0)
0267 return (ENOMEM);
0268
0269 start = pci_resource_start(ahd->dev_softc, 1);
0270 base_page = start & PAGE_MASK;
0271 base_offset = start - base_page;
0272 if (start != 0) {
0273 *bus_addr = start;
0274 if (!request_mem_region(start, 0x1000, "aic79xx"))
0275 error = ENOMEM;
0276 if (!error) {
0277 *maddr = ioremap(base_page, base_offset + 512);
0278 if (*maddr == NULL) {
0279 error = ENOMEM;
0280 release_mem_region(start, 0x1000);
0281 } else
0282 *maddr += base_offset;
0283 }
0284 } else
0285 error = ENOMEM;
0286 return (error);
0287 }
0288
0289 int
0290 ahd_pci_map_registers(struct ahd_softc *ahd)
0291 {
0292 uint32_t command;
0293 resource_size_t base;
0294 uint8_t __iomem *maddr;
0295 int error;
0296
0297
0298
0299
0300 command = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, 4);
0301 command &= ~(PCIM_CMD_PORTEN|PCIM_CMD_MEMEN);
0302 base = 0;
0303 maddr = NULL;
0304 error = ahd_linux_pci_reserve_mem_region(ahd, &base, &maddr);
0305 if (error == 0) {
0306 ahd->platform_data->mem_busaddr = base;
0307 ahd->tags[0] = BUS_SPACE_MEMIO;
0308 ahd->bshs[0].maddr = maddr;
0309 ahd->tags[1] = BUS_SPACE_MEMIO;
0310 ahd->bshs[1].maddr = maddr + 0x100;
0311 ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND,
0312 command | PCIM_CMD_MEMEN, 4);
0313
0314 if (ahd_pci_test_register_access(ahd) != 0) {
0315
0316 printk("aic79xx: PCI Device %d:%d:%d "
0317 "failed memory mapped test. Using PIO.\n",
0318 ahd_get_pci_bus(ahd->dev_softc),
0319 ahd_get_pci_slot(ahd->dev_softc),
0320 ahd_get_pci_function(ahd->dev_softc));
0321 iounmap(maddr);
0322 release_mem_region(ahd->platform_data->mem_busaddr,
0323 0x1000);
0324 ahd->bshs[0].maddr = NULL;
0325 maddr = NULL;
0326 } else
0327 command |= PCIM_CMD_MEMEN;
0328 } else if (bootverbose) {
0329 printk("aic79xx: PCI%d:%d:%d MEM region 0x%llx "
0330 "unavailable. Cannot memory map device.\n",
0331 ahd_get_pci_bus(ahd->dev_softc),
0332 ahd_get_pci_slot(ahd->dev_softc),
0333 ahd_get_pci_function(ahd->dev_softc),
0334 (unsigned long long)base);
0335 }
0336
0337 if (maddr == NULL) {
0338 resource_size_t base2;
0339
0340 error = ahd_linux_pci_reserve_io_regions(ahd, &base, &base2);
0341 if (error == 0) {
0342 ahd->tags[0] = BUS_SPACE_PIO;
0343 ahd->tags[1] = BUS_SPACE_PIO;
0344 ahd->bshs[0].ioport = (u_long)base;
0345 ahd->bshs[1].ioport = (u_long)base2;
0346 command |= PCIM_CMD_PORTEN;
0347 } else {
0348 printk("aic79xx: PCI%d:%d:%d IO regions 0x%llx and "
0349 "0x%llx unavailable. Cannot map device.\n",
0350 ahd_get_pci_bus(ahd->dev_softc),
0351 ahd_get_pci_slot(ahd->dev_softc),
0352 ahd_get_pci_function(ahd->dev_softc),
0353 (unsigned long long)base,
0354 (unsigned long long)base2);
0355 }
0356 }
0357 ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, 4);
0358 return (error);
0359 }
0360
0361 int
0362 ahd_pci_map_int(struct ahd_softc *ahd)
0363 {
0364 int error;
0365
0366 error = request_irq(ahd->dev_softc->irq, ahd_linux_isr,
0367 IRQF_SHARED, "aic79xx", ahd);
0368 if (!error)
0369 ahd->platform_data->irq = ahd->dev_softc->irq;
0370
0371 return (-error);
0372 }
0373
0374 void
0375 ahd_power_state_change(struct ahd_softc *ahd, ahd_power_state new_state)
0376 {
0377 pci_set_power_state(ahd->dev_softc, new_state);
0378 }