1 /* $NetBSD: bmd.c,v 1.15 2008/06/25 08:14:59 isaki Exp $ */
4 * Copyright (c) 2002 Tetsuya Isaki. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * Nereid bank memory disk
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: bmd.c,v 1.15 2008/06/25 08:14:59 isaki Exp $");
37 #include <sys/param.h>
38 #include <sys/systm.h>
41 #include <sys/device.h>
42 #include <sys/kernel.h>
45 #include <sys/disklabel.h>
46 #include <sys/ioctl.h>
47 #include <sys/fcntl.h>
50 #include <machine/bus.h>
51 #include <machine/cpu.h>
53 #include <arch/x68k/dev/intiovar.h>
55 #define BMD_ADDR1 (0xece3f0)
56 #define BMD_ADDR2 (0xecebf0)
58 #define BMD_PAGESIZE (0x10000) /* 64KB */
59 #define BMD_BSIZE (512)
60 #define BLKS_PER_PAGE (BMD_PAGESIZE / BMD_BSIZE)
64 #define BMD_CTRL_ENABLE (0x80) /* DIP8: 1=Enable, 0=Disable */
65 #define BMD_CTRL_MEMORY (0x40) /* 1=16M available, 0=4M available */
66 #define BMD_CTRL_WINDOW (0x20) /* DIP6: 1=0xee0000, 0=0xef0000 */
69 #define BMD_UNIT(dev) (minor(dev) / 8)
72 #define DPRINTF(x) printf x
74 #define DPRINTF(x) /* nothing */
79 bus_space_tag_t sc_iot
;
80 bus_space_handle_t sc_ioh
;
81 bus_space_handle_t sc_bank
;
87 #define BMD_OPENBLK (0x01)
88 #define BMD_OPENCHR (0x02)
89 #define BMD_OPEN (BMD_OPENBLK | BMD_OPENCHR)
92 static int bmd_match(device_t
, cfdata_t
, void *);
93 static void bmd_attach(device_t
, device_t
, void *);
94 static int bmd_getdisklabel(struct bmd_softc
*, dev_t
);
96 extern struct cfdriver bmd_cd
;
98 CFATTACH_DECL_NEW(bmd
, sizeof(struct bmd_softc
),
99 bmd_match
, bmd_attach
, NULL
, NULL
);
101 dev_type_open(bmdopen
);
102 dev_type_close(bmdclose
);
103 dev_type_read(bmdread
);
104 dev_type_write(bmdwrite
);
105 dev_type_ioctl(bmdioctl
);
106 dev_type_strategy(bmdstrategy
);
107 dev_type_dump(bmddump
);
108 dev_type_size(bmdsize
);
110 const struct bdevsw bmd_bdevsw
= {
111 bmdopen
, bmdclose
, bmdstrategy
, bmdioctl
, bmddump
, bmdsize
, D_DISK
114 const struct cdevsw bmd_cdevsw
= {
115 bmdopen
, bmdclose
, bmdread
, bmdwrite
, bmdioctl
,
116 nostop
, notty
, nopoll
, nommap
, nokqfilter
, D_DISK
119 struct dkdriver bmddkdriver
= { bmdstrategy
};
122 bmd_match(device_t parent
, cfdata_t cf
, void *aux
)
124 struct intio_attach_args
*ia
= aux
;
125 bus_space_tag_t iot
= ia
->ia_bst
;
126 bus_space_handle_t ioh
;
128 if (ia
->ia_addr
== INTIOCF_ADDR_DEFAULT
)
129 ia
->ia_addr
= BMD_ADDR1
;
131 /* fixed parameter */
132 if (ia
->ia_addr
!= BMD_ADDR1
&& ia
->ia_addr
!= BMD_ADDR2
)
135 if (badaddr((void *)IIOV(ia
->ia_addr
)))
139 if (bus_space_map(iot
, ia
->ia_addr
, ia
->ia_size
, 0, &ioh
))
142 bus_space_unmap(iot
, ioh
, ia
->ia_size
);
148 bmd_attach(device_t parent
, device_t self
, void *aux
)
150 struct bmd_softc
*sc
= device_private(self
);
151 struct intio_attach_args
*ia
= aux
;
152 bus_space_tag_t iot
= ia
->ia_bst
;
153 bus_space_handle_t ioh
;
156 aprint_normal(": Nereid Bank Memory Disk\n");
160 if (bus_space_map(iot
, ia
->ia_addr
, ia
->ia_size
, 0, &ioh
)) {
161 aprint_error_dev(self
, "can't map I/O space\n");
168 /* read control register */
169 r
= bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, BMD_CTRL
);
171 /* check enable-bit */
172 if ((r
& BMD_CTRL_ENABLE
) == 0) {
173 aprint_error_dev(self
, "disabled by DIP-SW 8\n");
177 if ((r
& BMD_CTRL_MEMORY
))
178 sc
->sc_maxpage
= 256;
182 if ((r
& BMD_CTRL_WINDOW
))
183 sc
->sc_window
= 0xef0000;
185 sc
->sc_window
= 0xee0000;
188 if (bus_space_map(iot
, sc
->sc_window
, BMD_PAGESIZE
, 0, &sc
->sc_bank
)) {
189 aprint_error_dev(self
, "can't map bank area: 0x%x\n",
194 aprint_normal_dev(self
, "%d MB, 0x%x(64KB) x %d pages\n",
195 (sc
->sc_maxpage
/ 16), sc
->sc_window
, sc
->sc_maxpage
);
197 disk_init(&sc
->sc_dkdev
, device_xname(self
), &bmddkdriver
);
198 disk_attach(&sc
->sc_dkdev
);
202 bmdopen(dev_t dev
, int oflags
, int devtype
, struct lwp
*l
)
204 struct bmd_softc
*sc
;
206 DPRINTF(("%s%d\n", __func__
, unit
));
208 sc
= device_lookup_private(&bmd_cd
, BMD_UNIT(dev
));
214 sc
->sc_flags
|= BMD_OPENCHR
;
217 sc
->sc_flags
|= BMD_OPENBLK
;
221 bmd_getdisklabel(sc
, dev
);
227 bmdclose(dev_t dev
, int fflag
, int devtype
, struct lwp
*l
)
229 struct bmd_softc
*sc
= device_lookup_private(&bmd_cd
, BMD_UNIT(dev
));
231 DPRINTF(("%s%d\n", __func__
, BMD_UNIT(dev
)));
235 sc
->sc_flags
&= ~BMD_OPENCHR
;
238 sc
->sc_flags
&= ~BMD_OPENBLK
;
246 bmdstrategy(struct buf
*bp
)
248 int unit
= BMD_UNIT(bp
->b_dev
);
249 struct bmd_softc
*sc
;
250 int offset
, disksize
, resid
;
251 int page
, pg_offset
, pg_resid
;
254 if (unit
>= bmd_cd
.cd_ndevs
) {
259 sc
= device_lookup_private(&bmd_cd
, BMD_UNIT(bp
->b_dev
));
265 DPRINTF(("bmdstrategy: %s blkno %d bcount %ld:",
266 (bp
->b_flags
& B_READ
) ? "read " : "write",
267 bp
->b_blkno
, bp
->b_bcount
));
269 bp
->b_resid
= bp
->b_bcount
;
270 offset
= (bp
->b_blkno
<< DEV_BSHIFT
);
271 disksize
= sc
->sc_maxpage
* BMD_PAGESIZE
;
272 if (offset
>= disksize
) {
273 /* EOF if read, EIO if write */
274 if (bp
->b_flags
& B_READ
)
281 if (resid
> disksize
- offset
)
282 resid
= disksize
- offset
;
286 page
= offset
/ BMD_PAGESIZE
;
287 pg_offset
= offset
% BMD_PAGESIZE
;
290 pg_resid
= MIN(resid
, BMD_PAGESIZE
- pg_offset
);
292 /* switch bank page */
293 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, BMD_PAGE
, page
);
295 /* XXX we should use DMA transfer? */
296 if ((bp
->b_flags
& B_READ
)) {
297 bus_space_read_region_1(sc
->sc_iot
, sc
->sc_bank
,
298 pg_offset
, data
, pg_resid
);
300 bus_space_write_region_1(sc
->sc_iot
, sc
->sc_bank
,
301 pg_offset
, data
, pg_resid
);
304 data
= (char *)data
+ pg_resid
;
307 bp
->b_resid
-= pg_resid
;
317 bmdioctl(dev_t dev
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
319 struct bmd_softc
*sc
;
323 DPRINTF(("%s%d %ld\n", __func__
, BMD_UNIT(dev
), cmd
));
325 sc
= device_lookup_private(&bmd_cd
, BMD_UNIT(dev
));
331 *(struct disklabel
*)data
= *(sc
->sc_dkdev
.dk_label
);
335 if ((flag
& FWRITE
) == 0)
338 error
= setdisklabel(&dl
, (struct disklabel
*)data
, 0, NULL
);
341 error
= writedisklabel(dev
, bmdstrategy
, &dl
, NULL
);
351 bmddump(dev_t dev
, daddr_t blkno
, void *va
, size_t size
)
354 DPRINTF(("%s%d ", __func__
, BMD_UNIT(dev
)));
361 struct bmd_softc
*sc
;
363 DPRINTF(("%s%d ", __func__
, BMD_UNIT(dev
)));
365 sc
= device_lookup_private(&bmd_cd
, BMD_UNIT(dev
));
369 return (sc
->sc_maxpage
* BMD_PAGESIZE
) >> DEV_BSHIFT
;
373 bmdread(dev_t dev
, struct uio
*uio
, int ioflag
)
375 return physio(bmdstrategy
, NULL
, dev
, B_READ
, minphys
, uio
);
379 bmdwrite(dev_t dev
, struct uio
*uio
, int ioflag
)
381 return physio(bmdstrategy
, NULL
, dev
, B_WRITE
, minphys
, uio
);
385 bmd_getdisklabel(struct bmd_softc
*sc
, dev_t dev
)
387 struct disklabel
*lp
;
390 part
= DISKPART(dev
);
391 lp
= sc
->sc_dkdev
.dk_label
;
392 memset(lp
, 0, sizeof(struct disklabel
));
394 lp
->d_secsize
= BMD_BSIZE
;
395 lp
->d_nsectors
= BLKS_PER_PAGE
;
396 lp
->d_ntracks
= sc
->sc_maxpage
;
397 lp
->d_ncylinders
= 1;
398 lp
->d_secpercyl
= lp
->d_nsectors
* lp
->d_ntracks
;
399 lp
->d_secperunit
= lp
->d_secpercyl
* lp
->d_ncylinders
;
401 lp
->d_type
= DTYPE_LD
;
402 lp
->d_rpm
= 300; /* dummy */
403 lp
->d_interleave
= 1; /* dummy? */
405 lp
->d_npartitions
= part
+ 1;
407 lp
->d_sbsize
= 8192; /* ? */
409 lp
->d_magic
= DISKMAGIC
;
410 lp
->d_magic2
= DISKMAGIC
;
411 lp
->d_checksum
= dkcksum(lp
);
413 lp
->d_partitions
[part
].p_size
= lp
->d_secperunit
;
414 lp
->d_partitions
[part
].p_fstype
= FS_BSDFFS
;
415 lp
->d_partitions
[part
].p_fsize
= 1024;
416 lp
->d_partitions
[part
].p_frag
= 8;