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