remove __P() from this directory
[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.4 2003/08/27 10:35:16 rob 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 #ifdef __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 #ifdef __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 #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__ */