1 1.5 andvar /* $NetBSD: wdc.c,v 1.5 2025/10/07 20:09:27 andvar Exp $ */ 2 1.1 kiyohara 3 1.1 kiyohara /*- 4 1.1 kiyohara * Copyright (c) 2003 The NetBSD Foundation, Inc. 5 1.1 kiyohara * All rights reserved. 6 1.1 kiyohara * 7 1.1 kiyohara * This code is derived from software contributed to The NetBSD Foundation 8 1.1 kiyohara * by Manuel Bouyer. 9 1.1 kiyohara * 10 1.1 kiyohara * Redistribution and use in source and binary forms, with or without 11 1.1 kiyohara * modification, are permitted provided that the following conditions 12 1.1 kiyohara * are met: 13 1.1 kiyohara * 1. Redistributions of source code must retain the above copyright 14 1.1 kiyohara * notice, this list of conditions and the following disclaimer. 15 1.1 kiyohara * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 kiyohara * notice, this list of conditions and the following disclaimer in the 17 1.1 kiyohara * documentation and/or other materials provided with the distribution. 18 1.1 kiyohara * 19 1.1 kiyohara * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 kiyohara * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 kiyohara * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 kiyohara * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 kiyohara * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 kiyohara * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 kiyohara * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 kiyohara * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 kiyohara * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 kiyohara * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 kiyohara * POSSIBILITY OF SUCH DAMAGE. 30 1.1 kiyohara */ 31 1.1 kiyohara 32 1.3 christos #include <sys/param.h> 33 1.1 kiyohara #include <sys/types.h> 34 1.1 kiyohara #include <sys/disklabel.h> 35 1.1 kiyohara #include <sys/bootblock.h> 36 1.1 kiyohara 37 1.1 kiyohara #include <lib/libsa/stand.h> 38 1.1 kiyohara #include <lib/libkern/libkern.h> 39 1.1 kiyohara 40 1.1 kiyohara #include "boot.h" 41 1.1 kiyohara #include "wdvar.h" 42 1.1 kiyohara 43 1.1 kiyohara #if defined(SH3) 44 1.1 kiyohara #define MMEYE_WDC0_IOBASE 0xb6000000 45 1.1 kiyohara #define MMEYE_WDC1_IOBASE 0xb7000000 46 1.1 kiyohara #elif defined(SH4) 47 1.1 kiyohara #define MMEYE_WDC0_IOBASE 0xb6000000 48 1.1 kiyohara #define MMEYE_WDC1_IOBASE 0xb7000000 49 1.1 kiyohara #endif 50 1.1 kiyohara #define MMEYE_WDC_CTLBASE 0x206 51 1.1 kiyohara 52 1.1 kiyohara #define WDCDELAY 100 53 1.1 kiyohara #define WDCNDELAY_RST 31000 * 10 54 1.1 kiyohara 55 1.1 kiyohara static int wdcprobe(struct wdc_channel *chp); 56 1.1 kiyohara static int wdc_wait_for_ready(struct wdc_channel *chp); 57 1.1 kiyohara static int wdc_read_block(struct wd_softc *sc, struct wdc_command *wd_c); 58 1.1 kiyohara static int __wdcwait_reset(struct wdc_channel *chp, int drv_mask); 59 1.1 kiyohara 60 1.1 kiyohara /* 61 1.1 kiyohara * Reset the controller. 62 1.1 kiyohara */ 63 1.1 kiyohara static int 64 1.1 kiyohara __wdcwait_reset(struct wdc_channel *chp, int drv_mask) 65 1.1 kiyohara { 66 1.1 kiyohara int timeout; 67 1.1 kiyohara uint8_t st0, st1; 68 1.1 kiyohara 69 1.1 kiyohara /* wait for BSY to deassert */ 70 1.1 kiyohara for (timeout = 0; timeout < WDCNDELAY_RST; timeout++) { 71 1.1 kiyohara WDC_WRITE_REG(chp, wd_sdh, WDSD_IBM); /* master */ 72 1.1 kiyohara delay(10); 73 1.1 kiyohara st0 = WDC_READ_REG(chp, wd_status); 74 1.1 kiyohara WDC_WRITE_REG(chp, wd_sdh, WDSD_IBM | 0x10); /* slave */ 75 1.1 kiyohara delay(10); 76 1.1 kiyohara st1 = WDC_READ_REG(chp, wd_status); 77 1.1 kiyohara 78 1.1 kiyohara if ((drv_mask & 0x01) == 0) { 79 1.1 kiyohara /* no master */ 80 1.1 kiyohara if ((drv_mask & 0x02) != 0 && (st1 & WDCS_BSY) == 0) { 81 1.1 kiyohara /* No master, slave is ready, it's done */ 82 1.1 kiyohara goto end; 83 1.1 kiyohara } 84 1.1 kiyohara } else if ((drv_mask & 0x02) == 0) { 85 1.1 kiyohara /* no slave */ 86 1.1 kiyohara if ((drv_mask & 0x01) != 0 && (st0 & WDCS_BSY) == 0) { 87 1.1 kiyohara /* No slave, master is ready, it's done */ 88 1.1 kiyohara goto end; 89 1.1 kiyohara } 90 1.1 kiyohara } else { 91 1.1 kiyohara /* Wait for both master and slave to be ready */ 92 1.1 kiyohara if ((st0 & WDCS_BSY) == 0 && (st1 & WDCS_BSY) == 0) { 93 1.1 kiyohara goto end; 94 1.1 kiyohara } 95 1.1 kiyohara } 96 1.1 kiyohara 97 1.1 kiyohara delay(WDCDELAY); 98 1.1 kiyohara } 99 1.1 kiyohara 100 1.1 kiyohara /* Reset timed out. Maybe it's because drv_mask was not right */ 101 1.1 kiyohara if (st0 & WDCS_BSY) 102 1.1 kiyohara drv_mask &= ~0x01; 103 1.1 kiyohara if (st1 & WDCS_BSY) 104 1.1 kiyohara drv_mask &= ~0x02; 105 1.1 kiyohara 106 1.1 kiyohara end: 107 1.1 kiyohara return drv_mask; 108 1.1 kiyohara } 109 1.1 kiyohara 110 1.1 kiyohara /* Test to see controller with at last one attached drive is there. 111 1.1 kiyohara * Returns a bit for each possible drive found (0x01 for drive 0, 112 1.1 kiyohara * 0x02 for drive 1). 113 1.1 kiyohara * Logic: 114 1.1 kiyohara * - If a status register is at 0xff, assume there is no drive here 115 1.1 kiyohara * (ISA has pull-up resistors). Similarly if the status register has 116 1.1 kiyohara * the value we last wrote to the bus (for IDE interfaces without pullups). 117 1.1 kiyohara * If no drive at all -> return. 118 1.1 kiyohara * - reset the controller, wait for it to complete (may take up to 31s !). 119 1.1 kiyohara * If timeout -> return. 120 1.1 kiyohara */ 121 1.1 kiyohara static int 122 1.1 kiyohara wdcprobe(struct wdc_channel *chp) 123 1.1 kiyohara { 124 1.1 kiyohara uint8_t st0, st1; 125 1.1 kiyohara uint8_t ret_value = 0x03; 126 1.1 kiyohara uint8_t drive; 127 1.1 kiyohara 128 1.1 kiyohara /* 129 1.1 kiyohara * Sanity check to see if the wdc channel responds at all. 130 1.1 kiyohara */ 131 1.1 kiyohara WDC_WRITE_REG(chp, wd_sdh, WDSD_IBM); 132 1.1 kiyohara delay(10); 133 1.1 kiyohara st0 = WDC_READ_REG(chp, wd_status); 134 1.1 kiyohara WDC_WRITE_REG(chp, wd_sdh, WDSD_IBM | 0x10); 135 1.1 kiyohara delay(10); 136 1.1 kiyohara st1 = WDC_READ_REG(chp, wd_status); 137 1.1 kiyohara 138 1.1 kiyohara if (st0 == 0xff || st0 == WDSD_IBM) 139 1.1 kiyohara ret_value &= ~0x01; 140 1.1 kiyohara if (st1 == 0xff || st1 == (WDSD_IBM | 0x10)) 141 1.1 kiyohara ret_value &= ~0x02; 142 1.1 kiyohara if (ret_value == 0) 143 1.1 kiyohara return ENXIO; 144 1.1 kiyohara 145 1.1 kiyohara /* assert SRST, wait for reset to complete */ 146 1.1 kiyohara WDC_WRITE_REG(chp, wd_sdh, WDSD_IBM); 147 1.1 kiyohara delay(10); 148 1.1 kiyohara WDC_WRITE_CTLREG(chp, wd_aux_ctlr, WDCTL_RST | WDCTL_IDS); 149 1.1 kiyohara delay(1000); 150 1.1 kiyohara WDC_WRITE_CTLREG(chp, wd_aux_ctlr, WDCTL_IDS); 151 1.1 kiyohara delay(1000); 152 1.1 kiyohara (void) WDC_READ_REG(chp, wd_error); 153 1.1 kiyohara WDC_WRITE_CTLREG(chp, wd_aux_ctlr, WDCTL_4BIT); 154 1.1 kiyohara delay(10); 155 1.1 kiyohara 156 1.1 kiyohara ret_value = __wdcwait_reset(chp, ret_value); 157 1.1 kiyohara 158 1.1 kiyohara /* if reset failed, there's nothing here */ 159 1.1 kiyohara if (ret_value == 0) 160 1.1 kiyohara return ENXIO; 161 1.1 kiyohara 162 1.1 kiyohara /* 163 1.1 kiyohara * Test presence of drives. First test register signatures looking for 164 1.1 kiyohara * ATAPI devices. If it's not an ATAPI and reset said there may be 165 1.1 kiyohara * something here assume it's ATA or OLD. Ghost will be killed later in 166 1.1 kiyohara * attach routine. 167 1.1 kiyohara */ 168 1.1 kiyohara for (drive = 0; drive < 2; drive++) { 169 1.1 kiyohara if ((ret_value & (0x01 << drive)) == 0) 170 1.1 kiyohara continue; 171 1.1 kiyohara return 0; 172 1.1 kiyohara } 173 1.1 kiyohara return ENXIO; 174 1.1 kiyohara } 175 1.1 kiyohara 176 1.1 kiyohara /* 177 1.1 kiyohara * Initialize the device. 178 1.1 kiyohara */ 179 1.1 kiyohara int 180 1.1 kiyohara wdc_init(struct wd_softc *sc, u_int *unit) 181 1.1 kiyohara { 182 1.1 kiyohara struct wdc_channel *chp = &sc->sc_channel; 183 1.1 kiyohara uint32_t cmdreg, ctlreg; 184 1.1 kiyohara int i; 185 1.1 kiyohara 186 1.5 andvar /* XXXX: Should reset CF COR here? */ 187 1.1 kiyohara 188 1.1 kiyohara switch (*unit) { 189 1.1 kiyohara case 0: cmdreg = MMEYE_WDC0_IOBASE; break; 190 1.1 kiyohara case 1: cmdreg = MMEYE_WDC1_IOBASE; break; 191 1.1 kiyohara 192 1.1 kiyohara default: 193 1.1 kiyohara return ENXIO; 194 1.1 kiyohara } 195 1.1 kiyohara ctlreg = cmdreg + MMEYE_WDC_CTLBASE; 196 1.1 kiyohara 197 1.2 kamil /* set up cmd registers */ 198 1.1 kiyohara chp->c_cmdbase = (uint8_t *)cmdreg; 199 1.1 kiyohara chp->c_data = (uint16_t *)(cmdreg + wd_data); 200 1.1 kiyohara for (i = 0; i < WDC_NPORTS; i++) 201 1.1 kiyohara chp->c_cmdreg[i] = chp->c_cmdbase + i; 202 1.1 kiyohara /* set up shadow registers */ 203 1.1 kiyohara chp->c_cmdreg[wd_status] = chp->c_cmdreg[wd_command]; 204 1.1 kiyohara chp->c_cmdreg[wd_features] = chp->c_cmdreg[wd_precomp]; 205 1.1 kiyohara /* set up ctl registers */ 206 1.1 kiyohara chp->c_ctlbase = (uint8_t *)ctlreg; 207 1.1 kiyohara 208 1.1 kiyohara if (wdcprobe(&sc->sc_channel) != 0) 209 1.1 kiyohara return ENXIO; 210 1.1 kiyohara return 0; 211 1.1 kiyohara } 212 1.1 kiyohara 213 1.1 kiyohara /* 214 1.1 kiyohara * Wait until the device is ready. 215 1.1 kiyohara */ 216 1.1 kiyohara int 217 1.1 kiyohara wdc_wait_for_ready(struct wdc_channel *chp) 218 1.1 kiyohara { 219 1.1 kiyohara u_int timeout; 220 1.1 kiyohara 221 1.1 kiyohara for (timeout = WDC_TIMEOUT; timeout > 0; --timeout) { 222 1.1 kiyohara if ((WDC_READ_REG(chp, wd_status) & (WDCS_BSY | WDCS_DRDY)) 223 1.1 kiyohara == WDCS_DRDY) 224 1.1 kiyohara return 0; 225 1.1 kiyohara delay(1); 226 1.1 kiyohara } 227 1.1 kiyohara return ENXIO; 228 1.1 kiyohara } 229 1.1 kiyohara 230 1.1 kiyohara /* 231 1.1 kiyohara * Read one block off the device. 232 1.1 kiyohara */ 233 1.1 kiyohara int 234 1.1 kiyohara wdc_read_block(struct wd_softc *sc, struct wdc_command *wd_c) 235 1.1 kiyohara { 236 1.1 kiyohara int i; 237 1.1 kiyohara struct wdc_channel *chp = &sc->sc_channel; 238 1.1 kiyohara uint16_t *ptr = (uint16_t *)wd_c->data; 239 1.1 kiyohara 240 1.1 kiyohara if (ptr == NULL) 241 1.1 kiyohara return 0; 242 1.1 kiyohara 243 1.1 kiyohara if (wd_c->r_command == WDCC_IDENTIFY) 244 1.1 kiyohara for (i = wd_c->bcount; i > 0; i -= sizeof(uint16_t)) 245 1.1 kiyohara *ptr++ = WDC_READ_DATA(chp); 246 1.1 kiyohara else 247 1.1 kiyohara for (i = wd_c->bcount; i > 0; i -= sizeof(uint16_t)) 248 1.1 kiyohara *ptr++ = WDC_READ_DATA_STREAM(chp); 249 1.1 kiyohara 250 1.1 kiyohara return 0; 251 1.1 kiyohara } 252 1.1 kiyohara 253 1.1 kiyohara /* 254 1.1 kiyohara * Send a command to the device (CHS and LBA addressing). 255 1.1 kiyohara */ 256 1.1 kiyohara int 257 1.1 kiyohara wdccommand(struct wd_softc *sc, struct wdc_command *wd_c) 258 1.1 kiyohara { 259 1.1 kiyohara struct wdc_channel *chp = &sc->sc_channel; 260 1.1 kiyohara 261 1.1 kiyohara #if 0 262 1.1 kiyohara DPRINTF(("wdccommand(%d, %d, %d, %d, %d, %d, %d)\n", 263 1.1 kiyohara wd_c->drive, wd_c->r_command, wd_c->r_cyl, 264 1.1 kiyohara wd_c->r_head, wd_c->r_sector, wd_c->bcount, 265 1.1 kiyohara wd_c->r_precomp)); 266 1.1 kiyohara #endif 267 1.1 kiyohara 268 1.1 kiyohara WDC_WRITE_REG(chp, wd_features, wd_c->r_features); 269 1.1 kiyohara WDC_WRITE_REG(chp, wd_seccnt, wd_c->r_count); 270 1.1 kiyohara WDC_WRITE_REG(chp, wd_sector, wd_c->r_sector); 271 1.1 kiyohara WDC_WRITE_REG(chp, wd_cyl_lo, wd_c->r_cyl); 272 1.1 kiyohara WDC_WRITE_REG(chp, wd_cyl_hi, wd_c->r_cyl >> 8); 273 1.1 kiyohara WDC_WRITE_REG(chp, wd_sdh, 274 1.1 kiyohara WDSD_IBM | (wd_c->drive << 4) | wd_c->r_head); 275 1.1 kiyohara WDC_WRITE_REG(chp, wd_command, wd_c->r_command); 276 1.1 kiyohara 277 1.1 kiyohara if (wdc_wait_for_ready(chp) != 0) 278 1.1 kiyohara return ENXIO; 279 1.1 kiyohara 280 1.1 kiyohara if (WDC_READ_REG(chp, wd_status) & WDCS_ERR) { 281 1.1 kiyohara printf("wd%d: error %x\n", chp->compatchan, 282 1.1 kiyohara WDC_READ_REG(chp, wd_error)); 283 1.1 kiyohara return ENXIO; 284 1.1 kiyohara } 285 1.1 kiyohara 286 1.1 kiyohara return 0; 287 1.1 kiyohara } 288 1.1 kiyohara 289 1.1 kiyohara /* 290 1.1 kiyohara * Send a command to the device (LBA48 addressing). 291 1.1 kiyohara */ 292 1.1 kiyohara int 293 1.1 kiyohara wdccommandext(struct wd_softc *wd, struct wdc_command *wd_c) 294 1.1 kiyohara { 295 1.1 kiyohara struct wdc_channel *chp = &wd->sc_channel; 296 1.1 kiyohara 297 1.1 kiyohara #if 0 298 1.1 kiyohara DPRINTF(("%s(%d, %x, %" PRId64 ", %d)\n", __func__, 299 1.1 kiyohara wd_c->drive, wd_c->r_command, 300 1.1 kiyohara wd_c->r_blkno, wd_c->r_count)); 301 1.1 kiyohara #endif 302 1.1 kiyohara 303 1.1 kiyohara /* Select drive, head, and addressing mode. */ 304 1.1 kiyohara WDC_WRITE_REG(chp, wd_sdh, (wd_c->drive << 4) | WDSD_LBA); 305 1.1 kiyohara 306 1.1 kiyohara /* previous */ 307 1.1 kiyohara WDC_WRITE_REG(chp, wd_features, 0); 308 1.1 kiyohara WDC_WRITE_REG(chp, wd_seccnt, wd_c->r_count >> 8); 309 1.1 kiyohara WDC_WRITE_REG(chp, wd_lba_hi, wd_c->r_blkno >> 40); 310 1.1 kiyohara WDC_WRITE_REG(chp, wd_lba_mi, wd_c->r_blkno >> 32); 311 1.1 kiyohara WDC_WRITE_REG(chp, wd_lba_lo, wd_c->r_blkno >> 24); 312 1.1 kiyohara 313 1.1 kiyohara /* current */ 314 1.1 kiyohara WDC_WRITE_REG(chp, wd_features, 0); 315 1.1 kiyohara WDC_WRITE_REG(chp, wd_seccnt, wd_c->r_count); 316 1.1 kiyohara WDC_WRITE_REG(chp, wd_lba_hi, wd_c->r_blkno >> 16); 317 1.1 kiyohara WDC_WRITE_REG(chp, wd_lba_mi, wd_c->r_blkno >> 8); 318 1.1 kiyohara WDC_WRITE_REG(chp, wd_lba_lo, wd_c->r_blkno); 319 1.1 kiyohara 320 1.1 kiyohara /* Send command. */ 321 1.1 kiyohara WDC_WRITE_REG(chp, wd_command, wd_c->r_command); 322 1.1 kiyohara 323 1.1 kiyohara if (wdc_wait_for_ready(chp) != 0) 324 1.1 kiyohara return ENXIO; 325 1.1 kiyohara 326 1.1 kiyohara if (WDC_READ_REG(chp, wd_status) & WDCS_ERR) { 327 1.1 kiyohara printf("wd%d: error %x\n", chp->compatchan, 328 1.1 kiyohara WDC_READ_REG(chp, wd_error)); 329 1.1 kiyohara return ENXIO; 330 1.1 kiyohara } 331 1.1 kiyohara 332 1.1 kiyohara return 0; 333 1.1 kiyohara } 334 1.1 kiyohara 335 1.1 kiyohara /* 336 1.1 kiyohara * Issue 'device identify' command. 337 1.1 kiyohara */ 338 1.1 kiyohara int 339 1.1 kiyohara wdc_exec_identify(struct wd_softc *wd, void *data) 340 1.1 kiyohara { 341 1.1 kiyohara int error; 342 1.1 kiyohara struct wdc_command wd_c; 343 1.1 kiyohara 344 1.1 kiyohara memset(&wd_c, 0, sizeof(wd_c)); 345 1.1 kiyohara 346 1.1 kiyohara wd_c.drive = 0; 347 1.1 kiyohara wd_c.r_command = WDCC_IDENTIFY; 348 1.1 kiyohara wd_c.bcount = DEV_BSIZE; 349 1.1 kiyohara wd_c.data = data; 350 1.1 kiyohara 351 1.1 kiyohara if ((error = wdccommand(wd, &wd_c)) != 0) 352 1.1 kiyohara return error; 353 1.1 kiyohara 354 1.1 kiyohara return wdc_read_block(wd, &wd_c); 355 1.1 kiyohara } 356 1.1 kiyohara 357 1.1 kiyohara /* 358 1.1 kiyohara * Issue 'read' command. 359 1.1 kiyohara */ 360 1.1 kiyohara int 361 1.1 kiyohara wdc_exec_read(struct wd_softc *wd, uint8_t cmd, daddr_t blkno, void *data) 362 1.1 kiyohara { 363 1.1 kiyohara int error; 364 1.1 kiyohara struct wdc_command wd_c; 365 1.1 kiyohara bool lba, lba48; 366 1.1 kiyohara 367 1.1 kiyohara memset(&wd_c, 0, sizeof(wd_c)); 368 1.1 kiyohara lba = false; 369 1.1 kiyohara lba48 = false; 370 1.1 kiyohara 371 1.1 kiyohara wd_c.data = data; 372 1.1 kiyohara wd_c.r_count = 1; 373 1.1 kiyohara wd_c.r_features = 0; 374 1.1 kiyohara wd_c.drive = 0; 375 1.1 kiyohara wd_c.bcount = wd->sc_label.d_secsize; 376 1.1 kiyohara 377 1.1 kiyohara if ((wd->sc_flags & WDF_LBA48) != 0 && blkno > wd->sc_capacity28) 378 1.1 kiyohara lba48 = true; 379 1.1 kiyohara else if ((wd->sc_flags & WDF_LBA) != 0) 380 1.1 kiyohara lba = true; 381 1.1 kiyohara 382 1.1 kiyohara if (lba48) { 383 1.1 kiyohara /* LBA48 */ 384 1.1 kiyohara wd_c.r_command = atacmd_to48(cmd); 385 1.1 kiyohara wd_c.r_blkno = blkno; 386 1.1 kiyohara } else if (lba) { 387 1.1 kiyohara /* LBA */ 388 1.1 kiyohara wd_c.r_command = cmd; 389 1.1 kiyohara wd_c.r_sector = (blkno >> 0) & 0xff; 390 1.1 kiyohara wd_c.r_cyl = (blkno >> 8) & 0xffff; 391 1.1 kiyohara wd_c.r_head = (blkno >> 24) & 0x0f; 392 1.1 kiyohara wd_c.r_head |= WDSD_LBA; 393 1.1 kiyohara } else { 394 1.1 kiyohara /* CHS */ 395 1.1 kiyohara wd_c.r_command = cmd; 396 1.1 kiyohara wd_c.r_sector = blkno % wd->sc_label.d_nsectors; 397 1.1 kiyohara wd_c.r_sector++; /* Sectors begin with 1, not 0. */ 398 1.1 kiyohara blkno /= wd->sc_label.d_nsectors; 399 1.1 kiyohara wd_c.r_head = blkno % wd->sc_label.d_ntracks; 400 1.1 kiyohara blkno /= wd->sc_label.d_ntracks; 401 1.1 kiyohara wd_c.r_cyl = blkno; 402 1.1 kiyohara wd_c.r_head |= WDSD_CHS; 403 1.1 kiyohara } 404 1.1 kiyohara 405 1.1 kiyohara if (lba48) 406 1.1 kiyohara error = wdccommandext(wd, &wd_c); 407 1.1 kiyohara else 408 1.1 kiyohara error = wdccommand(wd, &wd_c); 409 1.1 kiyohara 410 1.1 kiyohara if (error != 0) 411 1.1 kiyohara return error; 412 1.1 kiyohara 413 1.1 kiyohara return wdc_read_block(wd, &wd_c); 414 1.1 kiyohara } 415