]>
Commit | Line | Data |
---|---|---|
832b75ed GG |
1 | /* |
2 | * os_linux.h | |
3 | * | |
a86ec89e | 4 | * Home page of code is: http://www.smartmontools.org |
832b75ed | 5 | * |
f9e10201 | 6 | * Copyright (C) 2003-8 Bruce Allen |
832b75ed GG |
7 | * |
8 | * Derived from code that was | |
9 | * | |
10 | * Written By: Adam Radford <linux@3ware.com> | |
11 | * Modifications By: Joel Jacobson <linux@3ware.com> | |
4d59bff9 | 12 | * Arnaldo Carvalho de Melo <acme@conectiva.com.br> |
832b75ed GG |
13 | * Brad Strand <linux@3ware.com> |
14 | * | |
15 | * Copyright (C) 1999-2003 3ware Inc. | |
16 | * | |
ff28b140 | 17 | * Kernel compatibility By: Andre Hedrick <andre@suse.com> |
832b75ed GG |
18 | * Non-Copyright (C) 2000 Andre Hedrick <andre@suse.com> |
19 | * | |
ff28b140 | 20 | * SPDX-License-Identifier: GPL-2.0-or-later |
832b75ed GG |
21 | */ |
22 | ||
23 | ||
24 | #ifndef OS_LINUX_H_ | |
25 | #define OS_LINUX_H_ | |
26 | ||
ff28b140 | 27 | #define OS_LINUX_H_CVSID "$Id: os_linux.h 4842 2018-12-02 16:07:26Z chrfranke $\n" |
832b75ed GG |
28 | |
29 | /* | |
30 | The following definitions/macros/prototypes are used for three | |
31 | different interfaces, referred to as "the three cases" below. | |
32 | CONTROLLER_3WARE_678K -- 6000, 7000, and 8000 controllers via /dev/sd? | |
33 | CONTROLLER_3WARE_678K_CHAR -- 6000, 7000, and 8000 controllers via /dev/twe? | |
34 | CONTROLLER_3WARE_9000_CHAR -- 9000 controllers via /dev/twa? | |
35 | */ | |
36 | ||
37 | // USED FOR ALL THREE CASES | |
38 | ||
39 | #define u32 unsigned int | |
40 | #define TW_OP_ATA_PASSTHRU 0x11 | |
41 | #define MAX(x,y) ( (x)>(y)?(x):(y) ) | |
42 | ||
43 | #pragma pack(1) | |
44 | /* Scatter gather list entry */ | |
45 | typedef struct TAG_TW_SG_Entry { | |
46 | unsigned int address; | |
47 | unsigned int length; | |
48 | } TW_SG_Entry; | |
49 | ||
50 | /* Command header for ATA pass-thru. Note that for different | |
51 | drivers/interfaces the length of sg_list (here TW_ATA_PASS_SGL_MAX) | |
52 | is different. But it can be taken as same for all three cases | |
53 | because it's never used to define any other structures, and we | |
54 | never use anything in the sg_list or beyond! */ | |
55 | ||
56 | #define TW_ATA_PASS_SGL_MAX 60 | |
57 | ||
58 | typedef struct TAG_TW_Passthru { | |
59 | struct { | |
60 | unsigned char opcode:5; | |
61 | unsigned char sgloff:3; | |
62 | } byte0; | |
63 | unsigned char size; | |
64 | unsigned char request_id; | |
a37e7145 | 65 | unsigned char unit; |
832b75ed GG |
66 | unsigned char status; // On return, contains 3ware STATUS register |
67 | unsigned char flags; | |
68 | unsigned short param; | |
69 | unsigned short features; // On return, contains ATA ERROR register | |
70 | unsigned short sector_count; | |
71 | unsigned short sector_num; | |
72 | unsigned short cylinder_lo; | |
73 | unsigned short cylinder_hi; | |
74 | unsigned char drive_head; | |
75 | unsigned char command; // On return, contains ATA STATUS register | |
76 | TW_SG_Entry sg_list[TW_ATA_PASS_SGL_MAX]; | |
77 | unsigned char padding[12]; | |
78 | } TW_Passthru; | |
79 | ||
80 | // the following are for the SCSI interface only | |
81 | ||
82 | // Ioctl buffer: Note that this defn has changed in kernel tree... | |
83 | // Total size is 1041 bytes -- this is really weird | |
84 | ||
85 | #define TW_IOCTL 0x80 | |
86 | #define TW_ATA_PASSTHRU 0x1e | |
87 | ||
88 | // Adam -- should this be #pramga packed? Otherwise table_id gets | |
89 | // moved for byte alignment. Without packing, input passthru for SCSI | |
90 | // ioctl is 31 bytes in. With packing it is 30 bytes in. | |
91 | typedef struct TAG_TW_Ioctl { | |
92 | int input_length; | |
93 | int output_length; | |
94 | unsigned char cdb[16]; | |
95 | unsigned char opcode; | |
96 | // This one byte of padding is missing from the typedefs in the | |
97 | // kernel code, but it is indeed present. We put it explicitly | |
98 | // here, so that the structure can be packed. Adam agrees with | |
99 | // this. | |
100 | unsigned char packing; | |
101 | unsigned short table_id; | |
102 | unsigned char parameter_id; | |
103 | unsigned char parameter_size_bytes; | |
104 | unsigned char unit_index; | |
105 | // Size up to here is 30 bytes + 1 padding! | |
106 | unsigned char input_data[499]; | |
107 | // Reserve lots of extra space for commands that set Sector Count | |
108 | // register to large values | |
109 | unsigned char output_data[512]; // starts 530 bytes in! | |
110 | // two more padding bytes here if structure NOT packed. | |
111 | } TW_Ioctl; | |
112 | ||
113 | /* Ioctl buffer output -- SCSI interface only! */ | |
114 | typedef struct TAG_TW_Output { | |
115 | int padding[2]; | |
116 | char output_data[512]; | |
117 | } TW_Output; | |
118 | ||
119 | // What follows is needed for 9000 char interface only | |
120 | ||
121 | #define TW_IOCTL_FIRMWARE_PASS_THROUGH 0x108 | |
122 | #define TW_MAX_SGL_LENGTH_9000 61 | |
123 | ||
124 | typedef struct TAG_TW_Ioctl_Driver_Command_9000 { | |
125 | unsigned int control_code; | |
126 | unsigned int status; | |
127 | unsigned int unique_id; | |
128 | unsigned int sequence_id; | |
129 | unsigned int os_specific; | |
130 | unsigned int buffer_length; | |
131 | } TW_Ioctl_Driver_Command_9000; | |
132 | ||
133 | /* Command Packet */ | |
134 | typedef struct TW_Command_9000 { | |
135 | /* First DWORD */ | |
136 | struct { | |
137 | unsigned char opcode:5; | |
138 | unsigned char sgl_offset:3; | |
139 | } byte0; | |
140 | unsigned char size; | |
141 | unsigned char request_id; | |
142 | struct { | |
143 | unsigned char unit:4; | |
144 | unsigned char host_id:4; | |
145 | } byte3; | |
146 | /* Second DWORD */ | |
147 | unsigned char status; | |
148 | unsigned char flags; | |
149 | union { | |
150 | unsigned short block_count; | |
151 | unsigned short parameter_count; | |
152 | unsigned short message_credits; | |
153 | } byte6; | |
154 | union { | |
155 | struct { | |
156 | u32 lba; | |
157 | TW_SG_Entry sgl[TW_MAX_SGL_LENGTH_9000]; | |
158 | u32 padding; | |
159 | } io; | |
160 | struct { | |
161 | TW_SG_Entry sgl[TW_MAX_SGL_LENGTH_9000]; | |
162 | u32 padding[2]; | |
163 | } param; | |
164 | struct { | |
165 | u32 response_queue_pointer; | |
166 | u32 padding[125]; /* pad entire structure to 512 bytes */ | |
167 | } init_connection; | |
168 | struct { | |
169 | char version[504]; | |
170 | } ioctl_miniport_version; | |
171 | } byte8; | |
172 | } TW_Command_9000; | |
173 | ||
174 | /* Command Packet for 9000+ controllers */ | |
175 | typedef struct TAG_TW_Command_Apache { | |
176 | struct { | |
177 | unsigned char opcode:5; | |
178 | unsigned char reserved:3; | |
179 | } command; | |
180 | unsigned char unit; | |
181 | unsigned short request_id; | |
182 | unsigned char sense_length; | |
183 | unsigned char sgl_offset; | |
184 | unsigned short sgl_entries; | |
185 | unsigned char cdb[16]; | |
186 | TW_SG_Entry sg_list[TW_MAX_SGL_LENGTH_9000]; | |
187 | } TW_Command_Apache; | |
188 | ||
189 | /* New command packet header */ | |
190 | typedef struct TAG_TW_Command_Apache_Header { | |
191 | unsigned char sense_data[18]; | |
192 | struct { | |
193 | char reserved[4]; | |
194 | unsigned short error; | |
195 | unsigned char status; | |
196 | struct { | |
197 | unsigned char severity:3; | |
198 | unsigned char reserved:5; | |
199 | } substatus_block; | |
200 | } status_block; | |
201 | unsigned char err_specific_desc[102]; | |
202 | } TW_Command_Apache_Header; | |
203 | ||
204 | /* This struct is a union of the 2 command packets */ | |
205 | typedef struct TAG_TW_Command_Full_9000 { | |
206 | TW_Command_Apache_Header header; | |
207 | union { | |
208 | TW_Command_9000 oldcommand; | |
209 | TW_Command_Apache newcommand; | |
210 | } command; | |
211 | unsigned char padding[384]; /* Pad to 1024 bytes */ | |
212 | } TW_Command_Full_9000; | |
213 | ||
214 | typedef struct TAG_TW_Ioctl_Apache { | |
215 | TW_Ioctl_Driver_Command_9000 driver_command; | |
216 | char padding[488]; | |
217 | TW_Command_Full_9000 firmware_command; | |
218 | char data_buffer[1]; | |
219 | // three bytes of padding here if structure not packed! | |
220 | } TW_Ioctl_Buf_Apache; | |
221 | ||
222 | ||
223 | ||
224 | // START OF DEFINITIONS FOR THE CHARACTER INTERFACE TO THE | |
225 | // 6000/7000/8000 drivers | |
226 | ||
227 | #define TW_MAX_SGL_LENGTH 62 | |
228 | #define TW_CMD_PACKET_WITH_DATA 0x1f | |
229 | ||
230 | /* Command Packet */ | |
231 | typedef struct TW_Command { | |
232 | /* First DWORD */ | |
233 | struct { | |
234 | unsigned char opcode:5; | |
235 | unsigned char sgl_offset:3; | |
236 | } byte0; | |
237 | unsigned char size; | |
238 | unsigned char request_id; | |
239 | struct { | |
240 | unsigned char unit:4; | |
241 | unsigned char host_id:4; | |
242 | } byte3; | |
243 | /* Second DWORD */ | |
244 | unsigned char status; | |
245 | unsigned char flags; | |
246 | union { | |
247 | unsigned short block_count; | |
248 | unsigned short parameter_count; | |
249 | unsigned short message_credits; | |
250 | } byte6; | |
251 | union { | |
252 | struct { | |
253 | u32 lba; | |
254 | TW_SG_Entry sgl[TW_MAX_SGL_LENGTH]; | |
255 | u32 padding; /* pad to 512 bytes */ | |
256 | } io; | |
257 | struct { | |
258 | TW_SG_Entry sgl[TW_MAX_SGL_LENGTH]; | |
259 | u32 padding[2]; | |
260 | } param; | |
261 | struct { | |
262 | u32 response_queue_pointer; | |
263 | u32 padding[125]; | |
264 | } init_connection; | |
265 | struct { | |
266 | char version[504]; | |
267 | } ioctl_miniport_version; | |
268 | } byte8; | |
269 | } TW_Command; | |
270 | ||
271 | typedef struct TAG_TW_New_Ioctl { | |
272 | unsigned int data_buffer_length; | |
273 | unsigned char padding [508]; | |
274 | TW_Command firmware_command; | |
275 | char data_buffer[1]; | |
276 | // three bytes of padding here | |
277 | } TW_New_Ioctl; | |
278 | #pragma pack() | |
279 | ||
280 | #if 0 | |
281 | // Useful for checking/understanding packing of 3ware data structures | |
282 | // above. | |
283 | void my(int x, char *y){ | |
284 | printf("The size of %30s is: %5d\n",y, x); | |
285 | return; | |
286 | } | |
287 | ||
288 | int main() { | |
289 | TW_Ioctl tmp; | |
290 | my(sizeof(TW_SG_Entry),"TW_SG_Entry"); | |
291 | my(sizeof(TW_Passthru),"TW_Passthru"); | |
292 | my(sizeof(TW_Ioctl),"TW_Ioctl"); | |
293 | my(sizeof(TW_Output),"TW_Output"); | |
294 | my(sizeof(TW_Ioctl_Driver_Command_9000),"TW_Ioctl_Driver_Command_9000"); | |
295 | my(sizeof(TW_Command_9000),"TW_Command_9000"); | |
296 | my(sizeof(TW_Command_Apache),"TW_Command_Apache"); | |
297 | my(sizeof(TW_Command_Apache_Header),"TW_Command_Apache_Header"); | |
298 | my(sizeof(TW_Command_Full_9000),"TW_Command_Full_9000"); | |
299 | my(sizeof(TW_Ioctl_Buf_Apache),"TW_Ioctl_Buf_Apache"); | |
300 | my(sizeof(TW_Command),"TW_Command"); | |
301 | my(sizeof(TW_New_Ioctl),"TW_New_Ioctl"); | |
302 | printf("TW_Ioctl.table_id - start = %d (irrelevant)\n", | |
303 | (void *)&tmp.table_id - (void *)&tmp); | |
304 | printf("TW_Ioctl.input_data - start = %d (input passthru location)\n", | |
305 | (void *)&tmp.input_data - (void *)&tmp); | |
306 | printf("TW_Ioctl.output_data - start = %d (irrelevant)\n", | |
307 | (void *)&tmp.output_data - (void *)&tmp); | |
308 | return 0; | |
309 | } | |
310 | #endif | |
311 | ||
312 | // The following definitions are from hdreg.h in the kernel source | |
313 | // tree. They don't carry any Copyright statements, but I think they | |
314 | // are primarily from Mark Lord and Andre Hedrick. | |
315 | typedef unsigned char task_ioreg_t; | |
316 | ||
317 | typedef struct hd_drive_task_hdr { | |
318 | task_ioreg_t data; | |
319 | task_ioreg_t feature; | |
320 | task_ioreg_t sector_count; | |
321 | task_ioreg_t sector_number; | |
322 | task_ioreg_t low_cylinder; | |
323 | task_ioreg_t high_cylinder; | |
324 | task_ioreg_t device_head; | |
325 | task_ioreg_t command; | |
326 | } task_struct_t; | |
327 | ||
328 | typedef union ide_reg_valid_s { | |
329 | unsigned all : 16; | |
330 | struct { | |
331 | unsigned data : 1; | |
332 | unsigned error_feature : 1; | |
333 | unsigned sector : 1; | |
334 | unsigned nsector : 1; | |
335 | unsigned lcyl : 1; | |
336 | unsigned hcyl : 1; | |
337 | unsigned select : 1; | |
338 | unsigned status_command : 1; | |
339 | unsigned data_hob : 1; | |
340 | unsigned error_feature_hob : 1; | |
341 | unsigned sector_hob : 1; | |
342 | unsigned nsector_hob : 1; | |
343 | unsigned lcyl_hob : 1; | |
344 | unsigned hcyl_hob : 1; | |
345 | unsigned select_hob : 1; | |
346 | unsigned control_hob : 1; | |
347 | } b; | |
348 | } ide_reg_valid_t; | |
349 | ||
350 | typedef struct ide_task_request_s { | |
351 | task_ioreg_t io_ports[8]; | |
352 | task_ioreg_t hob_ports[8]; | |
353 | ide_reg_valid_t out_flags; | |
354 | ide_reg_valid_t in_flags; | |
355 | int data_phase; | |
356 | int req_cmd; | |
357 | unsigned long out_size; | |
358 | unsigned long in_size; | |
359 | } ide_task_request_t; | |
360 | ||
361 | #define TASKFILE_NO_DATA 0x0000 | |
362 | #define TASKFILE_IN 0x0001 | |
363 | #define TASKFILE_OUT 0x0004 | |
364 | #define HDIO_DRIVE_TASK_HDR_SIZE 8*sizeof(task_ioreg_t) | |
365 | #define IDE_DRIVE_TASK_NO_DATA 0 | |
366 | #define IDE_DRIVE_TASK_IN 2 | |
367 | #define IDE_DRIVE_TASK_OUT 3 | |
368 | #define HDIO_DRIVE_CMD 0x031f | |
369 | #define HDIO_DRIVE_TASK 0x031e | |
370 | #define HDIO_DRIVE_TASKFILE 0x031d | |
371 | #define HDIO_GET_IDENTITY 0x030d | |
372 | ||
4d59bff9 GG |
373 | #define HPTIO_CTL 0x03ff // ioctl interface for HighPoint raid device |
374 | ||
832b75ed | 375 | #endif /* OS_LINUX_H_ */ |