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