geom_pc98.c revision 107956
193354Sphk/*- 293354Sphk * Copyright (c) 2002 Poul-Henning Kamp 393354Sphk * Copyright (c) 2002 Networks Associates Technology, Inc. 493354Sphk * All rights reserved. 593354Sphk * 693354Sphk * This software was developed for the FreeBSD Project by Poul-Henning Kamp 793354Sphk * and NAI Labs, the Security Research Division of Network Associates, Inc. 893354Sphk * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the 993354Sphk * DARPA CHATS research program. 1093354Sphk * 1193354Sphk * Redistribution and use in source and binary forms, with or without 1293354Sphk * modification, are permitted provided that the following conditions 1393354Sphk * are met: 1493354Sphk * 1. Redistributions of source code must retain the above copyright 1593354Sphk * notice, this list of conditions and the following disclaimer. 1693354Sphk * 2. Redistributions in binary form must reproduce the above copyright 1793354Sphk * notice, this list of conditions and the following disclaimer in the 1893354Sphk * documentation and/or other materials provided with the distribution. 1993354Sphk * 2093354Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2193354Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2293354Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2393354Sphk * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2493354Sphk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2593354Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2693354Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2793354Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2893354Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2993354Sphk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3093354Sphk * SUCH DAMAGE. 3193354Sphk * 3293354Sphk * $FreeBSD: head/sys/geom/geom_pc98.c 107956 2002-12-16 23:08:48Z phk $ 3393354Sphk */ 3493354Sphk 3593354Sphk#include <sys/param.h> 3693354Sphk#ifndef _KERNEL 37106559Snyan#include <signal.h> 3893354Sphk#include <stdio.h> 39106559Snyan#include <stdlib.h> 4093354Sphk#include <string.h> 4193354Sphk#include <err.h> 4293354Sphk#else 4393354Sphk#include <sys/systm.h> 4493354Sphk#include <sys/kernel.h> 45106559Snyan#include <sys/malloc.h> 4693354Sphk#include <sys/bio.h> 4793354Sphk#include <sys/lock.h> 4893354Sphk#include <sys/mutex.h> 4993354Sphk#endif 50106559Snyan 51106559Snyan#include <sys/diskpc98.h> 5293354Sphk#include <geom/geom.h> 5393354Sphk#include <geom/geom_slice.h> 5493354Sphk 5597075Sphk#define PC98_CLASS_NAME "PC98" 5693354Sphk 57106559Snyanstatic void 58106559Snyang_dec_dos_partition(u_char *ptr, struct dos_partition *d) 59106559Snyan{ 60107953Sphk u_int u; 61106559Snyan 62106559Snyan d->dp_mid = ptr[0]; 63106559Snyan d->dp_sid = ptr[1]; 64106559Snyan d->dp_dum1 = ptr[2]; 65106559Snyan d->dp_dum2 = ptr[3]; 66106559Snyan d->dp_ipl_sct = ptr[4]; 67106559Snyan d->dp_ipl_head = ptr[5]; 68106559Snyan d->dp_ipl_cyl = g_dec_le2(ptr + 6); 69106559Snyan d->dp_ssect = ptr[8]; 70106559Snyan d->dp_shd = ptr[9]; 71106559Snyan d->dp_scyl = g_dec_le2(ptr + 10); 72106559Snyan d->dp_esect = ptr[12]; 73106559Snyan d->dp_ehd = ptr[13]; 74106559Snyan d->dp_ecyl = g_dec_le2(ptr + 14); 75107953Sphk for (u = 0; u < sizeof(d->dp_name); u++) 76107953Sphk d->dp_name[u] = ptr[16 + u]; 77106559Snyan} 78106559Snyan 7993354Sphkstruct g_pc98_softc { 80106559Snyan int type [NDOSPART]; 81107012Snyan struct dos_partition dp[NDOSPART]; 8293354Sphk}; 8393354Sphk 8493354Sphkstatic int 8593354Sphkg_pc98_start(struct bio *bp) 8693354Sphk{ 87106559Snyan struct g_provider *pp; 8893354Sphk struct g_geom *gp; 89106559Snyan struct g_pc98_softc *mp; 9093354Sphk struct g_slicer *gsp; 91107953Sphk int idx; 9293354Sphk 93106559Snyan pp = bp->bio_to; 94107953Sphk idx = pp->index; 95106559Snyan gp = pp->geom; 9693354Sphk gsp = gp->softc; 97106559Snyan mp = gsp->softc; 98106559Snyan if (bp->bio_cmd == BIO_GETATTR) { 99107953Sphk if (g_handleattr_int(bp, "PC98::type", mp->type[idx])) 100106559Snyan return (1); 101106559Snyan if (g_handleattr_off_t(bp, "PC98::offset", 102107953Sphk gsp->slices[idx].offset)) 103106559Snyan return (1); 104106559Snyan } 10593354Sphk return (0); 10693354Sphk} 10793354Sphk 10893354Sphkstatic void 109107953Sphkg_pc98_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, 110106559Snyan struct g_consumer *cp __unused, struct g_provider *pp) 11193354Sphk{ 112106559Snyan struct g_pc98_softc *mp; 113106559Snyan struct g_slicer *gsp; 114107012Snyan char sname[17]; 11593354Sphk 116106559Snyan gsp = gp->softc; 117106559Snyan mp = gsp->softc; 11893354Sphk g_slice_dumpconf(sb, indent, gp, cp, pp); 119106559Snyan if (pp != NULL) { 120107012Snyan strncpy(sname, mp->dp[pp->index].dp_name, 16); 121107012Snyan sname[16] = '\0'; 122107012Snyan if (indent == NULL) { 123106559Snyan sbuf_printf(sb, " ty %d", mp->type[pp->index]); 124107012Snyan sbuf_printf(sb, " sn %s", sname); 125107012Snyan } else { 126106559Snyan sbuf_printf(sb, "%s<type>%d</type>\n", indent, 127106559Snyan mp->type[pp->index]); 128107012Snyan sbuf_printf(sb, "%s<sname>%s</sname>\n", indent, 129107012Snyan sname); 130107012Snyan } 131106559Snyan } 13293354Sphk} 13393354Sphk 134106559Snyanstatic void 135106559Snyang_pc98_print(int i, struct dos_partition *dp) 136106559Snyan{ 137107012Snyan char sname[17]; 138106559Snyan 139107012Snyan strncpy(sname, dp->dp_name, 16); 140107012Snyan sname[16] = '\0'; 141107012Snyan 142106559Snyan g_hexdump(dp, sizeof(dp[0])); 143106559Snyan printf("[%d] mid:%d(0x%x) sid:%d(0x%x)", 144106559Snyan i, dp->dp_mid, dp->dp_mid, dp->dp_sid, dp->dp_sid); 145106559Snyan printf(" s:%d/%d/%d", dp->dp_scyl, dp->dp_shd, dp->dp_ssect); 146106559Snyan printf(" e:%d/%d/%d", dp->dp_ecyl, dp->dp_ehd, dp->dp_esect); 147107012Snyan printf(" sname:%s\n", sname); 148106559Snyan} 149106559Snyan 15093354Sphkstatic struct g_geom * 15193354Sphkg_pc98_taste(struct g_class *mp, struct g_provider *pp, int flags) 15293354Sphk{ 15393354Sphk struct g_geom *gp; 15493354Sphk struct g_consumer *cp; 15594287Sphk int error, i, npart; 15693354Sphk struct g_pc98_softc *ms; 15794287Sphk struct g_slicer *gsp; 158106559Snyan u_int fwsectors, fwheads, sectorsize; 159106559Snyan u_char *buf; 160106559Snyan off_t spercyl; 16193354Sphk 16293354Sphk g_trace(G_T_TOPOLOGY, "g_pc98_taste(%s,%s)", mp->name, pp->name); 16393354Sphk g_topology_assert(); 16493354Sphk if (flags == G_TF_NORMAL && 16593354Sphk !strcmp(pp->geom->class->name, PC98_CLASS_NAME)) 16693354Sphk return (NULL); 167106559Snyan gp = g_slice_new(mp, NDOSPART, pp, &cp, &ms, sizeof *ms, g_pc98_start); 16893354Sphk if (gp == NULL) 16993354Sphk return (NULL); 17094287Sphk gsp = gp->softc; 17193354Sphk g_topology_unlock(); 17293354Sphk gp->dumpconf = g_pc98_dumpconf; 17393354Sphk npart = 0; 17493354Sphk while (1) { /* a trick to allow us to use break */ 17593354Sphk if (gp->rank != 2 && flags == G_TF_NORMAL) 17693354Sphk break; 177106559Snyan error = g_getattr("GEOM::fwsectors", cp, &fwsectors); 178106559Snyan if (error || fwsectors == 0) { 179106559Snyan fwsectors = 17; 18093354Sphk printf("g_pc98_taste: error %d guessing %d sectors\n", 181106559Snyan error, fwsectors); 18293354Sphk } 183106559Snyan error = g_getattr("GEOM::fwheads", cp, &fwheads); 184106559Snyan if (error || fwheads == 0) { 185106559Snyan fwheads = 8; 18693354Sphk printf("g_pc98_taste: error %d guessing %d heads\n", 187106559Snyan error, fwheads); 18893354Sphk } 189106559Snyan sectorsize = cp->provider->sectorsize; 190106559Snyan if (sectorsize < 512) 191106559Snyan break; 192107562Ssos if (cp->provider->mediasize / sectorsize < 17 * 8 * 65536) { 193107562Ssos fwsectors = 17; 194107562Ssos fwheads = 8; 195107562Ssos } 196106559Snyan gsp->frontstuff = sectorsize * fwsectors; 197106559Snyan spercyl = (off_t)fwsectors * fwheads * sectorsize; 19893354Sphk buf = g_read_data(cp, 0, 19994285Sphk sectorsize < 1024 ? 1024 : sectorsize, &error); 20093354Sphk if (buf == NULL || error != 0) 20193354Sphk break; 202106559Snyan if (buf[0x1fe] != 0x55 || buf[0x1ff] != 0xaa) { 203106559Snyan g_free(buf); 20493354Sphk break; 205106559Snyan } 206106001Sphk#if 0 207106001Sphk/* 208106001Sphk * XXX: Some sources indicate this is a magic sequence, but appearantly 209106001Sphk * XXX: it is not universal. Documentation would be wonderfule to have. 210106001Sphk */ 21193354Sphk if (buf[4] != 'I' || buf[5] != 'P' || 212106559Snyan buf[6] != 'L' || buf[7] != '1') { 213106559Snyan g_free(buf); 21493354Sphk break; 215106559Snyan } 216106001Sphk#endif 217106559Snyan for (i = 0; i < NDOSPART; i++) 218106559Snyan g_dec_dos_partition( 219106559Snyan buf + 512 + i * sizeof(struct dos_partition), 220107012Snyan ms->dp + i); 221106559Snyan g_free(buf); 222106559Snyan for (i = 0; i < NDOSPART; i++) { 223106398Sphk /* If start and end are identical it's bogus */ 224107012Snyan if (ms->dp[i].dp_ssect == ms->dp[i].dp_esect && 225107012Snyan ms->dp[i].dp_shd == ms->dp[i].dp_ehd && 226107012Snyan ms->dp[i].dp_scyl == ms->dp[i].dp_ecyl) 227106398Sphk continue; 228107012Snyan if (ms->dp[i].dp_ecyl == 0) 22993354Sphk continue; 230106559Snyan if (bootverbose) { 231106559Snyan printf("PC98 Slice %d on %s:\n", 232106559Snyan i + 1, gp->name); 233107012Snyan g_pc98_print(i, ms->dp + i); 234106559Snyan } 23593354Sphk npart++; 236107012Snyan ms->type[i] = (ms->dp[i].dp_sid << 8) | 237107012Snyan ms->dp[i].dp_mid; 238104064Sphk g_topology_lock(); 239107956Sphk g_slice_config(gp, i, G_SLICE_CONFIG_SET, 240107012Snyan ms->dp[i].dp_scyl * spercyl, 241107012Snyan (ms->dp[i].dp_ecyl - ms->dp[i].dp_scyl + 1) * 242107012Snyan spercyl, 243105542Sphk sectorsize, 244106559Snyan "%ss%d", gp->name, i + 1); 245104064Sphk g_topology_unlock(); 24693354Sphk } 24793354Sphk break; 24893354Sphk } 24993354Sphk g_topology_lock(); 250107956Sphk g_access_rel(cp, -1, 0, 0); 251107956Sphk if (LIST_EMPTY(&gp->provider)) { 252107956Sphk g_std_spoiled(cp); 253107956Sphk return (NULL); 254106559Snyan } 255107956Sphk return (gp); 25693354Sphk} 25793354Sphk 25893354Sphkstatic struct g_class g_pc98_class = { 25993354Sphk PC98_CLASS_NAME, 26093354Sphk g_pc98_taste, 26193354Sphk NULL, 26298066Sphk G_CLASS_INITIALIZER 26393354Sphk}; 26493354Sphk 26593354SphkDECLARE_GEOM_CLASS(g_pc98_class, g_pc98); 266