FreeBSD/Linux Kernel Cross Reference
sys/i386/isa/bt_isa.c
1 /*
2 * Product specific probe and attach routines for:
3 * Buslogic BT-54X and BT-445 cards
4 *
5 * Copyright (c) 1998, 1999 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 * $FreeBSD$
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
43 static int bt_isa_probe __P((struct isa_device *dev));
44 static int bt_isa_attach __P((struct isa_device *dev));
45 static void bt_isa_intr __P((void *unit));
46
47 static bus_dma_filter_t btvlbouncefilter;
48 static bus_dmamap_callback_t btmapsensebuffers;
49
50 struct 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 */
63 static int
64 bt_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 bt_find_probe_range(dev->id_iobase, &port_index, &max_port_index);
90
91 if (port_index < 0)
92 return 0;
93
94 /* Attempt to find an adapter */
95 for (;port_index <= max_port_index; port_index++) {
96 struct bt_probe_info info;
97 u_int ioport;
98
99 ioport = bt_iop_from_bio(port_index);
100
101 /*
102 * Ensure this port has not already been claimed already
103 * by a PCI, EISA or ISA adapter.
104 */
105 if (bt_check_probed_iop(ioport) != 0)
106 continue;
107 dev->id_iobase = ioport;
108 if (haveseen_isadev(dev, CC_IOADDR | CC_QUIET))
109 continue;
110
111 /* Allocate a softc for use during probing */
112 bt = bt_alloc(dev->id_unit, I386_BUS_SPACE_IO, ioport);
113
114 if (bt == NULL)
115 break;
116
117 /* We're going to attempt to probe it now, so mark it probed */
118 bt_mark_probed_bio(port_index);
119
120 if (bt_port_probe(bt, &info) != 0) {
121 if (bootverbose)
122 printf("bt_isa_probe: Probe failed for card at 0x%x\n", ioport);
123 bt_free(bt);
124 continue;
125 }
126
127 dev->id_drq = info.drq;
128 dev->id_irq = 0x1 << info.irq;
129 dev->id_intr = bt_isa_intr;
130
131 bt_unit++;
132 return (BT_NREGS);
133 }
134
135 return (0);
136 }
137
138 /*
139 * Attach all the sub-devices we can find
140 */
141 static int
142 bt_isa_attach(dev)
143 struct isa_device *dev;
144 {
145 struct bt_softc *bt;
146 bus_dma_filter_t *filter;
147 void *filter_arg;
148 bus_addr_t lowaddr;
149
150 bt = bt_softcs[dev->id_unit];
151 if (dev->id_drq != -1)
152 isa_dmacascade(dev->id_drq);
153
154 /* Allocate our parent dmatag */
155 filter = NULL;
156 filter_arg = NULL;
157 lowaddr = BUS_SPACE_MAXADDR_24BIT;
158 if (bt->model[0] == '4') {
159 /*
160 * This is a VL adapter. Typically, VL devices have access
161 * to the full 32bit address space. On BT-445S adapters
162 * prior to revision E, there is a hardware bug that causes
163 * corruption of transfers to/from addresses in the range of
164 * the BIOS modulo 16MB. The only properly functioning
165 * BT-445S Host Adapters have firmware version 3.37.
166 * If we encounter one of these adapters and the BIOS is
167 * installed, install a filter function for our bus_dma_map
168 * that will catch these accesses and bounce them to a safe
169 * region of memory.
170 */
171 if (bt->bios_addr != 0
172 && strcmp(bt->model, "445S") == 0
173 && strcmp(bt->firmware_ver, "3.37") < 0) {
174 filter = btvlbouncefilter;
175 filter_arg = bt;
176 } else {
177 lowaddr = BUS_SPACE_MAXADDR_32BIT;
178 }
179 }
180
181 /* XXX Should be a child of the ISA or VL bus dma tag */
182 if (bus_dma_tag_create(/*parent*/NULL, /*alignemnt*/1, /*boundary*/0,
183 lowaddr, /*highaddr*/BUS_SPACE_MAXADDR,
184 filter, filter_arg,
185 /*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
186 /*nsegments*/BUS_SPACE_UNRESTRICTED,
187 /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
188 /*flags*/0, &bt->parent_dmat) != 0) {
189 bt_free(bt);
190 return (-1);
191 }
192
193 if (bt_init(bt)) {
194 bt_free(bt);
195 return (-1);
196 }
197
198 if (lowaddr != BUS_SPACE_MAXADDR_32BIT) {
199 /* DMA tag for our sense buffers */
200 if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/1,
201 /*boundary*/0,
202 /*lowaddr*/BUS_SPACE_MAXADDR,
203 /*highaddr*/BUS_SPACE_MAXADDR,
204 /*filter*/NULL, /*filterarg*/NULL,
205 bt->max_ccbs
206 * sizeof(struct scsi_sense_data),
207 /*nsegments*/1,
208 /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
209 /*flags*/0, &bt->sense_dmat) != 0) {
210 bt_free(bt);
211 return (-1);
212 }
213
214 bt->init_level++;
215
216 /* Allocation of sense buffers */
217 if (bus_dmamem_alloc(bt->sense_dmat,
218 (void **)&bt->sense_buffers,
219 BUS_DMA_NOWAIT, &bt->sense_dmamap) != 0) {
220 bt_free(bt);
221 return (-1);
222 }
223
224 bt->init_level++;
225
226 /* And permanently map them */
227 bus_dmamap_load(bt->sense_dmat, bt->sense_dmamap,
228 bt->sense_buffers,
229 bt->max_ccbs * sizeof(*bt->sense_buffers),
230 btmapsensebuffers, bt, /*flags*/0);
231
232 bt->init_level++;
233 }
234
235 return (bt_attach(bt));
236 }
237
238 /*
239 * Handle an ISA interrupt.
240 * XXX should go away as soon as ISA interrupt handlers
241 * take a (void *) arg.
242 */
243 static void
244 bt_isa_intr(void *unit)
245 {
246 struct bt_softc* arg = bt_softcs[(int)unit];
247 bt_intr((void *)arg);
248 }
249
250 #define BIOS_MAP_SIZE (16 * 1024)
251
252 static int
253 btvlbouncefilter(void *arg, bus_addr_t addr)
254 {
255 struct bt_softc *bt;
256
257 bt = (struct bt_softc *)arg;
258
259 addr &= BUS_SPACE_MAXADDR_24BIT;
260
261 if (addr == 0
262 || (addr >= bt->bios_addr
263 && addr < (bt->bios_addr + BIOS_MAP_SIZE)))
264 return (1);
265 return (0);
266 }
267
268 static void
269 btmapsensebuffers(void *arg, bus_dma_segment_t *segs, int nseg, int error)
270 {
271 struct bt_softc* bt;
272
273 bt = (struct bt_softc*)arg;
274 bt->sense_buffers_physbase = segs->ds_addr;
275 }
Cache object: 9644e8887eb6b3a6ebf64cb5f4e9eb03
|