1 /*
2 * Device probe and attach routines for the following
3 * Advanced Systems Inc. SCSI controllers:
4 *
5 * Single Channel Products:
6 * ABP742 - Bus-Master EISA (240 CDB)
7 *
8 * Dual Channel Products:
9 * ABP752 - Dual Channel Bus-Master EISA (240 CDB Per Channel)
10 *
11 * Copyright (c) 1997 Justin Gibbs.
12 * All rights reserved.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions, and the following disclaimer,
19 * without modification, immediately at the beginning of the file.
20 * 2. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
27 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * $FreeBSD$
36 */
37
38 #include "eisa.h"
39 #if NEISA > 0
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/kernel.h>
44
45 #include <machine/bus_pio.h>
46 #include <machine/bus.h>
47
48 #include <i386/eisa/eisaconf.h>
49
50 #include <dev/advansys/advansys.h>
51
52 #define EISA_DEVICE_ID_ADVANSYS_740 0x04507400
53 #define EISA_DEVICE_ID_ADVANSYS_750 0x04507500
54
55 #define ADV_EISA_SLOT_OFFSET 0xc00
56 #define ADV_EISA_OFFSET_CHAN1 0x30
57 #define ADV_EISA_OFFSET_CHAN2 0x50
58 #define ADV_EISA_IOSIZE 0x100
59
60 #define ADV_EISA_ROM_BIOS_ADDR_REG 0x86
61 #define ADV_EISA_IRQ_BURST_LEN_REG 0x87
62 #define ADV_EISA_IRQ_MASK 0x07
63 #define ADV_EISA_IRQ_10 0x00
64 #define ADV_EISA_IRQ_11 0x01
65 #define ADV_EISA_IRQ_12 0x02
66 #define ADV_EISA_IRQ_14 0x04
67 #define ADV_EISA_IRQ_15 0x05
68
69 #define ADV_EISA_MAX_DMA_ADDR (0x07FFFFFFL)
70 #define ADV_EISA_MAX_DMA_COUNT (0x07FFFFFFL)
71
72 static int adveisaprobe(void);
73 static int adveisaattach(struct eisa_device *e_dev);
74
75 /*
76 * The overrun buffer shared amongst all EISA adapters.
77 */
78 static u_int8_t* overrun_buf;
79 static bus_dma_tag_t overrun_dmat;
80 static bus_dmamap_t overrun_dmamap;
81 static bus_addr_t overrun_physbase;
82
83 static struct eisa_driver adv_eisa_driver =
84 {
85 "adv",
86 adveisaprobe,
87 adveisaattach,
88 /*shutdown*/NULL,
89 &adv_unit
90 };
91
92 DATA_SET (eisadriver_set, adv_eisa_driver);
93
94 static const char *adveisamatch(eisa_id_t type);
95
96 static const char*
97 adveisamatch(type)
98 eisa_id_t type;
99 {
100 switch (type & ~0xF) {
101 case EISA_DEVICE_ID_ADVANSYS_740:
102 return ("AdvanSys ABP-740/742 SCSI adapter");
103 break;
104 case EISA_DEVICE_ID_ADVANSYS_750:
105 return ("AdvanSys ABP-750/752 SCSI adapter");
106 break;
107 default:
108 break;
109 }
110 return (NULL);
111 }
112
113 static int
114 adveisaprobe(void)
115 {
116 u_int32_t iobase;
117 u_int8_t irq;
118 struct eisa_device *e_dev = NULL;
119 int count;
120
121 count = 0;
122 while ((e_dev = eisa_match_dev(e_dev, adveisamatch))) {
123 iobase = (e_dev->ioconf.slot * EISA_SLOT_SIZE)
124 + ADV_EISA_SLOT_OFFSET;
125
126 eisa_add_iospace(e_dev, iobase, ADV_EISA_IOSIZE, RESVADDR_NONE);
127 irq = inb(iobase + ADV_EISA_IRQ_BURST_LEN_REG);
128 irq &= ADV_EISA_IRQ_MASK;
129 switch (irq) {
130 case 0:
131 case 1:
132 case 2:
133 case 4:
134 case 5:
135 break;
136 default:
137 printf("adv at slot %d: illegal "
138 "irq setting %d\n", e_dev->ioconf.slot,
139 irq);
140 continue;
141 }
142 eisa_add_intr(e_dev, irq + 10);
143 eisa_registerdev(e_dev, &adv_eisa_driver);
144 count++;
145 }
146 return count;
147 }
148
149 static int
150 adveisaattach(struct eisa_device *e_dev)
151 {
152 struct adv_softc *adv;
153 struct adv_softc *adv_b;
154 resvaddr_t *iospace;
155 int unit;
156 int irq;
157 int error;
158
159 adv_b = NULL;
160 unit = e_dev->unit;
161 iospace = e_dev->ioconf.ioaddrs.lh_first;
162
163 if (TAILQ_FIRST(&e_dev->ioconf.irqs) == NULL)
164 return (-1);
165
166 irq = TAILQ_FIRST(&e_dev->ioconf.irqs)->irq_no;
167
168 if (!iospace)
169 return (-1);
170
171 switch (e_dev->id & ~0xF) {
172 case EISA_DEVICE_ID_ADVANSYS_750:
173 adv_b = adv_alloc(unit, I386_BUS_SPACE_IO,
174 iospace->addr + ADV_EISA_OFFSET_CHAN2);
175 if (adv_b == NULL)
176 return (-1);
177
178 /*
179 * Allocate a parent dmatag for all tags created
180 * by the MI portions of the advansys driver
181 */
182 /* XXX Should be a child of the PCI bus dma tag */
183 error = bus_dma_tag_create(/*parent*/NULL, /*alignment*/1,
184 /*boundary*/0,
185 /*lowaddr*/ADV_EISA_MAX_DMA_ADDR,
186 /*highaddr*/BUS_SPACE_MAXADDR,
187 /*filter*/NULL, /*filterarg*/NULL,
188 /*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
189 /*nsegments*/BUS_SPACE_UNRESTRICTED,
190 /*maxsegsz*/ADV_EISA_MAX_DMA_COUNT,
191 /*flags*/0,
192 &adv_b->parent_dmat);
193
194 if (error != 0) {
195 printf("%s: Could not allocate DMA tag - error %d\n",
196 adv_name(adv_b), error);
197 adv_free(adv_b);
198 return (-1);
199 }
200
201 adv_b->init_level++;
202
203 /* FALLTHROUGH */
204 case EISA_DEVICE_ID_ADVANSYS_740:
205 adv = adv_alloc(unit, I386_BUS_SPACE_IO,
206 iospace->addr + ADV_EISA_OFFSET_CHAN1);
207 if (adv == NULL) {
208 if (adv_b != NULL)
209 adv_free(adv_b);
210 return (-1);
211 }
212
213 /*
214 * Allocate a parent dmatag for all tags created
215 * by the MI portions of the advansys driver
216 */
217 /* XXX Should be a child of the PCI bus dma tag */
218 error = bus_dma_tag_create(/*parent*/NULL, /*alignment*/1,
219 /*boundary*/0,
220 /*lowaddr*/ADV_EISA_MAX_DMA_ADDR,
221 /*highaddr*/BUS_SPACE_MAXADDR,
222 /*filter*/NULL, /*filterarg*/NULL,
223 /*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
224 /*nsegments*/BUS_SPACE_UNRESTRICTED,
225 /*maxsegsz*/ADV_EISA_MAX_DMA_COUNT,
226 /*flags*/0,
227 &adv->parent_dmat);
228
229 if (error != 0) {
230 printf("%s: Could not allocate DMA tag - error %d\n",
231 adv_name(adv), error);
232 adv_free(adv);
233 return (-1);
234 }
235
236 adv->init_level++;
237 break;
238 default:
239 printf("adveisaattach: Unknown device type!\n");
240 return (-1);
241 break;
242 }
243
244 if (overrun_buf == NULL) {
245 /* Need to allocate our overrun buffer */
246 if (bus_dma_tag_create(adv->parent_dmat,
247 /*alignment*/8,
248 /*boundary*/0,
249 ADV_EISA_MAX_DMA_ADDR,
250 BUS_SPACE_MAXADDR,
251 /*filter*/NULL,
252 /*filterarg*/NULL,
253 ADV_OVERRUN_BSIZE,
254 /*nsegments*/1,
255 BUS_SPACE_MAXSIZE_32BIT,
256 /*flags*/0,
257 &overrun_dmat) != 0) {
258 adv_free(adv);
259 return (-1);
260 }
261 if (bus_dmamem_alloc(overrun_dmat,
262 (void **)&overrun_buf,
263 BUS_DMA_NOWAIT,
264 &overrun_dmamap) != 0) {
265 bus_dma_tag_destroy(overrun_dmat);
266 adv_free(adv);
267 return (-1);
268 }
269 /* And permanently map it in */
270 bus_dmamap_load(overrun_dmat, overrun_dmamap,
271 overrun_buf, ADV_OVERRUN_BSIZE,
272 adv_map, &overrun_physbase,
273 /*flags*/0);
274 }
275
276 eisa_reg_start(e_dev);
277 if (eisa_reg_iospace(e_dev, iospace)) {
278 adv_free(adv);
279 if (adv_b != NULL)
280 adv_free(adv_b);
281 return (-1);
282 }
283
284 if (eisa_reg_intr(e_dev, irq, adv_intr, (void *)adv, &cam_imask,
285 /*shared ==*/TRUE)) {
286 adv_free(adv);
287 if (adv_b != NULL)
288 adv_free(adv_b);
289 return (-1);
290 }
291 eisa_reg_end(e_dev);
292
293 /*
294 * Now that we know we own the resources we need, do the
295 * card initialization.
296 */
297
298 /*
299 * Stop the chip.
300 */
301 ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT);
302 ADV_OUTW(adv, ADV_CHIP_STATUS, 0);
303
304 adv->chip_version = EISA_REVISION_ID(e_dev->id)
305 + ADV_CHIP_MIN_VER_EISA - 1;
306
307 if (adv_init(adv) != 0) {
308 adv_free(adv);
309 if (adv_b != NULL)
310 adv_free(adv_b);
311 return(-1);
312 }
313
314 adv->max_dma_count = ADV_EISA_MAX_DMA_COUNT;
315 adv->max_dma_addr = ADV_EISA_MAX_DMA_ADDR;
316
317 if (adv_b != NULL) {
318 /*
319 * Stop the chip.
320 */
321 ADV_OUTB(adv_b, ADV_CHIP_CTRL, ADV_CC_HALT);
322 ADV_OUTW(adv_b, ADV_CHIP_STATUS, 0);
323
324 adv_b->chip_version = EISA_REVISION_ID(e_dev->id)
325 + ADV_CHIP_MIN_VER_EISA - 1;
326
327 if (adv_init(adv_b) != 0) {
328 adv_free(adv_b);
329 } else {
330 adv_b->max_dma_count = ADV_EISA_MAX_DMA_COUNT;
331 adv_b->max_dma_addr = ADV_EISA_MAX_DMA_ADDR;
332 }
333 }
334
335 /*
336 * Enable our interrupt handler.
337 */
338 if (eisa_enable_intr(e_dev, irq)) {
339 adv_free(adv);
340 if (adv_b != NULL)
341 adv_free(adv_b);
342 eisa_release_intr(e_dev, irq, adv_intr);
343 return (-1);
344 }
345
346 /* Attach sub-devices - always succeeds */
347 adv_attach(adv);
348 if (adv_b != NULL)
349 adv_attach(adv_b);
350
351 return 0;
352 }
353
354 #endif /* NEISA > 0 */
Cache object: 140b9b99236dedacaf759e432cdd8fa9
|