Signed-off-by: Michel Stam <michel@reverze.net> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
198 lines
5.7 KiB
C
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 */
|