gten.c revision 1.1 1 1.1 matt /* $NetBSD: gten.c,v 1.1 2000/12/01 21:54:01 matt Exp $ */
2 1.1 matt
3 1.1 matt #include <sys/param.h>
4 1.1 matt #include <sys/buf.h>
5 1.1 matt #include <sys/conf.h>
6 1.1 matt #include <sys/device.h>
7 1.1 matt #include <sys/ioctl.h>
8 1.1 matt #include <sys/kernel.h>
9 1.1 matt #include <sys/malloc.h>
10 1.1 matt #include <sys/systm.h>
11 1.1 matt
12 1.1 matt #include <uvm/uvm_extern.h>
13 1.1 matt
14 1.1 matt #include <dev/pci/pcidevs.h>
15 1.1 matt #include <dev/pci/pcireg.h>
16 1.1 matt #include <dev/pci/pcivar.h>
17 1.1 matt
18 1.1 matt #include <dev/wscons/wsconsio.h>
19 1.1 matt #include <dev/wscons/wsdisplayvar.h>
20 1.1 matt #include <dev/rasops/rasops.h>
21 1.1 matt
22 1.1 matt #include <machine/bus.h>
23 1.1 matt #include <machine/gtenvar.h>
24 1.1 matt
25 1.1 matt int gten_match (struct device *, struct cfdata *, void *);
26 1.1 matt void gten_attach (struct device *, struct device *, void *);
27 1.1 matt int gten_print (void *, const char *);
28 1.1 matt
29 1.1 matt struct cfattach gten_ca = {
30 1.1 matt sizeof(struct gten_softc), gten_match, gten_attach,
31 1.1 matt };
32 1.1 matt
33 1.1 matt static struct rasops_info gten_console_ri;
34 1.1 matt static pcitag_t gten_console_pcitag;
35 1.1 matt
36 1.1 matt static struct wsscreen_descr gten_stdscreen = {
37 1.1 matt "std",
38 1.1 matt 0, 0,
39 1.1 matt 0,
40 1.1 matt 0, 0,
41 1.1 matt WSSCREEN_REVERSE
42 1.1 matt };
43 1.1 matt
44 1.1 matt static const struct wsscreen_descr *_gten_scrlist[] = {
45 1.1 matt >en_stdscreen,
46 1.1 matt /* XXX other formats, graphics screen? */
47 1.1 matt };
48 1.1 matt
49 1.1 matt static struct wsscreen_list gten_screenlist = {
50 1.1 matt sizeof(_gten_scrlist) / sizeof(struct wsscreen_descr *), _gten_scrlist
51 1.1 matt };
52 1.1 matt
53 1.1 matt static int gten_ioctl (void *, u_long, caddr_t, int, struct proc *);
54 1.1 matt static paddr_t gten_mmap (void *, off_t, int);
55 1.1 matt static int gten_alloc_screen (void *, const struct wsscreen_descr *,
56 1.1 matt void **, int *, int *, long *);
57 1.1 matt static void gten_free_screen (void *, void *);
58 1.1 matt static int gten_show_screen (void *, void *, int,
59 1.1 matt void (*) (void *, int, int), void *);
60 1.1 matt
61 1.1 matt struct wsdisplay_accessops gten_accessops = {
62 1.1 matt gten_ioctl,
63 1.1 matt gten_mmap,
64 1.1 matt gten_alloc_screen,
65 1.1 matt gten_free_screen,
66 1.1 matt gten_show_screen,
67 1.1 matt 0 /* load_font */
68 1.1 matt };
69 1.1 matt
70 1.1 matt static void gten_common_init (struct rasops_info *);
71 1.1 matt static int gten_getcmap (struct gten_softc *, struct wsdisplay_cmap *);
72 1.1 matt static int gten_putcmap (struct gten_softc *, struct wsdisplay_cmap *);
73 1.1 matt
74 1.1 matt int
75 1.1 matt gten_match(struct device *parent, struct cfdata *match, void *aux)
76 1.1 matt {
77 1.1 matt struct pci_attach_args *pa = aux;
78 1.1 matt
79 1.1 matt if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_WD &&
80 1.1 matt PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_WD_90C)
81 1.1 matt return 2;
82 1.1 matt
83 1.1 matt return 0;
84 1.1 matt }
85 1.1 matt
86 1.1 matt void
87 1.1 matt gten_attach(struct device *parent, struct device *self, void *aux)
88 1.1 matt {
89 1.1 matt struct gten_softc *gt = (struct gten_softc *)self;
90 1.1 matt struct pci_attach_args *pa = aux;
91 1.1 matt struct wsemuldisplaydev_attach_args a;
92 1.1 matt int console = (pa->pa_tag == gten_console_pcitag);
93 1.1 matt int error;
94 1.1 matt char devinfo[256], pbuf[10];
95 1.1 matt
96 1.1 matt error = pci_mapreg_info(pa->pa_pc, pa->pa_tag, 0x14,
97 1.1 matt PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT,
98 1.1 matt >->gt_memaddr, >->gt_memsize, NULL);
99 1.1 matt if (error) {
100 1.1 matt printf(": can't determine memory size: error=%d\n",
101 1.1 matt error);
102 1.1 matt return;
103 1.1 matt }
104 1.1 matt if (console) {
105 1.1 matt gt->gt_ri = >en_console_ri;
106 1.1 matt gt->gt_nscreens = 1;
107 1.1 matt } else {
108 1.1 matt MALLOC(gt->gt_ri, struct rasops_info *, sizeof(*gt->gt_ri),
109 1.1 matt M_DEVBUF, M_NOWAIT);
110 1.1 matt if (gt->gt_ri == NULL) {
111 1.1 matt printf(": can't alloc memory\n");
112 1.1 matt return;
113 1.1 matt }
114 1.1 matt memset(gt->gt_ri, 0, sizeof(*gt->gt_ri));
115 1.1 matt #if 0
116 1.1 matt error = pci_mapreg_map(pa, 0x14,
117 1.1 matt PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT,
118 1.1 matt BUS_SPACE_MAP_LINEAR, NULL,
119 1.1 matt (bus_space_handle_t *) >->gt_ri->ri_bits,
120 1.1 matt NULL, NULL);
121 1.1 matt #else
122 1.1 matt error = bus_space_map(pa->pa_memt, gt->gt_memaddr + 0xef9000,
123 1.1 matt 1024*1024, BUS_SPACE_MAP_LINEAR,
124 1.1 matt (bus_space_handle_t *) >->gt_ri->ri_bits);
125 1.1 matt #endif
126 1.1 matt if (error) {
127 1.1 matt printf(": can't map frame buffer: error=%d\n", error);
128 1.1 matt return;
129 1.1 matt }
130 1.1 matt
131 1.1 matt gten_common_init(gt->gt_ri);
132 1.1 matt
133 1.1 matt #if 0
134 1.1 matt int i, len, screenbytes;
135 1.1 matt screenbytes = ri->ri_stride * ri->ri_height;
136 1.1 matt for (i = 0; i < screenbytes; i += sizeof(u_int32_t))
137 1.1 matt *(u_int32_t *)(gt->gt_ri->ri_bits + i) = 0xffffffff;
138 1.1 matt #endif
139 1.1 matt }
140 1.1 matt
141 1.1 matt gt->gt_paddr = vtophys((vaddr_t)gt->gt_ri->ri_bits);
142 1.1 matt if (gt->gt_paddr == 0) {
143 1.1 matt printf(": cannot map framebuffer\n");
144 1.1 matt return;
145 1.1 matt }
146 1.1 matt
147 1.1 matt pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo);
148 1.1 matt printf(": %s\n", devinfo);
149 1.1 matt format_bytes(pbuf, sizeof(pbuf), gt->gt_memsize);
150 1.1 matt printf("%s: %s, %d x %d, %dbpp\n", self->dv_xname, pbuf,
151 1.1 matt gt->gt_ri->ri_width, gt->gt_ri->ri_height, gt->gt_ri->ri_depth);
152 1.1 matt
153 1.1 matt gt->gt_cmap_red[0] = gt->gt_cmap_green[0] = gt->gt_cmap_blue[0] = 0;
154 1.1 matt gt->gt_cmap_red[15] = gt->gt_cmap_red[255] = 0xff;
155 1.1 matt gt->gt_cmap_green[15] = gt->gt_cmap_green[255] = 0xff;
156 1.1 matt gt->gt_cmap_blue[15] = gt->gt_cmap_blue[255] = 0xff;
157 1.1 matt
158 1.1 matt a.console = console;
159 1.1 matt a.scrdata = >en_screenlist;
160 1.1 matt a.accessops = >en_accessops;
161 1.1 matt a.accesscookie = gt;
162 1.1 matt
163 1.1 matt config_found(self, &a, wsemuldisplaydevprint);
164 1.1 matt }
165 1.1 matt
166 1.1 matt static void
167 1.1 matt gten_common_init(struct rasops_info *ri)
168 1.1 matt {
169 1.1 matt int32_t addr, width, height, linebytes, depth;
170 1.1 matt int i, screenbytes;
171 1.1 matt
172 1.1 matt /* initialize rasops */
173 1.1 matt ri->ri_width = 640;
174 1.1 matt ri->ri_height = 480;
175 1.1 matt ri->ri_depth = 8;
176 1.1 matt ri->ri_stride = 640;
177 1.1 matt ri->ri_flg = RI_FORCEMONO | RI_FULLCLEAR | RI_CENTER;
178 1.1 matt
179 1.1 matt rasops_init(ri, 24, 80);
180 1.1 matt /* black on white */
181 1.1 matt ri->ri_devcmap[0] = 0xffffffff; /* bg */
182 1.1 matt ri->ri_devcmap[1] = 0; /* fg */
183 1.1 matt
184 1.1 matt gten_stdscreen.nrows = ri->ri_rows;
185 1.1 matt gten_stdscreen.ncols = ri->ri_cols;
186 1.1 matt gten_stdscreen.textops = &ri->ri_ops;
187 1.1 matt gten_stdscreen.capabilities = ri->ri_caps;
188 1.1 matt
189 1.1 matt screenbytes = ri->ri_stride * ri->ri_height;
190 1.1 matt for (i = 0; i < screenbytes; i += sizeof(u_int32_t))
191 1.1 matt *(u_int32_t *)(ri->ri_bits + i) = 0xffffffff;
192 1.1 matt }
193 1.1 matt
194 1.1 matt int
195 1.1 matt gten_ioctl(v, cmd, data, flag, p)
196 1.1 matt void *v;
197 1.1 matt u_long cmd;
198 1.1 matt caddr_t data;
199 1.1 matt int flag;
200 1.1 matt struct proc *p;
201 1.1 matt {
202 1.1 matt struct gten_softc *gt = v;
203 1.1 matt struct wsdisplay_fbinfo *wdf;
204 1.1 matt struct grfinfo *gm;
205 1.1 matt
206 1.1 matt switch (cmd) {
207 1.1 matt case WSDISPLAYIO_GTYPE:
208 1.1 matt *(u_int *)data = WSDISPLAY_TYPE_PCIMISC; /* XXX ? */
209 1.1 matt return 0;
210 1.1 matt
211 1.1 matt case WSDISPLAYIO_GINFO:
212 1.1 matt wdf = (void *)data;
213 1.1 matt wdf->height = gt->gt_ri->ri_height;
214 1.1 matt wdf->width = gt->gt_ri->ri_width;
215 1.1 matt wdf->depth = gt->gt_ri->ri_depth;
216 1.1 matt wdf->cmsize = 256;
217 1.1 matt return 0;
218 1.1 matt
219 1.1 matt case WSDISPLAYIO_GETCMAP:
220 1.1 matt return gten_getcmap(gt, (struct wsdisplay_cmap *)data);
221 1.1 matt
222 1.1 matt case WSDISPLAYIO_PUTCMAP:
223 1.1 matt return gten_putcmap(gt, (struct wsdisplay_cmap *)data);
224 1.1 matt }
225 1.1 matt return -1;
226 1.1 matt }
227 1.1 matt
228 1.1 matt paddr_t
229 1.1 matt gten_mmap(v, offset, prot)
230 1.1 matt void *v;
231 1.1 matt off_t offset;
232 1.1 matt int prot;
233 1.1 matt {
234 1.1 matt struct gten_softc *gt = v;
235 1.1 matt
236 1.1 matt if (offset >=0 && offset < gt->gt_memsize)
237 1.1 matt return gt->gt_paddr + offset;
238 1.1 matt
239 1.1 matt return -1;
240 1.1 matt }
241 1.1 matt
242 1.1 matt int
243 1.1 matt gten_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
244 1.1 matt void *v;
245 1.1 matt const struct wsscreen_descr *type;
246 1.1 matt void **cookiep;
247 1.1 matt int *curxp, *curyp;
248 1.1 matt long *attrp;
249 1.1 matt {
250 1.1 matt struct gten_softc *gt = v;
251 1.1 matt struct rasops_info *ri = gt->gt_ri;
252 1.1 matt long defattr;
253 1.1 matt
254 1.1 matt if (gt->gt_nscreens > 0)
255 1.1 matt return (ENOMEM);
256 1.1 matt
257 1.1 matt *cookiep = ri; /* one and only for now */
258 1.1 matt *curxp = 0;
259 1.1 matt *curyp = 0;
260 1.1 matt (*ri->ri_ops.alloc_attr)(ri, 0, 0, 0, &defattr);
261 1.1 matt *attrp = defattr;
262 1.1 matt gt->gt_nscreens++;
263 1.1 matt return 0;
264 1.1 matt }
265 1.1 matt
266 1.1 matt void
267 1.1 matt gten_free_screen(v, cookie)
268 1.1 matt void *v;
269 1.1 matt void *cookie;
270 1.1 matt {
271 1.1 matt struct gten_softc *gt = v;
272 1.1 matt
273 1.1 matt if (gt->gt_ri == >en_console_ri)
274 1.1 matt panic("gten_free_screen: console");
275 1.1 matt
276 1.1 matt gt->gt_nscreens--;
277 1.1 matt }
278 1.1 matt
279 1.1 matt int
280 1.1 matt gten_show_screen(v, cookie, waitok, cb, cbarg)
281 1.1 matt void *v;
282 1.1 matt void *cookie;
283 1.1 matt int waitok;
284 1.1 matt void (*cb) (void *, int, int);
285 1.1 matt void *cbarg;
286 1.1 matt {
287 1.1 matt return (0);
288 1.1 matt }
289 1.1 matt
290 1.1 matt int
291 1.1 matt gten_cnattach(bus_space_tag_t memt)
292 1.1 matt {
293 1.1 matt struct rasops_info *ri = >en_console_ri;
294 1.1 matt u_int32_t mapreg, id, mask, mapsize;
295 1.1 matt long defattr;
296 1.1 matt pcitag_t tag;
297 1.1 matt int s, error;
298 1.1 matt bus_size_t bussize;
299 1.1 matt bus_addr_t busaddr;
300 1.1 matt
301 1.1 matt tag = pci_make_tag(NULL, 0, 14, 0);
302 1.1 matt
303 1.1 matt id = pci_conf_read(NULL, tag, PCI_ID_REG);
304 1.1 matt if (PCI_VENDOR(id) != PCI_VENDOR_WD ||
305 1.1 matt PCI_PRODUCT(id) != PCI_PRODUCT_WD_90C)
306 1.1 matt return ENXIO;
307 1.1 matt
308 1.1 matt mapreg = pci_conf_read(NULL, tag, 0x14);
309 1.1 matt if (PCI_MAPREG_TYPE(mapreg) != PCI_MAPREG_TYPE_MEM ||
310 1.1 matt PCI_MAPREG_MEM_TYPE(mapreg) != PCI_MAPREG_MEM_TYPE_32BIT)
311 1.1 matt return ENXIO;
312 1.1 matt
313 1.1 matt s = splhigh();
314 1.1 matt pci_conf_write(NULL, tag, 0x14, 0xffffffff);
315 1.1 matt mask = pci_conf_read(NULL, tag, 0x14);
316 1.1 matt pci_conf_write(NULL, tag, 0x14, mapreg);
317 1.1 matt splx(s);
318 1.1 matt bussize = PCI_MAPREG_MEM_SIZE(mask);
319 1.1 matt busaddr = PCI_MAPREG_MEM_ADDR(mapreg);
320 1.1 matt
321 1.1 matt error = bus_space_map(memt, busaddr + 0xef9000, bussize,
322 1.1 matt BUS_SPACE_MAP_LINEAR, (bus_space_handle_t *) &ri->ri_bits);
323 1.1 matt if (error)
324 1.1 matt return error;
325 1.1 matt
326 1.1 matt gten_common_init(ri);
327 1.1 matt
328 1.1 matt (*ri->ri_ops.alloc_attr)(ri, 0, 0, 0, &defattr);
329 1.1 matt wsdisplay_cnattach(>en_stdscreen, ri, 0, 0, defattr);
330 1.1 matt
331 1.1 matt gten_console_pcitag = tag;
332 1.1 matt
333 1.1 matt return 0;
334 1.1 matt }
335 1.1 matt
336 1.1 matt int
337 1.1 matt gten_getcmap(gt, cm)
338 1.1 matt struct gten_softc *gt;
339 1.1 matt struct wsdisplay_cmap *cm;
340 1.1 matt {
341 1.1 matt u_int index = cm->index;
342 1.1 matt u_int count = cm->count;
343 1.1 matt int error;
344 1.1 matt
345 1.1 matt if (index >= 256 || count > 256 || index + count > 256)
346 1.1 matt return EINVAL;
347 1.1 matt
348 1.1 matt error = copyout(>->gt_cmap_red[index], cm->red, count);
349 1.1 matt if (error)
350 1.1 matt return error;
351 1.1 matt error = copyout(>->gt_cmap_green[index], cm->green, count);
352 1.1 matt if (error)
353 1.1 matt return error;
354 1.1 matt error = copyout(>->gt_cmap_blue[index], cm->blue, count);
355 1.1 matt if (error)
356 1.1 matt return error;
357 1.1 matt
358 1.1 matt return 0;
359 1.1 matt }
360 1.1 matt
361 1.1 matt int
362 1.1 matt gten_putcmap(gt, cm)
363 1.1 matt struct gten_softc *gt;
364 1.1 matt struct wsdisplay_cmap *cm;
365 1.1 matt {
366 1.1 matt int index = cm->index;
367 1.1 matt int count = cm->count;
368 1.1 matt int i;
369 1.1 matt u_char *r, *g, *b;
370 1.1 matt
371 1.1 matt if (cm->index >= 256 || cm->count > 256 ||
372 1.1 matt (cm->index + cm->count) > 256)
373 1.1 matt return EINVAL;
374 1.1 matt if (!uvm_useracc(cm->red, cm->count, B_READ) ||
375 1.1 matt !uvm_useracc(cm->green, cm->count, B_READ) ||
376 1.1 matt !uvm_useracc(cm->blue, cm->count, B_READ))
377 1.1 matt return EFAULT;
378 1.1 matt copyin(cm->red, >->gt_cmap_red[index], count);
379 1.1 matt copyin(cm->green, >->gt_cmap_green[index], count);
380 1.1 matt copyin(cm->blue, >->gt_cmap_blue[index], count);
381 1.1 matt
382 1.1 matt r = >->gt_cmap_red[index];
383 1.1 matt g = >->gt_cmap_green[index];
384 1.1 matt b = >->gt_cmap_blue[index];
385 1.1 matt
386 1.1 matt #if 0
387 1.1 matt for (i = 0; i < count; i++) {
388 1.1 matt OF_call_method_1("color!", dc->dc_ih, 4, *r, *g, *b, index);
389 1.1 matt r++, g++, b++, index++;
390 1.1 matt }
391 1.1 matt #endif
392 1.1 matt
393 1.1 matt return 0;
394 1.1 matt }
395