Add C mock driver for RAIDGuard X GUI Server
This commit is contained in:
@@ -0,0 +1,27 @@
|
|||||||
|
# Makefile for Mock Driver
|
||||||
|
|
||||||
|
CC = gcc
|
||||||
|
CFLAGS = -Wall -Wextra -g -O0
|
||||||
|
SRCS = test_mock_driver.c mock_driver.c
|
||||||
|
OBJS = $(SRCS:.c=.o)
|
||||||
|
TARGET = test_mock_driver
|
||||||
|
|
||||||
|
all: $(TARGET)
|
||||||
|
|
||||||
|
$(TARGET): $(OBJS)
|
||||||
|
$(CC) $(CFLAGS) -o $@ $(OBJS)
|
||||||
|
|
||||||
|
test_mock_driver.o: test_mock_driver.c mock_driver.h
|
||||||
|
mock_driver.o: mock_driver.c mock_driver.h
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(TARGET) $(OBJS)
|
||||||
|
|
||||||
|
run: $(TARGET)
|
||||||
|
./$(TARGET)
|
||||||
|
|
||||||
|
# Enable verbose output
|
||||||
|
debug: CFLAGS += -DVERBOSE=1
|
||||||
|
debug: $(TARGET)
|
||||||
|
|
||||||
|
.PHONY: all clean run debug
|
||||||
@@ -0,0 +1,198 @@
|
|||||||
|
# RAIDGuard X Mock Driver (C)
|
||||||
|
|
||||||
|
Mock driver for RAIDGuard X GUI Server - provides simulated RAID controller for testing without hardware.
|
||||||
|
|
||||||
|
## 目錄結構
|
||||||
|
|
||||||
|
```
|
||||||
|
raidguard_c_gui_server_mock/
|
||||||
|
├── mock_driver.h # Header file
|
||||||
|
├── mock_driver.c # Implementation
|
||||||
|
├── test_mock_driver.c # Test program
|
||||||
|
├── Makefile # Build file
|
||||||
|
└── README.md # This file
|
||||||
|
```
|
||||||
|
|
||||||
|
## 建構
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
|
## 執行測試
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./test_mock_driver
|
||||||
|
```
|
||||||
|
|
||||||
|
## 使用方式
|
||||||
|
|
||||||
|
### 1. 初始化
|
||||||
|
|
||||||
|
```c
|
||||||
|
#include "mock_driver.h"
|
||||||
|
|
||||||
|
// 初始化 Mock Driver
|
||||||
|
mock_init();
|
||||||
|
|
||||||
|
// 啟用詳細輸出
|
||||||
|
mock_set_verbose(true);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 設定控制器
|
||||||
|
|
||||||
|
```c
|
||||||
|
// 設定控制器數量 (預設 1)
|
||||||
|
mock_set_controller_count(2);
|
||||||
|
|
||||||
|
// 設定控制器序號
|
||||||
|
mock_set_controller_serial(0, "MOCK00000001");
|
||||||
|
mock_set_controller_serial(1, "MOCK00000002");
|
||||||
|
|
||||||
|
// 設定控制器型號
|
||||||
|
mock_set_controller_model(0, "Accusys GEN2");
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 查詢控制器資訊
|
||||||
|
|
||||||
|
```c
|
||||||
|
UCHAR pageBuf[1024];
|
||||||
|
UCHAR heatsink;
|
||||||
|
|
||||||
|
// 查詢控制器資訊
|
||||||
|
CHAR result = mock_QuaryDTR(0, pageBuf, &heatsink);
|
||||||
|
|
||||||
|
if (result == 1) {
|
||||||
|
// 取得序號
|
||||||
|
printf("SN: %.16s\n", pageBuf);
|
||||||
|
|
||||||
|
// 取得型號
|
||||||
|
printf("Model: %.20s\n", pageBuf + 16);
|
||||||
|
|
||||||
|
// 取得韌體版本
|
||||||
|
printf("FW: %.8s\n", pageBuf + 64);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 取得事件
|
||||||
|
|
||||||
|
```c
|
||||||
|
EVENT_INFO evt;
|
||||||
|
UCHAR result = mock_GetCtlrEvent(0, &evt);
|
||||||
|
|
||||||
|
if (result == SYSOK && evt.bStatus) {
|
||||||
|
// 處理事件
|
||||||
|
printf("Event Type: %d\n", evt.bEventBuf[0]);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. 模擬事件
|
||||||
|
|
||||||
|
```c
|
||||||
|
// 模擬磁碟上線事件
|
||||||
|
mock_generate_disk_event(5, 0x01);
|
||||||
|
|
||||||
|
// 模擬 RAID 重建事件
|
||||||
|
mock_generate_raid_event(0, 0x02);
|
||||||
|
|
||||||
|
// 自訂事件
|
||||||
|
UCHAR customEvent[] = {
|
||||||
|
0x03, 0x00, 0x00, 0x00, // Event Type
|
||||||
|
0x00, 0x00, 0x00, 0x00, // Timestamp
|
||||||
|
0x00, 0x00, 0x00, 0x00, // Data
|
||||||
|
0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
mock_push_event(customEvent, 16);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. 清理
|
||||||
|
|
||||||
|
```c
|
||||||
|
mock_cleanup();
|
||||||
|
```
|
||||||
|
|
||||||
|
## API 參考
|
||||||
|
|
||||||
|
### 初始化與清理
|
||||||
|
|
||||||
|
| 函數 | 說明 |
|
||||||
|
|------|------|
|
||||||
|
| `mock_init()` | 初始化 Mock Driver |
|
||||||
|
| `mock_cleanup()` | 清理資源 |
|
||||||
|
| `mock_set_verbose(bool)` | 設定詳細輸出 |
|
||||||
|
|
||||||
|
### 控制器設定
|
||||||
|
|
||||||
|
| 函數 | 說明 |
|
||||||
|
|------|------|
|
||||||
|
| `mock_set_controller_count(int)` | 設定控制器數量 |
|
||||||
|
| `mock_set_controller_serial(int, const char*)` | 設定控制器序號 |
|
||||||
|
| `mock_set_controller_model(int, const char*)` | 設定控制器型號 |
|
||||||
|
| `mock_set_controller_status(int, UCHAR)` | 設定控制器狀態 |
|
||||||
|
|
||||||
|
### Driver 函數
|
||||||
|
|
||||||
|
| 函數 | 說明 |
|
||||||
|
|------|------|
|
||||||
|
| `mock_QuaryDTR(UCHAR, UCHAR*, UCHAR*)` | 查詢控制器資訊 |
|
||||||
|
| `mock_DevIoControl(...)` | I/O Control (模擬) |
|
||||||
|
| `mock_GetCtlrEvent(UCHAR, EVENT_INFO*)` | 取得事件 |
|
||||||
|
|
||||||
|
### 事件模擬
|
||||||
|
|
||||||
|
| 函數 | 說明 |
|
||||||
|
|------|------|
|
||||||
|
| `mock_push_event(UCHAR*, int)` | 推入自訂事件 |
|
||||||
|
| `mock_clear_events()` | 清除所有事件 |
|
||||||
|
| `mock_generate_disk_event(int, int)` | 產生磁碟事件 |
|
||||||
|
| `mock_generate_raid_event(int, int)` | 產生 RAID 事件 |
|
||||||
|
|
||||||
|
## 模擬的 Page 資料
|
||||||
|
|
||||||
|
| Page | 大小 | 內容 |
|
||||||
|
|------|------|------|
|
||||||
|
| 0x00 | 1024 | Controller Info |
|
||||||
|
| 0x01 | 1024 | RAID Snapshot |
|
||||||
|
| 0x07 | 512 | LUN Map Table |
|
||||||
|
| 0x0A | 1024 | RAID Info |
|
||||||
|
| 0x0B | 1024 | RAID Info |
|
||||||
|
| 0x0E | 1024 | RAID Info |
|
||||||
|
| 0x1B | 512 | Disk List |
|
||||||
|
|
||||||
|
## 整合到 GS
|
||||||
|
|
||||||
|
要將 Mock Driver 整合到 GS (DtrGuiSrv),請在編譯時使用 `-DENABLE_MOCK_MODE` :
|
||||||
|
|
||||||
|
```makefile
|
||||||
|
ifdef ENABLE_MOCK_MODE
|
||||||
|
CFLAGS += -DENABLE_MOCK_MODE
|
||||||
|
SRCS += mock_driver.c
|
||||||
|
|
||||||
|
# 置換函數
|
||||||
|
CFLAGS += -DQuaryDTR=mock_QuaryDTR
|
||||||
|
CFLAGS += -DDevIoControl=mock_DevIoControl
|
||||||
|
CFLAGS += -DGetCtlrEvent=mock_GetCtlrEvent
|
||||||
|
endif
|
||||||
|
```
|
||||||
|
|
||||||
|
或使用 FFI:
|
||||||
|
|
||||||
|
```c
|
||||||
|
#ifdef ENABLE_MOCK_MODE
|
||||||
|
#include "mock_driver.h"
|
||||||
|
#define DevIoControl mock_DevIoControl
|
||||||
|
#define QuaryDTR mock_QuaryDTR
|
||||||
|
#define GetCtlrEvent mock_GetCtlrEvent
|
||||||
|
#endif
|
||||||
|
```
|
||||||
|
|
||||||
|
## 開發日誌
|
||||||
|
|
||||||
|
- 2024-03-29: 初始版本
|
||||||
|
- 基本控制器模擬
|
||||||
|
- 事件佇列
|
||||||
|
- Page 0-1, 7, 10, 27 資料
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Proprietary - Accusys Inc.
|
||||||
@@ -0,0 +1,445 @@
|
|||||||
|
/*
|
||||||
|
* mock_driver.c
|
||||||
|
*
|
||||||
|
* Mock Driver for RAIDGuard X GUI Server
|
||||||
|
* Provides simulated RAID controller for testing without hardware
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mock_driver.h"
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Global Variables
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
static MOCK_CTRL_INFO g_mockCtrl[MAX_DTR_IN_HOST];
|
||||||
|
static UCHAR g_mockEventQueue[100][MAX_EDB_SZ];
|
||||||
|
static int g_mockEventHead = 0;
|
||||||
|
static int g_mockEventTail = 0;
|
||||||
|
static int g_mockEventCount = 0;
|
||||||
|
static bool g_bInitialized = false;
|
||||||
|
|
||||||
|
// Configuration
|
||||||
|
static int g_controllerCount = 1;
|
||||||
|
static bool g_verbose = false;
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Initialization
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
void mock_set_verbose(bool verbose) {
|
||||||
|
g_verbose = verbose;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mock_is_verbose(void) {
|
||||||
|
return g_verbose;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mock_init(void) {
|
||||||
|
if (g_bInitialized) return;
|
||||||
|
|
||||||
|
memset(g_mockCtrl, 0, sizeof(g_mockCtrl));
|
||||||
|
memset(g_mockEventQueue, 0, sizeof(g_mockEventQueue));
|
||||||
|
g_mockEventHead = 0;
|
||||||
|
g_mockEventTail = 0;
|
||||||
|
g_mockEventCount = 0;
|
||||||
|
|
||||||
|
// Initialize default controller
|
||||||
|
g_controllerCount = 1;
|
||||||
|
g_mockCtrl[0].bStatus = CTLR_STATUS_ALIVE;
|
||||||
|
memcpy(g_mockCtrl[0].bCtlrSN, "MOCK00000001\0", 16);
|
||||||
|
memcpy(g_mockCtrl[0].bModelName, "Accusys GEN2\0", 20);
|
||||||
|
|
||||||
|
// Fill mock page data
|
||||||
|
mock_fill_page0(0);
|
||||||
|
mock_fill_page1(0);
|
||||||
|
mock_fill_page7(0);
|
||||||
|
mock_fill_page10(0);
|
||||||
|
mock_fill_page11(0);
|
||||||
|
mock_fill_page14(0);
|
||||||
|
mock_fill_page27(0);
|
||||||
|
|
||||||
|
// Register default events
|
||||||
|
mock_register_default_events();
|
||||||
|
|
||||||
|
g_bInitialized = true;
|
||||||
|
|
||||||
|
if (g_verbose) {
|
||||||
|
printf("[MOCK] Driver initialized\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mock_cleanup(void) {
|
||||||
|
if (!g_bInitialized) return;
|
||||||
|
|
||||||
|
memset(g_mockCtrl, 0, sizeof(g_mockCtrl));
|
||||||
|
memset(g_mockEventQueue, 0, sizeof(g_mockEventQueue));
|
||||||
|
g_mockEventCount = 0;
|
||||||
|
g_bInitialized = false;
|
||||||
|
|
||||||
|
if (g_verbose) {
|
||||||
|
printf("[MOCK] Driver cleanup complete\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Page Data Fillers
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
void mock_fill_page0(int ctrlIndex) {
|
||||||
|
MOCK_CTRL_INFO *ctrl = &g_mockCtrl[ctrlIndex];
|
||||||
|
unsigned char *buf = ctrl->bPage0Data;
|
||||||
|
|
||||||
|
memset(buf, 0, 1024);
|
||||||
|
|
||||||
|
// Serial Number (Offset 0-15, 16 bytes)
|
||||||
|
memcpy(buf + 0, ctrl->bCtlrSN, 16);
|
||||||
|
|
||||||
|
// Model Name (Offset 16-47, 32 bytes)
|
||||||
|
memcpy(buf + 16, ctrl->bModelName, 20);
|
||||||
|
|
||||||
|
// Firmware Version (Offset 64-71, 8 bytes)
|
||||||
|
memcpy(buf + 64, "3.8.0.0\0", 8);
|
||||||
|
|
||||||
|
// BIOS Version (Offset 72-79, 8 bytes)
|
||||||
|
memcpy(buf + 72, "1.2.3.4\0", 8);
|
||||||
|
|
||||||
|
// Status (Offset 96)
|
||||||
|
buf[96] = 0x01; // Online
|
||||||
|
|
||||||
|
// Number of RAID Ports (Offset 104)
|
||||||
|
buf[104] = 4;
|
||||||
|
|
||||||
|
// Number of Disks (Offset 105)
|
||||||
|
buf[105] = 8;
|
||||||
|
|
||||||
|
// Controller Number (Offset 106)
|
||||||
|
buf[106] = ctrlIndex;
|
||||||
|
|
||||||
|
if (g_verbose) {
|
||||||
|
printf("[MOCK] Page 0 filled for controller %d\n", ctrlIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mock_fill_page1(int ctrlIndex) {
|
||||||
|
unsigned char *buf = g_mockCtrl[ctrlIndex].bPage1Data;
|
||||||
|
memset(buf, 0, 1024);
|
||||||
|
|
||||||
|
// RAID 0: Normal
|
||||||
|
buf[0] = 0x01; // Status: Normal
|
||||||
|
buf[1] = 0x05; // RAID Level: RAID 5
|
||||||
|
buf[2] = 0x04; // Disk Count
|
||||||
|
|
||||||
|
// RAID 1: Normal
|
||||||
|
buf[128] = 0x01;
|
||||||
|
buf[129] = 0x06; // RAID 6
|
||||||
|
buf[130] = 0x06; // 6 disks
|
||||||
|
|
||||||
|
if (g_verbose) {
|
||||||
|
printf("[MOCK] Page 1 filled for controller %d\n", ctrlIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mock_fill_page7(int ctrlIndex) {
|
||||||
|
unsigned char *buf = g_mockCtrl[ctrlIndex].bPage7Data;
|
||||||
|
memset(buf, 0, 512);
|
||||||
|
|
||||||
|
// LUN 0 mapping
|
||||||
|
buf[0] = 0x00; // LUN 0
|
||||||
|
buf[1] = 0x00; // RAID ID 0
|
||||||
|
buf[2] = 0x01; // Enable
|
||||||
|
|
||||||
|
if (g_verbose) {
|
||||||
|
printf("[MOCK] Page 7 filled for controller %d\n", ctrlIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mock_fill_page10(int ctrlIndex) {
|
||||||
|
unsigned char *buf = g_mockCtrl[ctrlIndex].bPage10Data;
|
||||||
|
memset(buf, 0, 1024);
|
||||||
|
|
||||||
|
// RAID Info Block 0
|
||||||
|
buf[0] = 0x01; // Status: Normal
|
||||||
|
buf[1] = 0x05; // RAID 5
|
||||||
|
buf[2] = 0x04; // 4 disks
|
||||||
|
buf[3] = 0x00; // Stripe Size
|
||||||
|
|
||||||
|
// Capacity (Offset 8-15, 8 bytes)
|
||||||
|
buf[8] = 0x00;
|
||||||
|
buf[9] = 0x00;
|
||||||
|
buf[10] = 0x00;
|
||||||
|
buf[11] = 0x10; // 1 TB
|
||||||
|
buf[12] = 0x00;
|
||||||
|
buf[13] = 0x00;
|
||||||
|
buf[14] = 0x00;
|
||||||
|
buf[15] = 0x00;
|
||||||
|
|
||||||
|
if (g_verbose) {
|
||||||
|
printf("[MOCK] Page 10 filled for controller %d\n", ctrlIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mock_fill_page11(int ctrlIndex) {
|
||||||
|
memset(g_mockCtrl[ctrlIndex].bPage11Data, 0, 1024);
|
||||||
|
g_mockCtrl[ctrlIndex].bPage11Data[0] = 0x01;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mock_fill_page14(int ctrlIndex) {
|
||||||
|
memset(g_mockCtrl[ctrlIndex].bPage14Data, 0, 1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mock_fill_page27(int ctrlIndex) {
|
||||||
|
unsigned char *buf = g_mockCtrl[ctrlIndex].bPage27Data;
|
||||||
|
memset(buf, 0, 512);
|
||||||
|
|
||||||
|
// Disk 0
|
||||||
|
buf[0] = 0x00; // Slot 0
|
||||||
|
buf[1] = 0x01; // Status: Online
|
||||||
|
buf[2] = 0x00; // Type: HDD
|
||||||
|
|
||||||
|
// Disk 1
|
||||||
|
buf[16] = 0x01; // Slot 1
|
||||||
|
buf[17] = 0x01; // Status: Online
|
||||||
|
|
||||||
|
// Disk 2
|
||||||
|
buf[32] = 0x02;
|
||||||
|
buf[33] = 0x01;
|
||||||
|
|
||||||
|
// Disk 3
|
||||||
|
buf[48] = 0x03;
|
||||||
|
buf[49] = 0x01;
|
||||||
|
|
||||||
|
// Disk 4 (Spare)
|
||||||
|
buf[64] = 0x04;
|
||||||
|
buf[65] = 0x01;
|
||||||
|
buf[66] = 0x02; // Spare
|
||||||
|
|
||||||
|
// Disk 5-7 Offline
|
||||||
|
buf[80] = 0x05;
|
||||||
|
buf[81] = 0x00; // Offline
|
||||||
|
|
||||||
|
if (g_verbose) {
|
||||||
|
printf("[MOCK] Page 27 filled for controller %d\n", ctrlIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mock_register_default_events(void) {
|
||||||
|
// Disk Online Event (Slot 2)
|
||||||
|
UCHAR diskOnline[] = {
|
||||||
|
0x01, 0x00, 0x00, 0x00, // Event Type: Disk Online
|
||||||
|
0x00, 0x00, 0x00, 0x00, // Timestamp
|
||||||
|
0x02, 0x00, 0x00, 0x00, // Slot 2
|
||||||
|
0x01, 0x00, 0x00, 0x00 // Status: OK
|
||||||
|
};
|
||||||
|
mock_push_event(diskOnline, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Driver Functions
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
UCHAR mock_DevIoControl(
|
||||||
|
UCHAR bDevNo,
|
||||||
|
ULONG lControlCode,
|
||||||
|
ULONG lInSize,
|
||||||
|
char *pInBuf,
|
||||||
|
ULONG lOutSize,
|
||||||
|
char *pOutBuf,
|
||||||
|
USHORT *pusInBandErrCode) {
|
||||||
|
|
||||||
|
if (!g_bInitialized) mock_init();
|
||||||
|
|
||||||
|
if (bDevNo >= MAX_DTR_IN_HOST) {
|
||||||
|
*pusInBandErrCode = 0xFF;
|
||||||
|
return 0x01;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle different IOCTL codes
|
||||||
|
switch (lControlCode) {
|
||||||
|
case 0x9001: // GET_CONTROLLER_INFO
|
||||||
|
if (g_verbose) {
|
||||||
|
printf("[MOCK] IOCTL: GET_CONTROLLER_INFO ctrl=%d\n", bDevNo);
|
||||||
|
}
|
||||||
|
memcpy(pOutBuf, g_mockCtrl[bDevNo].bPage0Data,
|
||||||
|
lOutSize > 1024 ? 1024 : lOutSize);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x9002: // GET_RAID_INFO
|
||||||
|
if (g_verbose) {
|
||||||
|
printf("[MOCK] IOCTL: GET_RAID_INFO ctrl=%d\n", bDevNo);
|
||||||
|
}
|
||||||
|
memcpy(pOutBuf, g_mockCtrl[bDevNo].bPage1Data,
|
||||||
|
lOutSize > 1024 ? 1024 : lOutSize);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x9020: // GET_INBAND_EVENT
|
||||||
|
if (g_verbose) {
|
||||||
|
printf("[MOCK] IOCTL: GET_INBAND_EVENT ctrl=%d\n", bDevNo);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
EVENT_INFO evt;
|
||||||
|
UCHAR result = mock_GetCtlrEvent(bDevNo, &evt);
|
||||||
|
if (result == SYSOK) {
|
||||||
|
memcpy(pOutBuf, evt.bEventBuf,
|
||||||
|
lOutSize > 512 ? 512 : lOutSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (g_verbose) {
|
||||||
|
printf("[MOCK] IOCTL: 0x%04lx (not handled, returning success)\n",
|
||||||
|
lControlCode);
|
||||||
|
}
|
||||||
|
// Return success for unknown codes
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pusInBandErrCode = 0x0000;
|
||||||
|
return SYSOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
CHAR mock_QuaryDTR(UCHAR ucCtlrIndex, UCHAR *bPageBuf, UCHAR *pbHeatsink) {
|
||||||
|
if (!g_bInitialized) mock_init();
|
||||||
|
|
||||||
|
if (ucCtlrIndex >= g_controllerCount) {
|
||||||
|
return 0; // FALSE
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return controller info
|
||||||
|
memcpy(bPageBuf, g_mockCtrl[ucCtlrIndex].bPage0Data, 1024);
|
||||||
|
*pbHeatsink = 0x00;
|
||||||
|
|
||||||
|
if (g_verbose) {
|
||||||
|
printf("[MOCK] QuaryDTR: controller %d, SN: %s\n",
|
||||||
|
ucCtlrIndex, g_mockCtrl[ucCtlrIndex].bCtlrSN);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1; // TRUE
|
||||||
|
}
|
||||||
|
|
||||||
|
UCHAR mock_GetCtlrEvent(UCHAR bCtlrNo, EVENT_INFO *pEvent_info) {
|
||||||
|
if (!g_bInitialized) mock_init();
|
||||||
|
|
||||||
|
if (g_mockEventCount <= 0) {
|
||||||
|
pEvent_info->bStatus = 0;
|
||||||
|
return 0x02; // SYSFAIL_EVENT_EMPTY
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get event from queue
|
||||||
|
memcpy(pEvent_info->bEventBuf, g_mockEventQueue[g_mockEventHead], MAX_EDB_SZ);
|
||||||
|
pEvent_info->bStatus = 1;
|
||||||
|
|
||||||
|
// Move head
|
||||||
|
g_mockEventHead = (g_mockEventHead + 1) % 100;
|
||||||
|
g_mockEventCount--;
|
||||||
|
|
||||||
|
if (g_verbose) {
|
||||||
|
printf("[MOCK] GetCtlrEvent: event retrieved, remaining: %d\n",
|
||||||
|
g_mockEventCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SYSOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Configuration Functions
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
void mock_set_controller_count(int count) {
|
||||||
|
if (count < 1) count = 1;
|
||||||
|
if (count > MAX_DTR_IN_HOST) count = MAX_DTR_IN_HOST;
|
||||||
|
g_controllerCount = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mock_set_controller_serial(int index, const char *sn) {
|
||||||
|
if (index < 0 || index >= MAX_DTR_IN_HOST) return;
|
||||||
|
memcpy(g_mockCtrl[index].bCtlrSN, sn, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mock_set_controller_model(int index, const char *model) {
|
||||||
|
if (index < 0 || index >= MAX_DTR_IN_HOST) return;
|
||||||
|
memcpy(g_mockCtrl[index].bModelName, model, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mock_set_controller_status(int index, UCHAR status) {
|
||||||
|
if (index < 0 || index >= MAX_DTR_IN_HOST) return;
|
||||||
|
g_mockCtrl[index].bStatus = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Event Simulation
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
void mock_push_event(UCHAR *eventData, int length) {
|
||||||
|
if (length > MAX_EDB_SZ) length = MAX_EDB_SZ;
|
||||||
|
if (g_mockEventCount >= 100) {
|
||||||
|
// Queue full, remove oldest
|
||||||
|
g_mockEventHead = (g_mockEventHead + 1) % 100;
|
||||||
|
g_mockEventCount--;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(g_mockEventQueue[g_mockEventTail], eventData, length);
|
||||||
|
g_mockEventTail = (g_mockEventTail + 1) % 100;
|
||||||
|
g_mockEventCount++;
|
||||||
|
|
||||||
|
if (g_verbose) {
|
||||||
|
printf("[MOCK] Event pushed, count: %d\n", g_mockEventCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mock_clear_events(void) {
|
||||||
|
g_mockEventHead = 0;
|
||||||
|
g_mockEventTail = 0;
|
||||||
|
g_mockEventCount = 0;
|
||||||
|
|
||||||
|
if (g_verbose) {
|
||||||
|
printf("[MOCK] Events cleared\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mock_generate_disk_event(int slot, int eventType) {
|
||||||
|
UCHAR event[16];
|
||||||
|
memset(event, 0, 16);
|
||||||
|
|
||||||
|
event[0] = eventType & 0xFF; // Event Type
|
||||||
|
event[3] = slot & 0xFF; // Slot Number
|
||||||
|
|
||||||
|
mock_push_event(event, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mock_generate_raid_event(int raidId, int eventType) {
|
||||||
|
UCHAR event[16];
|
||||||
|
memset(event, 0, 16);
|
||||||
|
|
||||||
|
event[0] = eventType & 0xFF; // Event Type
|
||||||
|
event[3] = raidId & 0xFF; // RAID ID
|
||||||
|
|
||||||
|
mock_push_event(event, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Configuration File (Stub)
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
int mock_load_config(const char *filename) {
|
||||||
|
// TODO: Parse JSON config file
|
||||||
|
if (g_verbose) {
|
||||||
|
printf("[MOCK] Config file loading not implemented: %s\n", filename);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mock_print_config(void) {
|
||||||
|
printf("=== Mock Configuration ===\n");
|
||||||
|
printf("Controller Count: %d\n", g_controllerCount);
|
||||||
|
for (int i = 0; i < g_controllerCount; i++) {
|
||||||
|
printf("Controller %d:\n", i);
|
||||||
|
printf(" SN: %s\n", g_mockCtrl[i].bCtlrSN);
|
||||||
|
printf(" Model: %s\n", g_mockCtrl[i].bModelName);
|
||||||
|
printf(" Status: %s\n",
|
||||||
|
g_mockCtrl[i].bStatus == CTLR_STATUS_ALIVE ? "Online" : "Offline");
|
||||||
|
}
|
||||||
|
printf("Pending Events: %d\n", g_mockEventCount);
|
||||||
|
printf("=========================\n");
|
||||||
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
#ifndef MOCK_DRIVER_H
|
||||||
|
#define MOCK_DRIVER_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
// Types
|
||||||
|
typedef uint8_t UCHAR;
|
||||||
|
typedef uint16_t USHORT;
|
||||||
|
typedef uint32_t ULONG;
|
||||||
|
typedef int8_t CHAR;
|
||||||
|
typedef int SHORT;
|
||||||
|
typedef int BOOL;
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
#define MAX_DTR_IN_HOST 4
|
||||||
|
#define MAX_EVENT_NO 512
|
||||||
|
#define MAX_EDB_SZ 512
|
||||||
|
|
||||||
|
// Status
|
||||||
|
#define CTLR_STATUS_ALIVE 0x01
|
||||||
|
#define CTLR_STATUS_DEAD 0x00
|
||||||
|
|
||||||
|
#define SYSOK 0x50
|
||||||
|
#define SYSFAIL 0x40
|
||||||
|
|
||||||
|
// Mock Controller Info Structure
|
||||||
|
typedef struct {
|
||||||
|
UCHAR bStatus;
|
||||||
|
UCHAR bCtlrSN[16];
|
||||||
|
UCHAR bModelName[32];
|
||||||
|
UCHAR bPad[16];
|
||||||
|
UCHAR bPage0Data[1024];
|
||||||
|
UCHAR bPage1Data[1024];
|
||||||
|
UCHAR bPage7Data[512];
|
||||||
|
UCHAR bPage10Data[1024];
|
||||||
|
UCHAR bPage11Data[1024];
|
||||||
|
UCHAR bPage14Data[1024];
|
||||||
|
UCHAR bPage20Data[512];
|
||||||
|
UCHAR bPage26Data[512];
|
||||||
|
UCHAR bPage27Data[512];
|
||||||
|
} MOCK_CTRL_INFO;
|
||||||
|
|
||||||
|
// Event Structure
|
||||||
|
typedef struct {
|
||||||
|
UCHAR bStatus;
|
||||||
|
UCHAR bEventBuf[MAX_EDB_SZ];
|
||||||
|
} EVENT_INFO;
|
||||||
|
|
||||||
|
// Function Declarations
|
||||||
|
|
||||||
|
// Initialization
|
||||||
|
void mock_init(void);
|
||||||
|
void mock_cleanup(void);
|
||||||
|
|
||||||
|
// Driver Functions
|
||||||
|
UCHAR mock_DevIoControl(
|
||||||
|
UCHAR bDevNo,
|
||||||
|
ULONG lControlCode,
|
||||||
|
ULONG lInSize,
|
||||||
|
char *pInBuf,
|
||||||
|
ULONG lOutSize,
|
||||||
|
char *pOutBuf,
|
||||||
|
USHORT *pusInBandErrCode);
|
||||||
|
|
||||||
|
CHAR mock_QuaryDTR(
|
||||||
|
UCHAR ucCtlrIndex,
|
||||||
|
UCHAR *bPageBuf,
|
||||||
|
UCHAR *pbHeatsink);
|
||||||
|
|
||||||
|
UCHAR mock_GetCtlrEvent(
|
||||||
|
UCHAR bCtlrNo,
|
||||||
|
EVENT_INFO *pEvent_info);
|
||||||
|
|
||||||
|
// Configuration
|
||||||
|
void mock_set_controller_count(int count);
|
||||||
|
void mock_set_controller_serial(int index, const char *sn);
|
||||||
|
void mock_set_controller_model(int index, const char *model);
|
||||||
|
void mock_set_controller_status(int index, UCHAR status);
|
||||||
|
void mock_set_verbose(bool verbose);
|
||||||
|
bool mock_is_verbose(void);
|
||||||
|
void mock_set_verbose(bool verbose);
|
||||||
|
|
||||||
|
// Event Simulation
|
||||||
|
void mock_push_event(UCHAR *eventData, int length);
|
||||||
|
void mock_clear_events(void);
|
||||||
|
void mock_generate_disk_event(int slot, int eventType);
|
||||||
|
void mock_generate_raid_event(int raidId, int eventType);
|
||||||
|
|
||||||
|
// Internal functions
|
||||||
|
void mock_fill_page0(int ctrlIndex);
|
||||||
|
void mock_fill_page1(int ctrlIndex);
|
||||||
|
void mock_fill_page7(int ctrlIndex);
|
||||||
|
void mock_fill_page10(int ctrlIndex);
|
||||||
|
void mock_fill_page11(int ctrlIndex);
|
||||||
|
void mock_fill_page14(int ctrlIndex);
|
||||||
|
void mock_fill_page27(int ctrlIndex);
|
||||||
|
void mock_register_default_events(void);
|
||||||
|
|
||||||
|
// Configuration File
|
||||||
|
int mock_load_config(const char *filename);
|
||||||
|
void mock_print_config(void);
|
||||||
|
|
||||||
|
#endif // MOCK_DRIVER_H
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* test_mock_driver.c
|
||||||
|
*
|
||||||
|
* Test program for mock driver
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "mock_driver.h"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
printf("=== Mock Driver Test ===\n\n");
|
||||||
|
|
||||||
|
// Enable verbose output
|
||||||
|
mock_set_verbose(true);
|
||||||
|
|
||||||
|
// Initialize mock driver
|
||||||
|
printf("\n--- Testing mock_init() ---\n");
|
||||||
|
mock_init();
|
||||||
|
|
||||||
|
// Print configuration
|
||||||
|
printf("\n--- Testing mock_print_config() ---\n");
|
||||||
|
mock_print_config();
|
||||||
|
|
||||||
|
// Test QuaryDTR
|
||||||
|
printf("\n--- Testing mock_QuaryDTR() ---\n");
|
||||||
|
UCHAR pageBuf[1024];
|
||||||
|
UCHAR heatsink;
|
||||||
|
CHAR result = mock_QuaryDTR(0, pageBuf, &heatsink);
|
||||||
|
printf("QuaryDTR result: %d\n", result);
|
||||||
|
printf("Serial Number: %.16s\n", pageBuf);
|
||||||
|
printf("Model Name: %.20s\n", pageBuf + 16);
|
||||||
|
printf("Firmware: %.8s\n", pageBuf + 64);
|
||||||
|
|
||||||
|
// Test GetCtlrEvent
|
||||||
|
printf("\n--- Testing mock_get_ctlr_event() ---\n");
|
||||||
|
EVENT_INFO evt;
|
||||||
|
result = mock_GetCtlrEvent(0, &evt);
|
||||||
|
printf("GetCtlrEvent result: 0x%02X\n", result);
|
||||||
|
printf("Event Status: %d\n", evt.bStatus);
|
||||||
|
if (evt.bStatus) {
|
||||||
|
printf("Event Data: ");
|
||||||
|
for (int i = 0; i < 16 && i < MAX_EDB_SZ; i++) {
|
||||||
|
printf("%02X ", evt.bEventBuf[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test pushing custom event
|
||||||
|
printf("\n--- Testing mock_push_event() ---\n");
|
||||||
|
UCHAR customEvent[] = {
|
||||||
|
0x03, 0x00, 0x00, 0x00, // Event Type: RAID Rebuild Start
|
||||||
|
0x00, 0x00, 0x00, 0x00, // Timestamp
|
||||||
|
0x00, 0x00, 0x00, 0x00, // RAID ID 0
|
||||||
|
0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
mock_push_event(customEvent, 16);
|
||||||
|
printf("Custom event pushed\n");
|
||||||
|
|
||||||
|
// Get the custom event
|
||||||
|
result = mock_GetCtlrEvent(0, &evt);
|
||||||
|
printf("GetCtlrEvent result: 0x%02X\n", result);
|
||||||
|
|
||||||
|
// Test configuration functions
|
||||||
|
printf("\n--- Testing configuration functions ---\n");
|
||||||
|
mock_set_controller_count(2);
|
||||||
|
mock_set_controller_serial(1, "MOCK00000002");
|
||||||
|
mock_set_controller_model(1, "Accusys GEN3");
|
||||||
|
mock_print_config();
|
||||||
|
|
||||||
|
// Test event generation
|
||||||
|
printf("\n--- Testing event generation ---\n");
|
||||||
|
mock_generate_disk_event(5, 0x01); // Disk 5 online
|
||||||
|
mock_generate_raid_event(0, 0x02); // RAID 0 rebuild
|
||||||
|
printf("Generated 2 events\n");
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
printf("\n--- Testing mock_cleanup() ---\n");
|
||||||
|
mock_cleanup();
|
||||||
|
|
||||||
|
printf("\n=== All Tests Completed ===\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user