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