xref: /netbsd-src/sys/arch/x68k/dev/bmd.c (revision 6b664a713479c31d4f17b38b42182a5d5fa21802)
1*6b664a71Sisaki /*	$NetBSD: bmd.c,v 1.28 2024/01/07 07:58:33 isaki Exp $	*/
214096cb1Sisaki 
314096cb1Sisaki /*
414096cb1Sisaki  * Copyright (c) 2002 Tetsuya Isaki. All rights reserved.
514096cb1Sisaki  *
614096cb1Sisaki  * Redistribution and use in source and binary forms, with or without
714096cb1Sisaki  * modification, are permitted provided that the following conditions
814096cb1Sisaki  * are met:
914096cb1Sisaki  * 1. Redistributions of source code must retain the above copyright
1014096cb1Sisaki  *    notice, this list of conditions and the following disclaimer.
1114096cb1Sisaki  * 2. Redistributions in binary form must reproduce the above copyright
1214096cb1Sisaki  *    notice, this list of conditions and the following disclaimer in the
1314096cb1Sisaki  *    documentation and/or other materials provided with the distribution.
1414096cb1Sisaki  *
1514096cb1Sisaki  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1614096cb1Sisaki  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1714096cb1Sisaki  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1814096cb1Sisaki  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1914096cb1Sisaki  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
2014096cb1Sisaki  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2114096cb1Sisaki  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2214096cb1Sisaki  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2314096cb1Sisaki  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2414096cb1Sisaki  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2514096cb1Sisaki  * SUCH DAMAGE.
2614096cb1Sisaki  */
2714096cb1Sisaki 
2814096cb1Sisaki /*
2914096cb1Sisaki  * Nereid bank memory disk
3014096cb1Sisaki  */
3114096cb1Sisaki 
32ab48a212Slukem #include <sys/cdefs.h>
33*6b664a71Sisaki __KERNEL_RCSID(0, "$NetBSD: bmd.c,v 1.28 2024/01/07 07:58:33 isaki Exp $");
34ab48a212Slukem 
3514096cb1Sisaki #include <sys/param.h>
3614096cb1Sisaki #include <sys/systm.h>
3714096cb1Sisaki #include <sys/buf.h>
3814096cb1Sisaki #include <sys/conf.h>
3914096cb1Sisaki #include <sys/device.h>
4014096cb1Sisaki #include <sys/kernel.h>
4114096cb1Sisaki #include <sys/stat.h>
4214096cb1Sisaki #include <sys/disk.h>
4314096cb1Sisaki #include <sys/disklabel.h>
4414096cb1Sisaki #include <sys/ioctl.h>
4514096cb1Sisaki #include <sys/fcntl.h>
4614096cb1Sisaki #include <sys/proc.h>
4714096cb1Sisaki 
4814096cb1Sisaki #include <machine/bus.h>
4914096cb1Sisaki #include <machine/cpu.h>
5014096cb1Sisaki 
5114096cb1Sisaki #include <arch/x68k/dev/intiovar.h>
5214096cb1Sisaki 
53623e78a6Stsutsui #include "ioconf.h"
54623e78a6Stsutsui 
5514096cb1Sisaki #define BMD_ADDR1	(0xece3f0)
5614096cb1Sisaki #define BMD_ADDR2	(0xecebf0)
5714096cb1Sisaki 
5814096cb1Sisaki #define BMD_PAGESIZE	(0x10000)	/* 64KB */
5914096cb1Sisaki #define BMD_BSIZE	(512)
6014096cb1Sisaki #define BLKS_PER_PAGE	(BMD_PAGESIZE / BMD_BSIZE)
6114096cb1Sisaki 
6214096cb1Sisaki #define BMD_PAGE	(0)
6314096cb1Sisaki #define BMD_CTRL	(1)
6414096cb1Sisaki #define BMD_CTRL_ENABLE	(0x80)	/* DIP8: 1=Enable, 0=Disable */
6514096cb1Sisaki #define BMD_CTRL_MEMORY	(0x40)	/*       1=16M available, 0=4M available */
6614096cb1Sisaki #define BMD_CTRL_WINDOW	(0x20)	/* DIP6: 1=0xee0000, 0=0xef0000 */
6714096cb1Sisaki 
6814096cb1Sisaki 
6914096cb1Sisaki #define BMD_UNIT(dev)	(minor(dev) / 8)
7014096cb1Sisaki 
7114096cb1Sisaki #ifdef BMD_DEBUG
7214096cb1Sisaki #define DPRINTF(x)	printf x
7314096cb1Sisaki #else
7414096cb1Sisaki #define DPRINTF(x)	/* nothing */
7514096cb1Sisaki #endif
7614096cb1Sisaki 
7714096cb1Sisaki struct bmd_softc {
7814096cb1Sisaki 	struct disk sc_dkdev;
7914096cb1Sisaki 	bus_space_tag_t    sc_iot;
8014096cb1Sisaki 	bus_space_handle_t sc_ioh;
8114096cb1Sisaki 	bus_space_handle_t sc_bank;
8214096cb1Sisaki 
8314096cb1Sisaki 	int sc_maxpage;
8414096cb1Sisaki 	int sc_window;
8514096cb1Sisaki 
8614096cb1Sisaki 	int sc_flags;
8714096cb1Sisaki #define BMD_OPENBLK	(0x01)
8814096cb1Sisaki #define BMD_OPENCHR	(0x02)
8914096cb1Sisaki #define BMD_OPEN	(BMD_OPENBLK | BMD_OPENCHR)
9014096cb1Sisaki };
9114096cb1Sisaki 
922830b81aSisaki static int  bmd_match(device_t, cfdata_t, void *);
932830b81aSisaki static void bmd_attach(device_t, device_t, void *);
9414096cb1Sisaki static int  bmd_getdisklabel(struct bmd_softc *, dev_t);
9514096cb1Sisaki 
962830b81aSisaki CFATTACH_DECL_NEW(bmd, sizeof(struct bmd_softc),
9714096cb1Sisaki 	bmd_match, bmd_attach, NULL, NULL);
9814096cb1Sisaki 
9914096cb1Sisaki dev_type_open(bmdopen);
10014096cb1Sisaki dev_type_close(bmdclose);
10114096cb1Sisaki dev_type_read(bmdread);
10214096cb1Sisaki dev_type_write(bmdwrite);
10314096cb1Sisaki dev_type_ioctl(bmdioctl);
10414096cb1Sisaki dev_type_strategy(bmdstrategy);
10514096cb1Sisaki dev_type_dump(bmddump);
10614096cb1Sisaki dev_type_size(bmdsize);
10714096cb1Sisaki 
10814096cb1Sisaki const struct bdevsw bmd_bdevsw = {
109a68f9396Sdholland 	.d_open = bmdopen,
110a68f9396Sdholland 	.d_close = bmdclose,
111a68f9396Sdholland 	.d_strategy = bmdstrategy,
112a68f9396Sdholland 	.d_ioctl = bmdioctl,
113a68f9396Sdholland 	.d_dump = bmddump,
114a68f9396Sdholland 	.d_psize = bmdsize,
1158c70ef39Sdholland 	.d_discard = nodiscard,
116a68f9396Sdholland 	.d_flag = D_DISK
11714096cb1Sisaki };
11814096cb1Sisaki 
11914096cb1Sisaki const struct cdevsw bmd_cdevsw = {
120a68f9396Sdholland 	.d_open = bmdopen,
121a68f9396Sdholland 	.d_close = bmdclose,
122a68f9396Sdholland 	.d_read = bmdread,
123a68f9396Sdholland 	.d_write = bmdwrite,
124a68f9396Sdholland 	.d_ioctl = bmdioctl,
125a68f9396Sdholland 	.d_stop = nostop,
126a68f9396Sdholland 	.d_tty = notty,
127a68f9396Sdholland 	.d_poll = nopoll,
128a68f9396Sdholland 	.d_mmap = nommap,
129a68f9396Sdholland 	.d_kqfilter = nokqfilter,
130f9228f42Sdholland 	.d_discard = nodiscard,
131a68f9396Sdholland 	.d_flag = D_DISK
13214096cb1Sisaki };
13314096cb1Sisaki 
1346f00c789Smlelstv struct dkdriver bmddkdriver = {
1356f00c789Smlelstv 	.d_strategy = bmdstrategy
1366f00c789Smlelstv };
13714096cb1Sisaki 
13814096cb1Sisaki static int
bmd_match(device_t parent,cfdata_t cf,void * aux)1392830b81aSisaki bmd_match(device_t parent, cfdata_t cf, void *aux)
14014096cb1Sisaki {
14114096cb1Sisaki 	struct intio_attach_args *ia = aux;
14214096cb1Sisaki 	bus_space_tag_t iot = ia->ia_bst;
14314096cb1Sisaki 	bus_space_handle_t ioh;
144bec4c1aeSisaki 	int window;
145bec4c1aeSisaki 	int r;
14614096cb1Sisaki 
14714096cb1Sisaki 	if (ia->ia_addr == INTIOCF_ADDR_DEFAULT)
14814096cb1Sisaki 		ia->ia_addr = BMD_ADDR1;
14914096cb1Sisaki 
15014096cb1Sisaki 	/* fixed parameter */
15114096cb1Sisaki 	if (ia->ia_addr != BMD_ADDR1 && ia->ia_addr != BMD_ADDR2)
15214096cb1Sisaki 		return (0);
15314096cb1Sisaki 
154bec4c1aeSisaki 	/* Check CTRL addr */
1553b878f89Sisaki 	if (badaddr((void *)IIOV(ia->ia_addr)))
15614096cb1Sisaki 		return (0);
15714096cb1Sisaki 
15814096cb1Sisaki 	ia->ia_size = 2;
15914096cb1Sisaki 	if (bus_space_map(iot, ia->ia_addr, ia->ia_size, 0, &ioh))
16014096cb1Sisaki 		return (0);
16114096cb1Sisaki 
162bec4c1aeSisaki 	/* Check window addr */
163bec4c1aeSisaki 	r = bus_space_read_1(iot, ioh, BMD_CTRL);
16414096cb1Sisaki 	bus_space_unmap(iot, ioh, ia->ia_size);
16514096cb1Sisaki 
166bec4c1aeSisaki 	if ((r & BMD_CTRL_WINDOW))
167bec4c1aeSisaki 		window = 0xef0000;
168bec4c1aeSisaki 	else
169bec4c1aeSisaki 		window = 0xee0000;
170bec4c1aeSisaki 	if (badaddr((void *)IIOV(window)))
171bec4c1aeSisaki 		return (0);
172bec4c1aeSisaki 
17314096cb1Sisaki 	return (1);
17414096cb1Sisaki }
17514096cb1Sisaki 
17614096cb1Sisaki static void
bmd_attach(device_t parent,device_t self,void * aux)1772830b81aSisaki bmd_attach(device_t parent, device_t self, void *aux)
17814096cb1Sisaki {
1792830b81aSisaki 	struct bmd_softc *sc = device_private(self);
18014096cb1Sisaki 	struct intio_attach_args *ia = aux;
18114096cb1Sisaki 	bus_space_tag_t iot = ia->ia_bst;
18214096cb1Sisaki 	bus_space_handle_t ioh;
18314096cb1Sisaki 	u_int8_t r;
18414096cb1Sisaki 
1852830b81aSisaki 	aprint_normal(": Nereid Bank Memory Disk\n");
18614096cb1Sisaki 
18714096cb1Sisaki 	/* Map I/O space */
18814096cb1Sisaki 	ia->ia_size = 2;
18914096cb1Sisaki 	if (bus_space_map(iot, ia->ia_addr, ia->ia_size, 0, &ioh)) {
1902830b81aSisaki 		aprint_error_dev(self, "can't map I/O space\n");
19114096cb1Sisaki 		return;
19214096cb1Sisaki 	}
19314096cb1Sisaki 
19414096cb1Sisaki 	sc->sc_iot = iot;
19514096cb1Sisaki 	sc->sc_ioh = ioh;
19614096cb1Sisaki 
19714096cb1Sisaki 	/* read control register */
19814096cb1Sisaki 	r = bus_space_read_1(sc->sc_iot, sc->sc_ioh, BMD_CTRL);
19914096cb1Sisaki 
20014096cb1Sisaki 	/* check enable-bit */
20114096cb1Sisaki 	if ((r & BMD_CTRL_ENABLE) == 0) {
2022830b81aSisaki 		aprint_error_dev(self, "disabled by DIP-SW 8\n");
20314096cb1Sisaki 		return;
20414096cb1Sisaki 	}
20514096cb1Sisaki 
20614096cb1Sisaki 	if ((r & BMD_CTRL_MEMORY))
20714096cb1Sisaki 		sc->sc_maxpage = 256;
20814096cb1Sisaki 	else
20914096cb1Sisaki 		sc->sc_maxpage = 64;
21014096cb1Sisaki 
21114096cb1Sisaki 	if ((r & BMD_CTRL_WINDOW))
21214096cb1Sisaki 		sc->sc_window = 0xef0000;
21314096cb1Sisaki 	else
21414096cb1Sisaki 		sc->sc_window = 0xee0000;
21514096cb1Sisaki 
21614096cb1Sisaki 	/* Map bank area */
21714096cb1Sisaki 	if (bus_space_map(iot, sc->sc_window, BMD_PAGESIZE, 0, &sc->sc_bank)) {
2182830b81aSisaki 		aprint_error_dev(self, "can't map bank area: 0x%x\n",
2192830b81aSisaki 			sc->sc_window);
22014096cb1Sisaki 		return;
22114096cb1Sisaki 	}
22214096cb1Sisaki 
2232830b81aSisaki 	aprint_normal_dev(self, "%d MB, 0x%x(64KB) x %d pages\n",
22414096cb1Sisaki 		(sc->sc_maxpage / 16), sc->sc_window, sc->sc_maxpage);
22514096cb1Sisaki 
2262830b81aSisaki 	disk_init(&sc->sc_dkdev, device_xname(self), &bmddkdriver);
22714096cb1Sisaki 	disk_attach(&sc->sc_dkdev);
22814096cb1Sisaki }
22914096cb1Sisaki 
23014096cb1Sisaki int
bmdopen(dev_t dev,int oflags,int devtype,struct lwp * l)23195e1ffb1Schristos bmdopen(dev_t dev, int oflags, int devtype, struct lwp *l)
23214096cb1Sisaki {
23314096cb1Sisaki 	struct bmd_softc *sc;
23414096cb1Sisaki 
23582bbbd48Sandvar 	DPRINTF(("%s%d\n", __func__, BMD_UNIT(dev)));
23614096cb1Sisaki 
23761f21080Scegger 	sc = device_lookup_private(&bmd_cd, BMD_UNIT(dev));
23814096cb1Sisaki 	if (sc == NULL)
23914096cb1Sisaki 		return ENXIO;
24014096cb1Sisaki 
24114096cb1Sisaki 	switch (devtype) {
24214096cb1Sisaki 	case S_IFCHR:
24314096cb1Sisaki 		sc->sc_flags |= BMD_OPENCHR;
24414096cb1Sisaki 		break;
24514096cb1Sisaki 	case S_IFBLK:
24614096cb1Sisaki 		sc->sc_flags |= BMD_OPENBLK;
24714096cb1Sisaki 		break;
24814096cb1Sisaki 	}
24914096cb1Sisaki 
25014096cb1Sisaki 	bmd_getdisklabel(sc, dev);
25114096cb1Sisaki 
25214096cb1Sisaki 	return (0);
25314096cb1Sisaki }
25414096cb1Sisaki 
25514096cb1Sisaki int
bmdclose(dev_t dev,int fflag,int devtype,struct lwp * l)25695e1ffb1Schristos bmdclose(dev_t dev, int fflag, int devtype, struct lwp *l)
25714096cb1Sisaki {
258661719faSisaki 	struct bmd_softc *sc = device_lookup_private(&bmd_cd, BMD_UNIT(dev));
25914096cb1Sisaki 
26061f21080Scegger 	DPRINTF(("%s%d\n", __func__, BMD_UNIT(dev)));
26114096cb1Sisaki 
26214096cb1Sisaki 	switch (devtype) {
26314096cb1Sisaki 	case S_IFCHR:
26414096cb1Sisaki 		sc->sc_flags &= ~BMD_OPENCHR;
26514096cb1Sisaki 		break;
26614096cb1Sisaki 	case S_IFBLK:
26714096cb1Sisaki 		sc->sc_flags &= ~BMD_OPENBLK;
26814096cb1Sisaki 		break;
26914096cb1Sisaki 	}
27014096cb1Sisaki 
27114096cb1Sisaki 	return (0);
27214096cb1Sisaki }
27314096cb1Sisaki 
27414096cb1Sisaki void
bmdstrategy(struct buf * bp)27514096cb1Sisaki bmdstrategy(struct buf *bp)
27614096cb1Sisaki {
27714096cb1Sisaki 	int unit = BMD_UNIT(bp->b_dev);
27814096cb1Sisaki 	struct bmd_softc *sc;
27914096cb1Sisaki 	int offset, disksize, resid;
28014096cb1Sisaki 	int page, pg_offset, pg_resid;
28153524e44Schristos 	void *data;
28214096cb1Sisaki 
28314096cb1Sisaki 	if (unit >= bmd_cd.cd_ndevs) {
28414096cb1Sisaki 		bp->b_error = ENXIO;
28566fefd11Sad 		goto done;
28614096cb1Sisaki 	}
28714096cb1Sisaki 
288661719faSisaki 	sc = device_lookup_private(&bmd_cd, BMD_UNIT(bp->b_dev));
28914096cb1Sisaki 	if (sc == NULL) {
29014096cb1Sisaki 		bp->b_error = ENXIO;
29166fefd11Sad 		goto done;
29214096cb1Sisaki 	}
29314096cb1Sisaki 
29482bbbd48Sandvar 	DPRINTF(("bmdstrategy: %s blkno %" PRIx64 " bcount %d:",
29514096cb1Sisaki 		(bp->b_flags & B_READ) ? "read " : "write",
29614096cb1Sisaki 		bp->b_blkno, bp->b_bcount));
29714096cb1Sisaki 
29814096cb1Sisaki 	bp->b_resid = bp->b_bcount;
29914096cb1Sisaki 	offset = (bp->b_blkno << DEV_BSHIFT);
30014096cb1Sisaki 	disksize = sc->sc_maxpage * BMD_PAGESIZE;
30114096cb1Sisaki 	if (offset >= disksize) {
30214096cb1Sisaki 		/* EOF if read, EIO if write */
30314096cb1Sisaki 		if (bp->b_flags & B_READ)
30414096cb1Sisaki 			goto done;
30514096cb1Sisaki 		bp->b_error = EIO;
30666fefd11Sad 		goto done;
30714096cb1Sisaki 	}
30814096cb1Sisaki 
30914096cb1Sisaki 	resid = bp->b_resid;
31014096cb1Sisaki 	if (resid > disksize - offset)
31114096cb1Sisaki 		resid = disksize - offset;
31214096cb1Sisaki 
31314096cb1Sisaki 	data = bp->b_data;
31414096cb1Sisaki 	do {
31514096cb1Sisaki 		page = offset / BMD_PAGESIZE;
31614096cb1Sisaki 		pg_offset = offset % BMD_PAGESIZE;
31714096cb1Sisaki 
31814096cb1Sisaki 		/* length */
31914096cb1Sisaki 		pg_resid = MIN(resid, BMD_PAGESIZE - pg_offset);
32014096cb1Sisaki 
32114096cb1Sisaki 		/* switch bank page */
32214096cb1Sisaki 		bus_space_write_1(sc->sc_iot, sc->sc_ioh, BMD_PAGE, page);
32314096cb1Sisaki 
32414096cb1Sisaki 		/* XXX we should use DMA transfer? */
32514096cb1Sisaki 		if ((bp->b_flags & B_READ)) {
32614096cb1Sisaki 			bus_space_read_region_1(sc->sc_iot, sc->sc_bank,
32714096cb1Sisaki 				pg_offset, data, pg_resid);
32814096cb1Sisaki 		} else {
32914096cb1Sisaki 			bus_space_write_region_1(sc->sc_iot, sc->sc_bank,
33014096cb1Sisaki 				pg_offset, data, pg_resid);
33114096cb1Sisaki 		}
33214096cb1Sisaki 
333f1f47464She 		data = (char *)data + pg_resid;
33414096cb1Sisaki 		offset += pg_resid;
33514096cb1Sisaki 		resid -= pg_resid;
33614096cb1Sisaki 		bp->b_resid -= pg_resid;
33714096cb1Sisaki 	} while (resid > 0);
33814096cb1Sisaki 
33914096cb1Sisaki 	DPRINTF(("\n"));
34014096cb1Sisaki 
34114096cb1Sisaki  done:
34214096cb1Sisaki 	biodone(bp);
34314096cb1Sisaki }
34414096cb1Sisaki 
34514096cb1Sisaki int
bmdioctl(dev_t dev,u_long cmd,void * data,int flag,struct lwp * l)34653524e44Schristos bmdioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
34714096cb1Sisaki {
34814096cb1Sisaki 	struct bmd_softc *sc;
34914096cb1Sisaki 	struct disklabel dl;
35014096cb1Sisaki 	int error;
35114096cb1Sisaki 
35261f21080Scegger 	DPRINTF(("%s%d %ld\n", __func__, BMD_UNIT(dev), cmd));
35314096cb1Sisaki 
354661719faSisaki 	sc = device_lookup_private(&bmd_cd, BMD_UNIT(dev));
355c60db2e9Schristos 
35614096cb1Sisaki 	if (sc == NULL)
35714096cb1Sisaki 		return ENXIO;
35814096cb1Sisaki 
359c60db2e9Schristos 	error = disk_ioctl(&sc->sc_dkdev, dev, cmd, data, flag, l);
360c60db2e9Schristos 	if (error != EPASSTHROUGH)
361c60db2e9Schristos 		return error;
36214096cb1Sisaki 
363c60db2e9Schristos 	switch (cmd) {
36414096cb1Sisaki 	case DIOCWDINFO:
36514096cb1Sisaki 		if ((flag & FWRITE) == 0)
36614096cb1Sisaki 			return EBADF;
36714096cb1Sisaki 
36814096cb1Sisaki 		error = setdisklabel(&dl, (struct disklabel *)data, 0, NULL);
36914096cb1Sisaki 		if (error)
37014096cb1Sisaki 			return error;
37114096cb1Sisaki 		error = writedisklabel(dev, bmdstrategy, &dl, NULL);
37214096cb1Sisaki 		return error;
37314096cb1Sisaki 
37414096cb1Sisaki 	default:
37514096cb1Sisaki 		return EINVAL;
37614096cb1Sisaki 	}
37714096cb1Sisaki 	return 0;
37814096cb1Sisaki }
37914096cb1Sisaki 
38014096cb1Sisaki int
bmddump(dev_t dev,daddr_t blkno,void * va,size_t size)38153524e44Schristos bmddump(dev_t dev, daddr_t blkno, void *va, size_t size)
38214096cb1Sisaki {
38314096cb1Sisaki 
3849b2b412cSperry 	DPRINTF(("%s%d ", __func__, BMD_UNIT(dev)));
38514096cb1Sisaki 	return ENODEV;
38614096cb1Sisaki }
38714096cb1Sisaki 
38814096cb1Sisaki int
bmdsize(dev_t dev)38914096cb1Sisaki bmdsize(dev_t dev)
39014096cb1Sisaki {
39114096cb1Sisaki 	struct bmd_softc *sc;
39214096cb1Sisaki 
39361f21080Scegger 	DPRINTF(("%s%d ", __func__, BMD_UNIT(dev)));
39414096cb1Sisaki 
395661719faSisaki 	sc = device_lookup_private(&bmd_cd, BMD_UNIT(dev));
39614096cb1Sisaki 	if (sc == NULL)
39714096cb1Sisaki 		return 0;
39814096cb1Sisaki 
39914096cb1Sisaki 	return (sc->sc_maxpage * BMD_PAGESIZE) >> DEV_BSHIFT;
40014096cb1Sisaki }
40114096cb1Sisaki 
40214096cb1Sisaki int
bmdread(dev_t dev,struct uio * uio,int ioflag)40314096cb1Sisaki bmdread(dev_t dev, struct uio *uio, int ioflag)
40414096cb1Sisaki {
40514096cb1Sisaki 	return physio(bmdstrategy, NULL, dev, B_READ, minphys, uio);
40614096cb1Sisaki }
40714096cb1Sisaki 
40814096cb1Sisaki int
bmdwrite(dev_t dev,struct uio * uio,int ioflag)40914096cb1Sisaki bmdwrite(dev_t dev, struct uio *uio, int ioflag)
41014096cb1Sisaki {
41114096cb1Sisaki 	return physio(bmdstrategy, NULL, dev, B_WRITE, minphys, uio);
41214096cb1Sisaki }
41314096cb1Sisaki 
41414096cb1Sisaki static int
bmd_getdisklabel(struct bmd_softc * sc,dev_t dev)41514096cb1Sisaki bmd_getdisklabel(struct bmd_softc *sc, dev_t dev)
41614096cb1Sisaki {
41714096cb1Sisaki 	struct disklabel *lp;
41814096cb1Sisaki 	int part;
41914096cb1Sisaki 
42014096cb1Sisaki 	part = DISKPART(dev);
42114096cb1Sisaki 	lp = sc->sc_dkdev.dk_label;
42214096cb1Sisaki 	memset(lp, 0, sizeof(struct disklabel));
42314096cb1Sisaki 
42414096cb1Sisaki 	lp->d_secsize     = BMD_BSIZE;
42514096cb1Sisaki 	lp->d_nsectors    = BLKS_PER_PAGE;
42614096cb1Sisaki 	lp->d_ntracks     = sc->sc_maxpage;
42714096cb1Sisaki 	lp->d_ncylinders  = 1;
42814096cb1Sisaki 	lp->d_secpercyl   = lp->d_nsectors * lp->d_ntracks;
42914096cb1Sisaki 	lp->d_secperunit  = lp->d_secpercyl * lp->d_ncylinders;
43014096cb1Sisaki 
431c182898bSchristos 	lp->d_type        = DKTYPE_LD;
43214096cb1Sisaki 	lp->d_rpm         = 300;	/* dummy */
43314096cb1Sisaki 	lp->d_interleave  = 1;	/* dummy? */
43414096cb1Sisaki 
43514096cb1Sisaki 	lp->d_npartitions = part + 1;
43614096cb1Sisaki 	lp->d_bbsize = 8192;
43714096cb1Sisaki 	lp->d_sbsize = 8192;	/* ? */
43814096cb1Sisaki 
43914096cb1Sisaki 	lp->d_magic       = DISKMAGIC;
44014096cb1Sisaki 	lp->d_magic2      = DISKMAGIC;
44114096cb1Sisaki 	lp->d_checksum    = dkcksum(lp);
44214096cb1Sisaki 
44314096cb1Sisaki 	lp->d_partitions[part].p_size   = lp->d_secperunit;
44414096cb1Sisaki 	lp->d_partitions[part].p_fstype = FS_BSDFFS;
44514096cb1Sisaki 	lp->d_partitions[part].p_fsize  = 1024;
44614096cb1Sisaki 	lp->d_partitions[part].p_frag   = 8;
44714096cb1Sisaki 
44814096cb1Sisaki 	return (0);
44914096cb1Sisaki }
450