]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/pc98/pc98/diskslice_machdep.c
Remove #if NFOO > 0 (it's not required in most cases) and also where it
[FreeBSD/FreeBSD.git] / sys / pc98 / pc98 / diskslice_machdep.c
1 /*-
2  * Copyright (c) 1994 Bruce D. Evans.
3  * All rights reserved.
4  *
5  * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *      This product includes software developed by the University of
19  *      California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  *      from: @(#)ufs_disksubr.c        7.16 (Berkeley) 5/4/91
37  *      from: ufs_disksubr.c,v 1.8 1994/06/07 01:21:39 phk Exp $
38  * $FreeBSD$
39  */
40
41 /*
42  * PC9801 port by KATO Takenor <kato@eclogite.eps.nagoya-u.ac.jp>
43  */
44
45 #include "compat_atdisk.h"
46
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/buf.h>
50 #include <sys/conf.h>
51 #include <sys/disklabel.h>
52 #ifndef PC98
53 #define DOSPTYP_EXTENDED        5
54 #define DOSPTYP_EXTENDEDX       15
55 #define DOSPTYP_ONTRACK         84
56 #endif
57 #include <sys/diskslice.h>
58 #include <sys/malloc.h>
59 #include <sys/syslog.h>
60
61 #define TRACE(str)      do { if (dsi_debug) printf str; } while (0)
62
63 static volatile u_char dsi_debug;
64
65 #ifndef PC98
66 static struct dos_partition historical_bogus_partition_table[NDOSPART] = {
67         { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
68         { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
69         { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
70         { 0x80, 0, 1, 0, DOSPTYP_386BSD, 255, 255, 255, 0, 50000, },
71 };
72 #endif
73
74 static int check_part __P((char *sname, struct dos_partition *dp,
75                            u_long offset, int nsectors, int ntracks,
76                            u_long mbr_offset));
77 #ifndef PC98
78 static void mbr_extended __P((dev_t dev, struct disklabel *lp,
79                               struct diskslices *ssp, u_long ext_offset,
80                               u_long ext_size, u_long base_ext_offset,
81                               int nsectors, int ntracks, u_long mbr_offset,
82                               int level));
83 #endif
84
85 #ifdef PC98
86 #define DPBLKNO(cyl,hd,sect) ((cyl)*(lp->d_secpercyl))
87 #if     NCOMPAT_ATDISK > 0
88 int     atcompat_dsinit __P((dev_t dev,
89                  struct disklabel *lp, struct diskslices **sspp));
90 #endif
91 #endif
92
93 static int
94 check_part(sname, dp, offset, nsectors, ntracks, mbr_offset )
95         char    *sname;
96         struct dos_partition *dp;
97         u_long  offset;
98         int     nsectors;
99         int     ntracks;
100         u_long  mbr_offset;
101 {
102         int     chs_ecyl;
103         int     chs_esect;
104         int     chs_scyl;
105         int     chs_ssect;
106         int     error;
107         u_long  esector;
108         u_long  esector1;
109         u_long  secpercyl;
110         u_long  ssector;
111         u_long  ssector1;
112 #ifdef PC98
113         u_long  pc98_start;
114         u_long  pc98_size;
115 #endif
116
117         secpercyl = (u_long)nsectors * ntracks;
118 #ifdef PC98
119         chs_scyl = dp->dp_scyl;
120         chs_ssect = dp->dp_ssect;
121         ssector = chs_ssect + dp->dp_shd * nsectors + 
122                 chs_scyl * secpercyl + mbr_offset;
123 #else
124         chs_scyl = DPCYL(dp->dp_scyl, dp->dp_ssect);
125         chs_ssect = DPSECT(dp->dp_ssect);
126         ssector = chs_ssect - 1 + dp->dp_shd * nsectors + chs_scyl * secpercyl
127                   + mbr_offset;
128 #endif
129 #ifdef PC98
130         pc98_start = dp->dp_scyl * secpercyl;
131         pc98_size = dp->dp_ecyl ?
132                 (dp->dp_ecyl + 1) * secpercyl - pc98_start : 0;
133         ssector1 = offset + pc98_start;
134 #else
135         ssector1 = offset + dp->dp_start;
136 #endif
137
138         /*
139          * If ssector1 is on a cylinder >= 1024, then ssector can't be right.
140          * Allow the C/H/S for it to be 1023/ntracks-1/nsectors, or correct
141          * apart from the cylinder being reduced modulo 1024.  Always allow
142          * 1023/255/63.
143          */
144         if ((ssector < ssector1
145              && ((chs_ssect == nsectors && dp->dp_shd == ntracks - 1
146                   && chs_scyl == 1023)
147                  || (secpercyl != 0
148                      && (ssector1 - ssector) % (1024 * secpercyl) == 0)))
149             || (dp->dp_scyl == 255 && dp->dp_shd == 255
150                 && dp->dp_ssect == 255)) {
151                 TRACE(("%s: C/H/S start %d/%d/%d, start %lu: allow\n",
152                        sname, chs_scyl, dp->dp_shd, chs_ssect, ssector1));
153                 ssector = ssector1;
154         }
155
156 #ifdef PC98
157         chs_ecyl = dp->dp_ecyl;
158         chs_esect = nsectors - 1;
159         esector = chs_esect + (ntracks - 1) * nsectors +
160                 chs_ecyl * secpercyl + mbr_offset;
161         esector1 = ssector1 + pc98_size - 1;
162 #else
163         chs_ecyl = DPCYL(dp->dp_ecyl, dp->dp_esect);
164         chs_esect = DPSECT(dp->dp_esect);
165         esector = chs_esect - 1 + dp->dp_ehd * nsectors + chs_ecyl * secpercyl
166                   + mbr_offset;
167         esector1 = ssector1 + dp->dp_size - 1;
168 #endif
169
170         /* Allow certain bogus C/H/S values for esector, as above. */
171         if ((esector < esector1
172              && ((chs_esect == nsectors && dp->dp_ehd == ntracks - 1
173                   && chs_ecyl == 1023)
174                  || (secpercyl != 0
175                      && (esector1 - esector) % (1024 * secpercyl) == 0)))
176             || (dp->dp_ecyl == 255 && dp->dp_ehd == 255
177                 && dp->dp_esect == 255)) {
178                 TRACE(("%s: C/H/S end %d/%d/%d, end %lu: allow\n",
179                        sname, chs_ecyl, dp->dp_ehd, chs_esect, esector1));
180                 esector = esector1;
181         }
182
183         error = (ssector == ssector1 && esector == esector1) ? 0 : EINVAL;
184         if (bootverbose)
185 #ifdef PC98
186                 printf("%s: mid 0x%x, start %lu, end = %lu, size %lu%s\n",
187                        sname, dp->dp_mid, ssector1, esector1, pc98_size,
188                         error ? "" : ": OK");
189 #else
190                 printf("%s: type 0x%x, start %lu, end = %lu, size %lu %s\n",
191                        sname, dp->dp_typ, ssector1, esector1,
192                        (u_long)dp->dp_size, error ? "" : ": OK");
193 #endif
194         if (ssector != ssector1 && bootverbose)
195                 printf("%s: C/H/S start %d/%d/%d (%lu) != start %lu: invalid\n",
196                        sname, chs_scyl, dp->dp_shd, chs_ssect,
197                        ssector, ssector1);
198         if (esector != esector1 && bootverbose)
199                 printf("%s: C/H/S end %d/%d/%d (%lu) != end %lu: invalid\n",
200                        sname, chs_ecyl, dp->dp_ehd, chs_esect,
201                        esector, esector1);
202         return (error);
203 }
204
205 int
206 dsinit(dev, lp, sspp)
207         dev_t   dev;
208         struct disklabel *lp;
209         struct diskslices **sspp;
210 {
211         struct buf *bp;
212         u_char  *cp;
213         int     dospart;
214         struct dos_partition *dp;
215         struct dos_partition *dp0;
216         int     error;
217         int     max_ncyls;
218         int     max_nsectors;
219         int     max_ntracks;
220         u_long  mbr_offset;
221         char    partname[2];
222         u_long  secpercyl;
223         char    *sname;
224         struct diskslice *sp;
225         struct diskslices *ssp;
226 #ifdef PC98
227         u_long  pc98_start;
228         u_long  pc98_size;
229 #endif
230
231         mbr_offset = DOSBBSECTOR;
232 #ifdef PC98
233         /* Read master boot record. */
234         if ((int)lp->d_secsize < 1024)
235                 bp = geteblk((int)1024);
236         else
237                 bp = geteblk((int)lp->d_secsize);
238 #else
239 reread_mbr:
240         /* Read master boot record. */
241         bp = geteblk((int)lp->d_secsize);
242 #endif
243         bp->b_dev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART);
244         bp->b_blkno = mbr_offset;
245         bp->b_bcount = lp->d_secsize;
246         bp->b_flags |= B_READ;
247 #ifdef PC98
248         if (bp->b_bcount < 1024)
249                 bp->b_bcount = 1024;
250 #endif
251         BUF_STRATEGY(bp, 1);
252         if (biowait(bp) != 0) {
253                 diskerr(bp, "reading primary partition table: error",
254                     LOG_PRINTF, 0, (struct disklabel *)NULL);
255                 printf("\n");
256                 error = EIO;
257                 goto done;
258         }
259
260         /* Weakly verify it. */
261         cp = bp->b_data;
262         sname = dsname(dev, dkunit(dev), WHOLE_DISK_SLICE, RAW_PART, partname);
263         if (cp[0x1FE] != 0x55 || cp[0x1FF] != 0xAA) {
264                 if (bootverbose)
265                         printf("%s: invalid primary partition table: no magic\n",
266                                sname);
267                 error = EINVAL;
268                 goto done;
269         }
270 #ifdef PC98
271         /*
272          * entire disk for FreeBSD
273          */
274         if ((*(cp + 512) == 0x57) && (*(cp + 513) == 0x45) &&
275                 (*(cp + 514) == 0x56) && (*(cp + 515) == 0x82)) {
276                 sname = dsname(dev, dkunit(dev), BASE_SLICE,
277                         RAW_PART, partname);
278                 free(*sspp, M_DEVBUF);
279                 ssp = dsmakeslicestruct(MAX_SLICES, lp);
280                 *sspp = ssp;
281
282                 /* Initialize normal slices. */
283                 sp = &ssp->dss_slices[BASE_SLICE];
284                 sp->ds_offset = 0;
285                 sp->ds_size = lp->d_secperunit;
286                 sp->ds_type = DOSPTYP_386BSD;
287                 sp->ds_subtype = 0xc4;
288                 error = 0;
289                 ssp->dss_nslices = BASE_SLICE + 1;
290                 goto done;
291         }
292
293         /*
294          * XXX --- MS-DOG MO
295          */
296         if ((*(cp + 0x0e) == 1) && (*(cp + 0x15) == 0xf0) &&
297             (*(cp + 0x1c) == 0x0) && 
298                 ((*(cp + 512) == 0xf0) || (*(cp + 512) == 0xf8)) &&
299             (*(cp + 513) == 0xff) && (*(cp + 514) == 0xff)) {
300                 sname = dsname(dev, dkunit(dev), BASE_SLICE,
301                         RAW_PART, partname);
302                 free(*sspp, M_DEVBUF);
303                 ssp = dsmakeslicestruct(MAX_SLICES, lp);
304                 *sspp = ssp;
305
306                 /* Initialize normal slices. */
307                 sp = &ssp->dss_slices[BASE_SLICE];
308                 sp->ds_offset = 0;
309                 sp->ds_size = lp->d_secperunit;
310                 sp->ds_type = 0xa0;  /* XXX */
311                 sp->ds_subtype = 0x81;  /* XXX */
312                 error = 0;
313                 ssp->dss_nslices = BASE_SLICE + 1;
314                 goto done;
315         }
316 #if NCOMPAT_ATDISK > 0
317         /* 
318          * Check magic number of 'extended format' for PC-9801.
319          * If no magic, it may be formatted on IBM-PC.
320          */
321         if (((cp[4] != 'I') || (cp[5] != 'P') || (cp[6] != 'L') ||
322                  (cp[7] != '1')) &&
323                 ((strncmp(devtoname(bp->b_dev), "da", 2) == 0) ||
324             (strncmp(devtoname(bp->b_dev), "wd", 2) == 0))) {
325                 /* IBM-PC HDD */
326                 bp->b_flags |= B_INVAL | B_AGE;
327                 brelse(bp);
328                 return atcompat_dsinit(dev, lp, sspp);
329         }
330 #endif
331         dp0 = (struct dos_partition *)(cp + 512);
332 #else
333         dp0 = (struct dos_partition *)(cp + DOSPARTOFF);
334
335         /* Check for "Ontrack Diskmanager". */
336         for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++) {
337                 if (dp->dp_typ == DOSPTYP_ONTRACK) {
338                         if (bootverbose)
339                                 printf(
340             "%s: Found \"Ontrack Disk Manager\" on this disk.\n", sname);
341                         bp->b_flags |= B_INVAL | B_AGE;
342                         brelse(bp);
343                         mbr_offset = 63;
344                         goto reread_mbr;
345                 }
346         }
347
348         if (bcmp(dp0, historical_bogus_partition_table,
349                  sizeof historical_bogus_partition_table) == 0) {
350                 TRACE(("%s: invalid primary partition table: historical\n",
351                        sname));
352                 error = EINVAL;
353                 goto done;
354         }
355 #endif
356
357         /* Guess the geometry. */
358         /*
359          * TODO:
360          * Perhaps skip entries with 0 size.
361          * Perhaps only look at entries of type DOSPTYP_386BSD.
362          */
363         max_ncyls = 0;
364         max_nsectors = 0;
365         max_ntracks = 0;
366         for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++) {
367                 int     ncyls;
368                 int     nsectors;
369                 int     ntracks;
370
371
372 #ifdef PC98
373                 ncyls = lp->d_ncylinders;
374 #else
375                 ncyls = DPCYL(dp->dp_ecyl, dp->dp_esect) + 1;
376 #endif
377                 if (max_ncyls < ncyls)
378                         max_ncyls = ncyls;
379 #ifdef PC98
380                 nsectors = lp->d_nsectors;
381 #else
382                 nsectors = DPSECT(dp->dp_esect);
383 #endif
384                 if (max_nsectors < nsectors)
385                         max_nsectors = nsectors;
386 #ifdef PC98
387                 ntracks = lp->d_ntracks;
388 #else
389                 ntracks = dp->dp_ehd + 1;
390 #endif
391                 if (max_ntracks < ntracks)
392                         max_ntracks = ntracks;
393         }
394
395         /*
396          * Check that we have guessed the geometry right by checking the
397          * partition entries.
398          */
399         /*
400          * TODO:
401          * As above.
402          * Check for overlaps.
403          * Check against d_secperunit if the latter is reliable.
404          */
405         error = 0;
406 #ifdef PC98
407         for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++) {
408                 if (dp->dp_scyl == 0 && dp->dp_shd == 0 && dp->dp_ssect == 0)
409                         continue;
410                 sname = dsname(dev, dkunit(dev), BASE_SLICE + dospart,
411                                 RAW_PART, partname);
412 #else
413         for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++) {
414                 if (dp->dp_scyl == 0 && dp->dp_shd == 0 && dp->dp_ssect == 0
415                     && dp->dp_start == 0 && dp->dp_size == 0)
416                         continue;
417                 sname = dsname(dev, dkunit(dev), BASE_SLICE + dospart,
418                                RAW_PART, partname);
419 #endif
420                 /*
421                  * Temporarily ignore errors from this check.  We could
422                  * simplify things by accepting the table eariler if we
423                  * always ignore errors here.  Perhaps we should always
424                  * accept the table if the magic is right but not let
425                  * bad entries affect the geometry.
426                  */
427                 check_part(sname, dp, mbr_offset, max_nsectors, max_ntracks,
428                            mbr_offset);
429         }
430         if (error != 0)
431                 goto done;
432
433         /*
434          * Accept the DOS partition table.
435          * First adjust the label (we have been careful not to change it
436          * before we can guarantee success).
437          */
438         secpercyl = (u_long)max_nsectors * max_ntracks;
439         if (secpercyl != 0) {
440                 u_long  secperunit;
441
442                 lp->d_nsectors = max_nsectors;
443                 lp->d_ntracks = max_ntracks;
444                 lp->d_secpercyl = secpercyl;
445                 secperunit = secpercyl * max_ncyls;
446                 if (lp->d_secperunit < secperunit)
447                         lp->d_secperunit = secperunit;
448                 lp->d_ncylinders = lp->d_secperunit / secpercyl;
449         }
450
451         /*
452          * We are passed a pointer to a suitably initialized minimal
453          * slices "struct" with no dangling pointers in it.  Replace it
454          * by a maximal one.  This usually oversizes the "struct", but
455          * enlarging it while searching for logical drives would be
456          * inconvenient.
457          */
458         free(*sspp, M_DEVBUF);
459         ssp = dsmakeslicestruct(MAX_SLICES, lp);
460         *sspp = ssp;
461
462         /* Initialize normal slices. */
463         sp = &ssp->dss_slices[BASE_SLICE];
464         for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++, sp++) {
465 #ifdef PC98
466                 pc98_start = DPBLKNO(dp->dp_scyl,dp->dp_shd,dp->dp_ssect);
467                 pc98_size = dp->dp_ecyl ? DPBLKNO(dp->dp_ecyl+1,dp->dp_ehd,dp->dp_esect) - pc98_start : 0;
468                 sp->ds_offset = pc98_start;
469                 sp->ds_size = pc98_size;
470                 sp->ds_type = dp->dp_mid;
471                 sp->ds_subtype = dp->dp_sid;
472                 strncpy(sp->ds_name, dp->dp_name, sizeof(sp->ds_name));
473 #else
474                 sp->ds_offset = mbr_offset + dp->dp_start;
475                 sp->ds_size = dp->dp_size;
476                 sp->ds_type = dp->dp_typ;
477 #endif
478 #if 0
479                 lp->d_subtype |= (lp->d_subtype & 3) | dospart
480                                  | DSTYPE_INDOSPART;
481 #endif
482         }
483         ssp->dss_nslices = BASE_SLICE + NDOSPART;
484
485 #ifndef PC98
486         /* Handle extended partitions. */
487         sp -= NDOSPART;
488         for (dospart = 0; dospart < NDOSPART; dospart++, sp++)
489                 if (sp->ds_type == DOSPTYP_EXTENDED ||
490                     sp->ds_type == DOSPTYP_EXTENDEDX)
491                         mbr_extended(bp->b_dev, lp, ssp,
492                                      sp->ds_offset, sp->ds_size, sp->ds_offset,
493                                      max_nsectors, max_ntracks, mbr_offset, 1);
494
495         /*
496          * mbr_extended() abuses ssp->dss_nslices for the number of slices
497          * that would be found if there were no limit on the number of slices
498          * in *ssp.  Cut it back now.
499          */
500         if (ssp->dss_nslices > MAX_SLICES)
501                 ssp->dss_nslices = MAX_SLICES;
502 #endif
503
504 done:
505         bp->b_flags |= B_INVAL | B_AGE;
506         brelse(bp);
507         if (error == EINVAL)
508                 error = 0;
509         return (error);
510 }
511
512 #ifndef PC98
513 void
514 mbr_extended(dev, lp, ssp, ext_offset, ext_size, base_ext_offset, nsectors,
515              ntracks, mbr_offset, level)
516         dev_t   dev;
517         struct disklabel *lp;
518         struct diskslices *ssp;
519         u_long  ext_offset;
520         u_long  ext_size;
521         u_long  base_ext_offset;
522         int     nsectors;
523         int     ntracks;
524         u_long  mbr_offset;
525         int     level;
526 {
527         struct buf *bp;
528         u_char  *cp;
529         int     dospart;
530         struct dos_partition *dp;
531         struct dos_partition dpcopy[NDOSPART];
532         u_long  ext_offsets[NDOSPART];
533         u_long  ext_sizes[NDOSPART];
534         char    partname[2];
535         int     slice;
536         char    *sname;
537         struct diskslice *sp;
538
539         if (level >= 16) {
540                 printf(
541         "%s: excessive recursion in search for slices; aborting search\n",
542                        devtoname(dev));
543                 return;
544         }
545
546         /* Read extended boot record. */
547         bp = geteblk((int)lp->d_secsize);
548         bp->b_dev = dev;
549         bp->b_blkno = ext_offset;
550         bp->b_bcount = lp->d_secsize;
551         bp->b_flags |= B_READ;
552         BUF_STRATEGY(bp, 1);
553         if (biowait(bp) != 0) {
554                 diskerr(bp, "reading extended partition table: error",
555                     LOG_PRINTF, 0, (struct disklabel *)NULL);
556                 printf("\n");
557                 goto done;
558         }
559
560         /* Weakly verify it. */
561         cp = bp->b_data;
562         if (cp[0x1FE] != 0x55 || cp[0x1FF] != 0xAA) {
563                 sname = dsname(dev, dkunit(dev), WHOLE_DISK_SLICE, RAW_PART,
564                                partname);
565                 if (bootverbose)
566                         printf("%s: invalid extended partition table: no magic\n",
567                                sname);
568                 goto done;
569         }
570
571         /* Make a copy of the partition table to avoid alignment problems. */
572         memcpy(&dpcopy[0], cp + DOSPARTOFF, sizeof(dpcopy));
573
574         slice = ssp->dss_nslices;
575         for (dospart = 0, dp = &dpcopy[0]; dospart < NDOSPART;
576             dospart++, dp++) {
577                 ext_sizes[dospart] = 0;
578                 if (dp->dp_scyl == 0 && dp->dp_shd == 0 && dp->dp_ssect == 0
579                     && dp->dp_start == 0 && dp->dp_size == 0)
580                         continue;
581                 if (dp->dp_typ == DOSPTYP_EXTENDED ||
582                     dp->dp_typ == DOSPTYP_EXTENDEDX) {
583                         static char buf[32];
584
585                         sname = dsname(dev, dkunit(dev), WHOLE_DISK_SLICE,
586                                        RAW_PART, partname);
587                         snprintf(buf, sizeof(buf), "%s", sname);
588                         if (strlen(buf) < sizeof buf - 11)
589                                 strcat(buf, "<extended>");
590                         check_part(buf, dp, base_ext_offset, nsectors,
591                                    ntracks, mbr_offset);
592                         ext_offsets[dospart] = base_ext_offset + dp->dp_start;
593                         ext_sizes[dospart] = dp->dp_size;
594                 } else {
595                         sname = dsname(dev, dkunit(dev), slice, RAW_PART,
596                                        partname);
597                         check_part(sname, dp, ext_offset, nsectors, ntracks,
598                                    mbr_offset);
599                         if (slice >= MAX_SLICES) {
600                                 printf("%s: too many slices\n", sname);
601                                 slice++;
602                                 continue;
603                         }
604                         sp = &ssp->dss_slices[slice];
605                         sp->ds_offset = ext_offset + dp->dp_start;
606                         sp->ds_size = dp->dp_size;
607                         sp->ds_type = dp->dp_typ;
608 #ifdef PC98_ATCOMPAT
609                         /* Fake FreeBSD(98). */
610                         if (sp->ds_type == DOSPTYP_386BSD)
611                                 sp->ds_type = 0x94;
612 #endif
613                         slice++;
614                 }
615         }
616         ssp->dss_nslices = slice;
617
618         /* If we found any more slices, recursively find all the subslices. */
619         for (dospart = 0; dospart < NDOSPART; dospart++)
620                 if (ext_sizes[dospart] != 0)
621                         mbr_extended(dev, lp, ssp, ext_offsets[dospart],
622                                      ext_sizes[dospart], base_ext_offset,
623                                      nsectors, ntracks, mbr_offset, ++level);
624
625 done:
626         bp->b_flags |= B_INVAL | B_AGE;
627         brelse(bp);
628 }
629 #endif
630
631 #ifdef __alpha__
632 void
633 alpha_fix_srm_checksum(bp)
634         struct buf *bp;
635 {
636         u_int64_t *p;
637         u_int64_t sum;
638         int i;
639
640         p = (u_int64_t *) bp->b_data;
641         sum = 0;
642         for (i = 0; i < 63; i++)
643                 sum += p[i];
644         p[63] = sum;
645 }
646 #endif