Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/dev/aic7xxx/ahd_pci.c
39507 views
1
/*-
2
* FreeBSD, PCI product support functions
3
*
4
* Copyright (c) 1995-2001 Justin T. Gibbs
5
* All rights reserved.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
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.
15
*
16
* Alternatively, this software may be distributed under the terms of the
17
* GNU Public License ("GPL").
18
*
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
29
* SUCH DAMAGE.
30
*
31
* $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/ahd_pci.c#17 $
32
*/
33
34
#include <dev/aic7xxx/aic79xx_osm.h>
35
36
static int ahd_pci_probe(device_t dev);
37
static int ahd_pci_attach(device_t dev);
38
39
static device_method_t ahd_pci_device_methods[] = {
40
/* Device interface */
41
DEVMETHOD(device_probe, ahd_pci_probe),
42
DEVMETHOD(device_attach, ahd_pci_attach),
43
DEVMETHOD(device_detach, ahd_detach),
44
{ 0, 0 }
45
};
46
47
static driver_t ahd_pci_driver = {
48
"ahd",
49
ahd_pci_device_methods,
50
sizeof(struct ahd_softc)
51
};
52
53
DRIVER_MODULE(ahd, pci, ahd_pci_driver, 0, 0);
54
MODULE_DEPEND(ahd_pci, ahd, 1, 1, 1);
55
MODULE_VERSION(ahd_pci, 1);
56
57
static int
58
ahd_pci_probe(device_t dev)
59
{
60
struct ahd_pci_identity *entry;
61
62
entry = ahd_find_pci_device(dev);
63
if (entry != NULL) {
64
device_set_desc(dev, entry->name);
65
return (BUS_PROBE_DEFAULT);
66
}
67
return (ENXIO);
68
}
69
70
static int
71
ahd_pci_attach(device_t dev)
72
{
73
struct ahd_pci_identity *entry;
74
struct ahd_softc *ahd;
75
char *name;
76
int error;
77
78
entry = ahd_find_pci_device(dev);
79
if (entry == NULL)
80
return (ENXIO);
81
82
/*
83
* Allocate a softc for this card and
84
* set it up for attachment by our
85
* common detect routine.
86
*/
87
name = malloc(strlen(device_get_nameunit(dev)) + 1, M_DEVBUF, M_NOWAIT);
88
if (name == NULL)
89
return (ENOMEM);
90
strcpy(name, device_get_nameunit(dev));
91
ahd = ahd_alloc(dev, name);
92
if (ahd == NULL)
93
return (ENOMEM);
94
95
ahd_set_unit(ahd, device_get_unit(dev));
96
97
/*
98
* Should we bother disabling 39Bit addressing
99
* based on installed memory?
100
*/
101
if (sizeof(bus_addr_t) > 4)
102
ahd->flags |= AHD_39BIT_ADDRESSING;
103
104
/* Allocate a dmatag for our SCB DMA maps */
105
error = aic_dma_tag_create(ahd, /*parent*/bus_get_dma_tag(dev),
106
/*alignment*/1, /*boundary*/0,
107
(ahd->flags & AHD_39BIT_ADDRESSING)
108
? 0x7FFFFFFFFF
109
: BUS_SPACE_MAXADDR_32BIT,
110
/*highaddr*/BUS_SPACE_MAXADDR,
111
/*filter*/NULL, /*filterarg*/NULL,
112
/*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
113
/*nsegments*/AHD_NSEG,
114
/*maxsegsz*/AHD_MAXTRANSFER_SIZE,
115
/*flags*/0,
116
&ahd->parent_dmat);
117
118
if (error != 0) {
119
printf("ahd_pci_attach: Could not allocate DMA tag "
120
"- error %d\n", error);
121
ahd_free(ahd);
122
return (ENOMEM);
123
}
124
ahd->dev_softc = dev;
125
error = ahd_pci_config(ahd, entry);
126
if (error != 0) {
127
ahd_free(ahd);
128
return (error);
129
}
130
131
ahd_sysctl(ahd);
132
ahd_attach(ahd);
133
return (0);
134
}
135
136
int
137
ahd_pci_map_registers(struct ahd_softc *ahd)
138
{
139
struct resource *regs;
140
struct resource *regs2;
141
int regs_type;
142
int regs_id;
143
int regs_id2;
144
int allow_memio;
145
146
regs = NULL;
147
regs2 = NULL;
148
regs_type = 0;
149
regs_id = 0;
150
151
/* Retrieve the per-device 'allow_memio' hint */
152
if (resource_int_value(device_get_name(ahd->dev_softc),
153
device_get_unit(ahd->dev_softc),
154
"allow_memio", &allow_memio) != 0) {
155
if (bootverbose)
156
device_printf(ahd->dev_softc,
157
"Defaulting to MEMIO on\n");
158
allow_memio = 1;
159
}
160
161
if ((ahd->bugs & AHD_PCIX_MMAPIO_BUG) == 0
162
&& allow_memio != 0) {
163
regs_type = SYS_RES_MEMORY;
164
regs_id = AHD_PCI_MEMADDR;
165
regs = bus_alloc_resource_any(ahd->dev_softc, regs_type,
166
&regs_id, RF_ACTIVE);
167
if (regs != NULL) {
168
int error;
169
170
ahd->tags[0] = rman_get_bustag(regs);
171
ahd->bshs[0] = rman_get_bushandle(regs);
172
ahd->tags[1] = ahd->tags[0];
173
error = bus_space_subregion(ahd->tags[0], ahd->bshs[0],
174
/*offset*/0x100,
175
/*size*/0x100,
176
&ahd->bshs[1]);
177
/*
178
* Do a quick test to see if memory mapped
179
* I/O is functioning correctly.
180
*/
181
if (error != 0
182
|| ahd_pci_test_register_access(ahd) != 0) {
183
device_printf(ahd->dev_softc,
184
"PCI Device %d:%d:%d failed memory "
185
"mapped test. Using PIO.\n",
186
aic_get_pci_bus(ahd->dev_softc),
187
aic_get_pci_slot(ahd->dev_softc),
188
aic_get_pci_function(ahd->dev_softc));
189
bus_release_resource(ahd->dev_softc, regs_type,
190
regs_id, regs);
191
regs = NULL;
192
AHD_CORRECTABLE_ERROR(ahd);
193
}
194
}
195
}
196
if (regs == NULL) {
197
regs_type = SYS_RES_IOPORT;
198
regs_id = AHD_PCI_IOADDR0;
199
regs = bus_alloc_resource_any(ahd->dev_softc, regs_type,
200
&regs_id, RF_ACTIVE);
201
if (regs == NULL) {
202
device_printf(ahd->dev_softc,
203
"can't allocate register resources\n");
204
AHD_UNCORRECTABLE_ERROR(ahd);
205
return (ENOMEM);
206
}
207
ahd->tags[0] = rman_get_bustag(regs);
208
ahd->bshs[0] = rman_get_bushandle(regs);
209
210
/* And now the second BAR */
211
regs_id2 = AHD_PCI_IOADDR1;
212
regs2 = bus_alloc_resource_any(ahd->dev_softc, regs_type,
213
&regs_id2, RF_ACTIVE);
214
if (regs2 == NULL) {
215
device_printf(ahd->dev_softc,
216
"can't allocate register resources\n");
217
AHD_UNCORRECTABLE_ERROR(ahd);
218
return (ENOMEM);
219
}
220
ahd->tags[1] = rman_get_bustag(regs2);
221
ahd->bshs[1] = rman_get_bushandle(regs2);
222
ahd->platform_data->regs_res_type[1] = regs_type;
223
ahd->platform_data->regs_res_id[1] = regs_id2;
224
ahd->platform_data->regs[1] = regs2;
225
}
226
ahd->platform_data->regs_res_type[0] = regs_type;
227
ahd->platform_data->regs_res_id[0] = regs_id;
228
ahd->platform_data->regs[0] = regs;
229
return (0);
230
}
231
232
int
233
ahd_pci_map_int(struct ahd_softc *ahd)
234
{
235
int zero;
236
237
zero = 0;
238
ahd->platform_data->irq =
239
bus_alloc_resource_any(ahd->dev_softc, SYS_RES_IRQ, &zero,
240
RF_ACTIVE | RF_SHAREABLE);
241
if (ahd->platform_data->irq == NULL)
242
return (ENOMEM);
243
ahd->platform_data->irq_res_type = SYS_RES_IRQ;
244
return (ahd_map_int(ahd));
245
}
246
247