1 1.17 jdc /* $NetBSD: disksubr.c,v 1.17 2020/05/03 06:31:02 jdc Exp $ */ 2 1.1 bouyer 3 1.4 perry /* 4 1.1 bouyer * Copyright (c) 1982, 1986, 1988 Regents of the University of California. 5 1.1 bouyer * All rights reserved. 6 1.1 bouyer * 7 1.1 bouyer * Redistribution and use in source and binary forms, with or without 8 1.1 bouyer * modification, are permitted provided that the following conditions 9 1.1 bouyer * are met: 10 1.1 bouyer * 1. Redistributions of source code must retain the above copyright 11 1.1 bouyer * notice, this list of conditions and the following disclaimer. 12 1.1 bouyer * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 bouyer * notice, this list of conditions and the following disclaimer in the 14 1.1 bouyer * documentation and/or other materials provided with the distribution. 15 1.1 bouyer * 3. Neither the name of the University nor the names of its contributors 16 1.1 bouyer * may be used to endorse or promote products derived from this software 17 1.1 bouyer * without specific prior written permission. 18 1.1 bouyer * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19 1.1 bouyer * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 1.1 bouyer * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 1.1 bouyer * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 1.1 bouyer * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 1.1 bouyer * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 1.1 bouyer * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 1.1 bouyer * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 1.1 bouyer * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 1.1 bouyer * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 1.1 bouyer * SUCH DAMAGE. 29 1.1 bouyer */ 30 1.1 bouyer 31 1.1 bouyer /* 32 1.1 bouyer * Copyright (c) 1994, 1995 Gordon W. Ross 33 1.1 bouyer * Copyright (c) 1994 Theo de Raadt 34 1.1 bouyer * All rights reserved. 35 1.1 bouyer * 36 1.1 bouyer * Redistribution and use in source and binary forms, with or without 37 1.1 bouyer * modification, are permitted provided that the following conditions 38 1.1 bouyer * are met: 39 1.1 bouyer * 1. Redistributions of source code must retain the above copyright 40 1.1 bouyer * notice, this list of conditions and the following disclaimer. 41 1.1 bouyer * 2. Redistributions in binary form must reproduce the above copyright 42 1.1 bouyer * notice, this list of conditions and the following disclaimer in the 43 1.1 bouyer * documentation and/or other materials provided with the distribution. 44 1.1 bouyer * 45 1.1 bouyer * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 46 1.1 bouyer * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 47 1.1 bouyer * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 48 1.1 bouyer * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 49 1.1 bouyer * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 50 1.1 bouyer * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 51 1.1 bouyer * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 52 1.1 bouyer * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 53 1.1 bouyer * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 54 1.1 bouyer * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 55 1.1 bouyer */ 56 1.1 bouyer 57 1.1 bouyer #include <sys/cdefs.h> 58 1.17 jdc __KERNEL_RCSID(0, "$NetBSD: disksubr.c,v 1.17 2020/05/03 06:31:02 jdc Exp $"); 59 1.1 bouyer 60 1.1 bouyer #include <sys/param.h> 61 1.1 bouyer #include <sys/systm.h> 62 1.1 bouyer #include <sys/buf.h> 63 1.1 bouyer #include <sys/ioccom.h> 64 1.1 bouyer #include <sys/device.h> 65 1.1 bouyer #include <sys/disklabel.h> 66 1.1 bouyer #include <sys/disk.h> 67 1.1 bouyer #include <sys/dkbad.h> 68 1.1 bouyer 69 1.1 bouyer #include <dev/sun/disklabel.h> 70 1.1 bouyer 71 1.1 bouyer #if LABELSECTOR != 0 72 1.1 bouyer #error "Default value of LABELSECTOR no longer zero?" 73 1.1 bouyer #endif 74 1.1 bouyer 75 1.6 christos static const char *disklabel_sun_to_bsd(char *, struct disklabel *); 76 1.3 perry static int disklabel_bsd_to_sun(struct disklabel *, char *); 77 1.1 bouyer 78 1.1 bouyer /* 79 1.1 bouyer * Attempt to read a disk label from a device 80 1.1 bouyer * using the indicated strategy routine. 81 1.1 bouyer * The label must be partly set up before this: 82 1.1 bouyer * secpercyl, secsize and anything required for a block i/o read 83 1.1 bouyer * operation in the driver's strategy/start routines 84 1.1 bouyer * must be filled in before calling us. 85 1.1 bouyer * 86 1.1 bouyer * Return buffer for use in signalling errors if requested. 87 1.1 bouyer * 88 1.1 bouyer * Returns null on success and an error string on failure. 89 1.1 bouyer */ 90 1.1 bouyer const char * 91 1.12 dsl readdisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, struct cpu_disklabel *clp) 92 1.1 bouyer { 93 1.1 bouyer struct buf *bp; 94 1.1 bouyer struct disklabel *dlp; 95 1.1 bouyer struct sun_disklabel *slp; 96 1.1 bouyer int error; 97 1.1 bouyer 98 1.1 bouyer /* minimal requirements for archtypal disk label */ 99 1.1 bouyer if (lp->d_secperunit == 0) 100 1.1 bouyer lp->d_secperunit = 0x1fffffff; 101 1.1 bouyer if (lp->d_npartitions == 0) { 102 1.1 bouyer lp->d_npartitions = RAW_PART + 1; 103 1.1 bouyer if (lp->d_partitions[RAW_PART].p_size == 0) 104 1.1 bouyer lp->d_partitions[RAW_PART].p_size = 0x1fffffff; 105 1.1 bouyer lp->d_partitions[RAW_PART].p_offset = 0; 106 1.1 bouyer } 107 1.17 jdc if (lp->d_secsize == 0) 108 1.17 jdc return ("sector size 0"); 109 1.1 bouyer 110 1.1 bouyer /* obtain buffer to probe drive with */ 111 1.1 bouyer bp = geteblk((int)lp->d_secsize); 112 1.1 bouyer 113 1.1 bouyer /* next, dig out disk label */ 114 1.1 bouyer bp->b_dev = dev; 115 1.1 bouyer bp->b_blkno = LABELSECTOR; 116 1.1 bouyer bp->b_cylinder = 0; 117 1.1 bouyer bp->b_bcount = lp->d_secsize; 118 1.1 bouyer bp->b_flags |= B_READ; 119 1.1 bouyer (*strat)(bp); 120 1.1 bouyer 121 1.1 bouyer /* if successful, locate disk label within block and validate */ 122 1.1 bouyer error = biowait(bp); 123 1.1 bouyer if (error == 0) { 124 1.1 bouyer /* Save the whole block in case it has info we need. */ 125 1.1 bouyer memcpy(clp->cd_block, bp->b_data, sizeof(clp->cd_block)); 126 1.1 bouyer } 127 1.9 ad brelse(bp, 0); 128 1.1 bouyer if (error) 129 1.1 bouyer return ("disk label read error"); 130 1.1 bouyer 131 1.1 bouyer /* Check for a NetBSD disk label at LABELOFFSET */ 132 1.1 bouyer dlp = (struct disklabel *) (clp->cd_block + LABELOFFSET); 133 1.1 bouyer if (dlp->d_magic == DISKMAGIC) { 134 1.1 bouyer if (dkcksum(dlp)) 135 1.1 bouyer return ("NetBSD disk label corrupted"); 136 1.1 bouyer *lp = *dlp; 137 1.1 bouyer return (NULL); 138 1.1 bouyer } 139 1.1 bouyer 140 1.1 bouyer /* Check for a Sun disk label (for PROM compatibility). */ 141 1.1 bouyer slp = (struct sun_disklabel *) clp->cd_block; 142 1.1 bouyer if (slp->sl_magic == SUN_DKMAGIC) 143 1.1 bouyer return (disklabel_sun_to_bsd(clp->cd_block, lp)); 144 1.1 bouyer 145 1.1 bouyer /* 146 1.1 bouyer * Check for a NetBSD disk label somewhere in LABELSECTOR 147 1.1 bouyer * (compat with others big-endian boxes) 148 1.1 bouyer */ 149 1.1 bouyer for (dlp = (struct disklabel *)clp->cd_block; 150 1.1 bouyer dlp <= (struct disklabel *)((char *)clp->cd_block + 151 1.1 bouyer DEV_BSIZE - sizeof(*dlp)); 152 1.1 bouyer dlp = (struct disklabel *)((char *)dlp + sizeof(long))) { 153 1.1 bouyer if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) { 154 1.1 bouyer continue; 155 1.1 bouyer } 156 1.1 bouyer if (dlp->d_npartitions > MAXPARTITIONS || dkcksum(dlp) != 0) 157 1.1 bouyer return("NetBSD disk label corrupted"); 158 1.1 bouyer else { 159 1.1 bouyer *lp = *dlp; 160 1.1 bouyer return(NULL); 161 1.1 bouyer } 162 1.1 bouyer } 163 1.1 bouyer 164 1.1 bouyer memset(clp->cd_block, 0, sizeof(clp->cd_block)); 165 1.15 martin return NULL; 166 1.1 bouyer } 167 1.1 bouyer 168 1.1 bouyer /* 169 1.1 bouyer * Write disk label back to device after modification. 170 1.1 bouyer * Current label is already in clp->cd_block[] 171 1.1 bouyer */ 172 1.1 bouyer int 173 1.12 dsl writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, struct cpu_disklabel *clp) 174 1.1 bouyer { 175 1.1 bouyer struct buf *bp; 176 1.1 bouyer int error; 177 1.1 bouyer struct disklabel *dlp; 178 1.1 bouyer struct sun_disklabel *slp; 179 1.1 bouyer 180 1.1 bouyer /* 181 1.1 bouyer * Embed native label in a piece of wasteland. 182 1.1 bouyer */ 183 1.1 bouyer if (sizeof(struct disklabel) > sizeof slp->sl_bsdlabel) 184 1.1 bouyer return EFBIG; 185 1.1 bouyer 186 1.1 bouyer slp = (struct sun_disklabel *)clp->cd_block; 187 1.1 bouyer memset(slp->sl_bsdlabel, 0, sizeof(slp->sl_bsdlabel)); 188 1.1 bouyer dlp = (struct disklabel *)slp->sl_bsdlabel; 189 1.1 bouyer *dlp = *lp; 190 1.1 bouyer 191 1.1 bouyer /* Build a SunOS compatible label around the native label */ 192 1.1 bouyer error = disklabel_bsd_to_sun(lp, clp->cd_block); 193 1.1 bouyer if (error) 194 1.1 bouyer return (error); 195 1.1 bouyer 196 1.1 bouyer /* Get a buffer and copy the new label into it. */ 197 1.1 bouyer bp = geteblk((int)lp->d_secsize); 198 1.1 bouyer memcpy(bp->b_data, clp->cd_block, sizeof(clp->cd_block)); 199 1.1 bouyer 200 1.1 bouyer /* Write out the updated label. */ 201 1.1 bouyer bp->b_dev = dev; 202 1.1 bouyer bp->b_blkno = LABELSECTOR; 203 1.1 bouyer bp->b_cylinder = 0; 204 1.1 bouyer bp->b_bcount = lp->d_secsize; 205 1.1 bouyer bp->b_flags |= B_WRITE; 206 1.1 bouyer (*strat)(bp); 207 1.1 bouyer error = biowait(bp); 208 1.9 ad brelse(bp, 0); 209 1.1 bouyer 210 1.1 bouyer return (error); 211 1.1 bouyer } 212 1.1 bouyer 213 1.1 bouyer /************************************************************************ 214 1.1 bouyer * 215 1.1 bouyer * The rest of this was taken from arch/sparc/scsi/sun_disklabel.c 216 1.1 bouyer * and then substantially rewritten by Gordon W. Ross 217 1.1 bouyer * 218 1.1 bouyer ************************************************************************/ 219 1.1 bouyer 220 1.1 bouyer /* What partition types to assume for Sun disklabels: */ 221 1.1 bouyer static u_char 222 1.1 bouyer sun_fstypes[8] = { 223 1.1 bouyer FS_BSDFFS, /* a */ 224 1.1 bouyer FS_SWAP, /* b */ 225 1.1 bouyer FS_OTHER, /* c - whole disk */ 226 1.1 bouyer FS_BSDFFS, /* d */ 227 1.1 bouyer FS_BSDFFS, /* e */ 228 1.1 bouyer FS_BSDFFS, /* f */ 229 1.1 bouyer FS_BSDFFS, /* g */ 230 1.1 bouyer FS_BSDFFS, /* h */ 231 1.1 bouyer }; 232 1.1 bouyer 233 1.1 bouyer /* 234 1.1 bouyer * Given a SunOS disk label, set lp to a BSD disk label. 235 1.1 bouyer * Returns NULL on success, else an error string. 236 1.1 bouyer * 237 1.1 bouyer * The BSD label is cleared out before this is called. 238 1.1 bouyer */ 239 1.5 christos static const char * 240 1.10 dsl disklabel_sun_to_bsd(char *cp, struct disklabel *lp) 241 1.1 bouyer { 242 1.1 bouyer struct sun_disklabel *sl; 243 1.1 bouyer struct partition *npp; 244 1.1 bouyer struct sun_dkpart *spp; 245 1.1 bouyer int i, secpercyl; 246 1.14 martin unsigned int secpblck; 247 1.1 bouyer u_short cksum, *sp1, *sp2; 248 1.1 bouyer 249 1.1 bouyer sl = (struct sun_disklabel *)cp; 250 1.1 bouyer 251 1.1 bouyer /* Verify the XOR check. */ 252 1.1 bouyer sp1 = (u_short *)sl; 253 1.1 bouyer sp2 = (u_short *)(sl + 1); 254 1.1 bouyer cksum = 0; 255 1.1 bouyer while (sp1 < sp2) 256 1.1 bouyer cksum ^= *sp1++; 257 1.1 bouyer if (cksum != 0) 258 1.1 bouyer return("SunOS disk label, bad checksum"); 259 1.1 bouyer 260 1.1 bouyer /* Format conversion. */ 261 1.1 bouyer lp->d_magic = DISKMAGIC; 262 1.1 bouyer lp->d_magic2 = DISKMAGIC; 263 1.1 bouyer memcpy(lp->d_packname, sl->sl_text, sizeof(lp->d_packname)); 264 1.1 bouyer 265 1.14 martin secpblck = lp->d_secsize / 512; 266 1.14 martin if (secpblck == 0) secpblck = 1; /* can't happen */ 267 1.1 bouyer lp->d_secsize = 512; 268 1.1 bouyer lp->d_nsectors = sl->sl_nsectors; 269 1.1 bouyer lp->d_ntracks = sl->sl_ntracks; 270 1.1 bouyer lp->d_ncylinders = sl->sl_ncylinders; 271 1.1 bouyer 272 1.1 bouyer secpercyl = sl->sl_nsectors * sl->sl_ntracks; 273 1.1 bouyer lp->d_secpercyl = secpercyl; 274 1.1 bouyer lp->d_secperunit = secpercyl * sl->sl_ncylinders; 275 1.1 bouyer 276 1.1 bouyer lp->d_sparespercyl = sl->sl_sparespercyl; 277 1.1 bouyer lp->d_acylinders = sl->sl_acylinders; 278 1.1 bouyer lp->d_rpm = sl->sl_rpm; 279 1.1 bouyer lp->d_interleave = sl->sl_interleave; 280 1.1 bouyer 281 1.1 bouyer lp->d_npartitions = 8; 282 1.1 bouyer /* These are as defined in <ufs/ffs/fs.h> */ 283 1.1 bouyer lp->d_bbsize = 8192; /* XXX */ 284 1.1 bouyer lp->d_sbsize = 8192; /* XXX */ 285 1.1 bouyer 286 1.1 bouyer for (i = 0; i < 8; i++) { 287 1.1 bouyer spp = &sl->sl_part[i]; 288 1.1 bouyer npp = &lp->d_partitions[i]; 289 1.14 martin 290 1.13 martin if (npp->p_fstype == FS_ISO9660 291 1.14 martin && spp->sdkp_cyloffset * secpercyl == npp->p_offset*secpblck 292 1.14 martin && spp->sdkp_nsectors <= npp->p_size*secpblck 293 1.13 martin && npp->p_size > 0 && spp->sdkp_nsectors > 0) { 294 1.13 martin /* 295 1.13 martin * This happens for example on sunlabel'd hybrid 296 1.13 martin * (ffs + ISO9660) CDs, like our install CDs. 297 1.13 martin * The cd driver has initialized a valid ISO9660 298 1.13 martin * partition (including session parameters), so 299 1.13 martin * we better not overwrite it. 300 1.13 martin */ 301 1.14 martin npp->p_offset *= secpblck; 302 1.14 martin npp->p_size = spp->sdkp_nsectors; 303 1.14 martin npp->p_cdsession *= secpblck; 304 1.13 martin continue; 305 1.13 martin } 306 1.1 bouyer npp->p_offset = spp->sdkp_cyloffset * secpercyl; 307 1.1 bouyer npp->p_size = spp->sdkp_nsectors; 308 1.1 bouyer if (npp->p_size == 0) { 309 1.1 bouyer npp->p_fstype = FS_UNUSED; 310 1.1 bouyer } else { 311 1.1 bouyer npp->p_fstype = sun_fstypes[i]; 312 1.1 bouyer if (npp->p_fstype == FS_BSDFFS) { 313 1.1 bouyer /* 314 1.1 bouyer * The sun label does not store the FFS fields, 315 1.1 bouyer * so just set them with default values here. 316 1.1 bouyer */ 317 1.1 bouyer npp->p_fsize = 1024; 318 1.1 bouyer npp->p_frag = 8; 319 1.1 bouyer npp->p_cpg = 16; 320 1.1 bouyer } 321 1.1 bouyer } 322 1.1 bouyer } 323 1.1 bouyer 324 1.1 bouyer lp->d_checksum = 0; 325 1.1 bouyer lp->d_checksum = dkcksum(lp); 326 1.1 bouyer return (NULL); 327 1.1 bouyer } 328 1.1 bouyer 329 1.1 bouyer /* 330 1.1 bouyer * Given a BSD disk label, update the Sun disklabel 331 1.1 bouyer * pointed to by cp with the new info. Note that the 332 1.1 bouyer * Sun disklabel may have other info we need to keep. 333 1.1 bouyer * Returns zero or error code. 334 1.1 bouyer */ 335 1.1 bouyer static int 336 1.10 dsl disklabel_bsd_to_sun(struct disklabel *lp, char *cp) 337 1.1 bouyer { 338 1.1 bouyer struct sun_disklabel *sl; 339 1.1 bouyer struct partition *npp; 340 1.1 bouyer struct sun_dkpart *spp; 341 1.1 bouyer int i, secpercyl; 342 1.1 bouyer u_short cksum, *sp1, *sp2; 343 1.1 bouyer 344 1.1 bouyer if (lp->d_secsize != 512) 345 1.1 bouyer return (EINVAL); 346 1.1 bouyer 347 1.1 bouyer sl = (struct sun_disklabel *)cp; 348 1.1 bouyer 349 1.1 bouyer /* 350 1.1 bouyer * Format conversion. 351 1.1 bouyer */ 352 1.1 bouyer memcpy(sl->sl_text, lp->d_packname, sizeof(lp->d_packname)); 353 1.1 bouyer sl->sl_rpm = lp->d_rpm; 354 1.1 bouyer sl->sl_pcylinders = lp->d_ncylinders + lp->d_acylinders; /* XXX */ 355 1.1 bouyer sl->sl_sparespercyl = lp->d_sparespercyl; 356 1.1 bouyer sl->sl_interleave = lp->d_interleave; 357 1.1 bouyer sl->sl_ncylinders = lp->d_ncylinders; 358 1.1 bouyer sl->sl_acylinders = lp->d_acylinders; 359 1.1 bouyer sl->sl_ntracks = lp->d_ntracks; 360 1.1 bouyer sl->sl_nsectors = lp->d_nsectors; 361 1.1 bouyer 362 1.1 bouyer secpercyl = sl->sl_nsectors * sl->sl_ntracks; 363 1.1 bouyer for (i = 0; i < 8; i++) { 364 1.1 bouyer spp = &sl->sl_part[i]; 365 1.1 bouyer npp = &lp->d_partitions[i]; 366 1.1 bouyer 367 1.1 bouyer /* 368 1.1 bouyer * SunOS partitions must start on a cylinder boundary. 369 1.1 bouyer * Note this restriction is forced upon NetBSD/sparc 370 1.1 bouyer * labels too, since we want to keep both labels 371 1.1 bouyer * synchronised. 372 1.1 bouyer */ 373 1.1 bouyer if (npp->p_offset % secpercyl) 374 1.1 bouyer return (EINVAL); 375 1.1 bouyer spp->sdkp_cyloffset = npp->p_offset / secpercyl; 376 1.1 bouyer spp->sdkp_nsectors = npp->p_size; 377 1.1 bouyer } 378 1.1 bouyer sl->sl_magic = SUN_DKMAGIC; 379 1.1 bouyer 380 1.1 bouyer /* Compute the XOR check. */ 381 1.1 bouyer sp1 = (u_short *)sl; 382 1.1 bouyer sp2 = (u_short *)(sl + 1); 383 1.1 bouyer sl->sl_cksum = cksum = 0; 384 1.1 bouyer while (sp1 < sp2) 385 1.1 bouyer cksum ^= *sp1++; 386 1.1 bouyer sl->sl_cksum = cksum; 387 1.1 bouyer 388 1.1 bouyer return (0); 389 1.1 bouyer } 390 1.1 bouyer 391 1.1 bouyer /* 392 1.1 bouyer * Search the bad sector table looking for the specified sector. 393 1.1 bouyer * Return index if found. 394 1.1 bouyer * Return -1 if not found. 395 1.1 bouyer */ 396 1.1 bouyer int 397 1.11 dsl isbad(struct dkbad *bt, int cyl, int trk, int sec) 398 1.1 bouyer { 399 1.1 bouyer int i; 400 1.1 bouyer long blk, bblk; 401 1.1 bouyer 402 1.1 bouyer blk = ((long)cyl << 16) + (trk << 8) + sec; 403 1.1 bouyer for (i = 0; i < 126; i++) { 404 1.1 bouyer bblk = ((long)bt->bt_bad[i].bt_cyl << 16) + 405 1.1 bouyer bt->bt_bad[i].bt_trksec; 406 1.1 bouyer if (blk == bblk) 407 1.1 bouyer return (i); 408 1.1 bouyer if (blk < bblk || bblk < 0) 409 1.1 bouyer break; 410 1.1 bouyer } 411 1.1 bouyer return (-1); 412 1.1 bouyer } 413