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

Annotation of sys/arch/jornada/stand/boot/wd.c, Revision 1.1.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