[BACK]Return to wd.c CVS log [TXT][DIR] Up to [local] / sys / arch / armish / stand / boot

Annotation of sys/arch/armish/stand/boot/wd.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: wd.c,v 1.5 2007/06/17 00:28:56 deraadt Exp $  */
        !             2: /*     $NetBSD: wd.c,v 1.5 2005/12/11 12:17:06 christos Exp $  */
        !             3:
        !             4: /*-
        !             5:  * Copyright (c) 2003 The NetBSD Foundation, Inc.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * This code is derived from software contributed to The NetBSD Foundation
        !             9:  * by Manuel Bouyer.
        !            10:  *
        !            11:  * Redistribution and use in source and binary forms, with or without
        !            12:  * modification, are permitted provided that the following conditions
        !            13:  * are met:
        !            14:  * 1. Redistributions of source code must retain the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer.
        !            16:  * 2. Redistributions in binary form must reproduce the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer in the
        !            18:  *    documentation and/or other materials provided with the distribution.
        !            19:  * 3. All advertising materials mentioning features or use of this software
        !            20:  *    must display the following acknowledgement:
        !            21:  *        This product includes software developed by the NetBSD
        !            22:  *        Foundation, Inc. and its contributors.
        !            23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
        !            24:  *    contributors may be used to endorse or promote products derived
        !            25:  *    from this software without specific prior written permission.
        !            26:  *
        !            27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
        !            28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
        !            31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            37:  * POSSIBILITY OF SUCH DAMAGE.
        !            38:  */
        !            39:
        !            40: #include <sys/types.h>
        !            41: #include <sys/stdint.h>
        !            42:
        !            43: #include <machine/param.h>
        !            44:
        !            45: #include "libsa.h"
        !            46: #include "wdvar.h"
        !            47:
        !            48: void   wdprobe(void);
        !            49: int    wd_get_params(struct wd_softc *wd);
        !            50: int    wdgetdisklabel(struct wd_softc *wd);
        !            51: void   wdgetdefaultlabel(struct wd_softc *wd, struct disklabel *lp);
        !            52:
        !            53: struct wd_softc wd_devs[NUNITS];
        !            54: int wd_ndevs = -1;
        !            55:
        !            56: void
        !            57: wdprobe(void)
        !            58: {
        !            59:        struct wd_softc *wd = wd_devs;
        !            60:        u_int chan, drive, unit = 0;
        !            61:
        !            62:        for (chan = 0; chan < PCIIDE_NUM_CHANNELS; chan++) {
        !            63:                if (wdc_init(wd, chan) != 0)
        !            64:                        continue;
        !            65:                for (drive = 0; drive < wd->sc_channel.ndrives; drive++) {
        !            66:                        wd->sc_unit = unit;
        !            67:                        wd->sc_drive = drive;
        !            68:
        !            69:                        if (wd_get_params(wd) != 0)
        !            70:                                continue;
        !            71:
        !            72:                        DPRINTF(("wd%d: channel %d drive %d\n",
        !            73:                                unit, chan, drive));
        !            74:                        unit++;
        !            75:                        wd++;
        !            76:                }
        !            77:        }
        !            78:
        !            79:        wd_ndevs = unit;
        !            80: }
        !            81:
        !            82: /*
        !            83:  * Get drive parameters through 'device identify' command.
        !            84:  */
        !            85: int
        !            86: wd_get_params(wd)
        !            87:        struct wd_softc *wd;
        !            88: {
        !            89:        int error;
        !            90:        unsigned char buf[DEV_BSIZE];
        !            91:
        !            92:        if ((error = wdc_exec_identify(wd, buf)) != 0)
        !            93:                return (error);
        !            94:
        !            95:        wd->sc_params = *(struct ataparams *)buf;
        !            96:
        !            97:        /* 48-bit LBA addressing */
        !            98:        if ((wd->sc_params.atap_cmd2_en & ATAPI_CMD2_48AD) != 0) {
        !            99:                DPRINTF(("Drive supports LBA48.\n"));
        !           100: #if defined(_ENABLE_LBA48)
        !           101:                wd->sc_flags |= WDF_LBA48;
        !           102: #endif
        !           103:        }
        !           104:
        !           105:        /* Prior to ATA-4, LBA was optional. */
        !           106:        if ((wd->sc_params.atap_capabilities1 & WDC_CAP_LBA) != 0) {
        !           107:                DPRINTF(("Drive supports LBA.\n"));
        !           108:                wd->sc_flags |= WDF_LBA;
        !           109:        }
        !           110:
        !           111:        return (0);
        !           112: }
        !           113:
        !           114: /*
        !           115:  * Initialize disk label to the default value.
        !           116:  */
        !           117: void
        !           118: wdgetdefaultlabel(wd, lp)
        !           119:        struct wd_softc *wd;
        !           120:        struct disklabel *lp;
        !           121: {
        !           122:        memset(lp, 0, sizeof(struct disklabel));
        !           123:
        !           124:        lp->d_secsize = DEV_BSIZE;
        !           125:        lp->d_ntracks = wd->sc_params.atap_heads;
        !           126:        lp->d_nsectors = wd->sc_params.atap_sectors;
        !           127:        lp->d_ncylinders = wd->sc_params.atap_cylinders;
        !           128:        lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
        !           129:
        !           130:        if (strcmp(wd->sc_params.atap_model, "ST506") == 0)
        !           131:                lp->d_type = DTYPE_ST506;
        !           132:        else
        !           133:                lp->d_type = DTYPE_ESDI;
        !           134:
        !           135:        strncpy(lp->d_typename, wd->sc_params.atap_model, 16);
        !           136:        strncpy(lp->d_packname, "fictitious", 16);
        !           137:        if (wd->sc_capacity > UINT32_MAX)
        !           138:                lp->d_secperunit = UINT32_MAX;
        !           139:        else
        !           140:                lp->d_secperunit = wd->sc_capacity;
        !           141:        lp->d_rpm = 3600;
        !           142:        lp->d_interleave = 1;
        !           143:        lp->d_flags = 0;
        !           144:
        !           145:        lp->d_partitions[RAW_PART].p_offset = 0;
        !           146:        lp->d_partitions[RAW_PART].p_size = lp->d_secperunit;
        !           147:        lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
        !           148:        lp->d_npartitions = MAXPARTITIONS;      /* RAW_PART + 1 ??? */
        !           149:
        !           150:        lp->d_magic = DISKMAGIC;
        !           151:        lp->d_magic2 = DISKMAGIC;
        !           152:        lp->d_checksum = dkcksum(lp);
        !           153: }
        !           154:
        !           155: /*
        !           156:  * Read disk label from the device.
        !           157:  */
        !           158: int
        !           159: wdgetdisklabel(wd)
        !           160:        struct wd_softc *wd;
        !           161: {
        !           162:        char *msg;
        !           163:        int sector;
        !           164:        size_t rsize;
        !           165:        struct disklabel *lp;
        !           166:        unsigned char buf[DEV_BSIZE];
        !           167:
        !           168:        wdgetdefaultlabel(wd, &wd->sc_label);
        !           169:
        !           170:        /*
        !           171:         * Find OpenBSD Partition in DOS partition table.
        !           172:         */
        !           173:        sector = 0;
        !           174:        if (wdstrategy(wd, F_READ, DOSBBSECTOR, DEV_BSIZE, buf, &rsize))
        !           175:                return EOFFSET;
        !           176:
        !           177:        if (*(u_int16_t *)&buf[DOSMBR_SIGNATURE_OFF] == DOSMBR_SIGNATURE) {
        !           178:                int i;
        !           179:                struct dos_partition *dp = (struct dos_partition *)buf;
        !           180:
        !           181:                /*
        !           182:                 * Lookup OpenBSD slice. If there is none, go ahead
        !           183:                 * and try to read the disklabel off sector #0.
        !           184:                 */
        !           185:
        !           186:                memcpy(dp, &buf[DOSPARTOFF], NDOSPART * sizeof(*dp));
        !           187:                for (i = 0; i < NDOSPART; i++) {
        !           188:                        if (dp[i].dp_typ == DOSPTYP_OPENBSD) {
        !           189:                                sector = letoh32(dp[i].dp_start);
        !           190:                                break;
        !           191:                        }
        !           192:                }
        !           193:        }
        !           194:
        !           195:        if (wdstrategy(wd, F_READ, sector + LABELSECTOR, DEV_BSIZE,
        !           196:                                buf, &rsize))
        !           197:                return EOFFSET;
        !           198:
        !           199:        if ((msg = getdisklabel(buf + LABELOFFSET, &wd->sc_label)))
        !           200:                printf("wd%d: getdisklabel: %s\n", wd->sc_unit, msg);
        !           201:
        !           202:        lp = &wd->sc_label;
        !           203:
        !           204:        /* check partition */
        !           205:        if ((wd->sc_part >= lp->d_npartitions) ||
        !           206:            (lp->d_partitions[wd->sc_part].p_fstype == FS_UNUSED)) {
        !           207:                DPRINTF(("illegal partition\n"));
        !           208:                return (EPART);
        !           209:        }
        !           210:
        !           211:        DPRINTF(("label info: d_secsize %d, d_nsectors %d, d_ncylinders %d,"
        !           212:                                "d_ntracks %d, d_secpercyl %d\n",
        !           213:                                wd->sc_label.d_secsize,
        !           214:                                wd->sc_label.d_nsectors,
        !           215:                                wd->sc_label.d_ncylinders,
        !           216:                                wd->sc_label.d_ntracks,
        !           217:                                wd->sc_label.d_secpercyl));
        !           218:
        !           219:        return (0);
        !           220: }
        !           221:
        !           222: /*
        !           223:  * Open device (read drive parameters and disklabel)
        !           224:  */
        !           225: int
        !           226: wdopen(struct open_file *f, ...)
        !           227: {
        !           228:        int error;
        !           229:        va_list ap;
        !           230:        u_int unit, part, drive;
        !           231:        struct wd_softc *wd;
        !           232:
        !           233:        va_start(ap, f);
        !           234:        unit = va_arg(ap, u_int);
        !           235:        part = va_arg(ap, u_int);
        !           236:        va_end(ap);
        !           237:
        !           238:        DPRINTF(("wdopen: wd%d%c\n", unit, 'a' + part));
        !           239:
        !           240:        if (unit < 0 || unit >= NUNITS)
        !           241:                return (ENXIO);
        !           242:
        !           243:        if (wd_ndevs == -1)
        !           244:                wdprobe();
        !           245:
        !           246:        if (unit >= wd_ndevs)
        !           247:                return (ENXIO);
        !           248:
        !           249:        wd = &wd_devs[unit];
        !           250:        wd->sc_part = part;
        !           251:
        !           252:        if ((error = wdgetdisklabel(wd)) != 0)
        !           253:                return (error);
        !           254:
        !           255:        f->f_devdata = wd;
        !           256:        return (0);
        !           257: }
        !           258:
        !           259: /*
        !           260:  * Close device.
        !           261:  */
        !           262: int
        !           263: wdclose(struct open_file *f)
        !           264: {
        !           265:        return 0;
        !           266: }
        !           267:
        !           268: /*
        !           269:  * Read some data.
        !           270:  */
        !           271: int
        !           272: wdstrategy(f, rw, dblk, size, buf, rsize)
        !           273:        void *f;
        !           274:        int rw;
        !           275:        daddr_t dblk;
        !           276:        size_t size;
        !           277:        void *buf;
        !           278:        size_t *rsize;
        !           279: {
        !           280:        int i, nsect;
        !           281:        daddr_t blkno;
        !           282:        struct wd_softc *wd = f;
        !           283:
        !           284:        if (size == 0)
        !           285:                return (0);
        !           286:
        !           287:        if (rw != F_READ)
        !           288:                return EOPNOTSUPP;
        !           289:
        !           290:        nsect = howmany(size, wd->sc_label.d_secsize);
        !           291:        blkno = dblk + wd->sc_label.d_partitions[wd->sc_part].p_offset;
        !           292:
        !           293:        for (i = 0; i < nsect; i++, blkno++) {
        !           294:                int error;
        !           295:
        !           296:                if ((error = wdc_exec_read(wd, WDCC_READ, blkno, buf)) != 0)
        !           297:                        return (error);
        !           298:
        !           299:                buf += wd->sc_label.d_secsize;
        !           300:        }
        !           301:
        !           302:        *rsize = size;
        !           303:        return (0);
        !           304: }

CVSweb