/*-
* 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