2 * Copyright (c) KATO Takenori, 1996, 1997.
4 * All rights reserved. Unpublished rights reserved under the copyright
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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.
36 #include <sys/param.h>
37 #include <sys/systm.h>
42 #include <sys/kernel.h>
43 #include <sys/sysctl.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>
50 static int ad_geom_method = AD_GEOM_ADJUST_COMPATIDE;
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");
57 * Initialize DMA controller
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 */
72 * Disconnect phisical memory in 15-16MB region.
74 * EPSON PC-486GR, P, SR, SE, HX, HG and HA only. Other system support
75 * this feature with software DIP switch.
78 init_epson_memwin(void)
80 /* Disable 15MB-16MB caching. */
81 switch (epson_machine_id) {
85 /* Cache control start. */
89 /* Disable 0xF00000-0xFFFFFF. */
101 /* Cache control end. */
107 case EPSON_PC486_GR_SUPER:
108 case EPSON_PC486_GR_PLUS:
111 /* Disable 0xF00000-0xFFFFFF. */
122 /* Disable 15MB-16MB RAM and enable memory window. */
123 outb(0x43b, inb(0x43b) & 0xfd); /* Clear bit1. */
128 * Get physical memory size
131 pc98_getmemsize(unsigned int *base, unsigned int *ext)
133 unsigned int under16, over16;
135 /* available conventional memory size */
136 *base = ((PC98_SYSTEM_PARAMETER(0x501) & 7) + 1) * 128;
138 /* available protected memory size under 16MB */
139 under16 = PC98_SYSTEM_PARAMETER(0x401) * 128 + 1024;
141 if (pc98_machine_type & M_EPSON_PC98) {
142 if (under16 > (15 * 1024))
143 /* chop under16 memory to 15MB */
149 /* available protected memory size over 16MB / 1MB */
150 over16 = PC98_SYSTEM_PARAMETER(0x594);
151 over16 += PC98_SYSTEM_PARAMETER(0x595) * 256;
154 *ext = (16 + over16) * 1024 - 1024;
156 *ext = under16 - 1024;
162 * Read a geometry information of SCSI HDD from BIOS work area.
164 * XXX - Before reading BIOS work area, we should check whether
165 * host adapter support it.
168 scsi_da_bios_params(struct ccb_calc_geometry *ccg)
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;
179 switch (*(tmp + 3) & 0x30) {
181 disk_parms->secsiz = 256;
182 printf("Warning!: not supported.\n");
185 disk_parms->secsiz = 512;
188 disk_parms->secsiz = 1024;
191 disk_parms->secsiz = 512;
192 printf("Warning!: not supported. But force to 512\n");
196 if (*(tmp+3) & 0x40) {
197 ccg->cylinders += (*(tmp+1)&0xf0)<<8;
198 ccg->heads = *(tmp+1)&0x0f;
200 ccg->heads = *(tmp+1);
209 * Adjust the geometry of the IDE HDD.
212 /* IDE BIOS compatible mode. */
214 pc98_ata_disk_geom_adjust_idebios(struct disk *disk)
217 if (disk->d_mediasize < MEDIASIZE_4_3G) {
218 disk->d_fwsectors = 17;
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;
232 disk->d_fwsectors = 255;
233 disk->d_fwheads = 255;
237 /* SCSI BIOS compatible mode. */
239 pc98_ata_disk_geom_adjust_scsibios(struct disk *disk)
242 if (disk->d_mediasize < MEDIASIZE_8G) {
243 disk->d_fwsectors = 32;
245 } else if (disk->d_mediasize < MEDIASIZE_32G) {
246 disk->d_fwsectors = 128;
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;
257 disk->d_fwsectors = 255;
258 disk->d_fwheads = 255;
262 /* Compatible with the revision 1.28. */
264 pc98_ata_disk_geom_adjust_cyl16bit(struct disk *disk)
266 off_t totsec = disk->d_mediasize / disk->d_sectorsize;
267 off_t cyl = totsec / disk->d_fwsectors / disk->d_fwheads;
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
275 if (totsec < 17*8*65535) {
276 disk->d_fwsectors = 17;
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;
285 disk->d_fwsectors = 255;
286 disk->d_fwheads = 255;
292 pc98_ata_disk_firmware_geom_adjust(struct disk *disk)
294 u_int oldsectors, oldheads;
296 oldsectors = disk->d_fwsectors;
297 oldheads = disk->d_fwheads;
299 switch (ad_geom_method) {
300 case AD_GEOM_ADJUST_COMPATIDE:
301 pc98_ata_disk_geom_adjust_idebios(disk);
303 case AD_GEOM_ADJUST_COMPATSCSI:
304 pc98_ata_disk_geom_adjust_scsibios(disk);
306 case AD_GEOM_ADJUST_COMPATCYL16:
307 pc98_ata_disk_geom_adjust_cyl16bit(disk);
315 (oldsectors != disk->d_fwsectors || oldheads != disk->d_fwheads))
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);
324 pc98_ad_firmware_geom_adjust(device_t dev __unused, struct disk *disk)
327 pc98_ata_disk_firmware_geom_adjust(disk);