mirror of
https://git.proxmox.com/git/mirror_smartmontools-debian
synced 2025-04-29 20:36:43 +00:00

Downloaded source from https://sourceforge.net/projects/smartmontools/files/smartmontools/7.0/ and imported here to git. Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
376 lines
11 KiB
C
376 lines
11 KiB
C
/*
|
|
* 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_ */
|