1 /* $NetBSD: leo.c,v 1.15 2009/03/14 15:36:04 dsl Exp $ */
4 * Copyright (c) 1997 maximum entropy <entropy@zippy.bernstein.com>
5 * Copyright (c) 1997 The NetBSD Foundation, Inc.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
31 * Driver for the Circad Leonardo 1.2 from Lexicor, a 24-bit true color
32 * VME graphics card based on the Texas Instruments TMS34061.
34 * Written by maximum entropy <entropy@zippy.bernstein.com>, December 5, 1997.
36 * This driver was written from scratch, but I referred to several other
37 * drivers in the NetBSD distribution as examples. The file I referred to
38 * the most was /sys/arch/atari/vme/if_le_vme.c. Due credits:
39 * Copyright (c) 1997 Leo Weppelman. All rights reserved.
40 * Copyright (c) 1995 Charles M. Hannum. All rights reserved.
41 * Copyright (c) 1992, 1993
42 * The Regents of the University of California. All rights reserved.
43 * This code is derived from software contributed to Berkeley by
44 * Ralph Campbell and Rick Macklem.
45 * This product includes software developed by the University of
46 * California, Berkeley and its contributors.
49 #include <sys/cdefs.h>
50 __KERNEL_RCSID(0, "$NetBSD: leo.c,v 1.15 2009/03/14 15:36:04 dsl Exp $");
52 #include <sys/param.h>
53 #include <sys/systm.h>
55 #include <sys/errno.h>
56 #include <sys/device.h>
58 #include <sys/ioctl.h>
59 #include <machine/cpu.h>
60 #include <machine/bus.h>
61 #include <machine/iomap.h>
62 #include <machine/scu.h>
63 #include <atari/vme/vmevar.h>
64 #include <atari/vme/leovar.h>
65 #include <atari/vme/leoioctl.h>
67 static struct leo_addresses
{
73 { 0xfed90000, 0x100, 0xfec00000, 0x100000 }
76 #define NLEOSTD (sizeof(leostd) / sizeof(leostd[0]))
79 struct device sc_dev
; /* XXX what goes here? */
80 bus_space_tag_t sc_iot
;
81 bus_space_tag_t sc_memt
;
82 bus_space_handle_t sc_ioh
;
83 bus_space_handle_t sc_memh
;
89 #define LEO_SC_FLAGS_INUSE 1
91 static int leo_match(struct device
*, struct cfdata
*, void *);
92 static void leo_attach(struct device
*, struct device
*, void *);
93 static int leo_probe(bus_space_tag_t
*, bus_space_tag_t
*,
94 bus_space_handle_t
*, bus_space_handle_t
*,
96 static int leo_init(struct leo_softc
*, int);
97 static int leo_scroll(struct leo_softc
*, int);
99 CFATTACH_DECL(leo
, sizeof(struct leo_softc
),
100 leo_match
, leo_attach
, NULL
, NULL
);
102 extern struct cfdriver leo_cd
;
104 dev_type_open(leoopen
);
105 dev_type_close(leoclose
);
106 dev_type_read(leomove
);
107 dev_type_ioctl(leoioctl
);
108 dev_type_mmap(leommap
);
110 const struct cdevsw leo_cdevsw
= {
111 leoopen
, leoclose
, leomove
, leomove
, leoioctl
,
112 nostop
, notty
, nopoll
, leommap
, nokqfilter
,
116 leo_match(struct device
*parent
, struct cfdata
*cfp
, void *aux
)
118 struct vme_attach_args
*va
= aux
;
121 bus_space_tag_t memt
;
122 bus_space_handle_t ioh
;
123 bus_space_handle_t memh
;
126 * We are passed our configuration in the attachment arguments.
127 * The configuration information may be partially unspecified.
128 * For any unspecified configuration parameters, we fill in those
129 * parameters with data for a "standard" configuration.
130 * Once we have a fully specified configuration, we try to probe
131 * a card with that configuration.
132 * The Leonardo only has one configuration and it isn't likely
133 * to change, but this routine doesn't assume that's the case.
137 for (i
= 0; i
< NLEOSTD
; i
++) {
138 struct leo_addresses
*leo_ap
= &leostd
[i
];
140 struct vme_attach_args vat
= *va
;
142 if (vat
.va_irq
!= VMECF_IRQ_DEFAULT
) {
143 printf("leo_match: config error: no irq support\n");
146 if (vat
.va_iobase
== VMECF_IOPORT_DEFAULT
)
147 vat
.va_iobase
= leo_ap
->reg_addr
;
148 if (vat
.va_maddr
== VMECF_MEM_DEFAULT
)
149 vat
.va_maddr
= leo_ap
->mem_addr
;
150 if (vat
.va_iosize
== VMECF_IOSIZE_DEFAULT
)
151 vat
.va_iosize
= leo_ap
->reg_size
;
152 if (vat
.va_msize
== VMECF_MEMSIZ_DEFAULT
)
153 vat
.va_msize
= leo_ap
->mem_size
;
154 if (bus_space_map(iot
, vat
.va_iobase
, vat
.va_iosize
, 0, &ioh
)) {
155 printf("leo_match: cannot map io area\n");
158 if (bus_space_map(memt
, vat
.va_maddr
, vat
.va_msize
,
159 BUS_SPACE_MAP_LINEAR
|BUS_SPACE_MAP_CACHEABLE
,
161 bus_space_unmap(iot
, ioh
, vat
.va_iosize
);
162 printf("leo_match: cannot map memory area\n");
165 found
= leo_probe(&iot
, &memt
, &ioh
, &memh
,
166 vat
.va_iosize
, vat
.va_msize
);
167 bus_space_unmap(iot
, ioh
, vat
.va_iosize
);
168 bus_space_unmap(memt
, memh
, vat
.va_msize
);
178 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
)
181 /* Test that our highest register is within the io range. */
182 if (0xca > iosize
) /* XXX */
184 /* Test if we can peek each register. */
185 if (!bus_space_peek_1(*iot
, *ioh
, LEO_REG_MSBSCROLL
))
187 if (!bus_space_peek_1(*iot
, *ioh
, LEO_REG_LSBSCROLL
))
190 * Write a test pattern at the start and end of the memory region,
191 * and test if the pattern can be read back. If so, the region is
192 * backed by memory (i.e. the card is present).
193 * On the Leonardo, the first byte of each longword isn't backed by
194 * physical memory, so we only compare the three low-order bytes
195 * with the test pattern.
197 bus_space_write_4(*memt
, *memh
, 0, 0xa5a5a5a5);
198 if ((bus_space_read_4(*memt
, *memh
, 0) & 0xffffff) != 0xa5a5a5)
200 bus_space_write_4(*memt
, *memh
, msize
- 4, 0xa5a5a5a5);
201 if ((bus_space_read_4(*memt
, *memh
, msize
- 4) & 0xffffff)
208 leo_attach(struct device
*parent
, struct device
*self
, void *aux
)
210 struct leo_softc
*sc
= (struct leo_softc
*)self
;
211 struct vme_attach_args
*va
= aux
;
212 bus_space_handle_t ioh
;
213 bus_space_handle_t memh
;
219 if (bus_space_map(va
->va_iot
, va
->va_iobase
, va
->va_iosize
, 0, &ioh
))
220 panic("leo_attach: cannot map io area");
221 if (bus_space_map(va
->va_memt
, va
->va_maddr
, va
->va_msize
,
222 BUS_SPACE_MAP_LINEAR
|BUS_SPACE_MAP_CACHEABLE
, &memh
))
223 panic("leo_attach: cannot map memory area");
224 #ifdef SET_REGION /* XXX seems to be unimplemented on atari? */
225 bus_space_set_region_4(va
->va_memt
, memh
, 0, 0, va
->va_msize
>> 2);
227 for (i
= 0; i
< (va
->va_msize
>> 2); i
++)
228 bus_space_write_4(va
->va_memt
, memh
, i
<< 2, 0);
230 sc
->sc_iot
= va
->va_iot
;
232 sc
->sc_memt
= va
->va_memt
;
235 sc
->sc_maddr
= va
->va_maddr
;
236 sc
->sc_msize
= va
->va_msize
;
242 leoopen(dev_t dev
, int flags
, int devtype
, struct proc
*p
)
244 struct leo_softc
*sc
;
247 sc
= device_lookup_private(&leo_cd
, minor(dev
));
250 if (sc
->sc_flags
& LEO_SC_FLAGS_INUSE
)
252 r
= leo_init(sc
, 512);
255 r
= leo_scroll(sc
, 0);
258 sc
->sc_flags
|= LEO_SC_FLAGS_INUSE
;
263 leo_init(struct leo_softc
*sc
, int ysize
)
266 if ((ysize
!= 256) && (ysize
!= 384) && (ysize
!= 512))
269 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, 0x00, 0x6);
270 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, 0x08, 0x0);
272 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, 0x10, 0x10);
274 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, 0x10, 0x11);
275 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, 0x18, 0x0);
277 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, 0x20, 0x50);
279 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, 0x20, 0x51);
280 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, 0x28, 0x0);
282 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, 0x30, 0x56);
284 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, 0x30, 0x57);
285 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, 0x38, 0x0);
286 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, 0x40, 0x6);
287 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, 0x48, 0x0);
288 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, 0x50, 0x25);
289 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, 0x58, 0x0);
291 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, 0x60, 0x1f);
292 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, 0x68, 0x1);
293 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, 0x70, 0x29);
294 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, 0x78, 0x1);
295 } else if (ysize
== 384) {
296 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, 0x60, 0xa5);
297 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, 0x68, 0x1);
298 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, 0x70, 0xa7);
299 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, 0x78, 0x1);
301 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, 0x60, 0x1d);
302 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, 0x68, 0x2);
303 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, 0x70, 0x27);
304 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, 0x78, 0x2);
306 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, 0xb8, 0x10);
307 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, 0xb0, 0x10);
308 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, 0x80, 0x4);
310 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, 0xc8, 0x21);
312 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, 0xc8, 0x20);
313 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, 0xc0, 0x40);
318 leo_scroll(struct leo_softc
*sc
, int scroll
)
321 if ((scroll
< 0) || (scroll
> 255))
323 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, LEO_REG_MSBSCROLL
,
324 (scroll
>> 6) && 0xff);
325 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, LEO_REG_LSBSCROLL
,
326 (scroll
<< 2) && 0xff);
331 leoclose(dev_t dev
, int flags
, int devtype
, struct proc
*p
)
333 struct leo_softc
*sc
;
335 sc
= device_lookup_private(&leo_cd
, minor(dev
));
336 sc
->sc_flags
&= ~LEO_SC_FLAGS_INUSE
;
340 #define SMALLBSIZE 32
343 leomove(dev_t dev
, struct uio
*uio
, int flags
)
345 struct leo_softc
*sc
;
346 int length
, size
, error
;
347 u_int8_t smallbuf
[SMALLBSIZE
];
350 sc
= device_lookup_private(&leo_cd
,minor(dev
));
351 if (uio
->uio_offset
> sc
->sc_msize
)
353 length
= sc
->sc_msize
- uio
->uio_offset
;
354 if (length
> uio
->uio_resid
)
355 length
= uio
->uio_resid
;
358 if (size
> SMALLBSIZE
)
361 offset
= uio
->uio_offset
;
362 if (uio
->uio_rw
== UIO_READ
)
363 bus_space_read_region_1(sc
->sc_memt
, sc
->sc_memh
,
364 offset
, smallbuf
, size
);
365 if ((error
= uiomove((void *)smallbuf
, size
, uio
)))
367 if (uio
->uio_rw
== UIO_WRITE
)
368 bus_space_write_region_1(sc
->sc_memt
, sc
->sc_memh
,
369 offset
, smallbuf
, size
);
375 leoioctl(dev_t dev
, u_long cmd
, void *data
, int flags
, struct proc
*p
)
377 struct leo_softc
*sc
;
379 sc
= device_lookup_private(&leo_cd
,minor(dev
));
382 return leo_init(sc
, *(int *)data
);
385 return leo_scroll(sc
, *(int *)data
);
394 leommap(dev_t dev
, off_t offset
, int prot
)
396 struct leo_softc
*sc
;
398 sc
= device_lookup_private(&leo_cd
, minor(dev
));
399 if (offset
>= 0 && offset
< sc
->sc_msize
)
400 return m68k_btop(sc
->sc_maddr
+ offset
);