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
|
/*
* 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 (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2018, Joyent, Inc.
* Copyright 2021 RackTop Systems, Inc.
*/
#ifndef _AHCIVAR_H
#define _AHCIVAR_H
#ifdef __cplusplus
extern "C" {
#endif
#include <sys/sata/adapters/ahci/ahciem.h>
/*
* AHCI address qualifier flags (in qual field of ahci_addr struct).
*/
#define AHCI_ADDR_NULL 0x00
#define AHCI_ADDR_PORT 0x01
#define AHCI_ADDR_PMPORT 0x02
#define AHCI_ADDR_PMULT 0x04
#define AHCI_ADDR_VALID (AHCI_ADDR_PORT | \
AHCI_ADDR_PMULT | \
AHCI_ADDR_PMPORT)
/*
* AHCI address structure.
*/
struct ahci_addr {
/* HBA port number */
uint8_t aa_port;
/* Port multiplier port number */
uint8_t aa_pmport;
/*
* AHCI_ADDR_NULL
* AHCI_ADDR_PORT
* AHCI_ADDR_PMPORT
* AHCI_ADDR_PMULT
*/
uint8_t aa_qual;
};
typedef struct ahci_addr ahci_addr_t;
_NOTE(SCHEME_PROTECTS_DATA("unshared data", ahci_addr))
#define AHCI_ADDR_IS_PORT(addrp) \
((addrp)->aa_qual & AHCI_ADDR_PORT)
#define AHCI_ADDR_IS_PMPORT(addrp) \
((addrp)->aa_qual & AHCI_ADDR_PMPORT)
#define AHCI_ADDR_IS_PMULT(addrp) \
((addrp)->aa_qual & AHCI_ADDR_PMULT)
#define AHCI_ADDR_IS_VALID(addrp) \
((addrp)->aa_port < SATA_MAX_CPORTS) && \
((addrp)->aa_pmport < SATA_MAX_PMPORTS) && \
((addrp)->aa_qual & AHCI_ADDR_VALID)
#define AHCI_ADDR_SET(addrp, port, pmport, qual) \
{ \
(addrp)->aa_port = port; \
(addrp)->aa_pmport = pmport; \
(addrp)->aa_qual = qual; \
}
#define AHCI_ADDR_SET_PORT(addrp, port) \
AHCI_ADDR_SET(addrp, port, 0, AHCI_ADDR_PORT)
#define AHCI_ADDR_SET_PMPORT(addrp, port, pmport) \
AHCI_ADDR_SET(addrp, port, pmport, AHCI_ADDR_PMPORT)
#define AHCI_ADDR_SET_PMULT(addrp, port) \
AHCI_ADDR_SET(addrp, port, SATA_PMULT_HOSTPORT, AHCI_ADDR_PMULT)
/* Type for argument of event handler */
typedef struct ahci_event_arg {
void *ahciea_ctlp;
void *ahciea_portp;
void *ahciea_addrp;
uint32_t ahciea_event;
} ahci_event_arg_t;
/* Warlock annotation */
_NOTE(DATA_READABLE_WITHOUT_LOCK(ahci_event_arg_t::ahciea_ctlp))
_NOTE(DATA_READABLE_WITHOUT_LOCK(ahci_event_arg_t::ahciea_portp))
_NOTE(DATA_READABLE_WITHOUT_LOCK(ahci_event_arg_t::ahciea_addrp))
_NOTE(DATA_READABLE_WITHOUT_LOCK(ahci_event_arg_t::ahciea_event))
/*
* ahci_pmult_info stores the information of a port multiplier and its
* sub-devices in case a port multiplier is attached to an HBA port.
*/
struct ahci_pmult_info {
/* Number of the device ports */
int ahcipmi_num_dev_ports;
/* Device type of the sub-devices of the port multipler */
uint8_t ahcipmi_device_type[SATA_MAX_PMPORTS];
/* State of port multiplier port */
uint32_t ahcipmi_port_state[SATA_MAX_PMPORTS];
/*
* Port multiplier port on which there is outstanding NCQ
* commands. Only make sense in command based switching mode.
*/
uint8_t ahcipmi_ncq_pmport;
/* Pending asynchronous notification events tags */
uint32_t ahcipmi_snotif_tags;
};
typedef struct ahci_pmult_info ahci_pmult_info_t;
/*
* flags for ahciport_flags
*
* AHCI_PORT_FLAG_MOPPING: this flag will be set when the HBA is stopped,
* and all the outstanding commands need to be aborted and sent to upper
* layers.
*
* AHCI_PORT_FLAG_POLLING: this flag will be set when the interrupt is
* disabled, and the command is executed in POLLING mode.
*
* AHCI_PORT_FLAG_RQSENSE: this flag will be set when a REQUEST SENSE which
* is used to retrieve sense data is being executed.
*
* AHCI_PORT_FLAG_STARTED: this flag will be set when the port is started,
* that is PxCMD.ST is set with '1', and be cleared when the port is put into
* idle, that is PxCMD.ST is changed from '1' to '0'.
*
* AHCI_PORT_FLAG_RDLOGEXT: this flag will be set when a READ LOG EXT which
* is used to retrieve NCQ failure context is being executed.
*
* AHCI_PORT_FLAG_NODEV: this flag will be set when a device is found gone
* during ahci_restart_port_wait_till_ready process.
*
* AHCI_PORT_FLAG_RDWR_PMULT: this flag will be set when a READ/WRITE
* PORTMULT command is being executed.
*
* AHCI_PORT_FLAG_IGNORE_IPMS: this flag will be set when enumerating a port
* multiplier. According AHCI spec, IPMS error should be ignore during
* enumeration of port multiplier.
*
* AHCI_PORT_FLAG_PMULT_SNTF: this flag will be set when the a asynchronous
* notification event on the port multiplier is being handled.
*
* AHCI_PORT_FLAG_HOTPLUG: this flag will be set when a hot plug event is
* being handled.
*
* AHCI_PORT_FLAG_ERRPRINT: this flag will be set when error recovery message
* will be printed. Note that, for INDENTIFY DEVICE command sent to ATAPI
* device or ATAPI PACKET command, this flag won't be set.
*/
#define AHCI_PORT_FLAG_MOPPING 0x02
#define AHCI_PORT_FLAG_POLLING 0x04
#define AHCI_PORT_FLAG_RQSENSE 0x08
#define AHCI_PORT_FLAG_STARTED 0x10
#define AHCI_PORT_FLAG_RDLOGEXT 0x20
#define AHCI_PORT_FLAG_NODEV 0x40
#define AHCI_PORT_FLAG_RDWR_PMULT 0x80
#define AHCI_PORT_FLAG_IGNORE_IPMS 0x100
#define AHCI_PORT_FLAG_PMULT_SNTF 0x200
#define AHCI_PORT_FLAG_HOTPLUG 0x400
#define AHCI_PORT_FLAG_ERRPRINT 0x800
typedef struct ahci_port {
/* The physical port number */
uint8_t ahciport_port_num;
/* Type of the device attached to the port */
uint8_t ahciport_device_type;
/* State of the port */
uint32_t ahciport_port_state;
/* Port multiplier struct */
ahci_pmult_info_t *ahciport_pmult_info;
/*
* AHCI_PORT_FLAG_MOPPING
* AHCI_PORT_FLAG_POLLING
* AHCI_PORT_FLAG_RQSENSE
* AHCI_PORT_FLAG_STARTED
* AHCI_PORT_FLAG_RDLOGEXT
* AHCI_PORT_FLAG_NODEV
* AHCI_PORT_FLAG_RDWR_PMULT
* AHCI_PORT_FLAG_IGNORE_IPMS
* AHCI_PORT_FLAG_PMULT_SNTF
* AHCI_PORT_FLAG_HOTPLUG
* AHCI_PORT_FLAG_ERRPRINT
*/
int ahciport_flags;
/* Pointer to received FIS structure */
ahci_rcvd_fis_t *ahciport_rcvd_fis;
ddi_dma_handle_t ahciport_rcvd_fis_dma_handle;
ddi_acc_handle_t ahciport_rcvd_fis_acc_handle;
ddi_dma_cookie_t ahciport_rcvd_fis_dma_cookie;
/* Pointer to command list structure */
ahci_cmd_header_t *ahciport_cmd_list;
ddi_dma_handle_t ahciport_cmd_list_dma_handle;
ddi_acc_handle_t ahciport_cmd_list_acc_handle;
ddi_dma_cookie_t ahciport_cmd_list_dma_cookie;
/* Pointer to cmmand table structure */
ahci_cmd_table_t \
*ahciport_cmd_tables[AHCI_PORT_MAX_CMD_SLOTS];
ddi_dma_handle_t \
ahciport_cmd_tables_dma_handle[AHCI_PORT_MAX_CMD_SLOTS];
ddi_acc_handle_t \
ahciport_cmd_tables_acc_handle[AHCI_PORT_MAX_CMD_SLOTS];
/* Condition variable used for sync mode commands */
kcondvar_t ahciport_cv;
/* The whole mutex for the port structure */
kmutex_t ahciport_mutex;
/* The maximum number of tags for native queuing command transfers */
int ahciport_max_ncq_tags;
/* Keep the tags of all pending non-ncq commands */
uint32_t ahciport_pending_tags;
/*
* Keep the tags of all pending ncq commands
* (READ/WRITE FPDMA QUEUED)
*/
uint32_t ahciport_pending_ncq_tags;
/* Keep all the pending sata packets */
sata_pkt_t *ahciport_slot_pkts[AHCI_PORT_MAX_CMD_SLOTS];
/* Used to check whether corresponding packet is timeout */
int ahciport_slot_timeout[AHCI_PORT_MAX_CMD_SLOTS];
/* Queue of completed (done) sata packet */
sata_pkt_t *ahciport_doneq;
/* Pointer of the tail of completed sata packet queue */
sata_pkt_t **ahciport_doneqtail;
/* the length of the completed sata packet queue */
uint32_t ahciport_doneq_len;
/* Keep the byte count of all PRD entries for every sata packet */
uint32_t \
ahciport_prd_bytecounts[AHCI_PORT_MAX_CMD_SLOTS];
/* Keep the error retrieval sata packet */
sata_pkt_t *ahciport_err_retri_pkt;
/* Keep the read/write port multiplier packet */
sata_pkt_t *ahciport_rdwr_pmult_pkt;
/*
* SATA HBA driver is supposed to remember and maintain device
* reset state. While the reset is in progress, it doesn't accept
* any more commands until receiving the command with
* SATA_CLEAR_DEV_RESET_STATE flag and SATA_IGNORE_DEV_RESET_STATE.
*/
int ahciport_reset_in_progress;
/* Taskq for handling event */
ddi_taskq_t *ahciport_event_taskq;
/* This is for error recovery handler */
ahci_event_arg_t *ahciport_event_args;
/* This is to calculate how many mops are in progress */
int ahciport_mop_in_progress;
} ahci_port_t;
/* Warlock annotation */
_NOTE(READ_ONLY_DATA(ahci_port_t::ahciport_rcvd_fis_dma_handle))
_NOTE(READ_ONLY_DATA(ahci_port_t::ahciport_cmd_list_dma_handle))
_NOTE(READ_ONLY_DATA(ahci_port_t::ahciport_cmd_tables_dma_handle))
_NOTE(MUTEX_PROTECTS_DATA(ahci_port_t::ahciport_mutex,
ahci_port_t::ahciport_device_type))
_NOTE(MUTEX_PROTECTS_DATA(ahci_port_t::ahciport_mutex,
ahci_port_t::ahciport_port_state))
_NOTE(MUTEX_PROTECTS_DATA(ahci_port_t::ahciport_mutex,
ahci_port_t::ahciport_flags))
_NOTE(MUTEX_PROTECTS_DATA(ahci_port_t::ahciport_mutex,
ahci_port_t::ahciport_pending_tags))
_NOTE(MUTEX_PROTECTS_DATA(ahci_port_t::ahciport_mutex,
ahci_port_t::ahciport_slot_pkts))
_NOTE(MUTEX_PROTECTS_DATA(ahci_port_t::ahciport_mutex,
ahci_port_t::ahciport_slot_timeout))
_NOTE(MUTEX_PROTECTS_DATA(ahci_port_t::ahciport_mutex,
ahci_port_t::ahciport_doneq))
_NOTE(MUTEX_PROTECTS_DATA(ahci_port_t::ahciport_mutex,
ahci_port_t::ahciport_doneqtail))
_NOTE(MUTEX_PROTECTS_DATA(ahci_port_t::ahciport_mutex,
ahci_port_t::ahciport_doneq_len))
_NOTE(MUTEX_PROTECTS_DATA(ahci_port_t::ahciport_mutex,
ahci_port_t::ahciport_reset_in_progress))
_NOTE(MUTEX_PROTECTS_DATA(ahci_port_t::ahciport_mutex,
ahci_port_t::ahciport_mop_in_progress))
_NOTE(MUTEX_PROTECTS_DATA(ahci_port_t::ahciport_mutex,
ahci_port_t::ahciport_event_taskq))
#define AHCI_NUM_PORTS(ctlp) \
(ctlp)->ahcictl_num_ports
#define AHCIPORT_NUM_PMPORTS(portp) \
(portp)->ahciport_pmult_info->ahcipmi_num_dev_ports
#define AHCIPORT_NCQ_PMPORT(ahci_portp) \
(ahci_portp->ahciport_pmult_info->ahcipmi_ncq_pmport)
#define AHCIPORT_DEV_TYPE(portp, addrp) \
(portp)->ahciport_device_type
#define AHCIPORT_PMDEV_TYPE(portp, addrp) \
(portp)->ahciport_pmult_info->ahcipmi_device_type \
[(addrp)->aa_pmport]
#define AHCIPORT_GET_DEV_TYPE(portp, addrp) \
(AHCI_ADDR_IS_PORT(addrp) | AHCI_ADDR_IS_PMULT(addrp) ? \
AHCIPORT_DEV_TYPE(portp, addrp) : \
AHCIPORT_PMDEV_TYPE(portp, addrp))
#define AHCIPORT_SET_DEV_TYPE(portp, addrp, type) \
if (AHCI_ADDR_IS_PORT(addrp) | AHCI_ADDR_IS_PMULT(addrp)) \
AHCIPORT_DEV_TYPE(portp, addrp) = type; \
else \
AHCIPORT_PMDEV_TYPE(portp, addrp) = type;
#define AHCIPORT_STATE(portp, addrp) \
(portp)->ahciport_port_state
#define AHCIPORT_PMSTATE(portp, addrp) \
(portp)->ahciport_pmult_info->ahcipmi_port_state \
[(addrp)->aa_pmport]
#define AHCIPORT_GET_STATE(portp, addrp) \
(AHCI_ADDR_IS_PORT(addrp) | AHCI_ADDR_IS_PMULT(addrp) ? \
AHCIPORT_STATE(portp, addrp) : AHCIPORT_PMSTATE(portp, addrp))
#define AHCIPORT_SET_STATE(portp, addrp, state) \
if (AHCI_ADDR_IS_PORT(addrp) | AHCI_ADDR_IS_PMULT(addrp)) \
AHCIPORT_STATE(portp, addrp) = state; \
else \
AHCIPORT_PMSTATE(portp, addrp) = state;
typedef enum ahci_em_flags {
AHCI_EM_PRESENT = 1 << 0,
AHCI_EM_RESETTING = 1 << 1,
AHCI_EM_TIMEOUT = 1 << 2,
AHCI_EM_QUIESCE = 1 << 3,
AHCI_EM_READY = 1 << 4,
} ahci_em_flags_t;
#define AHCI_EM_USABLE (AHCI_EM_PRESENT | AHCI_EM_READY)
typedef struct ahci_ctl {
dev_info_t *ahcictl_dip;
ushort_t ahcictl_venid;
ushort_t ahcictl_devid;
/* To map port number to cport number */
uint8_t ahcictl_port_to_cport[AHCI_MAX_PORTS];
/* To map cport number to port number */
uint8_t ahcictl_cport_to_port[AHCI_MAX_PORTS];
/* Number of controller ports */
int ahcictl_num_ports;
/* Number of command slots */
int ahcictl_num_cmd_slots;
/* Number of implemented ports */
int ahcictl_num_implemented_ports;
/* Bit map to indicate which port is implemented */
uint32_t ahcictl_ports_implemented;
ahci_port_t *ahcictl_ports[AHCI_MAX_PORTS];
int ahcictl_flags;
int ahcictl_power_level;
off_t ahcictl_pmcsr_offset;
/*
* AHCI_CAP_PIO_MDRQ
* AHCI_CAP_NO_MCMDLIST_NONQUEUE
* AHCI_CAP_NCQ
* AHCI_CAP_PM
* AHCI_CAP_BUF_32BIT_DMA
* AHCI_CAP_SCLO
* AHCI_CAP_COMMU_32BIT_DMA
* AHCI_CAP_INIT_PORT_RESET
* AHCI_CAP_SNTF
* AHCI_CAP_PMULT_CBSS
* AHCI_CAP_PMULT_FBSS
* AHCI_CAP_SRST_NO_HOSTPORT
*/
int ahcictl_cap;
/* Pci configuration space handle */
ddi_acc_handle_t ahcictl_pci_conf_handle;
/* Mapping into bar 5 - AHCI base address */
ddi_acc_handle_t ahcictl_ahci_acc_handle;
uintptr_t ahcictl_ahci_addr;
/* Pointer used for sata hba framework registration */
struct sata_hba_tran *ahcictl_sata_hba_tran;
/* DMA attributes for the data buffer */
ddi_dma_attr_t ahcictl_buffer_dma_attr;
/* DMA attributes for the rcvd FIS */
ddi_dma_attr_t ahcictl_rcvd_fis_dma_attr;
/* DMA attributes for the command list */
ddi_dma_attr_t ahcictl_cmd_list_dma_attr;
/* DMA attributes for command tables */
ddi_dma_attr_t ahcictl_cmd_table_dma_attr;
/* Used for watchdog handler */
timeout_id_t ahcictl_timeout_id;
/* Per controller mutex */
kmutex_t ahcictl_mutex;
/* Components for interrupt */
ddi_intr_handle_t *ahcictl_intr_htable; /* For array of intrs */
int ahcictl_intr_type; /* What type of interrupt */
int ahcictl_intr_cnt; /* # of intrs returned */
size_t ahcictl_intr_size; /* Size of intr array */
uint_t ahcictl_intr_pri; /* Intr priority */
int ahcictl_intr_cap; /* Intr capabilities */
/* FMA capabilities */
int ahcictl_fm_cap;
/*
* Enclosure information
*/
uint32_t ahcictl_em_loc;
uint32_t ahcictl_em_ctl;
uintptr_t ahcictl_em_tx_off;
ahci_em_flags_t ahcictl_em_flags;
ddi_taskq_t *ahcictl_em_taskq;
ahci_em_led_state_t ahcictl_em_state[AHCI_MAX_PORTS];
} ahci_ctl_t;
/* Warlock annotation */
_NOTE(READ_ONLY_DATA(ahci_ctl_t::ahcictl_ports))
_NOTE(READ_ONLY_DATA(ahci_ctl_t::ahcictl_cport_to_port))
_NOTE(READ_ONLY_DATA(ahci_ctl_t::ahcictl_port_to_cport))
_NOTE(MUTEX_PROTECTS_DATA(ahci_ctl_t::ahcictl_mutex,
ahci_ctl_t::ahcictl_power_level))
_NOTE(MUTEX_PROTECTS_DATA(ahci_ctl_t::ahcictl_mutex,
ahci_ctl_t::ahcictl_flags))
_NOTE(MUTEX_PROTECTS_DATA(ahci_ctl_t::ahcictl_mutex,
ahci_ctl_t::ahcictl_timeout_id))
#define AHCI_SUCCESS (0) /* Successful return */
#define AHCI_TIMEOUT (1) /* Timed out */
#define AHCI_FAILURE (-1) /* Unsuccessful return */
/* Flags for ahcictl_flags */
#define AHCI_ATTACH 0x1
#define AHCI_DETACH 0x2
#define AHCI_SUSPEND 0x4
#define AHCI_QUIESCE 0x8
/* Values for ahcictl_cap */
/* PIO Multiple DRQ Block */
#define AHCI_CAP_PIO_MDRQ 0x1
/*
* Multiple command slots in the command list cannot be used for
* non-queued commands
*/
#define AHCI_CAP_NO_MCMDLIST_NONQUEUE 0x2
/* Native Command Queuing (NCQ) */
#define AHCI_CAP_NCQ 0x4
/* Power Management (PM) */
#define AHCI_CAP_PM 0x8
/* 32-bit DMA addressing for buffer block */
#define AHCI_CAP_BUF_32BIT_DMA 0x10
/* Supports Command List Override */
#define AHCI_CAP_SCLO 0x20
/* 32-bit DMA addressing for communication memory descriptors */
#define AHCI_CAP_COMMU_32BIT_DMA 0x40
/* Port reset is needed for initialization */
#define AHCI_CAP_INIT_PORT_RESET 0x80
/* Port Asychronous Notification */
#define AHCI_CAP_SNTF 0x100
/* Port Multiplier Command-Based Switching Support (PMULT_CBSS) */
#define AHCI_CAP_PMULT_CBSS 0x200
/* Port Multiplier FIS-Based Switching Support (PMULT_FBSS) */
#define AHCI_CAP_PMULT_FBSS 0x400
/* Software Reset FIS cannot set pmport with 0xf for direct access device */
#define AHCI_CAP_SRST_NO_HOSTPORT 0x800
/* Enclosure Management Services available */
#define AHCI_CAP_EMS 0x1000
/* DevSleep Supported */
#define AHCI_CAP_SDS 0x2000
/* Flags controlling the restart port behavior */
#define AHCI_PORT_RESET 0x0001 /* Reset the port */
#define AHCI_RESET_NO_EVENTS_UP 0x0002 /* Don't send reset events up */
#define ERR_RETRI_CMD_IN_PROGRESS(ahci_portp) \
(ahci_portp->ahciport_flags & \
(AHCI_PORT_FLAG_RQSENSE|AHCI_PORT_FLAG_RDLOGEXT))
#define RDWR_PMULT_CMD_IN_PROGRESS(ahci_portp) \
(ahci_portp->ahciport_flags & \
AHCI_PORT_FLAG_RDWR_PMULT)
#define NON_NCQ_CMD_IN_PROGRESS(ahci_portp) \
(!ERR_RETRI_CMD_IN_PROGRESS(ahci_portp) && \
ahci_portp->ahciport_pending_tags != 0 && \
ahci_portp->ahciport_pending_ncq_tags == 0)
#define NCQ_CMD_IN_PROGRESS(ahci_portp) \
(!ERR_RETRI_CMD_IN_PROGRESS(ahci_portp) && \
ahci_portp->ahciport_pending_ncq_tags != 0)
/* Command type for ahci_claim_free_slot routine */
#define AHCI_NON_NCQ_CMD 0x0
#define AHCI_NCQ_CMD 0x1
#define AHCI_ERR_RETRI_CMD 0x2
#define AHCI_RDWR_PMULT_CMD 0x4
/* State values for ahci_attach */
#define AHCI_ATTACH_STATE_NONE (0x1 << 0)
#define AHCI_ATTACH_STATE_STATEP_ALLOC (0x1 << 1)
#define AHCI_ATTACH_STATE_FMA (0x1 << 2)
#define AHCI_ATTACH_STATE_REG_MAP (0x1 << 3)
#define AHCI_ATTACH_STATE_PCICFG_SETUP (0x1 << 4)
#define AHCI_ATTACH_STATE_INTR_ADDED (0x1 << 5)
#define AHCI_ATTACH_STATE_MUTEX_INIT (0x1 << 6)
#define AHCI_ATTACH_STATE_PORT_ALLOC (0x1 << 7)
#define AHCI_ATTACH_STATE_HW_INIT (0x1 << 8)
#define AHCI_ATTACH_STATE_TIMEOUT_ENABLED (0x1 << 9)
#define AHCI_ATTACH_STATE_ENCLOSURE (0x1 << 10)
/* Interval used for delay */
#define AHCI_10MS_TICKS (drv_usectohz(10000)) /* ticks in 10 ms */
#define AHCI_1MS_TICKS (drv_usectohz(1000)) /* ticks in 1 ms */
#define AHCI_100US_TICKS (drv_usectohz(100)) /* ticks in 100 us */
#define AHCI_10MS_USECS (10000) /* microsecs in 10 millisec */
#define AHCI_1MS_USECS (1000) /* microsecs in 1 millisec */
#define AHCI_100US_USECS (100)
/*
* The following values are the numbers of times to retry polled requests.
*/
#define AHCI_POLLRATE_HBA_RESET 100
#define AHCI_POLLRATE_PORT_SSTATUS 10
#define AHCI_POLLRATE_PORT_TFD_ERROR 1100
#define AHCI_POLLRATE_PORT_IDLE 50
#define AHCI_POLLRATE_PORT_SOFTRESET 100
#define AHCI_POLLRATE_GET_SPKT 100
#define AHCI_POLLRATE_PORT_IDLE_FR 500
/* Clearing & setting the n'th bit in a given tag */
#define CLEAR_BIT(tag, bit) (tag &= ~(0x1<<bit))
#define SET_BIT(tag, bit) (tag |= (0x1<<bit))
#if DEBUG
#define AHCI_DEBUG 1
#endif
#define AHCIDBG_INIT 0x0001
#define AHCIDBG_ENTRY 0x0002
#define AHCIDBG_PRDT 0x0004
#define AHCIDBG_EVENT 0x0008
#define AHCIDBG_POLL_LOOP 0x0010
#define AHCIDBG_PKTCOMP 0x0020
#define AHCIDBG_TIMEOUT 0x0040
#define AHCIDBG_INFO 0x0080
#define AHCIDBG_VERBOSE 0x0100
#define AHCIDBG_INTR 0x0200
#define AHCIDBG_ERRS 0x0400
#define AHCIDBG_ATACMD 0x0800
#define AHCIDBG_ATAPICMD 0x1000
#define AHCIDBG_SENSEDATA 0x2000
#define AHCIDBG_NCQ 0x4000
#define AHCIDBG_PM 0x8000
#define AHCIDBG_UNDERFLOW 0x10000
#define AHCIDBG_MSI 0x20000
#define AHCIDBG_PMULT 0x40000
extern uint32_t ahci_debug_flags;
#if DEBUG
#define AHCIDBG(flag, ahci_ctlp, fmt, args ...) \
if (ahci_debug_flags & (flag)) { \
ahci_log(ahci_ctlp, CE_WARN, fmt, ## args); \
if (ahci_ctlp == NULL) \
sata_trace_debug(NULL, fmt, ## args); \
else \
sata_trace_debug(ahci_ctlp->ahcictl_dip,\
fmt, ## args); \
}
#else
#define AHCIDBG(flag, ahci_ctlp, fmt, args ...) \
if (ahci_debug_flags & (flag)) { \
if (ahci_ctlp == NULL) \
sata_trace_debug(NULL, fmt, ## args); \
else \
sata_trace_debug(ahci_ctlp->ahcictl_dip,\
fmt, ## args); \
}
#endif /* DEBUG */
/*
* Minimum size required for the enclosure message buffer. This value is in
* 4-byte quantities. So we need to multiply it by two.
*/
#define AHCI_EM_BUFFER_MIN 2
/*
* Enclosure Management LED message format values
*/
#define AHCI_LED_OFF 0
#define AHCI_LED_ON 1
#define AHCI_LED_ACTIVITY_OFF 0
#define AHCI_LED_IDENT_OFF 3
#define AHCI_LED_FAULT_OFF 6
#define AHCI_LED_MASK 0x7
#define AHCI_EM_MSG_TYPE_LED 0
#define AHCI_EM_MSG_TYPE_SAFTE 1
#define AHCI_EM_MSG_TYPE_SES 2
#define AHCI_EM_MSG_TYPE_SGPIO 3
#pragma pack(1)
typedef struct ahci_em_led_msg {
uint8_t alm_hba;
uint8_t alm_pminfo;
uint16_t alm_value;
} ahci_em_led_msg_t;
typedef struct ahci_em_msg_hdr {
uint8_t aemh_rsvd;
uint8_t aemh_mlen;
uint8_t aemh_dlen;
uint8_t aemh_mtype;
} ahci_em_msg_hdr_t;
#pragma pack()
#ifdef __cplusplus
}
#endif
#endif /* _AHCIVAR_H */
|