Official read only mirror of the smartmontools project SVN https://www.smartmontools.org/browser
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
smartmontools/smartmontools/os_linux.h

375 lines
10 KiB

/*
* 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$\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_ */