/*-
 * Copyright (c) 2002-2018 The UbixOS Project.
 * All rights reserved.
 *
 * This was developed by Christopher W. Olsen for the UbixOS Project.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
 *
 * 1) Redistributions of source code must retain the above copyright notice, this list of
 *    conditions, the following disclaimer and the list of authors.
 * 2) Redistributions in binary form must reproduce the above copyright notice, this list of
 *    conditions, the following disclaimer and the list of authors in the documentation and/or
 *    other materials provided with the distribution.
 * 3) Neither the name of the UbixOS Project nor the names of its contributors may be used to
 *    endorse or promote products derived from this software without specific prior written
 *    permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _PCI_HD_H_
#define _PCI_HD_H_

#include <sys/types.h>
#include <ubixfs/ubixfs.h>

#define hdData     0x0
#define hdError    0x1
#define hdSecCount 0x2
#define hdSecNum   0x3
#define hdCylLow   0x4
#define hdCylHi    0x5
#define hdHead     0x6
#define hdStat     0x7
#define hdCmd      0x7

/* ATA Uhm? */
#define ATA_IDENTIFY_COMMAND_SET_SUPPORTED1_48BIT_ENABLE 0x0400
#define ATA_IDENTIFY_SECTOR_LARGER_THEN_512_ENABLE       0x0100

/* ATA register defines */
#define ATA_DATA                        0       /* (RW) data */

#define ATA_FEATURE                     1       /* (W) feature */
#define         ATA_F_DMA               0x01    /* enable DMA */
#define         ATA_F_OVL               0x02    /* enable overlap */

#define ATA_COUNT                       2       /* (W) sector count */

#define ATA_SECTOR                      3       /* (RW) sector # */
#define ATA_CYL_LSB                     4       /* (RW) cylinder# LSB */
#define ATA_CYL_MSB                     5       /* (RW) cylinder# MSB */
#define ATA_DRIVE                       6       /* (W) Sector/Drive/Head */
#define         ATA_D_LBA               0x40    /* use LBA addressing */
#define         ATA_D_IBM               0xa0    /* 512 byte sectors, ECC */

#define ATA_COMMAND                     7       /* (W) command */

#define ATA_ERROR                       8       /* (R) error */
#define         ATA_E_ILI               0x01    /* illegal length */
#define         ATA_E_NM                0x02    /* no media */
#define         ATA_E_ABORT             0x04    /* command aborted */
#define         ATA_E_MCR               0x08    /* media change request */
#define         ATA_E_IDNF              0x10    /* ID not found */
#define         ATA_E_MC                0x20    /* media changed */
#define         ATA_E_UNC               0x40    /* uncorrectable data */
#define         ATA_E_ICRC              0x80    /* UDMA crc error */
#define         ATA_E_ATAPI_SENSE_MASK  0xf0    /* ATAPI sense key mask */

#define ATA_IREASON                     9       /* (R) interrupt reason */
#define         ATA_I_CMD               0x01    /* cmd (1) | data (0) */
#define         ATA_I_IN                0x02    /* read (1) | write (0) */
#define         ATA_I_RELEASE           0x04    /* released bus (1) */
#define         ATA_I_TAGMASK           0xf8    /* tag mask */

#define ATA_STATUS                      10      /* (R) status */
#define ATA_ALTSTAT                     11      /* (R) alternate status */
#define         ATA_S_ERROR             0x01    /* error */
#define         ATA_S_INDEX             0x02    /* index */
#define         ATA_S_CORR              0x04    /* data corrected */
#define         ATA_S_DRQ               0x08    /* data request */
#define         ATA_S_DSC               0x10    /* drive seek completed */
#define         ATA_S_SERVICE           0x10    /* drive needs service */
#define         ATA_S_DWF               0x20    /* drive write fault */
#define         ATA_S_DMA               0x20    /* DMA ready */
#define         ATA_S_READY             0x40    /* drive ready */
#define         ATA_S_BUSY              0x80    /* busy */

#define ATA_CONTROL                     12      /* (W) control */

#define ATA_CTLOFFSET                   0x206   /* control register offset */
#define ATA_PCCARD_CTLOFFSET            0x0e    /* do for PCCARD devices */
#define ATA_PC98_CTLOFFSET              0x10c   /* do for PC98 devices */
#define         ATA_A_IDS               0x02    /* disable interrupts */
#define         ATA_A_RESET             0x04    /* RESET controller */
#ifdef  ATA_LEGACY_SUPPORT
#define         ATA_A_4BIT              0x08    /* 4 head bits: obsolete 1996 */
#else
#define         ATA_A_4BIT              0x00
#endif
#define         ATA_A_HOB               0x80    /* High Order Byte enable */

/* ATA Commands */
#define ATA_IDENTIFY                   0xEC
#define ATA_CHECK_POWER_MODE           0xE5
#define ATA_STANDBY                    0xE2
#define ATA_STANDBY_IMMED              0xE0
#define ATA_IDLE_IMMED                 0xE1
#define ATA_IDLE                       0xE3
#define ATA_FLUSH_CACHE                0xE7
#define ATA_FLUSH_CACHE_EXT            0xEA
#define ATA_READ_DMA_EXT               0x25
#define ATA_READ_DMA                   0xC8
#define ATA_READ_SECTORS_EXT           0x24
#define ATA_READ_SECTORS               0x20
#define ATA_WRITE_DMA_EXT              0x35
#define ATA_WRITE_DMA                  0xCA
#define ATA_WRITE_SECTORS_EXT          0x34
#define ATA_WRITE_SECTORS              0x30
#define ATA_WRITE_UNCORRECTABLE        0x45
#define ATA_READ_VERIFY_SECTORS        0x40
#define ATA_READ_VERIFY_SECTORS_EXT    0x42
#define ATA_READ_BUFFER                0xE4
#define ATA_WRITE_BUFFER               0xE8
#define ATA_EXECUTE_DEVICE_DIAG        0x90
#define ATA_SET_FEATURES               0xEF
#define ATA_SMART                      0xB0
#define ATA_PACKET_IDENTIFY            0xA1
#define ATA_PACKET                     0xA0
#define ATA_READ_FPDMA                 0x60
#define ATA_WRITE_FPDMA                0x61
#define ATA_READ_LOG_EXT               0x2F
#define ATA_NOP                        0x00
#define ATA_DEVICE_RESET               0x08
#define ATA_MEDIA_EJECT                0xED
#define ATA_SECURITY_UNLOCK            0xF2
#define ATA_SECURITY_FREEZE_LOCK       0xF5
#define ATA_DATA_SET_MANAGEMENT        0x06
#define ATA_DOWNLOAD_MICROCODE         0x92
#define ATA_WRITE_STREAM_DMA_EXT       0x3A
#define ATA_READ_LOG_DMA_EXT           0x47
#define ATA_READ_STREAM_DMA_EXT        0x2A
#define ATA_WRITE_DMA_FUA              0x3D
#define ATA_WRITE_LOG_DMA_EXT          0x57
#define ATA_READ_DMA_QUEUED            0xC7
#define ATA_READ_DMA_QUEUED_EXT        0x26
#define ATA_WRITE_DMA_QUEUED           0xCC
#define ATA_WRITE_DMA_QUEUED_EXT       0x36
#define ATA_WRITE_DMA_QUEUED_FUA_EXT   0x3E
#define ATA_READ_MULTIPLE              0xC4
#define ATA_READ_MULTIPLE_EXT          0x29
#define ATA_WRITE_MULTIPLE             0xC5
#define ATA_WRITE_MULTIPLE_EXT         0x39
#define ATA_WRITE_MULTIPLE_FUA_EXT     0xCE

struct driveInfo {
    struct driveDiskLabel *diskLabel;
    struct ata_identify_data *ata_identify;
    uint32_t lba_high;
    uint32_t lba_low;
    uint32_t sector_size;
    char hdEnable;
    char hdDev;
    char hdFlags;
    char hdShift;
    long hdMask;
    uint32_t hdMulti;
    long hdPort;
    long hdSize;
    long hdCalc;
    long parOffset;
    int part;
    long lba_start;
    long lba_end;
};

int initHardDisk();
int hdWrite(struct driveInfo *hdd, void *, uInt32, uInt32);
int hdRead(struct driveInfo *hdd, void *, uInt32, uInt32);
int hdReset();
int hdIoctl();
int hdStart();
int hdStop();
int hdStandby();
int hdInit(struct device_node *dev);

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_type; /* partition type */
    unsigned char dp_ehd; /* end head */
    unsigned char dp_esect; /* end sector */
    unsigned char dp_ecyl; /* end cylinder */
    uInt32 dp_start; /* absolute starting sector number */
    uInt32 dp_size; /* partition size in sectors */
};

#define MAXPARTITIONS   8

struct bsd_disklabel {
    uint32_t d_magic; /* the magic number */
    u_int16_t d_type; /* drive type */
    u_int16_t d_subtype; /* controller/d_type specific */
    char d_typename[16]; /* type name, e.g. "eagle" */

    char d_packname[16]; /* pack identifier */

    /* disk geometry: */
    uint32_t d_secsize; /* # of bytes per sector */
    uint32_t d_nsectors; /* # of data sectors per track */
    uint32_t d_ntracks; /* # of tracks per cylinder */
    uint32_t d_ncylinders; /* # of data cylinders per unit */
    uint32_t d_secpercyl; /* # of data sectors per cylinder */
    uint32_t d_secperunit; /* # of data sectors per unit */

    /*
     * Spares (bad sector replacements) below are not counted in
     * d_nsectors or d_secpercyl.  Spare sectors are assumed to
     * be physical sectors which occupy space at the end of each
     * track and/or cylinder.
     */
    u_int16_t d_sparespertrack; /* # of spare sectors per track */
    u_int16_t d_sparespercyl; /* # of spare sectors per cylinder */
    /*
     * Alternate cylinders include maintenance, replacement, configuration
     * description areas, etc.
     */
    uint32_t d_acylinders; /* # of alt. cylinders per unit */

    /* hardware characteristics: */
    /*
     * d_interleave, d_trackskew and d_cylskew describe perturbations
     * in the media format used to compensate for a slow controller.
     * Interleave is physical sector interleave, set up by the
     * formatter or controller when formatting.  When interleaving is
     * in use, logically adjacent sectors are not physically
     * contiguous, but instead are separated by some number of
     * sectors.  It is specified as the ratio of physical sectors
     * traversed per logical sector.  Thus an interleave of 1:1
     * implies contiguous layout, while 2:1 implies that logical
     * sector 0 is separated by one sector from logical sector 1.
     * d_trackskew is the offset of sector 0 on track N relative to
     * sector 0 on track N-1 on the same cylinder.  Finally, d_cylskew
     * is the offset of sector 0 on cylinder N relative to sector 0
     * on cylinder N-1.
     */
    u_int16_t d_rpm; /* rotational speed */
    u_int16_t d_interleave; /* hardware sector interleave */
    u_int16_t d_trackskew; /* sector 0 skew, per track */
    u_int16_t d_cylskew; /* sector 0 skew, per cylinder */
    uint32_t d_headswitch; /* head switch time, usec */
    uint32_t d_trkseek; /* track-to-track seek, usec */
    uint32_t d_flags; /* generic flags */
#define NDDATA 5
    uint32_t d_drivedata[NDDATA]; /* drive-type specific information */
#define NSPARE 5
    uint32_t d_spare[NSPARE]; /* reserved for future use */
    uint32_t d_magic2; /* the magic number (again) */
    u_int16_t d_checksum; /* xor of data incl. partitions */

    /* filesystem and partition information: */
    u_int16_t d_npartitions; /* number of partitions in following */
    uint32_t d_bbsize; /* size of boot area at sn0, bytes */
    uint32_t d_sbsize; /* max size of fs superblock, bytes */
    struct partition { /* the partition table */
        uint32_t p_size; /* number of sectors in partition */
        uint32_t p_offset; /* starting sector */
        uint32_t p_fsize; /* filesystem basic fragment size */
        u_int8_t p_fstype; /* filesystem type, see below */
        u_int8_t p_frag; /* filesystem fragments per block */
        u_int16_t p_cpg; /* filesystem cylinders per group */
    } d_partitions[MAXPARTITIONS]; /* actually may be more */
};

static const char *fstypenames[] = { "unused", "swap", "Version 6", "Version 7", "System V", "4.1BSD", "Eighth Edition", "4.2BSD", "MSDOS", "4.4LFS", "unknown", "HPFS", "ISO9660", "boot", "vinum", "raid", "?", "?", "?", "?", "jfs", NULL };

/**
 * @name ATA_IDENTIFY_DEVICE_FIELD_LENGTHS
 *
 * The following constants define the number of bytes contained in various
 * fields found in the IDENTIFY DEVICE data structure.
 */
#define ATA_IDENTIFY_SERIAL_NUMBER_LEN        20
#define ATA_IDENTIFY_MODEL_NUMBER_LEN         40
#define ATA_IDENTIFY_FW_REVISION_LEN          8
#define ATA_IDENTIFY_48_LBA_LEN               8
#define ATA_IDENTIFY_MEDIA_SERIAL_NUMBER_LEN  30
#define ATA_IDENTIFY_WWN_LEN                  8

struct ata_identify_data {
    u_int16_t general_config_bits;                             // word  00
    u_int16_t obsolete0;                                       // word  01 (num cylinders)
    u_int16_t vendor_specific_config_bits;                     // word  02
    u_int16_t obsolete1;                                       // word  03 (num heads)
    u_int16_t retired1[2];                                     // words 04-05
    u_int16_t obsolete2;                                       // word  06 (sectors / track)
    u_int16_t reserved_for_compact_flash1[2];                  // words 07-08
    u_int16_t retired0;                                        // word  09
    u_int8_t serial_number[ATA_IDENTIFY_SERIAL_NUMBER_LEN];   // word 10-19
    u_int16_t retired2[2];                                     // words 20-21
    u_int16_t obsolete4;                                       // word  22
    u_int8_t firmware_revision[ATA_IDENTIFY_FW_REVISION_LEN]; // words 23-26
    u_int8_t model_number[ATA_IDENTIFY_MODEL_NUMBER_LEN];     // words 27-46
    u_int16_t max_sectors_per_multiple;                        // word  47
    u_int16_t reserved0;                                       // word  48
    u_int16_t capabilities1;                                   // word  49
    u_int16_t capabilities2;                                   // word  50
    u_int16_t obsolete5[2];                                    // words 51-52
    u_int16_t validity_bits;                                   // word  53
    u_int16_t obsolete6[5];                                    // words 54-58 Used to be:
    // current cylinders,
    // current heads,
    // current sectors/Track,
    // current capacity
    u_int16_t current_max_sectors_per_multiple;                // word  59
    u_int8_t total_num_sectors[4];                            // words 60-61
    u_int16_t obsolete7;                                       // word  62
    u_int16_t multi_word_dma_mode;                             // word  63
    u_int16_t pio_modes_supported;                             // word  64
    u_int16_t min_multiword_dma_transfer_cycle;                // word  65
    u_int16_t rec_min_multiword_dma_transfer_cycle;            // word  66
    u_int16_t min_pio_transfer_no_flow_ctrl;                   // word  67
    u_int16_t min_pio_transfer_with_flow_ctrl;                 // word  68
    u_int16_t additional_supported;                            // word  69
    u_int16_t reserved1;                                       // word  70
    u_int16_t reserved2[4];                                    // words 71-74
    u_int16_t queue_depth;                                     // word  75
    u_int16_t serial_ata_capabilities;                         // word  76
    u_int16_t serial_ata_reserved;                             // word  77
    u_int16_t serial_ata_features_supported;                   // word  78
    u_int16_t serial_ata_features_enabled;                     // word  79
    u_int16_t major_version_number;                            // word  80
    u_int16_t minor_version_number;                            // word  81
    u_int16_t command_set_supported0;                          // word  82
    u_int16_t command_set_supported1;                          // word  83
    u_int16_t command_set_supported_extention;                 // word  84
    u_int16_t command_set_enabled0;                            // word  85
    u_int16_t command_set_enabled1;                            // word  86
    u_int16_t command_set_default;                             // word  87
    u_int16_t ultra_dma_mode;                                  // word  88
    u_int16_t security_erase_completion_time;                  // word  89
    u_int16_t enhanced_security_erase_time;                    // word  90
    u_int16_t current_power_mgmt_value;                        // word  91
    u_int16_t master_password_revision;                        // word  92
    u_int16_t hardware_reset_result;                           // word  93
    u_int16_t current_acoustic_management_value;               // word  94
    u_int16_t stream_min_request_size;                         // word  95
    u_int16_t stream_transfer_time;                            // word  96
    u_int16_t stream_access_latency;                           // word  97
    u_int16_t stream_performance_granularity[2];               // words 98-99
    u_int8_t max_48bit_lba[ATA_IDENTIFY_48_LBA_LEN];          // words 100-103
    u_int16_t streaming_transfer_time;                         // word  104
    u_int16_t max_lba_range_entry_blocks;                      // word  105
    u_int16_t physical_logical_sector_info;                    // word  106
    u_int16_t acoustic_test_interseek_delay;                   // word  107
    u_int8_t world_wide_name[ATA_IDENTIFY_WWN_LEN];           // words 108-111
    u_int8_t reserved_for_wwn_extention[ATA_IDENTIFY_WWN_LEN];           // words 112-115
    u_int16_t reserved4;                                       // word  116
    u_int8_t words_per_logical_sector[4];                     // words 117-118
    u_int16_t command_set_supported2;                          // word  119
    u_int16_t reserved5[7];                                    // words 120-126
    u_int16_t removable_media_status;                          // word  127
    u_int16_t security_status;                                 // word  128
    u_int16_t vendor_specific1[31];                            // words 129-159
    u_int16_t cfa_power_mode1;                                 // word  160
    u_int16_t reserved_for_compact_flash2[7];                  // words 161-167
    u_int16_t device_nominal_form_factor;                      // word  168
    u_int16_t data_set_management;                             // word  169
    u_int16_t reserved_for_compact_flash3[6];                  // words 170-175
    u_int16_t current_media_serial_number[ATA_IDENTIFY_MEDIA_SERIAL_NUMBER_LEN];                  //words 176-205
    u_int16_t reserved6[3];                                    // words 206-208
    u_int16_t logical_sector_alignment;                        // words 209
    u_int16_t reserved7[7];                                    // words 210-216
    u_int16_t nominal_media_rotation_rate;                     // word  217
    u_int16_t reserved8[16];                                   // words 218-233
    u_int16_t min_num_blocks_per_microcode;                    // word  234
    u_int16_t max_num_blocks_per_microcode;                    // word  235
    u_int16_t reserved9[19];                                   // words 236-254
    u_int16_t integrity_word;                                  // word  255
};

/*
 * A list of partition types, probably outdated.
 */
static const char * const part_types[256] = {
  [0x00] = "unused",
  [0x01] = "Primary DOS with 12 bit FAT",
  [0x02] = "XENIX / file system",
  [0x03] = "XENIX /usr file system",
  [0x04] = "Primary DOS with 16 bit FAT (< 32MB)",
  [0x05] = "Extended DOS",
  [0x06] = "Primary DOS, 16 bit FAT (>= 32MB)",
  [0x07] = "NTFS, OS/2 HPFS, QNX-2 (16 bit) or Advanced UNIX",
  [0x08] = "AIX file system or SplitDrive",
  [0x09] = "AIX boot partition or Coherent",
  [0x0A] = "OS/2 Boot Manager, OPUS or Coherent swap",
  [0x0B] = "DOS or Windows 95 with 32 bit FAT",
  [0x0C] = "DOS or Windows 95 with 32 bit FAT (LBA)",
  [0x0E] = "Primary 'big' DOS (>= 32MB, LBA)",
  [0x0F] = "Extended DOS (LBA)",
  [0x10] = "OPUS",
  [0x11] = "OS/2 BM: hidden DOS with 12-bit FAT",
  [0x12] = "Compaq diagnostics",
  [0x14] = "OS/2 BM: hidden DOS with 16-bit FAT (< 32MB)",
  [0x16] = "OS/2 BM: hidden DOS with 16-bit FAT (>= 32MB)",
  [0x17] = "OS/2 BM: hidden IFS (e.g. HPFS)",
  [0x18] = "AST Windows swapfile",
  [0x1b] = "ASUS Recovery partition (NTFS)",
  [0x24] = "NEC DOS",
  [0x3C] = "PartitionMagic recovery",
  [0x39] = "plan9",
  [0x40] = "VENIX 286",
  [0x41] = "Linux/MINIX (sharing disk with DRDOS)",
  [0x42] = "SFS or Linux swap (sharing disk with DRDOS)",
  [0x43] = "Linux native (sharing disk with DRDOS)",
  [0x4D] = "QNX 4.2 Primary",
  [0x4E] = "QNX 4.2 Secondary",
  [0x4F] = "QNX 4.2 Tertiary",
  [0x50] = "DM (disk manager)",
  [0x51] = "DM6 Aux1 (or Novell)",
  [0x52] = "CP/M or Microport SysV/AT",
  [0x53] = "DM6 Aux3",
  [0x54] = "DM6",
  [0x55] = "EZ-Drive (disk manager)",
  [0x56] = "Golden Bow (disk manager)",
  [0x5c] = "Priam Edisk (disk manager)", /* according to S. Widlake */
  [0x61] = "SpeedStor",
  [0x63] = "System V/386 (such as ISC UNIX), GNU HURD or Mach",
  [0x64] = "Novell Netware/286 2.xx",
  [0x65] = "Novell Netware/386 3.xx",
  [0x70] = "DiskSecure Multi-Boot",
  [0x75] = "PCIX",
  [0x77] = "QNX4.x",
  [0x78] = "QNX4.x 2nd part",
  [0x79] = "QNX4.x 3rd part",
  [0x80] = "Minix until 1.4a",
  [0x81] = "Minix since 1.4b, early Linux partition or Mitac disk manager",
  [0x82] = "Linux swap or Solaris x86",
  [0x83] = "Linux native",
  [0x84] = "OS/2 hidden C: drive",
  [0x85] = "Linux extended",
  [0x86] = "NTFS volume set??",
  [0x87] = "NTFS volume set??",
  [0x93] = "Amoeba file system",
  [0x94] = "Amoeba bad block table",
  [0x9F] = "BSD/OS",
  [0xA0] = "Suspend to Disk",
  [0xA5] = "FreeBSD/NetBSD/386BSD",
  [0xA6] = "OpenBSD",
  [0xA7] = "NeXTSTEP",
  [0xA9] = "NetBSD",
  [0xAC] = "IBM JFS",
  [0xAF] = "HFS+",
  [0xB7] = "BSDI BSD/386 file system",
  [0xB8] = "BSDI BSD/386 swap",
  [0xBE] = "Solaris x86 boot",
  [0xBF] = "Solaris x86 (new)",
  [0xC1] = "DRDOS/sec with 12-bit FAT",
  [0xC4] = "DRDOS/sec with 16-bit FAT (< 32MB)",
  [0xC6] = "DRDOS/sec with 16-bit FAT (>= 32MB)",
  [0xC7] = "Syrinx",
  [0xDB] = "CP/M, Concurrent CP/M, Concurrent DOS or CTOS",
  [0xDE] = "DELL Utilities - FAT filesystem",
  [0xE1] = "DOS access or SpeedStor with 12-bit FAT extended partition",
  [0xE3] = "DOS R/O or SpeedStor",
  [0xE4] = "SpeedStor with 16-bit FAT extended partition < 1024 cyl.",
  [0xEB] = "BeOS file system",
  [0xEE] = "EFI GPT",
  [0xEF] = "EFI System Partition",
  [0xF1] = "SpeedStor",
  [0xF2] = "DOS 3.3+ Secondary",
  [0xF4] = "SpeedStor large partition",
  [0xFB] = "VMware VMFS",
  [0xFE] = "SpeedStor >1024 cyl. or LANstep",
  [0xFF] = "Xenix bad blocks table", };

#endif
