Commit | Line | Data |
---|---|---|
984263bc MD |
1 | /* |
2 | * Device probe and attach routines for the following | |
3 | * Advanced Systems Inc. SCSI controllers: | |
4 | * | |
5 | * Connectivity Products: | |
6 | * ABP902/3902 - Bus-Master PCI (16 CDB) | |
7 | * ABP3905 - Bus-Master PCI (16 CDB) | |
8 | * ABP915 - Bus-Master PCI (16 CDB) | |
9 | * ABP920 - Bus-Master PCI (16 CDB) | |
10 | * ABP3922 - Bus-Master PCI (16 CDB) | |
11 | * ABP3925 - Bus-Master PCI (16 CDB) | |
12 | * ABP930 - Bus-Master PCI (16 CDB) * | |
13 | * ABP930U - Bus-Master PCI Ultra (16 CDB) | |
14 | * ABP930UA - Bus-Master PCI Ultra (16 CDB) | |
15 | * ABP960 - Bus-Master PCI MAC/PC (16 CDB) ** | |
16 | * ABP960U - Bus-Master PCI MAC/PC (16 CDB) ** | |
17 | * | |
18 | * Single Channel Products: | |
19 | * ABP940 - Bus-Master PCI (240 CDB) | |
20 | * ABP940U - Bus-Master PCI Ultra (240 CDB) | |
21 | * ABP940UA/3940UA - Bus-Master PCI Ultra (240 CDB) | |
22 | * ABP3960UA - Bus-Master PCI MAC/PC (240 CDB) | |
23 | * ABP970 - Bus-Master PCI MAC/PC (240 CDB) | |
24 | * ABP970U - Bus-Master PCI MAC/PC Ultra (240 CDB) | |
25 | * | |
26 | * Dual Channel Products: | |
27 | * ABP950 - Dual Channel Bus-Master PCI (240 CDB Per Channel) | |
28 | * ABP980 - Four Channel Bus-Master PCI (240 CDB Per Channel) | |
29 | * ABP980U - Four Channel Bus-Master PCI Ultra (240 CDB Per Channel) | |
30 | * ABP980UA/3980UA - Four Channel Bus-Master PCI Ultra (16 CDB Per Chan.) | |
31 | * | |
32 | * Footnotes: | |
33 | * * This board has been sold by SIIG as the Fast SCSI Pro PCI. | |
34 | * ** This board has been sold by Iomega as a Jaz Jet PCI adapter. | |
35 | * | |
36 | * Copyright (c) 1997 Justin Gibbs. | |
37 | * All rights reserved. | |
38 | * | |
39 | * Redistribution and use in source and binary forms, with or without | |
40 | * modification, are permitted provided that the following conditions | |
41 | * are met: | |
42 | * 1. Redistributions of source code must retain the above copyright | |
43 | * notice, this list of conditions, and the following disclaimer, | |
44 | * without modification. | |
45 | * 2. The name of the author may not be used to endorse or promote products | |
46 | * derived from this software without specific prior written permission. | |
47 | * | |
48 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
49 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
50 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
51 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR | |
52 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
53 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
54 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
55 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
56 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
57 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
58 | * SUCH DAMAGE. | |
59 | * | |
60 | * $FreeBSD: src/sys/dev/advansys/adv_pci.c,v 1.11.2.3 2001/06/02 04:38:10 nyan Exp $ | |
61 | */ | |
62 | ||
63 | #include <sys/param.h> | |
64 | #include <sys/systm.h> | |
65 | #include <sys/kernel.h> | |
984263bc MD |
66 | #include <sys/bus.h> |
67 | #include <sys/rman.h> | |
68 | ||
1f2de5d4 MD |
69 | #include <bus/pci/pcireg.h> |
70 | #include <bus/pci/pcivar.h> | |
984263bc | 71 | |
1f2de5d4 | 72 | #include "advansys.h" |
984263bc MD |
73 | |
74 | #define PCI_BASEADR0 PCIR_MAPS /* I/O Address */ | |
75 | #define PCI_BASEADR1 PCIR_MAPS + 4 /* Mem I/O Address */ | |
76 | ||
77 | #define PCI_DEVICE_ID_ADVANSYS_1200A 0x110010CD | |
78 | #define PCI_DEVICE_ID_ADVANSYS_1200B 0x120010CD | |
79 | #define PCI_DEVICE_ID_ADVANSYS_3000 0x130010CD | |
80 | #define PCI_DEVICE_REV_ADVANSYS_3150 0x02 | |
81 | #define PCI_DEVICE_REV_ADVANSYS_3050 0x03 | |
82 | ||
83 | #define ADV_PCI_MAX_DMA_ADDR (0xFFFFFFFFL) | |
84 | #define ADV_PCI_MAX_DMA_COUNT (0xFFFFFFFFL) | |
85 | ||
86 | static int adv_pci_probe(device_t); | |
87 | static int adv_pci_attach(device_t); | |
88 | ||
89 | /* | |
90 | * The overrun buffer shared amongst all PCI adapters. | |
91 | */ | |
92 | static u_int8_t* overrun_buf; | |
93 | static bus_dma_tag_t overrun_dmat; | |
94 | static bus_dmamap_t overrun_dmamap; | |
95 | static bus_addr_t overrun_physbase; | |
96 | ||
97 | static int | |
98 | adv_pci_probe(device_t dev) | |
99 | { | |
100 | int rev = pci_get_revid(dev); | |
101 | ||
102 | switch (pci_get_devid(dev)) { | |
103 | case PCI_DEVICE_ID_ADVANSYS_1200A: | |
104 | device_set_desc(dev, "AdvanSys ASC1200A SCSI controller"); | |
105 | return 0; | |
106 | case PCI_DEVICE_ID_ADVANSYS_1200B: | |
107 | device_set_desc(dev, "AdvanSys ASC1200B SCSI controller"); | |
108 | return 0; | |
109 | case PCI_DEVICE_ID_ADVANSYS_3000: | |
110 | if (rev == PCI_DEVICE_REV_ADVANSYS_3150) { | |
111 | device_set_desc(dev, | |
112 | "AdvanSys ASC3150 SCSI controller"); | |
113 | return 0; | |
114 | } else if (rev == PCI_DEVICE_REV_ADVANSYS_3050) { | |
115 | device_set_desc(dev, | |
116 | "AdvanSys ASC3030/50 SCSI controller"); | |
117 | return 0; | |
118 | } else if (rev >= PCI_DEVICE_REV_ADVANSYS_3150) { | |
119 | device_set_desc(dev, "Unknown AdvanSys controller"); | |
120 | return 0; | |
121 | } | |
122 | break; | |
123 | default: | |
124 | break; | |
125 | } | |
126 | return ENXIO; | |
127 | } | |
128 | ||
129 | static int | |
130 | adv_pci_attach(device_t dev) | |
131 | { | |
132 | struct adv_softc *adv; | |
133 | u_int32_t id; | |
134 | u_int32_t command; | |
135 | int error, rid, irqrid; | |
136 | void *ih; | |
137 | struct resource *iores, *irqres; | |
138 | ||
139 | /* | |
140 | * Determine the chip version. | |
141 | */ | |
142 | id = pci_read_config(dev, PCIR_DEVVENDOR, /*bytes*/4); | |
143 | command = pci_read_config(dev, PCIR_COMMAND, /*bytes*/1); | |
144 | ||
145 | /* | |
146 | * These cards do not allow memory mapped accesses, so we must | |
147 | * ensure that I/O accesses are available or we won't be able | |
148 | * to talk to them. | |
149 | */ | |
150 | if ((command & (PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN)) | |
151 | != (PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN)) { | |
152 | command |= PCIM_CMD_PORTEN|PCIM_CMD_BUSMASTEREN; | |
153 | pci_write_config(dev, PCIR_COMMAND, command, /*bytes*/1); | |
154 | } | |
155 | ||
156 | /* | |
157 | * Early chips can't handle non-zero latency timer settings. | |
158 | */ | |
159 | if (id == PCI_DEVICE_ID_ADVANSYS_1200A | |
160 | || id == PCI_DEVICE_ID_ADVANSYS_1200B) { | |
161 | pci_write_config(dev, PCIR_LATTIMER, /*value*/0, /*bytes*/1); | |
162 | } | |
163 | ||
164 | rid = PCI_BASEADR0; | |
165 | iores = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, | |
166 | RF_ACTIVE); | |
167 | if (iores == NULL) | |
168 | return ENXIO; | |
169 | ||
170 | if (adv_find_signature(rman_get_bustag(iores), | |
171 | rman_get_bushandle(iores)) == 0) { | |
172 | bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); | |
173 | return ENXIO; | |
174 | } | |
175 | ||
176 | adv = adv_alloc(dev, rman_get_bustag(iores), rman_get_bushandle(iores)); | |
177 | if (adv == NULL) { | |
178 | bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); | |
179 | return ENXIO; | |
180 | } | |
181 | ||
182 | /* Allocate a dmatag for our transfer DMA maps */ | |
183 | /* XXX Should be a child of the PCI bus dma tag */ | |
184 | error = bus_dma_tag_create(/*parent*/NULL, /*alignment*/1, | |
185 | /*boundary*/0, | |
186 | /*lowaddr*/ADV_PCI_MAX_DMA_ADDR, | |
187 | /*highaddr*/BUS_SPACE_MAXADDR, | |
984263bc MD |
188 | /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, |
189 | /*nsegments*/BUS_SPACE_UNRESTRICTED, | |
190 | /*maxsegsz*/ADV_PCI_MAX_DMA_COUNT, | |
191 | /*flags*/0, | |
192 | &adv->parent_dmat); | |
193 | ||
194 | if (error != 0) { | |
e3869ec7 | 195 | kprintf("%s: Could not allocate DMA tag - error %d\n", |
984263bc MD |
196 | adv_name(adv), error); |
197 | adv_free(adv); | |
198 | bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); | |
199 | return ENXIO; | |
200 | } | |
201 | ||
202 | adv->init_level++; | |
203 | ||
204 | if (overrun_buf == NULL) { | |
205 | /* Need to allocate our overrun buffer */ | |
206 | if (bus_dma_tag_create(adv->parent_dmat, | |
207 | /*alignment*/8, /*boundary*/0, | |
208 | ADV_PCI_MAX_DMA_ADDR, BUS_SPACE_MAXADDR, | |
984263bc MD |
209 | ADV_OVERRUN_BSIZE, /*nsegments*/1, |
210 | BUS_SPACE_MAXSIZE_32BIT, /*flags*/0, | |
211 | &overrun_dmat) != 0) { | |
212 | bus_dma_tag_destroy(adv->parent_dmat); | |
213 | adv_free(adv); | |
214 | bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); | |
215 | return ENXIO; | |
216 | } | |
217 | if (bus_dmamem_alloc(overrun_dmat, | |
da44240f | 218 | (void *)&overrun_buf, |
984263bc MD |
219 | BUS_DMA_NOWAIT, |
220 | &overrun_dmamap) != 0) { | |
221 | bus_dma_tag_destroy(overrun_dmat); | |
222 | bus_dma_tag_destroy(adv->parent_dmat); | |
223 | adv_free(adv); | |
224 | bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); | |
225 | return ENXIO; | |
226 | } | |
227 | /* And permanently map it in */ | |
228 | bus_dmamap_load(overrun_dmat, overrun_dmamap, | |
229 | overrun_buf, ADV_OVERRUN_BSIZE, | |
230 | adv_map, &overrun_physbase, | |
231 | /*flags*/0); | |
232 | } | |
233 | ||
234 | adv->overrun_physbase = overrun_physbase; | |
235 | ||
236 | /* | |
237 | * Stop the chip. | |
238 | */ | |
239 | ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT); | |
240 | ADV_OUTW(adv, ADV_CHIP_STATUS, 0); | |
241 | ||
242 | adv->chip_version = ADV_INB(adv, ADV_NONEISA_CHIP_REVISION); | |
243 | adv->type = ADV_PCI; | |
244 | ||
245 | /* | |
246 | * Setup active negation and signal filtering. | |
247 | */ | |
248 | { | |
249 | u_int8_t extra_cfg; | |
250 | ||
251 | if (adv->chip_version >= ADV_CHIP_VER_PCI_ULTRA_3150) | |
252 | adv->type |= ADV_ULTRA; | |
253 | if (adv->chip_version == ADV_CHIP_VER_PCI_ULTRA_3050) | |
254 | extra_cfg = ADV_IFC_ACT_NEG | ADV_IFC_WR_EN_FILTER; | |
255 | else | |
256 | extra_cfg = ADV_IFC_ACT_NEG | ADV_IFC_SLEW_RATE; | |
257 | ADV_OUTB(adv, ADV_REG_IFC, extra_cfg); | |
258 | } | |
259 | ||
260 | if (adv_init(adv) != 0) { | |
261 | adv_free(adv); | |
262 | bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); | |
263 | return ENXIO; | |
264 | } | |
265 | ||
266 | adv->max_dma_count = ADV_PCI_MAX_DMA_COUNT; | |
267 | adv->max_dma_addr = ADV_PCI_MAX_DMA_ADDR; | |
268 | ||
aa28b4e8 | 269 | #if defined(CC_DISABLE_PCI_PARITY_INT) && CC_DISABLE_PCI_PARITY_INT |
984263bc MD |
270 | { |
271 | u_int16_t config_msw; | |
272 | ||
273 | config_msw = ADV_INW(adv, ADV_CONFIG_MSW); | |
274 | config_msw &= 0xFFC0; | |
275 | ADV_OUTW(adv, ADV_CONFIG_MSW, config_msw); | |
276 | } | |
277 | #endif | |
278 | ||
279 | if (id == PCI_DEVICE_ID_ADVANSYS_1200A | |
280 | || id == PCI_DEVICE_ID_ADVANSYS_1200B) { | |
281 | adv->bug_fix_control |= ADV_BUG_FIX_IF_NOT_DWB; | |
282 | adv->bug_fix_control |= ADV_BUG_FIX_ASYN_USE_SYN; | |
283 | adv->fix_asyn_xfer = ~0; | |
284 | } | |
285 | ||
286 | irqrid = 0; | |
287 | irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &irqrid, 0, ~0, 1, | |
288 | RF_SHAREABLE | RF_ACTIVE); | |
289 | if (irqres == NULL || | |
ee61f228 | 290 | bus_setup_intr(dev, irqres, 0, adv_intr, adv, &ih, NULL)) { |
984263bc MD |
291 | adv_free(adv); |
292 | bus_release_resource(dev, SYS_RES_IOPORT, rid, iores); | |
293 | return ENXIO; | |
294 | } | |
295 | ||
296 | adv_attach(adv); | |
297 | return 0; | |
298 | } | |
299 | ||
300 | static device_method_t adv_pci_methods[] = { | |
301 | /* Device interface */ | |
302 | DEVMETHOD(device_probe, adv_pci_probe), | |
303 | DEVMETHOD(device_attach, adv_pci_attach), | |
d3c9c58e | 304 | DEVMETHOD_END |
984263bc MD |
305 | }; |
306 | ||
307 | static driver_t adv_pci_driver = { | |
308 | "adv", adv_pci_methods, sizeof(struct adv_softc) | |
309 | }; | |
310 | ||
311 | static devclass_t adv_pci_devclass; | |
aa2b9d05 | 312 | DRIVER_MODULE(adv, pci, adv_pci_driver, adv_pci_devclass, NULL, NULL); |