timeout/untimeout ==> callout_*
[dragonfly.git] / sys / dev / disk / i386 / 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: src/sys/i386/isa/bs/bsif.c,v 1.10.2.1 2000/08/24 08:06:08 kato Exp $
30  * $DragonFly: src/sys/dev/disk/i386/bs/Attic/bsif.c,v 1.8 2004/09/18 18:47:20 dillon Exp $
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 #if defined(__DragonFly__) || defined(__FreeBSD__)
42 #include "opt_bs.h"
43 #include "opt_pc98.h"
44 #include "bs.h"
45 #include "bsif.h"
46 #endif  /* __FreeBSD__ */
47
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>
53
54 #include <bus/cam/scsi/scsi_all.h>
55 #include <bus/cam/scsi/scsi_message.h>
56
57 /**************************************************
58  * DEVICE DECLARE
59  **************************************************/
60 #ifdef __NetBSD__
61 static void bs_scsi_minphys (struct buf *);
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 #if defined(__DragonFly__) || defined(__FreeBSD__)
83 static int bsprobe (struct isa_device *);
84 static void bs_poll(struct cam_sim *sim);
85 static int bsattach(struct isa_device *);
86 static ointhand2_t bsintr;
87 static int bs_dmarangecheck (caddr_t, unsigned);
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 #if defined(__DragonFly__) || defined(__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         bsc = malloc(sizeof(struct bs_softc), M_TEMP, M_WAITOK | M_ZERO);
153         callout_init(&bsc->timeout_ch);
154         bscdata[unit] = bsc;
155         bsc->unit = unit;
156
157         bsc->sc_cfgflags = DVCFG_MINOR(dev->id_flags);
158         bsc->sc_hw = DVCFG_HW(&bshw_hwsel, DVCFG_MAJOR(dev->id_flags));
159         if (bsc->sc_hw == NULL)
160                 return rv;
161
162         if ((bsc->sc_hw->hw_flags & BSHW_SMFIFO) &&
163                         (dev->id_maddr != (caddr_t)MADDRUNK))
164                 bsc->sm_offset = (u_long) dev->id_maddr;
165         else
166                 bsc->sm_offset = (u_long) 0;
167
168         snprintf(bsc->sc_dvname, sizeof(bsc->sc_dvname), "bs%d", unit);
169
170         if (dev->id_iobase == 0)
171         {
172                 printf("%s: iobase not specified. Assume default port(0x%x)\n",
173                         bsc->sc_dvname, BSHW_DEFAULT_PORT);
174                 dev->id_iobase = BSHW_DEFAULT_PORT;
175         }
176
177         bsc->sc_iobase = dev->id_iobase;
178         irq = IRQUNK;
179         drq = DRQUNK;
180         if (bshw_board_probe(bsc, &drq, &irq))
181                 goto bad;
182
183         dev->id_irq = pc98_irq_ball[irq];
184         dev->id_drq = (short)drq;
185
186         /* initialize host queue and target info */
187         bs_hostque_init(bsc);
188         for (i = 0; i < NTARGETS; i++)
189                 if (i != bsc->sc_hostid)
190                         bs_init_target_info(bsc, i);
191
192         /* initialize ccb queue */
193         bs_init_ccbque(BS_MAX_CCB);
194
195         /* scsi bus reset and restart */
196         bsc->sc_hstate = BSC_BOOTUP;
197         bsc->sc_retry = RETRIES;
198         bsc->sc_wc = delaycount * 250;  /* about 1 sec */
199         bs_reset_nexus(bsc);
200
201         return BSHW_IOSZ;
202 bad:
203         return rv;
204 }
205 #endif  /* __FreeBSD__ */
206
207 #ifdef __NetBSD__
208 int
209 bsprint(aux, name)
210         void *aux;
211         const char *name;
212 {
213
214         if (name != NULL)
215                 printf("%s: scsibus ", name);
216         return UNCONF;
217 }
218 #endif
219
220 #if defined(__DragonFly__) || defined(__FreeBSD__)
221 static void
222 bs_poll(struct cam_sim *sim)
223 {
224         bs_sequencer(cam_sim_softc(sim));
225 }
226
227 static int
228 bsattach(dev)
229         struct isa_device *dev;
230 {
231         int unit = dev->id_unit;
232         struct bs_softc *bsc = bscdata[unit];
233         struct cam_devq *devq;
234
235         dev->id_ointr = bsintr;
236
237         /*
238          * CAM support  HN2  MAX_START, MAX_TAGS xxxx
239          */
240         devq = cam_simq_alloc(256/*MAX_START*/);
241         if (devq == NULL)
242                 return 0;
243
244         bsc->sim = cam_sim_alloc(bs_scsi_cmd, bs_poll, "bs",
245                                  bsc, unit, 1, 32/*MAX_TAGS*/, devq);
246         cam_simq_release(devq);
247         if (bsc->sim == NULL)
248                 return 0;
249
250         if (xpt_bus_register(bsc->sim, 0) != CAM_SUCCESS) {
251                 free(bsc->sim, M_DEVBUF);
252                 return 0;
253         }
254         
255         if (xpt_create_path(&bsc->path, /*periph*/NULL,
256                             cam_sim_path(bsc->sim), CAM_TARGET_WILDCARD,
257                             CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
258                 xpt_bus_deregister(cam_sim_path(bsc->sim));
259                 cam_sim_free(bsc->sim);
260                 free(bsc->sim, M_DEVBUF);
261                 return 0;
262         }
263         bs_start_timeout(bsc);
264         return 1;
265 }
266 #endif  /* __FreeBSD__ */
267
268 #ifdef __NetBSD__
269 int
270 bsintr(arg)
271         void *arg;
272 {
273
274         return bs_sequencer((struct bs_softc *)arg);
275 }
276 #endif  /* __NetBSD__ */
277
278 #if defined(__DragonFly__) || defined(__FreeBSD__)
279 static void
280 bsintr(unit)
281         int unit;
282 {
283         (void)bs_sequencer(bscdata[unit]);
284 }
285 #endif  /* __FreeBSD__ */
286
287 /*****************************************************************
288  * JULIAN SCSI <=> BS INTERFACE
289  *****************************************************************/
290 #if !defined(__DragonFly__) && !defined(__FreeBSD__)
291 static void
292 bs_scsi_minphys(bp)
293         struct buf *bp;
294 {
295
296         if (bp->b_bcount > BSDMABUFSIZ)
297                 bp->b_bcount = BSDMABUFSIZ;
298         minphys(bp);
299 }
300 #endif
301 #if 0
302 XSBS_INT32T
303 bs_target_open(sc, cf)
304         struct scsi_link *sc;
305         struct cfdata *cf;
306 {
307         u_int target = sc->target;
308         struct bs_softc *bsc = (struct bs_softc *) (sc->adapter_softc);
309         struct targ_info *ti = bsc->sc_ti[target];
310         u_int flags;
311
312         if ((bsc->sc_openf & (1 << target)) == 0)
313                 return ENODEV;
314
315         if ((flags = cf->cf_flags) == 0)
316                 flags = BS_SCSI_DEFCFG;
317
318         bs_setup_ctrl(ti, (u_int)sc->quirks, flags);
319         return 0;
320 }
321 #endif
322 /*****************************************************************
323  * BS MEMORY ALLOCATION INTERFACE
324  *****************************************************************/
325 #ifdef __NetBSD__
326 void
327 bs_alloc_buf(ti)
328         struct targ_info *ti;
329 {
330         struct bs_softc *bsc = ti->ti_bsc;
331         caddr_t addr, physaddr;
332         bus_dma_segment_t seg;
333         int rseg, error;
334         u_int pages;
335         extern int cold;
336
337         /* XXX:
338          * strategy change!
339          * A) total memory >= 16M at boot: MAXBSIZE * 7 = 112k.
340          * B) others:  4K * 7 = 28 K.
341          */
342         if (get_sysinfo(SYSINFO_MEMLEVEL) == MEM_LEVEL1 && cold != 0)
343                 pages = 4;
344         else
345                 pages = 1;
346         ti->bounce_size = NBPG * pages;
347
348         addr = NULL;
349         error = bus_dmamem_alloc(bsc->sc_dmat, ti->bounce_size, NBPG, 0,
350                                  &seg, 1, &rseg, BUS_DMA_NOWAIT);
351         if (rseg == 1 && error == 0)
352                 error = bus_dmamem_map(bsc->sc_dmat, &seg, rseg,
353                                        ti->bounce_size, &addr, BUS_DMA_NOWAIT);
354         if (rseg != 1 || error != 0)
355         {
356                 ti->bounce_size = NBPG;
357                 if ((addr = malloc(NBPG, M_DEVBUF, M_INTWAIT)) == NULL)
358                         goto bad;
359         }
360
361         physaddr = (caddr_t) vtophys(addr);
362         if ((u_int) physaddr >= RAM_END)
363         {
364                 /* XXX: mem from malloc only! */
365                 free(addr, M_DEVBUF);
366                 goto bad;
367         }
368
369         ti->bounce_addr = (u_int8_t *) addr;
370         ti->bounce_phys = (u_int8_t *) physaddr;
371         return;
372
373 bad:
374         bs_printf(ti, "bs_alloc_buf", "no phys bounce buffer");
375         printf("WARNING: this target is dislocated\n");
376 }
377 #endif  /* __NetBSD__ */
378
379 #if defined(__DragonFly__) || defined(__FreeBSD__)
380 static int bs_dmarangecheck(caddr_t va, unsigned length)
381 {
382         vm_offset_t phys, priorpage = 0, endva;
383
384         endva = (vm_offset_t)round_page((unsigned long)(va+length));
385         for (; va < (caddr_t)endva; va += PAGE_SIZE) {
386                 phys = trunc_page(pmap_extract(pmap_kernel(), (vm_offset_t)va));
387                 if (phys == 0)
388                         panic("bs_dmarangecheck: no physical page present");
389                 if (phys >= RAM_END)
390                         return 1;
391                 if (priorpage) {
392                         if (priorpage + PAGE_SIZE != phys)
393                                 return 1;
394                 }
395                 priorpage = phys;
396         }
397         return 0;
398 }
399
400 void
401 bs_alloc_buf(ti)
402         struct targ_info *ti;
403 {
404         caddr_t addr, physaddr;
405
406 #if BS_BOUNCE_SIZE != 0
407         ti->bounce_size = BS_BOUNCE_SIZE;
408 #else
409         ti->bounce_size = BSHW_NBPG;
410 #endif
411         /* Try malloc() first.  It works better if it works. */
412         addr = malloc(ti->bounce_size, M_DEVBUF, M_INTWAIT);
413         if (addr != NULL) {
414                 if (bs_dmarangecheck(addr, ti->bounce_size) == 0) {
415                         physaddr = (caddr_t) vtophys(addr);
416                         ti->bounce_addr = (u_int8_t *) addr;
417                         ti->bounce_phys = (u_int8_t *) physaddr;
418                         return;
419                 }
420                 free(addr, M_DEVBUF);
421         }
422         addr = contigmalloc(ti->bounce_size, M_DEVBUF, M_NOWAIT,
423                                                 0ul, RAM_END, 1ul, 0x10000ul);
424         if (addr == NULL)
425                 goto bad;
426
427         physaddr = (caddr_t) vtophys(addr);
428         if ((u_int) physaddr >= RAM_END)
429         {
430                 /* XXX:
431                  * must free memory !
432                  */
433                 goto bad;
434         }
435
436         ti->bounce_addr = (u_int8_t *) addr;
437         ti->bounce_phys = (u_int8_t *) physaddr;
438         return;
439
440 bad:
441         bs_printf(ti, "bs_alloc_buf", "no phys bounce buffer");
442         printf("WARNING: this target is dislocated\n");
443 }
444 #endif  /* __FreeBSD__ */