From 5b1802a644975116f659a38a856e52149303221a Mon Sep 17 00:00:00 2001 From: kato Date: Mon, 27 Oct 2008 08:40:13 +0000 Subject: Improved IDE HDD geometry adjustment. Previous code didn't work with certain ATA-6 drives including CF cards. The IDE geometry of the PC98 is calculated from the drive capacity. In addition to the algorithm in NEC BIOS, a variety of algorithms are provided by 3'rd party boards and BIOS hacks. This change has implemented the three algorithms: IDE BIOS compatible mode, SCSI BIOS compatible mode and same way as the previous version. The tunable machdep.ad_geom_method selects the algorithm. I have been using this change for a year with CF cards. Reminded by: nyan --- sys/pc98/pc98/pc98_machdep.c | 104 ++++++++++++++++++++++++++++++++++++++++--- sys/pc98/pc98/pc98_machdep.h | 15 +++++++ 2 files changed, 112 insertions(+), 7 deletions(-) (limited to 'sys/pc98') diff --git a/sys/pc98/pc98/pc98_machdep.c b/sys/pc98/pc98/pc98_machdep.c index badf6a3..31bb756 100644 --- a/sys/pc98/pc98/pc98_machdep.c +++ b/sys/pc98/pc98/pc98_machdep.c @@ -36,15 +36,23 @@ #include #include -#include -#include #include #include #include +#include +#include +#include +#include #include #include #include +static int ad_geom_method = AD_GEOM_ADJUST_COMPATIDE; + +TUNABLE_INT("machdep.ad_geom_method", &ad_geom_method); +SYSCTL_INT(_machdep, OID_AUTO, ad_geom_method, CTLFLAG_RW, &ad_geom_method, 0, + "IDE disk geometry conversion method"); + /* * Initialize DMA controller */ @@ -198,12 +206,62 @@ scsi_da_bios_params(struct ccb_calc_geometry *ccg) } /* - * Get the geometry of the ATA HDD from the BIOS work area. - * - * XXX for now, we hack it + * Adjust the geometry of the IDE HDD. */ -void -pc98_ad_firmware_geom_adjust(device_t dev, struct disk *disk) + +/* IDE BIOS compatible mode. */ +static void +pc98_ad_geom_adjust_idebios(struct disk *disk) +{ + + if (disk->d_mediasize < MEDIASIZE_4_3G) { + disk->d_fwsectors = 17; + disk->d_fwheads = 8; + } else if (disk->d_mediasize < MEDIASIZE_29_5G) { + disk->d_fwsectors = 63; + if (disk->d_fwheads != 15) /* Allow 15H63S. */ + disk->d_fwheads = 16; + } else if (disk->d_mediasize < MEDIASIZE_31_5G) { + disk->d_fwsectors = 63; + disk->d_fwheads = 16; + } else if (disk->d_mediasize < MEDIASIZE_127G) { + disk->d_fwsectors = 255; + disk->d_fwheads = 16; + } else { + /* XXX */ + disk->d_fwsectors = 255; + disk->d_fwheads = 255; + } +} + +/* SCSI BIOS compatible mode. */ +static void +pc98_ad_geom_adjust_scsibios(struct disk *disk) +{ + + if (disk->d_mediasize < MEDIASIZE_8G) { + disk->d_fwsectors = 32; + disk->d_fwheads = 8; + } else if (disk->d_mediasize < MEDIASIZE_32G) { + disk->d_fwsectors = 128; + disk->d_fwheads = 8; + } else if (disk->d_mediasize < MEDIASIZE_60G) { + /* Compatible with IFC-USP 1.2. */ + disk->d_fwsectors = 128; + disk->d_fwheads = 15; + } else if (disk->d_mediasize < MEDIASIZE_120G) { + disk->d_fwsectors = 255; + disk->d_fwheads = 15; + } else { + /* XXX */ + disk->d_fwsectors = 255; + disk->d_fwheads = 255; + } +} + +/* Compatible with the revision 1.28. */ +static void +pc98_ad_geom_adjust_cyl16bit(struct disk *disk) { off_t totsec = disk->d_mediasize / disk->d_sectorsize; off_t cyl = totsec / disk->d_fwsectors / disk->d_fwheads; @@ -229,3 +287,35 @@ pc98_ad_firmware_geom_adjust(device_t dev, struct disk *disk) } } } + +void +pc98_ad_firmware_geom_adjust(device_t dev, struct disk *disk) +{ + u_int oldsectors, oldheads; + + oldsectors = disk->d_fwsectors; + oldheads = disk->d_fwheads; + + switch (ad_geom_method) { + case AD_GEOM_ADJUST_COMPATIDE: + pc98_ad_geom_adjust_idebios(disk); + break; + case AD_GEOM_ADJUST_COMPATSCSI: + pc98_ad_geom_adjust_scsibios(disk); + break; + case AD_GEOM_ADJUST_COMPATCYL16: + pc98_ad_geom_adjust_cyl16bit(disk); + break; + default: + /* Do nothing. */ + break; + } + + if (bootverbose && + (oldsectors != disk->d_fwsectors || oldheads != disk->d_fwheads)) + device_printf(dev, + "geometry adjusted from [%dH/%dS] to [%dH/%dS]\n", + oldheads, oldsectors, + disk->d_fwheads, disk->d_fwsectors); + +} diff --git a/sys/pc98/pc98/pc98_machdep.h b/sys/pc98/pc98/pc98_machdep.h index ffd4ba8..6113f14 100644 --- a/sys/pc98/pc98/pc98_machdep.h +++ b/sys/pc98/pc98/pc98_machdep.h @@ -85,6 +85,21 @@ extern unsigned char pc98_system_parameter[]; /* in locore.c */ #define EPSON_PC486_SR 0x38 #define EPSON_PC486_HA 0x3b +/* IDE HDD geometry conversion. */ +#define AD_GEOM_ADJUST_NONE 0 /* Do nothing. */ +#define AD_GEOM_ADJUST_COMPATIDE 1 /* PC-98 IDE BIOS. */ +#define AD_GEOM_ADJUST_COMPATSCSI 2 /* PC-98 SCSI. */ +#define AD_GEOM_ADJUST_COMPATCYL16 100 /* Compat Rev. 1.28. */ + +#define MEDIASIZE_4_3G (4351LL * 1024LL * 1024LL) /* 4351M */ +#define MEDIASIZE_8G (8192LL * 1024LL * 1024LL) /* 8192M */ +#define MEDIASIZE_29_5G (30239LL * 1024LL * 1024LL) /* 30239M */ +#define MEDIASIZE_31_5G (32255LL * 1024 * 1024) /* 32255M */ +#define MEDIASIZE_32G (32768LL * 1024LL * 1024LL) /* 32768M */ +#define MEDIASIZE_60G (61440LL * 1024LL * 1024LL) /* 61440M */ +#define MEDIASIZE_120G (122400LL * 1024LL * 1024LL) /* 122400M */ +#define MEDIASIZE_127G (130558LL * 1024LL * 1024LL) /* 130558M */ + #endif /* _KERNEL */ #endif /* __PC98_PC98_PC98_MACHDEP_H__ */ -- cgit v1.1