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