1 /*
2  * megaraid.h
3  *
4  * Home page of code is: http://www.smartmontools.org
5  *
6  * Copyright (C) 2008 Jordan Hargrave
7  *
8  * SPDX-License-Identifier: GPL-2.0-or-later
9  */
10 
11 int megaraid_io_interface(int device, int target, struct scsi_cmnd_io *, int);
12 
13 #undef u32
14 
15 #define u8  uint8_t
16 #define u16 uint16_t
17 #define u32 uint32_t
18 #define u64 uint64_t
19 
20 /*======================================================
21 * PERC2/3/4 Passthrough SCSI Command Interface
22 *
23 * Contents from:
24 *  drivers/scsi/megaraid/megaraid_ioctl.h
25 *  drivers/scsi/megaraid/mbox_defs.h
26 *======================================================*/
27 #define MEGAIOC_MAGIC   'm'
28 #define MEGAIOCCMD      _IOWR(MEGAIOC_MAGIC, 0, struct uioctl_t)
29 
30 /* Following subopcode work for opcode == 0x82 */
31 #define MKADAP(adapno)   (MEGAIOC_MAGIC << 8 | adapno)
32 #define MEGAIOC_QNADAP     'm'
33 #define MEGAIOC_QDRVRVER   'e'
34 #define MEGAIOC_QADAPINFO  'g'
35 
36 #define MEGA_MBOXCMD_PASSTHRU 0x03
37 
38 #define MAX_REQ_SENSE_LEN  0x20
39 #define MAX_CDB_LEN 10
40 
41 typedef struct
42 {
43   uint8_t  timeout : 3;
44   uint8_t  ars : 1;
45   uint8_t  reserved : 3;
46   uint8_t  islogical : 1;
47   uint8_t  logdrv;
48   uint8_t  channel;
49   uint8_t  target;
50   uint8_t  queuetag;
51   uint8_t  queueaction;
52   uint8_t  cdb[MAX_CDB_LEN];
53   uint8_t  cdblen;
54   uint8_t  reqsenselen;
55   uint8_t  reqsensearea[MAX_REQ_SENSE_LEN];
56   uint8_t  numsgelements;
57   uint8_t  scsistatus;
58   uint32_t dataxferaddr;
59   uint32_t dataxferlen;
60 } __attribute__((packed)) mega_passthru;
61 
62 typedef struct
63 {
64   uint8_t   cmd;
65   uint8_t   cmdid;
66   uint8_t   opcode;
67   uint8_t   subopcode;
68   uint32_t  lba;
69   uint32_t  xferaddr;
70   uint8_t   logdrv;
71   uint8_t   resvd[3];
72   uint8_t   numstatus;
73   uint8_t   status;
74 } __attribute__((packed)) megacmd_t;
75 
76 typedef union {
77   uint8_t   *pointer;
78   uint8_t    pad[8];
79 } ptr_t;
80 
81 // The above definition assumes sizeof(void*) <= 8.
82 // This assumption also exists in the linux megaraid device driver.
83 // So define a macro to check expected size of ptr_t at compile time using
84 // a dummy typedef.  On size mismatch, compiler reports a negative array
85 // size.  If you see an error message of this form, it means that
86 // you have an unexpected pointer size on your platform and can not
87 // use megaraid support in smartmontools.
88 typedef char assert_sizeof_ptr_t[sizeof(ptr_t) == 8 ? 1 : -1];
89 
90 struct uioctl_t
91 {
92   uint32_t       inlen;
93   uint32_t       outlen;
94   union {
95     uint8_t      fca[16];
96     struct {
97       uint8_t  opcode;
98       uint8_t  subopcode;
99       uint16_t adapno;
100       ptr_t    buffer;
101       uint32_t length;
102     } __attribute__((packed)) fcs;
103   } __attribute__((packed)) ui;
104 
105   megacmd_t     mbox;
106   mega_passthru pthru;
107   ptr_t         data;
108 } __attribute__((packed));
109 
110 /*===================================================
111 * PERC5/6 Passthrough SCSI Command Interface
112 *
113 * Contents from:
114 *  drivers/scsi/megaraid/megaraid_sas.h
115 *===================================================*/
116 #define MEGASAS_MAGIC          'M'
117 #define MEGASAS_IOC_FIRMWARE   _IOWR(MEGASAS_MAGIC, 1, struct megasas_iocpacket)
118 
119 #define MFI_CMD_PD_SCSI_IO        0x04
120 #define MFI_CMD_DCMD              0x05
121 #define MFI_FRAME_SGL64           0x02
122 #define MFI_STAT_OK               0x00
123 #define MFI_DCMD_PD_GET_LIST      0x02010000
124 /*
125 * Number of mailbox bytes in DCMD message frame
126 */
127 #define MFI_MBOX_SIZE             12
128 #define MAX_IOCTL_SGE             16
129 #define MFI_FRAME_DIR_NONE        0x0000
130 #define MFI_FRAME_DIR_WRITE       0x0008
131 #define MFI_FRAME_DIR_READ        0x0010
132 #define MFI_FRAME_DIR_BOTH        0x0018
133 
134 #define MAX_SYS_PDS               240
135 
136 struct megasas_sge32 {
137 
138   u32 phys_addr;
139   u32 length;
140 
141 } __attribute__ ((packed));
142 
143 struct megasas_sge64 {
144 
145   u64 phys_addr;
146   u32 length;
147 
148 } __attribute__ ((packed));
149 
150 union megasas_sgl {
151 
152   struct megasas_sge32 sge32[1];
153   struct megasas_sge64 sge64[1];
154 
155 } __attribute__ ((packed));
156 
157 struct megasas_header {
158 
159   u8 cmd;           /*00h */
160   u8 sense_len;     /*01h */
161   u8 cmd_status;    /*02h */
162   u8 scsi_status;   /*03h */
163 
164   u8 target_id;     /*04h */
165   u8 lun;           /*05h */
166   u8 cdb_len;       /*06h */
167   u8 sge_count;     /*07h */
168 
169   u32 context;      /*08h */
170   u32 pad_0;        /*0Ch */
171 
172   u16 flags;        /*10h */
173   u16 timeout;      /*12h */
174   u32 data_xferlen; /*14h */
175 
176 } __attribute__ ((packed));
177 
178 struct megasas_pthru_frame {
179 
180   u8 cmd;            /*00h */
181   u8 sense_len;      /*01h */
182   u8 cmd_status;     /*02h */
183   u8 scsi_status;    /*03h */
184 
185   u8 target_id;      /*04h */
186   u8 lun;            /*05h */
187   u8 cdb_len;        /*06h */
188   u8 sge_count;      /*07h */
189 
190   u32 context;       /*08h */
191   u32 pad_0;         /*0Ch */
192 
193   u16 flags;         /*10h */
194   u16 timeout;       /*12h */
195   u32 data_xfer_len; /*14h */
196 
197   u32 sense_buf_phys_addr_lo; /*18h */
198   u32 sense_buf_phys_addr_hi; /*1Ch */
199 
200   u8 cdb[16];            /*20h */
201   union megasas_sgl sgl; /*30h */
202 
203 } __attribute__ ((packed));
204 
205 struct megasas_dcmd_frame {
206 
207   u8 cmd;            /*00h */
208   u8 reserved_0;     /*01h */
209   u8 cmd_status;     /*02h */
210   u8 reserved_1[4];  /*03h */
211   u8 sge_count;      /*07h */
212 
213   u32 context;       /*08h */
214   u32 pad_0;         /*0Ch */
215 
216   u16 flags;         /*10h */
217   u16 timeout;  /*12h */
218 
219   u32 data_xfer_len; /*14h */
220   u32 opcode;  /*18h */
221 
222   union {   /*1Ch */
223     u8 b[12];
224     u16 s[6];
225     u32 w[3];
226   } mbox;
227 
228   union megasas_sgl sgl; /*28h */
229 
230 } __attribute__ ((packed));
231 
232 struct megasas_iocpacket {
233   u16 host_no;
234   u16 __pad1;
235   u32 sgl_off;
236   u32 sge_count;
237   u32 sense_off;
238   u32 sense_len;
239   union {
240     u8 raw[128];
241     struct megasas_header hdr;
242     struct megasas_pthru_frame pthru;
243     struct megasas_dcmd_frame dcmd;
244   } frame;
245 
246   struct iovec sgl[MAX_IOCTL_SGE];
247 } __attribute__ ((packed));
248 
249 struct megasas_pd_address {
250   u16 device_id;
251   u16 encl_device_id;
252   u8 encl_index;
253   u8 slot_number;
254   u8 scsi_dev_type; /* 0 = disk */
255   u8 connect_port_bitmap;
256   u64 sas_addr[2];
257 }   __attribute__ ((packed));
258 
259 struct megasas_pd_list {
260   u32 size;
261   u32 count;
262   struct megasas_pd_address addr[MAX_SYS_PDS];
263 } __attribute__ ((packed));
264 
265 #undef u8
266 #undef u16
267 #undef u32
268 #undef u64
269 
270