1 1.24 tsutsui /* $NetBSD: leo.c,v 1.24 2023/01/06 10:28:28 tsutsui Exp $ */ 2 1.1 leo 3 1.1 leo /*- 4 1.1 leo * Copyright (c) 1997 maximum entropy <entropy (at) zippy.bernstein.com> 5 1.1 leo * Copyright (c) 1997 The NetBSD Foundation, Inc. 6 1.1 leo * All rights reserved. 7 1.1 leo * 8 1.1 leo * Redistribution and use in source and binary forms, with or without 9 1.1 leo * modification, are permitted provided that the following conditions 10 1.1 leo * are met: 11 1.1 leo * 1. Redistributions of source code must retain the above copyright 12 1.1 leo * notice, this list of conditions and the following disclaimer. 13 1.1 leo * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 leo * notice, this list of conditions and the following disclaimer in the 15 1.1 leo * documentation and/or other materials provided with the distribution. 16 1.1 leo * 17 1.1 leo * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 18 1.1 leo * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 1.1 leo * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 1.1 leo * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21 1.1 leo * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 1.1 leo * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 1.1 leo * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 1.1 leo * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 1.1 leo * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 1.1 leo * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 1.1 leo * POSSIBILITY OF SUCH DAMAGE. 28 1.1 leo */ 29 1.1 leo 30 1.1 leo /* 31 1.1 leo * Driver for the Circad Leonardo 1.2 from Lexicor, a 24-bit true color 32 1.1 leo * VME graphics card based on the Texas Instruments TMS34061. 33 1.1 leo * 34 1.1 leo * Written by maximum entropy <entropy (at) zippy.bernstein.com>, December 5, 1997. 35 1.1 leo * 36 1.1 leo * This driver was written from scratch, but I referred to several other 37 1.1 leo * drivers in the NetBSD distribution as examples. The file I referred to 38 1.1 leo * the most was /sys/arch/atari/vme/if_le_vme.c. Due credits: 39 1.1 leo * Copyright (c) 1997 Leo Weppelman. All rights reserved. 40 1.1 leo * Copyright (c) 1995 Charles M. Hannum. All rights reserved. 41 1.1 leo * Copyright (c) 1992, 1993 42 1.1 leo * The Regents of the University of California. All rights reserved. 43 1.1 leo * This code is derived from software contributed to Berkeley by 44 1.24 tsutsui * Ralph Campbell and Rick Macklem. 45 1.1 leo * This product includes software developed by the University of 46 1.1 leo * California, Berkeley and its contributors. 47 1.1 leo */ 48 1.9 lukem 49 1.9 lukem #include <sys/cdefs.h> 50 1.24 tsutsui __KERNEL_RCSID(0, "$NetBSD: leo.c,v 1.24 2023/01/06 10:28:28 tsutsui Exp $"); 51 1.1 leo 52 1.1 leo #include <sys/param.h> 53 1.1 leo #include <sys/systm.h> 54 1.1 leo #include <sys/proc.h> 55 1.1 leo #include <sys/errno.h> 56 1.1 leo #include <sys/device.h> 57 1.1 leo #include <sys/conf.h> 58 1.1 leo #include <sys/ioctl.h> 59 1.1 leo #include <machine/cpu.h> 60 1.19 dyoung #include <sys/bus.h> 61 1.1 leo #include <machine/iomap.h> 62 1.1 leo #include <machine/scu.h> 63 1.1 leo #include <atari/vme/vmevar.h> 64 1.1 leo #include <atari/vme/leovar.h> 65 1.1 leo #include <atari/vme/leoioctl.h> 66 1.1 leo 67 1.17 tsutsui #include "ioconf.h" 68 1.17 tsutsui 69 1.1 leo static struct leo_addresses { 70 1.1 leo u_long reg_addr; 71 1.1 leo u_int reg_size; 72 1.1 leo u_long mem_addr; 73 1.1 leo u_int mem_size; 74 1.1 leo } leostd[] = { 75 1.1 leo { 0xfed90000, 0x100, 0xfec00000, 0x100000 } 76 1.1 leo }; 77 1.1 leo 78 1.1 leo #define NLEOSTD (sizeof(leostd) / sizeof(leostd[0])) 79 1.1 leo 80 1.1 leo struct leo_softc { 81 1.18 tsutsui device_t sc_dev; /* XXX what goes here? */ 82 1.1 leo bus_space_tag_t sc_iot; 83 1.1 leo bus_space_tag_t sc_memt; 84 1.1 leo bus_space_handle_t sc_ioh; 85 1.1 leo bus_space_handle_t sc_memh; 86 1.1 leo int sc_flags; 87 1.1 leo int sc_maddr; 88 1.1 leo u_int sc_msize; 89 1.1 leo }; 90 1.1 leo 91 1.1 leo #define LEO_SC_FLAGS_INUSE 1 92 1.1 leo 93 1.18 tsutsui static int leo_match(device_t, cfdata_t, void *); 94 1.18 tsutsui static void leo_attach(device_t, device_t, void *); 95 1.14 dsl static int leo_probe(bus_space_tag_t *, bus_space_tag_t *, 96 1.1 leo bus_space_handle_t *, bus_space_handle_t *, 97 1.14 dsl u_int, u_int); 98 1.14 dsl static int leo_init(struct leo_softc *, int); 99 1.14 dsl static int leo_scroll(struct leo_softc *, int); 100 1.1 leo 101 1.18 tsutsui CFATTACH_DECL_NEW(leo, sizeof(struct leo_softc), 102 1.7 thorpej leo_match, leo_attach, NULL, NULL); 103 1.1 leo 104 1.23 tsutsui static dev_type_open(leoopen); 105 1.23 tsutsui static dev_type_close(leoclose); 106 1.23 tsutsui static dev_type_read(leomove); 107 1.23 tsutsui static dev_type_ioctl(leoioctl); 108 1.23 tsutsui static dev_type_mmap(leommap); 109 1.4 gehenna 110 1.4 gehenna const struct cdevsw leo_cdevsw = { 111 1.20 dholland .d_open = leoopen, 112 1.20 dholland .d_close = leoclose, 113 1.20 dholland .d_read = leomove, 114 1.20 dholland .d_write = leomove, 115 1.20 dholland .d_ioctl = leoioctl, 116 1.20 dholland .d_stop = nostop, 117 1.20 dholland .d_tty = notty, 118 1.20 dholland .d_poll = nopoll, 119 1.20 dholland .d_mmap = leommap, 120 1.20 dholland .d_kqfilter = nokqfilter, 121 1.21 dholland .d_discard = nodiscard, 122 1.20 dholland .d_flag = 0 123 1.4 gehenna }; 124 1.4 gehenna 125 1.1 leo static int 126 1.18 tsutsui leo_match(device_t parent, cfdata_t cf, void *aux) 127 1.1 leo { 128 1.1 leo struct vme_attach_args *va = aux; 129 1.1 leo int i; 130 1.1 leo bus_space_tag_t iot; 131 1.1 leo bus_space_tag_t memt; 132 1.1 leo bus_space_handle_t ioh; 133 1.1 leo bus_space_handle_t memh; 134 1.1 leo 135 1.1 leo /* 136 1.1 leo * We are passed our configuration in the attachment arguments. 137 1.1 leo * The configuration information may be partially unspecified. 138 1.1 leo * For any unspecified configuration parameters, we fill in those 139 1.1 leo * parameters with data for a "standard" configuration. 140 1.1 leo * Once we have a fully specified configuration, we try to probe 141 1.1 leo * a card with that configuration. 142 1.1 leo * The Leonardo only has one configuration and it isn't likely 143 1.1 leo * to change, but this routine doesn't assume that's the case. 144 1.1 leo */ 145 1.1 leo iot = va->va_iot; 146 1.1 leo memt = va->va_memt; 147 1.1 leo for (i = 0; i < NLEOSTD; i++) { 148 1.1 leo struct leo_addresses *leo_ap = &leostd[i]; 149 1.1 leo int found = 0; 150 1.1 leo struct vme_attach_args vat = *va; 151 1.1 leo 152 1.1 leo if (vat.va_irq != VMECF_IRQ_DEFAULT) { 153 1.1 leo printf("leo_match: config error: no irq support\n"); 154 1.1 leo return 0; 155 1.1 leo } 156 1.1 leo if (vat.va_iobase == VMECF_IOPORT_DEFAULT) 157 1.1 leo vat.va_iobase = leo_ap->reg_addr; 158 1.1 leo if (vat.va_maddr == VMECF_MEM_DEFAULT) 159 1.1 leo vat.va_maddr = leo_ap->mem_addr; 160 1.1 leo if (vat.va_iosize == VMECF_IOSIZE_DEFAULT) 161 1.1 leo vat.va_iosize = leo_ap->reg_size; 162 1.1 leo if (vat.va_msize == VMECF_MEMSIZ_DEFAULT) 163 1.1 leo vat.va_msize = leo_ap->mem_size; 164 1.1 leo if (bus_space_map(iot, vat.va_iobase, vat.va_iosize, 0, &ioh)) { 165 1.1 leo printf("leo_match: cannot map io area\n"); 166 1.1 leo return 0; 167 1.1 leo } 168 1.1 leo if (bus_space_map(memt, vat.va_maddr, vat.va_msize, 169 1.24 tsutsui BUS_SPACE_MAP_LINEAR|BUS_SPACE_MAP_CACHEABLE, 170 1.24 tsutsui &memh)) { 171 1.2 leo bus_space_unmap(iot, ioh, vat.va_iosize); 172 1.1 leo printf("leo_match: cannot map memory area\n"); 173 1.1 leo return 0; 174 1.1 leo } 175 1.1 leo found = leo_probe(&iot, &memt, &ioh, &memh, 176 1.1 leo vat.va_iosize, vat.va_msize); 177 1.2 leo bus_space_unmap(iot, ioh, vat.va_iosize); 178 1.2 leo bus_space_unmap(memt, memh, vat.va_msize); 179 1.1 leo if (found) { 180 1.1 leo *va = vat; 181 1.1 leo return 1; 182 1.1 leo } 183 1.1 leo } 184 1.1 leo return 0; 185 1.1 leo } 186 1.1 leo 187 1.1 leo static int 188 1.16 dsl leo_probe(bus_space_tag_t *iot, bus_space_tag_t *memt, bus_space_handle_t *ioh, bus_space_handle_t *memh, u_int iosize, u_int msize) 189 1.1 leo { 190 1.1 leo 191 1.1 leo /* Test that our highest register is within the io range. */ 192 1.1 leo if (0xca > iosize) /* XXX */ 193 1.1 leo return 0; 194 1.1 leo /* Test if we can peek each register. */ 195 1.1 leo if (!bus_space_peek_1(*iot, *ioh, LEO_REG_MSBSCROLL)) 196 1.1 leo return 0; 197 1.1 leo if (!bus_space_peek_1(*iot, *ioh, LEO_REG_LSBSCROLL)) 198 1.1 leo return 0; 199 1.1 leo /* 200 1.1 leo * Write a test pattern at the start and end of the memory region, 201 1.1 leo * and test if the pattern can be read back. If so, the region is 202 1.1 leo * backed by memory (i.e. the card is present). 203 1.1 leo * On the Leonardo, the first byte of each longword isn't backed by 204 1.1 leo * physical memory, so we only compare the three low-order bytes 205 1.1 leo * with the test pattern. 206 1.1 leo */ 207 1.1 leo bus_space_write_4(*memt, *memh, 0, 0xa5a5a5a5); 208 1.1 leo if ((bus_space_read_4(*memt, *memh, 0) & 0xffffff) != 0xa5a5a5) 209 1.1 leo return 0; 210 1.1 leo bus_space_write_4(*memt, *memh, msize - 4, 0xa5a5a5a5); 211 1.1 leo if ((bus_space_read_4(*memt, *memh, msize - 4) & 0xffffff) 212 1.1 leo != 0xa5a5a5) 213 1.1 leo return 0; 214 1.1 leo return 1; 215 1.1 leo } 216 1.1 leo 217 1.1 leo static void 218 1.18 tsutsui leo_attach(device_t parent, device_t self, void *aux) 219 1.1 leo { 220 1.18 tsutsui struct leo_softc *sc = device_private(self); 221 1.1 leo struct vme_attach_args *va = aux; 222 1.1 leo bus_space_handle_t ioh; 223 1.1 leo bus_space_handle_t memh; 224 1.1 leo #ifndef SET_REGION 225 1.1 leo int i; 226 1.1 leo #endif 227 1.1 leo 228 1.18 tsutsui sc->sc_dev = self; 229 1.18 tsutsui 230 1.1 leo printf("\n"); 231 1.1 leo if (bus_space_map(va->va_iot, va->va_iobase, va->va_iosize, 0, &ioh)) 232 1.5 provos panic("leo_attach: cannot map io area"); 233 1.1 leo if (bus_space_map(va->va_memt, va->va_maddr, va->va_msize, 234 1.1 leo BUS_SPACE_MAP_LINEAR|BUS_SPACE_MAP_CACHEABLE, &memh)) 235 1.5 provos panic("leo_attach: cannot map memory area"); 236 1.1 leo #ifdef SET_REGION /* XXX seems to be unimplemented on atari? */ 237 1.1 leo bus_space_set_region_4(va->va_memt, memh, 0, 0, va->va_msize >> 2); 238 1.1 leo #else 239 1.1 leo for (i = 0; i < (va->va_msize >> 2); i++) 240 1.1 leo bus_space_write_4(va->va_memt, memh, i << 2, 0); 241 1.1 leo #endif 242 1.1 leo sc->sc_iot = va->va_iot; 243 1.1 leo sc->sc_ioh = ioh; 244 1.1 leo sc->sc_memt = va->va_memt; 245 1.1 leo sc->sc_memh = memh; 246 1.1 leo sc->sc_flags = 0; 247 1.1 leo sc->sc_maddr = va->va_maddr; 248 1.1 leo sc->sc_msize = va->va_msize; 249 1.1 leo leo_init(sc, 512); 250 1.1 leo leo_scroll(sc, 0); 251 1.1 leo } 252 1.1 leo 253 1.1 leo int 254 1.18 tsutsui leoopen(dev_t dev, int flags, int devtype, struct lwp *l) 255 1.1 leo { 256 1.1 leo struct leo_softc *sc; 257 1.1 leo int r; 258 1.1 leo 259 1.13 cegger sc = device_lookup_private(&leo_cd, minor(dev)); 260 1.1 leo if (!sc) 261 1.1 leo return ENXIO; 262 1.1 leo if (sc->sc_flags & LEO_SC_FLAGS_INUSE) 263 1.1 leo return EBUSY; 264 1.1 leo r = leo_init(sc, 512); 265 1.1 leo if (r != 0) 266 1.1 leo return r; 267 1.1 leo r = leo_scroll(sc, 0); 268 1.1 leo if (r != 0) 269 1.1 leo return r; 270 1.1 leo sc->sc_flags |= LEO_SC_FLAGS_INUSE; 271 1.1 leo return 0; 272 1.1 leo } 273 1.1 leo 274 1.1 leo static int 275 1.15 dsl leo_init(struct leo_softc *sc, int ysize) 276 1.1 leo { 277 1.1 leo 278 1.1 leo if ((ysize != 256) && (ysize != 384) && (ysize != 512)) 279 1.1 leo return EINVAL; 280 1.1 leo /* XXX */ 281 1.1 leo bus_space_write_2(sc->sc_iot, sc->sc_ioh, 0x00, 0x6); 282 1.1 leo bus_space_write_2(sc->sc_iot, sc->sc_ioh, 0x08, 0x0); 283 1.1 leo if (ysize == 384) 284 1.1 leo bus_space_write_2(sc->sc_iot, sc->sc_ioh, 0x10, 0x10); 285 1.1 leo else 286 1.1 leo bus_space_write_2(sc->sc_iot, sc->sc_ioh, 0x10, 0x11); 287 1.1 leo bus_space_write_2(sc->sc_iot, sc->sc_ioh, 0x18, 0x0); 288 1.1 leo if (ysize == 384) 289 1.1 leo bus_space_write_2(sc->sc_iot, sc->sc_ioh, 0x20, 0x50); 290 1.1 leo else 291 1.1 leo bus_space_write_2(sc->sc_iot, sc->sc_ioh, 0x20, 0x51); 292 1.1 leo bus_space_write_2(sc->sc_iot, sc->sc_ioh, 0x28, 0x0); 293 1.1 leo if (ysize == 384) 294 1.1 leo bus_space_write_2(sc->sc_iot, sc->sc_ioh, 0x30, 0x56); 295 1.1 leo else 296 1.1 leo bus_space_write_2(sc->sc_iot, sc->sc_ioh, 0x30, 0x57); 297 1.1 leo bus_space_write_2(sc->sc_iot, sc->sc_ioh, 0x38, 0x0); 298 1.1 leo bus_space_write_2(sc->sc_iot, sc->sc_ioh, 0x40, 0x6); 299 1.1 leo bus_space_write_2(sc->sc_iot, sc->sc_ioh, 0x48, 0x0); 300 1.1 leo bus_space_write_2(sc->sc_iot, sc->sc_ioh, 0x50, 0x25); 301 1.1 leo bus_space_write_2(sc->sc_iot, sc->sc_ioh, 0x58, 0x0); 302 1.1 leo if (ysize == 256) { 303 1.1 leo bus_space_write_2(sc->sc_iot, sc->sc_ioh, 0x60, 0x1f); 304 1.1 leo bus_space_write_2(sc->sc_iot, sc->sc_ioh, 0x68, 0x1); 305 1.1 leo bus_space_write_2(sc->sc_iot, sc->sc_ioh, 0x70, 0x29); 306 1.1 leo bus_space_write_2(sc->sc_iot, sc->sc_ioh, 0x78, 0x1); 307 1.1 leo } else if (ysize == 384) { 308 1.1 leo bus_space_write_2(sc->sc_iot, sc->sc_ioh, 0x60, 0xa5); 309 1.1 leo bus_space_write_2(sc->sc_iot, sc->sc_ioh, 0x68, 0x1); 310 1.1 leo bus_space_write_2(sc->sc_iot, sc->sc_ioh, 0x70, 0xa7); 311 1.1 leo bus_space_write_2(sc->sc_iot, sc->sc_ioh, 0x78, 0x1); 312 1.1 leo } else { 313 1.1 leo bus_space_write_2(sc->sc_iot, sc->sc_ioh, 0x60, 0x1d); 314 1.1 leo bus_space_write_2(sc->sc_iot, sc->sc_ioh, 0x68, 0x2); 315 1.1 leo bus_space_write_2(sc->sc_iot, sc->sc_ioh, 0x70, 0x27); 316 1.1 leo bus_space_write_2(sc->sc_iot, sc->sc_ioh, 0x78, 0x2); 317 1.1 leo } 318 1.1 leo bus_space_write_2(sc->sc_iot, sc->sc_ioh, 0xb8, 0x10); 319 1.1 leo bus_space_write_2(sc->sc_iot, sc->sc_ioh, 0xb0, 0x10); 320 1.1 leo bus_space_write_2(sc->sc_iot, sc->sc_ioh, 0x80, 0x4); 321 1.1 leo if (ysize == 384) 322 1.1 leo bus_space_write_2(sc->sc_iot, sc->sc_ioh, 0xc8, 0x21); 323 1.1 leo else 324 1.1 leo bus_space_write_2(sc->sc_iot, sc->sc_ioh, 0xc8, 0x20); 325 1.1 leo bus_space_write_2(sc->sc_iot, sc->sc_ioh, 0xc0, 0x40); 326 1.1 leo return 0; 327 1.1 leo } 328 1.1 leo 329 1.1 leo static int 330 1.15 dsl leo_scroll(struct leo_softc *sc, int scroll) 331 1.1 leo { 332 1.1 leo 333 1.1 leo if ((scroll < 0) || (scroll > 255)) 334 1.1 leo return EINVAL; 335 1.24 tsutsui bus_space_write_1(sc->sc_iot, sc->sc_ioh, LEO_REG_MSBSCROLL, 336 1.22 christos (scroll >> 6) & 0xff); 337 1.24 tsutsui bus_space_write_1(sc->sc_iot, sc->sc_ioh, LEO_REG_LSBSCROLL, 338 1.22 christos (scroll << 2) & 0xff); 339 1.1 leo return 0; 340 1.1 leo } 341 1.1 leo 342 1.1 leo int 343 1.18 tsutsui leoclose(dev_t dev, int flags, int devtype, struct lwp *l) 344 1.1 leo { 345 1.1 leo struct leo_softc *sc; 346 1.1 leo 347 1.13 cegger sc = device_lookup_private(&leo_cd, minor(dev)); 348 1.1 leo sc->sc_flags &= ~LEO_SC_FLAGS_INUSE; 349 1.1 leo return 0; 350 1.1 leo } 351 1.1 leo 352 1.1 leo #define SMALLBSIZE 32 353 1.1 leo 354 1.4 gehenna int 355 1.13 cegger leomove(dev_t dev, struct uio *uio, int flags) 356 1.1 leo { 357 1.24 tsutsui struct leo_softc *sc; 358 1.24 tsutsui int length, size, error; 359 1.24 tsutsui u_int8_t smallbuf[SMALLBSIZE]; 360 1.1 leo off_t offset; 361 1.1 leo 362 1.24 tsutsui sc = device_lookup_private(&leo_cd,minor(dev)); 363 1.24 tsutsui if (uio->uio_offset > sc->sc_msize) 364 1.24 tsutsui return 0; 365 1.24 tsutsui length = sc->sc_msize - uio->uio_offset; 366 1.24 tsutsui if (length > uio->uio_resid) 367 1.24 tsutsui length = uio->uio_resid; 368 1.24 tsutsui while (length > 0) { 369 1.24 tsutsui size = length; 370 1.24 tsutsui if (size > SMALLBSIZE) 371 1.24 tsutsui size = SMALLBSIZE; 372 1.24 tsutsui length -= size; 373 1.1 leo offset = uio->uio_offset; 374 1.24 tsutsui if (uio->uio_rw == UIO_READ) 375 1.24 tsutsui bus_space_read_region_1(sc->sc_memt, sc->sc_memh, 376 1.24 tsutsui offset, smallbuf, size); 377 1.24 tsutsui if ((error = uiomove((void *)smallbuf, size, uio))) 378 1.24 tsutsui return (error); 379 1.24 tsutsui if (uio->uio_rw == UIO_WRITE) 380 1.24 tsutsui bus_space_write_region_1(sc->sc_memt, sc->sc_memh, 381 1.24 tsutsui offset, smallbuf, size); 382 1.24 tsutsui } 383 1.24 tsutsui return 0; 384 1.1 leo } 385 1.1 leo 386 1.1 leo int 387 1.18 tsutsui leoioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) 388 1.1 leo { 389 1.1 leo struct leo_softc *sc; 390 1.1 leo 391 1.13 cegger sc = device_lookup_private(&leo_cd,minor(dev)); 392 1.24 tsutsui switch (cmd) { 393 1.24 tsutsui case LIOCYRES: 394 1.1 leo return leo_init(sc, *(int *)data); 395 1.1 leo break; 396 1.24 tsutsui case LIOCSCRL: 397 1.1 leo return leo_scroll(sc, *(int *)data); 398 1.1 leo break; 399 1.1 leo default: 400 1.1 leo return EINVAL; 401 1.1 leo break; 402 1.1 leo } 403 1.1 leo } 404 1.1 leo 405 1.3 simonb paddr_t 406 1.13 cegger leommap(dev_t dev, off_t offset, int prot) 407 1.1 leo { 408 1.1 leo struct leo_softc *sc; 409 1.1 leo 410 1.13 cegger sc = device_lookup_private(&leo_cd, minor(dev)); 411 1.1 leo if (offset >= 0 && offset < sc->sc_msize) 412 1.1 leo return m68k_btop(sc->sc_maddr + offset); 413 1.1 leo return -1; 414 1.1 leo } 415