2010-03-22 22:25:22 +01:00
|
|
|
#include <minix/drivers.h>
|
|
|
|
#include <minix/driver.h>
|
|
|
|
#include <minix/drvlib.h>
|
2005-04-21 16:53:53 +02:00
|
|
|
|
2005-09-11 19:09:11 +02:00
|
|
|
#define VERBOSE 0 /* display identify messages during boot */
|
|
|
|
#define ENABLE_ATAPI 1 /* add ATAPI cd-rom support to driver */
|
Basic System Event Framework (SEF) with ping and live update.
SYSLIB CHANGES:
- SEF must be used by every system process and is thereby part of the system
library.
- The framework provides a receive() interface (sef_receive) for system
processes to automatically catch known system even messages and process them.
- SEF provides a default behavior for each type of system event, but allows
system processes to register callbacks to override the default behavior.
- Custom (local to the process) or predefined (provided by SEF) callback
implementations can be registered to SEF.
- SEF currently includes support for 2 types of system events:
1. SEF Ping. The event occurs every time RS sends a ping to figure out
whether a system process is still alive. The default callback implementation
provided by SEF is to notify RS back to let it know the process is alive
and kicking.
2. SEF Live update. The event occurs every time RS sends a prepare to update
message to let a system process know an update is available and to prepare
for it. The live update support is very basic for now. SEF only deals with
verifying if the prepare state can be supported by the process, dumping the
state for debugging purposes, and providing an event-driven programming
model to the process to react to state changes check-in when ready to update.
- SEF should be extended in the future to integrate support for more types of
system events. Ideally, all the cross-cutting concerns should be integrated into
SEF to avoid duplicating code and ease extensibility. Examples include:
* PM notify messages primarily used at shutdown.
* SYSTEM notify messages primarily used for signals.
* CLOCK notify messages used for system alarms.
* Debug messages. IS could still be in charge of fkey handling but would
forward the debug message to the target process (e.g. PM, if the user
requested debug information about PM). SEF would then catch the message and
do nothing unless the process has registered an appropriate callback to
deal with the event. This simplifies the programming model to print debug
information, avoids duplicating code, and reduces the effort to print
debug information.
SYSTEM PROCESSES CHANGES:
- Every system process registers SEF callbacks it needs to override the default
system behavior and calls sef_startup() right after being started.
- sef_startup() does almost nothing now, but will be extended in the future to
support callbacks of its own to let RS control and synchronize with every
system process at initialization time.
- Every system process calls sef_receive() now rather than receive() directly,
to let SEF handle predefined system events.
RS CHANGES:
- RS supports a basic single-component live update protocol now, as follows:
* When an update command is issued (via "service update *"), RS notifies the
target system process to prepare for a specific update state.
* If the process doesn't respond back in time, the update is aborted.
* When the process responds back, RS kills it and marks it for refreshing.
* The process is then automatically restarted as for a buggy process and can
start running again.
* Live update is currently prototyped as a controlled failure.
2009-12-21 15:12:21 +01:00
|
|
|
|
|
|
|
#define ATAPI_DEBUG 0 /* To debug ATAPI code. */
|
|
|
|
|
|
|
|
/* I/O Ports used by winchester disk controllers. */
|
|
|
|
|
|
|
|
/* Read and write registers */
|
|
|
|
#define REG_CMD_BASE0 0x1F0 /* command base register of controller 0 */
|
|
|
|
#define REG_CMD_BASE1 0x170 /* command base register of controller 1 */
|
|
|
|
#define REG_CTL_BASE0 0x3F6 /* control base register of controller 0 */
|
|
|
|
#define REG_CTL_BASE1 0x376 /* control base register of controller 1 */
|
|
|
|
|
|
|
|
#define PCI_CTL_OFF 2 /* Offset of control registers from BAR2 */
|
|
|
|
#define PCI_DMA_2ND_OFF 8 /* Offset of DMA registers from BAR4 for
|
|
|
|
* secondary channel
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define REG_DATA 0 /* data register (offset from the base reg.) */
|
|
|
|
#define REG_PRECOMP 1 /* start of write precompensation */
|
|
|
|
#define REG_COUNT 2 /* sectors to transfer */
|
|
|
|
#define REG_SECTOR 3 /* sector number */
|
|
|
|
#define REG_CYL_LO 4 /* low byte of cylinder number */
|
|
|
|
#define REG_CYL_HI 5 /* high byte of cylinder number */
|
|
|
|
#define REG_LDH 6 /* lba, drive and head */
|
|
|
|
#define LDH_DEFAULT 0xA0 /* ECC enable, 512 bytes per sector */
|
|
|
|
#define LDH_LBA 0x40 /* Use LBA addressing */
|
|
|
|
#define LDH_DEV 0x10 /* Drive 1 iff set */
|
|
|
|
#define ldh_init(drive) (LDH_DEFAULT | ((drive) << 4))
|
|
|
|
|
|
|
|
/* Read only registers */
|
|
|
|
#define REG_STATUS 7 /* status */
|
|
|
|
#define STATUS_BSY 0x80 /* controller busy */
|
|
|
|
#define STATUS_RDY 0x40 /* drive ready */
|
|
|
|
#define STATUS_WF 0x20 /* write fault */
|
|
|
|
#define STATUS_SC 0x10 /* seek complete (obsolete) */
|
|
|
|
#define STATUS_DRQ 0x08 /* data transfer request */
|
|
|
|
#define STATUS_CRD 0x04 /* corrected data */
|
|
|
|
#define STATUS_IDX 0x02 /* index pulse */
|
|
|
|
#define STATUS_ERR 0x01 /* error */
|
|
|
|
#define STATUS_ADMBSY 0x100 /* administratively busy (software) */
|
|
|
|
#define REG_ERROR 1 /* error code */
|
|
|
|
#define ERROR_BB 0x80 /* bad block */
|
|
|
|
#define ERROR_ECC 0x40 /* bad ecc bytes */
|
|
|
|
#define ERROR_ID 0x10 /* id not found */
|
|
|
|
#define ERROR_AC 0x04 /* aborted command */
|
|
|
|
#define ERROR_TK 0x02 /* track zero error */
|
|
|
|
#define ERROR_DM 0x01 /* no data address mark */
|
|
|
|
|
|
|
|
/* Write only registers */
|
|
|
|
#define REG_COMMAND 7 /* command */
|
|
|
|
#define CMD_IDLE 0x00 /* for w_command: drive idle */
|
|
|
|
#define CMD_RECALIBRATE 0x10 /* recalibrate drive */
|
|
|
|
#define CMD_READ 0x20 /* read data */
|
|
|
|
#define CMD_READ_EXT 0x24 /* read data (LBA48 addressed) */
|
|
|
|
#define CMD_READ_DMA_EXT 0x25 /* read data using DMA (w/ LBA48) */
|
|
|
|
#define CMD_WRITE 0x30 /* write data */
|
|
|
|
#define CMD_WRITE_EXT 0x34 /* write data (LBA48 addressed) */
|
|
|
|
#define CMD_WRITE_DMA_EXT 0x35 /* write data using DMA (w/ LBA48) */
|
|
|
|
#define CMD_READVERIFY 0x40 /* read verify */
|
|
|
|
#define CMD_FORMAT 0x50 /* format track */
|
|
|
|
#define CMD_SEEK 0x70 /* seek cylinder */
|
|
|
|
#define CMD_DIAG 0x90 /* execute device diagnostics */
|
|
|
|
#define CMD_SPECIFY 0x91 /* specify parameters */
|
|
|
|
#define CMD_READ_DMA 0xC8 /* read data using DMA */
|
|
|
|
#define CMD_WRITE_DMA 0xCA /* write data using DMA */
|
|
|
|
#define ATA_IDENTIFY 0xEC /* identify drive */
|
|
|
|
/* #define REG_CTL 0x206 */ /* control register */
|
|
|
|
#define REG_CTL 0 /* control register */
|
|
|
|
#define CTL_NORETRY 0x80 /* disable access retry */
|
|
|
|
#define CTL_NOECC 0x40 /* disable ecc retry */
|
|
|
|
#define CTL_EIGHTHEADS 0x08 /* more than eight heads */
|
|
|
|
#define CTL_RESET 0x04 /* reset controller */
|
|
|
|
#define CTL_INTDISABLE 0x02 /* disable interrupts */
|
|
|
|
#define REG_CTL_ALTSTAT 0 /* alternate status register */
|
|
|
|
|
|
|
|
/* Identify words */
|
|
|
|
#define ID_GENERAL 0x00 /* General configuration information */
|
|
|
|
#define ID_GEN_NOT_ATA 0x8000 /* Not an ATA device */
|
|
|
|
#define ID_CAPABILITIES 0x31 /* Capabilities (49)*/
|
|
|
|
#define ID_CAP_LBA 0x0200 /* LBA supported */
|
|
|
|
#define ID_CAP_DMA 0x0100 /* DMA supported */
|
|
|
|
#define ID_FIELD_VALIDITY 0x35 /* Field Validity (53) */
|
|
|
|
#define ID_FV_88 0x04 /* Word 88 is valid (UDMA) */
|
|
|
|
#define ID_MULTIWORD_DMA 0x3f /* Multiword DMA (63) */
|
|
|
|
#define ID_MWDMA_2_SEL 0x0400 /* Mode 2 is selected */
|
|
|
|
#define ID_MWDMA_1_SEL 0x0200 /* Mode 1 is selected */
|
|
|
|
#define ID_MWDMA_0_SEL 0x0100 /* Mode 0 is selected */
|
|
|
|
#define ID_MWDMA_2_SUP 0x0004 /* Mode 2 is supported */
|
|
|
|
#define ID_MWDMA_1_SUP 0x0002 /* Mode 1 is supported */
|
|
|
|
#define ID_MWDMA_0_SUP 0x0001 /* Mode 0 is supported */
|
|
|
|
#define ID_CSS 0x53 /* Command Sets Supported (83) */
|
|
|
|
#define ID_CSS_LBA48 0x0400
|
|
|
|
#define ID_ULTRA_DMA 0x58 /* Ultra DMA (88) */
|
|
|
|
#define ID_UDMA_5_SEL 0x2000 /* Mode 5 is selected */
|
|
|
|
#define ID_UDMA_4_SEL 0x1000 /* Mode 4 is selected */
|
|
|
|
#define ID_UDMA_3_SEL 0x0800 /* Mode 3 is selected */
|
|
|
|
#define ID_UDMA_2_SEL 0x0400 /* Mode 2 is selected */
|
|
|
|
#define ID_UDMA_1_SEL 0x0200 /* Mode 1 is selected */
|
|
|
|
#define ID_UDMA_0_SEL 0x0100 /* Mode 0 is selected */
|
|
|
|
#define ID_UDMA_5_SUP 0x0020 /* Mode 5 is supported */
|
|
|
|
#define ID_UDMA_4_SUP 0x0010 /* Mode 4 is supported */
|
|
|
|
#define ID_UDMA_3_SUP 0x0008 /* Mode 3 is supported */
|
|
|
|
#define ID_UDMA_2_SUP 0x0004 /* Mode 2 is supported */
|
|
|
|
#define ID_UDMA_1_SUP 0x0002 /* Mode 1 is supported */
|
|
|
|
#define ID_UDMA_0_SUP 0x0001 /* Mode 0 is supported */
|
|
|
|
|
|
|
|
/* DMA registers */
|
|
|
|
#define DMA_COMMAND 0 /* Command register */
|
|
|
|
#define DMA_CMD_WRITE 0x08 /* PCI bus master writes */
|
|
|
|
#define DMA_CMD_START 0x01 /* Start Bus Master */
|
|
|
|
#define DMA_STATUS 2 /* Status register */
|
|
|
|
#define DMA_ST_D1_DMACAP 0x40 /* Drive 1 is DMA capable */
|
|
|
|
#define DMA_ST_D0_DMACAP 0x20 /* Drive 0 is DMA capable */
|
|
|
|
#define DMA_ST_INT 0x04 /* Interrupt */
|
|
|
|
#define DMA_ST_ERROR 0x02 /* Error */
|
|
|
|
#define DMA_ST_BM_ACTIVE 0x01 /* Bus Master IDE Active */
|
|
|
|
#define DMA_PRDTP 4 /* PRD Table Pointer */
|
|
|
|
|
|
|
|
/* Check for the presence of LBA48 only on drives that are 'big'. */
|
|
|
|
#define LBA48_CHECK_SIZE 0x0f000000
|
|
|
|
#define LBA_MAX_SIZE 0x0fffffff /* Highest sector size for
|
|
|
|
* regular LBA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#if ENABLE_ATAPI
|
|
|
|
#define ERROR_SENSE 0xF0 /* sense key mask */
|
|
|
|
#define SENSE_NONE 0x00 /* no sense key */
|
|
|
|
#define SENSE_RECERR 0x10 /* recovered error */
|
|
|
|
#define SENSE_NOTRDY 0x20 /* not ready */
|
|
|
|
#define SENSE_MEDERR 0x30 /* medium error */
|
|
|
|
#define SENSE_HRDERR 0x40 /* hardware error */
|
|
|
|
#define SENSE_ILRQST 0x50 /* illegal request */
|
|
|
|
#define SENSE_UATTN 0x60 /* unit attention */
|
|
|
|
#define SENSE_DPROT 0x70 /* data protect */
|
|
|
|
#define SENSE_ABRT 0xb0 /* aborted command */
|
|
|
|
#define SENSE_MISCOM 0xe0 /* miscompare */
|
|
|
|
#define ERROR_MCR 0x08 /* media change requested */
|
|
|
|
#define ERROR_ABRT 0x04 /* aborted command */
|
|
|
|
#define ERROR_EOM 0x02 /* end of media detected */
|
|
|
|
#define ERROR_ILI 0x01 /* illegal length indication */
|
|
|
|
#define REG_FEAT 1 /* features */
|
|
|
|
#define FEAT_OVERLAP 0x02 /* overlap */
|
|
|
|
#define FEAT_DMA 0x01 /* dma */
|
|
|
|
#define REG_IRR 2 /* interrupt reason register */
|
|
|
|
#define IRR_REL 0x04 /* release */
|
|
|
|
#define IRR_IO 0x02 /* direction for xfer */
|
|
|
|
#define IRR_COD 0x01 /* command or data */
|
|
|
|
#define REG_SAMTAG 3
|
|
|
|
#define REG_CNT_LO 4 /* low byte of cylinder number */
|
|
|
|
#define REG_CNT_HI 5 /* high byte of cylinder number */
|
|
|
|
#define REG_DRIVE 6 /* drive select */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define REG_STATUS 7 /* status */
|
|
|
|
#define STATUS_BSY 0x80 /* controller busy */
|
|
|
|
#define STATUS_DRDY 0x40 /* drive ready */
|
|
|
|
#define STATUS_DMADF 0x20 /* dma ready/drive fault */
|
|
|
|
#define STATUS_SRVCDSC 0x10 /* service or dsc */
|
|
|
|
#define STATUS_DRQ 0x08 /* data transfer request */
|
|
|
|
#define STATUS_CORR 0x04 /* correctable error occurred */
|
|
|
|
#define STATUS_CHECK 0x01 /* check error */
|
|
|
|
|
|
|
|
#if ENABLE_ATAPI
|
|
|
|
#define ATAPI_PACKETCMD 0xA0 /* packet command */
|
|
|
|
#define ATAPI_IDENTIFY 0xA1 /* identify drive */
|
|
|
|
#define SCSI_READ10 0x28 /* read from disk */
|
|
|
|
#define SCSI_SENSE 0x03 /* sense request */
|
|
|
|
#endif /* ATAPI */
|
|
|
|
|
|
|
|
/* Interrupt request lines. */
|
|
|
|
#define NO_IRQ 0 /* no IRQ set yet */
|
|
|
|
|
|
|
|
#define ATAPI_PACKETSIZE 12
|
|
|
|
#define SENSE_PACKETSIZE 18
|
|
|
|
|
|
|
|
/* Error codes */
|
|
|
|
#define ERR (-1) /* general error */
|
|
|
|
#define ERR_BAD_SECTOR (-2) /* block marked bad detected */
|
|
|
|
|
|
|
|
/* Some controllers don't interrupt, the clock will wake us up. */
|
|
|
|
#define WAKEUP_SECS 32 /* drive may be out for 31 seconds max */
|
|
|
|
#define WAKEUP_TICKS (WAKEUP_SECS*system_hz)
|
|
|
|
|
|
|
|
/* Miscellaneous. */
|
|
|
|
#define MAX_DRIVES 8
|
|
|
|
#define COMPAT_DRIVES 4
|
|
|
|
#if _WORD_SIZE > 2
|
|
|
|
#define MAX_SECS 256 /* controller can transfer this many sectors */
|
|
|
|
#else
|
|
|
|
#define MAX_SECS 127 /* but not to a 16 bit process */
|
|
|
|
#endif
|
|
|
|
#define MAX_ERRORS 4 /* how often to try rd/wt before quitting */
|
|
|
|
#define NR_MINORS (MAX_DRIVES * DEV_PER_DRIVE)
|
|
|
|
#define SUB_PER_DRIVE (NR_PARTITIONS * NR_PARTITIONS)
|
|
|
|
#define NR_SUBDEVS (MAX_DRIVES * SUB_PER_DRIVE)
|
|
|
|
#define DELAY_USECS 1000 /* controller timeout in microseconds */
|
|
|
|
#define DELAY_TICKS 1 /* controller timeout in ticks */
|
|
|
|
#define DEF_TIMEOUT_TICKS 300 /* controller timeout in ticks */
|
|
|
|
#define RECOVERY_USECS 500000 /* controller recovery time in microseconds */
|
|
|
|
#define RECOVERY_TICKS 30 /* controller recovery time in ticks */
|
|
|
|
#define INITIALIZED 0x01 /* drive is initialized */
|
|
|
|
#define DEAF 0x02 /* controller must be reset */
|
|
|
|
#define SMART 0x04 /* drive supports ATA commands */
|
|
|
|
#if ENABLE_ATAPI
|
|
|
|
#define ATAPI 0x08 /* it is an ATAPI device */
|
|
|
|
#else
|
|
|
|
#define ATAPI 0 /* don't bother with ATAPI; optimise out */
|
|
|
|
#endif
|
|
|
|
#define IDENTIFIED 0x10 /* w_identify done successfully */
|
|
|
|
#define IGNORING 0x20 /* w_identify failed once */
|
|
|
|
|
|
|
|
#define NO_DMA_VAR "ata_no_dma"
|
|
|
|
|