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 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
|
/*
* os_linux.h
*
* Home page of code is: http://www.smartmontools.org
*
* Copyright (C) 2003-8 Bruce Allen
*
* Derived from code that was
*
* Written By: Adam Radford <linux@3ware.com>
* Modifications By: Joel Jacobson <linux@3ware.com>
* Arnaldo Carvalho de Melo <acme@conectiva.com.br>
* Brad Strand <linux@3ware.com>
*
* Copyright (C) 1999-2003 3ware Inc.
*
* Kernel compatibility By: Andre Hedrick <andre@suse.com>
* Non-Copyright (C) 2000 Andre Hedrick <andre@suse.com>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef OS_LINUX_H_
#define OS_LINUX_H_
#define OS_LINUX_H_CVSID "$Id: os_linux.h 4842 2018-12-02 16:07:26Z chrfranke $\n"
/*
The following definitions/macros/prototypes are used for three
different interfaces, referred to as "the three cases" below.
CONTROLLER_3WARE_678K -- 6000, 7000, and 8000 controllers via /dev/sd?
CONTROLLER_3WARE_678K_CHAR -- 6000, 7000, and 8000 controllers via /dev/twe?
CONTROLLER_3WARE_9000_CHAR -- 9000 controllers via /dev/twa?
*/
// USED FOR ALL THREE CASES
#define u32 unsigned int
#define TW_OP_ATA_PASSTHRU 0x11
#define MAX(x,y) ( (x)>(y)?(x):(y) )
#pragma pack(1)
/* Scatter gather list entry */
typedef struct TAG_TW_SG_Entry {
unsigned int address;
unsigned int length;
} TW_SG_Entry;
/* Command header for ATA pass-thru. Note that for different
drivers/interfaces the length of sg_list (here TW_ATA_PASS_SGL_MAX)
is different. But it can be taken as same for all three cases
because it's never used to define any other structures, and we
never use anything in the sg_list or beyond! */
#define TW_ATA_PASS_SGL_MAX 60
typedef struct TAG_TW_Passthru {
struct {
unsigned char opcode:5;
unsigned char sgloff:3;
} byte0;
unsigned char size;
unsigned char request_id;
unsigned char unit;
unsigned char status; // On return, contains 3ware STATUS register
unsigned char flags;
unsigned short param;
unsigned short features; // On return, contains ATA ERROR register
unsigned short sector_count;
unsigned short sector_num;
unsigned short cylinder_lo;
unsigned short cylinder_hi;
unsigned char drive_head;
unsigned char command; // On return, contains ATA STATUS register
TW_SG_Entry sg_list[TW_ATA_PASS_SGL_MAX];
unsigned char padding[12];
} TW_Passthru;
// the following are for the SCSI interface only
// Ioctl buffer: Note that this defn has changed in kernel tree...
// Total size is 1041 bytes -- this is really weird
#define TW_IOCTL 0x80
#define TW_ATA_PASSTHRU 0x1e
// Adam -- should this be #pramga packed? Otherwise table_id gets
// moved for byte alignment. Without packing, input passthru for SCSI
// ioctl is 31 bytes in. With packing it is 30 bytes in.
typedef struct TAG_TW_Ioctl {
int input_length;
int output_length;
unsigned char cdb[16];
unsigned char opcode;
// This one byte of padding is missing from the typedefs in the
// kernel code, but it is indeed present. We put it explicitly
// here, so that the structure can be packed. Adam agrees with
// this.
unsigned char packing;
unsigned short table_id;
unsigned char parameter_id;
unsigned char parameter_size_bytes;
unsigned char unit_index;
// Size up to here is 30 bytes + 1 padding!
unsigned char input_data[499];
// Reserve lots of extra space for commands that set Sector Count
// register to large values
unsigned char output_data[512]; // starts 530 bytes in!
// two more padding bytes here if structure NOT packed.
} TW_Ioctl;
/* Ioctl buffer output -- SCSI interface only! */
typedef struct TAG_TW_Output {
int padding[2];
char output_data[512];
} TW_Output;
// What follows is needed for 9000 char interface only
#define TW_IOCTL_FIRMWARE_PASS_THROUGH 0x108
#define TW_MAX_SGL_LENGTH_9000 61
typedef struct TAG_TW_Ioctl_Driver_Command_9000 {
unsigned int control_code;
unsigned int status;
unsigned int unique_id;
unsigned int sequence_id;
unsigned int os_specific;
unsigned int buffer_length;
} TW_Ioctl_Driver_Command_9000;
/* Command Packet */
typedef struct TW_Command_9000 {
/* First DWORD */
struct {
unsigned char opcode:5;
unsigned char sgl_offset:3;
} byte0;
unsigned char size;
unsigned char request_id;
struct {
unsigned char unit:4;
unsigned char host_id:4;
} byte3;
/* Second DWORD */
unsigned char status;
unsigned char flags;
union {
unsigned short block_count;
unsigned short parameter_count;
unsigned short message_credits;
} byte6;
union {
struct {
u32 lba;
TW_SG_Entry sgl[TW_MAX_SGL_LENGTH_9000];
u32 padding;
} io;
struct {
TW_SG_Entry sgl[TW_MAX_SGL_LENGTH_9000];
u32 padding[2];
} param;
struct {
u32 response_queue_pointer;
u32 padding[125]; /* pad entire structure to 512 bytes */
} init_connection;
struct {
char version[504];
} ioctl_miniport_version;
} byte8;
} TW_Command_9000;
/* Command Packet for 9000+ controllers */
typedef struct TAG_TW_Command_Apache {
struct {
unsigned char opcode:5;
unsigned char reserved:3;
} command;
unsigned char unit;
unsigned short request_id;
unsigned char sense_length;
unsigned char sgl_offset;
unsigned short sgl_entries;
unsigned char cdb[16];
TW_SG_Entry sg_list[TW_MAX_SGL_LENGTH_9000];
} TW_Command_Apache;
/* New command packet header */
typedef struct TAG_TW_Command_Apache_Header {
unsigned char sense_data[18];
struct {
char reserved[4];
unsigned short error;
unsigned char status;
struct {
unsigned char severity:3;
unsigned char reserved:5;
} substatus_block;
} status_block;
unsigned char err_specific_desc[102];
} TW_Command_Apache_Header;
/* This struct is a union of the 2 command packets */
typedef struct TAG_TW_Command_Full_9000 {
TW_Command_Apache_Header header;
union {
TW_Command_9000 oldcommand;
TW_Command_Apache newcommand;
} command;
unsigned char padding[384]; /* Pad to 1024 bytes */
} TW_Command_Full_9000;
typedef struct TAG_TW_Ioctl_Apache {
TW_Ioctl_Driver_Command_9000 driver_command;
char padding[488];
TW_Command_Full_9000 firmware_command;
char data_buffer[1];
// three bytes of padding here if structure not packed!
} TW_Ioctl_Buf_Apache;
// START OF DEFINITIONS FOR THE CHARACTER INTERFACE TO THE
// 6000/7000/8000 drivers
#define TW_MAX_SGL_LENGTH 62
#define TW_CMD_PACKET_WITH_DATA 0x1f
/* Command Packet */
typedef struct TW_Command {
/* First DWORD */
struct {
unsigned char opcode:5;
unsigned char sgl_offset:3;
} byte0;
unsigned char size;
unsigned char request_id;
struct {
unsigned char unit:4;
unsigned char host_id:4;
} byte3;
/* Second DWORD */
unsigned char status;
unsigned char flags;
union {
unsigned short block_count;
unsigned short parameter_count;
unsigned short message_credits;
} byte6;
union {
struct {
u32 lba;
TW_SG_Entry sgl[TW_MAX_SGL_LENGTH];
u32 padding; /* pad to 512 bytes */
} io;
struct {
TW_SG_Entry sgl[TW_MAX_SGL_LENGTH];
u32 padding[2];
} param;
struct {
u32 response_queue_pointer;
u32 padding[125];
} init_connection;
struct {
char version[504];
} ioctl_miniport_version;
} byte8;
} TW_Command;
typedef struct TAG_TW_New_Ioctl {
unsigned int data_buffer_length;
unsigned char padding [508];
TW_Command firmware_command;
char data_buffer[1];
// three bytes of padding here
} TW_New_Ioctl;
#pragma pack()
#if 0
// Useful for checking/understanding packing of 3ware data structures
// above.
void my(int x, char *y){
printf("The size of %30s is: %5d\n",y, x);
return;
}
int main() {
TW_Ioctl tmp;
my(sizeof(TW_SG_Entry),"TW_SG_Entry");
my(sizeof(TW_Passthru),"TW_Passthru");
my(sizeof(TW_Ioctl),"TW_Ioctl");
my(sizeof(TW_Output),"TW_Output");
my(sizeof(TW_Ioctl_Driver_Command_9000),"TW_Ioctl_Driver_Command_9000");
my(sizeof(TW_Command_9000),"TW_Command_9000");
my(sizeof(TW_Command_Apache),"TW_Command_Apache");
my(sizeof(TW_Command_Apache_Header),"TW_Command_Apache_Header");
my(sizeof(TW_Command_Full_9000),"TW_Command_Full_9000");
my(sizeof(TW_Ioctl_Buf_Apache),"TW_Ioctl_Buf_Apache");
my(sizeof(TW_Command),"TW_Command");
my(sizeof(TW_New_Ioctl),"TW_New_Ioctl");
printf("TW_Ioctl.table_id - start = %d (irrelevant)\n",
(void *)&tmp.table_id - (void *)&tmp);
printf("TW_Ioctl.input_data - start = %d (input passthru location)\n",
(void *)&tmp.input_data - (void *)&tmp);
printf("TW_Ioctl.output_data - start = %d (irrelevant)\n",
(void *)&tmp.output_data - (void *)&tmp);
return 0;
}
#endif
// The following definitions are from hdreg.h in the kernel source
// tree. They don't carry any Copyright statements, but I think they
// are primarily from Mark Lord and Andre Hedrick.
typedef unsigned char task_ioreg_t;
typedef struct hd_drive_task_hdr {
task_ioreg_t data;
task_ioreg_t feature;
task_ioreg_t sector_count;
task_ioreg_t sector_number;
task_ioreg_t low_cylinder;
task_ioreg_t high_cylinder;
task_ioreg_t device_head;
task_ioreg_t command;
} task_struct_t;
typedef union ide_reg_valid_s {
unsigned all : 16;
struct {
unsigned data : 1;
unsigned error_feature : 1;
unsigned sector : 1;
unsigned nsector : 1;
unsigned lcyl : 1;
unsigned hcyl : 1;
unsigned select : 1;
unsigned status_command : 1;
unsigned data_hob : 1;
unsigned error_feature_hob : 1;
unsigned sector_hob : 1;
unsigned nsector_hob : 1;
unsigned lcyl_hob : 1;
unsigned hcyl_hob : 1;
unsigned select_hob : 1;
unsigned control_hob : 1;
} b;
} ide_reg_valid_t;
typedef struct ide_task_request_s {
task_ioreg_t io_ports[8];
task_ioreg_t hob_ports[8];
ide_reg_valid_t out_flags;
ide_reg_valid_t in_flags;
int data_phase;
int req_cmd;
unsigned long out_size;
unsigned long in_size;
} ide_task_request_t;
#define TASKFILE_NO_DATA 0x0000
#define TASKFILE_IN 0x0001
#define TASKFILE_OUT 0x0004
#define HDIO_DRIVE_TASK_HDR_SIZE 8*sizeof(task_ioreg_t)
#define IDE_DRIVE_TASK_NO_DATA 0
#define IDE_DRIVE_TASK_IN 2
#define IDE_DRIVE_TASK_OUT 3
#define HDIO_DRIVE_CMD 0x031f
#define HDIO_DRIVE_TASK 0x031e
#define HDIO_DRIVE_TASKFILE 0x031d
#define HDIO_GET_IDENTITY 0x030d
#define HPTIO_CTL 0x03ff // ioctl interface for HighPoint raid device
#endif /* OS_LINUX_H_ */
|