summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/sys/sata/sata_hba.h
blob: aa036d26cde6dd046c5a064b80f90b9db3fca7c6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */
/*
 * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
 */

#ifndef _SATA_HBA_H
#define	_SATA_HBA_H

#ifdef	__cplusplus
extern "C" {
#endif

#include <sys/sata/sata_defs.h>

/*
 * SATA Host Bus Adapter (HBA) driver transport definitions
 */

#include <sys/types.h>

#ifndef	TRUE
#define	TRUE	1
#define	FALSE	0
#endif

#define	SATA_SUCCESS	0
#define	SATA_RETRY	1
#define	SATA_FAILURE	-1


/* SATA Framework definitions */

#define	SATA_MAX_CPORTS		32	/* Max number of controller ports */
					/* Multiplier (PMult) */
#define	SATA_MAX_PMPORTS	16	/* Maximum number of ports on PMult */
#define	SATA_PMULT_HOSTPORT	0xf	/* Port Multiplier host port number */


/*
 * SATA device address
 * Address qualifier flags are used to specify what is addressed (device
 * or port) and where (controller or port multiplier data port).
 */
struct sata_address {
	uint8_t		cport;		/* Controller's SATA port number */
	uint8_t 	pmport;		/* Port Multiplier SATA port number */
	uint8_t		qual;		/* Address Qualifier flags */
	uint8_t		pad;		/* Reserved */
};

typedef struct sata_address sata_address_t;

/*
 * SATA address Qualifier flags (in qual field of sata_address struct).
 * They are mutually exclusive.
 */

#define	SATA_ADDR_NULL		0x00	/* No address */
#define	SATA_ADDR_DCPORT	0x01	/* Device attched to controller port */
#define	SATA_ADDR_DPMPORT	0x02	/* Device attched to PM device port */
#define	SATA_ADDR_CPORT		0x04	/* Controller's device port */
#define	SATA_ADDR_PMPORT	0x08	/* Port Multiplier's device port */
#define	SATA_ADDR_CNTRL		0x10	/* Controller */
#define	SATA_ADDR_PMULT		0x20	/* Port Multiplier */
#define	SATA_ADDR_PMULT_SPEC	0x40	/* Port Multiplier Specific */

/*
 * SATA port status and control register block.
 * The sstatus, serror, scontrol, sactive and snotific
 * are the copies of the SATA port status and control registers.
 * (Port SStatus, SError, SControl, SActive and SNotification are
 * defined by Serial ATA r1.0a sepc and Serial ATA II spec.
 */

struct sata_port_scr
{
	uint32_t	sstatus;	/* Port SStatus register */
	uint32_t	serror;		/* Port SError register */
	uint32_t	scontrol;	/* Port SControl register */
	uint32_t	sactive;	/* Port SActive register */
	uint32_t	snotific; 	/* Port SNotification register */
};

typedef struct sata_port_scr sata_port_scr_t;

/*
 * SATA Port Multiplier general status and control register block.
 * The gscr0, gscr1, gscr2 are the copyies of the register on port multiplier.
 * GSCR[0], GSCR[1], GSCR[2] are defined in SATA defined by Port Multiplier
 * 1.0/1.1/1.2 spec.
 */
struct sata_pmult_gscr {
	uint32_t	gscr0;		/* Product Identifier register */
	uint32_t	gscr1;		/* Resrved Information register */
	uint32_t	gscr2;		/* Port Information register */
	uint32_t	gscr64;		/* Feature register */
	uint32_t	resv[4];	/* Reseved */
};

typedef struct sata_pmult_gscr sata_pmult_gscr_t;

/*
 * SATA Device Structure (rev 1)
 * Used to request/return state of the controller, port, port multiplier
 * or an attached drive:
 *  	The satadev_addr.cport, satadev_addr.pmport and satadev_addr.qual
 *  	fields are used to specify SATA address (see sata_address structure
 *  	description).
 * 	The satadev_scr structure is used to pass the content of a port
 *	status and control registers.
 *	The satadev_add_info field is used by SATA HBA driver to return an
 *	additional information, which type depends on the function using
 *	sata_device as argument. For example:
 *	- in case of sata_tran_probe_port() this field should contain
 *	a number of available Port Multiplier device ports;
 *	- in case of sata_hba_event_notify() this field may contain
 *	a value specific for a reported event.
 */
#define	SATA_DEVICE_REV_1	1
#define	SATA_DEVICE_REV		SATA_DEVICE_REV_1

struct sata_device
{
	int		satadev_rev;		/* structure  version */
	struct sata_address satadev_addr;	/* sata port/device address */
	uint32_t	satadev_state;		/* Port or device state */
	uint32_t	satadev_type;		/* Attached device type */
	struct sata_port_scr satadev_scr; 	/* Port status and ctrl regs */
	uint32_t	satadev_add_info;	/* additional information, */
						/* function specific */
};

typedef struct sata_device sata_device_t;

_NOTE(SCHEME_PROTECTS_DATA("unshared data", sata_device))


/*
 * satadev_state field of sata_device structure.
 * Common flags specifying current state of a port or an attached drive.
 * These states are mutually exclusive, obviously
 */
#define	SATA_STATE_UNKNOWN		0x000000
#define	SATA_STATE_READY		0x000010

/*
 * Attached drive specific states (satadev_state field of the sata_device
 * structure).
 * SATA_DSTATE_PWR_ACTIVE, SATA_DSTATE_PWR_IDLE and SATA_DSTATE_PWR_STANDBY
 * are mutually exclusive. All other states may be combined with each other
 * and with one of the power states.
 * These flags may be used only if the address qualifier (satadev_addr.qual) is
 * set to SATA_ADDR_DCPORT or SATA_ADDR_DPMPORT value.
 */

#define	SATA_DSTATE_PWR_ACTIVE		0x000100
#define	SATA_DSTATE_PWR_IDLE		0x000200
#define	SATA_DSTATE_PWR_STANDBY		0x000400
#define	SATA_DSTATE_RESET		0x001000
#define	SATA_DSTATE_PMULT_INIT		0x002000
#define	SATA_DSTATE_FAILED		0x008000

/* Mask for drive power states */
#define	SATA_DSTATE_PWR			(SATA_DSTATE_PWR_ACTIVE | \
					SATA_DSTATE_PWR_IDLE | \
					SATA_DSTATE_PWR_STANDBY)
/*
 * SATA Port specific states (satadev_state field of sata_device structure).
 * SATA_PSTATE_PWRON and SATA_PSTATE_PWROFF are mutually exclusive.
 * All other states may be combined with each other and with one of the power
 * level state.
 * These flags may be used only if the address qualifier (satadev_addr.qual) is
 * set to SATA_ADDR_CPORT or SATA_ADDR_PMPORT value.
 */

#define	SATA_PSTATE_PWRON		0x010000
#define	SATA_PSTATE_PWROFF		0X020000
#define	SATA_PSTATE_SHUTDOWN		0x040000
#define	SATA_PSTATE_FAILED		0x080000

/* Mask for the valid port-specific state flags */
#define	SATA_PSTATE_VALID		(SATA_PSTATE_PWRON | \
					SATA_PSTATE_PWROFF | \
					SATA_PSTATE_SHUTDOWN | \
					SATA_PSTATE_FAILED)

/* Mask for a port power states */
#define	SATA_PSTATE_PWR			(SATA_PSTATE_PWRON | \
					SATA_PSTATE_PWROFF)
/*
 * Device type (in satadev_type field of sata_device structure).
 * More device types may be added in the future.
 */

#define	SATA_DTYPE_NONE			0x00	/* No device attached */
#define	SATA_DTYPE_ATADISK		0x01	/* ATA disk */
#define	SATA_DTYPE_ATAPI		0x40	/* ATAPI device */
#define	SATA_DTYPE_ATAPICD	\
	(SATA_DTYPE_ATAPI|0x02)			/* ATAPI CD/DVD device */
#define	SATA_DTYPE_ATAPITAPE	\
	(SATA_DTYPE_ATAPI|0x04)			/* ATAPI tape */
#define	SATA_DTYPE_ATAPIDISK	\
	(SATA_DTYPE_ATAPI|0x08)			/* ATAPI disk */
#define	SATA_DTYPE_PMULT		0x10	/* Port Multiplier */
#define	SATA_DTYPE_UNKNOWN		0x20	/* Device attached, unkown */
#define	SATA_DTYPE_ATAPIPROC	\
	(SATA_DTYPE_ATAPI|0x80)			/* ATAPI processor */


/*
 * SATA cmd structure  (rev 1)
 *
 * SATA HBA framework always sets all fields except status_reg and error_reg.
 * SATA HBA driver action depends on the addressing type specified by
 * addr_type field:
 * If LBA48 addressing is indicated, SATA HBA driver has to load values from
 * satacmd_sec_count_msb_reg, satacmd_lba_low_msb_reg,
 * satacmd_lba_mid_msb_reg and satacmd_lba_hi_msb_reg
 * to appropriate registers prior to loading other registers.
 * For other addressing modes, SATA HBA driver should skip loading values
 * from satacmd_sec_count_msb_reg, satacmd_lba_low_msb_reg,
 * satacmd_lba_mid_msb_reg and satacmd_lba_hi_msb_reg
 * fields and load only remaining field values to corresponding registers.
 *
 * satacmd_sec_count_msb and satamcd_sec_count_lsb values are loaded into
 * sec_count register, satacmd_sec_count_msb loaded first (if LBA48
 * addressing is used).
 * satacmd_lba_low_msb and satacmd_lba_low_lsb values are loaded into the
 * lba_low register, satacmd_lba_low_msb loaded first (if LBA48 addressing
 * is used). The lba_low register is the newer name for the old
 * sector_number register.
 * satacmd_lba_mid_msb and satacmd_lba_mid_lsb values are loaded into lba_mid
 * register, satacmd_lba_mid_msb loaded first (if LBA48 addressing is used).
 * The lba_mid register is the newer name for the old cylinder_low register.
 * satacmd_lba_high_msb and satacmd_lba_high_lsb values are loaded into
 * the lba_high regster, satacmd_lba_high_msb loaded first (if LBA48
 * addressing is used). The lba_high register  is a newer name for the old
 * cylinder_high register.
 *
 * No addressing mode is selected when an ata command does not involve actual
 * reading/writing data from/to the media (for example IDENTIFY DEVICE or
 * SET FEATURE command), or the ATAPI PACKET command is sent.
 * If ATAPI PACKET command is sent and tagged commands are used,
 * SATA HBA driver has to provide and manage a tag value and
 * set it into the sector_count register.
 *
 * Device Control register is not specified in sata_cmd structure - SATA HBA
 * driver shall set it accordingly to current mode of operation (interrupt
 * enable/disable).
 *
 * Buffer structure's b_flags should be used to determine the
 * address type of b_un.b_addr. However, there is no need to allocate DMA
 * resources for the buffer in SATA HBA driver.
 * DMA resources for a buffer structure are allocated by the SATA HBA
 * framework. Scatter/gather list is to be used only for DMA transfers
 * and it should be based on the DMA cookies list.
 *
 * Upon completion of a command, SATA HBA driver has to update
 * satacmd_status_reg and satacmd_error_reg to reflect the contents of
 * the corresponding device status and error registers.
 * If the command completed successfully, satacmd_flags.sata_copy_xxx flags
 * specify what register fields should be updated in sata_cmd structure.
 * If the command completed with error, SATA HBA driver has to update
 * satacmd_sec_count_msb, satacmd_sec_count_lsb, satacmd_lba_low_msb,
 * satacmd_lba_low_lsb, satacmd_lba_mid_msb, satacmd_lba_mid_lsb,
 * satacmd_lba_high_msb and satacmd_lba_high_lsb to values read from the
 * corresponding device registers.
 * If an operation could not complete because of the port error, the
 * sata_pkt.satapkt_device.satadev_scr structure has to be updated.
 *
 * If ATAPI PACKET command was sent and command completed with error,
 * rqsense structure has to be filed by SATA HBA driver. The satacmd_arq_cdb
 * points to pre-set request sense cdb that may be used for issuing request
 * sense data from the device.
 *
 * The sata_max_queue_depth field specifies the maximum allowable queue depth
 * minus one, i.e. for maximum queue depth of 32, sata_max_queue_depth would
 * be set to value 0x1f.
 * If FPDMA-type command was sent and command completed with error, the HBA
 * driver may use pre-set command READ LOG EXTENDED command pointed to
 * by satacmd_rle_sata_cmd field to retrieve error data from a device.
 * Only ATA register fields of the sata_cmd are set-up for that purpose.
 *
 * If the READ MULTIPLIER command was specified in cmd_reg (command directed
 * to a port multiplier host port rather then to an attached device),
 * upon the command completion SATA HBA driver has to update_sector count
 * and lba fields of the sata_cmd structure to values returned via
 * command block registers (task file registers).
 */
#define	SATA_CMD_REV_1	1
#define	SATA_CMD_REV_2	2
#define	SATA_CMD_REV_3	3
#define	SATA_CMD_REV	SATA_CMD_REV_3

#define	SATA_ATAPI_MAX_CDB_LEN	16	/* Covers both 12 and 16 byte cdbs */
#define	SATA_ATAPI_RQSENSE_LEN	24	/* Allocated Request Sense data */
#define	SATA_ATAPI_MIN_RQSENSE_LEN 18	/* Min Fixed size Request Sense data */
#define	SATA_ATAPI_RQSENSE_CDB_LEN 6	/* Request Sense CDB length */

#define	SATA_MAX_QUEUE_DEPTH	32	/* Default max queue depth */

struct sata_cmd {
	int		satacmd_rev;		/* version */
	struct buf	*satacmd_bp;		/* ptr to buffer structure */
	struct sata_cmd_flags {
		uint32_t	sata_data_direction : 3;	 /* 0-2 */
		uint32_t	: 1;		/* reserved */	 /* 3 */
		uint32_t	sata_queue_stag : 1;		 /* 4 */
		uint32_t	sata_queue_otag : 1;		 /* 5 */
		uint32_t	: 2;		/* reserved */	 /* 6-7 */
		uint32_t	sata_queued : 1;		 /* 8 */
		uint32_t	: 3;		/* reserved */	 /* 9-11 */
		uint32_t	sata_ignore_dev_reset : 1;	 /* 12 */
		uint32_t	sata_clear_dev_reset : 1;	 /* 13 */
		uint32_t	: 2;		/* reserved */	 /* 14-15 */
		uint32_t	sata_special_regs : 1;		 /* 16 */
		uint32_t	sata_copy_out_sec_count_msb : 1; /* 17 */
		uint32_t	sata_copy_out_lba_low_msb : 1;	 /* 18 */
		uint32_t	sata_copy_out_lba_mid_msb : 1;	 /* 19 */
		uint32_t	sata_copy_out_lba_high_msb : 1;	 /* 20 */
		uint32_t	sata_copy_out_sec_count_lsb : 1; /* 21 */
		uint32_t	sata_copy_out_lba_low_lsb : 1;	 /* 22 */
		uint32_t	sata_copy_out_lba_mid_lsb : 1;	 /* 23 */
		uint32_t	sata_copy_out_lba_high_lsb : 1;	 /* 24 */
		uint32_t	sata_copy_out_device_reg : 1;	 /* 25 */
		uint32_t	sata_copy_out_error_reg : 1;	 /* 26 */
		uint32_t	sata_max_queue_depth: 5;	 /* 27-31 */
	} satacmd_flags;
	uint8_t 	satacmd_addr_type; 	/* addr type: LBA28, LBA48 */
	uint8_t		satacmd_features_reg_ext; /* features reg extended */
	uint8_t		satacmd_sec_count_msb;	/* sector count MSB (LBA48) */
	uint8_t		satacmd_lba_low_msb; 	/* LBA Low MSB (LBA48) */
	uint8_t		satacmd_lba_mid_msb;	/* LBA Mid MSB (LBA48) */
	uint8_t		satacmd_lba_high_msb;	/* LBA High MSB (LBA48) */
	uint8_t		satacmd_sec_count_lsb;	/* sector count LSB */
	uint8_t		satacmd_lba_low_lsb;	/* LBA Low LSB */
	uint8_t		satacmd_lba_mid_lsb;	/* LBA Mid LSB */
	uint8_t		satacmd_lba_high_lsb;	/* LBA High LSB */
	uint8_t		satacmd_device_reg;	/* ATA dev reg & LBA28 MSB */
	uint8_t		satacmd_cmd_reg;	/* ata command code */
	uint8_t		satacmd_features_reg;	/* ATA features register */
	uint8_t		satacmd_status_reg;	/* ATA status register */
	uint8_t		satacmd_error_reg;	/* ATA error register  */
	uint8_t		satacmd_acdb_len;	/* ATAPI cdb length */
	uint8_t		satacmd_acdb[SATA_ATAPI_MAX_CDB_LEN]; /* ATAPI cdb */

						/* kept for binary compat. */
	uint8_t		*pad1;			/* unused */

	uint8_t 	satacmd_rqsense[SATA_ATAPI_RQSENSE_LEN];
						/*
						 * Error retrieval buffer
						 * dma handle pointer
						 * (for buffer DMA syncing)
						 * Valid only in error
						 * retrieval packet!
						 */
	ddi_dma_handle_t *satacmd_err_ret_buf_handle;

	int		satacmd_num_dma_cookies; /* number of dma cookies */
						/* ptr to dma cookie list */
	ddi_dma_cookie_t *satacmd_dma_cookie_list;
};

typedef struct sata_cmd sata_cmd_t;

_NOTE(SCHEME_PROTECTS_DATA("unshared data", sata_cmd))


/* ATA address type (in satacmd_addr_type field */
#define	ATA_ADDR_LBA	0x1
#define	ATA_ADDR_LBA28	0x2
#define	ATA_ADDR_LBA48	0x4

/*
 * satacmd_flags : contain data transfer direction flags,
 * tagged queuing type flags, queued command flag, and reset state handling
 * flag.
 */

/*
 * Data transfer direction flags (satacmd_flags.sata_data_direction)
 * Direction flags are mutually exclusive.
 */
#define	SATA_DIR_NODATA_XFER	0x0001	/* No data transfer */
#define	SATA_DIR_READ		0x0002	/* Reading data from a device */
#define	SATA_DIR_WRITE		0x0004	/* Writing data to a device */

/*
 * Tagged Queuing type flags
 * 	satacmd_flags.sata_queue_stag
 * 	satacmd_flags.sata_queue_otag
 *
 * These flags indicate how the SATA command should be queued.
 *
 * sata_queue_stag
 * Simple-queue-tagged command. It may be executed out-of-order in respect
 * to other queued commands.
 * sata_queue_otag
 * Ordered-queue-tagged command. It cannot be executed out-of-order in
 * respect to other commands, i.e. it should be executed in the order of
 * being transported to the HBA.
 *
 * Translated head-of-queue-tagged scsi commands and commands that are
 * to be put at the head of the queue are treated as sata_queue_otag
 * tagged commands.
 */


/*
 * Queuing command set-up flag (satacmd_flags.sata_queued).
 * This flag indicates that sata_cmd was set-up for DMA Queued command
 * (either READ_DMA_QUEUED, READ_DMA_QUEUED_EXT, WRITE_DMA_QUEUED or
 * WRITE_DMA_QUEUED_EXT command) or one of the Native Command Queuing commands
 * (either READ_FPDMA_QUEUED or WRITE_FPDMA_QUEUED).
 * This flag will be used only if sata_tran_hba_flags indicates controller
 * support for queuing and the device for which sata_cmd is prepared supports
 * either legacy queuing (indicated by Device Identify data word 83 bit 2)
 * or NCQ (indicated by  word 76 of Device Identify data).
 */

/*
 * Reset state handling
 *	satacmd_flags.sata_ignore_dev_reset
 *	satacmd_flags.sata_clear_dev_reset
 *
 * SATA HBA device enters reset state if the device was subjected to
 * the Device Reset (may also enter this state if the device was reset
 * as a side effect of port reset). SATA HBA driver sets this state.
 * Device stays in this condition until explicit request from SATA HBA
 * framework to clear the state.
 */

/*
 * SATA Packet structure (rev 1)
 * hba_driver_private is for a private use of the SATA HBA driver;
 * satapkt_framework_private is used only by SATA HBA framework;
 * satapkt_comp is a callback function to be called when packet
 * execution is completed (for any reason) if mode of operation is not
 * synchronous (SATA_OPMODE_SYNCH);
 * satapkt_reason specifies why the packet operation was completed
 *
 * NOTE: after the packet completion callback SATA HBA driver should not
 * attempt to access any sata_pkt fields because sata_pkt is not valid anymore
 * (it could have been destroyed).
 * Since satapkt_hba_driver_private field cannot be retrieved, any hba private
 * data respources allocated per packet and accessed via this pointer should
 * either be freed before the completion callback is done, or the pointer has
 * to be saved by the HBA driver before the completion callback.
 */
#define	SATA_PKT_REV_1	1
#define	SATA_PKT_REV	SATA_PKT_REV_1

struct sata_pkt {
	int		satapkt_rev;		/* version */
	struct sata_device satapkt_device;	/* Device address/type */

						/* HBA driver private data */
	void		*satapkt_hba_driver_private;

						/* SATA framework priv data */
	void		*satapkt_framework_private;

						/* Rqsted mode of operation */
	uint32_t	satapkt_op_mode;

	struct sata_cmd	satapkt_cmd;		/* composite sata command */
	int		satapkt_time;		/* time allotted to command */
	void		(*satapkt_comp)(struct sata_pkt *); /* callback */
	int		satapkt_reason; 	/* completion reason */
};

typedef struct sata_pkt sata_pkt_t;

_NOTE(SCHEME_PROTECTS_DATA("unshared data", sata_pkt))


/*
 * Operation mode flags (in satapkt_op_mode field of sata_pkt structure).
 * Use to specify what should be a mode of operation for specified command.
 * Default (000b) means use Interrupt and Asynchronous mode to
 * perform an operation.
 * Synchronous operation menas that the packet operation has to be completed
 * before the function called to initiate the operation returns.
 */
#define	SATA_OPMODE_INTERRUPTS	0 /* Use interrupts (hint) */
#define	SATA_OPMODE_POLLING	1 /* Use polling instead of interrupts */
#define	SATA_OPMODE_ASYNCH	0 /* Return immediately after accepting pkt */
#define	SATA_OPMODE_SYNCH	4 /* Perform synchronous operation */

/*
 * satapkt_reason values:
 *
 * SATA_PKT_QUEUE_FULL - cmd not sent because of queue full (detected
 * 	by the controller). If a device reject command for this reason, it
 * 	should be reported as SATA_PKT_DEV_ERROR
 *
 * SATA_PKT_CMD_NOT_SUPPORTED - command not supported by a controller
 *	Controller is unable to send such command to a device.
 *	If device rejects a command, it should be reported as
 *	SATA_PKT_DEV_ERROR.
 *
 * SATA_PKT_DEV_ERROR - cmd failed because of device reported an error.
 *	The content of status_reg (ERROR bit has to be set) and error_reg
 *	fields of the sata_cmd structure have to be set and will be used
 *	by SATA HBA Framework to determine the error cause.
 *
 * SATA_PKT_PORT_ERROR - cmd failed because of a link or a port error.
 *	Link failed / no communication with a device / communication error
 *	or other port related error was detected by a controller.
 *	sata_pkt.satapkt_device.satadev_scr.sXXXXXXX words have to be set.
 *
 * SATA_PKT_ABORTED - cmd execution was aborted by the request from the
 *	framework. Abort mechanism is HBA driver specific.
 *
 * SATA_PKT_TIMEOUT - cmd execution has timed-out. Timeout specified by
 *	 pkt_time was exceeded. The command was terminated by the SATA HBA
 *	driver.
 *
 * SATA_PKT_COMPLETED - this is a value returned when an operation
 *	completes without errors.
 *
 * SATA_PKT_BUSY - packet was not accepted for execution because the
 *      driver was busy performing some other operation(s).
 *
 * SATA_PKT_RESET - packet execution was aborted because of device
 * reset originated by either the HBA driver or the SATA framework.
 *
 */

#define	SATA_PKT_BUSY			-1	/* Not completed, busy */
#define	SATA_PKT_COMPLETED		0	/* No error */
#define	SATA_PKT_DEV_ERROR		1	/* Device reported error */
#define	SATA_PKT_QUEUE_FULL		2	/* Not accepted, queue full */
#define	SATA_PKT_PORT_ERROR		3	/* Not completed, port error */
#define	SATA_PKT_CMD_UNSUPPORTED	4	/* Cmd unsupported */
#define	SATA_PKT_ABORTED		5	/* Aborted by request */
#define	SATA_PKT_TIMEOUT		6	/* Operation timeut */
#define	SATA_PKT_RESET			7	/* Aborted by reset request */

/*
 * Error retrieval sata packet types
 */
#define	SATA_ERR_RETR_PKT_TYPE_NCQ	1
#define	SATA_ERR_RETR_PKT_TYPE_ATAPI	2

/*
 * Read/write port multiplier packet types
 */
#define	SATA_RDWR_PMULT_PKT_TYPE_READ	1
#define	SATA_RDWR_PMULT_PKT_TYPE_WRITE	2

/*
 * Hoplug functions vector structure (rev 1)
 */
#define	SATA_TRAN_HOTPLUG_OPS_REV_1	1

struct sata_tran_hotplug_ops {
	int	sata_tran_hotplug_ops_rev; /* version */
	int	(*sata_tran_port_activate)(dev_info_t  *, sata_device_t *);
	int	(*sata_tran_port_deactivate)(dev_info_t  *, sata_device_t *);
};

typedef struct sata_tran_hotplug_ops sata_tran_hotplug_ops_t;


/*
 * Power management functions vector structure (rev 1)
 * The embedded function returns information about the controller's
 * power level.
 * Additional functions may be added in the future without changes to
 * sata_tran structure.
 */
#define	SATA_TRAN_PWRMGT_OPS_REV_1	1

struct sata_tran_pwrmgt_ops {
	int	sata_tran_pwrmgt_ops_rev; /* version */
	int	(*sata_tran_get_pwr_level)(dev_info_t  *, sata_device_t *);
};

typedef struct sata_tran_pwrmgt_ops sata_tran_pwrmgt_ops_t;


/*
 * SATA port PHY Power Level
 * These states correspond to the interface power management state as defined
 * in Serial ATA spec.
 */
#define	SATA_TRAN_PORTPWR_LEVEL1	1 /* Interface in active PM state */
#define	SATA_TRAN_PORTPWR_LEVEL2	2 /* Interface in PARTIAL PM state */
#define	SATA_TRAN_PORTPWR_LEVEL3	3 /* Interface in SLUMBER PM state */

/*
 * SATA HBA Tran structure (rev 1)
 * Registered with SATA Framework
 *
 * dma_attr is a pointer to data (buffer) dma attibutes of the controller
 * DMA engine.
 *
 * The qdepth field specifies number of commands that may be accepted by
 * the controller. Value range 1-32. A value greater than 1 indicates that
 * the controller supports queuing. Support for Native Command Queuing
 * indicated by SATA_CTLF_NCQ flag also requires qdepth set to a value
 * greater then 1.
 *
 */
#define	SATA_TRAN_HBA_REV_1	1
#define	SATA_TRAN_HBA_REV_2	2
#define	SATA_TRAN_HBA_REV_3	3
#define	SATA_TRAN_HBA_REV	SATA_TRAN_HBA_REV_3

struct sata_hba_tran {
	int		sata_tran_hba_rev;	/* version */
	dev_info_t	*sata_tran_hba_dip;	/* Controler dev info */
	ddi_dma_attr_t	*sata_tran_hba_dma_attr; /* DMA attributes */
	int		sata_tran_hba_num_cports; /* Num of HBA device ports */
	uint16_t	sata_tran_hba_features_support; /* HBA features */
	uint16_t	sata_tran_hba_qdepth;	/* HBA-supported queue depth */

	int		(*sata_tran_probe_port)(dev_info_t *, sata_device_t *);
	int		(*sata_tran_start)(dev_info_t *, sata_pkt_t *);
	int		(*sata_tran_abort)(dev_info_t *, sata_pkt_t *, int);
	int		(*sata_tran_reset_dport)(dev_info_t *,
					sata_device_t *);
	int		(*sata_tran_selftest)(dev_info_t *, sata_device_t *);

						/* Hotplug vector */
	struct sata_tran_hotplug_ops *sata_tran_hotplug_ops;

						/* Power mgt vector */
	struct sata_tran_pwrmgt_ops *sata_tran_pwrmgt_ops;

	int		(*sata_tran_ioctl)(dev_info_t *, int, intptr_t);
};

typedef struct sata_hba_tran sata_hba_tran_t;


/*
 * Controller's features support flags (sata_tran_hba_features_support).
 * Note: SATA_CTLF_NCQ indicates that SATA controller supports NCQ in addition
 * to legacy queuing commands, indicated by SATA_CTLF_QCMD flag.
 */

#define	SATA_CTLF_ATAPI			0x001 /* ATAPI support */
#define	SATA_CTLF_PORT_MULTIPLIER 	0x010 /* Port Multiplier suport */
#define	SATA_CTLF_HOTPLUG		0x020 /* Hotplug support */
#define	SATA_CTLF_ASN			0x040 /* Asynchronous Event Support */
#define	SATA_CTLF_QCMD			0x080 /* Queued commands support */
#define	SATA_CTLF_NCQ			0x100 /* NCQ support */
#define	SATA_CTLF_PMULT_FBS		0x200 /* FIS-based switching support */

/*
 * sata_tran_start() return values.
 * When pkt is not accepted, the satapkt_reason has to be updated
 * before function returns - it should reflect the same reason for not being
 * executed as the return status of above functions.
 * If pkt was accepted and executed synchronously,
 * satapk_reason should indicate a completion status.
 */
#define	SATA_TRAN_ACCEPTED		0 /* accepted */
#define	SATA_TRAN_QUEUE_FULL		1 /* not accepted, queue full */
#define	SATA_TRAN_PORT_ERROR		2 /* not accepted, port error */
#define	SATA_TRAN_CMD_UNSUPPORTED	3 /* not accepted, cmd not supported */
#define	SATA_TRAN_BUSY			4 /* not accepted, busy */


/*
 * sata_tran_abort() abort type flag
 */
#define	SATA_ABORT_PACKET		0
#define	SATA_ABORT_ALL_PACKETS		1


/*
 * Events handled by SATA HBA Framework
 * More then one event may be reported at the same time
 *
 * SATA_EVNT__DEVICE_ATTACHED
 * HBA detected the presence of a device ( electrical connection with
 * a device was detected ).
 *
 * SATA_EVNT_DEVICE_DETACHED
 * HBA detected the detachment of a device (electrical connection with
 * a device was broken)
 *
 * SATA_EVNT_LINK_LOST
 * HBA lost link with an attached device
 *
 * SATA_EVNT_LINK_ESTABLISHED
 * HBA established a link with an attached device
 *
 * SATA_EVNT_PORT_FAILED
 * HBA has determined that the port failed and is unuseable
 *
 * SATA_EVENT_DEVICE_RESET
 * SATA device was reset, causing loss of the device setting
 *
 * SATA_EVNT_PWR_LEVEL_CHANGED
 * A port or entire SATA controller power level has changed
 *
 * SATA_EVNT_PMULT_LINK_CHANGED
 * Port multiplier detect change on a link of its device port
 *
 */
#define	SATA_EVNT_DEVICE_ATTACHED	0x01
#define	SATA_EVNT_DEVICE_DETACHED	0x02
#define	SATA_EVNT_LINK_LOST		0x04
#define	SATA_EVNT_LINK_ESTABLISHED	0x08
#define	SATA_EVNT_PORT_FAILED		0x10
#define	SATA_EVNT_DEVICE_RESET		0x20
#define	SATA_EVNT_PWR_LEVEL_CHANGED	0x40
#define	SATA_EVNT_PMULT_LINK_CHANGED	0x80

/*
 * SATA Framework interface entry points
 */
int 	sata_hba_init(struct modlinkage *);
int 	sata_hba_attach(dev_info_t *, sata_hba_tran_t *, ddi_attach_cmd_t);
int 	sata_hba_detach(dev_info_t *, ddi_detach_cmd_t);
void 	sata_hba_fini(struct modlinkage *);
void 	sata_hba_event_notify(dev_info_t *, sata_device_t *, int);
sata_pkt_t *sata_get_error_retrieval_pkt(dev_info_t *, sata_device_t *, int);
void	sata_free_error_retrieval_pkt(sata_pkt_t *);
sata_pkt_t *sata_get_rdwr_pmult_pkt(dev_info_t *, sata_device_t *, uint8_t,
    uint32_t, uint32_t);
void	sata_free_rdwr_pmult_pkt(sata_pkt_t *);
void	sata_register_pmult(dev_info_t *, sata_device_t *, sata_pmult_gscr_t *);
void	sata_free_dma_resources(sata_pkt_t *);
void	sata_split_model(char *, char **, char **);

/*
 * SATA trace ring buffer constants
 */
#define	DMSG_RING_SIZE		0x100000	/* 1MB */
#define	DMSG_BUF_SIZE		256

/*
 * SATA trace ring buffer content
 */
typedef struct sata_trace_dmsg {
	dev_info_t		*dip;
	timespec_t		timestamp;
	char			buf[DMSG_BUF_SIZE];
	struct sata_trace_dmsg	*next;
} sata_trace_dmsg_t;

/*
 * SATA trace ring buffer header
 */
typedef struct sata_trace_rbuf {
	kmutex_t		lock;		/* lock to avoid clutter */
	int			looped;		/* completed ring */
	int			allocfailed;	/* dmsg mem alloc failed */
	size_t			size;		/* current size */
	size_t			maxsize;	/* max size */
	sata_trace_dmsg_t	*dmsgh;		/* messages head */
	sata_trace_dmsg_t	*dmsgp;		/* ptr to last message */
} sata_trace_rbuf_t;

/*
 * SATA trace ring buffer interfaces
 */
void sata_trace_debug(dev_info_t *, const char *fmt, ...);
void sata_vtrace_debug(dev_info_t *, const char *fmt, va_list);

#ifdef	__cplusplus
}
#endif

#endif /* _SATA_HBA_H */