Add C mock driver for RAIDGuard X GUI Server

This commit is contained in:
accusys
2026-03-29 14:46:28 +08:00
parent 27da85879f
commit c42b62b473
5 changed files with 860 additions and 0 deletions
+445
View File
@@ -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");
}