Print this page
MFV: illumos-gate@fd6d41c5025e9fb45a115fc82d86e9983d1e9fd6
9815 Want basic AHCI enclosure services
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Reviewed by: Rob Johnston <rob.johnston@joyent.com>
Reviewed by: Yuri Pankov <yuripv@yuripv.net>
Approved by: Dan McDonald <danmcd@joyent.com>
Author: Robert Mustacchi <rm@joyent.com>
Conflicts:
        usr/src/cmd/Makefile
re #12164 Marvell 88SE9128: Appliance hard hangs on boot probing duplicated ahci device

@@ -20,10 +20,11 @@
  */
 
 /*
  * 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.
  */
 
 
 #ifndef _AHCIVAR_H
 #define _AHCIVAR_H

@@ -30,10 +31,12 @@
 
 #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

@@ -362,10 +365,20 @@
         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;

@@ -438,10 +451,20 @@
         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))

@@ -490,10 +513,12 @@
 #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
 
 /* 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 */
 

@@ -529,10 +554,11 @@
 #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 */

@@ -608,11 +634,48 @@
                             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 */