pc98_machdep.c revision 22407
1/*
2 * Copyright (c) KATO Takenori, 1996, 1997.
3 *
4 * All rights reserved.  Unpublished rights reserved under the copyright
5 * laws of Japan.
6 *
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer as
13 *    the first lines of this file unmodified.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. The name of the author may not be used to endorse or promote products
18 *    derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/vmmeter.h>
35
36#include <scsi/scsiconf.h>
37
38#include <vm/vm.h>
39#include <vm/vm_param.h>
40#include <vm/vm_prot.h>
41#include <vm/lock.h>
42#include <vm/vm_kern.h>
43#include <vm/vm_object.h>
44#include <vm/vm_page.h>
45#include <vm/vm_map.h>
46#include <vm/vm_pager.h>
47#include <vm/vm_extern.h>
48
49#include <pc98/pc98/pc98.h>
50#include <pc98/pc98/pc98_machdep.h>
51#include <i386/isa/isa_device.h>
52
53extern	int Maxmem;
54extern	int Maxmem_under16M;
55
56#ifdef notyet
57static	void init_cpu_accel_mem __P((void));
58#endif
59void	pc98_init_dmac __P((void));
60void	pc98_getmemsize __P((void));
61
62/*
63 * Initialize DMA controller
64 */
65void
66pc98_init_dmac(void)
67{
68	outb(0x439, (inb(0x439) & 0xfb));	/* DMA Accsess Control over 1MB */
69	outb(0x29, (0x0c | 0));				/* Bank Mode Reg. 16M mode */
70	outb(0x29, (0x0c | 1));				/* Bank Mode Reg. 16M mode */
71	outb(0x29, (0x0c | 2));				/* Bank Mode Reg. 16M mode */
72	outb(0x29, (0x0c | 3));				/* Bank Mode Reg. 16M mode */
73	outb(0x11, 0x50);
74}
75
76#ifdef EPSON_MEMWIN
77static	void init_epson_memwin __P((void));
78
79/*
80 * Disconnect phisical memory in 15-16MB region.
81 *
82 * EPSON PC-486GR, P, SR, SE, HX, HG and HA only.  Other system support
83 * this feature with software DIP switch.
84 */
85static void
86init_epson_memwin(void)
87{
88
89	if (pc98_machine_type & M_EPSON_PC98) {
90		if (Maxmem > 3840) {
91			if (Maxmem == Maxmem_under16M) {
92				Maxmem = 3840;
93				Maxmem_under16M = 3840;
94			} else if (Maxmem_under16M > 3840) {
95				Maxmem_under16M = 3840;
96			}
97		}
98
99		/* Disable 15MB-16MB caching. */
100		switch (epson_machine_id) {
101		case 0x34:	/* PC486HX */
102		case 0x35:	/* PC486HG */
103		case 0x3B:	/* PC486HA */
104			/* Cache control start. */
105			outb(0x43f, 0x42);
106			outw(0xc40, 0x0033);
107
108			/* Disable 0xF00000-0xFFFFFF. */
109			outb(0xc48, 0x49);
110			outb(0xc4c, 0x00);
111			outb(0xc48, 0x48);
112			outb(0xc4c, 0xf0);
113			outb(0xc48, 0x4d);
114			outb(0xc4c, 0x00);
115			outb(0xc48, 0x4c);
116			outb(0xc4c, 0xff);
117			outb(0xc48, 0x4f);
118			outb(0xc4c, 0x00);
119
120			/* Cache control end. */
121			outb(0x43f, 0x40);
122			break;
123
124		case 0x2B:	/* PC486GR/GF */
125		case 0x30:	/* PC486P */
126		case 0x31:	/* PC486GRSuper */
127		case 0x32:	/* PC486GR+ */
128		case 0x37:	/* PC486SE */
129		case 0x38:	/* PC486SR */
130			/* Disable 0xF00000-0xFFFFFF. */
131			outb(0x43f, 0x42);
132			outb(0x467, 0xe0);
133			outb(0x567, 0xd8);
134
135			outb(0x43f, 0x40);
136			outb(0x467, 0xe0);
137			outb(0x567, 0xe0);
138			break;
139		}
140
141		/* Disable 15MB-16MB RAM and enable memory window. */
142		outb(0x43b, inb(0x43b) & 0xfd);	/* Clear bit1. */
143	}
144}
145#endif
146
147#ifdef notyet
148static	void init_cpu_accel_mem(void);
149
150static void
151init_cpu_accel_mem(void)
152{
153	u_int target_page;
154	/*
155	 * Certain 'CPU accelerator' supports over 16MB memory on
156	 * the machines whose BIOS doesn't store true size.
157	 * To support this, we don't trust BIOS values if Maxmem < 4096.
158	 */
159	if (Maxmem < 4096) {
160		for (target_page = ptoa(4096);		/* 16MB */
161			 target_page < ptoa(32768);		/* 128MB */
162			 target_page += 256 * PAGE_SIZE	/* 1MB step */) {
163			u_int tmp, page_bad = FALSE, OrigMaxmem = Maxmem;
164
165			*(int *)CMAP1 = PG_V | PG_RW | PG_N | target_page;
166			invltlb();
167
168			tmp = *(u_int *)CADDR1;
169			/*
170			 * Test for alternating 1's and 0's
171			 */
172			*(volatile u_int *)CADDR1 = 0xaaaaaaaa;
173			if (*(volatile u_int *)CADDR1 != 0xaaaaaaaa) {
174				page_bad = TRUE;
175			}
176			/*
177			 * Test for alternating 0's and 1's
178			 */
179			*(volatile u_int *)CADDR1 = 0x55555555;
180			if (*(volatile u_int *)CADDR1 != 0x55555555) {
181				page_bad = TRUE;
182			}
183			/*
184			 * Test for all 1's
185			 */
186			*(volatile u_int *)CADDR1 = 0xffffffff;
187			if (*(volatile u_int *)CADDR1 != 0xffffffff) {
188				page_bad = TRUE;
189			}
190			/*
191			 * Test for all 0's
192			 */
193			*(volatile u_int *)CADDR1 = 0x0;
194			if (*(volatile u_int *)CADDR1 != 0x0) {
195				/*
196				 * test of page failed
197				 */
198				page_bad = TRUE;
199			}
200			/*
201			 * Restore original value.
202			 */
203			*(u_int *)CADDR1 = tmp;
204			if (page_bad == TRUE) {
205				Maxmem = atop(target_page) + 256;
206			} else
207				break;
208		}
209		*(int *)CMAP1 = 0;
210		invltlb();
211	}
212}
213#endif
214
215/*
216 * Get physical memory size
217 */
218void
219pc98_getmemsize(void)
220{
221	unsigned char under16, over16;
222
223	/* available protected memory size under 16MB / 128KB */
224	under16 = PC98_SYSTEM_PARAMETER(0x401);
225	/* available protected memory size over 16MB / 1MB */
226	over16 = PC98_SYSTEM_PARAMETER(0x594);
227	/* add conventional memory size (1024KB / 128KB = 8) */
228	under16 += 8;
229
230	Maxmem = Maxmem_under16M = under16 * 128 * 1024 / PAGE_SIZE;
231	Maxmem += (over16 * 1024 * 1024 / PAGE_SIZE);
232#ifdef EPSON_MEMWIN
233	init_epson_memwin();
234#endif
235}
236
237#include "sd.h"
238
239#if NSD > 0
240/*
241 * XXX copied from sd.c.
242 */
243struct disk_parms {
244	u_char	heads;	/* Number of heads */
245	u_int16_t	cyls;	/* Number of cylinders */
246	u_char	sectors;	/*dubious *//* Number of sectors/track */
247	u_int16_t	secsiz;	/* Number of bytes/sector */
248	u_int32_t	disksize;	/* total number sectors */
249};
250
251int	sd_bios_parms __P((struct disk_parms *, struct scsi_link *));
252
253/*
254 * Read a geometry information of SCSI HDD from BIOS work area.
255 *
256 * XXX - Before reading BIOS work area, we should check whether
257 * host adapter support it.
258 */
259int
260sd_bios_parms(disk_parms, sc_link)
261	struct	disk_parms *disk_parms;
262	struct	scsi_link *sc_link;
263{
264	u_char *tmp;
265
266	tmp = (u_char *)&PC98_SYSTEM_PARAMETER(0x460 + sc_link->target*4);
267	if ((PC98_SYSTEM_PARAMETER(0x482) & ((1 << sc_link->target)&0xff)) != 0) {
268		disk_parms->sectors = *tmp;
269		disk_parms->cyls = ((*(tmp+3)<<8)|*(tmp+2))&0xfff;
270		switch (*(tmp + 3) & 0x30) {
271		case 0x00:
272			disk_parms->secsiz = 256;
273			printf("Warning!: not supported.\n");
274			break;
275		case 0x10:
276			disk_parms->secsiz = 512;
277			break;
278		case 0x20:
279			disk_parms->secsiz = 1024;
280			break;
281		default:
282			disk_parms->secsiz = 512;
283			printf("Warning!: not supported. But force to 512\n");
284			break;
285		}
286		if (*(tmp+3) & 0x40) {
287			disk_parms->cyls += (*(tmp+1)&0xf0)<<8;
288			disk_parms->heads = *(tmp+1)&0x0f;
289		} else {
290			disk_parms->heads = *(tmp+1);
291		}
292		disk_parms->disksize = disk_parms->sectors * disk_parms->heads *
293									disk_parms->cyls;
294		return 1;
295	}
296	return 0;
297}
298#endif
299