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