9
0
Fork 0
barebox/include/ata_drive.h

198 lines
5.7 KiB
C

/*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef ATA_DISK_H
# define ATA_DISK
#include <block.h>
/* IDE register file */
#define IDE_REG_DATA 0x00
#define IDE_REG_ERR 0x01
#define IDE_REG_NSECT 0x02
#define IDE_REG_LBAL 0x03
#define IDE_REG_LBAM 0x04
#define IDE_REG_LBAH 0x05
#define IDE_REG_DEVICE 0x06
#define IDE_REG_STATUS 0x07
#define IDE_REG_FEATURE IDE_REG_ERR /* and their aliases */
#define IDE_REG_CMD IDE_REG_STATUS
#define IDE_REG_ALT_STATUS 0x00
#define IDE_REG_DEV_CTL 0x00
#define IDE_REG_DRV_ADDR 0x01
#define ATA_CMD_ID_ATA 0xEC
#define ATA_CMD_READ 0x20
#define ATA_CMD_READ_EXT 0x25
#define ATA_CMD_WRITE 0x30
#define ATA_CMD_WRITE_EXT 0x35
/* drive's status flags */
#define ATA_STATUS_BUSY (1 << 7)
#define ATA_STATUS_READY (1 << 6)
#define ATA_STATUS_WR_FLT (1 << 5)
#define ATA_STATUS_DSC (1 << 4)
#define ATA_STATUS_DRQ (1 << 3)
#define ATA_STATUS_CORR (1 << 2)
#define ATA_STATUS_IDX (1 << 1)
#define ATA_STATUS_ERROR (1 << 0)
/* command flags */
#define LBA_FLAG (1 << 6)
#define ATA_DEVCTL_SOFT_RESET (1 << 2)
#define ATA_DEVCTL_INTR_DISABLE (1 << 1)
#define ata_id_u32(id,n) \
(((uint32_t) (id)[(n) + 1] << 16) | ((uint32_t) (id)[(n)]))
#define ata_id_u64(id,n) \
( ((uint64_t) (id)[(n) + 3] << 48) | \
((uint64_t) (id)[(n) + 2] << 32) | \
((uint64_t) (id)[(n) + 1] << 16) | \
((uint64_t) (id)[(n) + 0]) )
#define ata_id_has_lba(id) ((id)[49] & (1 << 9))
enum {
ATA_ID_SERNO = 10,
#define ATA_ID_SERNO_LEN 20
ATA_ID_FW_REV = 23,
#define ATA_ID_FW_REV_LEN 8
ATA_ID_PROD = 27,
#define ATA_ID_PROD_LEN 40
ATA_ID_CAPABILITY = 49,
ATA_ID_FIELD_VALID = 53,
ATA_ID_LBA_CAPACITY = 60,
ATA_ID_MWDMA_MODES = 63,
ATA_ID_PIO_MODES = 64,
ATA_ID_QUEUE_DEPTH = 75,
ATA_ID_MAJOR_VER = 80,
ATA_ID_COMMAND_SET_1 = 82,
ATA_ID_COMMAND_SET_2 = 83,
ATA_ID_CFSSE = 84,
ATA_ID_CFS_ENABLE_1 = 85,
ATA_ID_CFS_ENABLE_2 = 86,
ATA_ID_CSF_DEFAULT = 87,
ATA_ID_UDMA_MODES = 88,
ATA_ID_HW_CONFIG = 93,
ATA_ID_LBA_CAPACITY_2 = 100,
};
static inline int ata_id_has_lba48(const uint16_t *id)
{
if ((id[ATA_ID_COMMAND_SET_2] & 0xC000) != 0x4000)
return 0;
if (!ata_id_u64(id, ATA_ID_LBA_CAPACITY_2))
return 0;
return id[ATA_ID_COMMAND_SET_2] & (1 << 10);
}
/** addresses of each individual IDE drive register */
struct ata_ioports {
void __iomem *cmd_addr;
void __iomem *data_addr;
void __iomem *error_addr;
void __iomem *feature_addr;
void __iomem *nsect_addr;
void __iomem *lbal_addr;
void __iomem *lbam_addr;
void __iomem *lbah_addr;
void __iomem *device_addr;
void __iomem *status_addr;
void __iomem *command_addr;
void __iomem *altstatus_addr;
void __iomem *ctl_addr;
void __iomem *alt_dev_addr;
/* hard reset line handling */
void (*reset)(int); /* true: assert reset, false: de-assert reset */
int dataif_be; /* true if 16 bit data register is big endian */
int mmio; /* true if memory-mapped io */
};
struct ata_port;
struct ata_port_operations {
int (*init)(struct ata_port *port);
int (*read)(struct ata_port *port, void *buf, unsigned int block, int num_blocks);
int (*write)(struct ata_port *port, const void *buf, unsigned int block, int num_blocks);
int (*read_id)(struct ata_port *port, void *buf);
int (*reset)(struct ata_port *port);
};
struct ata_port {
struct ata_port_operations *ops;
struct device_d *dev;
struct device_d class_dev;
const char *devname;
void *drvdata;
struct block_device blk;
uint16_t *id;
int initialized;
int probe;
};
struct ide_port {
struct ata_ioports io; /**< register file */
struct ata_port port;
};
int ide_port_register(struct ide_port *ide);
int ata_port_register(struct ata_port *port);
int ata_port_detect(struct ata_port *port);
struct device_d;
/**
* @file
* @brief Register file examples of generic types of ATA devices
*
* PC IDE:
*
* Offset Read Write Note
*-----------------------------------------------------------
* 0x1f0 data data 16 bit register
* 0x1f1 error feature
* 0x1f2 sec cnt set cnt
* 0x1f3 sec no sec no
* 0x1f4 cyl low cyl low
* 0x1f5 cyl high cyl high
* 0x1f6 head head
* 0x1f7 status command
* 0x3f6 alt status dev cntrl
* 0x3f7 drv addr
*
* PCMCIA memory mapped:
*
* Offset Read Write Note
*-----------------------------------------------------------
* 0x0 data data 16 bit register
* 0x1 error feature
* 0x2 sec cnt set cnt
* 0x3 sec no sec no
* 0x4 cyl low cyl low
* 0x5 cyl high cyl high
* 0x6 head head
* 0x7 status command
* 0x8 data data 16 bit or 8 bit register (even byte)
* 0x9 data data 8 bit register (odd byte)
* 0xd error feature dup of offset 1
* 0xe alt status dev cntrl
* 0xf drv addr
* 0x400 data data 16 bit area with 1 kiB in size
*/
#endif /* ATA_DISK */