1*2a84159aStsutsui /* $NetBSD: pci_tseng.c,v 1.14 2023/01/06 10:28:28 tsutsui Exp $ */
2b9cb0eefSleo
3b9cb0eefSleo /*
4b9cb0eefSleo * Copyright (c) 1999 Leo Weppelman. All rights reserved.
5b9cb0eefSleo *
6b9cb0eefSleo * Redistribution and use in source and binary forms, with or without
7b9cb0eefSleo * modification, are permitted provided that the following conditions
8b9cb0eefSleo * are met:
9b9cb0eefSleo * 1. Redistributions of source code must retain the above copyright
10b9cb0eefSleo * notice, this list of conditions and the following disclaimer.
11b9cb0eefSleo * 2. Redistributions in binary form must reproduce the above copyright
12b9cb0eefSleo * notice, this list of conditions and the following disclaimer in the
13b9cb0eefSleo * documentation and/or other materials provided with the distribution.
14b9cb0eefSleo *
15b9cb0eefSleo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16b9cb0eefSleo * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17b9cb0eefSleo * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18b9cb0eefSleo * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19b9cb0eefSleo * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20b9cb0eefSleo * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21b9cb0eefSleo * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22b9cb0eefSleo * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23b9cb0eefSleo * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24b9cb0eefSleo * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25b9cb0eefSleo */
26e803bea7Slukem
27e803bea7Slukem #include <sys/cdefs.h>
28*2a84159aStsutsui __KERNEL_RCSID(0, "$NetBSD: pci_tseng.c,v 1.14 2023/01/06 10:28:28 tsutsui Exp $");
29e803bea7Slukem
30b9cb0eefSleo #include <sys/param.h>
31b9cb0eefSleo #include <sys/queue.h>
32b9cb0eefSleo #include <sys/systm.h>
33b9cb0eefSleo #include <dev/pci/pcireg.h>
34b9cb0eefSleo #include <dev/pci/pcivar.h>
35b9cb0eefSleo #include <dev/pci/pcidevs.h>
36b9cb0eefSleo #include <atari/pci/pci_vga.h>
37b9cb0eefSleo #include <atari/dev/grf_etreg.h>
38b9cb0eefSleo
39b9cb0eefSleo #define PCI_LINMEMBASE 0x0e000000
40b9cb0eefSleo #define PCI_IOBASE 0x800
41b9cb0eefSleo
429b30bd93Stsutsui static void et6000_init(volatile uint8_t *, uint8_t *, int);
43b9cb0eefSleo
44b9cb0eefSleo /*
45b9cb0eefSleo * Use tables for the card init...
46b9cb0eefSleo */
47863a28deStsutsui static const uint8_t seq_tab[] = {
489b30bd93Stsutsui 0x03, 0x01, 0x03, 0x00, 0x02, 0x00, 0x00, 0xb4
499b30bd93Stsutsui };
50b9cb0eefSleo
51863a28deStsutsui static const uint8_t gfx_tab[] = {
529b30bd93Stsutsui 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x0f, 0xff
539b30bd93Stsutsui };
54b9cb0eefSleo
55863a28deStsutsui static const uint8_t attr_tab[] = {
569b30bd93Stsutsui 0x0a, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00
579b30bd93Stsutsui };
58b9cb0eefSleo
59863a28deStsutsui static const uint8_t crt_tab[] = {
60b9cb0eefSleo 0x60, 0x53, 0x4f, 0x94, 0x56, 0x05, 0xc1, 0x1f,
61b9cb0eefSleo 0x00, 0x4f, 0x00, 0x0f, 0x00, 0x00, 0x07, 0x80,
62b9cb0eefSleo 0x98, 0x3d, 0x8f, 0x28, 0x0f, 0x8f, 0xc2, 0xa3,
6375ef6675Sthomas 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6475ef6675Sthomas 0x00, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00,
6575ef6675Sthomas 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6675ef6675Sthomas #ifdef ET4000_HAS_2MB_MEM
6775ef6675Sthomas 0x00, 0x80, 0xa0, 0x00, 0x00, 0x10, 0x03, 0x89, /* 2 MB video memory */
6875ef6675Sthomas #else
6975ef6675Sthomas 0x00, 0x80, 0x28, 0x00, 0x00, 0x10, 0x43, 0x09, /* 1 MB video memory */
7075ef6675Sthomas #endif
719b30bd93Stsutsui 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
729b30bd93Stsutsui };
73b9cb0eefSleo
74863a28deStsutsui static const uint8_t ras_cas_tab[] = {
759b30bd93Stsutsui 0x11, 0x14, 0x15
769b30bd93Stsutsui };
776a477596Sleo
78b9cb0eefSleo void
tseng_init(pci_chipset_tag_t pc,pcitag_t tag,int id,volatile uint8_t * ba,uint8_t * fb)799b30bd93Stsutsui tseng_init(pci_chipset_tag_t pc, pcitag_t tag, int id, volatile uint8_t *ba,
809b30bd93Stsutsui uint8_t *fb)
81b9cb0eefSleo {
829b30bd93Stsutsui int i, j;
83b9cb0eefSleo int is_et6000 = 0;
849b30bd93Stsutsui uint32_t csr;
85b9cb0eefSleo
86b9cb0eefSleo is_et6000 = (id == PCI_PRODUCT_TSENG_ET6000) ? 1 : 0;
87b9cb0eefSleo
88b9cb0eefSleo /* Turn on the card */
89b9cb0eefSleo pci_conf_write(pc, tag, PCI_MAPREG_START, PCI_LINMEMBASE);
90b9cb0eefSleo if (is_et6000)
91b9cb0eefSleo pci_conf_write(pc, tag, PCI_MAPREG_START + 4,
92b9cb0eefSleo PCI_IOBASE | PCI_MAPREG_TYPE_IO);
93b9cb0eefSleo csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
94b9cb0eefSleo csr |= (PCI_COMMAND_MEM_ENABLE|PCI_COMMAND_IO_ENABLE);
95b9cb0eefSleo csr |= PCI_COMMAND_MASTER_ENABLE;
96b9cb0eefSleo pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr);
97b9cb0eefSleo
986a477596Sleo if (is_et6000) {
996a477596Sleo /*
1006a477596Sleo * The et6[01]000 cards have MDRAM chips. The
1018ce1f4ffSmsaitoh * timing to those chips is not properly initialized
1026a477596Sleo * by the card on init. The way to determine the
1036a477596Sleo * values is not documented either :-( So that's why
1046a477596Sleo * all this mess below (and in et6000_init()....
1056a477596Sleo */
1066a477596Sleo for (i = 0; i < sizeof(ras_cas_tab); i++) {
1076a477596Sleo et6000_init(ba, fb, i);
1086a477596Sleo for (j = 0; j < 32; j++)
1096a477596Sleo fb[j] = j;
1106a477596Sleo for (j = 0; j < 32; j++)
1116a477596Sleo if (fb[j] != j)
1126a477596Sleo break;
1136a477596Sleo if (j == 32)
1146a477596Sleo break;
1156a477596Sleo }
1166a477596Sleo }
1176a477596Sleo
118b9cb0eefSleo vgaw(ba, GREG_MISC_OUTPUT_W, 0x63);
119b9cb0eefSleo vgaw(ba, GREG_VIDEOSYSENABLE, 0x01);
120b9cb0eefSleo WCrt(ba, 0x17 , 0x00); /* color */
121b9cb0eefSleo WCrt(ba, 0x11 , 0x00); /* color */
122b9cb0eefSleo vgaw(ba, VDAC_MASK , 0xff);
123b9cb0eefSleo WSeq(ba, SEQ_ID_RESET , 0x00);
124b9cb0eefSleo vgaw(ba, GREG_HERCULESCOMPAT, 0x03);
125b9cb0eefSleo vgaw(ba, GREG_DISPMODECONTROL, 0xa0);
126b9cb0eefSleo
127b9cb0eefSleo /* Load sequencer */
128b9cb0eefSleo for (i = 1; i < 8; i++)
129b9cb0eefSleo WSeq(ba, i, seq_tab[i]);
130b9cb0eefSleo WSeq(ba, SEQ_ID_RESET , 0x03);
131b9cb0eefSleo
132b9cb0eefSleo vgar(ba, VDAC_ADDRESS); /* clear old state */
133b9cb0eefSleo vgar(ba, VDAC_MASK);
134b9cb0eefSleo vgar(ba, VDAC_MASK);
135b9cb0eefSleo vgar(ba, VDAC_MASK);
136b9cb0eefSleo vgar(ba, VDAC_MASK);
137b9cb0eefSleo vgaw(ba, VDAC_MASK, 0); /* set to palette */
138b9cb0eefSleo vgar(ba, VDAC_ADDRESS); /* clear state */
139b9cb0eefSleo vgaw(ba, VDAC_MASK, 0xff);
140b9cb0eefSleo
141b9cb0eefSleo /*
142b9cb0eefSleo * Make sure we're allowed to write all crt-registers
143b9cb0eefSleo */
144b9cb0eefSleo WCrt(ba, CRT_ID_END_VER_RETR, (RCrt(ba, CRT_ID_END_VER_RETR) & 0x7f));
145b9cb0eefSleo
146b9cb0eefSleo /* CRT registers */
147b9cb0eefSleo for (i = 0; i < 0x3e; i++)
148b9cb0eefSleo WCrt(ba, i, crt_tab[i]);
149b9cb0eefSleo
150b9cb0eefSleo /* GCT registers */
151b9cb0eefSleo for (i = 0; i < 0x09; i++)
152b9cb0eefSleo WGfx(ba, i, gfx_tab[i]);
153b9cb0eefSleo
154b9cb0eefSleo for (i = 0; i < 0x10; i++)
155b9cb0eefSleo WAttr(ba, i, i);
156b9cb0eefSleo for (; i < 0x18; i++)
157b9cb0eefSleo WAttr(ba, i, attr_tab[i - 0x10]);
158b9cb0eefSleo WAttr(ba, 0x20, 0);
159b9cb0eefSleo }
160b9cb0eefSleo
161b9cb0eefSleo /*
162b9cb0eefSleo * Initialize the et6000 specific (PCI) registers. Try to do it like the
163b9cb0eefSleo * video-bios would have done it, so things like Xservers get what they
164b9cb0eefSleo * expect. Most info was kindly provided by Koen Gadeyne.
165b9cb0eefSleo */
166b9cb0eefSleo
167b9cb0eefSleo static void
et6000_init(volatile uint8_t * ba,uint8_t * fb,int iter)1689b30bd93Stsutsui et6000_init(volatile uint8_t *ba, uint8_t *fb, int iter)
169b9cb0eefSleo {
170b9cb0eefSleo int i;
1719b30bd93Stsutsui uint8_t dac_tab[] = { 0x7d,0x67, 0x5d,0x64, 0x56,0x63,
172b9cb0eefSleo 0x28,0x22, 0x79,0x49, 0x6f,0x47,
173b9cb0eefSleo 0x28,0x41, 0x6b,0x44, 0x00,0x00,
174b9cb0eefSleo 0x00,0x00, 0x5d,0x25, 0x00,0x00,
175b9cb0eefSleo 0x00,0x00, 0x00,0x96 };
176b9cb0eefSleo
177b9cb0eefSleo ba += 0x800;
178b9cb0eefSleo
179b9cb0eefSleo ba[0x40] = 0x06; /* Use standard vga addressing */
180b9cb0eefSleo ba[0x41] = 0x2a; /* Performance control */
181b9cb0eefSleo ba[0x43] = 0x02; /* XCLK/SCLK config */
1826a477596Sleo ba[0x44] = ras_cas_tab[iter]; /* RAS/CAS config */
183b9cb0eefSleo ba[0x46] = 0x00; /* CRT display feature */
184b9cb0eefSleo ba[0x47] = 0x10;
185b9cb0eefSleo ba[0x58] = 0x00; /* Video Control 1 */
186b9cb0eefSleo ba[0x59] = 0x04; /* Video Control 2 */
187b9cb0eefSleo
188b9cb0eefSleo /*
189b9cb0eefSleo * Setup a 'standard' CLKDAC
190b9cb0eefSleo */
191b9cb0eefSleo ba[0x42] = 0x00; /* MCLK == CLK0 */
192b9cb0eefSleo ba[0x67] = 0x00; /* Start filling from dac-reg 0 and up... */
193b9cb0eefSleo for (i = 0; i < 0x16; i++)
194b9cb0eefSleo ba[0x69] = dac_tab[i];
195b9cb0eefSleo
196b9cb0eefSleo if (ba[8] == 0x70) { /* et6100, right? */
1979b30bd93Stsutsui volatile uint8_t *ma = (volatile uint8_t *)fb;
1989b30bd93Stsutsui uint8_t bv;
199b9cb0eefSleo
200b9cb0eefSleo /*
201b9cb0eefSleo * XXX Black magic to get the bloody MDRAM's to function...
202b9cb0eefSleo * XXX _Only_ tested on my card! [leo]
203b9cb0eefSleo */
204b9cb0eefSleo bv = ba[45];
205b9cb0eefSleo ba[0x45] = bv | 0x40; /* Reset MDRAM's */
206b9cb0eefSleo ba[0x45] = bv | 0x70; /* Program latency value */
207b9cb0eefSleo ma[0x0] = 0; /* Yeah, right :-( */
208b9cb0eefSleo ba[0x45] = bv; /* Back to normal */
209b9cb0eefSleo }
210b9cb0eefSleo }
211