| @@ -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 | |
175 | int | | 179 | int |
176 | perform_atareset(struct dkdev_ata *l, int n) | | 180 | perform_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 | |
267 | static char * | | 271 | static char * |
268 | mkident(char *src, int len) | | 272 | mkident(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 | |
353 | static void | | 357 | static void |
354 | set_xfermode(struct dkdev_ata *l, int n) | | 358 | set_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 | |
369 | static int | | 370 | static int |
370 | lba_read(struct disk *d, uint64_t bno, uint32_t bcnt, void *buf) | | 371 | lba_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 | |
403 | static void | | 408 | static void |
404 | issue48(struct dvata_chan *chan, uint64_t bno, uint32_t nblk) | | 409 | issue48(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 | |
419 | static void | | 424 | static void |
420 | issue28(struct dvata_chan *chan, uint64_t bno, uint32_t nblk) | | 425 | issue28(struct dvata_chan *chan, uint64_t bno, uint32_t nblk) |