Sat Jan 22 00:32:42 2011 UTC ()
- make sure to wait for BUSY bit goes down prior to each 512B block
read from xfer register, or corrupted datum may be retrieved.  Uncovered
by corrected PIO READ_CMD value.
- remove redundant register assignments to set transfer mode.


(nisimura)
diff -r1.7 -r1.8 src/sys/arch/sandpoint/stand/netboot/dsk.c

cvs diff -r1.7 -r1.8 src/sys/arch/sandpoint/stand/netboot/Attic/dsk.c (switch to unified diff)

--- src/sys/arch/sandpoint/stand/netboot/Attic/dsk.c 2011/01/11 07:01:21 1.7
+++ src/sys/arch/sandpoint/stand/netboot/Attic/dsk.c 2011/01/22 00:32:41 1.8
@@ -1,534 +1,539 @@ @@ -1,534 +1,539 @@
1/* $NetBSD: dsk.c,v 1.7 2011/01/11 07:01:21 nisimura Exp $ */ 1/* $NetBSD: dsk.c,v 1.8 2011/01/22 00:32:41 nisimura Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2010 The NetBSD Foundation, Inc. 4 * Copyright (c) 2010 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Tohru Nishimura. 8 * by Tohru Nishimura.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32/* 32/*
33 * assumptions; 33 * assumptions;
34 * - up to 4 IDE/SATA drives. 34 * - up to 4 IDE/SATA drives.
35 * - a single (master) drive in each IDE channel. 35 * - a single (master) drive in each IDE channel.
36 * - all drives are up and spinning. 36 * - all drives are up and spinning.
37 */ 37 */
38 38
39#include <sys/types.h> 39#include <sys/types.h>
40 40
41#include <lib/libsa/stand.h> 41#include <lib/libsa/stand.h>
42#include <lib/libsa/ufs.h> 42#include <lib/libsa/ufs.h>
43 43
44#include <sys/disklabel.h> 44#include <sys/disklabel.h>
45#include <sys/bootblock.h> 45#include <sys/bootblock.h>
46 46
47#include <machine/bootinfo.h> 47#include <machine/bootinfo.h>
48#include <machine/stdarg.h> 48#include <machine/stdarg.h>
49 49
50#include "globals.h" 50#include "globals.h"
51 51
52/* 52/*
53 * - no vtophys() translation, vaddr_t == paddr_t. 53 * - no vtophys() translation, vaddr_t == paddr_t.
54 */ 54 */
55#define CSR_READ_4(r) in32rb(r) 55#define CSR_READ_4(r) in32rb(r)
56#define CSR_WRITE_4(r,v) out32rb(r,v) 56#define CSR_WRITE_4(r,v) out32rb(r,v)
57#define CSR_READ_1(r) *(volatile uint8_t *)(r) 57#define CSR_READ_1(r) *(volatile uint8_t *)(r)
58#define CSR_WRITE_1(r,v) *(volatile uint8_t *)(r)=(v) 58#define CSR_WRITE_1(r,v) *(volatile uint8_t *)(r)=(v)
59 59
60#define DSK_DECL(xxx) \ 60#define DSK_DECL(xxx) \
61 int xxx ## _match(unsigned, void *); \ 61 int xxx ## _match(unsigned, void *); \
62 void * xxx ## _init(unsigned, void *) 62 void * xxx ## _init(unsigned, void *)
63 63
64DSK_DECL(pciide); 64DSK_DECL(pciide);
65DSK_DECL(siisata); 65DSK_DECL(siisata);
66 66
67struct dskdv { 67struct dskdv {
68 char *name; 68 char *name;
69 int (*match)(unsigned, void *); 69 int (*match)(unsigned, void *);
70 void *(*init)(unsigned, void *); 70 void *(*init)(unsigned, void *);
71 void *priv; 71 void *priv;
72}; 72};
73 73
74static struct dskdv ldskdv[] = { 74static struct dskdv ldskdv[] = {
75 { "pciide", pciide_match, pciide_init, }, 75 { "pciide", pciide_match, pciide_init, },
76 { "siisata", siisata_match, siisata_init, }, 76 { "siisata", siisata_match, siisata_init, },
77}; 77};
78static int ndskdv = sizeof(ldskdv)/sizeof(ldskdv[0]); 78static int ndskdv = sizeof(ldskdv)/sizeof(ldskdv[0]);
79 79
80static int probe_drive(struct dkdev_ata *, int); 80static int probe_drive(struct dkdev_ata *, int);
81static void drive_ident(struct disk *, char *); 81static void drive_ident(struct disk *, char *);
82static char *mkident(char *, int); 82static char *mkident(char *, int);
83static void set_xfermode(struct dkdev_ata *, int); 83static void set_xfermode(struct dkdev_ata *, int);
84static void decode_dlabel(struct disk *, char *); 84static void decode_dlabel(struct disk *, char *);
85static int lba_read(struct disk *, uint64_t, uint32_t, void *); 85static int lba_read(struct disk *, uint64_t, uint32_t, void *);
86static void issue48(struct dvata_chan *, uint64_t, uint32_t); 86static void issue48(struct dvata_chan *, uint64_t, uint32_t);
87static void issue28(struct dvata_chan *, uint64_t, uint32_t); 87static void issue28(struct dvata_chan *, uint64_t, uint32_t);
88static struct disk *lookup_disk(int); 88static struct disk *lookup_disk(int);
89 89
90static struct disk ldisk[4]; 90static struct disk ldisk[4];
91 91
92int 92int
93dskdv_init(unsigned tag, void **cookie) 93dskdv_init(unsigned tag, void **cookie)
94{ 94{
95 struct dskdv *dv; 95 struct dskdv *dv;
96 int n; 96 int n;
97 97
98 for (n = 0; n < ndskdv; n++) { 98 for (n = 0; n < ndskdv; n++) {
99 dv = &ldskdv[n]; 99 dv = &ldskdv[n];
100 if ((*dv->match)(tag, NULL) > 0) 100 if ((*dv->match)(tag, NULL) > 0)
101 goto found; 101 goto found;
102 } 102 }
103 return 0; 103 return 0;
104 found: 104 found:
105 dv->priv = (*dv->init)(tag, NULL); 105 dv->priv = (*dv->init)(tag, NULL);
106 *cookie = dv; 106 *cookie = dv;
107 return 1; 107 return 1;
108} 108}
109 109
110int 110int
111disk_scan(void *cookie) 111disk_scan(void *cookie)
112{ 112{
113 struct dskdv *dv = cookie; 113 struct dskdv *dv = cookie;
114 struct dkdev_ata *l = dv->priv; 114 struct dkdev_ata *l = dv->priv;
115 struct disk *d; 115 struct disk *d;
116 int n, ndrive; 116 int n, ndrive;
117 117
118 ndrive = 0; 118 ndrive = 0;
119 for (n = 0; n < 4; n++) { 119 for (n = 0; n < 4; n++) {
120 if (l->presense[n] == 0) 120 if (l->presense[n] == 0)
121 continue; 121 continue;
122 if (probe_drive(l, n) == 0) { 122 if (probe_drive(l, n) == 0) {
123 l->presense[n] = 0; 123 l->presense[n] = 0;
124 continue; 124 continue;
125 } 125 }
126 d = &ldisk[ndrive]; 126 d = &ldisk[ndrive];
127 d->dvops = l; 127 d->dvops = l;
128 d->unittag = ndrive; 128 d->unittag = ndrive;
129 snprintf(d->xname, sizeof(d->xname), "wd%d", d->unittag); 129 snprintf(d->xname, sizeof(d->xname), "wd%d", d->unittag);
130 set_xfermode(l, n); 130 set_xfermode(l, n);
131 drive_ident(d, l->iobuf); 131 drive_ident(d, l->iobuf);
132 decode_dlabel(d, l->iobuf); 132 decode_dlabel(d, l->iobuf);
133 ndrive += 1; 133 ndrive += 1;
134 } 134 }
135 return ndrive; 135 return ndrive;
136} 136}
137 137
138int 138int
139spinwait_unbusy(struct dkdev_ata *l, int n, int milli, const char **err) 139spinwait_unbusy(struct dkdev_ata *l, int n, int milli, const char **err)
140{ 140{
141 struct dvata_chan *chan = &l->chan[n]; 141 struct dvata_chan *chan = &l->chan[n];
142 int sts; 142 int sts;
143 const char *msg; 143 const char *msg;
144 144
145 /* 145 /*
146 * For best compatibility it is recommended to wait 400ns and 146 * For best compatibility it is recommended to wait 400ns and
147 * read the alternate status byte four times before the status 147 * read the alternate status byte four times before the status
148 * is valid. 148 * is valid.
149 */ 149 */
150 delay(1); 150 delay(1);
151 (void)CSR_READ_1(chan->alt); 151 (void)CSR_READ_1(chan->alt);
152 (void)CSR_READ_1(chan->alt); 152 (void)CSR_READ_1(chan->alt);
153 (void)CSR_READ_1(chan->alt); 153 (void)CSR_READ_1(chan->alt);
154 (void)CSR_READ_1(chan->alt); 154 (void)CSR_READ_1(chan->alt);
155 155
156 sts = CSR_READ_1(chan->cmd + _STS); 156 sts = CSR_READ_1(chan->cmd + _STS);
157 while (milli-- > 0 && sts != 0xff && (sts & ATA_STS_BUSY)) { 157 while (milli-- > 0
 158 && sts != 0xff
 159 && (sts & (ATA_STS_BUSY|ATA_STS_DRDY)) != ATA_STS_DRDY) {
158 delay(1000); 160 delay(1000);
159 sts = CSR_READ_1(chan->cmd + _STS); 161 sts = CSR_READ_1(chan->cmd + _STS);
160 } 162 }
161 163
162 msg = NULL; 164 msg = NULL;
163 if (sts == 0xff) 165 if (sts == 0xff)
164 msg = "returned 0xff"; 166 msg = "returned 0xff";
165 else if (sts & ATA_STS_ERR) 167 else if (sts & ATA_STS_ERR)
166 msg = "returned ERR"; 168 msg = "returned ERR";
167 else if (sts & ATA_STS_BUSY) 169 else if (sts & ATA_STS_BUSY)
168 msg = "remains BUSY"; 170 msg = "remains BUSY";
 171 else if ((sts & ATA_STS_DRDY) == 0)
 172 msg = "no DRDY";
169 173
170 if (err != NULL) 174 if (err != NULL)
171 *err = msg; 175 *err = msg;
172 return msg == NULL; 176 return msg == NULL;
173} 177}
174 178
175int 179int
176perform_atareset(struct dkdev_ata *l, int n) 180perform_atareset(struct dkdev_ata *l, int n)
177{ 181{
178 struct dvata_chan *chan = &l->chan[n]; 182 struct dvata_chan *chan = &l->chan[n];
179 183
180 CSR_WRITE_1(chan->ctl, ATA_DREQ); 184 CSR_WRITE_1(chan->ctl, ATA_DREQ);
181 delay(10); 185 delay(10);
182 CSR_WRITE_1(chan->ctl, ATA_SRST|ATA_DREQ); 186 CSR_WRITE_1(chan->ctl, ATA_SRST|ATA_DREQ);
183 delay(10); 187 delay(10);
184 CSR_WRITE_1(chan->ctl, ATA_DREQ); 188 CSR_WRITE_1(chan->ctl, ATA_DREQ);
185 189
186 return spinwait_unbusy(l, n, 150, NULL); 190 return spinwait_unbusy(l, n, 150, NULL);
187} 191}
188 192
189int 193int
190satapresense(struct dkdev_ata *l, int n) 194satapresense(struct dkdev_ata *l, int n)
191{ 195{
192#define VND_CH(n) (((n&02)<<8)+((n&01)<<7)) 196#define VND_CH(n) (((n&02)<<8)+((n&01)<<7))
193#define VND_SC(n) (0x100+VND_CH(n)) 197#define VND_SC(n) (0x100+VND_CH(n))
194#define VND_SS(n) (0x104+VND_CH(n)) 198#define VND_SS(n) (0x104+VND_CH(n))
195 199
196 uint32_t sc = l->bar[5] + VND_SC(n); 200 uint32_t sc = l->bar[5] + VND_SC(n);
197 uint32_t ss = l->bar[5] + VND_SS(n); 201 uint32_t ss = l->bar[5] + VND_SS(n);
198 unsigned val; 202 unsigned val;
199 203
200 val = (00 << 4) | (03 << 8); /* any speed, no pwrmgt */ 204 val = (00 << 4) | (03 << 8); /* any speed, no pwrmgt */
201 CSR_WRITE_4(sc, val | 01); /* perform init */ 205 CSR_WRITE_4(sc, val | 01); /* perform init */
202 delay(50 * 1000); 206 delay(50 * 1000);
203 CSR_WRITE_4(sc, val); 207 CSR_WRITE_4(sc, val);
204 delay(50 * 1000);  208 delay(50 * 1000);
205 val = CSR_READ_4(ss); /* has completed */ 209 val = CSR_READ_4(ss); /* has completed */
206 return ((val & 03) == 03); /* active drive found */ 210 return ((val & 03) == 03); /* active drive found */
207} 211}
208 212
209static int 213static int
210probe_drive(struct dkdev_ata *l, int n) 214probe_drive(struct dkdev_ata *l, int n)
211{ 215{
212 struct dvata_chan *chan = &l->chan[n]; 216 struct dvata_chan *chan = &l->chan[n];
213 uint16_t *p; 217 uint16_t *p;
214 int i; 218 int i;
215  219
216 CSR_WRITE_1(chan->cmd + _CMD, ATA_CMD_IDENT); 220 CSR_WRITE_1(chan->cmd + _CMD, ATA_CMD_IDENT);
217 (void)CSR_READ_1(chan->alt); 221 (void)CSR_READ_1(chan->alt);
218 delay(10 * 1000); 222 delay(10 * 1000);
219 if (spinwait_unbusy(l, n, 1000, NULL) == 0) 223 if (spinwait_unbusy(l, n, 1000, NULL) == 0)
220 return 0; 224 return 0;
221 225
222 p = (uint16_t *)l->iobuf; 226 p = (uint16_t *)l->iobuf;
223 for (i = 0; i < 512; i += 2) { 227 for (i = 0; i < 512; i += 2) {
224 /* need to have bswap16 */ 228 /* need to have bswap16 */
225 *p++ = iole16toh(chan->cmd + _DAT); 229 *p++ = iole16toh(chan->cmd + _DAT);
226 } 230 }
227 (void)CSR_READ_1(chan->cmd + _STS); 231 (void)CSR_READ_1(chan->cmd + _STS);
228 return 1; 232 return 1;
229} 233}
230 234
231static void 235static void
232drive_ident(struct disk *d, char *ident) 236drive_ident(struct disk *d, char *ident)
233{ 237{
234 uint16_t *p; 238 uint16_t *p;
235 uint64_t huge; 239 uint64_t huge;
236 240
237 p = (uint16_t *)ident; 241 p = (uint16_t *)ident;
238#if 1 242#if 1
239 printf("[49]%04x [82]%04x [83]%04x [84]%04x " 243 printf("[49]%04x [82]%04x [83]%04x [84]%04x "
240 "[85]%04x [86]%04x [87]%04x [88]%04x\n", 244 "[85]%04x [86]%04x [87]%04x [88]%04x\n",
241 p[49], p[82], p[83], p[84], 245 p[49], p[82], p[83], p[84],
242 p[85], p[86], p[87], p[88]); 246 p[85], p[86], p[87], p[88]);
243#endif 247#endif
244 huge = 0; 248 huge = 0;
245 printf("%s: ", d->xname); 249 printf("%s: ", d->xname);
246 printf("<%s> ", mkident((char *)ident + 54, 40)); 250 printf("<%s> ", mkident((char *)ident + 54, 40));
247 if (p[49] & (1 << 8)) 251 if (p[49] & (1 << 8))
248 printf("DMA "); 252 printf("DMA ");
249 if (p[49] & (1 << 9)) { 253 if (p[49] & (1 << 9)) {
250 printf("LBA "); 254 printf("LBA ");
251 huge = p[60] | (p[61] << 16); 255 huge = p[60] | (p[61] << 16);
252 } 256 }
253 if ((p[83] & 0xc000) == 0x4000 && (p[83] & (1 << 10))) { 257 if ((p[83] & 0xc000) == 0x4000 && (p[83] & (1 << 10))) {
 258 printf("LBA48 ");
254 huge = p[100] | (p[101] << 16); 259 huge = p[100] | (p[101] << 16);
255 huge |= (uint64_t)p[102] << 32; 260 huge |= (uint64_t)p[102] << 32;
256 huge |= (uint64_t)p[103] << 48; 261 huge |= (uint64_t)p[103] << 48;
257 printf("LBA48 "); 
258 } 262 }
259 huge >>= (1 + 10); 263 huge >>= (1 + 10);
260 printf("%d MB\n", (int)huge); 264 printf("%d MB\n", (int)huge);
261 265
262 memcpy(d->ident, ident, sizeof(d->ident)); 266 memcpy(d->ident, ident, sizeof(d->ident));
263 d->nsect = huge; 267 d->nsect = huge;
264 d->lba_read = lba_read; 268 d->lba_read = lba_read;
265} 269}
266 270
267static char * 271static char *
268mkident(char *src, int len) 272mkident(char *src, int len)
269{ 273{
270 static char local[40]; 274 static char local[40];
271 char *dst, *end, *last; 275 char *dst, *end, *last;
272  276
273 if (len > sizeof(local)) 277 if (len > sizeof(local))
274 len = sizeof(local); 278 len = sizeof(local);
275 dst = last = local; 279 dst = last = local;
276 end = src + len - 1; 280 end = src + len - 1;
277 281
278 /* reserve space for '\0' */ 282 /* reserve space for '\0' */
279 if (len < 2) 283 if (len < 2)
280 goto out; 284 goto out;
281 /* skip leading white space */ 285 /* skip leading white space */
282 while (*src != '\0' && src < end && *src == ' ') 286 while (*src != '\0' && src < end && *src == ' ')
283 ++src; 287 ++src;
284 /* copy string, omitting trailing white space */ 288 /* copy string, omitting trailing white space */
285 while (*src != '\0' && src < end) { 289 while (*src != '\0' && src < end) {
286 *dst++ = *src; 290 *dst++ = *src;
287 if (*src++ != ' ') 291 if (*src++ != ' ')
288 last = dst; 292 last = dst;
289 } 293 }
290 out: 294 out:
291 *last = '\0'; 295 *last = '\0';
292 return local; 296 return local;
293} 297}
294 298
295static void 299static void
296decode_dlabel(struct disk *d, char *iobuf) 300decode_dlabel(struct disk *d, char *iobuf)
297{ 301{
298 struct mbr_partition *mp, *bsdp; 302 struct mbr_partition *mp, *bsdp;
299 struct disklabel *dlp; 303 struct disklabel *dlp;
300 struct partition *pp; 304 struct partition *pp;
301 char *dp; 305 char *dp;
302 int i, first; 306 int i, first;
303 307
304 bsdp = NULL; 308 bsdp = NULL;
305 (*d->lba_read)(d, 0, 1, iobuf); 309 (*d->lba_read)(d, 0, 1, iobuf);
306 if (bswap16(*(uint16_t *)(iobuf + MBR_MAGIC_OFFSET)) != MBR_MAGIC) 310 if (bswap16(*(uint16_t *)(iobuf + MBR_MAGIC_OFFSET)) != MBR_MAGIC)
307 goto skip; 311 goto skip;
308 mp = (struct mbr_partition *)(iobuf + MBR_PART_OFFSET); 312 mp = (struct mbr_partition *)(iobuf + MBR_PART_OFFSET);
309 for (i = 0; i < MBR_PART_COUNT; i++, mp++) { 313 for (i = 0; i < MBR_PART_COUNT; i++, mp++) {
310 if (mp->mbrp_type == MBR_PTYPE_NETBSD) { 314 if (mp->mbrp_type == MBR_PTYPE_NETBSD) {
311 bsdp = mp; 315 bsdp = mp;
312 break; 316 break;
313 } 317 }
314 } 318 }
315 skip: 319 skip:
316 first = (bsdp) ? bswap32(bsdp->mbrp_start) : 0; 320 first = (bsdp) ? bswap32(bsdp->mbrp_start) : 0;
317 (*d->lba_read)(d, first + LABELSECTOR, 1, iobuf); 321 (*d->lba_read)(d, first + LABELSECTOR, 1, iobuf);
318 dp = iobuf /* + LABELOFFSET */; 322 dp = iobuf /* + LABELOFFSET */;
319 for (i = 0; i < 512 - sizeof(struct disklabel); i++, dp += 4) { 323 for (i = 0; i < 512 - sizeof(struct disklabel); i++, dp += 4) {
320 dlp = (struct disklabel *)dp; 324 dlp = (struct disklabel *)dp;
321 if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC) { 325 if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC) {
322 goto found; 326 goto found;
323 } 327 }
324 } 328 }
325 d->dlabel = NULL; 329 d->dlabel = NULL;
326 printf("%s: no disklabel\n", d->xname); 330 printf("%s: no disklabel\n", d->xname);
327 return; 331 return;
328 found: 332 found:
329 d->dlabel = allocaligned(sizeof(struct disklabel), 4); 333 d->dlabel = allocaligned(sizeof(struct disklabel), 4);
330 memcpy(d->dlabel, dlp, sizeof(struct disklabel)); 334 memcpy(d->dlabel, dlp, sizeof(struct disklabel));
331#if 1 335#if 1
332 for (i = 0; i < dlp->d_npartitions; i += 1) { 336 for (i = 0; i < dlp->d_npartitions; i += 1) {
333 const char *type; 337 const char *type;
334 pp = &dlp->d_partitions[i]; 338 pp = &dlp->d_partitions[i];
335 type = NULL; 339 type = NULL;
336 switch (pp->p_fstype) { 340 switch (pp->p_fstype) {
337 case FS_SWAP: /* swap */ 341 case FS_SWAP: /* swap */
338 type = "swap"; 342 type = "swap";
339 break; 343 break;
340 case FS_BSDFFS: 344 case FS_BSDFFS:
341 type = "ffs"; 345 type = "ffs";
342 break; 346 break;
343 case FS_EX2FS: 347 case FS_EX2FS:
344 type = "ext2fs"; 348 type = "ext2fs";
345 break; 349 break;
346 } 350 }
347 if (type != NULL) 351 if (type != NULL)
348 printf("%s%c: %s\n", d->xname, i + 'a', type); 352 printf("%s%c: %s\n", d->xname, i + 'a', type);
349 } 353 }
350#endif 354#endif
351} 355}
352 356
353static void 357static void
354set_xfermode(struct dkdev_ata *l, int n) 358set_xfermode(struct dkdev_ata *l, int n)
355{ 359{
356 struct dvata_chan *chan = &l->chan[n]; 360 struct dvata_chan *chan = &l->chan[n];
357 361
358 CSR_WRITE_1(chan->cmd + _FEA, ATA_XFER); 362 CSR_WRITE_1(chan->cmd + _FEA, ATA_XFER);
359 CSR_WRITE_1(chan->cmd + _NSECT, XFER_PIO0); 363 CSR_WRITE_1(chan->cmd + _NSECT, XFER_PIO0);
360 CSR_WRITE_1(chan->cmd + _LBAL, 0); 364 CSR_WRITE_1(chan->cmd + _DEV, ATA_DEV_OBS); /* ??? */
361 CSR_WRITE_1(chan->cmd + _LBAM, 0); 
362 CSR_WRITE_1(chan->cmd + _LBAH, 0); 
363 CSR_WRITE_1(chan->cmd + _DEV, ATA_DEV_OBS); 
364 CSR_WRITE_1(chan->cmd + _CMD, ATA_CMD_SETF); 365 CSR_WRITE_1(chan->cmd + _CMD, ATA_CMD_SETF);
365 366
366 spinwait_unbusy(l, n, 1000, NULL); 367 spinwait_unbusy(l, n, 1000, NULL);
367} 368}
368 369
369static int 370static int
370lba_read(struct disk *d, uint64_t bno, uint32_t bcnt, void *buf) 371lba_read(struct disk *d, uint64_t bno, uint32_t bcnt, void *buf)
371{ 372{
372 struct dkdev_ata *l; 373 struct dkdev_ata *l;
373 struct dvata_chan *chan; 374 struct dvata_chan *chan;
374 void (*issue)(struct dvata_chan *, uint64_t, uint32_t); 375 void (*issue)(struct dvata_chan *, uint64_t, uint32_t);
375 int n, rdcnt, i; 376 int n, rdcnt, i, k;
376 uint16_t *p; 377 uint16_t *p;
377 const char *err; 378 const char *err;
378 int error; 379 int error;
379 380
380 l = d->dvops; 381 l = d->dvops;
381 n = d->unittag; 382 n = d->unittag;
382 p = (uint16_t *)buf; 383 p = (uint16_t *)buf;
383 chan = &l->chan[n]; 384 chan = &l->chan[n];
384 error = 0; 385 error = 0;
385 for ( ; bcnt > 0; bno += rdcnt, bcnt -= rdcnt) { 386 for ( ; bcnt > 0; bno += rdcnt, bcnt -= rdcnt) {
386 issue = (bno < (1ULL<<28)) ? issue28 : issue48; 387 issue = (bno < (1ULL<<28)) ? issue28 : issue48;
387 rdcnt = (bcnt > 255) ? 255 : bcnt; 388 rdcnt = (bcnt > 255) ? 255 : bcnt;
388 (*issue)(chan, bno, rdcnt); 389 (*issue)(chan, bno, rdcnt);
389 if (spinwait_unbusy(l, n, 1000, &err) == 0) { 390 for (k = 0; k < rdcnt; k++) {
390 printf("%s blk %d %s\n", d->xname, (int)bno, err); 391 if (spinwait_unbusy(l, n, 1000, &err) == 0) {
391 error = EIO; 392 printf("%s blk %d %s\n",
392 continue; 393 d->xname, (int)bno, err);
393 } 394 error = EIO;
394 for (i = 0; i < rdcnt * 512; i += 2) { 395 break;
395 /* arrives in native order */ 396 }
396 *p++ = *(uint16_t *)(chan->cmd + _DAT); 397 for (i = 0; i < 512; i += 2) {
 398 /* arrives in native order */
 399 *p++ = *(uint16_t *)(chan->cmd + _DAT);
 400 }
 401 /* clear irq if any */
 402 (void)CSR_READ_1(chan->cmd + _STS);
397 } 403 }
398 (void)CSR_READ_1(chan->cmd + _STS); 
399 } 404 }
400 return error; 405 return error;
401} 406}
402 407
403static void 408static void
404issue48(struct dvata_chan *chan, uint64_t bno, uint32_t nblk) 409issue48(struct dvata_chan *chan, uint64_t bno, uint32_t nblk)
405{ 410{
406 411
407 CSR_WRITE_1(chan->cmd + _NSECT, 0); 412 CSR_WRITE_1(chan->cmd + _NSECT, 0); /* always less than 256 */
408 CSR_WRITE_1(chan->cmd + _LBAL, (bno >> 24) & 0xff); 413 CSR_WRITE_1(chan->cmd + _LBAL, (bno >> 24) & 0xff);
409 CSR_WRITE_1(chan->cmd + _LBAM, (bno >> 32) & 0xff); 414 CSR_WRITE_1(chan->cmd + _LBAM, (bno >> 32) & 0xff);
410 CSR_WRITE_1(chan->cmd + _LBAH, (bno >> 40) & 0xff); 415 CSR_WRITE_1(chan->cmd + _LBAH, (bno >> 40) & 0xff);
411 CSR_WRITE_1(chan->cmd + _NSECT, nblk); 416 CSR_WRITE_1(chan->cmd + _NSECT, nblk);
412 CSR_WRITE_1(chan->cmd + _LBAL, (bno >> 0) & 0xff); 417 CSR_WRITE_1(chan->cmd + _LBAL, (bno >> 0) & 0xff);
413 CSR_WRITE_1(chan->cmd + _LBAM, (bno >> 8) & 0xff); 418 CSR_WRITE_1(chan->cmd + _LBAM, (bno >> 8) & 0xff);
414 CSR_WRITE_1(chan->cmd + _LBAH, (bno >> 16) & 0xff); 419 CSR_WRITE_1(chan->cmd + _LBAH, (bno >> 16) & 0xff);
415 CSR_WRITE_1(chan->cmd + _DEV, ATA_DEV_LBA); 420 CSR_WRITE_1(chan->cmd + _DEV, ATA_DEV_LBA);
416 CSR_WRITE_1(chan->cmd + _CMD, ATA_CMD_READ_EXT); 421 CSR_WRITE_1(chan->cmd + _CMD, ATA_CMD_READ_EXT);
417} 422}
418 423
419static void 424static void
420issue28(struct dvata_chan *chan, uint64_t bno, uint32_t nblk) 425issue28(struct dvata_chan *chan, uint64_t bno, uint32_t nblk)
421{ 426{
422 427
423 CSR_WRITE_1(chan->cmd + _NSECT, nblk); 428 CSR_WRITE_1(chan->cmd + _NSECT, nblk);
424 CSR_WRITE_1(chan->cmd + _LBAL, (bno >> 0) & 0xff); 429 CSR_WRITE_1(chan->cmd + _LBAL, (bno >> 0) & 0xff);
425 CSR_WRITE_1(chan->cmd + _LBAM, (bno >> 8) & 0xff); 430 CSR_WRITE_1(chan->cmd + _LBAM, (bno >> 8) & 0xff);
426 CSR_WRITE_1(chan->cmd + _LBAH, (bno >> 16) & 0xff); 431 CSR_WRITE_1(chan->cmd + _LBAH, (bno >> 16) & 0xff);
427 CSR_WRITE_1(chan->cmd + _DEV, ((bno >> 24) & 0xf) | ATA_DEV_LBA); 432 CSR_WRITE_1(chan->cmd + _DEV, ((bno >> 24) & 0xf) | ATA_DEV_LBA);
428 CSR_WRITE_1(chan->cmd + _CMD, ATA_CMD_READ); 433 CSR_WRITE_1(chan->cmd + _CMD, ATA_CMD_READ);
429} 434}
430 435
431static struct disk * 436static struct disk *
432lookup_disk(int unit) 437lookup_disk(int unit)
433{ 438{
434 439
435 return &ldisk[unit]; 440 return &ldisk[unit];
436} 441}
437 442
438int 443int
439dsk_open(struct open_file *f, ...) 444dsk_open(struct open_file *f, ...)
440{ 445{
441 va_list ap; 446 va_list ap;
442 int unit, part; 447 int unit, part;
443 const char *name; 448 const char *name;
444 struct disk *d; 449 struct disk *d;
445 struct disklabel *dlp; 450 struct disklabel *dlp;
446 struct fs_ops *fs; 451 struct fs_ops *fs;
447 int error; 452 int error;
448 extern struct btinfo_bootpath bi_path; 453 extern struct btinfo_bootpath bi_path;
449 extern struct btinfo_rootdevice bi_rdev; 454 extern struct btinfo_rootdevice bi_rdev;
450 extern struct fs_ops fs_ffsv2, fs_ffsv1; 455 extern struct fs_ops fs_ffsv2, fs_ffsv1;
451 456
452 va_start(ap, f); 457 va_start(ap, f);
453 unit = va_arg(ap, int); 458 unit = va_arg(ap, int);
454 part = va_arg(ap, int); 459 part = va_arg(ap, int);
455 name = va_arg(ap, const char *); 460 name = va_arg(ap, const char *);
456 va_end(ap); 461 va_end(ap);
457 462
458 if ((d = lookup_disk(unit)) == NULL) 463 if ((d = lookup_disk(unit)) == NULL)
459 return ENXIO; 464 return ENXIO;
460 f->f_devdata = d; 465 f->f_devdata = d;
461 if ((dlp = d->dlabel) == NULL || part >= dlp->d_npartitions) 466 if ((dlp = d->dlabel) == NULL || part >= dlp->d_npartitions)
462 return ENXIO; 467 return ENXIO;
463 d->part = part; 468 d->part = part;
464 469
465 snprintf(bi_path.bootpath, sizeof(bi_path.bootpath), name); 470 snprintf(bi_path.bootpath, sizeof(bi_path.bootpath), name);
466 if (dlp->d_partitions[part].p_fstype == FS_BSDFFS) { 471 if (dlp->d_partitions[part].p_fstype == FS_BSDFFS) {
467 if ((error = ffsv2_open(name, f)) == 0) { 472 if ((error = ffsv2_open(name, f)) == 0) {
468 fs = &fs_ffsv2; 473 fs = &fs_ffsv2;
469 goto found; 474 goto found;
470 } 475 }
471 if (error == EINVAL && (error = ffsv1_open(name, f)) == 0) { 476 if (error == EINVAL && (error = ffsv1_open(name, f)) == 0) {
472 fs = &fs_ffsv1; 477 fs = &fs_ffsv1;
473 goto found; 478 goto found;
474 } 479 }
475 return error; 480 return error;
476 } 481 }
477 return ENXIO; 482 return ENXIO;
478 found: 483 found:
479#if 0 484#if 0
480printf("dsk_open found %s\n", fsmod); 485printf("dsk_open found %s\n", fsmod);
481#endif 486#endif
482 d->fsops = fs; 487 d->fsops = fs;
483 f->f_devdata = d; 488 f->f_devdata = d;
484 489
485 /* build btinfo to identify disk device */ 490 /* build btinfo to identify disk device */
486 snprintf(bi_rdev.devname, sizeof(bi_rdev.devname), "wd"); 491 snprintf(bi_rdev.devname, sizeof(bi_rdev.devname), "wd");
487 bi_rdev.cookie = d->unittag; /* disk unit number */ 492 bi_rdev.cookie = d->unittag; /* disk unit number */
488 return 0; 493 return 0;
489} 494}
490 495
491int 496int
492dsk_close(struct open_file *f) 497dsk_close(struct open_file *f)
493{ 498{
494 struct disk *d = f->f_devdata; 499 struct disk *d = f->f_devdata;
495 struct fs_ops *fs = d->fsops; 500 struct fs_ops *fs = d->fsops;
496 501
497 (*fs->close)(f); 502 (*fs->close)(f);
498 d->fsops = NULL; 503 d->fsops = NULL;
499 f->f_devdata = NULL; 504 f->f_devdata = NULL;
500 return 0; 505 return 0;
501} 506}
502 507
503int 508int
504dsk_strategy(void *devdata, int rw, daddr_t dblk, size_t size, 509dsk_strategy(void *devdata, int rw, daddr_t dblk, size_t size,
505 void *p, size_t *rsize) 510 void *p, size_t *rsize)
506{ 511{
507 struct disk *d = devdata; 512 struct disk *d = devdata;
508 struct disklabel *dlp; 513 struct disklabel *dlp;
509 uint64_t bno; 514 uint64_t bno;
510 515
511#if 0 516#if 0
512printf("%s %d %d\n", d->xname, (int)dblk, size); 517printf("%s %d %d\n", d->xname, (int)dblk, size);
513#endif 518#endif
514 if (size == 0) 519 if (size == 0)
515 return 0; 520 return 0;
516 if (rw != F_READ) 521 if (rw != F_READ)
517 return EOPNOTSUPP; 522 return EOPNOTSUPP;
518 523
519 bno = dblk; 524 bno = dblk;
520 if ((dlp = d->dlabel) != NULL) 525 if ((dlp = d->dlabel) != NULL)
521 bno += dlp->d_partitions[d->part].p_offset; 526 bno += dlp->d_partitions[d->part].p_offset;
522 (*d->lba_read)(d, bno, size / 512, p); 527 (*d->lba_read)(d, bno, size / 512, p);
523 if (rsize != NULL) 528 if (rsize != NULL)
524 *rsize = size; 529 *rsize = size;
525 return 0; 530 return 0;
526} 531}
527 532
528struct fs_ops * 533struct fs_ops *
529dsk_fsops(struct open_file *f) 534dsk_fsops(struct open_file *f)
530{ 535{
531 struct disk *d = f->f_devdata; 536 struct disk *d = f->f_devdata;
532 537
533 return d->fsops; 538 return d->fsops;
534} 539}