Subject: Re: Reading DOS formatted ZIP drive
To: None <fou@ON-Luebeck.DE>
From: Ken Nakata <kenn@synap.ne.jp>
List: port-mac68k
Date: 08/04/1998 20:06:58
If you can compile your own kernel, try the following diffs (not sure
if it still applies cleanly, tho).  This is my old Quick Dirty Hack
[TM] to make mac68k read DOS type partition.  Just make sure you have
the "file-system MSDOSFS" line *uncommented* in your config file
(GENERIC has it uncommented by default).  With this patch applied,
you'll be able to see DOS partitions on your Zip disks so you can
mount them:

*** orig/src/sys/arch/mac68k/mac68k/disksubr.c  Tue Jan 13 08:45:14 1998
--- src/sys/arch/mac68k/mac68k/disksubr.c       Sun Feb 15 17:14:32 1998
***************
*** 109,114 ****
--- 109,116 ----
  __P((struct partmapentry *, int, struct disklabel *, int, int, int *));
  static char *read_mac_label __P((dev_t, void (*)(struct buf *),
                register struct disklabel *, struct cpu_disklabel *));
+ static char *read_dos_label __P((dev_t, void (*)(struct buf *),
+               register struct disklabel *, struct cpu_disklabel *));


  /*
   * Find an entry in the disk label that is unused and return it
***************
*** 452,458 ****
                        break;
                }
        }
!       lp->d_npartitions = maxslot+1;


  done:
        bp->b_flags = B_INVAL | B_AGE | B_READ;
--- 454,460 ----
                        break;
                }
        }
!       lp->d_npartitions = ((maxslot >= RAW_PART) ? maxslot : RAW_PART) + 1;


  done:
        bp->b_flags = B_INVAL | B_AGE | B_READ;
***************
*** 460,465 ****
--- 462,539 ----
        return msg;
  }


+ #ifdef MSDOSFS
+ static int fat_types[] = { DOSPTYP_FAT12, DOSPTYP_FAT16S,
+                          DOSPTYP_FAT16B, DOSPTYP_FAT16C, -1 };
+
+ /* Read MS-DOS partition table.
+  *
+  * XXX -
+  * Since FFS is endian sensitive, we pay no effort in attempting to
+  * dig up *BSD/i386 disk labels that may be present on the disk.
+  * Hence anything but DOS partitions is treated as unknown FS type, but
+  * this should suffice to mount_msdos Zip and other removable media.
+  */
+ static char *
+ read_dos_label(dev, strat, lp, osdep)
+       dev_t dev;
+       void (*strat)(struct buf *);
+       register struct disklabel *lp;
+       struct cpu_disklabel *osdep;
+ {
+       struct dos_partition *dp;
+       struct partition *pp;
+       struct buf *bp;
+       char *msg = NULL;
+       int i, *ip, slot, maxslot = 0;
+
+       /* get a buffer and initialize it */
+       bp = geteblk((int)lp->d_secsize);
+       bp->b_dev = dev;
+
+       /* read master boot record */
+       bp->b_blkno = DOSBBSECTOR;
+       bp->b_bcount = lp->d_secsize;
+       bp->b_flags = B_BUSY | B_READ;
+       bp->b_cylin = DOSBBSECTOR / lp->d_secpercyl;
+       (*strat)(bp);
+
+       /* if successful, wander through dos partition table */
+       if (biowait(bp)) {
+               msg = "dos partition I/O error";
+               goto done;
+       } else {
+               /* XXX */
+               dp = (struct dos_partition *)(bp->b_data + DOSPARTOFF);
+               for (i = 0; i < NDOSPART; i++, dp++) {
+                       if (dp->dp_typ != 0) {
+                               u_int8_t fstype = FS_OTHER;
+
+                               slot = getFreeLabelEntry(lp);
+                               if (slot > maxslot) maxslot = slot;
+
+                               for (ip = fat_types; *ip != -1; ip++) {
+                                       if (dp->dp_typ == *ip) {
+                                               fstype = FS_MSDOS;
+                                               break;
+                                       }
+                               }
+                               pp = &lp->d_partitions[slot];
+                               pp->p_fstype = fstype;
+                               pp->p_offset = bswap32(dp->dp_start);
+                               pp->p_size = bswap32(dp->dp_size);
+                       }
+               }
+       }
+       lp->d_npartitions = ((maxslot >= RAW_PART) ? maxslot : RAW_PART) + 1;
+
+  done:
+       bp->b_flags |= B_INVAL;
+       brelse(bp);
+       return (msg);
+ }
+ #endif /* MSDOSFS */
+
  /*
   * Attempt to read a disk label from a device using the indicated stategy
   * routine.  The label must be partly set up before this: secpercyl and
***************
*** 506,511 ****
--- 580,590 ----
                sbSigp = (u_int16_t *) bp->b_un.b_addr;
                if (*sbSigp == 0x4552) {
                        msg = read_mac_label(dev, strat, lp, osdep);
+ #ifdef MSDOSFS
+               } else if (*(u_int16_t *)(bp->b_data + 510) == 0x55aa
+                          /* XXX */) {
+                       msg = read_dos_label(dev, strat, lp, osdep);
+ #endif /* MSDOSFS */
                } else {
                        dlp = (struct disklabel *)(bp->b_un.b_addr + 0);
                        if (dlp->d_magic == DISKMAGIC) {
*** orig/src/sys/arch/mac68k/include/disklabel.h        Sun May  5 07:31:44 199
6
--- src/sys/arch/mac68k/include/disklabel.h     Sun Feb 15 00:11:01 1998
***************
*** 38,43 ****
--- 38,71 ----
  #define       MAXPARTITIONS   8                       /* number of partitions
 */
  #define       RAW_PART        2                       /* raw partition: xx?c
*/


+ #ifdef MSDOSFS
+ /* DOS partition table -- located in boot block */
+ #define       DOSBBSECTOR     0               /* DOS boot block relative sect
or # */
+ #define       DOSPARTOFF      446
+ #define       NDOSPART        4
+
+ struct dos_partition {
+       unsigned char   dp_flag;        /* bootstrap flags */
+       unsigned char   dp_shd;         /* starting head */
+       unsigned char   dp_ssect;       /* starting sector */
+       unsigned char   dp_scyl;        /* starting cylinder */
+       unsigned char   dp_typ;         /* partition type (see below) */
+       unsigned char   dp_ehd;         /* end head */
+       unsigned char   dp_esect;       /* end sector */
+       unsigned char   dp_ecyl;        /* end cylinder */
+       unsigned long   dp_start;       /* absolute starting sector number */
+       unsigned long   dp_size;        /* partition size in sectors */
+ };
+
+ /* Known DOS partition types. */
+ #define       DOSPTYP_386BSD  0xa5            /* 386BSD partition type */
+ #define DOSPTYP_NETBSD        DOSPTYP_386BSD  /* NetBSD partition type (XXX)
*/
+ #define DOSPTYP_FAT12 0x1             /* 12-bit FAT */
+ #define DOSPTYP_FAT16S        0x4             /* 16-bit FAT, less than 32M */
+ #define DOSPTYP_FAT16B        0x6             /* 16-bit FAT, more than 32M */
+ #define DOSPTYP_FAT16C        0xe             /* 16-bit FAT, CHS-mapped */
+ #endif /* MSDOSFS */
+
  /* Just a dummy */
  struct cpu_disklabel {
        int     cd_dummy;                       /* must have one element. */