Annotation of sys/arch/armish/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