pc98_machdep.c revision 161129
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 * $FreeBSD: head/sys/pc98/pc98/pc98_machdep.c 161129 2006-08-09 18:25:07Z imp $
32 */
33
34#include "opt_pc98.h"
35
36#include <sys/param.h>
37#include <sys/systm.h>
38
39#include <cam/cam.h>
40#include <cam/cam_ccb.h>
41#include <sys/bio.h>
42#include <sys/bus.h>
43#include <sys/conf.h>
44#include <geom/geom_disk.h>
45#include <machine/md_var.h>
46#include <pc98/pc98/pc98_machdep.h>
47
48/*
49 * Initialize DMA controller
50 */
51void
52pc98_init_dmac(void)
53{
54	outb(0x439, (inb(0x439) & 0xfb));	/* DMA Accsess Control over 1MB */
55	outb(0x29, (0x0c | 0));				/* Bank Mode Reg. 16M mode */
56	outb(0x29, (0x0c | 1));				/* Bank Mode Reg. 16M mode */
57	outb(0x29, (0x0c | 2));				/* Bank Mode Reg. 16M mode */
58	outb(0x29, (0x0c | 3));				/* Bank Mode Reg. 16M mode */
59	outb(0x11, 0x50);
60}
61
62#ifdef EPSON_MEMWIN
63/*
64 * Disconnect phisical memory in 15-16MB region.
65 *
66 * EPSON PC-486GR, P, SR, SE, HX, HG and HA only.  Other system support
67 * this feature with software DIP switch.
68 */
69static void
70init_epson_memwin(void)
71{
72	/* Disable 15MB-16MB caching. */
73	switch (epson_machine_id) {
74	case EPSON_PC486_HX:
75	case EPSON_PC486_HG:
76	case EPSON_PC486_HA:
77		/* Cache control start. */
78		outb(0x43f, 0x42);
79		outw(0xc40, 0x0033);
80
81		/* Disable 0xF00000-0xFFFFFF. */
82		outb(0xc48, 0x49);
83		outb(0xc4c, 0x00);
84		outb(0xc48, 0x48);
85		outb(0xc4c, 0xf0);
86		outb(0xc48, 0x4d);
87		outb(0xc4c, 0x00);
88		outb(0xc48, 0x4c);
89		outb(0xc4c, 0xff);
90		outb(0xc48, 0x4f);
91		outb(0xc4c, 0x00);
92
93		/* Cache control end. */
94		outb(0x43f, 0x40);
95		break;
96
97	case EPSON_PC486_GR:
98	case EPSON_PC486_P:
99	case EPSON_PC486_GR_SUPER:
100	case EPSON_PC486_GR_PLUS:
101	case EPSON_PC486_SE:
102	case EPSON_PC486_SR:
103		/* Disable 0xF00000-0xFFFFFF. */
104		outb(0x43f, 0x42);
105		outb(0x467, 0xe0);
106		outb(0x567, 0xd8);
107
108		outb(0x43f, 0x40);
109		outb(0x467, 0xe0);
110		outb(0x567, 0xe0);
111		break;
112	}
113
114	/* Disable 15MB-16MB RAM and enable memory window. */
115	outb(0x43b, inb(0x43b) & 0xfd);	/* Clear bit1. */
116}
117#endif
118
119/*
120 * Get physical memory size
121 */
122unsigned int
123pc98_getmemsize(unsigned int *base, unsigned int *ext)
124{
125	unsigned int under16, over16;
126
127	/* available conventional memory size */
128	*base = ((PC98_SYSTEM_PARAMETER(0x501) & 7) + 1) * 128;
129
130	/* available protected memory size under 16MB */
131	under16 = PC98_SYSTEM_PARAMETER(0x401) * 128 + 1024;
132#ifdef EPSON_MEMWIN
133	if (pc98_machine_type & M_EPSON_PC98) {
134		if (under16 > (15 * 1024))
135			/* chop under16 memory to 15MB */
136			under16 = 15 * 1024;
137		init_epson_memwin();
138	}
139#endif
140
141	/* available protected memory size over 16MB / 1MB */
142	over16  = PC98_SYSTEM_PARAMETER(0x594);
143	over16 += PC98_SYSTEM_PARAMETER(0x595) * 256;
144
145	if (over16 > 0)
146		*ext = (16 + over16) * 1024 - 1024;
147	else
148		*ext = under16 - 1024;
149
150	return (under16);
151}
152
153/*
154 * Read a geometry information of SCSI HDD from BIOS work area.
155 *
156 * XXX - Before reading BIOS work area, we should check whether
157 * host adapter support it.
158 */
159int
160scsi_da_bios_params(struct ccb_calc_geometry *ccg)
161{
162	u_char *tmp;
163	int	target;
164
165	target = ccg->ccb_h.target_id;
166	tmp = (u_char *)&PC98_SYSTEM_PARAMETER(0x460 + target*4);
167	if ((PC98_SYSTEM_PARAMETER(0x482) & ((1 << target)&0xff)) != 0) {
168		ccg->secs_per_track = *tmp;
169		ccg->cylinders = ((*(tmp+3)<<8)|*(tmp+2))&0xfff;
170#if 0
171		switch (*(tmp + 3) & 0x30) {
172		case 0x00:
173			disk_parms->secsiz = 256;
174			printf("Warning!: not supported.\n");
175			break;
176		case 0x10:
177			disk_parms->secsiz = 512;
178			break;
179		case 0x20:
180			disk_parms->secsiz = 1024;
181			break;
182		default:
183			disk_parms->secsiz = 512;
184			printf("Warning!: not supported. But force to 512\n");
185			break;
186		}
187#endif
188		if (*(tmp+3) & 0x40) {
189			ccg->cylinders += (*(tmp+1)&0xf0)<<8;
190			ccg->heads = *(tmp+1)&0x0f;
191		} else {
192			ccg->heads = *(tmp+1);
193		}
194		return (1);
195	}
196
197	return (0);
198}
199
200/*
201 * Get the geometry of the ATA HDD from the BIOS work area.
202 *
203 * XXX for now, we hack it
204 */
205void
206pc98_ad_firmware_geom_adjust(device_t dev, struct disk *disk)
207{
208	off_t totsec = disk->d_mediasize / disk->d_sectorsize;
209	off_t cyl = totsec / disk->d_fwsectors / disk->d_fwheads;
210
211	/*
212	 * It is impossible to have more than 65535 cylendars, so if
213	 * we have more then try to adjust.  This is lame, but it is
214	 * only POC.
215	 */
216	if (cyl > 65355) {
217		if (totsec < 17*8*65535) {
218			disk->d_fwsectors = 17;
219			disk->d_fwheads = 8;
220		} else if (totsec < 63*16*65535) {
221			disk->d_fwsectors = 63;
222			disk->d_fwheads = 16;
223		} else if (totsec < 255*16*65535) {
224			disk->d_fwsectors = 255;
225			disk->d_fwheads = 16;
226		} else {
227			disk->d_fwsectors = 255;
228			disk->d_fwheads = 255;
229		}
230	}
231}
232