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