SES Page读写调用流程

SES Page读写调用流程

1. SES Page概述

SES (SCSI Enclosure Services) Page是SAS Expander固件中用于管理和监控存储设备的重要机制。SES协议定义了多种Page类型,每种Page包含特定的状态信息或控制功能。常见的Page包括:

  • Page 0x00: Supported Diagnostic Pages
  • Page 0x01: Configuration Page
  • Page 0x02: Enclosure Status/Control Page
  • Page 0x03: Help Text Page
  • Page 0x04: String In/Out Page
  • Page 0x05: Threshold In/Out Page
  • Page 0x07: Element Descriptor Page
  • Page 0x0A: Device Element Page
  • Page 0x0E: Microcode Page
  • Page 0x0F: Nickname Page
  • Page 0x82: Firmware Status Page (厂商自定义)

2. SES Page读取流程

SES Page的读取是通过SCSI RECEIVE DIAGNOSTIC RESULTS命令实现的。整体流程如下:

SCSI命令 -> STE模块 -> SES模块 -> DBS数据库

2.1 详细调用流程

  1. SCSI命令接收

    • 主机发送RECEIVE DIAGNOSTIC RESULTS命令
    • 命令包含Page Code参数指定要读取的SES Page
  2. STE模块处理

    • ste_rcv_diag_results() 解析SCSI命令
    • 调用 ste_ses_rcv_diag_results() 处理SES相关命令
  3. SES模块处理

    • ses_rcv_diag_process() 根据Page Code分发到对应处理函数
    • 例如Page 0x01调用 ses_page_config_process()
  4. 数据库读取

    • ses_page_read() 从DBS数据库读取Page数据
    • 返回数据给主机

2.2 核心函数解析

PUBLIC BOOL ses_rcv_diag_process(UINT32 cmd_id,
                                 scsi_initiator_id_type initiator,
                                 UINT8 initiator_zone_tag,
                                 UINT8 page_code,
                                 UINT8 *page_ptr,
                                 UINT16 buff_size,
                                 UINT16 *page_size_ptr,
                                 ses_sense_enum *sense_ptr)
{
    /* 根据Page Code分发到不同的处理函数 */
    switch(page_code)
    {
        case SES_PAGE_CODE_SUPP_DIAG_PG:
            ses_page_supp_diag_process(page_size_ptr,
                                       page_ptr,
                                       buff_size,
                                       sense_ptr);
            break;
        
        case SES_PAGE_CODE_CONFIG_PG:
            ses_page_config_process(page_size_ptr,
                                    page_ptr,
                                    buff_size,
                                    sense_ptr);
            break;
        
        /* 其他Page Code的处理... */
    }
}
PUBLIC void ses_page_read(UINT16 dbs_page,
                          UINT16 *length_ptr,
                          UINT8 *buffer_ptr,
                          UINT16 buff_size,
                          BOOL *data_valid_ptr)
{
    /* 读取SES Page长度 */
    dbs_entry_read(dbs_page, PAGE_LENGTH_OFFSET,
                   sizeof(UINT16), temp_buffer);
    
    /* 计算总长度 (Page长度 + 头部大小) */
    *length_ptr = (UINT16)((temp_buffer[0]<<8) + (temp_buffer[1]) + 4);
    
    /* 读取SES Page数据 */
    dbs_entry_read(dbs_page, 0, *length_ptr, buffer_ptr);
    
    /* 检查数据是否有效 */
    dbs_page_data_valid_flag_check(dbs_page, data_valid_ptr);
}

3. SES Page写入流程

SES Page的写入是通过SCSI SEND DIAGNOSTIC命令实现的。整体流程如下:

SCSI命令 -> STE模块 -> SES模块 -> DBS数据库

3.1 详细调用流程

  1. SCSI命令接收

    • 主机发送SEND DIAGNOSTIC命令
    • 命令包含Page Code和要写入的数据
  2. STE模块处理

    • ste_send_diag() 解析SCSI命令
    • 调用 ste_ses_send_diag() 处理SES相关命令
  3. SES模块处理

    • ses_send_diag_process() 解析Page头部
    • 根据Page Code分发到对应处理函数
    • 例如Page 0x02调用 ses_page_encl_cntl_process()
  4. 数据库更新

    • 更新DBS数据库中的Page数据
    • 返回操作结果给主机

3.2 核心函数解析

PUBLIC BOOL ses_send_diag_process(UINT32 cmd_id,
                                  scsi_initiator_id_type initiator,
                                  UINT8 initiator_zone_tag,
                                  UINT8 *diag_page_ptr,
                                  UINT16 diag_page_len,
                                  ses_sense_enum *sense_ptr)
{
    /* 根据Page Code分发到不同的处理函数 */
    switch(diag_page_ptr[0])
    {
        case SES_PAGE_CODE_ENCL_PG:
            ses_page_encl_cntl_process(diag_page_len,
                                       diag_page_ptr,
                                       initiator,
                                       initiator_zone_tag,
                                       sense_ptr);
            break;
        
        case SES_PAGE_CODE_STR_PG:
            ses_page_str_out_process(diag_page_len, 
                                     diag_page_ptr, 
                                     sense_ptr);
            break;
        
        /* 其他Page Code的处理... */
    }
}

4. 主要SES Page处理函数

4.1 读取Page的处理函数

  • ses_page_supp_diag_process(): 处理Supported Diagnostic Pages (Page 0x00)
  • ses_page_config_process(): 处理Configuration Page (Page 0x01)
  • ses_page_encl_stat_process(): 处理Enclosure Status Page (Page 0x02)
  • ses_help_text_page_process(): 处理Help Text Page (Page 0x03)
  • ses_page_str_in_process(): 处理String In Page (Page 0x04)
  • ses_page_thr_in_process(): 处理Threshold In Page (Page 0x05)
  • ses_page_element_desc_process(): 处理Element Descriptor Page (Page 0x07)
  • ses_page_dev_element_process(): 处理Device Element Page (Page 0x0A)
  • ses_microcode_status_page_process(): 处理Microcode Status Page (Page 0x0E)
  • ses_nickname_status_page_process(): 处理Nickname Status Page (Page 0x0F)

4.2 写入Page的处理函数

  • ses_page_encl_cntl_process(): 处理Enclosure Control Page (Page 0x02)
  • ses_page_str_out_process(): 处理String Out Page (Page 0x04)
  • ses_page_thr_out_process(): 处理Threshold Out Page (Page 0x05)
  • ses_microcode_cntrl_page_process(): 处理Microcode Control Page (Page 0x0E)
  • ses_nickname_control_page_process(): 处理Nickname Control Page (Page 0x0F)

5. 典型应用场景

5.1 读取设备状态

// 读取Enclosure Status Page获取设备状态
UINT8 buffer[1024];
UINT16 page_size;
ses_sense_enum sense;
BOOL result;

result = ses_rcv_diag_process(cmd_id, 
                             initiator,
                             initiator_zone_tag,
                             SES_PAGE_CODE_ENCL_PG,
                             buffer,
                             sizeof(buffer),
                             &page_size,
                             &sense);

if (result && sense == SES_SENSE_NO_SENSE) {
    // 解析buffer中的状态信息
    ses_encl_header_struct *header = (ses_encl_header_struct *)buffer;
    // 处理状态信息...
}

5.2 控制设备LED灯

// 构造Enclosure Control Page控制LED灯
UINT8 buffer[1024];
ses_sense_enum sense;
BOOL result;

// 填充Page头部
buffer[0] = SES_PAGE_CODE_ENCL_PG;  // Page Code
buffer[1] = 0;  // 保留字节
buffer[2] = 0;  // Page Length高字节
buffer[3] = 24; // Page Length低字节

// 填充控制信息
// 例如:设置第一个磁盘槽位的LED为闪烁状态
buffer[8] = 0x80;  // Select bit
buffer[9] = 0x02;  // 闪烁状态

result = ses_send_diag_process(cmd_id,
                              initiator,
                              initiator_zone_tag,
                              buffer,
                              28,  // 头部4字节 + 数据24字节
                              &sense);

5.3 固件版本信息读取

固件状态信息可以通过Page 0x82 (Firmware Status Page)获取:

// 读取Firmware Status Page获取固件版本信息
UINT8 buffer[1024];
UINT16 page_size;
ses_sense_enum sense;
BOOL result;

result = ses_rcv_diag_process(cmd_id, 
                             initiator,
                             initiator_zone_tag,
                             SES_PAGE_CODE_FW_STAT_PG,
                             buffer,
                             sizeof(buffer),
                             &page_size,
                             &sense);

if (result && sense == SES_SENSE_NO_SENSE) {
    // 解析buffer中的固件版本信息
    ses_fw_status_page_struct *fw_status = (ses_fw_status_page_struct *)buffer;
    UINT32 active_fw_revision = fw_status->active_fw_revision;
    // 处理版本信息...
}

6. 注意事项

  1. 页面长度检查:调用ses_page_length_check()确保Page长度正确

  2. 生成码检查:调用ses_page_gen_code_check()验证生成码是否匹配

  3. 访问权限:某些Page的访问可能受到权限控制,需要验证initiator和zone_tag

  4. 数据库锁:操作DBS数据库时需要使用dbs_page_lock()dbs_page_unlock()

  5. 错误处理:通过sense_ptr返回错误码,如SES_SENSE_INVALID_FIELD_IN_PARM_LIST

  6. 自定义Page:厂商可以实现自定义Page,如Firmware Status Page (0x82)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值