]>
Commit | Line | Data |
---|---|---|
832b75ed GG |
1 | /* |
2 | * os_linux.h | |
3 | * | |
4 | * Home page of code is: http://smartmontools.sourceforge.net | |
5 | * | |
34ad0c5f | 6 | * Copyright (C) 2003-8 Bruce Allen <smartmontools-support@lists.sourceforge.net> |
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 | * | |
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 | ||
34ad0c5f | 41 | #define OS_LINUX_H_CVSID "$Id: os_linux.h,v 1.27 2008/03/04 22:09:47 ballen4705 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; | |
a37e7145 | 79 | unsigned char unit; |
832b75ed GG |
80 | unsigned char status; // On return, contains 3ware STATUS register |
81 | unsigned char flags; | |
82 | unsigned short param; | |
83 | unsigned short features; // On return, contains ATA ERROR register | |
84 | unsigned short sector_count; | |
85 | unsigned short sector_num; | |
86 | unsigned short cylinder_lo; | |
87 | unsigned short cylinder_hi; | |
88 | unsigned char drive_head; | |
89 | unsigned char command; // On return, contains ATA STATUS register | |
90 | TW_SG_Entry sg_list[TW_ATA_PASS_SGL_MAX]; | |
91 | unsigned char padding[12]; | |
92 | } TW_Passthru; | |
93 | ||
94 | // the following are for the SCSI interface only | |
95 | ||
96 | // Ioctl buffer: Note that this defn has changed in kernel tree... | |
97 | // Total size is 1041 bytes -- this is really weird | |
98 | ||
99 | #define TW_IOCTL 0x80 | |
100 | #define TW_ATA_PASSTHRU 0x1e | |
101 | ||
102 | // Adam -- should this be #pramga packed? Otherwise table_id gets | |
103 | // moved for byte alignment. Without packing, input passthru for SCSI | |
104 | // ioctl is 31 bytes in. With packing it is 30 bytes in. | |
105 | typedef struct TAG_TW_Ioctl { | |
106 | int input_length; | |
107 | int output_length; | |
108 | unsigned char cdb[16]; | |
109 | unsigned char opcode; | |
110 | // This one byte of padding is missing from the typedefs in the | |
111 | // kernel code, but it is indeed present. We put it explicitly | |
112 | // here, so that the structure can be packed. Adam agrees with | |
113 | // this. | |
114 | unsigned char packing; | |
115 | unsigned short table_id; | |
116 | unsigned char parameter_id; | |
117 | unsigned char parameter_size_bytes; | |
118 | unsigned char unit_index; | |
119 | // Size up to here is 30 bytes + 1 padding! | |
120 | unsigned char input_data[499]; | |
121 | // Reserve lots of extra space for commands that set Sector Count | |
122 | // register to large values | |
123 | unsigned char output_data[512]; // starts 530 bytes in! | |
124 | // two more padding bytes here if structure NOT packed. | |
125 | } TW_Ioctl; | |
126 | ||
127 | /* Ioctl buffer output -- SCSI interface only! */ | |
128 | typedef struct TAG_TW_Output { | |
129 | int padding[2]; | |
130 | char output_data[512]; | |
131 | } TW_Output; | |
132 | ||
133 | // What follows is needed for 9000 char interface only | |
134 | ||
135 | #define TW_IOCTL_FIRMWARE_PASS_THROUGH 0x108 | |
136 | #define TW_MAX_SGL_LENGTH_9000 61 | |
137 | ||
138 | typedef struct TAG_TW_Ioctl_Driver_Command_9000 { | |
139 | unsigned int control_code; | |
140 | unsigned int status; | |
141 | unsigned int unique_id; | |
142 | unsigned int sequence_id; | |
143 | unsigned int os_specific; | |
144 | unsigned int buffer_length; | |
145 | } TW_Ioctl_Driver_Command_9000; | |
146 | ||
147 | /* Command Packet */ | |
148 | typedef struct TW_Command_9000 { | |
149 | /* First DWORD */ | |
150 | struct { | |
151 | unsigned char opcode:5; | |
152 | unsigned char sgl_offset:3; | |
153 | } byte0; | |
154 | unsigned char size; | |
155 | unsigned char request_id; | |
156 | struct { | |
157 | unsigned char unit:4; | |
158 | unsigned char host_id:4; | |
159 | } byte3; | |
160 | /* Second DWORD */ | |
161 | unsigned char status; | |
162 | unsigned char flags; | |
163 | union { | |
164 | unsigned short block_count; | |
165 | unsigned short parameter_count; | |
166 | unsigned short message_credits; | |
167 | } byte6; | |
168 | union { | |
169 | struct { | |
170 | u32 lba; | |
171 | TW_SG_Entry sgl[TW_MAX_SGL_LENGTH_9000]; | |
172 | u32 padding; | |
173 | } io; | |
174 | struct { | |
175 | TW_SG_Entry sgl[TW_MAX_SGL_LENGTH_9000]; | |
176 | u32 padding[2]; | |
177 | } param; | |
178 | struct { | |
179 | u32 response_queue_pointer; | |
180 | u32 padding[125]; /* pad entire structure to 512 bytes */ | |
181 | } init_connection; | |
182 | struct { | |
183 | char version[504]; | |
184 | } ioctl_miniport_version; | |
185 | } byte8; | |
186 | } TW_Command_9000; | |
187 | ||
188 | /* Command Packet for 9000+ controllers */ | |
189 | typedef struct TAG_TW_Command_Apache { | |
190 | struct { | |
191 | unsigned char opcode:5; | |
192 | unsigned char reserved:3; | |
193 | } command; | |
194 | unsigned char unit; | |
195 | unsigned short request_id; | |
196 | unsigned char sense_length; | |
197 | unsigned char sgl_offset; | |
198 | unsigned short sgl_entries; | |
199 | unsigned char cdb[16]; | |
200 | TW_SG_Entry sg_list[TW_MAX_SGL_LENGTH_9000]; | |
201 | } TW_Command_Apache; | |
202 | ||
203 | /* New command packet header */ | |
204 | typedef struct TAG_TW_Command_Apache_Header { | |
205 | unsigned char sense_data[18]; | |
206 | struct { | |
207 | char reserved[4]; | |
208 | unsigned short error; | |
209 | unsigned char status; | |
210 | struct { | |
211 | unsigned char severity:3; | |
212 | unsigned char reserved:5; | |
213 | } substatus_block; | |
214 | } status_block; | |
215 | unsigned char err_specific_desc[102]; | |
216 | } TW_Command_Apache_Header; | |
217 | ||
218 | /* This struct is a union of the 2 command packets */ | |
219 | typedef struct TAG_TW_Command_Full_9000 { | |
220 | TW_Command_Apache_Header header; | |
221 | union { | |
222 | TW_Command_9000 oldcommand; | |
223 | TW_Command_Apache newcommand; | |
224 | } command; | |
225 | unsigned char padding[384]; /* Pad to 1024 bytes */ | |
226 | } TW_Command_Full_9000; | |
227 | ||
228 | typedef struct TAG_TW_Ioctl_Apache { | |
229 | TW_Ioctl_Driver_Command_9000 driver_command; | |
230 | char padding[488]; | |
231 | TW_Command_Full_9000 firmware_command; | |
232 | char data_buffer[1]; | |
233 | // three bytes of padding here if structure not packed! | |
234 | } TW_Ioctl_Buf_Apache; | |
235 | ||
236 | ||
237 | ||
238 | // START OF DEFINITIONS FOR THE CHARACTER INTERFACE TO THE | |
239 | // 6000/7000/8000 drivers | |
240 | ||
241 | #define TW_MAX_SGL_LENGTH 62 | |
242 | #define TW_CMD_PACKET_WITH_DATA 0x1f | |
243 | ||
244 | /* Command Packet */ | |
245 | typedef struct TW_Command { | |
246 | /* First DWORD */ | |
247 | struct { | |
248 | unsigned char opcode:5; | |
249 | unsigned char sgl_offset:3; | |
250 | } byte0; | |
251 | unsigned char size; | |
252 | unsigned char request_id; | |
253 | struct { | |
254 | unsigned char unit:4; | |
255 | unsigned char host_id:4; | |
256 | } byte3; | |
257 | /* Second DWORD */ | |
258 | unsigned char status; | |
259 | unsigned char flags; | |
260 | union { | |
261 | unsigned short block_count; | |
262 | unsigned short parameter_count; | |
263 | unsigned short message_credits; | |
264 | } byte6; | |
265 | union { | |
266 | struct { | |
267 | u32 lba; | |
268 | TW_SG_Entry sgl[TW_MAX_SGL_LENGTH]; | |
269 | u32 padding; /* pad to 512 bytes */ | |
270 | } io; | |
271 | struct { | |
272 | TW_SG_Entry sgl[TW_MAX_SGL_LENGTH]; | |
273 | u32 padding[2]; | |
274 | } param; | |
275 | struct { | |
276 | u32 response_queue_pointer; | |
277 | u32 padding[125]; | |
278 | } init_connection; | |
279 | struct { | |
280 | char version[504]; | |
281 | } ioctl_miniport_version; | |
282 | } byte8; | |
283 | } TW_Command; | |
284 | ||
285 | typedef struct TAG_TW_New_Ioctl { | |
286 | unsigned int data_buffer_length; | |
287 | unsigned char padding [508]; | |
288 | TW_Command firmware_command; | |
289 | char data_buffer[1]; | |
290 | // three bytes of padding here | |
291 | } TW_New_Ioctl; | |
292 | #pragma pack() | |
293 | ||
294 | #if 0 | |
295 | // Useful for checking/understanding packing of 3ware data structures | |
296 | // above. | |
297 | void my(int x, char *y){ | |
298 | printf("The size of %30s is: %5d\n",y, x); | |
299 | return; | |
300 | } | |
301 | ||
302 | int main() { | |
303 | TW_Ioctl tmp; | |
304 | my(sizeof(TW_SG_Entry),"TW_SG_Entry"); | |
305 | my(sizeof(TW_Passthru),"TW_Passthru"); | |
306 | my(sizeof(TW_Ioctl),"TW_Ioctl"); | |
307 | my(sizeof(TW_Output),"TW_Output"); | |
308 | my(sizeof(TW_Ioctl_Driver_Command_9000),"TW_Ioctl_Driver_Command_9000"); | |
309 | my(sizeof(TW_Command_9000),"TW_Command_9000"); | |
310 | my(sizeof(TW_Command_Apache),"TW_Command_Apache"); | |
311 | my(sizeof(TW_Command_Apache_Header),"TW_Command_Apache_Header"); | |
312 | my(sizeof(TW_Command_Full_9000),"TW_Command_Full_9000"); | |
313 | my(sizeof(TW_Ioctl_Buf_Apache),"TW_Ioctl_Buf_Apache"); | |
314 | my(sizeof(TW_Command),"TW_Command"); | |
315 | my(sizeof(TW_New_Ioctl),"TW_New_Ioctl"); | |
316 | printf("TW_Ioctl.table_id - start = %d (irrelevant)\n", | |
317 | (void *)&tmp.table_id - (void *)&tmp); | |
318 | printf("TW_Ioctl.input_data - start = %d (input passthru location)\n", | |
319 | (void *)&tmp.input_data - (void *)&tmp); | |
320 | printf("TW_Ioctl.output_data - start = %d (irrelevant)\n", | |
321 | (void *)&tmp.output_data - (void *)&tmp); | |
322 | return 0; | |
323 | } | |
324 | #endif | |
325 | ||
326 | // The following definitions are from hdreg.h in the kernel source | |
327 | // tree. They don't carry any Copyright statements, but I think they | |
328 | // are primarily from Mark Lord and Andre Hedrick. | |
329 | typedef unsigned char task_ioreg_t; | |
330 | ||
331 | typedef struct hd_drive_task_hdr { | |
332 | task_ioreg_t data; | |
333 | task_ioreg_t feature; | |
334 | task_ioreg_t sector_count; | |
335 | task_ioreg_t sector_number; | |
336 | task_ioreg_t low_cylinder; | |
337 | task_ioreg_t high_cylinder; | |
338 | task_ioreg_t device_head; | |
339 | task_ioreg_t command; | |
340 | } task_struct_t; | |
341 | ||
342 | typedef union ide_reg_valid_s { | |
343 | unsigned all : 16; | |
344 | struct { | |
345 | unsigned data : 1; | |
346 | unsigned error_feature : 1; | |
347 | unsigned sector : 1; | |
348 | unsigned nsector : 1; | |
349 | unsigned lcyl : 1; | |
350 | unsigned hcyl : 1; | |
351 | unsigned select : 1; | |
352 | unsigned status_command : 1; | |
353 | unsigned data_hob : 1; | |
354 | unsigned error_feature_hob : 1; | |
355 | unsigned sector_hob : 1; | |
356 | unsigned nsector_hob : 1; | |
357 | unsigned lcyl_hob : 1; | |
358 | unsigned hcyl_hob : 1; | |
359 | unsigned select_hob : 1; | |
360 | unsigned control_hob : 1; | |
361 | } b; | |
362 | } ide_reg_valid_t; | |
363 | ||
364 | typedef struct ide_task_request_s { | |
365 | task_ioreg_t io_ports[8]; | |
366 | task_ioreg_t hob_ports[8]; | |
367 | ide_reg_valid_t out_flags; | |
368 | ide_reg_valid_t in_flags; | |
369 | int data_phase; | |
370 | int req_cmd; | |
371 | unsigned long out_size; | |
372 | unsigned long in_size; | |
373 | } ide_task_request_t; | |
374 | ||
375 | #define TASKFILE_NO_DATA 0x0000 | |
376 | #define TASKFILE_IN 0x0001 | |
377 | #define TASKFILE_OUT 0x0004 | |
378 | #define HDIO_DRIVE_TASK_HDR_SIZE 8*sizeof(task_ioreg_t) | |
379 | #define IDE_DRIVE_TASK_NO_DATA 0 | |
380 | #define IDE_DRIVE_TASK_IN 2 | |
381 | #define IDE_DRIVE_TASK_OUT 3 | |
382 | #define HDIO_DRIVE_CMD 0x031f | |
383 | #define HDIO_DRIVE_TASK 0x031e | |
384 | #define HDIO_DRIVE_TASKFILE 0x031d | |
385 | #define HDIO_GET_IDENTITY 0x030d | |
386 | ||
4d59bff9 GG |
387 | #define HPTIO_CTL 0x03ff // ioctl interface for HighPoint raid device |
388 | ||
832b75ed | 389 | #endif /* OS_LINUX_H_ */ |