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 (expand / 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,14 +1,14 @@ @@ -1,14 +1,14 @@
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.
@@ -144,38 +144,42 @@ spinwait_unbusy(struct dkdev_ata *l, int @@ -144,38 +144,42 @@ spinwait_unbusy(struct dkdev_ata *l, int
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);
@@ -241,30 +245,30 @@ drive_ident(struct disk *d, char *ident) @@ -241,30 +245,30 @@ drive_ident(struct disk *d, char *ident)
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];
@@ -347,74 +351,75 @@ decode_dlabel(struct disk *d, char *iobu @@ -347,74 +351,75 @@ decode_dlabel(struct disk *d, char *iobu
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)