smartmontools SVN Rev 3317
Utility to control and monitor storage systems with "S.M.A.R.T."
os_linux.h
Go to the documentation of this file.
00001 /* 
00002  *  os_linux.h
00003  * 
00004  * Home page of code is: http://smartmontools.sourceforge.net
00005  *
00006  * Copyright (C) 2003-8 Bruce Allen <smartmontools-support@lists.sourceforge.net>
00007  *
00008  * Derived from code that was
00009  *
00010  *  Written By: Adam Radford <linux@3ware.com>
00011  *  Modifications By: Joel Jacobson <linux@3ware.com>
00012  *                    Arnaldo Carvalho de Melo <acme@conectiva.com.br>
00013  *                    Brad Strand <linux@3ware.com>
00014  *
00015  *  Copyright (C) 1999-2003 3ware Inc.
00016  *
00017  *  Kernel compatablity By:     Andre Hedrick <andre@suse.com>
00018  *  Non-Copyright (C) 2000      Andre Hedrick <andre@suse.com>
00019  *
00020  *
00021  * This program is free software; you can redistribute it and/or modify
00022  * it under the terms of the GNU General Public License as published by
00023  * the Free Software Foundation; either version 2, or (at your option)
00024  * any later version.
00025  *
00026  * You should have received a copy of the GNU General Public License
00027  * (for example COPYING); if not, write to the Free Software Foundation,
00028  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00029  *
00030  * This code was originally developed as a Senior Thesis by Michael Cornwell
00031  * at the Concurrent Systems Laboratory (now part of the Storage Systems
00032  * Research Center), Jack Baskin School of Engineering, University of
00033  * California, Santa Cruz. http://ssrc.soe.ucsc.edu/
00034  * 
00035  */
00036 
00037 
00038 #ifndef OS_LINUX_H_
00039 #define OS_LINUX_H_
00040 
00041 #define OS_LINUX_H_CVSID "$Id: os_linux.h 3728 2012-12-13 17:57:50Z chrfranke $\n"
00042 
00043 /* 
00044    The following definitions/macros/prototypes are used for three
00045    different interfaces, referred to as "the three cases" below.
00046    CONTROLLER_3WARE_678K      -- 6000, 7000, and 8000 controllers via /dev/sd?
00047    CONTROLLER_3WARE_678K_CHAR -- 6000, 7000, and 8000 controllers via /dev/twe?
00048    CONTROLLER_3WARE_9000_CHAR -- 9000 controllers via /dev/twa?
00049 */
00050 
00051 // USED FOR ALL THREE CASES
00052 
00053 #define u32 unsigned int
00054 #define TW_OP_ATA_PASSTHRU 0x11
00055 #define MAX(x,y) ( (x)>(y)?(x):(y) )
00056 
00057 #pragma pack(1)
00058 /* Scatter gather list entry */
00059 typedef struct TAG_TW_SG_Entry {
00060   unsigned int address;
00061   unsigned int length;
00062 } TW_SG_Entry;
00063 
00064 /* Command header for ATA pass-thru.  Note that for different
00065    drivers/interfaces the length of sg_list (here TW_ATA_PASS_SGL_MAX)
00066    is different.  But it can be taken as same for all three cases
00067    because it's never used to define any other structures, and we
00068    never use anything in the sg_list or beyond! */
00069 
00070 #define TW_ATA_PASS_SGL_MAX      60
00071 
00072 typedef struct TAG_TW_Passthru {
00073   struct {
00074     unsigned char opcode:5;
00075     unsigned char sgloff:3;
00076   } byte0;
00077   unsigned char size;
00078   unsigned char request_id;
00079   unsigned char unit;
00080   unsigned char status;  // On return, contains 3ware STATUS register
00081   unsigned char flags;
00082   unsigned short param;
00083   unsigned short features;  // On return, contains ATA ERROR register
00084   unsigned short sector_count;
00085   unsigned short sector_num;
00086   unsigned short cylinder_lo;
00087   unsigned short cylinder_hi;
00088   unsigned char drive_head;
00089   unsigned char command; // On return, contains ATA STATUS register
00090   TW_SG_Entry sg_list[TW_ATA_PASS_SGL_MAX];
00091   unsigned char padding[12];
00092 } TW_Passthru;
00093 
00094 // the following are for the SCSI interface only 
00095 
00096 // Ioctl buffer: Note that this defn has changed in kernel tree...
00097 // Total size is 1041 bytes -- this is really weird
00098 
00099 #define TW_IOCTL                 0x80
00100 #define TW_ATA_PASSTHRU          0x1e
00101 
00102 // Adam -- should this be #pramga packed? Otherwise table_id gets
00103 // moved for byte alignment.  Without packing, input passthru for SCSI
00104 // ioctl is 31 bytes in.  With packing it is 30 bytes in.
00105 typedef struct TAG_TW_Ioctl { 
00106   int input_length;
00107   int output_length;
00108   unsigned char cdb[16];
00109   unsigned char opcode;
00110   // This one byte of padding is missing from the typedefs in the
00111   // kernel code, but it is indeed present.  We put it explicitly
00112   // here, so that the structure can be packed.  Adam agrees with
00113   // this.
00114   unsigned char packing;
00115   unsigned short table_id;
00116   unsigned char parameter_id;
00117   unsigned char parameter_size_bytes;
00118   unsigned char unit_index;
00119   // Size up to here is 30 bytes + 1 padding!
00120   unsigned char input_data[499];
00121   // Reserve lots of extra space for commands that set Sector Count
00122   // register to large values
00123   unsigned char output_data[512]; // starts 530 bytes in!
00124   // two more padding bytes here if structure NOT packed.
00125 } TW_Ioctl;
00126 
00127 /* Ioctl buffer output -- SCSI interface only! */
00128 typedef struct TAG_TW_Output {
00129   int padding[2];
00130   char output_data[512];
00131 } TW_Output; 
00132 
00133 // What follows is needed for 9000 char interface only
00134 
00135 #define TW_IOCTL_FIRMWARE_PASS_THROUGH 0x108
00136 #define TW_MAX_SGL_LENGTH_9000 61
00137 
00138 typedef struct TAG_TW_Ioctl_Driver_Command_9000 {
00139   unsigned int control_code;
00140   unsigned int status;
00141   unsigned int unique_id;
00142   unsigned int sequence_id;
00143   unsigned int os_specific;
00144   unsigned int buffer_length;
00145 } TW_Ioctl_Driver_Command_9000;
00146 
00147 /* Command Packet */
00148 typedef struct TW_Command_9000 {
00149   /* First DWORD */
00150   struct {
00151     unsigned char opcode:5;
00152     unsigned char sgl_offset:3;
00153   } byte0;
00154   unsigned char size;
00155   unsigned char request_id;
00156   struct {
00157     unsigned char unit:4;
00158     unsigned char host_id:4;
00159   } byte3;
00160   /* Second DWORD */
00161   unsigned char status;
00162   unsigned char flags;
00163   union {
00164     unsigned short block_count;
00165     unsigned short parameter_count;
00166     unsigned short message_credits;
00167   } byte6;
00168   union {
00169     struct {
00170       u32 lba;
00171       TW_SG_Entry sgl[TW_MAX_SGL_LENGTH_9000];
00172       u32 padding;
00173     } io;
00174     struct {
00175       TW_SG_Entry sgl[TW_MAX_SGL_LENGTH_9000];
00176       u32 padding[2];
00177     } param;
00178     struct {
00179       u32 response_queue_pointer;
00180       u32 padding[125]; /* pad entire structure to 512 bytes */
00181     } init_connection;
00182     struct {
00183       char version[504];
00184     } ioctl_miniport_version;
00185   } byte8;
00186 } TW_Command_9000;
00187 
00188 /* Command Packet for 9000+ controllers */
00189 typedef struct TAG_TW_Command_Apache {
00190   struct {
00191     unsigned char opcode:5;
00192     unsigned char reserved:3;
00193   } command;
00194   unsigned char   unit;
00195   unsigned short  request_id;
00196   unsigned char   sense_length;
00197   unsigned char   sgl_offset;
00198   unsigned short  sgl_entries;
00199   unsigned char   cdb[16];
00200   TW_SG_Entry     sg_list[TW_MAX_SGL_LENGTH_9000];
00201 } TW_Command_Apache;
00202 
00203 /* New command packet header */
00204 typedef struct TAG_TW_Command_Apache_Header {
00205   unsigned char sense_data[18];
00206   struct {
00207     char reserved[4];
00208     unsigned short error;
00209     unsigned char status;
00210     struct {
00211       unsigned char severity:3;
00212       unsigned char reserved:5;
00213     } substatus_block;
00214   } status_block;
00215   unsigned char err_specific_desc[102];
00216 } TW_Command_Apache_Header;
00217 
00218 /* This struct is a union of the 2 command packets */
00219 typedef struct TAG_TW_Command_Full_9000 {
00220   TW_Command_Apache_Header header;
00221   union {
00222     TW_Command_9000   oldcommand;
00223     TW_Command_Apache newcommand;
00224   } command;
00225   unsigned char padding[384]; /* Pad to 1024 bytes */
00226 } TW_Command_Full_9000;
00227 
00228 typedef struct TAG_TW_Ioctl_Apache {
00229   TW_Ioctl_Driver_Command_9000 driver_command;
00230   char                         padding[488];
00231   TW_Command_Full_9000         firmware_command;
00232   char                         data_buffer[1];
00233   // three bytes of padding here if structure not packed!
00234 } TW_Ioctl_Buf_Apache;
00235 
00236 
00237 
00238 // START OF DEFINITIONS FOR THE CHARACTER INTERFACE TO THE
00239 // 6000/7000/8000 drivers
00240 
00241 #define TW_MAX_SGL_LENGTH        62
00242 #define TW_CMD_PACKET_WITH_DATA 0x1f
00243 
00244 /* Command Packet */
00245 typedef struct TW_Command {
00246   /* First DWORD */
00247   struct {
00248     unsigned char opcode:5;
00249     unsigned char sgl_offset:3;
00250   } byte0;
00251   unsigned char size;
00252   unsigned char request_id;
00253   struct {
00254     unsigned char unit:4;
00255     unsigned char host_id:4;
00256   } byte3;
00257   /* Second DWORD */
00258   unsigned char status;
00259   unsigned char flags;
00260   union {
00261     unsigned short block_count;
00262     unsigned short parameter_count;
00263     unsigned short message_credits;
00264   } byte6;
00265   union {
00266     struct {
00267       u32 lba;
00268       TW_SG_Entry sgl[TW_MAX_SGL_LENGTH];
00269       u32 padding;      /* pad to 512 bytes */
00270     } io;
00271     struct {
00272       TW_SG_Entry sgl[TW_MAX_SGL_LENGTH];
00273       u32 padding[2];
00274     } param;
00275     struct {
00276       u32 response_queue_pointer;
00277       u32 padding[125];
00278     } init_connection;
00279     struct {
00280       char version[504];
00281     } ioctl_miniport_version;
00282   } byte8;
00283 } TW_Command;
00284 
00285 typedef struct TAG_TW_New_Ioctl {
00286   unsigned int  data_buffer_length;
00287   unsigned char padding [508];
00288   TW_Command    firmware_command;
00289   char          data_buffer[1];
00290   // three bytes of padding here
00291 } TW_New_Ioctl;
00292 #pragma pack()
00293 
00294 #if 0
00295 // Useful for checking/understanding packing of 3ware data structures
00296 // above.
00297 void my(int x, char *y){
00298   printf("The size of %30s is: %5d\n",y, x);
00299   return;
00300 }
00301 
00302 int main() {
00303   TW_Ioctl tmp;
00304   my(sizeof(TW_SG_Entry),"TW_SG_Entry");
00305   my(sizeof(TW_Passthru),"TW_Passthru");
00306   my(sizeof(TW_Ioctl),"TW_Ioctl");
00307   my(sizeof(TW_Output),"TW_Output");
00308   my(sizeof(TW_Ioctl_Driver_Command_9000),"TW_Ioctl_Driver_Command_9000");
00309   my(sizeof(TW_Command_9000),"TW_Command_9000");
00310   my(sizeof(TW_Command_Apache),"TW_Command_Apache");
00311   my(sizeof(TW_Command_Apache_Header),"TW_Command_Apache_Header");
00312   my(sizeof(TW_Command_Full_9000),"TW_Command_Full_9000");
00313   my(sizeof(TW_Ioctl_Buf_Apache),"TW_Ioctl_Buf_Apache");
00314   my(sizeof(TW_Command),"TW_Command");
00315   my(sizeof(TW_New_Ioctl),"TW_New_Ioctl");                                                                
00316   printf("TW_Ioctl.table_id - start = %d (irrelevant)\n",
00317          (void *)&tmp.table_id - (void *)&tmp);
00318   printf("TW_Ioctl.input_data - start = %d (input passthru location)\n",
00319          (void *)&tmp.input_data - (void *)&tmp);
00320   printf("TW_Ioctl.output_data - start = %d (irrelevant)\n",
00321          (void *)&tmp.output_data - (void *)&tmp);
00322   return 0;
00323 }
00324 #endif
00325 
00326 // The following definitions are from hdreg.h in the kernel source
00327 // tree.  They don't carry any Copyright statements, but I think they
00328 // are primarily from Mark Lord and Andre Hedrick.
00329 typedef unsigned char task_ioreg_t;
00330 
00331 typedef struct hd_drive_task_hdr {
00332   task_ioreg_t data;
00333   task_ioreg_t feature;
00334   task_ioreg_t sector_count;
00335   task_ioreg_t sector_number;
00336   task_ioreg_t low_cylinder;
00337   task_ioreg_t high_cylinder;
00338   task_ioreg_t device_head;
00339   task_ioreg_t command;
00340 } task_struct_t;
00341 
00342 typedef union ide_reg_valid_s {
00343   unsigned all                  : 16;
00344   struct {
00345     unsigned data               : 1;
00346     unsigned error_feature      : 1;
00347     unsigned sector             : 1;
00348     unsigned nsector            : 1;
00349     unsigned lcyl               : 1;
00350     unsigned hcyl               : 1;
00351     unsigned select             : 1;
00352     unsigned status_command     : 1;
00353     unsigned data_hob           : 1;
00354     unsigned error_feature_hob  : 1;
00355     unsigned sector_hob         : 1;
00356     unsigned nsector_hob        : 1;
00357     unsigned lcyl_hob           : 1;
00358     unsigned hcyl_hob           : 1;
00359     unsigned select_hob         : 1;
00360     unsigned control_hob        : 1;
00361   } b;
00362 } ide_reg_valid_t;
00363 
00364 typedef struct ide_task_request_s {
00365   task_ioreg_t     io_ports[8];
00366   task_ioreg_t     hob_ports[8];
00367   ide_reg_valid_t  out_flags;
00368   ide_reg_valid_t  in_flags;
00369   int              data_phase;
00370   int              req_cmd;
00371   unsigned long    out_size;
00372   unsigned long    in_size;
00373 } ide_task_request_t;
00374 
00375 #define TASKFILE_NO_DATA          0x0000
00376 #define TASKFILE_IN               0x0001
00377 #define TASKFILE_OUT              0x0004
00378 #define HDIO_DRIVE_TASK_HDR_SIZE  8*sizeof(task_ioreg_t)
00379 #define IDE_DRIVE_TASK_NO_DATA         0
00380 #define IDE_DRIVE_TASK_IN              2
00381 #define IDE_DRIVE_TASK_OUT             3
00382 #define HDIO_DRIVE_CMD            0x031f
00383 #define HDIO_DRIVE_TASK           0x031e
00384 #define HDIO_DRIVE_TASKFILE       0x031d
00385 #define HDIO_GET_IDENTITY         0x030d
00386 
00387 #define HPTIO_CTL                       0x03ff // ioctl interface for HighPoint raid device
00388 
00389 #endif /* OS_LINUX_H_ */