xref: /trueos/sys/pc98/pc98/pc98_machdep.c (revision 8fe640108653f13042f1b15213769e338aa524f6)
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$
32  */
33 
34 #include "opt_pc98.h"
35 
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 
39 #include <sys/bio.h>
40 #include <sys/bus.h>
41 #include <sys/conf.h>
42 #include <sys/kernel.h>
43 #include <sys/sysctl.h>
44 #include <cam/cam.h>
45 #include <cam/cam_ccb.h>
46 #include <geom/geom_disk.h>
47 #include <machine/md_var.h>
48 #include <pc98/pc98/pc98_machdep.h>
49 
50 static	int	ad_geom_method = AD_GEOM_ADJUST_COMPATIDE;
51 
52 TUNABLE_INT("machdep.ad_geom_method", &ad_geom_method);
53 SYSCTL_INT(_machdep, OID_AUTO, ad_geom_method, CTLFLAG_RW, &ad_geom_method, 0,
54     "IDE disk geometry conversion method");
55 
56 /*
57  * Initialize DMA controller
58  */
59 void
pc98_init_dmac(void)60 pc98_init_dmac(void)
61 {
62 	outb(0x439, (inb(0x439) & 0xfb));	/* DMA Accsess Control over 1MB */
63 	outb(0x29, (0x0c | 0));				/* Bank Mode Reg. 16M mode */
64 	outb(0x29, (0x0c | 1));				/* Bank Mode Reg. 16M mode */
65 	outb(0x29, (0x0c | 2));				/* Bank Mode Reg. 16M mode */
66 	outb(0x29, (0x0c | 3));				/* Bank Mode Reg. 16M mode */
67 	outb(0x11, 0x50);
68 }
69 
70 #ifdef EPSON_MEMWIN
71 /*
72  * Disconnect phisical memory in 15-16MB region.
73  *
74  * EPSON PC-486GR, P, SR, SE, HX, HG and HA only.  Other system support
75  * this feature with software DIP switch.
76  */
77 static void
init_epson_memwin(void)78 init_epson_memwin(void)
79 {
80 	/* Disable 15MB-16MB caching. */
81 	switch (epson_machine_id) {
82 	case EPSON_PC486_HX:
83 	case EPSON_PC486_HG:
84 	case EPSON_PC486_HA:
85 		/* Cache control start. */
86 		outb(0x43f, 0x42);
87 		outw(0xc40, 0x0033);
88 
89 		/* Disable 0xF00000-0xFFFFFF. */
90 		outb(0xc48, 0x49);
91 		outb(0xc4c, 0x00);
92 		outb(0xc48, 0x48);
93 		outb(0xc4c, 0xf0);
94 		outb(0xc48, 0x4d);
95 		outb(0xc4c, 0x00);
96 		outb(0xc48, 0x4c);
97 		outb(0xc4c, 0xff);
98 		outb(0xc48, 0x4f);
99 		outb(0xc4c, 0x00);
100 
101 		/* Cache control end. */
102 		outb(0x43f, 0x40);
103 		break;
104 
105 	case EPSON_PC486_GR:
106 	case EPSON_PC486_P:
107 	case EPSON_PC486_GR_SUPER:
108 	case EPSON_PC486_GR_PLUS:
109 	case EPSON_PC486_SE:
110 	case EPSON_PC486_SR:
111 		/* Disable 0xF00000-0xFFFFFF. */
112 		outb(0x43f, 0x42);
113 		outb(0x467, 0xe0);
114 		outb(0x567, 0xd8);
115 
116 		outb(0x43f, 0x40);
117 		outb(0x467, 0xe0);
118 		outb(0x567, 0xe0);
119 		break;
120 	}
121 
122 	/* Disable 15MB-16MB RAM and enable memory window. */
123 	outb(0x43b, inb(0x43b) & 0xfd);	/* Clear bit1. */
124 }
125 #endif
126 
127 /*
128  * Get physical memory size
129  */
130 unsigned int
pc98_getmemsize(unsigned int * base,unsigned int * ext)131 pc98_getmemsize(unsigned int *base, unsigned int *ext)
132 {
133 	unsigned int under16, over16;
134 
135 	/* available conventional memory size */
136 	*base = ((PC98_SYSTEM_PARAMETER(0x501) & 7) + 1) * 128;
137 
138 	/* available protected memory size under 16MB */
139 	under16 = PC98_SYSTEM_PARAMETER(0x401) * 128 + 1024;
140 #ifdef EPSON_MEMWIN
141 	if (pc98_machine_type & M_EPSON_PC98) {
142 		if (under16 > (15 * 1024))
143 			/* chop under16 memory to 15MB */
144 			under16 = 15 * 1024;
145 		init_epson_memwin();
146 	}
147 #endif
148 
149 	/* available protected memory size over 16MB / 1MB */
150 	over16  = PC98_SYSTEM_PARAMETER(0x594);
151 	over16 += PC98_SYSTEM_PARAMETER(0x595) * 256;
152 
153 	if (over16 > 0)
154 		*ext = (16 + over16) * 1024 - 1024;
155 	else
156 		*ext = under16 - 1024;
157 
158 	return (under16);
159 }
160 
161 /*
162  * Read a geometry information of SCSI HDD from BIOS work area.
163  *
164  * XXX - Before reading BIOS work area, we should check whether
165  * host adapter support it.
166  */
167 int
scsi_da_bios_params(struct ccb_calc_geometry * ccg)168 scsi_da_bios_params(struct ccb_calc_geometry *ccg)
169 {
170 	u_char *tmp;
171 	int	target;
172 
173 	target = ccg->ccb_h.target_id;
174 	tmp = (u_char *)&PC98_SYSTEM_PARAMETER(0x460 + target*4);
175 	if ((PC98_SYSTEM_PARAMETER(0x482) & ((1 << target)&0xff)) != 0) {
176 		ccg->secs_per_track = *tmp;
177 		ccg->cylinders = ((*(tmp+3)<<8)|*(tmp+2))&0xfff;
178 #if 0
179 		switch (*(tmp + 3) & 0x30) {
180 		case 0x00:
181 			disk_parms->secsiz = 256;
182 			printf("Warning!: not supported.\n");
183 			break;
184 		case 0x10:
185 			disk_parms->secsiz = 512;
186 			break;
187 		case 0x20:
188 			disk_parms->secsiz = 1024;
189 			break;
190 		default:
191 			disk_parms->secsiz = 512;
192 			printf("Warning!: not supported. But force to 512\n");
193 			break;
194 		}
195 #endif
196 		if (*(tmp+3) & 0x40) {
197 			ccg->cylinders += (*(tmp+1)&0xf0)<<8;
198 			ccg->heads = *(tmp+1)&0x0f;
199 		} else {
200 			ccg->heads = *(tmp+1);
201 		}
202 		return (1);
203 	}
204 
205 	return (0);
206 }
207 
208 /*
209  * Adjust the geometry of the IDE HDD.
210  */
211 
212 /* IDE BIOS compatible mode. */
213 static	void
pc98_ata_disk_geom_adjust_idebios(struct disk * disk)214 pc98_ata_disk_geom_adjust_idebios(struct disk *disk)
215 {
216 
217 	if (disk->d_mediasize < MEDIASIZE_4_3G) {
218 		disk->d_fwsectors = 17;
219 		disk->d_fwheads = 8;
220 	} else if (disk->d_mediasize < MEDIASIZE_29_5G) {
221 		disk->d_fwsectors = 63;
222 		if (disk->d_fwheads != 15)	/* Allow 15H63S. */
223 			disk->d_fwheads = 16;
224 	} else if (disk->d_mediasize < MEDIASIZE_31_5G) {
225 		disk->d_fwsectors = 63;
226 		disk->d_fwheads = 16;
227 	} else if (disk->d_mediasize < MEDIASIZE_127G) {
228 		disk->d_fwsectors = 255;
229 		disk->d_fwheads = 16;
230 	} else {
231 		/* XXX */
232 		disk->d_fwsectors = 255;
233 		disk->d_fwheads = 255;
234 	}
235 }
236 
237 /* SCSI BIOS compatible mode. */
238 static	void
pc98_ata_disk_geom_adjust_scsibios(struct disk * disk)239 pc98_ata_disk_geom_adjust_scsibios(struct disk *disk)
240 {
241 
242 	if (disk->d_mediasize < MEDIASIZE_8G) {
243 		disk->d_fwsectors = 32;
244 		disk->d_fwheads = 8;
245 	} else if (disk->d_mediasize < MEDIASIZE_32G) {
246 		disk->d_fwsectors = 128;
247 		disk->d_fwheads = 8;
248 	} else if (disk->d_mediasize < MEDIASIZE_60G) {
249 		/* Compatible with IFC-USP 1.2. */
250 		disk->d_fwsectors = 128;
251 		disk->d_fwheads = 15;
252 	} else if (disk->d_mediasize < MEDIASIZE_120G) {
253 		disk->d_fwsectors = 255;
254 		disk->d_fwheads = 15;
255 	} else {
256 		/* XXX */
257 		disk->d_fwsectors = 255;
258 		disk->d_fwheads = 255;
259 	}
260 }
261 
262 /* Compatible with the revision 1.28. */
263 static	void
pc98_ata_disk_geom_adjust_cyl16bit(struct disk * disk)264 pc98_ata_disk_geom_adjust_cyl16bit(struct disk *disk)
265 {
266 	off_t totsec = disk->d_mediasize / disk->d_sectorsize;
267 	off_t cyl = totsec / disk->d_fwsectors / disk->d_fwheads;
268 
269 	/*
270 	 * It is impossible to have more than 65535 cylinders, so if
271 	 * we have more then try to adjust.  This is lame, but it is
272 	 * only POC.
273 	 */
274 	if (cyl > 65355) {
275 		if (totsec < 17*8*65535) {
276 			disk->d_fwsectors = 17;
277 			disk->d_fwheads = 8;
278 		} else if (totsec < 63*16*65535) {
279 			disk->d_fwsectors = 63;
280 			disk->d_fwheads = 16;
281 		} else if (totsec < 255*16*65535) {
282 			disk->d_fwsectors = 255;
283 			disk->d_fwheads = 16;
284 		} else {
285 			disk->d_fwsectors = 255;
286 			disk->d_fwheads = 255;
287 		}
288 	}
289 }
290 
291 void
pc98_ata_disk_firmware_geom_adjust(struct disk * disk)292 pc98_ata_disk_firmware_geom_adjust(struct disk *disk)
293 {
294 	u_int	oldsectors, oldheads;
295 
296 	oldsectors = disk->d_fwsectors;
297 	oldheads = disk->d_fwheads;
298 
299 	switch (ad_geom_method) {
300 	case AD_GEOM_ADJUST_COMPATIDE:
301 		pc98_ata_disk_geom_adjust_idebios(disk);
302 		break;
303 	case AD_GEOM_ADJUST_COMPATSCSI:
304 		pc98_ata_disk_geom_adjust_scsibios(disk);
305 		break;
306 	case AD_GEOM_ADJUST_COMPATCYL16:
307 		pc98_ata_disk_geom_adjust_cyl16bit(disk);
308 		break;
309 	default:
310 		/* Do nothing. */
311 		break;
312 	}
313 
314 	if (bootverbose &&
315 	    (oldsectors != disk->d_fwsectors || oldheads != disk->d_fwheads))
316 		printf(
317 		    "%s%d: geometry adjusted from [%dH/%dS] to [%dH/%dS]\n",
318 		    disk->d_name, disk->d_unit,
319 		    oldheads, oldsectors,
320 		    disk->d_fwheads, disk->d_fwsectors);
321 }
322