1139825Simp/*-
222338Skato * Copyright (c) KATO Takenori, 1996, 1997.
322338Skato *
422338Skato * All rights reserved.  Unpublished rights reserved under the copyright
522338Skato * laws of Japan.
622338Skato *
717350Sasami *
817350Sasami * Redistribution and use in source and binary forms, with or without
917350Sasami * modification, are permitted provided that the following conditions
1017350Sasami * are met:
1117350Sasami * 1. Redistributions of source code must retain the above copyright
1217350Sasami *    notice, this list of conditions and the following disclaimer as
1317350Sasami *    the first lines of this file unmodified.
1417350Sasami * 2. Redistributions in binary form must reproduce the above copyright
1517350Sasami *    notice, this list of conditions and the following disclaimer in the
1617350Sasami *    documentation and/or other materials provided with the distribution.
1717350Sasami * 3. The name of the author may not be used to endorse or promote products
1817350Sasami *    derived from this software without specific prior written permission.
1917350Sasami *
2017350Sasami * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2117350Sasami * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2217350Sasami * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2317350Sasami * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2417350Sasami * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2517350Sasami * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2617350Sasami * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2717350Sasami * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2817350Sasami * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2917350Sasami * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3052467Snyan *
3152467Snyan * $FreeBSD: releng/10.3/sys/pc98/pc98/pc98_machdep.c 208349 2010-05-20 12:46:19Z marius $
3217350Sasami */
3317350Sasami
3433715Skato#include "opt_pc98.h"
3533715Skato
3617350Sasami#include <sys/param.h>
3717350Sasami#include <sys/systm.h>
3817350Sasami
39161129Simp#include <sys/bio.h>
40161129Simp#include <sys/bus.h>
41161129Simp#include <sys/conf.h>
42184327Skato#include <sys/kernel.h>
43184327Skato#include <sys/sysctl.h>
44184327Skato#include <cam/cam.h>
45184327Skato#include <cam/cam_ccb.h>
46161129Simp#include <geom/geom_disk.h>
47161129Simp#include <machine/md_var.h>
4822407Skato#include <pc98/pc98/pc98_machdep.h>
4917350Sasami
50184327Skatostatic	int	ad_geom_method = AD_GEOM_ADJUST_COMPATIDE;
51184327Skato
52184327SkatoTUNABLE_INT("machdep.ad_geom_method", &ad_geom_method);
53184327SkatoSYSCTL_INT(_machdep, OID_AUTO, ad_geom_method, CTLFLAG_RW, &ad_geom_method, 0,
54184327Skato    "IDE disk geometry conversion method");
55184327Skato
5622338Skato/*
5722338Skato * Initialize DMA controller
5822338Skato */
5922338Skatovoid
6022338Skatopc98_init_dmac(void)
6122338Skato{
6222338Skato	outb(0x439, (inb(0x439) & 0xfb));	/* DMA Accsess Control over 1MB */
6322338Skato	outb(0x29, (0x0c | 0));				/* Bank Mode Reg. 16M mode */
6422338Skato	outb(0x29, (0x0c | 1));				/* Bank Mode Reg. 16M mode */
6522338Skato	outb(0x29, (0x0c | 2));				/* Bank Mode Reg. 16M mode */
6622338Skato	outb(0x29, (0x0c | 3));				/* Bank Mode Reg. 16M mode */
6722338Skato	outb(0x11, 0x50);
6822338Skato}
6922338Skato
7017350Sasami#ifdef EPSON_MEMWIN
7122338Skato/*
7222338Skato * Disconnect phisical memory in 15-16MB region.
7322338Skato *
7422338Skato * EPSON PC-486GR, P, SR, SE, HX, HG and HA only.  Other system support
7522338Skato * this feature with software DIP switch.
7622338Skato */
7722165Skatostatic void
7822165Skatoinit_epson_memwin(void)
7917350Sasami{
8058145Snyan	/* Disable 15MB-16MB caching. */
8158145Snyan	switch (epson_machine_id) {
82150128Snyan	case EPSON_PC486_HX:
83150128Snyan	case EPSON_PC486_HG:
84150128Snyan	case EPSON_PC486_HA:
8558145Snyan		/* Cache control start. */
8658145Snyan		outb(0x43f, 0x42);
8758145Snyan		outw(0xc40, 0x0033);
8822165Skato
8958145Snyan		/* Disable 0xF00000-0xFFFFFF. */
9058145Snyan		outb(0xc48, 0x49);
9158145Snyan		outb(0xc4c, 0x00);
9258145Snyan		outb(0xc48, 0x48);
9358145Snyan		outb(0xc4c, 0xf0);
9458145Snyan		outb(0xc48, 0x4d);
9558145Snyan		outb(0xc4c, 0x00);
9658145Snyan		outb(0xc48, 0x4c);
9758145Snyan		outb(0xc4c, 0xff);
9858145Snyan		outb(0xc48, 0x4f);
9958145Snyan		outb(0xc4c, 0x00);
10017350Sasami
10158145Snyan		/* Cache control end. */
10258145Snyan		outb(0x43f, 0x40);
10358145Snyan		break;
10417350Sasami
105150128Snyan	case EPSON_PC486_GR:
106150128Snyan	case EPSON_PC486_P:
107150128Snyan	case EPSON_PC486_GR_SUPER:
108150128Snyan	case EPSON_PC486_GR_PLUS:
109150128Snyan	case EPSON_PC486_SE:
110150128Snyan	case EPSON_PC486_SR:
11158145Snyan		/* Disable 0xF00000-0xFFFFFF. */
11258145Snyan		outb(0x43f, 0x42);
11358145Snyan		outb(0x467, 0xe0);
11458145Snyan		outb(0x567, 0xd8);
11517350Sasami
11658145Snyan		outb(0x43f, 0x40);
11758145Snyan		outb(0x467, 0xe0);
11858145Snyan		outb(0x567, 0xe0);
11958145Snyan		break;
12017350Sasami	}
12117350Sasami
12258145Snyan	/* Disable 15MB-16MB RAM and enable memory window. */
12358145Snyan	outb(0x43b, inb(0x43b) & 0xfd);	/* Clear bit1. */
12417350Sasami}
12522165Skato#endif
12617350Sasami
12722338Skato/*
12822338Skato * Get physical memory size
12922338Skato */
13076931Snyanunsigned int
13176931Snyanpc98_getmemsize(unsigned int *base, unsigned int *ext)
13218846Sasami{
13376931Snyan	unsigned int under16, over16;
13418846Sasami
13558145Snyan	/* available conventional memory size */
13658145Snyan	*base = ((PC98_SYSTEM_PARAMETER(0x501) & 7) + 1) * 128;
13718846Sasami
13858145Snyan	/* available protected memory size under 16MB */
13976931Snyan	under16 = PC98_SYSTEM_PARAMETER(0x401) * 128 + 1024;
14018846Sasami#ifdef EPSON_MEMWIN
14158145Snyan	if (pc98_machine_type & M_EPSON_PC98) {
142144257Simp		if (under16 > (15 * 1024))
14358145Snyan			/* chop under16 memory to 15MB */
14476931Snyan			under16 = 15 * 1024;
14558145Snyan		init_epson_memwin();
14658145Snyan	}
14718846Sasami#endif
14858145Snyan
14958145Snyan	/* available protected memory size over 16MB / 1MB */
15058145Snyan	over16  = PC98_SYSTEM_PARAMETER(0x594);
15158145Snyan	over16 += PC98_SYSTEM_PARAMETER(0x595) * 256;
15258145Snyan
153144257Simp	if (over16 > 0)
15476931Snyan		*ext = (16 + over16) * 1024 - 1024;
155144257Simp	else
15676931Snyan		*ext = under16 - 1024;
15776931Snyan
158144257Simp	return (under16);
15918846Sasami}
16022263Skato
16122263Skato/*
16222263Skato * Read a geometry information of SCSI HDD from BIOS work area.
16322263Skato *
16422263Skato * XXX - Before reading BIOS work area, we should check whether
16522263Skato * host adapter support it.
16622263Skato */
16722263Skatoint
16839246Sgibbsscsi_da_bios_params(struct ccb_calc_geometry *ccg)
16922263Skato{
17022263Skato	u_char *tmp;
17139246Sgibbs	int	target;
17222263Skato
17339246Sgibbs	target = ccg->ccb_h.target_id;
17439246Sgibbs	tmp = (u_char *)&PC98_SYSTEM_PARAMETER(0x460 + target*4);
17539246Sgibbs	if ((PC98_SYSTEM_PARAMETER(0x482) & ((1 << target)&0xff)) != 0) {
17639246Sgibbs		ccg->secs_per_track = *tmp;
17739246Sgibbs		ccg->cylinders = ((*(tmp+3)<<8)|*(tmp+2))&0xfff;
17839246Sgibbs#if 0
17922263Skato		switch (*(tmp + 3) & 0x30) {
18022263Skato		case 0x00:
18122263Skato			disk_parms->secsiz = 256;
18222263Skato			printf("Warning!: not supported.\n");
18322263Skato			break;
18422263Skato		case 0x10:
18522263Skato			disk_parms->secsiz = 512;
18622263Skato			break;
18722263Skato		case 0x20:
18822263Skato			disk_parms->secsiz = 1024;
18922263Skato			break;
19022263Skato		default:
19122263Skato			disk_parms->secsiz = 512;
19222263Skato			printf("Warning!: not supported. But force to 512\n");
19322263Skato			break;
19422263Skato		}
19539246Sgibbs#endif
19622263Skato		if (*(tmp+3) & 0x40) {
19739246Sgibbs			ccg->cylinders += (*(tmp+1)&0xf0)<<8;
19839246Sgibbs			ccg->heads = *(tmp+1)&0x0f;
19922263Skato		} else {
20039246Sgibbs			ccg->heads = *(tmp+1);
20122263Skato		}
202144257Simp		return (1);
20322263Skato	}
20461654Skato
205144257Simp	return (0);
20622263Skato}
207161129Simp
208161129Simp/*
209184327Skato * Adjust the geometry of the IDE HDD.
210161129Simp */
211184327Skato
212184327Skato/* IDE BIOS compatible mode. */
213184327Skatostatic	void
214208349Smariuspc98_ata_disk_geom_adjust_idebios(struct disk *disk)
215161129Simp{
216184327Skato
217184327Skato	if (disk->d_mediasize < MEDIASIZE_4_3G) {
218184327Skato		disk->d_fwsectors = 17;
219184327Skato		disk->d_fwheads = 8;
220184327Skato	} else if (disk->d_mediasize < MEDIASIZE_29_5G) {
221184327Skato		disk->d_fwsectors = 63;
222184327Skato		if (disk->d_fwheads != 15)	/* Allow 15H63S. */
223184327Skato			disk->d_fwheads = 16;
224184327Skato	} else if (disk->d_mediasize < MEDIASIZE_31_5G) {
225184327Skato		disk->d_fwsectors = 63;
226184327Skato		disk->d_fwheads = 16;
227184327Skato	} else if (disk->d_mediasize < MEDIASIZE_127G) {
228184327Skato		disk->d_fwsectors = 255;
229184327Skato		disk->d_fwheads = 16;
230184327Skato	} else {
231184327Skato		/* XXX */
232184327Skato		disk->d_fwsectors = 255;
233184327Skato		disk->d_fwheads = 255;
234184327Skato	}
235184327Skato}
236184327Skato
237184327Skato/* SCSI BIOS compatible mode. */
238184327Skatostatic	void
239208349Smariuspc98_ata_disk_geom_adjust_scsibios(struct disk *disk)
240184327Skato{
241184327Skato
242184327Skato	if (disk->d_mediasize < MEDIASIZE_8G) {
243184327Skato		disk->d_fwsectors = 32;
244184327Skato		disk->d_fwheads = 8;
245184327Skato	} else if (disk->d_mediasize < MEDIASIZE_32G) {
246184327Skato		disk->d_fwsectors = 128;
247184327Skato		disk->d_fwheads = 8;
248184327Skato	} else if (disk->d_mediasize < MEDIASIZE_60G) {
249184327Skato		/* Compatible with IFC-USP 1.2. */
250184327Skato		disk->d_fwsectors = 128;
251184327Skato		disk->d_fwheads = 15;
252184327Skato	} else if (disk->d_mediasize < MEDIASIZE_120G) {
253184327Skato		disk->d_fwsectors = 255;
254184327Skato		disk->d_fwheads = 15;
255184327Skato	} else {
256184327Skato		/* XXX */
257184327Skato		disk->d_fwsectors = 255;
258184327Skato		disk->d_fwheads = 255;
259184327Skato	}
260184327Skato}
261184327Skato
262184327Skato/* Compatible with the revision 1.28. */
263184327Skatostatic	void
264208349Smariuspc98_ata_disk_geom_adjust_cyl16bit(struct disk *disk)
265184327Skato{
266161129Simp	off_t totsec = disk->d_mediasize / disk->d_sectorsize;
267161129Simp	off_t cyl = totsec / disk->d_fwsectors / disk->d_fwheads;
268208349Smarius
269161129Simp	/*
270208349Smarius	 * It is impossible to have more than 65535 cylinders, so if
271161129Simp	 * we have more then try to adjust.  This is lame, but it is
272161129Simp	 * only POC.
273161129Simp	 */
274161129Simp	if (cyl > 65355) {
275161129Simp		if (totsec < 17*8*65535) {
276161129Simp			disk->d_fwsectors = 17;
277161129Simp			disk->d_fwheads = 8;
278161129Simp		} else if (totsec < 63*16*65535) {
279161129Simp			disk->d_fwsectors = 63;
280161129Simp			disk->d_fwheads = 16;
281161129Simp		} else if (totsec < 255*16*65535) {
282161129Simp			disk->d_fwsectors = 255;
283161129Simp			disk->d_fwheads = 16;
284161129Simp		} else {
285161129Simp			disk->d_fwsectors = 255;
286161129Simp			disk->d_fwheads = 255;
287161129Simp		}
288161129Simp	}
289161129Simp}
290184327Skato
291184327Skatovoid
292208349Smariuspc98_ata_disk_firmware_geom_adjust(struct disk *disk)
293184327Skato{
294184327Skato	u_int	oldsectors, oldheads;
295184327Skato
296184327Skato	oldsectors = disk->d_fwsectors;
297184327Skato	oldheads = disk->d_fwheads;
298184327Skato
299184327Skato	switch (ad_geom_method) {
300184327Skato	case AD_GEOM_ADJUST_COMPATIDE:
301208349Smarius		pc98_ata_disk_geom_adjust_idebios(disk);
302184327Skato		break;
303184327Skato	case AD_GEOM_ADJUST_COMPATSCSI:
304208349Smarius		pc98_ata_disk_geom_adjust_scsibios(disk);
305184327Skato		break;
306184327Skato	case AD_GEOM_ADJUST_COMPATCYL16:
307208349Smarius		pc98_ata_disk_geom_adjust_cyl16bit(disk);
308184327Skato		break;
309184327Skato	default:
310184327Skato		/* Do nothing. */
311184327Skato		break;
312184327Skato	}
313184327Skato
314184327Skato	if (bootverbose &&
315184327Skato	    (oldsectors != disk->d_fwsectors || oldheads != disk->d_fwheads))
316208349Smarius		printf(
317208349Smarius		    "%s%d: geometry adjusted from [%dH/%dS] to [%dH/%dS]\n",
318208349Smarius		    disk->d_name, disk->d_unit,
319184327Skato		    oldheads, oldsectors,
320184327Skato		    disk->d_fwheads, disk->d_fwsectors);
321184327Skato}
322