1433d6423SLionel Sambuc #include <minix/drivers.h> 2433d6423SLionel Sambuc #include <minix/blockdriver.h> 3433d6423SLionel Sambuc #include <minix/drvlib.h> 4433d6423SLionel Sambuc 5433d6423SLionel Sambuc #define VERBOSE 0 /* display identify messages during boot */ 6433d6423SLionel Sambuc #define VERBOSE_DMA 0 /* display DMA debugging information */ 7433d6423SLionel Sambuc 8433d6423SLionel Sambuc #define ATAPI_DEBUG 0 /* To debug ATAPI code. */ 9433d6423SLionel Sambuc 10433d6423SLionel Sambuc /* I/O Ports used by winchester disk controllers. */ 11433d6423SLionel Sambuc 12433d6423SLionel Sambuc /* Read and write registers */ 13433d6423SLionel Sambuc #define REG_CMD_BASE0 0x1F0 /* command base register of controller 0 */ 14433d6423SLionel Sambuc #define REG_CMD_BASE1 0x170 /* command base register of controller 1 */ 15433d6423SLionel Sambuc #define REG_CTL_BASE0 0x3F6 /* control base register of controller 0 */ 16433d6423SLionel Sambuc #define REG_CTL_BASE1 0x376 /* control base register of controller 1 */ 17433d6423SLionel Sambuc 18433d6423SLionel Sambuc #define PCI_CTL_OFF 2 /* Offset of control registers from BAR2 */ 19433d6423SLionel Sambuc #define PCI_DMA_2ND_OFF 8 /* Offset of DMA registers from BAR4 for 20433d6423SLionel Sambuc * secondary channel 21433d6423SLionel Sambuc */ 22433d6423SLionel Sambuc 23433d6423SLionel Sambuc #define REG_DATA 0 /* data register (offset from the base reg.) */ 24433d6423SLionel Sambuc #define REG_PRECOMP 1 /* start of write precompensation */ 25433d6423SLionel Sambuc #define REG_COUNT 2 /* sectors to transfer */ 26433d6423SLionel Sambuc #define REG_SECTOR 3 /* sector number */ 27433d6423SLionel Sambuc #define REG_CYL_LO 4 /* low byte of cylinder number */ 28433d6423SLionel Sambuc #define REG_CYL_HI 5 /* high byte of cylinder number */ 29433d6423SLionel Sambuc #define REG_LDH 6 /* lba, drive and head */ 30433d6423SLionel Sambuc #define LDH_DEFAULT 0xA0 /* ECC enable, 512 bytes per sector */ 31433d6423SLionel Sambuc #define LDH_LBA 0x40 /* Use LBA addressing */ 32433d6423SLionel Sambuc #define LDH_DEV 0x10 /* Drive 1 iff set */ 33433d6423SLionel Sambuc #define ldh_init(drive) (LDH_DEFAULT | ((drive) << 4)) 34433d6423SLionel Sambuc 35433d6423SLionel Sambuc /* Read only registers */ 36433d6423SLionel Sambuc #define REG_STATUS 7 /* status */ 37433d6423SLionel Sambuc #define STATUS_BSY 0x80 /* controller busy */ 38433d6423SLionel Sambuc #define STATUS_RDY 0x40 /* drive ready */ 39433d6423SLionel Sambuc #define STATUS_WF 0x20 /* write fault */ 40433d6423SLionel Sambuc #define STATUS_SC 0x10 /* seek complete (obsolete) */ 41433d6423SLionel Sambuc #define STATUS_DRQ 0x08 /* data transfer request */ 42433d6423SLionel Sambuc #define STATUS_CRD 0x04 /* corrected data */ 43433d6423SLionel Sambuc #define STATUS_IDX 0x02 /* index pulse */ 44433d6423SLionel Sambuc #define STATUS_ERR 0x01 /* error */ 45433d6423SLionel Sambuc #define STATUS_ADMBSY 0x100 /* administratively busy (software) */ 46433d6423SLionel Sambuc #define REG_ERROR 1 /* error code */ 47433d6423SLionel Sambuc #define ERROR_BB 0x80 /* bad block */ 48433d6423SLionel Sambuc #define ERROR_ECC 0x40 /* bad ecc bytes */ 49433d6423SLionel Sambuc #define ERROR_ID 0x10 /* id not found */ 50433d6423SLionel Sambuc #define ERROR_AC 0x04 /* aborted command */ 51433d6423SLionel Sambuc #define ERROR_TK 0x02 /* track zero error */ 52433d6423SLionel Sambuc #define ERROR_DM 0x01 /* no data address mark */ 53433d6423SLionel Sambuc 54433d6423SLionel Sambuc /* Write only registers */ 55433d6423SLionel Sambuc #define REG_COMMAND 7 /* command */ 56433d6423SLionel Sambuc #define CMD_IDLE 0x00 /* for w_command: drive idle */ 57433d6423SLionel Sambuc #define CMD_RECALIBRATE 0x10 /* recalibrate drive */ 58433d6423SLionel Sambuc #define CMD_READ 0x20 /* read data */ 59433d6423SLionel Sambuc #define CMD_READ_EXT 0x24 /* read data (LBA48 addressed) */ 60433d6423SLionel Sambuc #define CMD_READ_DMA_EXT 0x25 /* read data using DMA (w/ LBA48) */ 61433d6423SLionel Sambuc #define CMD_WRITE 0x30 /* write data */ 62433d6423SLionel Sambuc #define CMD_WRITE_EXT 0x34 /* write data (LBA48 addressed) */ 63433d6423SLionel Sambuc #define CMD_WRITE_DMA_EXT 0x35 /* write data using DMA (w/ LBA48) */ 64433d6423SLionel Sambuc #define CMD_READVERIFY 0x40 /* read verify */ 65433d6423SLionel Sambuc #define CMD_FORMAT 0x50 /* format track */ 66433d6423SLionel Sambuc #define CMD_SEEK 0x70 /* seek cylinder */ 67433d6423SLionel Sambuc #define CMD_DIAG 0x90 /* execute device diagnostics */ 68433d6423SLionel Sambuc #define CMD_SPECIFY 0x91 /* specify parameters */ 69433d6423SLionel Sambuc #define CMD_READ_DMA 0xC8 /* read data using DMA */ 70433d6423SLionel Sambuc #define CMD_WRITE_DMA 0xCA /* write data using DMA */ 71433d6423SLionel Sambuc #define CMD_FLUSH_CACHE 0xE7 /* flush the write cache */ 72433d6423SLionel Sambuc #define ATA_IDENTIFY 0xEC /* identify drive */ 73433d6423SLionel Sambuc /* #define REG_CTL 0x206 */ /* control register */ 74433d6423SLionel Sambuc #define REG_CTL 0 /* control register */ 75433d6423SLionel Sambuc #define CTL_NORETRY 0x80 /* disable access retry */ 76433d6423SLionel Sambuc #define CTL_NOECC 0x40 /* disable ecc retry */ 77433d6423SLionel Sambuc #define CTL_EIGHTHEADS 0x08 /* more than eight heads */ 78433d6423SLionel Sambuc #define CTL_RESET 0x04 /* reset controller */ 79433d6423SLionel Sambuc #define CTL_INTDISABLE 0x02 /* disable interrupts */ 80433d6423SLionel Sambuc #define REG_CTL_ALTSTAT 0 /* alternate status register */ 81433d6423SLionel Sambuc 82433d6423SLionel Sambuc /* Identify words */ 83433d6423SLionel Sambuc #define ID_GENERAL 0x00 /* General configuration information */ 84433d6423SLionel Sambuc #define ID_GEN_NOT_ATA 0x8000 /* Not an ATA device */ 85433d6423SLionel Sambuc #define ID_CAPABILITIES 0x31 /* Capabilities (49)*/ 86433d6423SLionel Sambuc #define ID_CAP_LBA 0x0200 /* LBA supported */ 87433d6423SLionel Sambuc #define ID_CAP_DMA 0x0100 /* DMA supported */ 88433d6423SLionel Sambuc #define ID_FIELD_VALIDITY 0x35 /* Field Validity (53) */ 89433d6423SLionel Sambuc #define ID_FV_88 0x04 /* Word 88 is valid (UDMA) */ 90433d6423SLionel Sambuc #define ID_MULTIWORD_DMA 0x3f /* Multiword DMA (63) */ 91433d6423SLionel Sambuc #define ID_MWDMA_2_SEL 0x0400 /* Mode 2 is selected */ 92433d6423SLionel Sambuc #define ID_MWDMA_1_SEL 0x0200 /* Mode 1 is selected */ 93433d6423SLionel Sambuc #define ID_MWDMA_0_SEL 0x0100 /* Mode 0 is selected */ 94433d6423SLionel Sambuc #define ID_MWDMA_2_SUP 0x0004 /* Mode 2 is supported */ 95433d6423SLionel Sambuc #define ID_MWDMA_1_SUP 0x0002 /* Mode 1 is supported */ 96433d6423SLionel Sambuc #define ID_MWDMA_0_SUP 0x0001 /* Mode 0 is supported */ 97433d6423SLionel Sambuc #define ID_CSS 0x53 /* Command Sets Supported (83) */ 98433d6423SLionel Sambuc #define ID_CSS_LBA48 0x0400 99433d6423SLionel Sambuc #define ID_ULTRA_DMA 0x58 /* Ultra DMA (88) */ 100433d6423SLionel Sambuc #define ID_UDMA_5_SEL 0x2000 /* Mode 5 is selected */ 101433d6423SLionel Sambuc #define ID_UDMA_4_SEL 0x1000 /* Mode 4 is selected */ 102433d6423SLionel Sambuc #define ID_UDMA_3_SEL 0x0800 /* Mode 3 is selected */ 103433d6423SLionel Sambuc #define ID_UDMA_2_SEL 0x0400 /* Mode 2 is selected */ 104433d6423SLionel Sambuc #define ID_UDMA_1_SEL 0x0200 /* Mode 1 is selected */ 105433d6423SLionel Sambuc #define ID_UDMA_0_SEL 0x0100 /* Mode 0 is selected */ 106433d6423SLionel Sambuc #define ID_UDMA_5_SUP 0x0020 /* Mode 5 is supported */ 107433d6423SLionel Sambuc #define ID_UDMA_4_SUP 0x0010 /* Mode 4 is supported */ 108433d6423SLionel Sambuc #define ID_UDMA_3_SUP 0x0008 /* Mode 3 is supported */ 109433d6423SLionel Sambuc #define ID_UDMA_2_SUP 0x0004 /* Mode 2 is supported */ 110433d6423SLionel Sambuc #define ID_UDMA_1_SUP 0x0002 /* Mode 1 is supported */ 111433d6423SLionel Sambuc #define ID_UDMA_0_SUP 0x0001 /* Mode 0 is supported */ 112433d6423SLionel Sambuc 113433d6423SLionel Sambuc /* DMA registers */ 114433d6423SLionel Sambuc #define DMA_COMMAND 0 /* Command register */ 115433d6423SLionel Sambuc #define DMA_CMD_WRITE 0x08 /* PCI bus master writes */ 116433d6423SLionel Sambuc #define DMA_CMD_START 0x01 /* Start Bus Master */ 117433d6423SLionel Sambuc #define DMA_STATUS 2 /* Status register */ 118433d6423SLionel Sambuc #define DMA_ST_D1_DMACAP 0x40 /* Drive 1 is DMA capable */ 119433d6423SLionel Sambuc #define DMA_ST_D0_DMACAP 0x20 /* Drive 0 is DMA capable */ 120433d6423SLionel Sambuc #define DMA_ST_INT 0x04 /* Interrupt */ 121433d6423SLionel Sambuc #define DMA_ST_ERROR 0x02 /* Error */ 122433d6423SLionel Sambuc #define DMA_ST_BM_ACTIVE 0x01 /* Bus Master IDE Active */ 123433d6423SLionel Sambuc #define DMA_PRDTP 4 /* PRD Table Pointer */ 124433d6423SLionel Sambuc 125433d6423SLionel Sambuc /* Check for the presence of LBA48 only on drives that are 'big'. */ 126433d6423SLionel Sambuc #define LBA48_CHECK_SIZE 0x0f000000 127433d6423SLionel Sambuc #define LBA_MAX_SIZE 0x0fffffff /* Highest sector size for 128433d6423SLionel Sambuc * regular LBA. 129433d6423SLionel Sambuc */ 130433d6423SLionel Sambuc 131433d6423SLionel Sambuc #define ERROR_SENSE 0xF0 /* sense key mask */ 132433d6423SLionel Sambuc #define SENSE_NONE 0x00 /* no sense key */ 133433d6423SLionel Sambuc #define SENSE_RECERR 0x10 /* recovered error */ 134433d6423SLionel Sambuc #define SENSE_NOTRDY 0x20 /* not ready */ 135433d6423SLionel Sambuc #define SENSE_MEDERR 0x30 /* medium error */ 136433d6423SLionel Sambuc #define SENSE_HRDERR 0x40 /* hardware error */ 137433d6423SLionel Sambuc #define SENSE_ILRQST 0x50 /* illegal request */ 138433d6423SLionel Sambuc #define SENSE_UATTN 0x60 /* unit attention */ 139433d6423SLionel Sambuc #define SENSE_DPROT 0x70 /* data protect */ 140433d6423SLionel Sambuc #define SENSE_ABRT 0xb0 /* aborted command */ 141433d6423SLionel Sambuc #define SENSE_MISCOM 0xe0 /* miscompare */ 142433d6423SLionel Sambuc #define ERROR_MCR 0x08 /* media change requested */ 143433d6423SLionel Sambuc #define ERROR_ABRT 0x04 /* aborted command */ 144433d6423SLionel Sambuc #define ERROR_EOM 0x02 /* end of media detected */ 145433d6423SLionel Sambuc #define ERROR_ILI 0x01 /* illegal length indication */ 146433d6423SLionel Sambuc #define REG_FEAT 1 /* features */ 147433d6423SLionel Sambuc #define FEAT_OVERLAP 0x02 /* overlap */ 148433d6423SLionel Sambuc #define FEAT_DMA 0x01 /* dma */ 149433d6423SLionel Sambuc #define REG_IRR 2 /* interrupt reason register */ 150433d6423SLionel Sambuc #define IRR_REL 0x04 /* release */ 151433d6423SLionel Sambuc #define IRR_IO 0x02 /* direction for xfer */ 152433d6423SLionel Sambuc #define IRR_COD 0x01 /* command or data */ 153433d6423SLionel Sambuc #define REG_SAMTAG 3 154433d6423SLionel Sambuc #define REG_CNT_LO 4 /* low byte of cylinder number */ 155433d6423SLionel Sambuc #define REG_CNT_HI 5 /* high byte of cylinder number */ 156433d6423SLionel Sambuc #define REG_DRIVE 6 /* drive select */ 157433d6423SLionel Sambuc 158433d6423SLionel Sambuc #define REG_STATUS 7 /* status */ 159433d6423SLionel Sambuc #define STATUS_BSY 0x80 /* controller busy */ 160433d6423SLionel Sambuc #define STATUS_DRDY 0x40 /* drive ready */ 161433d6423SLionel Sambuc #define STATUS_DMADF 0x20 /* dma ready/drive fault */ 162433d6423SLionel Sambuc #define STATUS_SRVCDSC 0x10 /* service or dsc */ 163433d6423SLionel Sambuc #define STATUS_DRQ 0x08 /* data transfer request */ 164433d6423SLionel Sambuc #define STATUS_CORR 0x04 /* correctable error occurred */ 165433d6423SLionel Sambuc #define STATUS_CHECK 0x01 /* check error */ 166433d6423SLionel Sambuc 167433d6423SLionel Sambuc #define ATAPI_PACKETCMD 0xA0 /* packet command */ 168433d6423SLionel Sambuc #define ATAPI_IDENTIFY 0xA1 /* identify drive */ 169433d6423SLionel Sambuc #define SCSI_READ10 0x28 /* read from disk */ 170433d6423SLionel Sambuc #define SCSI_SENSE 0x03 /* sense request */ 171433d6423SLionel Sambuc 172433d6423SLionel Sambuc #define ATAPI_PACKETSIZE 12 173433d6423SLionel Sambuc #define SENSE_PACKETSIZE 18 174433d6423SLionel Sambuc 175433d6423SLionel Sambuc /* Error codes */ 176433d6423SLionel Sambuc #define ERR (-1) /* general error */ 177433d6423SLionel Sambuc #define ERR_BAD_SECTOR (-2) /* block marked bad detected */ 178433d6423SLionel Sambuc 179433d6423SLionel Sambuc /* Some controllers don't interrupt, the clock will wake us up. */ 180433d6423SLionel Sambuc #define WAKEUP_SECS 32 /* drive may be out for 31 seconds max */ 181433d6423SLionel Sambuc #define WAKEUP_TICKS (WAKEUP_SECS*system_hz) 182433d6423SLionel Sambuc 183433d6423SLionel Sambuc /* Miscellaneous. */ 184433d6423SLionel Sambuc #define MAX_DRIVES 4 /* max number of actual drives per instance */ 185433d6423SLionel Sambuc #define MAX_DRIVENODES 8 /* number of drive nodes, for node numbering */ 186433d6423SLionel Sambuc #define MAX_SECS 256 /* controller can transfer this many sectors */ 187433d6423SLionel Sambuc #define MAX_ERRORS 4 /* how often to try rd/wt before quitting */ 188433d6423SLionel Sambuc #define NR_MINORS (MAX_DRIVENODES * DEV_PER_DRIVE) 189433d6423SLionel Sambuc #define NR_SUBDEVS (MAX_DRIVENODES * SUB_PER_DRIVE) 190433d6423SLionel Sambuc #define DELAY_USECS 1000 /* controller timeout in microseconds */ 191433d6423SLionel Sambuc #define DELAY_TICKS 1 /* controller timeout in ticks */ 192433d6423SLionel Sambuc #define DEF_TIMEOUT_USECS 5000000L /* controller timeout in microseconds */ 193433d6423SLionel Sambuc #define RECOVERY_USECS 500000 /* controller recovery time in microseconds */ 194433d6423SLionel Sambuc #define RECOVERY_TICKS 30 /* controller recovery time in ticks */ 195433d6423SLionel Sambuc #define INITIALIZED 0x01 /* drive is initialized */ 196433d6423SLionel Sambuc #define DEAF 0x02 /* controller must be reset */ 197433d6423SLionel Sambuc #define SMART 0x04 /* drive supports ATA commands */ 198433d6423SLionel Sambuc #define ATAPI 0x08 /* it is an ATAPI device */ 199433d6423SLionel Sambuc #define IDENTIFIED 0x10 /* w_identify done successfully */ 200433d6423SLionel Sambuc #define IGNORING 0x20 /* w_identify failed once */ 201433d6423SLionel Sambuc 202433d6423SLionel Sambuc #define NO_DMA_VAR "ata_no_dma" 203433d6423SLionel Sambuc 204433d6423SLionel Sambuc #define ATA_IF_NATIVE0 (1L << 0) /* first channel is in native mode */ 205433d6423SLionel Sambuc #define ATA_IF_NATIVE1 (1L << 2) /* second channel is in native mode */ 206433d6423SLionel Sambuc 207433d6423SLionel Sambuc extern int sef_cb_lu_prepare(int state); 208*e1f889d2SCristiano Giuffrida extern int sef_cb_lu_state_isvalid(int state, int flags); 209433d6423SLionel Sambuc extern void sef_cb_lu_state_dump(int state); 210