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