18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Linux driver attachment glue for PCI based U320 controllers. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (c) 2000-2001 Adaptec Inc. 58c2ecf20Sopenharmony_ci * All rights reserved. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 88c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions 98c2ecf20Sopenharmony_ci * are met: 108c2ecf20Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright 118c2ecf20Sopenharmony_ci * notice, this list of conditions, and the following disclaimer, 128c2ecf20Sopenharmony_ci * without modification. 138c2ecf20Sopenharmony_ci * 2. Redistributions in binary form must reproduce at minimum a disclaimer 148c2ecf20Sopenharmony_ci * substantially similar to the "NO WARRANTY" disclaimer below 158c2ecf20Sopenharmony_ci * ("Disclaimer") and any redistribution must be conditioned upon 168c2ecf20Sopenharmony_ci * including a substantially similar Disclaimer requirement for further 178c2ecf20Sopenharmony_ci * binary redistribution. 188c2ecf20Sopenharmony_ci * 3. Neither the names of the above-listed copyright holders nor the names 198c2ecf20Sopenharmony_ci * of any contributors may be used to endorse or promote products derived 208c2ecf20Sopenharmony_ci * from this software without specific prior written permission. 218c2ecf20Sopenharmony_ci * 228c2ecf20Sopenharmony_ci * Alternatively, this software may be distributed under the terms of the 238c2ecf20Sopenharmony_ci * GNU General Public License ("GPL") version 2 as published by the Free 248c2ecf20Sopenharmony_ci * Software Foundation. 258c2ecf20Sopenharmony_ci * 268c2ecf20Sopenharmony_ci * NO WARRANTY 278c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 288c2ecf20Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 298c2ecf20Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 308c2ecf20Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 318c2ecf20Sopenharmony_ci * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 328c2ecf20Sopenharmony_ci * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 338c2ecf20Sopenharmony_ci * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 348c2ecf20Sopenharmony_ci * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 358c2ecf20Sopenharmony_ci * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 368c2ecf20Sopenharmony_ci * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 378c2ecf20Sopenharmony_ci * POSSIBILITY OF SUCH DAMAGES. 388c2ecf20Sopenharmony_ci * 398c2ecf20Sopenharmony_ci * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm_pci.c#25 $ 408c2ecf20Sopenharmony_ci */ 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci#include "aic79xx_osm.h" 438c2ecf20Sopenharmony_ci#include "aic79xx_inline.h" 448c2ecf20Sopenharmony_ci#include "aic79xx_pci.h" 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci/* Define the macro locally since it's different for different class of chips. 478c2ecf20Sopenharmony_ci */ 488c2ecf20Sopenharmony_ci#define ID(x) \ 498c2ecf20Sopenharmony_ci ID2C(x), \ 508c2ecf20Sopenharmony_ci ID2C(IDIROC(x)) 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_cistatic const struct pci_device_id ahd_linux_pci_id_table[] = { 538c2ecf20Sopenharmony_ci /* aic7901 based controllers */ 548c2ecf20Sopenharmony_ci ID(ID_AHA_29320A), 558c2ecf20Sopenharmony_ci ID(ID_AHA_29320ALP), 568c2ecf20Sopenharmony_ci ID(ID_AHA_29320LPE), 578c2ecf20Sopenharmony_ci /* aic7902 based controllers */ 588c2ecf20Sopenharmony_ci ID(ID_AHA_29320), 598c2ecf20Sopenharmony_ci ID(ID_AHA_29320B), 608c2ecf20Sopenharmony_ci ID(ID_AHA_29320LP), 618c2ecf20Sopenharmony_ci ID(ID_AHA_39320), 628c2ecf20Sopenharmony_ci ID(ID_AHA_39320_B), 638c2ecf20Sopenharmony_ci ID(ID_AHA_39320A), 648c2ecf20Sopenharmony_ci ID(ID_AHA_39320D), 658c2ecf20Sopenharmony_ci ID(ID_AHA_39320D_HP), 668c2ecf20Sopenharmony_ci ID(ID_AHA_39320D_B), 678c2ecf20Sopenharmony_ci ID(ID_AHA_39320D_B_HP), 688c2ecf20Sopenharmony_ci /* Generic chip probes for devices we don't know exactly. */ 698c2ecf20Sopenharmony_ci ID16(ID_AIC7901 & ID_9005_GENERIC_MASK), 708c2ecf20Sopenharmony_ci ID(ID_AIC7901A & ID_DEV_VENDOR_MASK), 718c2ecf20Sopenharmony_ci ID16(ID_AIC7902 & ID_9005_GENERIC_MASK), 728c2ecf20Sopenharmony_ci { 0 } 738c2ecf20Sopenharmony_ci}; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pci, ahd_linux_pci_id_table); 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 788c2ecf20Sopenharmony_cistatic int 798c2ecf20Sopenharmony_ciahd_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg) 808c2ecf20Sopenharmony_ci{ 818c2ecf20Sopenharmony_ci struct ahd_softc *ahd = pci_get_drvdata(pdev); 828c2ecf20Sopenharmony_ci int rc; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci if ((rc = ahd_suspend(ahd))) 858c2ecf20Sopenharmony_ci return rc; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci ahd_pci_suspend(ahd); 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci pci_save_state(pdev); 908c2ecf20Sopenharmony_ci pci_disable_device(pdev); 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci if (mesg.event & PM_EVENT_SLEEP) 938c2ecf20Sopenharmony_ci pci_set_power_state(pdev, PCI_D3hot); 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci return rc; 968c2ecf20Sopenharmony_ci} 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_cistatic int 998c2ecf20Sopenharmony_ciahd_linux_pci_dev_resume(struct pci_dev *pdev) 1008c2ecf20Sopenharmony_ci{ 1018c2ecf20Sopenharmony_ci struct ahd_softc *ahd = pci_get_drvdata(pdev); 1028c2ecf20Sopenharmony_ci int rc; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci pci_set_power_state(pdev, PCI_D0); 1058c2ecf20Sopenharmony_ci pci_restore_state(pdev); 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci if ((rc = pci_enable_device(pdev))) { 1088c2ecf20Sopenharmony_ci dev_printk(KERN_ERR, &pdev->dev, 1098c2ecf20Sopenharmony_ci "failed to enable device after resume (%d)\n", rc); 1108c2ecf20Sopenharmony_ci return rc; 1118c2ecf20Sopenharmony_ci } 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci pci_set_master(pdev); 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci ahd_pci_resume(ahd); 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci ahd_resume(ahd); 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci return rc; 1208c2ecf20Sopenharmony_ci} 1218c2ecf20Sopenharmony_ci#endif 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_cistatic void 1248c2ecf20Sopenharmony_ciahd_linux_pci_dev_remove(struct pci_dev *pdev) 1258c2ecf20Sopenharmony_ci{ 1268c2ecf20Sopenharmony_ci struct ahd_softc *ahd = pci_get_drvdata(pdev); 1278c2ecf20Sopenharmony_ci u_long s; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci if (ahd->platform_data && ahd->platform_data->host) 1308c2ecf20Sopenharmony_ci scsi_remove_host(ahd->platform_data->host); 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci ahd_lock(ahd, &s); 1338c2ecf20Sopenharmony_ci ahd_intr_enable(ahd, FALSE); 1348c2ecf20Sopenharmony_ci ahd_unlock(ahd, &s); 1358c2ecf20Sopenharmony_ci ahd_free(ahd); 1368c2ecf20Sopenharmony_ci} 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_cistatic void 1398c2ecf20Sopenharmony_ciahd_linux_pci_inherit_flags(struct ahd_softc *ahd) 1408c2ecf20Sopenharmony_ci{ 1418c2ecf20Sopenharmony_ci struct pci_dev *pdev = ahd->dev_softc, *master_pdev; 1428c2ecf20Sopenharmony_ci unsigned int master_devfn = PCI_DEVFN(PCI_SLOT(pdev->devfn), 0); 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci master_pdev = pci_get_slot(pdev->bus, master_devfn); 1458c2ecf20Sopenharmony_ci if (master_pdev) { 1468c2ecf20Sopenharmony_ci struct ahd_softc *master = pci_get_drvdata(master_pdev); 1478c2ecf20Sopenharmony_ci if (master) { 1488c2ecf20Sopenharmony_ci ahd->flags &= ~AHD_BIOS_ENABLED; 1498c2ecf20Sopenharmony_ci ahd->flags |= master->flags & AHD_BIOS_ENABLED; 1508c2ecf20Sopenharmony_ci } else 1518c2ecf20Sopenharmony_ci printk(KERN_ERR "aic79xx: no multichannel peer found!\n"); 1528c2ecf20Sopenharmony_ci pci_dev_put(master_pdev); 1538c2ecf20Sopenharmony_ci } 1548c2ecf20Sopenharmony_ci} 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_cistatic int 1578c2ecf20Sopenharmony_ciahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci char buf[80]; 1608c2ecf20Sopenharmony_ci struct ahd_softc *ahd; 1618c2ecf20Sopenharmony_ci ahd_dev_softc_t pci; 1628c2ecf20Sopenharmony_ci const struct ahd_pci_identity *entry; 1638c2ecf20Sopenharmony_ci char *name; 1648c2ecf20Sopenharmony_ci int error; 1658c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci pci = pdev; 1688c2ecf20Sopenharmony_ci entry = ahd_find_pci_device(pci); 1698c2ecf20Sopenharmony_ci if (entry == NULL) 1708c2ecf20Sopenharmony_ci return (-ENODEV); 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci /* 1738c2ecf20Sopenharmony_ci * Allocate a softc for this card and 1748c2ecf20Sopenharmony_ci * set it up for attachment by our 1758c2ecf20Sopenharmony_ci * common detect routine. 1768c2ecf20Sopenharmony_ci */ 1778c2ecf20Sopenharmony_ci sprintf(buf, "ahd_pci:%d:%d:%d", 1788c2ecf20Sopenharmony_ci ahd_get_pci_bus(pci), 1798c2ecf20Sopenharmony_ci ahd_get_pci_slot(pci), 1808c2ecf20Sopenharmony_ci ahd_get_pci_function(pci)); 1818c2ecf20Sopenharmony_ci name = kstrdup(buf, GFP_ATOMIC); 1828c2ecf20Sopenharmony_ci if (name == NULL) 1838c2ecf20Sopenharmony_ci return (-ENOMEM); 1848c2ecf20Sopenharmony_ci ahd = ahd_alloc(NULL, name); 1858c2ecf20Sopenharmony_ci if (ahd == NULL) 1868c2ecf20Sopenharmony_ci return (-ENOMEM); 1878c2ecf20Sopenharmony_ci if (pci_enable_device(pdev)) { 1888c2ecf20Sopenharmony_ci ahd_free(ahd); 1898c2ecf20Sopenharmony_ci return (-ENODEV); 1908c2ecf20Sopenharmony_ci } 1918c2ecf20Sopenharmony_ci pci_set_master(pdev); 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci if (sizeof(dma_addr_t) > 4) { 1948c2ecf20Sopenharmony_ci const u64 required_mask = dma_get_required_mask(dev); 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci if (required_mask > DMA_BIT_MASK(39) && 1978c2ecf20Sopenharmony_ci dma_set_mask(dev, DMA_BIT_MASK(64)) == 0) 1988c2ecf20Sopenharmony_ci ahd->flags |= AHD_64BIT_ADDRESSING; 1998c2ecf20Sopenharmony_ci else if (required_mask > DMA_BIT_MASK(32) && 2008c2ecf20Sopenharmony_ci dma_set_mask(dev, DMA_BIT_MASK(39)) == 0) 2018c2ecf20Sopenharmony_ci ahd->flags |= AHD_39BIT_ADDRESSING; 2028c2ecf20Sopenharmony_ci else 2038c2ecf20Sopenharmony_ci dma_set_mask(dev, DMA_BIT_MASK(32)); 2048c2ecf20Sopenharmony_ci } else { 2058c2ecf20Sopenharmony_ci dma_set_mask(dev, DMA_BIT_MASK(32)); 2068c2ecf20Sopenharmony_ci } 2078c2ecf20Sopenharmony_ci ahd->dev_softc = pci; 2088c2ecf20Sopenharmony_ci error = ahd_pci_config(ahd, entry); 2098c2ecf20Sopenharmony_ci if (error != 0) { 2108c2ecf20Sopenharmony_ci ahd_free(ahd); 2118c2ecf20Sopenharmony_ci return (-error); 2128c2ecf20Sopenharmony_ci } 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci /* 2158c2ecf20Sopenharmony_ci * Second Function PCI devices need to inherit some 2168c2ecf20Sopenharmony_ci * * settings from function 0. 2178c2ecf20Sopenharmony_ci */ 2188c2ecf20Sopenharmony_ci if ((ahd->features & AHD_MULTI_FUNC) && PCI_FUNC(pdev->devfn) != 0) 2198c2ecf20Sopenharmony_ci ahd_linux_pci_inherit_flags(ahd); 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci pci_set_drvdata(pdev, ahd); 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci ahd_linux_register_host(ahd, &aic79xx_driver_template); 2248c2ecf20Sopenharmony_ci return (0); 2258c2ecf20Sopenharmony_ci} 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_cistatic struct pci_driver aic79xx_pci_driver = { 2288c2ecf20Sopenharmony_ci .name = "aic79xx", 2298c2ecf20Sopenharmony_ci .probe = ahd_linux_pci_dev_probe, 2308c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 2318c2ecf20Sopenharmony_ci .suspend = ahd_linux_pci_dev_suspend, 2328c2ecf20Sopenharmony_ci .resume = ahd_linux_pci_dev_resume, 2338c2ecf20Sopenharmony_ci#endif 2348c2ecf20Sopenharmony_ci .remove = ahd_linux_pci_dev_remove, 2358c2ecf20Sopenharmony_ci .id_table = ahd_linux_pci_id_table 2368c2ecf20Sopenharmony_ci}; 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ciint 2398c2ecf20Sopenharmony_ciahd_linux_pci_init(void) 2408c2ecf20Sopenharmony_ci{ 2418c2ecf20Sopenharmony_ci return pci_register_driver(&aic79xx_pci_driver); 2428c2ecf20Sopenharmony_ci} 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_civoid 2458c2ecf20Sopenharmony_ciahd_linux_pci_exit(void) 2468c2ecf20Sopenharmony_ci{ 2478c2ecf20Sopenharmony_ci pci_unregister_driver(&aic79xx_pci_driver); 2488c2ecf20Sopenharmony_ci} 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_cistatic int 2518c2ecf20Sopenharmony_ciahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd, resource_size_t *base, 2528c2ecf20Sopenharmony_ci resource_size_t *base2) 2538c2ecf20Sopenharmony_ci{ 2548c2ecf20Sopenharmony_ci *base = pci_resource_start(ahd->dev_softc, 0); 2558c2ecf20Sopenharmony_ci /* 2568c2ecf20Sopenharmony_ci * This is really the 3rd bar and should be at index 2, 2578c2ecf20Sopenharmony_ci * but the Linux PCI code doesn't know how to "count" 64bit 2588c2ecf20Sopenharmony_ci * bars. 2598c2ecf20Sopenharmony_ci */ 2608c2ecf20Sopenharmony_ci *base2 = pci_resource_start(ahd->dev_softc, 3); 2618c2ecf20Sopenharmony_ci if (*base == 0 || *base2 == 0) 2628c2ecf20Sopenharmony_ci return (ENOMEM); 2638c2ecf20Sopenharmony_ci if (!request_region(*base, 256, "aic79xx")) 2648c2ecf20Sopenharmony_ci return (ENOMEM); 2658c2ecf20Sopenharmony_ci if (!request_region(*base2, 256, "aic79xx")) { 2668c2ecf20Sopenharmony_ci release_region(*base, 256); 2678c2ecf20Sopenharmony_ci return (ENOMEM); 2688c2ecf20Sopenharmony_ci } 2698c2ecf20Sopenharmony_ci return (0); 2708c2ecf20Sopenharmony_ci} 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_cistatic int 2738c2ecf20Sopenharmony_ciahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd, 2748c2ecf20Sopenharmony_ci resource_size_t *bus_addr, 2758c2ecf20Sopenharmony_ci uint8_t __iomem **maddr) 2768c2ecf20Sopenharmony_ci{ 2778c2ecf20Sopenharmony_ci resource_size_t start; 2788c2ecf20Sopenharmony_ci resource_size_t base_page; 2798c2ecf20Sopenharmony_ci u_long base_offset; 2808c2ecf20Sopenharmony_ci int error = 0; 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci if (aic79xx_allow_memio == 0) 2838c2ecf20Sopenharmony_ci return (ENOMEM); 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci if ((ahd->bugs & AHD_PCIX_MMAPIO_BUG) != 0) 2868c2ecf20Sopenharmony_ci return (ENOMEM); 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci start = pci_resource_start(ahd->dev_softc, 1); 2898c2ecf20Sopenharmony_ci base_page = start & PAGE_MASK; 2908c2ecf20Sopenharmony_ci base_offset = start - base_page; 2918c2ecf20Sopenharmony_ci if (start != 0) { 2928c2ecf20Sopenharmony_ci *bus_addr = start; 2938c2ecf20Sopenharmony_ci if (!request_mem_region(start, 0x1000, "aic79xx")) 2948c2ecf20Sopenharmony_ci error = ENOMEM; 2958c2ecf20Sopenharmony_ci if (!error) { 2968c2ecf20Sopenharmony_ci *maddr = ioremap(base_page, base_offset + 512); 2978c2ecf20Sopenharmony_ci if (*maddr == NULL) { 2988c2ecf20Sopenharmony_ci error = ENOMEM; 2998c2ecf20Sopenharmony_ci release_mem_region(start, 0x1000); 3008c2ecf20Sopenharmony_ci } else 3018c2ecf20Sopenharmony_ci *maddr += base_offset; 3028c2ecf20Sopenharmony_ci } 3038c2ecf20Sopenharmony_ci } else 3048c2ecf20Sopenharmony_ci error = ENOMEM; 3058c2ecf20Sopenharmony_ci return (error); 3068c2ecf20Sopenharmony_ci} 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ciint 3098c2ecf20Sopenharmony_ciahd_pci_map_registers(struct ahd_softc *ahd) 3108c2ecf20Sopenharmony_ci{ 3118c2ecf20Sopenharmony_ci uint32_t command; 3128c2ecf20Sopenharmony_ci resource_size_t base; 3138c2ecf20Sopenharmony_ci uint8_t __iomem *maddr; 3148c2ecf20Sopenharmony_ci int error; 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci /* 3178c2ecf20Sopenharmony_ci * If its allowed, we prefer memory mapped access. 3188c2ecf20Sopenharmony_ci */ 3198c2ecf20Sopenharmony_ci command = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, 4); 3208c2ecf20Sopenharmony_ci command &= ~(PCIM_CMD_PORTEN|PCIM_CMD_MEMEN); 3218c2ecf20Sopenharmony_ci base = 0; 3228c2ecf20Sopenharmony_ci maddr = NULL; 3238c2ecf20Sopenharmony_ci error = ahd_linux_pci_reserve_mem_region(ahd, &base, &maddr); 3248c2ecf20Sopenharmony_ci if (error == 0) { 3258c2ecf20Sopenharmony_ci ahd->platform_data->mem_busaddr = base; 3268c2ecf20Sopenharmony_ci ahd->tags[0] = BUS_SPACE_MEMIO; 3278c2ecf20Sopenharmony_ci ahd->bshs[0].maddr = maddr; 3288c2ecf20Sopenharmony_ci ahd->tags[1] = BUS_SPACE_MEMIO; 3298c2ecf20Sopenharmony_ci ahd->bshs[1].maddr = maddr + 0x100; 3308c2ecf20Sopenharmony_ci ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, 3318c2ecf20Sopenharmony_ci command | PCIM_CMD_MEMEN, 4); 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci if (ahd_pci_test_register_access(ahd) != 0) { 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci printk("aic79xx: PCI Device %d:%d:%d " 3368c2ecf20Sopenharmony_ci "failed memory mapped test. Using PIO.\n", 3378c2ecf20Sopenharmony_ci ahd_get_pci_bus(ahd->dev_softc), 3388c2ecf20Sopenharmony_ci ahd_get_pci_slot(ahd->dev_softc), 3398c2ecf20Sopenharmony_ci ahd_get_pci_function(ahd->dev_softc)); 3408c2ecf20Sopenharmony_ci iounmap(maddr); 3418c2ecf20Sopenharmony_ci release_mem_region(ahd->platform_data->mem_busaddr, 3428c2ecf20Sopenharmony_ci 0x1000); 3438c2ecf20Sopenharmony_ci ahd->bshs[0].maddr = NULL; 3448c2ecf20Sopenharmony_ci maddr = NULL; 3458c2ecf20Sopenharmony_ci } else 3468c2ecf20Sopenharmony_ci command |= PCIM_CMD_MEMEN; 3478c2ecf20Sopenharmony_ci } else if (bootverbose) { 3488c2ecf20Sopenharmony_ci printk("aic79xx: PCI%d:%d:%d MEM region 0x%llx " 3498c2ecf20Sopenharmony_ci "unavailable. Cannot memory map device.\n", 3508c2ecf20Sopenharmony_ci ahd_get_pci_bus(ahd->dev_softc), 3518c2ecf20Sopenharmony_ci ahd_get_pci_slot(ahd->dev_softc), 3528c2ecf20Sopenharmony_ci ahd_get_pci_function(ahd->dev_softc), 3538c2ecf20Sopenharmony_ci (unsigned long long)base); 3548c2ecf20Sopenharmony_ci } 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci if (maddr == NULL) { 3578c2ecf20Sopenharmony_ci resource_size_t base2; 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci error = ahd_linux_pci_reserve_io_regions(ahd, &base, &base2); 3608c2ecf20Sopenharmony_ci if (error == 0) { 3618c2ecf20Sopenharmony_ci ahd->tags[0] = BUS_SPACE_PIO; 3628c2ecf20Sopenharmony_ci ahd->tags[1] = BUS_SPACE_PIO; 3638c2ecf20Sopenharmony_ci ahd->bshs[0].ioport = (u_long)base; 3648c2ecf20Sopenharmony_ci ahd->bshs[1].ioport = (u_long)base2; 3658c2ecf20Sopenharmony_ci command |= PCIM_CMD_PORTEN; 3668c2ecf20Sopenharmony_ci } else { 3678c2ecf20Sopenharmony_ci printk("aic79xx: PCI%d:%d:%d IO regions 0x%llx and " 3688c2ecf20Sopenharmony_ci "0x%llx unavailable. Cannot map device.\n", 3698c2ecf20Sopenharmony_ci ahd_get_pci_bus(ahd->dev_softc), 3708c2ecf20Sopenharmony_ci ahd_get_pci_slot(ahd->dev_softc), 3718c2ecf20Sopenharmony_ci ahd_get_pci_function(ahd->dev_softc), 3728c2ecf20Sopenharmony_ci (unsigned long long)base, 3738c2ecf20Sopenharmony_ci (unsigned long long)base2); 3748c2ecf20Sopenharmony_ci } 3758c2ecf20Sopenharmony_ci } 3768c2ecf20Sopenharmony_ci ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, 4); 3778c2ecf20Sopenharmony_ci return (error); 3788c2ecf20Sopenharmony_ci} 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ciint 3818c2ecf20Sopenharmony_ciahd_pci_map_int(struct ahd_softc *ahd) 3828c2ecf20Sopenharmony_ci{ 3838c2ecf20Sopenharmony_ci int error; 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci error = request_irq(ahd->dev_softc->irq, ahd_linux_isr, 3868c2ecf20Sopenharmony_ci IRQF_SHARED, "aic79xx", ahd); 3878c2ecf20Sopenharmony_ci if (!error) 3888c2ecf20Sopenharmony_ci ahd->platform_data->irq = ahd->dev_softc->irq; 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci return (-error); 3918c2ecf20Sopenharmony_ci} 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_civoid 3948c2ecf20Sopenharmony_ciahd_power_state_change(struct ahd_softc *ahd, ahd_power_state new_state) 3958c2ecf20Sopenharmony_ci{ 3968c2ecf20Sopenharmony_ci pci_set_power_state(ahd->dev_softc, new_state); 3978c2ecf20Sopenharmony_ci} 398