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