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