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
|