#ifndef IDE_H #define IDE_H #include "hdreg.h" /* * legacy ide ports */ #define IDEREG_DATA 0x00 #define IDEREG_ERROR 0x01 #define IDEREG_FEATURE IDEREG_ERROR #define IDEREG_NSECTOR 0x02 #define IDEREG_SECTOR 0x03 #define IDEREG_LCYL 0x04 #define IDEREG_HCYL 0x05 #define IDEREG_CURRENT 0x06 #define IDEREG_STATUS 0x07 #define IDEREG_COMMAND IDEREG_STATUS #define IDEREG_CONTROL 0x08 #define IDEREG_ASTATUS IDEREG_CONTROL /* * device control bits */ #define IDECON_NIEN 0x02 #define IDECON_SRST 0x04 /* * device head bits */ #define IDEHEAD_LBA 0x40 #define IDEHEAD_DEV0 0x00 #define IDEHEAD_DEV1 0x10 /* * status bytes */ #define ERR_STAT 0x01 #define DRQ_STAT 0x08 #define SEEK_STAT 0x10 #define WRERR_STAT 0x20 #define READY_STAT 0x40 #define BUSY_STAT 0x80 #define IREASON_CD 0x01 #define IREASON_IO 0x02 /* * ATA opcodes */ #define WIN_READ 0x20 #define WIN_READ_EXT 0x24 #define WIN_IDENTIFY 0xEC #define WIN_PACKET 0xA0 #define WIN_IDENTIFY_PACKET 0xA1 /* * ATAPI opcodes */ #define ATAPI_TUR 0x00 #define ATAPI_READ_10 0x28 #define ATAPI_REQ_SENSE 0x03 #define ATAPI_START_STOP_UNIT 0x1b #define ATAPI_READ_CAPACITY 0x25 /* * atapi sense keys */ #define ATAPI_SENSE_NOT_READY 0x02 /* * supported device types */ enum { ide_type_unknown, ide_type_ata, ide_type_atapi, }; enum { ide_media_floppy = 0x00, ide_media_cdrom = 0x05, ide_media_optical = 0x07, ide_media_disk = 0x20, }; /* * drive addressing */ enum { ide_chs = 1, ide_lba28, ide_lba48, }; /* * simple ata command that works for everything (except 48-bit lba commands) */ struct ata_command { unsigned char *buffer; unsigned int buflen; /* * data register */ unsigned char data; unsigned char feature; unsigned char nsector; unsigned char sector; unsigned char lcyl; unsigned char hcyl; unsigned char device_head; unsigned char command; unsigned char control; /* * or tasklet, just for lba48 for now (above could be scrapped) */ unsigned char task[10]; /* * output */ unsigned char stat; unsigned int bytes; }; struct atapi_command { unsigned char cdb[12]; unsigned char *buffer; unsigned int buflen; unsigned char data_direction; unsigned char stat; unsigned char sense_valid; struct request_sense sense; unsigned char old_cdb; }; struct ide_channel; struct ide_drive { char unit; /* 0: master, 1: slave */ char present; /* there or not */ char type; /* ata or atapi */ char media; /* disk, cdrom, etc */ char addressing; /* chs/lba28/lba48 */ char model[41]; /* name */ int nr; unsigned long sectors; unsigned int max_sectors; /* * for legacy chs crap */ unsigned int cyl; unsigned int head; unsigned int sect; unsigned int bs; /* block size */ struct ide_channel *channel; }; struct ide_channel { phandle_t ph; struct ide_channel *next; /* * either mmio or io_regs is set to indicate mmio or not */ unsigned long mmio; int io_regs[10]; /* * can be set to a mmio hook, default it legacy outb/inb */ void (*obide_outb)(struct ide_channel *chan, unsigned char addr, unsigned int port); unsigned char (*obide_inb)(struct ide_channel *chan, unsigned int port); void (*obide_insw)(struct ide_channel *chan, unsigned int port, unsigned char *addr, unsigned int count); void (*obide_outsw)(struct ide_channel *chan, unsigned int port, unsigned char *addr, unsigned int count); struct ide_drive drives[2]; char selected; char present; /* * only one can be busy per channel */ struct ata_command ata_cmd; struct atapi_command atapi_cmd; }; enum { atapi_ddir_none, atapi_ddir_read, atapi_ddir_write, }; static int ob_ide_atapi_request_sense(struct ide_drive *drive); #endif