xref: /freebsd/sys/dev/mlx/mlxreg.h (revision 5129159789cc9d7bc514e4546b88e3427695002d)
1 /*-
2  * Copyright (c) 1999 Michael Smith
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  *	$FreeBSD$
27  */
28 
29 #define MLX_CFG_BASE0   0x10		/* first region */
30 #define MLX_CFG_BASE1   0x14		/* second region (type 3 only) */
31 
32 #define MLX_BLKSIZE	512		/* fixed feature */
33 
34 /*
35  * Selected command codes.
36  */
37 #define MLX_CMD_ENQUIRY		0x53
38 #define MLX_CMD_ENQUIRY2	0x1c
39 #define MLX_CMD_ENQSYSDRIVE	0x19
40 #define MLX_CMD_READOLDSG	0xb6
41 #define MLX_CMD_WRITEOLDSG	0xb7
42 #define MLX_CMD_FLUSH		0x0a
43 #define MLX_CMD_LOGOP		0x72
44 #define MLX_CMD_REBUILDASYNC	0x16
45 #define MLX_CMD_CHECKASYNC	0x1e
46 #define MLX_CMD_REBUILDSTAT	0x0c
47 #define MLX_CMD_STOPCHANNEL	0x13
48 #define MLX_CMD_STARTCHANNEL	0x12
49 
50 /*
51  * Status values.
52  */
53 #define MLX_STATUS_OK		0x0000
54 #define MLX_STATUS_RDWROFFLINE	0x0002	/* read/write claims drive is offline */
55 #define MLX_STATUS_WEDGED	0xdead	/* controller not listening */
56 #define MLX_STATUS_LOST		0xbeef	/* never came back */
57 #define MLX_STATUS_BUSY		0xffff	/* command is in controller */
58 
59 /*
60  * Accessor defines for the V3 interface.
61  */
62 #define MLX_V3_MAILBOX		0x00
63 #define	MLX_V3_STATUS_IDENT	0x0d
64 #define MLX_V3_STATUS		0x0e
65 #define MLX_V3_IDBR		0x40
66 #define MLX_V3_ODBR		0x41
67 #define MLX_V3_IER		0x43
68 
69 #define MLX_V3_PUT_MAILBOX(sc, idx, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V3_MAILBOX + idx, val)
70 #define MLX_V3_GET_STATUS_IDENT(sc)	 bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V3_STATUS_IDENT)
71 #define MLX_V3_GET_STATUS(sc)		 bus_space_read_2 (sc->mlx_btag, sc->mlx_bhandle, MLX_V3_STATUS)
72 #define MLX_V3_GET_IDBR(sc)		 bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V3_IDBR)
73 #define MLX_V3_PUT_IDBR(sc, val)	 bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V3_IDBR, val)
74 #define MLX_V3_GET_ODBR(sc)		 bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V3_ODBR)
75 #define MLX_V3_PUT_ODBR(sc, val)	 bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V3_ODBR, val)
76 #define MLX_V3_PUT_IER(sc, val)		 bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V3_IER, val)
77 
78 #define MLX_V3_IDB_FULL		(1<<0)		/* mailbox is full */
79 #define MLX_V3_IDB_SACK		(1<<1)		/* acknowledge status read */
80 
81 #define MLX_V3_ODB_SAVAIL	(1<<0)		/* status is available */
82 
83 /*
84  * Accessor defines for the V4 interface.
85  */
86 #define MLX_V4_MAILBOX		0x1000
87 #define	MLX_V4_STATUS_IDENT	0x1018
88 #define MLX_V4_STATUS		0x101a
89 #define MLX_V4_IDBR		0x0020
90 #define MLX_V4_ODBR		0x002c
91 #define MLX_V4_IER		0x0034
92 
93 /* use longword access? */
94 #define MLX_V4_PUT_MAILBOX(sc, idx, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V4_MAILBOX + idx, val)
95 #define MLX_V4_GET_STATUS_IDENT(sc)	 bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V4_STATUS_IDENT)
96 #define MLX_V4_GET_STATUS(sc)		 bus_space_read_2 (sc->mlx_btag, sc->mlx_bhandle, MLX_V4_STATUS)
97 #define MLX_V4_GET_IDBR(sc)		 bus_space_read_4 (sc->mlx_btag, sc->mlx_bhandle, MLX_V4_IDBR)
98 #define MLX_V4_PUT_IDBR(sc, val)	 bus_space_write_4(sc->mlx_btag, sc->mlx_bhandle, MLX_V4_IDBR, val)
99 #define MLX_V4_GET_ODBR(sc)		 bus_space_read_4 (sc->mlx_btag, sc->mlx_bhandle, MLX_V4_ODBR)
100 #define MLX_V4_PUT_ODBR(sc, val)	 bus_space_write_4(sc->mlx_btag, sc->mlx_bhandle, MLX_V4_ODBR, val)
101 #define MLX_V4_PUT_IER(sc, val)		 bus_space_write_4(sc->mlx_btag, sc->mlx_bhandle, MLX_V4_IER, val)
102 
103 #define MLX_V4_IDB_FULL		(1<<0)		/* mailbox is full */
104 
105 #define MLX_V4_IDB_HWMBOX_CMD	(1<<0)		/* posted hardware mailbox command */
106 #define MLX_V4_IDB_SACK		(1<<1)		/* acknowledge status read */
107 #define MLX_V4_IDB_MEMMBOX_CMD	(1<<4)		/* posted memory mailbox command */
108 
109 #define MLX_V4_ODB_HWSAVAIL	(1<<0)		/* status is available for hardware mailbox */
110 #define MLX_V4_ODB_MEMSAVAIL	(1<<1)		/* status is available for memory mailbox */
111 
112 #define MLX_V4_ODB_HWMBOX_ACK	(1<<0)		/* ack status read from hardware mailbox */
113 #define MLX_V4_ODB_MEMMBOX_ACK	(1<<1)		/* ack status read from memory mailbox */
114 
115 #define MLX_V4_IER_MASK		0xfb		/* message unit interrupt mask */
116 #define MLX_V4_IER_DISINT	(1<<2)		/* interrupt disable bit */
117 
118 /*
119  * Accessor defines for the V5 interface
120  */
121 #define MLX_V5_MAILBOX		0x50
122 #define MLX_V5_STATUS_IDENT	0x5d
123 #define MLX_V5_STATUS		0x5e
124 #define MLX_V5_IDBR		0x60
125 #define MLX_V5_ODBR		0x61
126 #define MLX_V5_IER		0x34
127 
128 #define MLX_V5_PUT_MAILBOX(sc, idx, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V5_MAILBOX + idx, val)
129 #define MLX_V5_GET_STATUS_IDENT(sc)	 bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V5_STATUS_IDENT)
130 #define MLX_V5_GET_STATUS(sc)		 bus_space_read_2 (sc->mlx_btag, sc->mlx_bhandle, MLX_V5_STATUS)
131 #define MLX_V5_GET_IDBR(sc)		 bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V5_IDBR)
132 #define MLX_V5_PUT_IDBR(sc, val)	 bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V5_IDBR, val)
133 #define MLX_V5_GET_ODBR(sc)		 bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V5_ODBR)
134 #define MLX_V5_PUT_ODBR(sc, val)	 bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V5_ODBR, val)
135 #define MLX_V5_PUT_IER(sc, val)		 bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V5_IER, val)
136 
137 #define MLX_V5_IDB_EMPTY	(1<<0)		/* mailbox is empty */
138 
139 #define MLX_V5_IDB_HWMBOX_CMD	(1<<0)		/* posted hardware mailbox command */
140 #define MLX_V5_IDB_SACK		(1<<1)		/* acknowledge status read */
141 #define MLX_V5_IDB_MEMMBOX_CMD	(1<<4)		/* posted memory mailbox command */
142 
143 #define MLX_V5_ODB_HWSAVAIL	(1<<0)		/* status is available for hardware mailbox */
144 #define MLX_V5_ODB_MEMSAVAIL	(1<<1)		/* status is available for memory mailbox */
145 
146 #define MLX_V5_ODB_HWMBOX_ACK	(1<<0)		/* ack status read from hardware mailbox */
147 #define MLX_V5_ODB_MEMMBOX_ACK	(1<<1)		/* ack status read from memory mailbox */
148 
149 #define MLX_V5_IER_DISINT	(1<<2)		/* interrupt disable bit */
150 
151 
152 /*
153  * Scatter-gather list format, type 1, kind 00.
154  */
155 struct mlx_sgentry
156 {
157     u_int32_t	sg_addr;
158     u_int32_t	sg_count;
159 } __attribute__ ((packed));
160 
161 /*
162  * Command result buffers, as placed in system memory by the controller.
163  */
164 struct mlx_enquiry	/* MLX_CMD_ENQUIRY */
165 {
166     u_int8_t		me_num_sys_drvs;
167     u_int8_t		res1[3];
168     u_int32_t		me_drvsize[32];
169     u_int16_t		me_flash_age;
170     u_int8_t		me_status_flags;
171 #define MLX_ENQ_SFLAG_DEFWRERR	(1<<0)	/* deferred write error indicator */
172 #define MLX_ENQ_SFLAG_BATTLOW	(1<<1)	/* battery low */
173     u_int8_t		res2;
174     u_int8_t		me_fwminor;
175     u_int8_t		me_fwmajor;
176     u_int8_t		me_rebuild_flag;
177     u_int8_t		me_max_commands;
178     u_int8_t		me_offline_sd_count;
179     u_int8_t		res3;
180     u_int16_t		me_event_log_seq_num;
181     u_int8_t		me_critical_sd_count;
182     u_int8_t		res4[3];
183     u_int8_t		me_dead_count;
184     u_int8_t		res5;
185     u_int8_t		me_rebuild_count;
186     u_int8_t		me_misc_flags;
187 #define MLX_ENQ_MISC_BBU	(1<<3)	/* battery backup present */
188     struct
189     {
190 	u_int8_t	dd_targ;
191 	u_int8_t	dd_chan;
192     } __attribute__ ((packed)) me_dead[20];
193 } __attribute__ ((packed));
194 
195 struct mlx_enquiry2	/* MLX_CMD_ENQUIRY2 */
196 {
197     u_int32_t		me_hardware_id;
198     u_int32_t		me_firmware_id;
199     u_int32_t		res1;
200     u_int8_t		me_configured_channels;
201     u_int8_t		me_actual_channels;
202     u_int8_t		me_max_targets;
203     u_int8_t		me_max_tags;
204     u_int8_t		me_max_sys_drives;
205     u_int8_t		me_max_arms;
206     u_int8_t		me_max_spans;
207     u_int8_t		res2;
208     u_int32_t		res3;
209     u_int32_t		me_mem_size;
210     u_int32_t		me_cache_size;
211     u_int32_t		me_flash_size;
212     u_int32_t		me_nvram_size;
213     u_int16_t		me_mem_type;
214     u_int16_t		me_clock_speed;
215     u_int16_t		me_mem_speed;
216     u_int16_t		me_hardware_speed;
217     u_int8_t		res4[10];
218     u_int16_t		me_max_commands;
219     u_int16_t		me_max_sg;
220     u_int16_t		me_max_dp;
221     u_int16_t		me_max_iod;
222     u_int16_t		me_max_comb;
223     u_int8_t		me_latency;
224     u_int8_t		res5;
225     u_int8_t		me_scsi_timeout;
226     u_int8_t		res6;
227     u_int16_t		me_min_freelines;
228     u_int8_t		res7[8];
229     u_int8_t		me_rate_const;
230     u_int8_t		res8[11];
231     u_int16_t		me_physblk;
232     u_int16_t		me_logblk;
233     u_int16_t		me_maxblk;
234     u_int16_t		me_blocking_factor;
235     u_int16_t		me_cacheline;
236     u_int8_t		me_scsi_cap;
237     u_int8_t		res9[5];
238     u_int16_t		me_fimware_build;
239     u_int8_t		me_fault_mgmt_type;
240     u_int8_t		res10;
241     u_int32_t		me_firmware_features;
242     u_int8_t		res11[8];
243 } __attribute__ ((packed));
244 
245 struct mlx_enq_sys_drive /* MLX_CMD_ENQSYSDRIVE returns an array of 32 of these */
246 {
247     u_int32_t		sd_size;
248     u_int8_t		sd_state;
249     u_int8_t		sd_raidlevel;
250     u_int16_t		res1;
251 } __attribute__ ((packed));
252 
253 struct mlx_eventlog_entry	/* MLX_CMD_LOGOP/MLX_LOGOP_GET */
254 {
255     u_int8_t		el_type;
256     u_int8_t		el_length;
257     u_char		el_target:5;
258     u_char		el_channel:3;
259     u_char		el_lun:6;
260     u_char		res1:2;
261     u_int16_t		el_seqno;
262     u_char		el_errorcode:7;
263     u_char		el_valid:1;
264     u_int8_t		el_segment;
265     u_char		el_sensekey:4;
266     u_char		res2:1;
267     u_char		el_ILI:1;
268     u_char		el_EOM:1;
269     u_char		el_filemark:1;
270     u_int8_t		el_information[4];
271     u_int8_t		el_addsense;
272     u_int8_t		el_csi[4];
273     u_int8_t		el_asc;
274     u_int8_t		el_asq;
275     u_int8_t		res3[12];
276 } __attribute__ ((packed));
277 
278 #define MLX_LOGOP_GET		0x00	/* operation codes for MLX_CMD_LOGOP */
279 #define MLX_LOGMSG_SENSE	0x00	/* log message contents codes */
280 
281 struct mlx_rebuild_stat	/* MLX_CMD_REBUILDSTAT */
282 {
283     u_int32_t	rb_drive;
284     u_int32_t	rb_size;
285     u_int32_t	rb_remaining;
286 } __attribute__ ((packed));
287 
288 /*
289  * Inlines to build various command structures
290  */
291 static __inline void
292 mlx_make_type1(struct mlx_command *mc,
293 	       u_int8_t code,
294 	       u_int16_t f1,
295 	       u_int32_t f2,
296 	       u_int8_t f3,
297 	       u_int32_t f4,
298 	       u_int8_t f5)
299 {
300     mc->mc_mailbox[0x0] = code;
301     mc->mc_mailbox[0x2] = f1 & 0xff;
302     mc->mc_mailbox[0x3] = (((f2 >> 24) & 0x3) << 6) | ((f1 >> 8) & 0x3f);
303     mc->mc_mailbox[0x4] = f2 & 0xff;
304     mc->mc_mailbox[0x5] = (f2 >> 8) & 0xff;
305     mc->mc_mailbox[0x6] = (f2 >> 16) & 0xff;
306     mc->mc_mailbox[0x7] = f3;
307     mc->mc_mailbox[0x8] = f4 & 0xff;
308     mc->mc_mailbox[0x9] = (f4 >> 8) & 0xff;
309     mc->mc_mailbox[0xa] = (f4 >> 16) & 0xff;
310     mc->mc_mailbox[0xb] = (f4 >> 24) & 0xff;
311     mc->mc_mailbox[0xc] = f5;
312 }
313 
314 static __inline void
315 mlx_make_type2(struct mlx_command *mc,
316 	       u_int8_t code,
317 	       u_int8_t f1,
318 	       u_int8_t f2,
319 	       u_int8_t f3,
320 	       u_int8_t f4,
321 	       u_int8_t f5,
322 	       u_int8_t f6,
323 	       u_int32_t f7,
324 	       u_int8_t f8)
325 {
326     mc->mc_mailbox[0x0] = code;
327     mc->mc_mailbox[0x2] = f1;
328     mc->mc_mailbox[0x3] = f2;
329     mc->mc_mailbox[0x4] = f3;
330     mc->mc_mailbox[0x5] = f4;
331     mc->mc_mailbox[0x6] = f5;
332     mc->mc_mailbox[0x7] = f6;
333     mc->mc_mailbox[0x8] = f7 & 0xff;
334     mc->mc_mailbox[0x9] = (f7 >> 8) & 0xff;
335     mc->mc_mailbox[0xa] = (f7 >> 16) & 0xff;
336     mc->mc_mailbox[0xb] = (f7 >> 24) & 0xff;
337     mc->mc_mailbox[0xc] = f8;
338 }
339 
340 static __inline void
341 mlx_make_type3(struct mlx_command *mc,
342 	       u_int8_t code,
343 	       u_int8_t f1,
344 	       u_int8_t f2,
345 	       u_int16_t f3,
346 	       u_int8_t f4,
347 	       u_int8_t f5,
348 	       u_int32_t f6,
349 	       u_int8_t f7)
350 {
351     mc->mc_mailbox[0x0] = code;
352     mc->mc_mailbox[0x2] = f1;
353     mc->mc_mailbox[0x3] = f2;
354     mc->mc_mailbox[0x4] = f3 & 0xff;
355     mc->mc_mailbox[0x5] = (f3 >> 8) & 0xff;
356     mc->mc_mailbox[0x6] = f4;
357     mc->mc_mailbox[0x7] = f5;
358     mc->mc_mailbox[0x8] = f6 & 0xff;
359     mc->mc_mailbox[0x9] = (f6 >> 8) & 0xff;
360     mc->mc_mailbox[0xa] = (f6 >> 16) & 0xff;
361     mc->mc_mailbox[0xb] = (f6 >> 24) & 0xff;
362     mc->mc_mailbox[0xc] = f7;
363 }
364 
365 static __inline void
366 mlx_make_type4(struct mlx_command *mc,
367 	       u_int8_t code,
368 	       u_int16_t f1,
369 	       u_int32_t f2,
370 	       u_int32_t f3,
371 	       u_int8_t f4)
372 {
373     mc->mc_mailbox[0x0] = code;
374     mc->mc_mailbox[0x2] = f1 & 0xff;
375     mc->mc_mailbox[0x3] = (f1 >> 8) & 0xff;
376     mc->mc_mailbox[0x4] = f2 & 0xff;
377     mc->mc_mailbox[0x5] = (f2 >> 8) & 0xff;
378     mc->mc_mailbox[0x6] = (f2 >> 16) & 0xff;
379     mc->mc_mailbox[0x7] = (f2 >> 24) & 0xff;
380     mc->mc_mailbox[0x8] = f3 & 0xff;
381     mc->mc_mailbox[0x9] = (f3 >> 8) & 0xff;
382     mc->mc_mailbox[0xa] = (f3 >> 16) & 0xff;
383     mc->mc_mailbox[0xb] = (f3 >> 24) & 0xff;
384     mc->mc_mailbox[0xc] = f4;
385 }
386 
387 static __inline void
388 mlx_make_type5(struct mlx_command *mc,
389 	       u_int8_t code,
390 	       u_int8_t f1,
391 	       u_int8_t f2,
392 	       u_int32_t f3,
393 	       u_int32_t f4,
394 	       u_int8_t f5)
395 {
396     mc->mc_mailbox[0x0] = code;
397     mc->mc_mailbox[0x2] = f1;
398     mc->mc_mailbox[0x3] = f2;
399     mc->mc_mailbox[0x4] = f3 & 0xff;
400     mc->mc_mailbox[0x5] = (f3 >> 8) & 0xff;
401     mc->mc_mailbox[0x6] = (f3 >> 16) & 0xff;
402     mc->mc_mailbox[0x7] = (f3 >> 24) & 0xff;
403     mc->mc_mailbox[0x8] = f4 & 0xff;
404     mc->mc_mailbox[0x9] = (f4 >> 8) & 0xff;
405     mc->mc_mailbox[0xa] = (f4 >> 16) & 0xff;
406     mc->mc_mailbox[0xb] = (f4 >> 24) & 0xff;
407     mc->mc_mailbox[0xc] = f5;
408 }
409