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.1 1998/09/15 07:32:54 gibbs 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 }
106
107 /* Attempt to find an adapter */
108 for (;port_index <= max_port_index; port_index++) {
109 config_data_t config_data;
110 u_int ioport;
111 int error;
112
113 ioport = bt_isa_ports[port_index].addr;
114
115 /*
116 * Ensure this port has not already been claimed already
117 * by a PCI or EISA adapter.
118 */
119 if (bt_check_probed_iop(ioport) != 0)
120 continue;
121
122 /* Allocate a softc for use during probing */
123 bt = bt_alloc(dev->id_unit, I386_BUS_SPACE_IO, ioport);
124
125 if (bt == NULL)
126 break;
127
128 /* We're going to attempt to probe it now, so mark it probed */
129 bt_mark_probed_bio(port_index);
130
131 /* See if there is really a card present */
132 if (bt_probe(bt) || bt_fetch_adapter_info(bt)) {
133 bt_free(bt);
134 continue;
135 }
136
137 /*
138 * Determine our IRQ, and DMA settings and
139 * export them to the configuration system.
140 */
141 error = bt_cmd(bt, BOP_INQUIRE_CONFIG, NULL, /*parmlen*/0,
142 (u_int8_t*)&config_data, sizeof(config_data),
143 DEFAULT_CMD_TIMEOUT);
144 if (error != 0) {
145 printf("bt_isa_probe: Could not determine IRQ or DMA "
146 "settings for adapter at 0x%x. Failing probe\n",
147 ioport);
148 bt_free(bt);
149 continue;
150 }
151
152 if (bt->model[0] == '5') {
153 /* DMA settings only make sense for ISA cards */
154 switch (config_data.dma_chan) {
155 case DMA_CHAN_5:
156 dev->id_drq = 5;
157 break;
158 case DMA_CHAN_6:
159 dev->id_drq = 6;
160 break;
161 case DMA_CHAN_7:
162 dev->id_drq = 7;
163 break;
164 default:
165 printf("bt_isa_probe: Invalid DMA setting "
166 "detected for adapter at 0x%x. "
167 "Failing probe\n", ioport);
168 }
169 } else {
170 /* VL DMA */
171 dev->id_drq = -1;
172 }
173 dev->id_iobase = bt_isa_ports[port_index].addr;
174 dev->id_irq = (config_data.irq << 9);
175 dev->id_intr = bt_isa_intr;
176 bt_unit++;
177 return (BT_NREGS);
178 }
179
180 return (0);
181}
182
183/*
184 * Attach all the sub-devices we can find
185 */
186static int
187bt_isa_attach(dev)
188 struct isa_device *dev;
189{
190 struct bt_softc *bt;
191 bus_dma_filter_t *filter;
192 void *filter_arg;
193 bus_addr_t lowaddr;
194
195 bt = bt_softcs[dev->id_unit];
196 if (dev->id_drq != -1)
197 isa_dmacascade(dev->id_drq);
198
199 /* Allocate our parent dmatag */
200 filter = NULL;
201 filter_arg = NULL;
202 lowaddr = BUS_SPACE_MAXADDR_24BIT;
203 if (bt->model[0] == '4') {
204 /*
205 * This is a VL adapter. Typically, VL devices have access
206 * to the full 32bit address space. On BT-445S adapters
207 * prior to revision E, there is a hardware bug that causes
208 * corruption of transfers to/from addresses in the range of
209 * the BIOS modulo 16MB. The only properly functioning
210 * BT-445S Host Adapters have firmware version 3.37.
211 * If we encounter one of these adapters and the BIOS is
212 * installed, install a filter function for our bus_dma_map
213 * that will catch these accesses and bounce them to a safe
214 * region of memory.
215 */
216 if (bt->bios_addr != 0
217 && strcmp(bt->model, "445S") == 0
218 && strcmp(bt->firmware_ver, "3.37") < 0) {
219 filter = btvlbouncefilter;
220 filter_arg = bt;
221 } else {
222 lowaddr = BUS_SPACE_MAXADDR_32BIT;
223 }
224 }
225
226 /* XXX Should be a child of the ISA or VL bus dma tag */
227 if (bus_dma_tag_create(/*parent*/NULL, /*alignemnt*/0, /*boundary*/0,
228 lowaddr, /*highaddr*/BUS_SPACE_MAXADDR,
229 filter, filter_arg,
230 /*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
231 /*nsegments*/BUS_SPACE_UNRESTRICTED,
232 /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
233 /*flags*/0, &bt->parent_dmat) != 0) {
234 bt_free(bt);
235 return (-1);
236 }
237
238 if (bt_init(bt)) {
239 bt_free(bt);
240 return (-1);
241 }
242
243 if (lowaddr != BUS_SPACE_MAXADDR_32BIT) {
244 /* DMA tag for our sense buffers */
245 if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/0,
246 /*boundary*/0,
247 /*lowaddr*/BUS_SPACE_MAXADDR,
248 /*highaddr*/BUS_SPACE_MAXADDR,
249 /*filter*/NULL, /*filterarg*/NULL,
250 bt->max_ccbs
251 * sizeof(struct scsi_sense_data),
252 /*nsegments*/1,
253 /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
254 /*flags*/0, &bt->sense_dmat) != 0) {
255 bt_free(bt);
256 return (-1);
257 }
258
259 bt->init_level++;
260
261 /* Allocation of sense buffers */
262 if (bus_dmamem_alloc(bt->sense_dmat,
263 (void **)&bt->sense_buffers,
264 BUS_DMA_NOWAIT, &bt->sense_dmamap) != 0) {
265 bt_free(bt);
266 return (-1);
267 }
268
269 bt->init_level++;
270
271 /* And permanently map them */
272 bus_dmamap_load(bt->sense_dmat, bt->sense_dmamap,
273 bt->sense_buffers,
274 bt->max_ccbs * sizeof(*bt->sense_buffers),
275 btmapsensebuffers, bt, /*flags*/0);
276
277 bt->init_level++;
278 }
279
280 return (bt_attach(bt));
281}
282
283/*
284 * Handle an ISA interrupt.
285 * XXX should go away as soon as ISA interrupt handlers
286 * take a (void *) arg.
287 */
288static void
289bt_isa_intr(void *unit)
290{
291 struct bt_softc* arg = bt_softcs[(int)unit];
292 bt_intr((void *)arg);
293}
294
295#define BIOS_MAP_SIZE (16 * 1024)
296
297static int
298btvlbouncefilter(void *arg, bus_addr_t addr)
299{
300 struct bt_softc *bt;
301
302 bt = (struct bt_softc *)arg;
303
304 addr &= BUS_SPACE_MAXADDR_24BIT;
305
306 if (addr == 0
307 || (addr >= bt->bios_addr
308 && addr < (bt->bios_addr + BIOS_MAP_SIZE)))
309 return (1);
310 return (0);
311}
312
313static void
314btmapsensebuffers(void *arg, bus_dma_segment_t *segs, int nseg, int error)
315{
316 struct bt_softc* bt;
317
318 bt = (struct bt_softc*)arg;
319 bt->sense_buffers_physbase = segs->ds_addr;
320}
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.1 1998/09/15 07:32:54 gibbs 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 }
106
107 /* Attempt to find an adapter */
108 for (;port_index <= max_port_index; port_index++) {
109 config_data_t config_data;
110 u_int ioport;
111 int error;
112
113 ioport = bt_isa_ports[port_index].addr;
114
115 /*
116 * Ensure this port has not already been claimed already
117 * by a PCI or EISA adapter.
118 */
119 if (bt_check_probed_iop(ioport) != 0)
120 continue;
121
122 /* Allocate a softc for use during probing */
123 bt = bt_alloc(dev->id_unit, I386_BUS_SPACE_IO, ioport);
124
125 if (bt == NULL)
126 break;
127
128 /* We're going to attempt to probe it now, so mark it probed */
129 bt_mark_probed_bio(port_index);
130
131 /* See if there is really a card present */
132 if (bt_probe(bt) || bt_fetch_adapter_info(bt)) {
133 bt_free(bt);
134 continue;
135 }
136
137 /*
138 * Determine our IRQ, and DMA settings and
139 * export them to the configuration system.
140 */
141 error = bt_cmd(bt, BOP_INQUIRE_CONFIG, NULL, /*parmlen*/0,
142 (u_int8_t*)&config_data, sizeof(config_data),
143 DEFAULT_CMD_TIMEOUT);
144 if (error != 0) {
145 printf("bt_isa_probe: Could not determine IRQ or DMA "
146 "settings for adapter at 0x%x. Failing probe\n",
147 ioport);
148 bt_free(bt);
149 continue;
150 }
151
152 if (bt->model[0] == '5') {
153 /* DMA settings only make sense for ISA cards */
154 switch (config_data.dma_chan) {
155 case DMA_CHAN_5:
156 dev->id_drq = 5;
157 break;
158 case DMA_CHAN_6:
159 dev->id_drq = 6;
160 break;
161 case DMA_CHAN_7:
162 dev->id_drq = 7;
163 break;
164 default:
165 printf("bt_isa_probe: Invalid DMA setting "
166 "detected for adapter at 0x%x. "
167 "Failing probe\n", ioport);
168 }
169 } else {
170 /* VL DMA */
171 dev->id_drq = -1;
172 }
173 dev->id_iobase = bt_isa_ports[port_index].addr;
174 dev->id_irq = (config_data.irq << 9);
175 dev->id_intr = bt_isa_intr;
176 bt_unit++;
177 return (BT_NREGS);
178 }
179
180 return (0);
181}
182
183/*
184 * Attach all the sub-devices we can find
185 */
186static int
187bt_isa_attach(dev)
188 struct isa_device *dev;
189{
190 struct bt_softc *bt;
191 bus_dma_filter_t *filter;
192 void *filter_arg;
193 bus_addr_t lowaddr;
194
195 bt = bt_softcs[dev->id_unit];
196 if (dev->id_drq != -1)
197 isa_dmacascade(dev->id_drq);
198
199 /* Allocate our parent dmatag */
200 filter = NULL;
201 filter_arg = NULL;
202 lowaddr = BUS_SPACE_MAXADDR_24BIT;
203 if (bt->model[0] == '4') {
204 /*
205 * This is a VL adapter. Typically, VL devices have access
206 * to the full 32bit address space. On BT-445S adapters
207 * prior to revision E, there is a hardware bug that causes
208 * corruption of transfers to/from addresses in the range of
209 * the BIOS modulo 16MB. The only properly functioning
210 * BT-445S Host Adapters have firmware version 3.37.
211 * If we encounter one of these adapters and the BIOS is
212 * installed, install a filter function for our bus_dma_map
213 * that will catch these accesses and bounce them to a safe
214 * region of memory.
215 */
216 if (bt->bios_addr != 0
217 && strcmp(bt->model, "445S") == 0
218 && strcmp(bt->firmware_ver, "3.37") < 0) {
219 filter = btvlbouncefilter;
220 filter_arg = bt;
221 } else {
222 lowaddr = BUS_SPACE_MAXADDR_32BIT;
223 }
224 }
225
226 /* XXX Should be a child of the ISA or VL bus dma tag */
227 if (bus_dma_tag_create(/*parent*/NULL, /*alignemnt*/0, /*boundary*/0,
228 lowaddr, /*highaddr*/BUS_SPACE_MAXADDR,
229 filter, filter_arg,
230 /*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
231 /*nsegments*/BUS_SPACE_UNRESTRICTED,
232 /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
233 /*flags*/0, &bt->parent_dmat) != 0) {
234 bt_free(bt);
235 return (-1);
236 }
237
238 if (bt_init(bt)) {
239 bt_free(bt);
240 return (-1);
241 }
242
243 if (lowaddr != BUS_SPACE_MAXADDR_32BIT) {
244 /* DMA tag for our sense buffers */
245 if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/0,
246 /*boundary*/0,
247 /*lowaddr*/BUS_SPACE_MAXADDR,
248 /*highaddr*/BUS_SPACE_MAXADDR,
249 /*filter*/NULL, /*filterarg*/NULL,
250 bt->max_ccbs
251 * sizeof(struct scsi_sense_data),
252 /*nsegments*/1,
253 /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
254 /*flags*/0, &bt->sense_dmat) != 0) {
255 bt_free(bt);
256 return (-1);
257 }
258
259 bt->init_level++;
260
261 /* Allocation of sense buffers */
262 if (bus_dmamem_alloc(bt->sense_dmat,
263 (void **)&bt->sense_buffers,
264 BUS_DMA_NOWAIT, &bt->sense_dmamap) != 0) {
265 bt_free(bt);
266 return (-1);
267 }
268
269 bt->init_level++;
270
271 /* And permanently map them */
272 bus_dmamap_load(bt->sense_dmat, bt->sense_dmamap,
273 bt->sense_buffers,
274 bt->max_ccbs * sizeof(*bt->sense_buffers),
275 btmapsensebuffers, bt, /*flags*/0);
276
277 bt->init_level++;
278 }
279
280 return (bt_attach(bt));
281}
282
283/*
284 * Handle an ISA interrupt.
285 * XXX should go away as soon as ISA interrupt handlers
286 * take a (void *) arg.
287 */
288static void
289bt_isa_intr(void *unit)
290{
291 struct bt_softc* arg = bt_softcs[(int)unit];
292 bt_intr((void *)arg);
293}
294
295#define BIOS_MAP_SIZE (16 * 1024)
296
297static int
298btvlbouncefilter(void *arg, bus_addr_t addr)
299{
300 struct bt_softc *bt;
301
302 bt = (struct bt_softc *)arg;
303
304 addr &= BUS_SPACE_MAXADDR_24BIT;
305
306 if (addr == 0
307 || (addr >= bt->bios_addr
308 && addr < (bt->bios_addr + BIOS_MAP_SIZE)))
309 return (1);
310 return (0);
311}
312
313static void
314btmapsensebuffers(void *arg, bus_dma_segment_t *segs, int nseg, int error)
315{
316 struct bt_softc* bt;
317
318 bt = (struct bt_softc*)arg;
319 bt->sense_buffers_physbase = segs->ds_addr;
320}