Home | History | Annotate | Download | only in SasV1Dxe
      1 /** @file
      2 
      3   Copyright (c) 2016 Linaro Ltd.
      4   Copyright (c) 2016 Hisilicon Limited.
      5 
      6   This program and the accompanying materials
      7   are licensed and made available under the terms and conditions of the BSD License
      8   which accompanies this distribution.  The full text of the license may be found at
      9   http://opensource.org/licenses/bsd-license.php
     10 
     11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include <Uefi.h>
     17 
     18 #include <Library/BaseLib.h>
     19 #include <Library/BaseMemoryLib.h>
     20 #include <Library/DebugLib.h>
     21 #include <Library/DevicePathLib.h>
     22 #include <Library/DmaLib.h>
     23 #include <Library/IoLib.h>
     24 #include <Library/MemoryAllocationLib.h>
     25 #include <Library/PcdLib.h>
     26 #include <Library/TimerLib.h>
     27 #include <Library/UefiBootServicesTableLib.h>
     28 #include <Library/UefiLib.h>
     29 #include <Library/UncachedMemoryAllocationLib.h>
     30 
     31 #include <Protocol/PlatformSasProtocol.h>
     32 #include <Protocol/ScsiPassThruExt.h>
     33 #include <IndustryStandard/Scsi.h>
     34 
     35 #define READ_REG32(Base, Offset) MmioRead32 ((Base) + (Offset))
     36 #define WRITE_REG32(Base, Offset, Val)  MmioWrite32 ((Base) + (Offset), (Val))
     37 
     38 #define PHY_READ_REG32(Base, Offset, phy) MmioRead32 ((Base) + (Offset) + 0x400 * (phy))
     39 #define PHY_WRITE_REG32(Base, Offset, phy, Val)  MmioWrite32 ((Base) + (Offset) + 0x400 * (phy), (Val))
     40 
     41 #define DLVRY_QUEUE_ENABLE              0x0
     42 #define IOST_BASE_ADDR_LO               0x8
     43 #define IOST_BASE_ADDR_HI               0xc
     44 #define ITCT_BASE_ADDR_LO               0x10
     45 #define ITCT_BASE_ADDR_HI               0x14
     46 #define BROKEN_MSG_ADDR_LO              0x18
     47 #define BROKEN_MSG_ADDR_HI              0x1c
     48 #define PHY_CONTEXT                     0x20
     49 #define PHY_PORT_NUM_MA                 0x28
     50 #define HGC_TRANS_TASK_CNT_LIMIT        0x38
     51 #define AXI_AHB_CLK_CFG                 0x3c
     52 #define HGC_SAS_TXFAIL_RETRY_CTRL       0x84
     53 #define HGC_GET_ITV_TIME                0x90
     54 #define DEVICE_MSG_WORK_MODE            0x94
     55 #define I_T_NEXUS_LOSS_TIME             0xa0
     56 #define BUS_INACTIVE_LIMIT_TIME         0xa8
     57 #define REJECT_TO_OPEN_LIMIT_TIME       0xac
     58 #define CFG_AGING_TIME                  0xbc
     59 #define HGC_DFX_CFG2                    0xc0
     60 #define FIS_LIST_BADDR_L                0xc4
     61 #define CFG_1US_TIMER_TRSH              0xcc
     62 #define CFG_SAS_CONFIG                  0xd4
     63 #define INT_COAL_EN                     0x1bc
     64 #define OQ_INT_COAL_TIME                0x1c0
     65 #define OQ_INT_COAL_CNT                 0x1c4
     66 #define ENT_INT_COAL_TIME               0x1c8
     67 #define ENT_INT_COAL_CNT                0x1cc
     68 #define OQ_INT_SRC                      0x1d0
     69 #define OQ_INT_SRC_MSK                  0x1d4
     70 #define ENT_INT_SRC1                    0x1d8
     71 #define ENT_INT_SRC2                    0x1dc
     72 #define ENT_INT_SRC_MSK1                0x1e0
     73 #define ENT_INT_SRC_MSK2                0x1e4
     74 #define SAS_ECC_INTR_MSK                0x1ec
     75 #define HGC_ERR_STAT_EN                 0x238
     76 #define DLVRY_Q_0_BASE_ADDR_LO          0x260
     77 #define DLVRY_Q_0_BASE_ADDR_HI          0x264
     78 #define DLVRY_Q_0_DEPTH                 0x268
     79 #define DLVRY_Q_0_WR_PTR                0x26c
     80 #define DLVRY_Q_0_RD_PTR                0x270
     81 #define COMPL_Q_0_BASE_ADDR_LO          0x4e0
     82 #define COMPL_Q_0_BASE_ADDR_HI          0x4e4
     83 #define COMPL_Q_0_DEPTH                 0x4e8
     84 #define COMPL_Q_0_WR_PTR                0x4ec
     85 #define COMPL_Q_0_RD_PTR                0x4f0
     86 #define AXI_CFG                         0x5100
     87 
     88 #define PORT_BASE                       0x800
     89 #define PHY_CFG                         (PORT_BASE + 0x0)
     90 #define PHY_CFG_ENA_OFF                 0
     91 #define PHY_CFG_ENA_MSK                 (0x1 << PHY_CFG_ENA_OFF)
     92 #define PHY_CFG_DC_OPT_OFF              2
     93 #define PHY_CFG_DC_OPT_MSK              (0x1 << PHY_CFG_DC_OPT_OFF)
     94 #define PROG_PHY_LINK_RATE              (PORT_BASE + 0xc)
     95 #define PHY_CTRL                        (PORT_BASE + 0x14)
     96 #define PHY_CTRL_RESET                  BIT0
     97 #define PHY_RATE_NEGO                   (PORT_BASE + 0x30)
     98 #define PHY_PCN                         (PORT_BASE + 0x44)
     99 #define SL_TOUT_CFG                     (PORT_BASE + 0x8c)
    100 #define SL_CONTROL                      (PORT_BASE + 0x94)
    101 #define SL_CONTROL_NOTIFY_EN            BIT0
    102 #define TX_ID_DWORD0                    (PORT_BASE + 0x9c)
    103 #define TX_ID_DWORD1                    (PORT_BASE + 0xa0)
    104 #define TX_ID_DWORD2                    (PORT_BASE + 0xa4)
    105 #define TX_ID_DWORD3                    (PORT_BASE + 0xa8)
    106 #define TX_ID_DWORD4                    (PORT_BASE + 0xaC)
    107 #define TX_ID_DWORD5                    (PORT_BASE + 0xb0)
    108 #define TX_ID_DWORD6                    (PORT_BASE + 0xb4)
    109 #define RX_IDAF_DWORD3                  (PORT_BASE + 0xd0)
    110 #define RX_IDAF_DWORD4                  (PORT_BASE + 0xd4)
    111 #define RXOP_CHECK_CFG_H                (PORT_BASE + 0xfc)
    112 #define DONE_RECEIVED_TIME              (PORT_BASE + 0x12c)
    113 #define CON_CFG_DRIVER                  (PORT_BASE + 0x130)
    114 #define PHY_CONFIG2                     (PORT_BASE + 0x1a8)
    115 #define PHY_CONFIG2_FORCE_TXDEEMPH_OFF  3
    116 #define PHY_CONFIG2_FORCE_TXDEEMPH_MSK  (0x1 << PHY_CONFIG2_FORCE_TXDEEMPH_OFF)
    117 #define CHL_INT_COAL_EN                 (PORT_BASE + 0x1d0)
    118 #define CHL_INT0                        (PORT_BASE + 0x1b0)
    119 #define CHL_INT0_PHYCTRL_NOTRDY         BIT0
    120 #define CHL_INT1                        (PORT_BASE + 0x1b4)
    121 #define CHL_INT2                        (PORT_BASE + 0x1b8)
    122 #define CHL_INT2_SL_PHY_ENA             BIT6
    123 #define CHL_INT0_MSK                    (PORT_BASE + 0x1bc)
    124 #define CHL_INT0_MSK_PHYCTRL_NOTRDY     BIT0
    125 #define CHL_INT1_MSK                    (PORT_BASE + 0x1c0)
    126 #define CHL_INT2_MSK                    (PORT_BASE + 0x1c4)
    127 #define DMA_TX_STATUS                   (PORT_BASE + 0x2d0)
    128 #define DMA_TX_STATUS_BUSY              BIT0
    129 #define DMA_RX_STATUS                   (PORT_BASE + 0x2e8)
    130 #define DMA_RX_STATUS_BUSY              BIT0
    131 
    132 #define QUEUE_CNT                       32
    133 #define QUEUE_SLOTS                     256
    134 #define SLOT_ENTRIES                    8192
    135 #define PHY_CNT                         8
    136 #define MAX_ITCT_ENTRIES                1
    137 
    138 // Completion header
    139 #define CMPLT_HDR_IPTT_OFF              0
    140 #define CMPLT_HDR_IPTT_MSK              (0xffff << CMPLT_HDR_IPTT_OFF)
    141 
    142 #define BIT(x)                          (1 << x)
    143 
    144 // HW dma structures
    145 // Delivery queue header
    146 // dw0
    147 #define CMD_HDR_RESP_REPORT_OFF     5
    148 #define CMD_HDR_RESP_REPORT_MSK     0x20
    149 #define CMD_HDR_TLR_CTRL_OFF        6
    150 #define CMD_HDR_TLR_CTRL_MSK        0xc0
    151 #define CMD_HDR_PORT_OFF            17
    152 #define CMD_HDR_PORT_MSK            0xe0000
    153 #define CMD_HDR_PRIORITY_OFF        27
    154 #define CMD_HDR_PRIORITY_MSK        0x8000000
    155 #define CMD_HDR_MODE_OFF            28
    156 #define CMD_HDR_MODE_MSK            0x10000000
    157 #define CMD_HDR_CMD_OFF             29
    158 #define CMD_HDR_CMD_MSK             0xe0000000
    159 // dw1
    160 #define CMD_HDR_VERIFY_DTL_OFF      10
    161 #define CMD_HDR_VERIFY_DTL_MSK      0x400
    162 #define CMD_HDR_SSP_FRAME_TYPE_OFF  13
    163 #define CMD_HDR_SSP_FRAME_TYPE_MSK  0xe000
    164 #define CMD_HDR_DEVICE_ID_OFF       16
    165 #define CMD_HDR_DEVICE_ID_MSK       0xffff0000
    166 // dw2
    167 #define CMD_HDR_CFL_OFF             0
    168 #define CMD_HDR_CFL_MSK             0x1ff
    169 #define CMD_HDR_MRFL_OFF            15
    170 #define CMD_HDR_MRFL_MSK            0xff8000
    171 #define CMD_HDR_FIRST_BURST_OFF     25
    172 #define CMD_HDR_FIRST_BURST_MSK     0x2000000
    173 // dw3
    174 #define CMD_HDR_IPTT_OFF            0
    175 #define CMD_HDR_IPTT_MSK            0xffff
    176 // dw6
    177 #define CMD_HDR_DATA_SGL_LEN_OFF    16
    178 #define CMD_HDR_DATA_SGL_LEN_MSK    0xffff0000
    179 
    180 // Completion header
    181 #define CMPLT_HDR_IPTT_OFF          0
    182 #define CMPLT_HDR_IPTT_MSK          (0xffff << CMPLT_HDR_IPTT_OFF)
    183 #define CMPLT_HDR_CMD_CMPLT_MSK     BIT17
    184 #define CMPLT_HDR_ERR_RCRD_XFRD_MSK BIT18
    185 #define CMPLT_HDR_RSPNS_XFRD_MSK    BIT19
    186 #define CMPLT_HDR_IO_CFG_ERR_MSK    BIT27
    187 
    188 #define SENSE_DATA_PRES             26
    189 
    190 #define SGE_LIMIT 0x10000
    191 #define upper_32_bits(n) ((UINT32)(((n) >> 16) >> 16))
    192 #define lower_32_bits(n) ((UINT32)(n))
    193 #define MAX_TARGET_ID 4
    194 
    195 // Generic HW DMA host memory structures
    196 struct hisi_sas_cmd_hdr {
    197     UINT32 dw0;
    198     UINT32 dw1;
    199     UINT32 dw2;
    200     UINT32 transfer_tags;
    201     UINT32 data_transfer_len;
    202     UINT32 first_burst_num;
    203     UINT32 sg_len;
    204     UINT32 dw7;
    205     UINT64 cmd_table_addr;
    206     UINT64 sts_buffer_addr;
    207     UINT64 prd_table_addr;
    208     UINT64 dif_prd_table_addr;
    209 };
    210 
    211 struct hisi_sas_complete_hdr {
    212     UINT32 data;
    213 };
    214 
    215 struct hisi_sas_iost {
    216     UINT64 qw0;
    217     UINT64 qw1;
    218     UINT64 qw2;
    219     UINT64 qw3;
    220 };
    221 
    222 struct hisi_sas_itct {
    223     UINT64 qw0;
    224     UINT64 sas_addr;
    225     UINT64 qw2;
    226     UINT64 qw3;
    227     UINT64 qw4;
    228     UINT64 qw_sata_ncq0_3;
    229     UINT64 qw_sata_ncq7_4;
    230     UINT64 qw_sata_ncq11_8;
    231     UINT64 qw_sata_ncq15_12;
    232     UINT64 qw_sata_ncq19_16;
    233     UINT64 qw_sata_ncq23_20;
    234     UINT64 qw_sata_ncq27_24;
    235     UINT64 qw_sata_ncq31_28;
    236     UINT64 qw_non_ncq_iptt;
    237     UINT64 qw_rsvd0;
    238     UINT64 qw_rsvd1;
    239 };
    240 
    241 struct hisi_sas_breakpoint {
    242     UINT8 data[128];
    243 };
    244 
    245 struct hisi_sas_sge {
    246     UINT64 addr;
    247     UINT32 page_ctrl_0;
    248     UINT32 page_ctrl_1;
    249     UINT32 data_len;
    250     UINT32 data_off;
    251 };
    252 
    253 struct hisi_sas_sge_page {
    254     struct hisi_sas_sge sg[512];
    255 };
    256 
    257 struct hisi_sas_cmd {
    258     UINT8 cmd[128];
    259 };
    260 
    261 struct hisi_sas_sts {
    262 UINT32 status[260];
    263 };
    264 
    265 struct hisi_sas_slot {
    266     BOOLEAN used;
    267 };
    268 
    269 struct hisi_hba {
    270     struct hisi_sas_cmd_hdr      *cmd_hdr[QUEUE_CNT];
    271     struct hisi_sas_complete_hdr *complete_hdr[QUEUE_CNT];
    272     struct hisi_sas_sge_page     *sge[QUEUE_CNT];
    273     struct hisi_sas_sts          *status_buf[QUEUE_CNT];
    274     struct hisi_sas_cmd          *command_table[QUEUE_CNT];
    275     struct hisi_sas_iost         *iost;
    276     struct hisi_sas_itct         *itct;
    277     struct hisi_sas_breakpoint   *breakpoint;
    278     struct hisi_sas_slot         *slots;
    279     UINT32 base;
    280     int queue;
    281     int port_id;
    282     UINT32 LatestTargetId;
    283     UINT64 LatestLun;
    284 };
    285 
    286 #pragma pack (1)
    287 typedef struct {
    288   VENDOR_DEVICE_PATH                  Vendor;
    289   UINT64                              PhysBase;
    290   EFI_DEVICE_PATH_PROTOCOL            End;
    291 } SAS_V1_TRANSPORT_DEVICE_PATH;
    292 #pragma pack ()
    293 
    294 typedef struct {
    295     UINT32 Signature;
    296     EFI_EXT_SCSI_PASS_THRU_MODE     ExtScsiPassThruMode;
    297     EFI_EXT_SCSI_PASS_THRU_PROTOCOL ExtScsiPassThru;
    298     SAS_V1_TRANSPORT_DEVICE_PATH    *DevicePath;
    299     struct hisi_hba *hba;
    300     EFI_EVENT TimerEvent;
    301 } SAS_V1_INFO;
    302 
    303 #define SAS_DEVICE_SIGNATURE SIGNATURE_32 ('S','A','S','0')
    304 #define SAS_FROM_PASS_THRU(a) CR (a, SAS_V1_INFO, ExtScsiPassThru, SAS_DEVICE_SIGNATURE)
    305 
    306 STATIC EFI_STATUS prepare_cmd (
    307   struct hisi_hba *hba,
    308   EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET    *Packet
    309   )
    310 {
    311   struct hisi_sas_slot *slot;
    312   struct hisi_sas_cmd_hdr *hdr;
    313   struct hisi_sas_sge_page *sge;
    314   struct hisi_sas_sts *sts;
    315   struct hisi_sas_cmd *cmd;
    316   EFI_SCSI_SENSE_DATA *SensePtr = Packet->SenseData;
    317   VOID   *Buffer = NULL;
    318   UINTN BufferSize = 0;
    319   int queue = hba->queue;
    320   UINT32 r, w = 0, slot_idx = 0;
    321   UINT32 base = hba->base;
    322   UINT8 *p;
    323   EFI_PHYSICAL_ADDRESS  BufferAddress;
    324   EFI_STATUS            Status = EFI_SUCCESS;
    325   VOID                  *BufferMap = NULL;
    326   DMA_MAP_OPERATION DmaOperation = MapOperationBusMasterCommonBuffer;
    327 
    328   while (1) {
    329     w = READ_REG32(base, DLVRY_Q_0_WR_PTR + (queue * 0x14));
    330     r = READ_REG32(base, DLVRY_Q_0_RD_PTR + (queue * 0x14));
    331     slot_idx = queue * QUEUE_SLOTS + w;
    332     slot = &hba->slots[slot_idx];
    333     if (slot->used || (r == (w+1) % QUEUE_SLOTS)) {
    334       queue = (queue + 1) % QUEUE_CNT;
    335       if (queue == hba->queue) {
    336         DEBUG ((EFI_D_ERROR, "could not find free slot\n"));
    337         return EFI_NOT_READY;
    338       }
    339       continue;
    340     }
    341     break;
    342   }
    343 
    344   hdr = &hba->cmd_hdr[queue][w];
    345   cmd = &hba->command_table[queue][w];
    346   sts = &hba->status_buf[queue][w];
    347   sge = &hba->sge[queue][w];
    348 
    349   ZeroMem (cmd, sizeof (struct hisi_sas_cmd));
    350   ZeroMem (sts, sizeof (struct hisi_sas_sts));
    351   if (SensePtr)
    352     ZeroMem (SensePtr, sizeof (EFI_SCSI_SENSE_DATA));
    353 
    354   slot->used = TRUE;
    355   hba->queue = (queue + 1) % QUEUE_CNT;
    356 
    357   // Only consider ssp
    358   hdr->dw0 = (1 << CMD_HDR_RESP_REPORT_OFF) |
    359        (0x2 << CMD_HDR_TLR_CTRL_OFF) |
    360        (hba->port_id << CMD_HDR_PORT_OFF) |
    361        (1 << CMD_HDR_MODE_OFF) |
    362        (1 << CMD_HDR_CMD_OFF);
    363   hdr->dw1 = 1 << CMD_HDR_VERIFY_DTL_OFF;
    364   hdr->dw1 |= 0 << CMD_HDR_DEVICE_ID_OFF;
    365   hdr->dw2 = 0x83000d;
    366   hdr->transfer_tags = slot_idx << CMD_HDR_IPTT_OFF;
    367 
    368   if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
    369     Buffer = Packet->InDataBuffer;
    370     BufferSize = Packet->InTransferLength;
    371     if (Buffer) {
    372       hdr->dw1 |= 1 << CMD_HDR_SSP_FRAME_TYPE_OFF;
    373       DmaOperation = MapOperationBusMasterWrite;
    374     }
    375   } else if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_WRITE) {
    376     Buffer = Packet->OutDataBuffer;
    377     BufferSize = Packet->OutTransferLength;
    378     if (Buffer) {
    379       DmaOperation = MapOperationBusMasterRead;
    380       hdr->dw1 |= 2 << CMD_HDR_SSP_FRAME_TYPE_OFF;
    381     }
    382   } else {
    383     hdr->dw1 |= 0 << CMD_HDR_SSP_FRAME_TYPE_OFF;
    384   }
    385 
    386   hdr->data_transfer_len = BufferSize;
    387   hdr->cmd_table_addr = (UINT64)cmd;
    388   hdr->sts_buffer_addr = (UINT64)sts;
    389 
    390   CopyMem (&cmd->cmd[36], Packet->Cdb, Packet->CdbLength);
    391 
    392   if (Buffer != NULL) {
    393     struct hisi_sas_sge *sg;
    394     UINT32 remain, len, pos = 0, i = 0;
    395 
    396     Status = DmaMap (DmaOperation, Buffer, &BufferSize, &BufferAddress, &BufferMap);
    397     if (EFI_ERROR (Status)) {
    398       return Status;
    399     }
    400     remain = len = BufferSize;
    401 
    402     while (remain) {
    403       if (len > SGE_LIMIT)
    404         len = SGE_LIMIT;
    405       sg = &sge->sg[i];
    406       sg->addr = (UINT64)(BufferAddress + pos);
    407       sg->page_ctrl_0 = sg->page_ctrl_1 = 0;
    408       sg->data_len = len;
    409       sg->data_off = 0;
    410       remain -= len;
    411       pos += len;
    412       len = remain;
    413       i++;
    414     }
    415 
    416     hdr->prd_table_addr = (UINT64)sge;
    417     hdr->sg_len = i << CMD_HDR_DATA_SGL_LEN_OFF;
    418   }
    419 
    420   // Ensure descriptor effective before start dma
    421   MemoryFence();
    422 
    423   // Start dma
    424   WRITE_REG32(base, DLVRY_Q_0_WR_PTR + queue * 0x14, ++w % QUEUE_SLOTS);
    425 
    426   // Wait for dma complete
    427   while (slot->used) {
    428     if (READ_REG32(base, OQ_INT_SRC) & BIT(queue)) {
    429       struct hisi_sas_complete_hdr *complete_hdr;
    430       UINT32 data, rd;
    431       rd = READ_REG32(base, COMPL_Q_0_RD_PTR + (0x14 * queue));
    432 
    433       complete_hdr = &hba->complete_hdr[queue][rd];
    434       data = complete_hdr->data;
    435 
    436       // Check whether dma transfer error
    437       if ((data & CMPLT_HDR_ERR_RCRD_XFRD_MSK) &&
    438         !(data & CMPLT_HDR_RSPNS_XFRD_MSK)) {
    439         DEBUG ((EFI_D_VERBOSE, "sas retry data=0x%x\n", data));
    440         DEBUG ((EFI_D_VERBOSE, "sts[0]=0x%x\n", sts->status[0]));
    441         DEBUG ((EFI_D_VERBOSE, "sts[1]=0x%x\n", sts->status[1]));
    442         DEBUG ((EFI_D_VERBOSE, "sts[2]=0x%x\n", sts->status[2]));
    443         Status = EFI_NOT_READY;
    444         // wait 1 second and retry, some disk need long time to be ready
    445         // and ScsiDisk treat retry over 3 times as error
    446         MicroSecondDelay(1000000);
    447       }
    448        // Update read point
    449        WRITE_REG32(base, COMPL_Q_0_RD_PTR + (0x14 * queue), w);
    450        // Clear int
    451        WRITE_REG32(base, OQ_INT_SRC, BIT(queue));
    452        slot->used = FALSE;
    453        break;
    454     }
    455     // Wait for status change in polling
    456     NanoSecondDelay (100);
    457   }
    458 
    459   if (BufferMap)
    460        DmaUnmap (BufferMap);
    461 
    462   p = (UINT8 *)&sts->status[0];
    463   if (p[SENSE_DATA_PRES]) {
    464     // Disk not ready normal return for ScsiDiskTestUnitReady do next try
    465     SensePtr->Sense_Key = EFI_SCSI_SK_NOT_READY;
    466     SensePtr->Addnl_Sense_Code = EFI_SCSI_ASC_NOT_READY;
    467     SensePtr->Addnl_Sense_Code_Qualifier = EFI_SCSI_ASCQ_IN_PROGRESS;
    468     // wait 1 second for disk spin up, refer drivers/scsi/sd.c
    469     MicroSecondDelay(1000000);
    470   }
    471   return Status;
    472 }
    473 
    474 STATIC VOID hisi_sas_v1_init(struct hisi_hba *hba, PLATFORM_SAS_PROTOCOL *plat)
    475 {
    476   int i, j;
    477   UINT32 val, base = hba->base;
    478 
    479   // Reset
    480   for (i = 0; i < PHY_CNT; i++) {
    481     UINT32 phy_ctrl = PHY_READ_REG32(base, PHY_CTRL, i);
    482 
    483     phy_ctrl |= PHY_CTRL_RESET;
    484     PHY_WRITE_REG32(base, PHY_CTRL, i, phy_ctrl);
    485   }
    486   // spec says safe to wait 50us after reset
    487   MicroSecondDelay(50);
    488 
    489   // Ensure DMA tx & rx idle
    490   for (i = 0; i < PHY_CNT; i++) {
    491     UINT32 dma_tx_status, dma_rx_status;
    492 
    493     for (j = 0; j < 100; j++) {
    494       dma_tx_status = PHY_READ_REG32(base, DMA_TX_STATUS, i);
    495       dma_rx_status = PHY_READ_REG32(base, DMA_RX_STATUS, i);
    496 
    497       if (!(dma_tx_status & DMA_TX_STATUS_BUSY) &&
    498         !(dma_rx_status & DMA_RX_STATUS_BUSY))
    499         break;
    500 
    501         // Wait for status change in polling
    502         NanoSecondDelay (100);
    503     }
    504   }
    505 
    506   // Ensure axi bus idle
    507   for (j = 0; j < 100; j++) {
    508     UINT32 axi_status = READ_REG32(base, AXI_CFG);
    509     if (axi_status == 0)
    510       break;
    511 
    512     // Wait for status change in polling
    513     NanoSecondDelay (100);
    514   }
    515 
    516   plat->Init(plat);
    517 
    518   WRITE_REG32(base, DLVRY_QUEUE_ENABLE, 0xffffffff);
    519   WRITE_REG32(base, HGC_TRANS_TASK_CNT_LIMIT, 0x11);
    520   WRITE_REG32(base, DEVICE_MSG_WORK_MODE, 0x1);
    521   WRITE_REG32(base, HGC_SAS_TXFAIL_RETRY_CTRL, 0x1ff);
    522   WRITE_REG32(base, HGC_ERR_STAT_EN, 0x401);
    523   WRITE_REG32(base, CFG_1US_TIMER_TRSH, 0x64);
    524   WRITE_REG32(base, HGC_GET_ITV_TIME, 0x1);
    525   WRITE_REG32(base, I_T_NEXUS_LOSS_TIME, 0x64);
    526   WRITE_REG32(base, BUS_INACTIVE_LIMIT_TIME, 0x2710);
    527   WRITE_REG32(base, REJECT_TO_OPEN_LIMIT_TIME, 0x1);
    528   WRITE_REG32(base, CFG_AGING_TIME, 0x7a12);
    529   WRITE_REG32(base, HGC_DFX_CFG2, 0x9c40);
    530   WRITE_REG32(base, FIS_LIST_BADDR_L, 0x2);
    531   WRITE_REG32(base, INT_COAL_EN, 0xc);
    532   WRITE_REG32(base, OQ_INT_COAL_TIME, 0x186a0);
    533   WRITE_REG32(base, OQ_INT_COAL_CNT, 1);
    534   WRITE_REG32(base, ENT_INT_COAL_TIME, 0x1);
    535   WRITE_REG32(base, ENT_INT_COAL_CNT, 0x1);
    536   WRITE_REG32(base, OQ_INT_SRC, 0xffffffff);
    537   WRITE_REG32(base, ENT_INT_SRC1, 0xffffffff);
    538   WRITE_REG32(base, ENT_INT_SRC_MSK1, 0);
    539   WRITE_REG32(base, ENT_INT_SRC2, 0xffffffff);
    540   WRITE_REG32(base, ENT_INT_SRC_MSK2, 0);
    541   WRITE_REG32(base, SAS_ECC_INTR_MSK, 0);
    542   WRITE_REG32(base, AXI_AHB_CLK_CFG, 0x2);
    543   WRITE_REG32(base, CFG_SAS_CONFIG, 0x22000000);
    544 
    545   for (i = 0; i < PHY_CNT; i++) {
    546     PHY_WRITE_REG32(base, PROG_PHY_LINK_RATE, i, 0x88a);
    547     PHY_WRITE_REG32(base, PHY_CONFIG2, i, 0x7c080);
    548     PHY_WRITE_REG32(base, PHY_RATE_NEGO, i, 0x415ee00);
    549     PHY_WRITE_REG32(base, PHY_PCN, i, 0x80a80000);
    550     PHY_WRITE_REG32(base, SL_TOUT_CFG, i, 0x7d7d7d7d);
    551     PHY_WRITE_REG32(base, DONE_RECEIVED_TIME, i, 0x0);
    552     PHY_WRITE_REG32(base, RXOP_CHECK_CFG_H, i, 0x1000);
    553     PHY_WRITE_REG32(base, DONE_RECEIVED_TIME, i, 0);
    554     PHY_WRITE_REG32(base, CON_CFG_DRIVER, i, 0x13f0a);
    555     PHY_WRITE_REG32(base, CHL_INT_COAL_EN, i, 3);
    556     PHY_WRITE_REG32(base, DONE_RECEIVED_TIME, i, 8);
    557   }
    558 
    559   for (i = 0; i < QUEUE_CNT; i++) {
    560     WRITE_REG32(base, DLVRY_Q_0_BASE_ADDR_HI + (i * 0x14), upper_32_bits((UINT64)(hba->cmd_hdr[i])));
    561     WRITE_REG32(base, DLVRY_Q_0_BASE_ADDR_LO + (i * 0x14), lower_32_bits((UINT64)(hba->cmd_hdr[i])));
    562     WRITE_REG32(base, DLVRY_Q_0_DEPTH + (i * 0x14), QUEUE_SLOTS);
    563 
    564     WRITE_REG32(base, COMPL_Q_0_BASE_ADDR_HI + (i * 0x14), upper_32_bits((UINT64)(hba->complete_hdr[i])));
    565     WRITE_REG32(base, COMPL_Q_0_BASE_ADDR_LO + (i * 0x14), lower_32_bits((UINT64)(hba->complete_hdr[i])));
    566     WRITE_REG32(base, COMPL_Q_0_DEPTH + (i * 0x14), QUEUE_SLOTS);
    567   }
    568 
    569   WRITE_REG32(base, ITCT_BASE_ADDR_LO, lower_32_bits((UINT64)(hba->itct)));
    570   WRITE_REG32(base, ITCT_BASE_ADDR_HI, upper_32_bits((UINT64)(hba->itct)));
    571 
    572   WRITE_REG32(base, IOST_BASE_ADDR_LO, lower_32_bits((UINT64)(hba->iost)));
    573   WRITE_REG32(base, IOST_BASE_ADDR_HI, upper_32_bits((UINT64)(hba->iost)));
    574 
    575   WRITE_REG32(base, BROKEN_MSG_ADDR_LO, lower_32_bits((UINT64)(hba->breakpoint)));
    576   WRITE_REG32(base, BROKEN_MSG_ADDR_HI, upper_32_bits((UINT64)(hba->breakpoint)));
    577 
    578   for (i = 0; i < PHY_CNT; i++) {
    579     // Clear interrupt status
    580     val = PHY_READ_REG32(base, CHL_INT0, i);
    581     PHY_WRITE_REG32(base, CHL_INT0, i, val);
    582     val = PHY_READ_REG32(base, CHL_INT1, i);
    583     PHY_WRITE_REG32(base, CHL_INT1, i, val);
    584     val = PHY_READ_REG32(base, CHL_INT2, i);
    585     PHY_WRITE_REG32(base, CHL_INT2, i, val);
    586 
    587     // Bypass chip bug mask abnormal intr
    588     PHY_WRITE_REG32(base, CHL_INT0_MSK, i, 0x3fffff & ~CHL_INT0_MSK_PHYCTRL_NOTRDY);
    589   }
    590 
    591   // Init phy
    592   for (i = 0; i < PHY_CNT; i++) {
    593     PHY_WRITE_REG32(base, TX_ID_DWORD0, i, 0x10010e00);
    594     PHY_WRITE_REG32(base, TX_ID_DWORD1, i, 0x16);
    595     PHY_WRITE_REG32(base, TX_ID_DWORD2, i, 0x20880150);
    596     PHY_WRITE_REG32(base, TX_ID_DWORD3, i, 0x16);
    597     PHY_WRITE_REG32(base, TX_ID_DWORD4, i, 0x20880150);
    598     PHY_WRITE_REG32(base, TX_ID_DWORD5, i, 0x0);
    599 
    600     val = PHY_READ_REG32(base, PHY_CFG, i);
    601     val &= ~PHY_CFG_DC_OPT_MSK;
    602     val |= 1 << PHY_CFG_DC_OPT_OFF;
    603     PHY_WRITE_REG32(base, PHY_CFG, i, val);
    604 
    605     val = PHY_READ_REG32(base, PHY_CONFIG2, i);
    606     val &= ~PHY_CONFIG2_FORCE_TXDEEMPH_MSK;
    607     PHY_WRITE_REG32(base, PHY_CONFIG2, i, val);
    608 
    609     val = PHY_READ_REG32(base, PHY_CFG, i);
    610     val |= PHY_CFG_ENA_MSK;
    611     PHY_WRITE_REG32(base, PHY_CFG, i, val);
    612   }
    613 }
    614 
    615 STATIC VOID sas_init(SAS_V1_INFO *SasV1Info, PLATFORM_SAS_PROTOCOL *plat)
    616 {
    617   struct hisi_hba *hba = SasV1Info->hba;
    618   int i, s;
    619 
    620   for (i = 0; i < QUEUE_CNT; i++) {
    621     s = sizeof(struct hisi_sas_cmd_hdr) * QUEUE_SLOTS;
    622     DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES (s), (VOID *)&hba->cmd_hdr[i]);
    623     ASSERT (hba->cmd_hdr[i] != NULL);
    624     ZeroMem (hba->cmd_hdr[i], s);
    625 
    626     s = sizeof(struct hisi_sas_complete_hdr) * QUEUE_SLOTS;
    627     DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES (s), (VOID *)&hba->complete_hdr[i]);
    628     ASSERT (hba->complete_hdr[i] != NULL);
    629     ZeroMem (hba->complete_hdr[i], s);
    630 
    631     s = sizeof(struct hisi_sas_sts) * QUEUE_SLOTS;
    632     DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES (s), (VOID *)&hba->status_buf[i]);
    633     ASSERT (hba->status_buf[i] != NULL);
    634     ZeroMem (hba->status_buf[i], s);
    635 
    636     s = sizeof(struct hisi_sas_cmd) * QUEUE_SLOTS;
    637     DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES (s), (VOID *)&hba->command_table[i]);
    638     ASSERT (hba->command_table[i] != NULL);
    639     ZeroMem (hba->command_table[i], s);
    640 
    641     s = sizeof(struct hisi_sas_sge_page) * QUEUE_SLOTS;
    642     DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES (s), (VOID *)&hba->sge[i]);
    643     ASSERT (hba->sge[i] != NULL);
    644     ZeroMem (hba->sge[i], s);
    645   }
    646 
    647   s = SLOT_ENTRIES * sizeof(struct hisi_sas_iost);
    648   DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES (s), (VOID *)&hba->iost);
    649   ASSERT (hba->iost != NULL);
    650   ZeroMem (hba->iost, s);
    651 
    652   s = SLOT_ENTRIES * sizeof(struct hisi_sas_breakpoint);
    653   DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES (s), (VOID *)&hba->breakpoint);
    654   ASSERT (hba->breakpoint != NULL);
    655   ZeroMem (hba->breakpoint, s);
    656 
    657   s = MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct);
    658   DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES (s), (VOID *)&hba->itct);
    659   ASSERT (hba->itct != NULL);
    660   ZeroMem (hba->itct, s);
    661 
    662   hba->slots = AllocateZeroPool (SLOT_ENTRIES * sizeof(struct hisi_sas_slot));
    663   ASSERT (hba->slots != NULL);
    664 
    665   hisi_sas_v1_init(hba, plat);
    666 }
    667 
    668 STATIC
    669 EFI_STATUS
    670 EFIAPI
    671 SasV1ExtScsiPassThruFunction (
    672   IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL                    *This,
    673   IN UINT8                                              *Target,
    674   IN UINT64                                             Lun,
    675   IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET     *Packet,
    676   IN EFI_EVENT                                          Event OPTIONAL
    677   )
    678 {
    679   SAS_V1_INFO *SasV1Info = SAS_FROM_PASS_THRU(This);
    680   struct hisi_hba *hba = SasV1Info->hba;
    681 
    682   return prepare_cmd(hba, Packet);
    683 }
    684 
    685 STATIC
    686 EFI_STATUS
    687 EFIAPI
    688 SasV1ExtScsiPassThruGetNextTargetLun (
    689   IN  EFI_EXT_SCSI_PASS_THRU_PROTOCOL    *This,
    690   IN OUT UINT8                           **Target,
    691   IN OUT UINT64                          *Lun
    692   )
    693 {
    694   SAS_V1_INFO *SasV1Info = SAS_FROM_PASS_THRU(This);
    695   struct hisi_hba *hba = SasV1Info->hba;
    696   UINT8 ScsiId[TARGET_MAX_BYTES];
    697   UINT8 TargetId;
    698 
    699   if (*Target == NULL || Lun == NULL) {
    700     return EFI_INVALID_PARAMETER;
    701   }
    702 
    703   SetMem (ScsiId, TARGET_MAX_BYTES, 0xFF);
    704 
    705   TargetId = (*Target)[0];
    706 
    707   if (TargetId == MAX_TARGET_ID) {
    708     return EFI_NOT_FOUND;
    709   }
    710 
    711   if (CompareMem(*Target, ScsiId, TARGET_MAX_BYTES) == 0) {
    712     SetMem (*Target, TARGET_MAX_BYTES,0);
    713   } else {
    714     (*Target)[0] = (UINT8) (hba->LatestTargetId + 1);
    715   }
    716 
    717   *Lun = 0;
    718 
    719   //
    720   // Update the LatestTargetId.
    721   //
    722   hba->LatestTargetId  = (*Target)[0];
    723   hba->LatestLun       = *Lun;
    724 
    725   return EFI_SUCCESS;
    726 }
    727 
    728 STATIC
    729 EFI_STATUS
    730 EFIAPI
    731 SasV1ExtScsiPassThruBuildDevicePath (
    732   IN     EFI_EXT_SCSI_PASS_THRU_PROTOCOL    *This,
    733   IN     UINT8                              *Target,
    734   IN     UINT64                             Lun,
    735   IN OUT EFI_DEVICE_PATH_PROTOCOL           **DevicePath
    736   )
    737 {
    738   SAS_V1_INFO *SasV1Info = SAS_FROM_PASS_THRU(This);
    739 
    740   *DevicePath  = DuplicateDevicePath ((EFI_DEVICE_PATH_PROTOCOL *)(SasV1Info->DevicePath));
    741   return EFI_SUCCESS;
    742 }
    743 
    744 STATIC
    745 EFI_STATUS
    746 EFIAPI
    747 SasV1ExtScsiPassThruGetTargetLun (
    748   IN  EFI_EXT_SCSI_PASS_THRU_PROTOCOL    *This,
    749   IN  EFI_DEVICE_PATH_PROTOCOL           *DevicePath,
    750   OUT UINT8                              **Target,
    751   OUT UINT64                             *Lun
    752   )
    753 {
    754   return EFI_UNSUPPORTED;
    755 }
    756 
    757 STATIC
    758 EFI_STATUS
    759 EFIAPI
    760 SasV1ExtScsiPassThruResetChannel (
    761   IN  EFI_EXT_SCSI_PASS_THRU_PROTOCOL   *This
    762   )
    763 {
    764 
    765   return EFI_UNSUPPORTED;
    766 }
    767 
    768 STATIC
    769 EFI_STATUS
    770 EFIAPI
    771 SasV1ExtScsiPassThruResetTarget (
    772   IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL    *This,
    773   IN UINT8                              *Target,
    774   IN UINT64                             Lun
    775   )
    776 {
    777 
    778   return EFI_UNSUPPORTED;
    779 }
    780 
    781 STATIC
    782 EFI_STATUS
    783 EFIAPI
    784 SasV1ExtScsiPassThruGetNextTarget (
    785   IN  EFI_EXT_SCSI_PASS_THRU_PROTOCOL    *This,
    786   IN OUT UINT8                           **Target
    787   )
    788 {
    789 
    790   return EFI_UNSUPPORTED;
    791 }
    792 
    793 STATIC EFI_EXT_SCSI_PASS_THRU_PROTOCOL SasV1ExtScsiPassThruProtocolTemplate = {
    794   NULL,
    795   SasV1ExtScsiPassThruFunction,
    796   SasV1ExtScsiPassThruGetNextTargetLun,
    797   SasV1ExtScsiPassThruBuildDevicePath,
    798   SasV1ExtScsiPassThruGetTargetLun,
    799   SasV1ExtScsiPassThruResetChannel,
    800   SasV1ExtScsiPassThruResetTarget,
    801   SasV1ExtScsiPassThruGetNextTarget
    802 };
    803 
    804 EFI_STATUS
    805 EFIAPI
    806 SasDriverBindingSupported (
    807   IN EFI_DRIVER_BINDING_PROTOCOL    *This,
    808   IN EFI_HANDLE                     Controller,
    809   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
    810   )
    811 {
    812   PLATFORM_SAS_PROTOCOL *plat;
    813   EFI_STATUS Status;
    814 
    815   Status = gBS->OpenProtocol (
    816                 Controller,
    817                 &gPlatformSasProtocolGuid,
    818                 (VOID **) &plat,
    819                 This->DriverBindingHandle,
    820                 Controller,
    821                 EFI_OPEN_PROTOCOL_BY_DRIVER
    822                 );
    823   if (Status == EFI_ALREADY_STARTED) {
    824     return EFI_SUCCESS;
    825   }
    826   if (EFI_ERROR (Status)) {
    827     return Status;
    828   }
    829 
    830   //
    831   // Close the Sas Host used to perform the supported test
    832   //
    833   gBS->CloseProtocol (
    834       Controller,
    835       &gPlatformSasProtocolGuid,
    836       This->DriverBindingHandle,
    837       Controller
    838       );
    839 
    840   return EFI_SUCCESS;
    841 }
    842 
    843 EFI_STATUS
    844 EFIAPI
    845 SasDriverBindingStart (
    846   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    847   IN EFI_HANDLE                   Controller,
    848   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
    849   )
    850 {
    851   EFI_STATUS Status;
    852   PLATFORM_SAS_PROTOCOL *plat;
    853   SAS_V1_INFO *SasV1Info = NULL;
    854   SAS_V1_TRANSPORT_DEVICE_PATH  *DevicePath;
    855   UINT32 val, base;
    856   int i, phy_id = 0;
    857   struct hisi_sas_itct *itct;
    858   struct hisi_hba *hba;
    859 
    860   Status = gBS->OpenProtocol (
    861                 Controller,
    862                 &gPlatformSasProtocolGuid,
    863                 (VOID **) &plat,
    864                 This->DriverBindingHandle,
    865                 Controller,
    866                 EFI_OPEN_PROTOCOL_BY_DRIVER
    867                 );
    868 
    869   if (EFI_ERROR (Status)) {
    870     if (Status == EFI_ALREADY_STARTED) {
    871       return EFI_SUCCESS;
    872     }
    873     return Status;
    874   }
    875 
    876   SasV1Info = AllocateZeroPool (sizeof (SAS_V1_INFO));
    877   ASSERT (SasV1Info);
    878   SasV1Info->Signature = SAS_DEVICE_SIGNATURE;
    879 
    880   SasV1Info->hba = AllocateZeroPool (sizeof(struct hisi_hba));
    881   ASSERT (SasV1Info->hba);
    882   hba = SasV1Info->hba;
    883   base = hba->base = plat->BaseAddr;
    884 
    885   sas_init(SasV1Info, plat);
    886 
    887   // Wait for sas controller phyup happen
    888   MicroSecondDelay(100000);
    889 
    890   for (i = 0; i < PHY_CNT; i++) {
    891     val = PHY_READ_REG32(base, CHL_INT2, i);
    892 
    893     if (val & CHL_INT2_SL_PHY_ENA) {
    894       phy_id = i;
    895     }
    896   }
    897 
    898   itct = &hba->itct[0]; //device_id = 0
    899 
    900   hba->port_id = (READ_REG32(base, PHY_PORT_NUM_MA) >> (4 * phy_id)) & 0xf;
    901   // Setup itct
    902   itct->qw0 = 0x355;
    903   itct->sas_addr = PHY_READ_REG32(base, RX_IDAF_DWORD3, phy_id);
    904   itct->sas_addr = itct->sas_addr << 32 | PHY_READ_REG32(base, RX_IDAF_DWORD4, phy_id);
    905   itct->qw2 = 0;
    906 
    907   // Clear phyup
    908   PHY_WRITE_REG32(base, CHL_INT2, phy_id, CHL_INT2_SL_PHY_ENA);
    909   val = PHY_READ_REG32(base, CHL_INT0, phy_id);
    910   val &= ~CHL_INT0_PHYCTRL_NOTRDY;
    911   PHY_WRITE_REG32(base, CHL_INT0, phy_id, val);
    912   PHY_WRITE_REG32(base, CHL_INT0_MSK, phy_id, 0x3ce3ee);
    913 
    914   // Need notify
    915   val = PHY_READ_REG32(base, SL_CONTROL, phy_id);
    916   val |= SL_CONTROL_NOTIFY_EN;
    917   PHY_WRITE_REG32(base, SL_CONTROL, phy_id, val);
    918   // wait 100ms required for notify takes effect, refer drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
    919   MicroSecondDelay(100000);
    920   val = PHY_READ_REG32(base, SL_CONTROL, phy_id);
    921   val &= ~SL_CONTROL_NOTIFY_EN;
    922   PHY_WRITE_REG32(base, SL_CONTROL, phy_id, val);
    923 
    924   CopyMem (&SasV1Info->ExtScsiPassThru, &SasV1ExtScsiPassThruProtocolTemplate, sizeof (EFI_EXT_SCSI_PASS_THRU_PROTOCOL));
    925   SasV1Info->ExtScsiPassThruMode.AdapterId = 2;
    926   SasV1Info->ExtScsiPassThruMode.Attributes = EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;
    927   SasV1Info->ExtScsiPassThruMode.IoAlign  = 64; //cache line align
    928   SasV1Info->ExtScsiPassThru.Mode = &SasV1Info->ExtScsiPassThruMode;
    929 
    930   DevicePath = (SAS_V1_TRANSPORT_DEVICE_PATH *)CreateDeviceNode (
    931                                                HARDWARE_DEVICE_PATH,
    932                                                HW_VENDOR_DP,
    933                                                sizeof (SAS_V1_TRANSPORT_DEVICE_PATH));
    934   ASSERT (DevicePath != NULL);
    935   SasV1Info->DevicePath = DevicePath;
    936 
    937   CopyMem (&DevicePath->Vendor.Guid, &gPlatformSasProtocolGuid, sizeof (EFI_GUID));
    938   DevicePath->PhysBase = base;
    939   SetDevicePathNodeLength (&DevicePath->Vendor,
    940                            sizeof (*DevicePath) - sizeof (DevicePath->End));
    941   SetDevicePathEndNode (&DevicePath->End);
    942 
    943   Status = gBS->InstallMultipleProtocolInterfaces (
    944                 &Controller,
    945                 &gEfiDevicePathProtocolGuid, DevicePath,
    946                 &gEfiExtScsiPassThruProtocolGuid, &SasV1Info->ExtScsiPassThru,
    947                 NULL);
    948   ASSERT_EFI_ERROR (Status);
    949 
    950   return EFI_SUCCESS;
    951 }
    952 
    953 EFI_STATUS
    954 EFIAPI
    955 SasDriverBindingStop (
    956   IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
    957   IN  EFI_HANDLE                    Controller,
    958   IN  UINTN                         NumberOfChildren,
    959   IN  EFI_HANDLE                    *ChildHandleBuffer
    960   )
    961 {
    962   SAS_V1_INFO *SasV1Info;
    963   EFI_STATUS Status;
    964   EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExtScsi;
    965   int i, s;
    966 
    967   Status = gBS->OpenProtocol (
    968                   Controller,
    969                   &gEfiExtScsiPassThruProtocolGuid,
    970                   (VOID **) &ExtScsi,
    971                   This->DriverBindingHandle,
    972                   Controller,
    973                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    974                   );
    975   if (EFI_ERROR (Status)) {
    976     return Status;
    977   }
    978 
    979   SasV1Info = SAS_FROM_PASS_THRU(ExtScsi);
    980 
    981   Status = gBS->UninstallMultipleProtocolInterfaces (
    982                 Controller,
    983                 &gEfiDevicePathProtocolGuid,
    984                 SasV1Info->DevicePath,
    985                 &gEfiExtScsiPassThruProtocolGuid,
    986                 &SasV1Info->ExtScsiPassThru,
    987                 NULL);
    988   if (!EFI_ERROR (Status)) {
    989     gBS->CloseProtocol (
    990            Controller,
    991            &gPlatformSasProtocolGuid,
    992            This->DriverBindingHandle,
    993            Controller
    994            );
    995 
    996     gBS->CloseEvent (SasV1Info->TimerEvent);
    997 
    998     for (i = 0; i < QUEUE_CNT; i++) {
    999       s = sizeof(struct hisi_sas_cmd_hdr) * QUEUE_SLOTS;
   1000       DmaFreeBuffer(EFI_SIZE_TO_PAGES (s), (VOID *)SasV1Info->hba->cmd_hdr[i]);
   1001       s = sizeof(struct hisi_sas_complete_hdr) * QUEUE_SLOTS;
   1002       DmaFreeBuffer(EFI_SIZE_TO_PAGES (s), (VOID *)SasV1Info->hba->complete_hdr[i]);
   1003       s = sizeof(struct hisi_sas_sts) * QUEUE_SLOTS;
   1004       DmaFreeBuffer(EFI_SIZE_TO_PAGES (s), (VOID *)SasV1Info->hba->status_buf[i]);
   1005       s = sizeof(struct hisi_sas_cmd) * QUEUE_SLOTS;
   1006       DmaFreeBuffer(EFI_SIZE_TO_PAGES (s), (VOID *)SasV1Info->hba->command_table[i]);
   1007       s = sizeof(struct hisi_sas_sge_page) * QUEUE_SLOTS;
   1008       DmaFreeBuffer(EFI_SIZE_TO_PAGES (s), (VOID *)SasV1Info->hba->sge[i]);
   1009     }
   1010 
   1011     s = SLOT_ENTRIES * sizeof(struct hisi_sas_iost);
   1012     DmaFreeBuffer(EFI_SIZE_TO_PAGES (s), (VOID *)SasV1Info->hba->iost);
   1013     s = SLOT_ENTRIES * sizeof(struct hisi_sas_breakpoint);
   1014     DmaFreeBuffer(EFI_SIZE_TO_PAGES (s), (VOID *)SasV1Info->hba->breakpoint);
   1015     s = MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct);
   1016     DmaFreeBuffer(EFI_SIZE_TO_PAGES (s), (VOID *)SasV1Info->hba->itct);
   1017 
   1018     FreePool (SasV1Info->hba->slots);
   1019     FreePool (SasV1Info->hba);
   1020     FreePool (SasV1Info);
   1021     return EFI_SUCCESS;
   1022   }
   1023   return Status;
   1024 }
   1025 
   1026 EFI_DRIVER_BINDING_PROTOCOL gSasDriverBinding = {
   1027   SasDriverBindingSupported,
   1028   SasDriverBindingStart,
   1029   SasDriverBindingStop,
   1030   0xa,
   1031   NULL,
   1032   NULL
   1033 };
   1034 
   1035 EFI_STATUS
   1036 SasV1Initialize (
   1037   IN EFI_HANDLE         ImageHandle,
   1038   IN EFI_SYSTEM_TABLE   *SystemTable
   1039   )
   1040 {
   1041   return EfiLibInstallDriverBindingComponentName2 (
   1042            ImageHandle,
   1043            SystemTable,
   1044            &gSasDriverBinding,
   1045            ImageHandle,
   1046            NULL,
   1047            NULL
   1048            );
   1049 }
   1050