1/*
2 * Product specific probe and attach routines for:
3 * Buslogic BT-54X and BT-445 cards
4 *
5 * Copyright (c) 1998 Justin T. Gibbs
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions, and the following disclaimer,
13 * without modification, immediately at the beginning of the file.
14 * 2. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $Id: bt_isa.c,v 1.2 1998/09/24 10:43:42 bde Exp $
30 */
31
32#include <sys/param.h>
33#include <sys/systm.h>
34
35#include <machine/bus_pio.h>
36#include <machine/bus.h>
37
38#include <i386/isa/isa_device.h>
39#include <dev/buslogic/btreg.h>
40
41#include <cam/scsi/scsi_all.h>
42
43static int bt_isa_probe __P((struct isa_device *dev));
44static int bt_isa_attach __P((struct isa_device *dev));
45static void bt_isa_intr __P((void *unit));
46
47static bus_dma_filter_t btvlbouncefilter;
48static bus_dmamap_callback_t btmapsensebuffers;
49
50struct isa_driver btdriver =
51{
52 bt_isa_probe,
53 bt_isa_attach,
54 "bt"
55};
56
57/*
58 * Check if the device can be found at the port given
59 * and if so, set it up ready for further work
60 * as an argument, takes the isa_device structure from
61 * autoconf.c
62 */
63static int
64bt_isa_probe(dev)
65 struct isa_device *dev;
66{
67 /*
68 * find unit and check we have that many defined
69 */
70 struct bt_softc *bt;
71 int port_index;
72 int max_port_index;
73
74 /*
75 * We ignore the unit number assigned by config to allow
76 * consistant numbering between PCI/EISA/ISA devices.
77 * This is a total kludge until we have a configuration
78 * manager.
79 */
80 dev->id_unit = bt_unit;
81
82 bt = NULL;
83 port_index = 0;
84 max_port_index = BT_NUM_ISAPORTS - 1;
85 /*
86 * Bound our board search if the user has
87 * specified an exact port.
88 */
89 if (dev->id_iobase > 0) {
90 for (;port_index <= max_port_index; port_index++)
91 if (dev->id_iobase >= bt_isa_ports[port_index].addr)
92 break;
93 if ((port_index > max_port_index)
94 || (dev->id_iobase != bt_isa_ports[port_index].addr)) {
95 printf("
96bt_isa_probe: Invalid baseport of 0x%x specified.
97bt_isa_probe: Nearest valid baseport is 0x%x.
98bt_isa_probe: Failing probe.\n",
99 dev->id_iobase,
100 (port_index <= max_port_index)
101 ? bt_isa_ports[port_index].addr
102 : bt_isa_ports[max_port_index].addr);
103 return 0;
104 }
105 max_port_index = port_index;
106 }
107
108 /* Attempt to find an adapter */
109 for (;port_index <= max_port_index; port_index++) {
110 config_data_t config_data;
111 u_int ioport;
112 int error;
113
114 ioport = bt_isa_ports[port_index].addr;
115
116 /*
117 * Ensure this port has not already been claimed already
118 * by a PCI or EISA adapter.
119 */
120 if (bt_check_probed_iop(ioport) != 0)
121 continue;
122
123 /*
124 * Make sure that we do not conflict with another device's
125 * I/O address.
126 */
127 if (haveseen_isadev(dev, CC_IOADDR))
128 continue;
129
130 /* Allocate a softc for use during probing */
131 bt = bt_alloc(dev->id_unit, I386_BUS_SPACE_IO, ioport);
132
133 if (bt == NULL)
134 break;
135
136 /* We're going to attempt to probe it now, so mark it probed */
137 bt_mark_probed_bio(port_index);
138
139 /* See if there is really a card present */
140 if (bt_probe(bt) || bt_fetch_adapter_info(bt)) {
141 bt_free(bt);
142 continue;
143 }
144
145 /*
146 * Determine our IRQ, and DMA settings and
147 * export them to the configuration system.
148 */
149 error = bt_cmd(bt, BOP_INQUIRE_CONFIG, NULL, /*parmlen*/0,
150 (u_int8_t*)&config_data, sizeof(config_data),
151 DEFAULT_CMD_TIMEOUT);
152 if (error != 0) {
153 printf("bt_isa_probe: Could not determine IRQ or DMA "
154 "settings for adapter at 0x%x. Failing probe\n",
155 ioport);
156 bt_free(bt);
157 continue;
158 }
159
160 if (bt->model[0] == '5') {
161 /* DMA settings only make sense for ISA cards */
162 switch (config_data.dma_chan) {
163 case DMA_CHAN_5:
164 dev->id_drq = 5;
165 break;
166 case DMA_CHAN_6:
167 dev->id_drq = 6;
168 break;
169 case DMA_CHAN_7:
170 dev->id_drq = 7;
171 break;
172 default:
173 printf("bt_isa_probe: Invalid DMA setting "
174 "detected for adapter at 0x%x. "
175 "Failing probe\n", ioport);
176 }
177 } else {
178 /* VL DMA */
179 dev->id_drq = -1;
180 }
181 dev->id_iobase = bt_isa_ports[port_index].addr;
182 dev->id_irq = (config_data.irq << 9);
183 dev->id_intr = bt_isa_intr;
184
185 /*
186 * OK, check to make sure that we're not stepping on
187 * someone else's IRQ or DRQ
188 */
189 if (haveseen_isadev(dev, CC_DRQ)) {
190 printf("bt_isa_probe: Bt card at I/O 0x%x's drq %d "
191 "conflicts, ignoring card.\n", dev->id_iobase,
192 dev->id_drq);
193 bt_free(bt);
194 return 0;
195 }
196 if (haveseen_isadev(dev, CC_IRQ)) {
197 printf("bt_isa_probe: Bt card at I/O 0x%x's irq %d "
198 "conflicts, ignoring card.\n", dev->id_iobase,
199 config_data.irq + 9);
200 bt_free(bt);
201 return 0;
202 }
203 bt_unit++;
204 return (BT_NREGS);
205 }
206
207 return (0);
208}
209
210/*
211 * Attach all the sub-devices we can find
212 */
213static int
214bt_isa_attach(dev)
215 struct isa_device *dev;
216{
217 struct bt_softc *bt;
218 bus_dma_filter_t *filter;
219 void *filter_arg;
220 bus_addr_t lowaddr;
221
222 bt = bt_softcs[dev->id_unit];
223 if (dev->id_drq != -1)
224 isa_dmacascade(dev->id_drq);
225
226 /* Allocate our parent dmatag */
227 filter = NULL;
228 filter_arg = NULL;
229 lowaddr = BUS_SPACE_MAXADDR_24BIT;
230 if (bt->model[0] == '4') {
231 /*
232 * This is a VL adapter. Typically, VL devices have access
233 * to the full 32bit address space. On BT-445S adapters
234 * prior to revision E, there is a hardware bug that causes
235 * corruption of transfers to/from addresses in the range of
236 * the BIOS modulo 16MB. The only properly functioning
237 * BT-445S Host Adapters have firmware version 3.37.
238 * If we encounter one of these adapters and the BIOS is
239 * installed, install a filter function for our bus_dma_map
240 * that will catch these accesses and bounce them to a safe
241 * region of memory.
242 */
243 if (bt->bios_addr != 0
244 && strcmp(bt->model, "445S") == 0
245 && strcmp(bt->firmware_ver, "3.37") < 0) {
246 filter = btvlbouncefilter;
247 filter_arg = bt;
248 } else {
249 lowaddr = BUS_SPACE_MAXADDR_32BIT;
250 }
251 }
252
253 /* XXX Should be a child of the ISA or VL bus dma tag */
254 if (bus_dma_tag_create(/*parent*/NULL, /*alignemnt*/0, /*boundary*/0,
255 lowaddr, /*highaddr*/BUS_SPACE_MAXADDR,
256 filter, filter_arg,
257 /*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
258 /*nsegments*/BUS_SPACE_UNRESTRICTED,
259 /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
260 /*flags*/0, &bt->parent_dmat) != 0) {
261 bt_free(bt);
262 return (-1);
263 }
264
265 if (bt_init(bt)) {
266 bt_free(bt);
267 return (-1);
268 }
269
270 if (lowaddr != BUS_SPACE_MAXADDR_32BIT) {
271 /* DMA tag for our sense buffers */
272 if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/0,
273 /*boundary*/0,
274 /*lowaddr*/BUS_SPACE_MAXADDR,
275 /*highaddr*/BUS_SPACE_MAXADDR,
276 /*filter*/NULL, /*filterarg*/NULL,
277 bt->max_ccbs
278 * sizeof(struct scsi_sense_data),
279 /*nsegments*/1,
280 /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
281 /*flags*/0, &bt->sense_dmat) != 0) {
282 bt_free(bt);
283 return (-1);
284 }
285
286 bt->init_level++;
287
288 /* Allocation of sense buffers */
289 if (bus_dmamem_alloc(bt->sense_dmat,
290 (void **)&bt->sense_buffers,
291 BUS_DMA_NOWAIT, &bt->sense_dmamap) != 0) {
292 bt_free(bt);
293 return (-1);
294 }
295
296 bt->init_level++;
297
298 /* And permanently map them */
299 bus_dmamap_load(bt->sense_dmat, bt->sense_dmamap,
300 bt->sense_buffers,
301 bt->max_ccbs * sizeof(*bt->sense_buffers),
302 btmapsensebuffers, bt, /*flags*/0);
303
304 bt->init_level++;
305 }
306
307 return (bt_attach(bt));
308}
309
310/*
311 * Handle an ISA interrupt.
312 * XXX should go away as soon as ISA interrupt handlers
313 * take a (void *) arg.
314 */
315static void
316bt_isa_intr(void *unit)
317{
318 struct bt_softc* arg = bt_softcs[(int)unit];
319 bt_intr((void *)arg);
320}
321
322#define BIOS_MAP_SIZE (16 * 1024)
323
324static int
325btvlbouncefilter(void *arg, bus_addr_t addr)
326{
327 struct bt_softc *bt;
328
329 bt = (struct bt_softc *)arg;
330
331 addr &= BUS_SPACE_MAXADDR_24BIT;
332
333 if (addr == 0
334 || (addr >= bt->bios_addr
335 && addr < (bt->bios_addr + BIOS_MAP_SIZE)))
336 return (1);
337 return (0);
338}
339
340static void
341btmapsensebuffers(void *arg, bus_dma_segment_t *segs, int nseg, int error)
342{
343 struct bt_softc* bt;
344
345 bt = (struct bt_softc*)arg;
346 bt->sense_buffers_physbase = segs->ds_addr;
347}
2 * Product specific probe and attach routines for:
3 * Buslogic BT-54X and BT-445 cards
4 *
5 * Copyright (c) 1998 Justin T. Gibbs
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions, and the following disclaimer,
13 * without modification, immediately at the beginning of the file.
14 * 2. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $Id: bt_isa.c,v 1.2 1998/09/24 10:43:42 bde Exp $
30 */
31
32#include <sys/param.h>
33#include <sys/systm.h>
34
35#include <machine/bus_pio.h>
36#include <machine/bus.h>
37
38#include <i386/isa/isa_device.h>
39#include <dev/buslogic/btreg.h>
40
41#include <cam/scsi/scsi_all.h>
42
43static int bt_isa_probe __P((struct isa_device *dev));
44static int bt_isa_attach __P((struct isa_device *dev));
45static void bt_isa_intr __P((void *unit));
46
47static bus_dma_filter_t btvlbouncefilter;
48static bus_dmamap_callback_t btmapsensebuffers;
49
50struct isa_driver btdriver =
51{
52 bt_isa_probe,
53 bt_isa_attach,
54 "bt"
55};
56
57/*
58 * Check if the device can be found at the port given
59 * and if so, set it up ready for further work
60 * as an argument, takes the isa_device structure from
61 * autoconf.c
62 */
63static int
64bt_isa_probe(dev)
65 struct isa_device *dev;
66{
67 /*
68 * find unit and check we have that many defined
69 */
70 struct bt_softc *bt;
71 int port_index;
72 int max_port_index;
73
74 /*
75 * We ignore the unit number assigned by config to allow
76 * consistant numbering between PCI/EISA/ISA devices.
77 * This is a total kludge until we have a configuration
78 * manager.
79 */
80 dev->id_unit = bt_unit;
81
82 bt = NULL;
83 port_index = 0;
84 max_port_index = BT_NUM_ISAPORTS - 1;
85 /*
86 * Bound our board search if the user has
87 * specified an exact port.
88 */
89 if (dev->id_iobase > 0) {
90 for (;port_index <= max_port_index; port_index++)
91 if (dev->id_iobase >= bt_isa_ports[port_index].addr)
92 break;
93 if ((port_index > max_port_index)
94 || (dev->id_iobase != bt_isa_ports[port_index].addr)) {
95 printf("
96bt_isa_probe: Invalid baseport of 0x%x specified.
97bt_isa_probe: Nearest valid baseport is 0x%x.
98bt_isa_probe: Failing probe.\n",
99 dev->id_iobase,
100 (port_index <= max_port_index)
101 ? bt_isa_ports[port_index].addr
102 : bt_isa_ports[max_port_index].addr);
103 return 0;
104 }
105 max_port_index = port_index;
106 }
107
108 /* Attempt to find an adapter */
109 for (;port_index <= max_port_index; port_index++) {
110 config_data_t config_data;
111 u_int ioport;
112 int error;
113
114 ioport = bt_isa_ports[port_index].addr;
115
116 /*
117 * Ensure this port has not already been claimed already
118 * by a PCI or EISA adapter.
119 */
120 if (bt_check_probed_iop(ioport) != 0)
121 continue;
122
123 /*
124 * Make sure that we do not conflict with another device's
125 * I/O address.
126 */
127 if (haveseen_isadev(dev, CC_IOADDR))
128 continue;
129
130 /* Allocate a softc for use during probing */
131 bt = bt_alloc(dev->id_unit, I386_BUS_SPACE_IO, ioport);
132
133 if (bt == NULL)
134 break;
135
136 /* We're going to attempt to probe it now, so mark it probed */
137 bt_mark_probed_bio(port_index);
138
139 /* See if there is really a card present */
140 if (bt_probe(bt) || bt_fetch_adapter_info(bt)) {
141 bt_free(bt);
142 continue;
143 }
144
145 /*
146 * Determine our IRQ, and DMA settings and
147 * export them to the configuration system.
148 */
149 error = bt_cmd(bt, BOP_INQUIRE_CONFIG, NULL, /*parmlen*/0,
150 (u_int8_t*)&config_data, sizeof(config_data),
151 DEFAULT_CMD_TIMEOUT);
152 if (error != 0) {
153 printf("bt_isa_probe: Could not determine IRQ or DMA "
154 "settings for adapter at 0x%x. Failing probe\n",
155 ioport);
156 bt_free(bt);
157 continue;
158 }
159
160 if (bt->model[0] == '5') {
161 /* DMA settings only make sense for ISA cards */
162 switch (config_data.dma_chan) {
163 case DMA_CHAN_5:
164 dev->id_drq = 5;
165 break;
166 case DMA_CHAN_6:
167 dev->id_drq = 6;
168 break;
169 case DMA_CHAN_7:
170 dev->id_drq = 7;
171 break;
172 default:
173 printf("bt_isa_probe: Invalid DMA setting "
174 "detected for adapter at 0x%x. "
175 "Failing probe\n", ioport);
176 }
177 } else {
178 /* VL DMA */
179 dev->id_drq = -1;
180 }
181 dev->id_iobase = bt_isa_ports[port_index].addr;
182 dev->id_irq = (config_data.irq << 9);
183 dev->id_intr = bt_isa_intr;
184
185 /*
186 * OK, check to make sure that we're not stepping on
187 * someone else's IRQ or DRQ
188 */
189 if (haveseen_isadev(dev, CC_DRQ)) {
190 printf("bt_isa_probe: Bt card at I/O 0x%x's drq %d "
191 "conflicts, ignoring card.\n", dev->id_iobase,
192 dev->id_drq);
193 bt_free(bt);
194 return 0;
195 }
196 if (haveseen_isadev(dev, CC_IRQ)) {
197 printf("bt_isa_probe: Bt card at I/O 0x%x's irq %d "
198 "conflicts, ignoring card.\n", dev->id_iobase,
199 config_data.irq + 9);
200 bt_free(bt);
201 return 0;
202 }
203 bt_unit++;
204 return (BT_NREGS);
205 }
206
207 return (0);
208}
209
210/*
211 * Attach all the sub-devices we can find
212 */
213static int
214bt_isa_attach(dev)
215 struct isa_device *dev;
216{
217 struct bt_softc *bt;
218 bus_dma_filter_t *filter;
219 void *filter_arg;
220 bus_addr_t lowaddr;
221
222 bt = bt_softcs[dev->id_unit];
223 if (dev->id_drq != -1)
224 isa_dmacascade(dev->id_drq);
225
226 /* Allocate our parent dmatag */
227 filter = NULL;
228 filter_arg = NULL;
229 lowaddr = BUS_SPACE_MAXADDR_24BIT;
230 if (bt->model[0] == '4') {
231 /*
232 * This is a VL adapter. Typically, VL devices have access
233 * to the full 32bit address space. On BT-445S adapters
234 * prior to revision E, there is a hardware bug that causes
235 * corruption of transfers to/from addresses in the range of
236 * the BIOS modulo 16MB. The only properly functioning
237 * BT-445S Host Adapters have firmware version 3.37.
238 * If we encounter one of these adapters and the BIOS is
239 * installed, install a filter function for our bus_dma_map
240 * that will catch these accesses and bounce them to a safe
241 * region of memory.
242 */
243 if (bt->bios_addr != 0
244 && strcmp(bt->model, "445S") == 0
245 && strcmp(bt->firmware_ver, "3.37") < 0) {
246 filter = btvlbouncefilter;
247 filter_arg = bt;
248 } else {
249 lowaddr = BUS_SPACE_MAXADDR_32BIT;
250 }
251 }
252
253 /* XXX Should be a child of the ISA or VL bus dma tag */
254 if (bus_dma_tag_create(/*parent*/NULL, /*alignemnt*/0, /*boundary*/0,
255 lowaddr, /*highaddr*/BUS_SPACE_MAXADDR,
256 filter, filter_arg,
257 /*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
258 /*nsegments*/BUS_SPACE_UNRESTRICTED,
259 /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
260 /*flags*/0, &bt->parent_dmat) != 0) {
261 bt_free(bt);
262 return (-1);
263 }
264
265 if (bt_init(bt)) {
266 bt_free(bt);
267 return (-1);
268 }
269
270 if (lowaddr != BUS_SPACE_MAXADDR_32BIT) {
271 /* DMA tag for our sense buffers */
272 if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/0,
273 /*boundary*/0,
274 /*lowaddr*/BUS_SPACE_MAXADDR,
275 /*highaddr*/BUS_SPACE_MAXADDR,
276 /*filter*/NULL, /*filterarg*/NULL,
277 bt->max_ccbs
278 * sizeof(struct scsi_sense_data),
279 /*nsegments*/1,
280 /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
281 /*flags*/0, &bt->sense_dmat) != 0) {
282 bt_free(bt);
283 return (-1);
284 }
285
286 bt->init_level++;
287
288 /* Allocation of sense buffers */
289 if (bus_dmamem_alloc(bt->sense_dmat,
290 (void **)&bt->sense_buffers,
291 BUS_DMA_NOWAIT, &bt->sense_dmamap) != 0) {
292 bt_free(bt);
293 return (-1);
294 }
295
296 bt->init_level++;
297
298 /* And permanently map them */
299 bus_dmamap_load(bt->sense_dmat, bt->sense_dmamap,
300 bt->sense_buffers,
301 bt->max_ccbs * sizeof(*bt->sense_buffers),
302 btmapsensebuffers, bt, /*flags*/0);
303
304 bt->init_level++;
305 }
306
307 return (bt_attach(bt));
308}
309
310/*
311 * Handle an ISA interrupt.
312 * XXX should go away as soon as ISA interrupt handlers
313 * take a (void *) arg.
314 */
315static void
316bt_isa_intr(void *unit)
317{
318 struct bt_softc* arg = bt_softcs[(int)unit];
319 bt_intr((void *)arg);
320}
321
322#define BIOS_MAP_SIZE (16 * 1024)
323
324static int
325btvlbouncefilter(void *arg, bus_addr_t addr)
326{
327 struct bt_softc *bt;
328
329 bt = (struct bt_softc *)arg;
330
331 addr &= BUS_SPACE_MAXADDR_24BIT;
332
333 if (addr == 0
334 || (addr >= bt->bios_addr
335 && addr < (bt->bios_addr + BIOS_MAP_SIZE)))
336 return (1);
337 return (0);
338}
339
340static void
341btmapsensebuffers(void *arg, bus_dma_segment_t *segs, int nseg, int error)
342{
343 struct bt_softc* bt;
344
345 bt = (struct bt_softc*)arg;
346 bt->sense_buffers_physbase = segs->ds_addr;
347}