summaryrefslogtreecommitdiffstats
path: root/qemu/roms/openbios/drivers/ide.h
blob: d6c4b9f5d8ab4b6336c9af56da96b650c58039fe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#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 {

	char name[32];
	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