2 * FreeBSD, PCI product support functions
4 * Copyright (c) 1995-2001 Justin T. Gibbs
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer,
12 * without modification, immediately at the beginning of the file.
13 * 2. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * Alternatively, this software may be distributed under the terms of the
17 * GNU Public License ("GPL").
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/ahc_pci.c#19 $
33 * $FreeBSD: src/sys/dev/aic7xxx/ahc_pci.c,v 1.64 2005/03/05 19:24:22 imp Exp $
34 * $DragonFly: src/sys/dev/disk/aic7xxx/ahc_pci.c,v 1.15 2008/05/18 20:30:21 pavalos Exp $
37 #include "aic7xxx_osm.h"
39 static int ahc_pci_probe(device_t dev
);
40 static int ahc_pci_attach(device_t dev
);
42 static device_method_t ahc_pci_device_methods
[] = {
43 /* Device interface */
44 DEVMETHOD(device_probe
, ahc_pci_probe
),
45 DEVMETHOD(device_attach
, ahc_pci_attach
),
46 DEVMETHOD(device_detach
, ahc_detach
),
50 static driver_t ahc_pci_driver
= {
52 ahc_pci_device_methods
,
53 sizeof(struct ahc_softc
)
56 DRIVER_MODULE(ahc_pci
, pci
, ahc_pci_driver
, ahc_devclass
, 0, 0);
57 DRIVER_MODULE(ahc_pci
, cardbus
, ahc_pci_driver
, ahc_devclass
, 0, 0);
58 MODULE_DEPEND(ahc_pci
, ahc
, 1, 1, 1);
59 MODULE_VERSION(ahc_pci
, 1);
62 ahc_pci_probe(device_t dev
)
64 struct ahc_pci_identity
*entry
;
66 entry
= ahc_find_pci_device(dev
);
68 device_set_desc(dev
, entry
->name
);
69 return (BUS_PROBE_DEFAULT
);
75 ahc_pci_attach(device_t dev
)
77 struct ahc_pci_identity
*entry
;
78 struct ahc_softc
*ahc
;
82 entry
= ahc_find_pci_device(dev
);
87 * Allocate a softc for this card and
88 * set it up for attachment by our
89 * common detect routine.
91 name
= kmalloc(strlen(device_get_nameunit(dev
)) + 1, M_DEVBUF
, M_INTWAIT
);
92 strcpy(name
, device_get_nameunit(dev
));
93 ahc
= ahc_alloc(dev
, name
);
97 ahc_set_unit(ahc
, device_get_unit(dev
));
100 * Should we bother disabling 39Bit addressing
101 * based on installed memory?
103 if (sizeof(bus_addr_t
) > 4)
104 ahc
->flags
|= AHC_39BIT_ADDRESSING
;
106 /* Allocate a dmatag for our SCB DMA maps */
107 /* XXX Should be a child of the PCI bus dma tag */
108 error
= aic_dma_tag_create(ahc
, /*parent*/NULL
, /*alignment*/1,
110 (ahc
->flags
& AHC_39BIT_ADDRESSING
)
112 : BUS_SPACE_MAXADDR_32BIT
,
113 /*highaddr*/BUS_SPACE_MAXADDR
,
114 /*filter*/NULL
, /*filterarg*/NULL
,
115 /*maxsize*/BUS_SPACE_MAXSIZE_32BIT
,
116 /*nsegments*/AHC_NSEG
,
117 /*maxsegsz*/AHC_MAXTRANSFER_SIZE
,
122 kprintf("ahc_pci_attach: Could not allocate DMA tag "
123 "- error %d\n", error
);
127 ahc
->dev_softc
= dev
;
128 error
= ahc_pci_config(ahc
, entry
);
139 ahc_pci_map_registers(struct ahc_softc
*ahc
)
141 struct resource
*regs
;
147 command
= aic_pci_read_config(ahc
->dev_softc
, PCIR_COMMAND
, /*bytes*/1);
152 /* Retrieve the per-device 'allow_memio' hint */
153 if (resource_int_value(device_get_name(ahc
->dev_softc
),
154 device_get_unit(ahc
->dev_softc
),
155 "allow_memio", &allow_memio
) != 0) {
157 device_printf(ahc
->dev_softc
, "Defaulting to MEMIO ");
158 #ifdef AHC_ALLOW_MEMIO
169 if ((allow_memio
!= 0) && (command
& PCIM_CMD_MEMEN
) != 0) {
171 regs_type
= SYS_RES_MEMORY
;
172 regs_id
= AHC_PCI_MEMADDR
;
173 regs
= bus_alloc_resource_any(ahc
->dev_softc
, regs_type
,
174 ®s_id
, RF_ACTIVE
);
176 ahc
->tag
= rman_get_bustag(regs
);
177 ahc
->bsh
= rman_get_bushandle(regs
);
180 * Do a quick test to see if memory mapped
181 * I/O is functioning correctly.
183 if (ahc_pci_test_register_access(ahc
) != 0) {
184 device_printf(ahc
->dev_softc
,
185 "PCI Device %d:%d:%d failed memory "
186 "mapped test. Using PIO.\n",
187 aic_get_pci_bus(ahc
->dev_softc
),
188 aic_get_pci_slot(ahc
->dev_softc
),
189 aic_get_pci_function(ahc
->dev_softc
));
190 bus_release_resource(ahc
->dev_softc
, regs_type
,
194 command
&= ~PCIM_CMD_PORTEN
;
195 aic_pci_write_config(ahc
->dev_softc
,
197 command
, /*bytes*/1);
202 if (regs
== NULL
&& (command
& PCIM_CMD_PORTEN
) != 0) {
203 regs_type
= SYS_RES_IOPORT
;
204 regs_id
= AHC_PCI_IOADDR
;
205 regs
= bus_alloc_resource_any(ahc
->dev_softc
, regs_type
,
206 ®s_id
, RF_ACTIVE
);
208 ahc
->tag
= rman_get_bustag(regs
);
209 ahc
->bsh
= rman_get_bushandle(regs
);
210 if (ahc_pci_test_register_access(ahc
) != 0) {
211 device_printf(ahc
->dev_softc
,
212 "PCI Device %d:%d:%d failed I/O "
214 aic_get_pci_bus(ahc
->dev_softc
),
215 aic_get_pci_slot(ahc
->dev_softc
),
216 aic_get_pci_function(ahc
->dev_softc
));
217 bus_release_resource(ahc
->dev_softc
, regs_type
,
221 command
&= ~PCIM_CMD_MEMEN
;
222 aic_pci_write_config(ahc
->dev_softc
,
224 command
, /*bytes*/1);
229 device_printf(ahc
->dev_softc
,
230 "can't allocate register resources\n");
233 ahc
->platform_data
->regs_res_type
= regs_type
;
234 ahc
->platform_data
->regs_res_id
= regs_id
;
235 ahc
->platform_data
->regs
= regs
;