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_BLKSIZE	512		/* fixed feature */
30#define MLX_PAGE_SIZE	4096		/* controller, not cpu, attribute */
31
32/*
33 * Selected command codes.
34 */
35#define MLX_CMD_ENQUIRY_OLD	0x05
36#define MLX_CMD_ENQUIRY		0x53
37#define MLX_CMD_ENQUIRY2	0x1c
38#define MLX_CMD_ENQSYSDRIVE	0x19
39#define MLX_CMD_READSG		0xb6
40#define MLX_CMD_WRITESG		0xb7
41#define MLX_CMD_READSG_OLD	0x82
42#define MLX_CMD_WRITESG_OLD	0x83
43#define MLX_CMD_FLUSH		0x0a
44#define MLX_CMD_LOGOP		0x72
45#define MLX_CMD_REBUILDASYNC	0x16
46#define MLX_CMD_CHECKASYNC	0x1e
47#define MLX_CMD_REBUILDSTAT	0x0c
48#define MLX_CMD_STOPCHANNEL	0x13
49#define MLX_CMD_STARTCHANNEL	0x12
50#define MLX_CMD_READ_CONFIG	0x4e
51#define MLX_CMD_DIRECT_CDB	0x04
52#define MLX_CMD_DEVICE_STATE	0x50
53
54#ifdef _KERNEL
55
56#define MLX_CFG_BASE0   0x10		/* first region */
57#define MLX_CFG_BASE1   0x14		/* second region (type 3 only) */
58
59/*
60 * Status values.
61 */
62#define MLX_STATUS_OK		0x0000
63#define MLX_STATUS_RDWROFFLINE	0x0002	/* read/write claims drive is offline */
64#define MLX_STATUS_WEDGED	0xdead	/* controller not listening */
65#define MLX_STATUS_LOST		0xbeef	/* never came back */
66#define MLX_STATUS_BUSY		0xffff	/* command is in controller */
67
68/*
69 * Accessor defines for the V3 interface.
70 */
71#define MLX_V3_MAILBOX		0x00
72#define	MLX_V3_STATUS_IDENT	0x0d
73#define MLX_V3_STATUS		0x0e
74#define MLX_V3_IDBR		0x40
75#define MLX_V3_ODBR		0x41
76#define MLX_V3_IER		0x43
77#define MLX_V3_FWERROR		0x3f
78#define MLX_V3_FWERROR_PARAM1	0x00
79#define MLX_V3_FWERROR_PARAM2	0x01
80
81#define MLX_V3_PUT_MAILBOX(sc, idx, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V3_MAILBOX + idx, val)
82#define MLX_V3_GET_STATUS_IDENT(sc)	 bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V3_STATUS_IDENT)
83#define MLX_V3_GET_STATUS(sc)		 bus_space_read_2 (sc->mlx_btag, sc->mlx_bhandle, MLX_V3_STATUS)
84#define MLX_V3_GET_IDBR(sc)		 bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V3_IDBR)
85#define MLX_V3_PUT_IDBR(sc, val)	 bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V3_IDBR, val)
86#define MLX_V3_GET_ODBR(sc)		 bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V3_ODBR)
87#define MLX_V3_PUT_ODBR(sc, val)	 bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V3_ODBR, val)
88#define MLX_V3_PUT_IER(sc, val)		 bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V3_IER, val)
89#define MLX_V3_GET_FWERROR(sc)		 bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V3_FWERROR)
90#define MLX_V3_PUT_FWERROR(sc, val)	 bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V3_FWERROR, val)
91#define MLX_V3_GET_FWERROR_PARAM1(sc)	 bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V3_FWERROR_PARAM1)
92#define MLX_V3_GET_FWERROR_PARAM2(sc)	 bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V3_FWERROR_PARAM2)
93
94#define MLX_V3_IDB_FULL		(1<<0)		/* mailbox is full */
95#define MLX_V3_IDB_INIT_BUSY	(1<<1)		/* initialisation in progress */
96
97#define MLX_V3_IDB_SACK		(1<<1)		/* acknowledge status read */
98
99#define MLX_V3_ODB_SAVAIL	(1<<0)		/* status is available */
100
101#define MLX_V3_FWERROR_PEND	(1<<2)		/* firmware error pending */
102
103/*
104 * Accessor defines for the V4 interface.
105 */
106#define MLX_V4_MAILBOX		0x1000
107#define MLX_V4_MAILBOX_LENGTH		16
108#define MLX_V4_STATUS_IDENT	0x1018
109#define MLX_V4_STATUS		0x101a
110#define MLX_V4_IDBR		0x0020
111#define MLX_V4_ODBR		0x002c
112#define MLX_V4_IER		0x0034
113#define MLX_V4_FWERROR		0x103f
114#define MLX_V4_FWERROR_PARAM1	0x1000
115#define MLX_V4_FWERROR_PARAM2	0x1001
116
117/* use longword access? */
118#define MLX_V4_PUT_MAILBOX(sc, idx, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V4_MAILBOX + idx, val)
119#define MLX_V4_GET_STATUS_IDENT(sc)	 bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V4_STATUS_IDENT)
120#define MLX_V4_GET_STATUS(sc)		 bus_space_read_2 (sc->mlx_btag, sc->mlx_bhandle, MLX_V4_STATUS)
121#define MLX_V4_GET_IDBR(sc)		 bus_space_read_4 (sc->mlx_btag, sc->mlx_bhandle, MLX_V4_IDBR)
122#define MLX_V4_PUT_IDBR(sc, val)	 bus_space_write_4(sc->mlx_btag, sc->mlx_bhandle, MLX_V4_IDBR, val)
123#define MLX_V4_GET_ODBR(sc)		 bus_space_read_4 (sc->mlx_btag, sc->mlx_bhandle, MLX_V4_ODBR)
124#define MLX_V4_PUT_ODBR(sc, val)	 bus_space_write_4(sc->mlx_btag, sc->mlx_bhandle, MLX_V4_ODBR, val)
125#define MLX_V4_PUT_IER(sc, val)		 bus_space_write_4(sc->mlx_btag, sc->mlx_bhandle, MLX_V4_IER, val)
126#define MLX_V4_GET_FWERROR(sc)		 bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V4_FWERROR)
127#define MLX_V4_PUT_FWERROR(sc, val)	 bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V4_FWERROR, val)
128#define MLX_V4_GET_FWERROR_PARAM1(sc)	 bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V4_FWERROR_PARAM1)
129#define MLX_V4_GET_FWERROR_PARAM2(sc)	 bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V4_FWERROR_PARAM2)
130
131#define MLX_V4_IDB_FULL		(1<<0)		/* mailbox is full */
132#define MLX_V4_IDB_INIT_BUSY	(1<<1)		/* initialisation in progress */
133
134#define MLX_V4_IDB_HWMBOX_CMD	(1<<0)		/* posted hardware mailbox command */
135#define MLX_V4_IDB_SACK		(1<<1)		/* acknowledge status read */
136#define MLX_V4_IDB_MEMMBOX_CMD	(1<<4)		/* posted memory mailbox command */
137
138#define MLX_V4_ODB_HWSAVAIL	(1<<0)		/* status is available for hardware mailbox */
139#define MLX_V4_ODB_MEMSAVAIL	(1<<1)		/* status is available for memory mailbox */
140
141#define MLX_V4_ODB_HWMBOX_ACK	(1<<0)		/* ack status read from hardware mailbox */
142#define MLX_V4_ODB_MEMMBOX_ACK	(1<<1)		/* ack status read from memory mailbox */
143
144#define MLX_V4_IER_MASK		0xfb		/* message unit interrupt mask */
145#define MLX_V4_IER_DISINT	(1<<2)		/* interrupt disable bit */
146
147#define MLX_V4_FWERROR_PEND	(1<<2)		/* firmware error pending */
148
149/*
150 * Accessor defines for the V5 interface
151 */
152#define MLX_V5_MAILBOX		0x50
153#define MLX_V5_MAILBOX_LENGTH		16
154#define MLX_V5_STATUS_IDENT	0x5d
155#define MLX_V5_STATUS		0x5e
156#define MLX_V5_IDBR		0x60
157#define MLX_V5_ODBR		0x61
158#define MLX_V5_IER		0x34
159#define MLX_V5_FWERROR		0x63
160#define MLX_V5_FWERROR_PARAM1	0x50
161#define MLX_V5_FWERROR_PARAM2	0x51
162
163#define MLX_V5_PUT_MAILBOX(sc, idx, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V5_MAILBOX + idx, val)
164#define MLX_V5_GET_STATUS_IDENT(sc)	 bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V5_STATUS_IDENT)
165#define MLX_V5_GET_STATUS(sc)		 bus_space_read_2 (sc->mlx_btag, sc->mlx_bhandle, MLX_V5_STATUS)
166#define MLX_V5_GET_IDBR(sc)		 bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V5_IDBR)
167#define MLX_V5_PUT_IDBR(sc, val)	 bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V5_IDBR, val)
168#define MLX_V5_GET_ODBR(sc)		 bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V5_ODBR)
169#define MLX_V5_PUT_ODBR(sc, val)	 bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V5_ODBR, val)
170#define MLX_V5_PUT_IER(sc, val)		 bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V5_IER, val)
171#define MLX_V5_GET_FWERROR(sc)		 bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V5_FWERROR)
172#define MLX_V5_PUT_FWERROR(sc, val)	 bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V5_FWERROR, val)
173#define MLX_V5_GET_FWERROR_PARAM1(sc)	 bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V5_FWERROR_PARAM1)
174#define MLX_V5_GET_FWERROR_PARAM2(sc)	 bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V5_FWERROR_PARAM2)
175
176#define MLX_V5_IDB_EMPTY	(1<<0)		/* mailbox is empty */
177#define MLX_V5_IDB_INIT_DONE	(1<<1)		/* initialisation has completed */
178
179#define MLX_V5_IDB_HWMBOX_CMD	(1<<0)		/* posted hardware mailbox command */
180#define MLX_V5_IDB_SACK		(1<<1)		/* acknowledge status read */
181#define MLX_V5_IDB_RESET	(1<<3)		/* reset request */
182#define MLX_V5_IDB_MEMMBOX_CMD	(1<<4)		/* posted memory mailbox command */
183
184#define MLX_V5_ODB_HWSAVAIL	(1<<0)		/* status is available for hardware mailbox */
185#define MLX_V5_ODB_MEMSAVAIL	(1<<1)		/* status is available for memory mailbox */
186
187#define MLX_V5_ODB_HWMBOX_ACK	(1<<0)		/* ack status read from hardware mailbox */
188#define MLX_V5_ODB_MEMMBOX_ACK	(1<<1)		/* ack status read from memory mailbox */
189
190#define MLX_V5_IER_DISINT	(1<<2)		/* interrupt disable bit */
191
192#define MLX_V5_FWERROR_PEND	(1<<2)		/* firmware error pending */
193
194#endif /* _KERNEL */
195
196/*
197 * Scatter-gather list format, type 1, kind 00.
198 */
199struct mlx_sgentry
200{
201    u_int32_t	sg_addr;
202    u_int32_t	sg_count;
203} __packed;
204
205/*
206 * Command result buffers, as placed in system memory by the controller.
207 */
208
209struct mlx_enquiry_old	/* MLX_CMD_ENQUIRY_OLD */
210{
211    u_int8_t		me_num_sys_drvs;
212    u_int8_t		res1[3];
213    u_int32_t		me_drvsize[8];
214    u_int16_t		me_flash_age;
215    u_int8_t		me_status_flags;
216    u_int8_t		me_free_state_change_count;
217    u_int8_t		me_fwminor;
218    u_int8_t		me_fwmajor;
219    u_int8_t		me_rebuild_flag;
220    u_int8_t		me_max_commands;
221    u_int8_t		me_offline_sd_count;
222    u_int8_t		res3;
223    u_int8_t		me_critical_sd_count;
224    u_int8_t		res4[3];
225    u_int8_t		me_dead_count;
226    u_int8_t		res5;
227    u_int8_t		me_rebuild_count;
228    u_int8_t		me_misc_flags;
229    struct
230    {
231	u_int8_t	dd_targ;
232	u_int8_t	dd_chan;
233    } __packed me_dead[20];
234} __packed;
235
236struct mlx_enquiry	/* MLX_CMD_ENQUIRY */
237{
238    u_int8_t		me_num_sys_drvs;
239    u_int8_t		res1[3];
240    u_int32_t		me_drvsize[32];
241    u_int16_t		me_flash_age;
242    u_int8_t		me_status_flags;
243#define MLX_ENQ_SFLAG_DEFWRERR	(1<<0)	/* deferred write error indicator */
244#define MLX_ENQ_SFLAG_BATTLOW	(1<<1)	/* battery low */
245    u_int8_t		res2;
246    u_int8_t		me_fwminor;
247    u_int8_t		me_fwmajor;
248    u_int8_t		me_rebuild_flag;
249    u_int8_t		me_max_commands;
250    u_int8_t		me_offline_sd_count;
251    u_int8_t		res3;
252    u_int16_t		me_event_log_seq_num;
253    u_int8_t		me_critical_sd_count;
254    u_int8_t		res4[3];
255    u_int8_t		me_dead_count;
256    u_int8_t		res5;
257    u_int8_t		me_rebuild_count;
258    u_int8_t		me_misc_flags;
259#define MLX_ENQ_MISC_BBU	(1<<3)	/* battery backup present */
260    struct
261    {
262	u_int8_t	dd_targ;
263	u_int8_t	dd_chan;
264    } __packed me_dead[20];
265} __packed;
266
267struct mlx_enquiry2	/* MLX_CMD_ENQUIRY2 */
268{
269    u_int32_t		me_hardware_id;
270    u_int32_t		me_firmware_id;
271    u_int32_t		res1;
272    u_int8_t		me_configured_channels;
273    u_int8_t		me_actual_channels;
274    u_int8_t		me_max_targets;
275    u_int8_t		me_max_tags;
276    u_int8_t		me_max_sys_drives;
277    u_int8_t		me_max_arms;
278    u_int8_t		me_max_spans;
279    u_int8_t		res2;
280    u_int32_t		res3;
281    u_int32_t		me_mem_size;
282    u_int32_t		me_cache_size;
283    u_int32_t		me_flash_size;
284    u_int32_t		me_nvram_size;
285    u_int16_t		me_mem_type;
286    u_int16_t		me_clock_speed;
287    u_int16_t		me_mem_speed;
288    u_int16_t		me_hardware_speed;
289    u_int8_t		res4[12];
290    u_int16_t		me_max_commands;
291    u_int16_t		me_max_sg;
292    u_int16_t		me_max_dp;
293    u_int16_t		me_max_iod;
294    u_int16_t		me_max_comb;
295    u_int8_t		me_latency;
296    u_int8_t		res5;
297    u_int8_t		me_scsi_timeout;
298    u_int8_t		res6;
299    u_int16_t		me_min_freelines;
300    u_int8_t		res7[8];
301    u_int8_t		me_rate_const;
302    u_int8_t		res8[11];
303    u_int16_t		me_physblk;
304    u_int16_t		me_logblk;
305    u_int16_t		me_maxblk;
306    u_int16_t		me_blocking_factor;
307    u_int16_t		me_cacheline;
308    u_int8_t		me_scsi_cap;
309    u_int8_t		res9[5];
310    u_int16_t		me_firmware_build;
311    u_int8_t		me_fault_mgmt_type;
312    u_int8_t		res10;
313    u_int32_t		me_firmware_features;
314    u_int8_t		res11[8];
315} __packed;
316
317struct mlx_enq_sys_drive /* MLX_CMD_ENQSYSDRIVE returns an array of 32 of these */
318{
319    u_int32_t		sd_size;
320    u_int8_t		sd_state;
321    u_int8_t		sd_raidlevel;
322    u_int16_t		res1;
323} __packed;
324
325struct mlx_eventlog_entry	/* MLX_CMD_LOGOP/MLX_LOGOP_GET */
326{
327    u_int8_t		el_type;
328    u_int8_t		el_length;
329    u_char		el_target:5;
330    u_char		el_channel:3;
331    u_char		el_lun:6;
332    u_char		res1:2;
333    u_int16_t		el_seqno;
334    u_char		el_errorcode:7;
335    u_char		el_valid:1;
336    u_int8_t		el_segment;
337    u_char		el_sensekey:4;
338    u_char		res2:1;
339    u_char		el_ILI:1;
340    u_char		el_EOM:1;
341    u_char		el_filemark:1;
342    u_int8_t		el_information[4];
343    u_int8_t		el_addsense;
344    u_int8_t		el_csi[4];
345    u_int8_t		el_asc;
346    u_int8_t		el_asq;
347    u_int8_t		res3[12];
348} __packed;
349
350#define MLX_LOGOP_GET		0x00	/* operation codes for MLX_CMD_LOGOP */
351#define MLX_LOGMSG_SENSE	0x00	/* log message contents codes */
352
353struct mlx_rebuild_stat	/* MLX_CMD_REBUILDSTAT */
354{
355    u_int32_t	rb_drive;
356    u_int32_t	rb_size;
357    u_int32_t	rb_remaining;
358} __packed;
359
360struct mlx_config2
361{
362    u_int16_t	cf_flags1;
363#define MLX_CF2_ACTV_NEG	(1<<1)
364#define MLX_CF2_NORSTRTRY	(1<<7)
365#define MLX_CF2_STRGWRK		(1<<8)
366#define MLX_CF2_HPSUPP		(1<<9)
367#define MLX_CF2_NODISCN		(1<<10)
368#define MLX_CF2_ARM    		(1<<13)
369#define MLX_CF2_OFM		(1<<15)
370#define MLX_CF2_AEMI (MLX_CF2_ARM | MLX_CF2_OFM)
371    u_int8_t	cf_oemid;
372    u_int8_t	cf_oem_model;
373    u_int8_t	cf_physical_sector;
374    u_int8_t	cf_logical_sector;
375    u_int8_t	cf_blockfactor;
376    u_int8_t	cf_flags2;
377#define MLX_CF2_READAH		(1<<0)
378#define MLX_CF2_BIOSDLY		(1<<1)
379#define MLX_CF2_REASS1S		(1<<4)
380#define MLX_CF2_FUAENABL	(1<<6)
381#define MLX_CF2_R5ALLS		(1<<7)
382    u_int8_t	cf_rcrate;
383    u_int8_t	cf_res1;
384    u_int8_t	cf_blocks_per_cache_line;
385    u_int8_t	cf_blocks_per_stripe;
386    u_int8_t	cf_scsi_param_0;
387    u_int8_t	cf_scsi_param_1;
388    u_int8_t	cf_scsi_param_2;
389    u_int8_t	cf_scsi_param_3;
390    u_int8_t	cf_scsi_param_4;
391    u_int8_t	cf_scsi_param_5;
392    u_int8_t	cf_scsi_initiator_id;
393    u_int8_t	cf_res2;
394    u_int8_t	cf_startup_mode;
395    u_int8_t	cf_simultaneous_spinup_devices;
396    u_int8_t	cf_delay_between_spinups;
397    u_int8_t	cf_res3;
398    u_int16_t	cf_checksum;
399} __packed;
400
401struct mlx_sys_drv_span
402{
403    u_int32_t	sp_start_lba;
404    u_int32_t	sp_nblks;
405    u_int8_t	sp_arm[8];
406} __packed;
407
408struct mlx_sys_drv
409{
410    u_int8_t	sd_status;
411    u_int8_t	sd_ext_status;
412    u_int8_t	sd_mod1;
413    u_int8_t	sd_mod2;
414    u_int8_t	sd_raidlevel;
415#define MLX_SYS_DRV_WRITEBACK	(1<<7)
416#define MLX_SYS_DRV_RAID0	0
417#define MLX_SYS_DRV_RAID1	1
418#define MLX_SYS_DRV_RAID3	3
419#define MLX_SYS_DRV_RAID5	5
420#define MLX_SYS_DRV_RAID6	6
421#define MLX_SYS_DRV_JBOD	7
422    u_int8_t	sd_valid_arms;
423    u_int8_t	sd_valid_spans;
424    u_int8_t	sd_init_state;
425#define MLX_SYS_DRV_INITTED	0x81;
426    struct mlx_sys_drv_span sd_span[4];
427} __packed;
428
429struct mlx_phys_drv
430{
431    u_int8_t	pd_flags1;
432#define	MLX_PHYS_DRV_PRESENT	(1<<0)
433    u_int8_t	pd_flags2;
434#define MLX_PHYS_DRV_OTHER	0x00
435#define MLX_PHYS_DRV_DISK	0x01
436#define MLX_PHYS_DRV_SEQUENTIAL	0x02
437#define MLX_PHYS_DRV_CDROM	0x03
438#define MLX_PHYS_DRV_FAST20	(1<<3)
439#define MLX_PHYS_DRV_SYNC	(1<<4)
440#define MLX_PHYS_DRV_FAST	(1<<5)
441#define MLX_PHYS_DRV_WIDE	(1<<6)
442#define MLX_PHYS_DRV_TAG	(1<<7)
443    u_int8_t	pd_status;
444#define MLX_PHYS_DRV_DEAD	0x00
445#define MLX_PHYS_DRV_WRONLY	0x02
446#define MLX_PHYS_DRV_ONLINE	0x03
447#define MLX_PHYS_DRV_STANDBY	0x10
448    u_int8_t	pd_res1;
449    u_int8_t	pd_period;
450    u_int8_t	pd_offset;
451    u_int32_t	pd_config_size;
452} __packed;
453
454struct mlx_core_cfg
455{
456    u_int8_t	cc_num_sys_drives;
457    u_int8_t	cc_res1[3];
458    struct mlx_sys_drv	cc_sys_drives[32];
459    struct mlx_phys_drv cc_phys_drives[5 * 16];
460} __packed;
461
462struct mlx_dcdb
463{
464    u_int8_t	dcdb_target:4;
465    u_int8_t	dcdb_channel:4;
466    u_int8_t	dcdb_flags;
467#define MLX_DCDB_NO_DATA	0x00
468#define MLX_DCDB_DATA_IN	0x01
469#define MLX_DCDB_DATA_OUT	0x02
470#define MLX_DCDB_EARLY_STATUS		(1<<2)
471#define MLX_DCDB_TIMEOUT_10S	0x10
472#define MLX_DCDB_TIMEOUT_60S	0x20
473#define MLX_DCDB_TIMEOUT_20M	0x30
474#define MLX_DCDB_TIMEOUT_24H	0x40
475#define MLX_DCDB_NO_AUTO_SENSE	(1<<6)
476#define MLX_DCDB_DISCONNECT	(1<<7)
477    u_int16_t	dcdb_datasize;
478    u_int32_t	dcdb_physaddr;
479    u_int8_t	dcdb_cdb_length:4;
480    u_int8_t	dcdb_datasize_high:4;
481    u_int8_t	dcdb_sense_length;
482    u_int8_t	dcdb_cdb[12];
483    u_int8_t	dcdb_sense[64];
484    u_int8_t	dcdb_status;
485    u_int8_t	res1;
486} __packed;
487
488struct mlx_bbtable_entry
489{
490    u_int32_t	bbt_block_number;
491    u_int8_t	bbt_extent;
492    u_int8_t	res1;
493    u_int8_t	bbt_entry_type;
494    u_int8_t	bbt_system_drive:5;
495    u_int8_t	res2:3;
496} __packed;
497
498#ifdef _KERNEL
499/*
500 * Inlines to build various command structures
501 */
502static __inline void
503mlx_make_type1(struct mlx_command *mc,
504	       u_int8_t code,
505	       u_int16_t f1,
506	       u_int32_t f2,
507	       u_int8_t f3,
508	       u_int32_t f4,
509	       u_int8_t f5)
510{
511    mc->mc_mailbox[0x0] = code;
512    mc->mc_mailbox[0x2] = f1 & 0xff;
513    mc->mc_mailbox[0x3] = (((f2 >> 24) & 0x3) << 6) | ((f1 >> 8) & 0x3f);
514    mc->mc_mailbox[0x4] = f2 & 0xff;
515    mc->mc_mailbox[0x5] = (f2 >> 8) & 0xff;
516    mc->mc_mailbox[0x6] = (f2 >> 16) & 0xff;
517    mc->mc_mailbox[0x7] = f3;
518    mc->mc_mailbox[0x8] = f4 & 0xff;
519    mc->mc_mailbox[0x9] = (f4 >> 8) & 0xff;
520    mc->mc_mailbox[0xa] = (f4 >> 16) & 0xff;
521    mc->mc_mailbox[0xb] = (f4 >> 24) & 0xff;
522    mc->mc_mailbox[0xc] = f5;
523}
524
525static __inline void
526mlx_make_type2(struct mlx_command *mc,
527	       u_int8_t code,
528	       u_int8_t f1,
529	       u_int8_t f2,
530	       u_int8_t f3,
531	       u_int8_t f4,
532	       u_int8_t f5,
533	       u_int8_t f6,
534	       u_int32_t f7,
535	       u_int8_t f8)
536{
537    mc->mc_mailbox[0x0] = code;
538    mc->mc_mailbox[0x2] = f1;
539    mc->mc_mailbox[0x3] = f2;
540    mc->mc_mailbox[0x4] = f3;
541    mc->mc_mailbox[0x5] = f4;
542    mc->mc_mailbox[0x6] = f5;
543    mc->mc_mailbox[0x7] = f6;
544    mc->mc_mailbox[0x8] = f7 & 0xff;
545    mc->mc_mailbox[0x9] = (f7 >> 8) & 0xff;
546    mc->mc_mailbox[0xa] = (f7 >> 16) & 0xff;
547    mc->mc_mailbox[0xb] = (f7 >> 24) & 0xff;
548    mc->mc_mailbox[0xc] = f8;
549}
550
551static __inline void
552mlx_make_type3(struct mlx_command *mc,
553	       u_int8_t code,
554	       u_int8_t f1,
555	       u_int8_t f2,
556	       u_int16_t f3,
557	       u_int8_t f4,
558	       u_int8_t f5,
559	       u_int32_t f6,
560	       u_int8_t f7)
561{
562    mc->mc_mailbox[0x0] = code;
563    mc->mc_mailbox[0x2] = f1;
564    mc->mc_mailbox[0x3] = f2;
565    mc->mc_mailbox[0x4] = f3 & 0xff;
566    mc->mc_mailbox[0x5] = (f3 >> 8) & 0xff;
567    mc->mc_mailbox[0x6] = f4;
568    mc->mc_mailbox[0x7] = f5;
569    mc->mc_mailbox[0x8] = f6 & 0xff;
570    mc->mc_mailbox[0x9] = (f6 >> 8) & 0xff;
571    mc->mc_mailbox[0xa] = (f6 >> 16) & 0xff;
572    mc->mc_mailbox[0xb] = (f6 >> 24) & 0xff;
573    mc->mc_mailbox[0xc] = f7;
574}
575
576static __inline void
577mlx_make_type4(struct mlx_command *mc,
578	       u_int8_t code,
579	       u_int16_t f1,
580	       u_int32_t f2,
581	       u_int32_t f3,
582	       u_int8_t f4)
583{
584    mc->mc_mailbox[0x0] = code;
585    mc->mc_mailbox[0x2] = f1 & 0xff;
586    mc->mc_mailbox[0x3] = (f1 >> 8) & 0xff;
587    mc->mc_mailbox[0x4] = f2 & 0xff;
588    mc->mc_mailbox[0x5] = (f2 >> 8) & 0xff;
589    mc->mc_mailbox[0x6] = (f2 >> 16) & 0xff;
590    mc->mc_mailbox[0x7] = (f2 >> 24) & 0xff;
591    mc->mc_mailbox[0x8] = f3 & 0xff;
592    mc->mc_mailbox[0x9] = (f3 >> 8) & 0xff;
593    mc->mc_mailbox[0xa] = (f3 >> 16) & 0xff;
594    mc->mc_mailbox[0xb] = (f3 >> 24) & 0xff;
595    mc->mc_mailbox[0xc] = f4;
596}
597
598static __inline void
599mlx_make_type5(struct mlx_command *mc,
600	       u_int8_t code,
601	       u_int8_t f1,
602	       u_int8_t f2,
603	       u_int32_t f3,
604	       u_int32_t f4,
605	       u_int8_t f5)
606{
607    mc->mc_mailbox[0x0] = code;
608    mc->mc_mailbox[0x2] = f1;
609    mc->mc_mailbox[0x3] = f2;
610    mc->mc_mailbox[0x4] = f3 & 0xff;
611    mc->mc_mailbox[0x5] = (f3 >> 8) & 0xff;
612    mc->mc_mailbox[0x6] = (f3 >> 16) & 0xff;
613    mc->mc_mailbox[0x7] = (f3 >> 24) & 0xff;
614    mc->mc_mailbox[0x8] = f4 & 0xff;
615    mc->mc_mailbox[0x9] = (f4 >> 8) & 0xff;
616    mc->mc_mailbox[0xa] = (f4 >> 16) & 0xff;
617    mc->mc_mailbox[0xb] = (f4 >> 24) & 0xff;
618    mc->mc_mailbox[0xc] = f5;
619}
620
621#endif /* _KERNEL */
622