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 * $FreeBSD: releng/5.0/sys/i386/isa/bs/bsif.c 95710 2002-04-29 07:43:16Z peter $
30 */
31
32 #if 0
33 /* WARNING: Any bug report must contain BS_REL_VERSION */
34 #define BS_REL_VERSION "NetBSD1.2/030" /* major jump */
35 #endif
36
37 #ifdef __NetBSD__
38 #include <i386/Cbus/dev/bs/bsif.h>
39 #endif /* __NetBSD__ */
40 #ifdef __FreeBSD__
41 #include "opt_bs.h"
42 #include "opt_pc98.h"
43 #include "bs.h"
44 #include <i386/isa/bs/bsif.h>
45 #include <sys/bus.h>
46 #endif /* __FreeBSD__ */
47
48 #include <sys/bio.h>
49 #include <sys/buf.h>
50 #include <cam/cam.h>
51 #include <cam/cam_ccb.h>
52 #include <cam/cam_sim.h>
53 #include <cam/cam_xpt_sim.h>
54 #include <cam/cam_debug.h>
55
56 #include <cam/scsi/scsi_all.h>
57 #include <cam/scsi/scsi_message.h>
58
59 /**************************************************
60 * DEVICE DECLARE
61 **************************************************/
62 #ifdef __NetBSD__
63 static void bs_scsi_minphys(struct buf *);
64
65 struct cfdriver bs_cd = {
66 NULL, "bs", DV_DULL
67 };
68
69 struct scsi_device bs_dev = {
70 NULL, /* Use default error handler */
71 NULL, /* have a queue, served by this */
72 NULL, /* have no async handler */
73 NULL, /* Use default 'done' routine */
74 };
75
76 struct scsi_adapter pc98texa55bs = {
77 bs_scsi_cmd,
78 bs_scsi_minphys,
79 bs_target_open,
80 0,
81 };
82 #endif /* __NetBSD__ */
83
84 #ifdef __FreeBSD__
85 static int bsprobe(struct isa_device *);
86 static void bs_poll(struct cam_sim *sim);
87 static int bsattach(struct isa_device *);
88 static ointhand2_t bsintr;
89 static int bs_dmarangecheck(caddr_t, unsigned);
90
91 struct isa_driver bsdriver = {
92 INTR_TYPE_CAM,
93 bsprobe,
94 bsattach,
95 "bs"
96 };
97 COMPAT_ISA_DRIVER(bs, bsdriver);
98 #if 0
99 struct scsi_device bs_dev = {
100 NULL, /* Use default error handler */
101 NULL, /* have a queue, served by this */
102 NULL, /* have no async handler */
103 NULL, /* Use default 'done' routine */
104 "bs",
105 0, {0, 0}
106 };
107 #endif
108 u_int32_t
109 bs_adapter_info(unit)
110 int unit;
111 {
112 return (1);
113 }
114 #if 0
115 static struct scsi_adapter pc98texa55bs = {
116 bs_scsi_cmd,
117 bs_scsi_minphys,
118 bs_target_open,
119 0,
120 bs_adapter_info,
121 "bs", {0, 0}
122 };
123 #endif
124 static u_short pc98_irq_ball[16] = {
125 IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
126 IRQ8, IRQ9, IRQ10, IRQ11, IRQ12, IRQ13, IRQ14, IRQ15
127 };
128
129 static struct bs_softc *bscdata[NBS];
130 #endif /* __FreeBSD__ */
131
132 /*****************************************************************
133 * OS <=> BS INTERFACE
134 *****************************************************************/
135 #ifdef __FreeBSD__
136 static int
137 bsprobe(dev)
138 struct isa_device *dev;
139 {
140 struct bs_softc *bsc;
141 int unit = dev->id_unit;
142 u_int irq, drq;
143 int i, rv = 0;
144
145 if (unit >= NBS) {
146 printf("bs%d: unit number too high\n", unit);
147 return rv;
148 }
149 /*
150 * Allocate a storage for us
151 */
152 if (bscdata[unit]) {
153 printf("bs%d: memory already allocated\n", unit);
154 return rv;
155 }
156 if (!(bsc = malloc(sizeof(struct bs_softc), M_TEMP, M_NOWAIT | M_ZERO)))
157 {
158 printf("bs%d cannot malloc!\n", unit);
159 return rv;
160 }
161 callout_handle_init(&bsc->timeout_ch);
162 bscdata[unit] = bsc;
163 bsc->unit = unit;
164
165 bsc->sc_cfgflags = DVCFG_MINOR(dev->id_flags);
166 bsc->sc_hw = DVCFG_HW(&bshw_hwsel, DVCFG_MAJOR(dev->id_flags));
167 if (bsc->sc_hw == NULL)
168 return rv;
169
170 if ((bsc->sc_hw->hw_flags & BSHW_SMFIFO) &&
171 (dev->id_maddr != (caddr_t)MADDRUNK))
172 bsc->sm_offset = (u_long) dev->id_maddr;
173 else
174 bsc->sm_offset = (u_long) 0;
175
176 snprintf(bsc->sc_dvname, sizeof(bsc->sc_dvname), "bs%d", unit);
177
178 if (dev->id_iobase == 0)
179 {
180 printf("%s: iobase not specified. Assume default port(0x%x)\n",
181 bsc->sc_dvname, BSHW_DEFAULT_PORT);
182 dev->id_iobase = BSHW_DEFAULT_PORT;
183 }
184
185 bsc->sc_iobase = dev->id_iobase;
186 irq = IRQUNK;
187 drq = DRQUNK;
188 if (bshw_board_probe(bsc, &drq, &irq))
189 goto bad;
190
191 dev->id_irq = pc98_irq_ball[irq];
192 dev->id_drq = (short)drq;
193
194 /* initialize host queue and target info */
195 bs_hostque_init(bsc);
196 for (i = 0; i < NTARGETS; i++)
197 if (i != bsc->sc_hostid)
198 bs_init_target_info(bsc, i);
199
200 /* initialize ccb queue */
201 bs_init_ccbque(BS_MAX_CCB);
202
203 /* scsi bus reset and restart */
204 bsc->sc_hstate = BSC_BOOTUP;
205 bsc->sc_retry = RETRIES;
206 bsc->sc_wc = delaycount * 250; /* about 1 sec */
207 bs_reset_nexus(bsc);
208
209 return BSHW_IOSZ;
210 bad:
211 return rv;
212 }
213 #endif /* __FreeBSD__ */
214
215 #ifdef __NetBSD__
216 int
217 bsprint(aux, name)
218 void *aux;
219 const char *name;
220 {
221
222 if (name != NULL)
223 printf("%s: scsibus ", name);
224 return UNCONF;
225 }
226 #endif
227
228 #ifdef __FreeBSD__
229 static void
230 bs_poll(struct cam_sim *sim)
231 {
232 bs_sequencer(cam_sim_softc(sim));
233 }
234
235 static int
236 bsattach(dev)
237 struct isa_device *dev;
238 {
239 int unit = dev->id_unit;
240 struct bs_softc *bsc = bscdata[unit];
241 struct cam_devq *devq;
242
243 dev->id_ointr = bsintr;
244
245 /*
246 * CAM support HN2 MAX_START, MAX_TAGS xxxx
247 */
248 devq = cam_simq_alloc(256/*MAX_START*/);
249 if (devq == NULL)
250 return 0;
251
252 bsc->sim = cam_sim_alloc(bs_scsi_cmd, bs_poll, "bs",
253 bsc, unit, 1, 32/*MAX_TAGS*/, devq);
254 if (bsc->sim == NULL) {
255 cam_simq_free(devq);
256 return 0;
257 }
258
259 if (xpt_bus_register(bsc->sim, 0) != CAM_SUCCESS) {
260 free(bsc->sim, M_DEVBUF);
261 return 0;
262 }
263
264 if (xpt_create_path(&bsc->path, /*periph*/NULL,
265 cam_sim_path(bsc->sim), CAM_TARGET_WILDCARD,
266 CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
267 xpt_bus_deregister(cam_sim_path(bsc->sim));
268 cam_sim_free(bsc->sim, /*free_simq*/TRUE);
269 free(bsc->sim, M_DEVBUF);
270 return 0;
271 }
272 bs_start_timeout(bsc);
273 return 1;
274 }
275 #endif /* __FreeBSD__ */
276
277 #ifdef __NetBSD__
278 int
279 bsintr(arg)
280 void *arg;
281 {
282
283 return bs_sequencer((struct bs_softc *)arg);
284 }
285 #endif /* __NetBSD__ */
286
287 #ifdef __FreeBSD__
288 static void
289 bsintr(unit)
290 int unit;
291 {
292 (void)bs_sequencer(bscdata[unit]);
293 }
294 #endif /* __FreeBSD__ */
295
296 /*****************************************************************
297 * JULIAN SCSI <=> BS INTERFACE
298 *****************************************************************/
299 #ifndef __FreeBSD__
300 static void
301 bs_scsi_minphys(bp)
302 struct buf *bp;
303 {
304
305 if (bp->b_bcount > BSDMABUFSIZ)
306 bp->b_bcount = BSDMABUFSIZ;
307 minphys(bp);
308 }
309 #endif
310 #if 0
311 XSBS_INT32T
312 bs_target_open(sc, cf)
313 struct scsi_link *sc;
314 struct cfdata *cf;
315 {
316 u_int target = sc->target;
317 struct bs_softc *bsc = (struct bs_softc *) (sc->adapter_softc);
318 struct targ_info *ti = bsc->sc_ti[target];
319 u_int flags;
320
321 if ((bsc->sc_openf & (1 << target)) == 0)
322 return ENODEV;
323
324 if ((flags = cf->cf_flags) == 0)
325 flags = BS_SCSI_DEFCFG;
326
327 bs_setup_ctrl(ti, (u_int)sc->quirks, flags);
328 return 0;
329 }
330 #endif
331 /*****************************************************************
332 * BS MEMORY ALLOCATION INTERFACE
333 *****************************************************************/
334 #ifdef __NetBSD__
335 void
336 bs_alloc_buf(ti)
337 struct targ_info *ti;
338 {
339 struct bs_softc *bsc = ti->ti_bsc;
340 caddr_t addr, physaddr;
341 bus_dma_segment_t seg;
342 int rseg, error;
343 u_int pages;
344 extern int cold;
345
346 /* XXX:
347 * strategy change!
348 * A) total memory >= 16M at boot: MAXBSIZE * 7 = 112k.
349 * B) others: 4K * 7 = 28 K.
350 */
351 if (get_sysinfo(SYSINFO_MEMLEVEL) == MEM_LEVEL1 && cold != 0)
352 pages = 4;
353 else
354 pages = 1;
355 ti->bounce_size = NBPG * pages;
356
357 addr = NULL;
358 error = bus_dmamem_alloc(bsc->sc_dmat, ti->bounce_size, NBPG, 0,
359 &seg, 1, &rseg, BUS_DMA_NOWAIT);
360 if (rseg == 1 && error == 0)
361 error = bus_dmamem_map(bsc->sc_dmat, &seg, rseg,
362 ti->bounce_size, &addr, BUS_DMA_NOWAIT);
363 if (rseg != 1 || error != 0)
364 {
365 ti->bounce_size = NBPG;
366 if ((addr = malloc(NBPG, M_DEVBUF, M_NOWAIT)) == NULL)
367 goto bad;
368 }
369
370 physaddr = (caddr_t) vtophys(addr);
371 if ((u_int) physaddr >= RAM_END)
372 {
373 /* XXX: mem from malloc only! */
374 free(addr, M_DEVBUF);
375 goto bad;
376 }
377
378 ti->bounce_addr = (u_int8_t *) addr;
379 ti->bounce_phys = (u_int8_t *) physaddr;
380 return;
381
382 bad:
383 bs_printf(ti, "bs_alloc_buf", "no phys bounce buffer");
384 printf("WARNING: this target is dislocated\n");
385 }
386 #endif /* __NetBSD__ */
387
388 #ifdef __FreeBSD__
389 static int bs_dmarangecheck(caddr_t va, unsigned length)
390 {
391 vm_offset_t phys, priorpage = 0, endva;
392
393 endva = (vm_offset_t)round_page((unsigned long)(va+length));
394 for (; va < (caddr_t)endva; va += PAGE_SIZE) {
395 phys = trunc_page(pmap_extract(kernel_pmap, (vm_offset_t)va));
396 if (phys == 0)
397 panic("bs_dmarangecheck: no physical page present");
398 if (phys >= RAM_END)
399 return 1;
400 if (priorpage) {
401 if (priorpage + PAGE_SIZE != phys)
402 return 1;
403 }
404 priorpage = phys;
405 }
406 return 0;
407 }
408
409 void
410 bs_alloc_buf(ti)
411 struct targ_info *ti;
412 {
413 caddr_t addr, physaddr;
414
415 #if BS_BOUNCE_SIZE != 0
416 ti->bounce_size = BS_BOUNCE_SIZE;
417 #else
418 ti->bounce_size = BSHW_NBPG;
419 #endif
420 /* Try malloc() first. It works better if it works. */
421 addr = malloc(ti->bounce_size, M_DEVBUF, M_NOWAIT);
422 if (addr != NULL) {
423 if (bs_dmarangecheck(addr, ti->bounce_size) == 0) {
424 physaddr = (caddr_t) vtophys(addr);
425 ti->bounce_addr = (u_int8_t *) addr;
426 ti->bounce_phys = (u_int8_t *) physaddr;
427 return;
428 }
429 free(addr, M_DEVBUF);
430 }
431 addr = contigmalloc(ti->bounce_size, M_DEVBUF, M_NOWAIT,
432 0ul, RAM_END, 1ul, 0x10000ul);
433 if (addr == NULL)
434 goto bad;
435
436 physaddr = (caddr_t) vtophys(addr);
437 if ((u_int) physaddr >= RAM_END)
438 {
439 /* XXX:
440 * must free memory !
441 */
442 goto bad;
443 }
444
445 ti->bounce_addr = (u_int8_t *) addr;
446 ti->bounce_phys = (u_int8_t *) physaddr;
447 return;
448
449 bad:
450 bs_printf(ti, "bs_alloc_buf", "no phys bounce buffer");
451 printf("WARNING: this target is dislocated\n");
452 }
453 #endif /* __FreeBSD__ */
Cache object: 11ebbda8a32dbe89657bd7a4ecc878b3
|