pc98_machdep.c revision 33715
1119815Smarcel/*
2119815Smarcel * Copyright (c) KATO Takenori, 1996, 1997.
3119815Smarcel *
4119815Smarcel * All rights reserved.  Unpublished rights reserved under the copyright
5119815Smarcel * laws of Japan.
6119815Smarcel *
7119815Smarcel *
8119815Smarcel * Redistribution and use in source and binary forms, with or without
9119815Smarcel * modification, are permitted provided that the following conditions
10119815Smarcel * are met:
11119815Smarcel * 1. Redistributions of source code must retain the above copyright
12119815Smarcel *    notice, this list of conditions and the following disclaimer as
13119815Smarcel *    the first lines of this file unmodified.
14119815Smarcel * 2. Redistributions in binary form must reproduce the above copyright
15119815Smarcel *    notice, this list of conditions and the following disclaimer in the
16119815Smarcel *    documentation and/or other materials provided with the distribution.
17119815Smarcel * 3. The name of the author may not be used to endorse or promote products
18119815Smarcel *    derived from this software without specific prior written permission.
19119815Smarcel *
20119815Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21119815Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22119815Smarcel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23119815Smarcel * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24119815Smarcel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25119815Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26119815Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27119815Smarcel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28119815Smarcel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29119815Smarcel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30119815Smarcel */
31119815Smarcel
32119815Smarcel#include "opt_pc98.h"
33119815Smarcel
34119815Smarcel#include <sys/param.h>
35119815Smarcel#include <sys/systm.h>
36119815Smarcel
37119815Smarcel#include <scsi/scsiconf.h>
38119815Smarcel
39119815Smarcel#include <pc98/pc98/pc98.h>
40119815Smarcel#include <pc98/pc98/pc98_machdep.h>
41119815Smarcel
42122466Sjakeextern	int Maxmem;
43122466Sjakeextern	int Maxmem_under16M;
44119815Smarcel
45119815Smarcel#ifdef notyet
46119815Smarcelstatic	void init_cpu_accel_mem __P((void));
47119815Smarcel#endif
48119815Smarcel
49119815Smarcel/*
50119815Smarcel * Initialize DMA controller
51119815Smarcel */
52119815Smarcelvoid
53119815Smarcelpc98_init_dmac(void)
54119815Smarcel{
55119815Smarcel	outb(0x439, (inb(0x439) & 0xfb));	/* DMA Accsess Control over 1MB */
56119815Smarcel	outb(0x29, (0x0c | 0));				/* Bank Mode Reg. 16M mode */
57119815Smarcel	outb(0x29, (0x0c | 1));				/* Bank Mode Reg. 16M mode */
58119815Smarcel	outb(0x29, (0x0c | 2));				/* Bank Mode Reg. 16M mode */
59119815Smarcel	outb(0x29, (0x0c | 3));				/* Bank Mode Reg. 16M mode */
60120452Smarcel	outb(0x11, 0x50);
61119815Smarcel}
62119815Smarcel
63119815Smarcel#ifdef EPSON_MEMWIN
64119866Smarcelstatic	void init_epson_memwin __P((void));
65119866Smarcel
66119866Smarcel/*
67119866Smarcel * Disconnect phisical memory in 15-16MB region.
68119866Smarcel *
69119866Smarcel * EPSON PC-486GR, P, SR, SE, HX, HG and HA only.  Other system support
70122466Sjake * this feature with software DIP switch.
71122466Sjake */
72122466Sjakestatic void
73122466Sjakeinit_epson_memwin(void)
74122466Sjake{
75122466Sjake
76122466Sjake	if (pc98_machine_type & M_EPSON_PC98) {
77122466Sjake		if (Maxmem > 3840) {
78122466Sjake			if (Maxmem == Maxmem_under16M) {
79122466Sjake				Maxmem = 3840;
80122466Sjake				Maxmem_under16M = 3840;
81122466Sjake			} else if (Maxmem_under16M > 3840) {
82122466Sjake				Maxmem_under16M = 3840;
83122466Sjake			}
84122466Sjake		}
85122466Sjake
86122466Sjake		/* Disable 15MB-16MB caching. */
87122466Sjake		switch (epson_machine_id) {
88122466Sjake		case 0x34:	/* PC486HX */
89119866Smarcel		case 0x35:	/* PC486HG */
90119815Smarcel		case 0x3B:	/* PC486HA */
91119815Smarcel			/* Cache control start. */
92120009Stmm			outb(0x43f, 0x42);
93119815Smarcel			outw(0xc40, 0x0033);
94119815Smarcel
95120452Smarcel			/* Disable 0xF00000-0xFFFFFF. */
96119815Smarcel			outb(0xc48, 0x49);
97119815Smarcel			outb(0xc4c, 0x00);
98119815Smarcel			outb(0xc48, 0x48);
99119815Smarcel			outb(0xc4c, 0xf0);
100119815Smarcel			outb(0xc48, 0x4d);
101119815Smarcel			outb(0xc4c, 0x00);
102119815Smarcel			outb(0xc48, 0x4c);
103119815Smarcel			outb(0xc4c, 0xff);
104119815Smarcel			outb(0xc48, 0x4f);
105119815Smarcel			outb(0xc4c, 0x00);
106119815Smarcel
107119815Smarcel			/* Cache control end. */
108119815Smarcel			outb(0x43f, 0x40);
109119815Smarcel			break;
110122466Sjake
111122466Sjake		case 0x2B:	/* PC486GR/GF */
112122466Sjake		case 0x30:	/* PC486P */
113122466Sjake		case 0x31:	/* PC486GRSuper */
114119815Smarcel		case 0x32:	/* PC486GR+ */
115122466Sjake		case 0x37:	/* PC486SE */
116122466Sjake		case 0x38:	/* PC486SR */
117122466Sjake			/* Disable 0xF00000-0xFFFFFF. */
118122466Sjake			outb(0x43f, 0x42);
119122466Sjake			outb(0x467, 0xe0);
120122466Sjake			outb(0x567, 0xd8);
121119815Smarcel
122119815Smarcel			outb(0x43f, 0x40);
123119815Smarcel			outb(0x467, 0xe0);
124119815Smarcel			outb(0x567, 0xe0);
125119815Smarcel			break;
126119815Smarcel		}
127119815Smarcel
128122466Sjake		/* Disable 15MB-16MB RAM and enable memory window. */
129122466Sjake		outb(0x43b, inb(0x43b) & 0xfd);	/* Clear bit1. */
130122466Sjake	}
131119815Smarcel}
132119815Smarcel#endif
133119815Smarcel
134119815Smarcel#ifdef notyet
135119815Smarcelstatic	void init_cpu_accel_mem(void);
136119815Smarcel
137119815Smarcelstatic void
138119815Smarcelinit_cpu_accel_mem(void)
139119815Smarcel{
140119815Smarcel	u_int target_page;
141120009Stmm	/*
142120009Stmm	 * Certain 'CPU accelerator' supports over 16MB memory on
143119815Smarcel	 * the machines whose BIOS doesn't store true size.
144119815Smarcel	 * To support this, we don't trust BIOS values if Maxmem < 4096.
145119815Smarcel	 */
146119815Smarcel	if (Maxmem < 4096) {
147120452Smarcel		for (target_page = ptoa(4096);		/* 16MB */
148120452Smarcel			 target_page < ptoa(32768);		/* 128MB */
149119815Smarcel			 target_page += 256 * PAGE_SIZE	/* 1MB step */) {
150119815Smarcel			u_int tmp, page_bad = FALSE, OrigMaxmem = Maxmem;
151120452Smarcel
152119815Smarcel			*(int *)CMAP1 = PG_V | PG_RW | PG_N | target_page;
153120452Smarcel			invltlb();
154120009Stmm
155120452Smarcel			tmp = *(u_int *)CADDR1;
156119815Smarcel			/*
157120452Smarcel			 * Test for alternating 1's and 0's
158120452Smarcel			 */
159119815Smarcel			*(volatile u_int *)CADDR1 = 0xaaaaaaaa;
160119815Smarcel			if (*(volatile u_int *)CADDR1 != 0xaaaaaaaa) {
161119815Smarcel				page_bad = TRUE;
162119815Smarcel			}
163119815Smarcel			/*
164119815Smarcel			 * Test for alternating 0's and 1's
165119815Smarcel			 */
166120545Sjake			*(volatile u_int *)CADDR1 = 0x55555555;
167120545Sjake			if (*(volatile u_int *)CADDR1 != 0x55555555) {
168120545Sjake				page_bad = TRUE;
169120545Sjake			}
170119815Smarcel			/*
171119815Smarcel			 * Test for all 1's
172119815Smarcel			 */
173119815Smarcel			*(volatile u_int *)CADDR1 = 0xffffffff;
174119815Smarcel			if (*(volatile u_int *)CADDR1 != 0xffffffff) {
175119815Smarcel				page_bad = TRUE;
176119815Smarcel			}
177119815Smarcel			/*
178119815Smarcel			 * Test for all 0's
179119815Smarcel			 */
180119815Smarcel			*(volatile u_int *)CADDR1 = 0x0;
181119815Smarcel			if (*(volatile u_int *)CADDR1 != 0x0) {
182119815Smarcel				/*
183119815Smarcel				 * test of page failed
184119815Smarcel				 */
185119815Smarcel				page_bad = TRUE;
186			}
187			/*
188			 * Restore original value.
189			 */
190			*(u_int *)CADDR1 = tmp;
191			if (page_bad == TRUE) {
192				Maxmem = atop(target_page) + 256;
193			} else
194				break;
195		}
196		*(int *)CMAP1 = 0;
197		invltlb();
198	}
199}
200#endif
201
202/*
203 * Get physical memory size
204 */
205void
206pc98_getmemsize(void)
207{
208	unsigned char under16, over16;
209
210	/* available protected memory size under 16MB / 128KB */
211	under16 = PC98_SYSTEM_PARAMETER(0x401);
212	/* available protected memory size over 16MB / 1MB */
213	over16 = PC98_SYSTEM_PARAMETER(0x594);
214	/* add conventional memory size (1024KB / 128KB = 8) */
215	under16 += 8;
216
217	Maxmem = Maxmem_under16M = under16 * 128 * 1024 / PAGE_SIZE;
218	Maxmem += (over16 * 1024 * 1024 / PAGE_SIZE);
219#ifdef EPSON_MEMWIN
220	init_epson_memwin();
221#endif
222}
223
224#include "sd.h"
225
226#if NSD > 0
227/*
228 * XXX copied from sd.c.
229 */
230struct disk_parms {
231	u_char	heads;	/* Number of heads */
232	u_int16_t	cyls;	/* Number of cylinders */
233	u_char	sectors;	/*dubious *//* Number of sectors/track */
234	u_int16_t	secsiz;	/* Number of bytes/sector */
235	u_int32_t	disksize;	/* total number sectors */
236};
237
238/*
239 * Read a geometry information of SCSI HDD from BIOS work area.
240 *
241 * XXX - Before reading BIOS work area, we should check whether
242 * host adapter support it.
243 */
244int
245sd_bios_parms(disk_parms, sc_link)
246	struct	disk_parms *disk_parms;
247	struct	scsi_link *sc_link;
248{
249	u_char *tmp;
250
251	tmp = (u_char *)&PC98_SYSTEM_PARAMETER(0x460 + sc_link->target*4);
252	if ((PC98_SYSTEM_PARAMETER(0x482) & ((1 << sc_link->target)&0xff)) != 0) {
253		disk_parms->sectors = *tmp;
254		disk_parms->cyls = ((*(tmp+3)<<8)|*(tmp+2))&0xfff;
255		switch (*(tmp + 3) & 0x30) {
256		case 0x00:
257			disk_parms->secsiz = 256;
258			printf("Warning!: not supported.\n");
259			break;
260		case 0x10:
261			disk_parms->secsiz = 512;
262			break;
263		case 0x20:
264			disk_parms->secsiz = 1024;
265			break;
266		default:
267			disk_parms->secsiz = 512;
268			printf("Warning!: not supported. But force to 512\n");
269			break;
270		}
271		if (*(tmp+3) & 0x40) {
272			disk_parms->cyls += (*(tmp+1)&0xf0)<<8;
273			disk_parms->heads = *(tmp+1)&0x0f;
274		} else {
275			disk_parms->heads = *(tmp+1);
276		}
277		disk_parms->disksize = disk_parms->sectors * disk_parms->heads *
278									disk_parms->cyls;
279		return 1;
280	}
281	return 0;
282}
283#endif
284