FreeBSD/Linux Kernel Cross Reference
sys/i386/isa/bs/bsif.c
1 /* $NecBSD: bsif.c,v 1.6 1997/10/31 17:43:40 honda Exp $ */
2 /*
3 * Copyright (c) HONDA Naofumi, KATO Takenori, 1996. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer as
11 * the first lines of this file unmodified.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #if 0
31 /* WARNING: Any bug report must contain BS_REL_VERSION */
32 #define BS_REL_VERSION "NetBSD1.2/030" /* major jump */
33 #endif
34
35 #ifdef __NetBSD__
36 #include <i386/Cbus/dev/bs/bsif.h>
37 #endif /* __NetBSD__ */
38 #ifdef __FreeBSD__
39 #include "bs.h"
40 #include <i386/isa/bs/bsif.h>
41 #endif /* __FreeBSD__ */
42
43 /**************************************************
44 * DEVICE DECLARE
45 **************************************************/
46 #ifdef __NetBSD__
47 static void bs_scsi_minphys __P((struct buf *));
48
49 struct cfdriver bs_cd = {
50 NULL, "bs", DV_DULL
51 };
52
53 struct scsi_device bs_dev = {
54 NULL, /* Use default error handler */
55 NULL, /* have a queue, served by this */
56 NULL, /* have no async handler */
57 NULL, /* Use default 'done' routine */
58 };
59
60 struct scsi_adapter pc98texa55bs = {
61 bs_scsi_cmd,
62 bs_scsi_minphys,
63 bs_target_open,
64 0,
65 };
66 #endif /* __NetBSD__ */
67
68 #ifdef __FreeBSD__
69 static int bsprobe __P((struct isa_device *));
70 static int bsattach __P((struct isa_device *));
71 static int bsprint __P((void *, const char *));
72 static void bs_scsi_minphys __P((struct buf *));
73 static int bs_dmarangecheck __P((caddr_t, unsigned));
74
75 struct isa_driver bsdriver = {
76 bsprobe,
77 bsattach,
78 "bs"
79 };
80
81 struct scsi_device bs_dev = {
82 NULL, /* Use default error handler */
83 NULL, /* have a queue, served by this */
84 NULL, /* have no async handler */
85 NULL, /* Use default 'done' routine */
86 "bs",
87 0, {0, 0}
88 };
89
90 u_int32_t
91 bs_adapter_info(unit)
92 int unit;
93 {
94 return (1);
95 }
96
97 struct scsi_adapter pc98texa55bs = {
98 bs_scsi_cmd,
99 bs_scsi_minphys,
100 bs_target_open,
101 0,
102 bs_adapter_info,
103 "bs", {0, 0}
104 };
105
106 static u_short pc98_irq_ball[16] = {
107 IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
108 IRQ8, IRQ9, IRQ10, IRQ11, IRQ12, IRQ13, IRQ14, IRQ15
109 };
110
111 static struct bs_softc *bscdata[NBS];
112 #endif /* __FreeBSD__ */
113
114 /*****************************************************************
115 * OS <=> BS INTERFACE
116 *****************************************************************/
117 #ifdef __FreeBSD__
118 static int
119 bsprobe(dev)
120 struct isa_device *dev;
121 {
122 struct bs_softc *bsc;
123 int unit = dev->id_unit;
124 u_int irq, drq;
125 int i, rv = 0;
126
127 if (unit >= NBS) {
128 printf("bs%d: unit number too high\n", unit);
129 return rv;
130 }
131 /*
132 * Allocate a storage for us
133 */
134 if (bscdata[unit]) {
135 printf("bs%d: memory already allocated\n", unit);
136 return rv;
137 }
138 if (!(bsc = malloc(sizeof(struct bs_softc), M_TEMP, M_NOWAIT))) {
139 printf("bs%d cannot malloc!\n", unit);
140 return rv;
141 }
142 bzero(bsc, sizeof(struct bs_softc));
143 bscdata[unit] = bsc;
144 bsc->unit = unit;
145
146 bsc->sc_cfgflags = DVCFG_MINOR(dev->id_flags);
147 bsc->sc_hw = DVCFG_HW(&bshw_hwsel, DVCFG_MAJOR(dev->id_flags));
148 if (bsc->sc_hw == NULL)
149 return rv;
150
151 if ((bsc->sc_hw->hw_flags & BSHW_SMFIFO) &&
152 (dev->id_maddr != (caddr_t)MADDRUNK))
153 bsc->sm_offset = (u_long) dev->id_maddr;
154 else
155 bsc->sm_offset = (u_long) 0;
156
157 sprintf(bsc->sc_dvname, "bs%d", unit);
158
159 if (dev->id_iobase == 0)
160 {
161 printf("%s: iobase not specified. Assume default port(0x%x)\n",
162 bsc->sc_dvname, BSHW_DEFAULT_PORT);
163 dev->id_iobase = BSHW_DEFAULT_PORT;
164 }
165
166 bsc->sc_iobase = dev->id_iobase;
167 irq = IRQUNK;
168 drq = DRQUNK;
169 if (bshw_board_probe(bsc, &drq, &irq))
170 goto bad;
171
172 dev->id_irq = pc98_irq_ball[irq];
173 dev->id_drq = (short)drq;
174
175 /* initialize host queue and target info */
176 bs_hostque_init(bsc);
177 for (i = 0; i < NTARGETS; i++)
178 if (i != bsc->sc_hostid)
179 bs_init_target_info(bsc, i);
180
181 /* initialize ccb queue */
182 bs_init_ccbque(BS_MAX_CCB);
183
184 /* scsi bus reset and restart */
185 bsc->sc_hstate = BSC_BOOTUP;
186 bsc->sc_retry = RETRIES;
187 bsc->sc_wc = delaycount * 250; /* about 1 sec */
188 bs_reset_nexus(bsc);
189
190 return BSHW_IOSZ;
191 bad:
192 return rv;
193 }
194 #endif /* __FreeBSD__ */
195
196 #ifdef __FreeBSD__
197 static int
198 #else /* __NetBSD__ */
199 int
200 #endif /* __NetBSD__ */
201 bsprint(aux, name)
202 void *aux;
203 const char *name;
204 {
205
206 if (name != NULL)
207 printf("%s: scsibus ", name);
208 return UNCONF;
209 }
210
211 #ifdef __FreeBSD__
212 static int
213 bsattach(dev)
214 struct isa_device *dev;
215 {
216 int unit = dev->id_unit;
217 struct bs_softc *bsc = bscdata[unit];
218 struct scsibus_data *scbus;
219
220 bsc->sc_link.adapter_unit = unit;
221 bsc->sc_link.adapter_targ = bsc->sc_hostid;
222 bsc->sc_link.flags = SDEV_BOUNCE;
223 bsc->sc_link.opennings = XSMAX;
224 bsc->sc_link.adapter_softc = bsc;
225 bsc->sc_link.adapter = &pc98texa55bs;
226 bsc->sc_link.device = &bs_dev;
227
228 /*
229 * Prepare the scsibus_data area for the upperlevel
230 * scsi code.
231 */
232 scbus = scsi_alloc_bus();
233 if (!scbus)
234 return 0;
235 scbus->adapter_link = &bsc->sc_link;
236 /*
237 * ask the adapter what subunits are present
238 */
239 scsi_attachdevs(scbus);
240 bs_start_timeout(bsc);
241 return 1;
242 }
243 #endif /* __FreeBSD__ */
244
245 #ifdef __NetBSD__
246 int
247 bsintr(arg)
248 void *arg;
249 {
250
251 return bs_sequencer((struct bs_softc *)arg);
252 }
253 #endif /* __NetBSD__ */
254
255 #ifdef __FreeBSD__
256 void
257 bsintr(unit)
258 int unit;
259 {
260 (void)bs_sequencer(bscdata[unit]);
261 }
262 #endif /* __FreeBSD__ */
263
264 /*****************************************************************
265 * JULIAN SCSI <=> BS INTERFACE
266 *****************************************************************/
267 static void
268 bs_scsi_minphys(bp)
269 struct buf *bp;
270 {
271
272 if (bp->b_bcount > BSDMABUFSIZ)
273 bp->b_bcount = BSDMABUFSIZ;
274 minphys(bp);
275 }
276
277 XSBS_INT32T
278 bs_target_open(sc, cf)
279 struct scsi_link *sc;
280 struct cfdata *cf;
281 {
282 u_int target = sc->target;
283 struct bs_softc *bsc = (struct bs_softc *) (sc->adapter_softc);
284 struct targ_info *ti = bsc->sc_ti[target];
285 u_int flags;
286
287 if ((bsc->sc_openf & (1 << target)) == 0)
288 return ENODEV;
289
290 if ((flags = cf->cf_flags) == 0)
291 flags = BS_SCSI_DEFCFG;
292
293 bs_setup_ctrl(ti, (u_int)sc->quirks, flags);
294 return 0;
295 }
296
297 /*****************************************************************
298 * BS MEMORY ALLOCATION INTERFACE
299 *****************************************************************/
300 #ifdef __NetBSD__
301 void
302 bs_alloc_buf(ti)
303 struct targ_info *ti;
304 {
305 struct bs_softc *bsc = ti->ti_bsc;
306 caddr_t addr, physaddr;
307 bus_dma_segment_t seg;
308 int rseg, error;
309 u_int pages;
310 extern int cold;
311
312 /* XXX:
313 * strategy change!
314 * A) total memory >= 16M at boot: MAXBSIZE * 7 = 112k.
315 * B) others: 4K * 7 = 28 K.
316 */
317 if (get_sysinfo(SYSINFO_MEMLEVEL) == MEM_LEVEL1 && cold != 0)
318 pages = 4;
319 else
320 pages = 1;
321 ti->bounce_size = NBPG * pages;
322
323 addr = NULL;
324 error = bus_dmamem_alloc(bsc->sc_dmat, ti->bounce_size, NBPG, 0,
325 &seg, 1, &rseg, BUS_DMA_NOWAIT);
326 if (rseg == 1 && error == 0)
327 error = bus_dmamem_map(bsc->sc_dmat, &seg, rseg,
328 ti->bounce_size, &addr, BUS_DMA_NOWAIT);
329 if (rseg != 1 || error != 0)
330 {
331 ti->bounce_size = NBPG;
332 if ((addr = malloc(NBPG, M_DEVBUF, M_NOWAIT)) == NULL)
333 goto bad;
334 }
335
336 physaddr = (caddr_t) vtophys(addr);
337 if ((u_int) physaddr >= RAM_END)
338 {
339 /* XXX: mem from malloc only! */
340 free(addr, M_DEVBUF);
341 goto bad;
342 }
343
344 ti->bounce_addr = (u_int8_t *) addr;
345 ti->bounce_phys = (u_int8_t *) physaddr;
346 return;
347
348 bad:
349 bs_printf(ti, "bs_alloc_buf", "no phys bounce buffer");
350 printf("WARNING: this target is dislocated\n");
351 }
352 #endif /* __NetBSD__ */
353
354 #ifdef __FreeBSD__
355 static int bs_dmarangecheck(caddr_t va, unsigned length)
356 {
357 vm_offset_t phys, priorpage = 0, endva;
358
359 endva = (vm_offset_t)round_page(va+length);
360 for (; va < (caddr_t)endva; va += PAGE_SIZE) {
361 phys = trunc_page(pmap_extract(pmap_kernel(), (vm_offset_t)va));
362 if (phys == 0)
363 panic("bs_dmarangecheck: no physical page present");
364 if (phys >= RAM_END)
365 return 1;
366 if (priorpage) {
367 if (priorpage + PAGE_SIZE != phys)
368 return 1;
369 }
370 priorpage = phys;
371 }
372 return 0;
373 }
374
375 void
376 bs_alloc_buf(ti)
377 struct targ_info *ti;
378 {
379 caddr_t addr, physaddr;
380
381 #if BS_BOUNCE_SIZE != 0
382 ti->bounce_size = BS_BOUNCE_SIZE;
383 #else
384 ti->bounce_size = BSHW_NBPG;
385 #endif
386 /* Try malloc() first. It works better if it works. */
387 addr = malloc(ti->bounce_size, M_DEVBUF, M_NOWAIT);
388 if (addr != NULL) {
389 if (bs_dmarangecheck(addr, ti->bounce_size) == 0) {
390 physaddr = (caddr_t) vtophys(addr);
391 ti->bounce_addr = (u_int8_t *) addr;
392 ti->bounce_phys = (u_int8_t *) physaddr;
393 return;
394 }
395 free(buf, M_DEVBUF);
396 }
397 addr = contigmalloc(ti->bounce_size, M_DEVBUF, M_NOWAIT,
398 0ul, RAM_END, 1ul, 0x10000ul);
399 if (addr == NULL)
400 goto bad;
401
402 physaddr = (caddr_t) vtophys(addr);
403 if ((u_int) physaddr >= RAM_END)
404 {
405 /* XXX:
406 * must free memory !
407 */
408 goto bad;
409 }
410
411 ti->bounce_addr = (u_int8_t *) addr;
412 ti->bounce_phys = (u_int8_t *) physaddr;
413 return;
414
415 bad:
416 bs_printf(ti, "bs_alloc_buf", "no phys bounce buffer");
417 printf("WARNING: this target is dislocated\n");
418 }
419 #endif /* __FreeBSD__ */
Cache object: 1bdeaa98597f3990743d18cf21e487f8
|