1 /* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */
2 /* */
3 /* This library is free software; you can redistribute it and/or */
4 /* modify it without any restrictions. This library is distributed */
5 /* in the hope that it will be useful, but without any warranty. */
6
7 /* Multi-chipset support Copyright 1993 Harm Hanemaayer */
8 /* partially copyrighted (C) 1993 by Hartmut Schirmer */
9
10 /* GVGA 6400 driver Copyright 1994 Arno Schaefer */
11 /* only Hires 256 color modes (640x480, 800x600) supported */
12
13
14 #include <stdlib.h> /* for NULL */
15 #include <sys/types.h>
16 #include <sys/mman.h>
17 #include <fcntl.h>
18 #include <unistd.h>
19
20 #include "vga.h"
21 #include "libvga.h"
22 #include "driver.h"
23
24 #include "gvga6400.regs"
25
26 /* Mode table */
27 static ModeTable gvga6400_modes[] =
28 {
29 /* *INDENT-OFF* */
30 OneModeEntry(640x480x256),
31 OneModeEntry(800x600x256),
32 END_OF_MODE_TABLE
33 /* *INDENT-ON* */
34 };
35
36 static unsigned char last_page = 0;
37
38 static void gvga6400_setregs(const unsigned char regs[], int mode);
39 static int gvga6400_init(int force, int par1, int par2);
40
41 /* Fill in chipset-specific modeinfo */
42
gvga6400_getmodeinfo(int mode,vga_modeinfo * modeinfo)43 static void gvga6400_getmodeinfo(int mode, vga_modeinfo * modeinfo)
44 {
45 if (modeinfo->bytesperpixel == 1) { /* linear mode */
46 modeinfo->maxpixels = 512 * 1024;
47 modeinfo->startaddressrange = 0xffff;
48 } else
49 switch (modeinfo->colors) {
50 case 16: /* 4-plane 16 color mode */
51 modeinfo->maxpixels = 65536 * 8;
52 modeinfo->startaddressrange = 0x7ffff;
53 break;
54 case 256: /* 4-plane 256 color mode */
55 modeinfo->maxpixels = 65536 * 4;
56 modeinfo->startaddressrange = 0x3ffff;
57 break;
58 }
59
60 modeinfo->maxlogicalwidth = 2040;
61 modeinfo->haveblit = 0;
62 modeinfo->flags &= ~IS_INTERLACED;
63 modeinfo->flags |= HAVE_RWPAGE;
64 }
65
nothing(void)66 static void nothing(void)
67 {
68 }
69
70 /* Return nonzero if mode available */
71
gvga6400_modeavailable(int mode)72 static int gvga6400_modeavailable(int mode)
73 {
74 const unsigned char *regs;
75
76 regs = LOOKUPMODE(gvga6400_modes, mode);
77
78 if (regs == NULL || mode == GPLANE16)
79 return __svgalib_vga_driverspecs.modeavailable(mode);
80 if (regs == DISABLE_MODE || mode <= TEXT || mode > GLASTMODE)
81 return 0;
82
83 return SVGADRV;
84 }
85
86
87 /* Set a mode */
88
89 static int lastmode;
90
gvga6400_setmode(int mode,int prv_mode)91 static int gvga6400_setmode(int mode, int prv_mode)
92 {
93 const unsigned char *regs;
94
95 switch (gvga6400_modeavailable(mode)) {
96 case STDVGADRV:
97 return __svgalib_vga_driverspecs.setmode(mode, prv_mode);
98 case SVGADRV:
99 regs = LOOKUPMODE(gvga6400_modes, mode);
100 if (regs != NULL)
101 break;
102 default:
103 return (1); /* not available */
104 }
105
106 __svgalib_setregs(regs);
107 gvga6400_setregs(regs, mode);
108
109 return 0;
110 }
111
gvga6400_setpage(int page)112 static void gvga6400_setpage(int page)
113 {
114 page &= 7;
115 last_page = 0x40 | page | (page << 3);
116
117 outb(SEQ_I, 6);
118 outb(SEQ_D, last_page);
119 }
120
gvga6400_setrdpage(int page)121 static void gvga6400_setrdpage(int page)
122 {
123 last_page &= 0xf8;
124 last_page |= page & 0x07;
125
126 outb(SEQ_I, 6);
127 outb(SEQ_D, last_page);
128 }
129
gvga6400_setwrpage(int page)130 static void gvga6400_setwrpage(int page)
131 {
132 last_page &= 0xc7;
133 last_page |= ((page & 7) << 3);
134
135 outb(SEQ_I, 6);
136 outb(SEQ_D, last_page);
137 }
138
139
140 /* Set display start */
141
gvga6400_setdisplaystart(int address)142 static void gvga6400_setdisplaystart(int address)
143 {
144 vga_modeinfo modeinfo;
145 gvga6400_getmodeinfo(lastmode, &modeinfo);
146
147 if (modeinfo.bytesperpixel == 0)
148 switch (modeinfo.colors) {
149 case 16: /* planar 16-color mode */
150 inb(0x3da);
151 outb(ATT_IW, 0x13 + 0x20);
152 outb(ATT_IW, (inb(ATT_R) & 0xf0) | (address & 7));
153 /* write sa0-2 to bits 0-2 */
154 address >>= 3;
155 break;
156 case 256: /* planar 256-color mode */
157 inb(0x3da);
158 outb(ATT_IW, 0x13 + 0x20);
159 outb(ATT_IW, (inb(ATT_R) & 0xf0) | ((address & 3) << 1));
160 /* write sa0-1 to bits 1-2 */
161 address >>= 2;
162 break;
163 }
164 outw(CRT_IC, 0x0d + (address & 0x00ff) * 256); /* sa0-sa7 */
165 outw(CRT_IC, 0x0c + (address & 0xff00)); /* sa8-sa15 */
166 }
167
gvga6400_setlogicalwidth(int width)168 static void gvga6400_setlogicalwidth(int width)
169 {
170 outw(CRT_IC, 0x13 + (width >> 3) * 256); /* lw3-lw11 */
171 }
172
173
gvga6400_test(void)174 static int gvga6400_test(void)
175 {
176 int mem_fd;
177 unsigned char *vga_bios;
178 int result = 0;
179 int address;
180
181 mem_fd = open("/dev/mem", O_RDONLY);
182
183 /* Changed to use valloc(). */
184 if ((vga_bios = valloc(4096)) == NULL) {
185 fprintf(stderr, "svgalib: malloc error\n");
186 exit(-1);
187 }
188 vga_bios = (unsigned char *) mmap
189 (
190 (caddr_t) vga_bios,
191 4096,
192 PROT_READ,
193 MAP_SHARED | MAP_FIXED,
194 mem_fd,
195 0xc0000
196 );
197 if ((long) vga_bios < 0) {
198 fprintf(stderr, "svgalib: mmap error\n");
199 exit(-1);
200 }
201 address = vga_bios[0x37];
202
203 if (vga_bios[address] == 0x77 &&
204 vga_bios[address + 1] == 0x11 &&
205 vga_bios[address + 2] == 0x99 &&
206 vga_bios[address + 3] == 0x66) {
207 result = 1;
208 gvga6400_init(0, 0, 0);
209 }
210 #if 0
211 munmap((caddr_t) vga_bios, 4096);
212 free(vga_bios);
213 #endif
214 close(mem_fd);
215
216 return (result);
217 }
218
gvga6400_saveregs(unsigned char regs[])219 static int gvga6400_saveregs(unsigned char regs[])
220 {
221 outb(SEQ_I, 6);
222 regs[EXT + 2] = inb(SEQ_D);
223 outb(SEQ_I, 7);
224 regs[EXT + 3] = inb(SEQ_D);
225 outb(SEQ_I, 8);
226 regs[EXT + 4] = inb(SEQ_D);
227 outb(SEQ_I, 0x10);
228 regs[EXT + 5] = inb(SEQ_D);
229 outb(GRA_I, 9);
230 regs[EXT + 6] = inb(GRA_D);
231 outb(CRT_IC, 0x2f);
232 regs[EXT + 10] = inb(CRT_DC);
233
234 return (11);
235 }
236
gvga6400_setregs(const unsigned char regs[],int mode)237 static void gvga6400_setregs(const unsigned char regs[], int mode)
238 {
239 outb(SEQ_I, 6);
240 outb(SEQ_D, regs[EXT + 2]);
241 outb(SEQ_I, 7);
242 outb(SEQ_D, regs[EXT + 3]);
243 outb(SEQ_I, 8);
244 outb(SEQ_D, regs[EXT + 4]);
245 outb(SEQ_I, 0x10);
246 outb(SEQ_D, regs[EXT + 5]);
247 outb(GRA_I, 9);
248 outb(GRA_D, regs[EXT + 6]);
249 outb(CRT_IC, 0x2f);
250 outb(CRT_DC, regs[EXT + 10]);
251 }
252
253 DriverSpecs __svgalib_gvga6400_driverspecs =
254 {
255 gvga6400_saveregs,
256 gvga6400_setregs,
257 nothing,
258 nothing,
259 gvga6400_test,
260 gvga6400_init,
261 gvga6400_setpage,
262 gvga6400_setrdpage,
263 gvga6400_setwrpage,
264 gvga6400_setmode,
265 gvga6400_modeavailable,
266 gvga6400_setdisplaystart,
267 gvga6400_setlogicalwidth,
268 gvga6400_getmodeinfo,
269 0, /* bitblt */
270 0, /* imageblt */
271 0, /* fillblt */
272 0, /* hlinelistblt */
273 0, /* bltwait */
274 0, /* extset */
275 0,
276 0, /* linear */
277 NULL, /* Accelspecs */
278 NULL, /* Emulation */
279 };
280
281 /* Initialize chipset (called after detection) */
282
gvga6400_init(int force,int par1,int par2)283 static int gvga6400_init(int force, int par1, int par2)
284 {
285 if (__svgalib_driver_report)
286 printf("Using Genoa GVGA 6400 driver.\n");
287 __svgalib_driverspecs = &__svgalib_gvga6400_driverspecs;
288 __svgalib_banked_mem_base=0xa0000;
289 __svgalib_banked_mem_size=0x10000;
290
291 return 0;
292 }
293