Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

698 lines
20 KiB

/*++
Module Name:
mxload.C
Abstract:
The module contains the functions that download the
firmware code to hardware.
Environment:
kernel mode only
Notes:
Revision History:
--*/
#include <ntddk.h>
#include <wdmguid.h>
#include <ntddser.h>
#include <initguid.h>
#include "mxenum.h"
#define BIOS 0
#define BOARD_FIRMWARE 1
#define MODULE_FIRMWARE 2
//
// for C218 BIOS initialization
//
#define C218_ConfBase 0x800
#define C218_status (C218_ConfBase + 0) /* BIOS running status */
#define C218_diag (C218_ConfBase + 2) /* diagnostic status */
#define C218_key (C218_ConfBase + 4) /* WORD (0x218 for C218)*/
#define C218DLoad_len (C218_ConfBase + 6) /* WORD */
#define C218check_sum (C218_ConfBase + 8) /* BYTE */
#define C218chksum_ok (C218_ConfBase + 0x0a) /* BYTE (1:ok) */
#define C218_TestRx (C218_ConfBase + 0x10) /* 8 bytes for 8 ports */
#define C218_TestTx (C218_ConfBase + 0x18) /* 8 bytes for 8 ports */
#define C218_RXerr (C218_ConfBase + 0x20) /* 8 bytes for 8 ports */
#define C218_ErrFlag (C218_ConfBase + 0x28) /* 8 bytes for 8 ports */
#define C218_TestCnt C218_ConfBase + 0x30 /* 8 words for 8 ports */
#define C218_LoadBuf 0x0f00
#define C218_KeyCode 0x218
#define CP204J_KeyCode 0x204
/*
* for C320 BIOS initialization
*/
#define C320_ConfBase 0x800
#define C320_status C320_ConfBase + 0 /* BIOS running status */
#define C320_diag C320_ConfBase + 2 /* diagnostic status */
#define C320_key C320_ConfBase + 4 /* WORD (0320H for C320)*/
#define C320DLoad_len C320_ConfBase + 6 /* WORD */
#define C320check_sum C320_ConfBase + 8 /* WORD */
#define C320chksum_ok C320_ConfBase + 0x0a /* WORD (1:ok) */
#define C320bapi_len C320_ConfBase + 0x0c /* WORD */
#define C320UART_no C320_ConfBase + 0x0e /* WORD */
#define STS_init 0x05 /* for C320_status */
#define C320_LoadBuf 0x0f00
#define C320_KeyCode 0x320
#define FixPage_addr 0x0000 /* starting addr of static page */
#define DynPage_addr 0x2000 /* starting addr of dynamic page */
#define Control_reg 0x1ff0 /* select page and reset control */
#define HW_reset 0x80
//
// Dual-Ported RAM
//
#define DRAM_global 0
#define INT_data (DRAM_global + 0)
#define Config_base (DRAM_global + 0x108)
//
#define Magic_code 0x404
#define Magic_no (Config_base + 0)
#define Card_model_no (Config_base + 2)
#define Total_ports (Config_base + 4)
#define C320B_len (Config_base + 6)
#define Module_cnt (Config_base + 8)
#define Module_no (Config_base + 10)
#define C320B_restart (Config_base + 12)
#define Card_Exist (Config_base + 14)
#define Disable_Irq (Config_base + 20)
#define TMS320Port1 (Config_base + 22)
#define TMS320Port2 (Config_base + 24)
#define TMS320Clock (Config_base + 26)
//
// DATA BUFFER in DRAM
//
#define Extern_table 0x400 /* Base address of the external table
(24 words * 64) total 3K bytes
(24 words * 128) total 6K bytes */
#define Extern_size 0x60 /* 96 bytes */
#define RXrptr 0 /* read pointer for RX buffer */
#define RXwptr 2 /* write pointer for RX buffer */
#define TXrptr 4 /* read pointer for TX buffer */
#define TXwptr 6 /* write pointer for TX buffer */
#define HostStat 8 /* IRQ flag and general flag */
#define FlagStat 10
#define Flow_control 0x0C /* B7 B6 B5 B4 B3 B2 B1 B0 */
/* x x x x | | | | */
/* | | | + CTS flow */
/* | | +--- RTS flow */
/* | +------ TX Xon/Xoff*/
/* +--------- RX Xon/Xoff*/
#define Break_cnt 0x0e /* received break count */
#define CD180TXirq 0x10 /* if non-0: enable TX irq */
#define RX_mask 0x12
#define TX_mask 0x14
#define Ofs_rxb 0x16
#define Ofs_txb 0x18
#define Page_rxb 0x1A
#define Page_txb 0x1C
#define EndPage_rxb 0x1E
#define EndPage_txb 0x20
#define C218rx_size 0x2000 /* 8K bytes */
#define C218tx_size 0x8000 /* 32K bytes */
#define C218rx_mask (C218rx_size - 1)
#define C218tx_mask (C218tx_size - 1)
#define C320p8rx_size 0x2000
#define C320p8tx_size 0x8000
#define C320p8rx_mask (C320p8rx_size - 1)
#define C320p8tx_mask (C320p8tx_size - 1)
#define C320p16rx_size 0x2000
#define C320p16tx_size 0x4000
#define C320p16rx_mask (C320p16rx_size - 1)
#define C320p16tx_mask (C320p16tx_size - 1)
#define C320p24rx_size 0x2000
#define C320p24tx_size 0x2000
#define C320p24rx_mask (C320p24rx_size - 1)
#define C320p24tx_mask (C320p24tx_size - 1)
#define C320p32rx_size 0x1000
#define C320p32tx_size 0x1000
#define C320p32rx_mask (C320p32rx_size - 1)
#define C320p32tx_mask (C320p32tx_size - 1)
#define Page_size 0x2000
#define Page_mask (Page_size - 1)
#define C218rx_spage 3
#define C218tx_spage 4
#define C218rx_pageno 1
#define C218tx_pageno 4
#define C218buf_pageno 5
#define C320p8rx_spage 3
#define C320p8tx_spage 4
#define C320p8rx_pgno 1
#define C320p8tx_pgno 4
#define C320p8buf_pgno 5
#define C320p16rx_spage 3
#define C320p16tx_spage 4
#define C320p16rx_pgno 1
#define C320p16tx_pgno 2
#define C320p16buf_pgno 3
#define C320p24rx_spage 3
#define C320p24tx_spage 4
#define C320p24rx_pgno 1
#define C320p24tx_pgno 1
#define C320p24buf_pgno 2
#define C320p32rx_spage 3
#define C320p32tx_ofs C320p32rx_size
#define C320p32tx_spage 3
#define C320p32buf_pgno 1
USHORT FirmwareBoardType[MOXA_MAX_BOARD_TYPE] = {
1, // C218Turbo
1, // C218Turbo/PCI
2, // C320Turbo
2, // C320Turbo/PCI
3 // CP-204J
};
USHORT C320rx_mask[4] = {
C320p8rx_mask,
C320p16rx_mask,
C320p24rx_mask,
C320p32rx_mask
};
USHORT C320tx_mask[4] = {
C320p8tx_mask,
C320p16tx_mask,
C320p24tx_mask,
C320p32tx_mask
};
USHORT C320tx_ofs[4] = {
0,
0,
0,
C320p32tx_ofs
};
USHORT C320rx_spage[4] = {
C320p8rx_spage,
C320p16rx_spage,
C320p24rx_spage,
C320p32rx_spage
};
USHORT C320tx_spage[4] = {
C320p8tx_spage,
C320p16tx_spage,
C320p24tx_spage,
C320p32tx_spage
};
USHORT C320buf_pgno[4] = {
C320p8buf_pgno,
C320p16buf_pgno,
C320p24buf_pgno,
C320p32buf_pgno
};
USHORT C320tx_pgno[4] = {
C320p8tx_pgno,
C320p16tx_pgno,
0,
0
};
UCHAR fileHead[32];
int
MxenumDownloadFirmware(PFDO_DEVICE_DATA DeviceData,BOOLEAN NumPortDefined)
{
HANDLE hfile;
NTSTATUS status;
PWCHAR fileName;
PUCHAR buffer;
PUCHAR ofs,base = DeviceData->BaseAddress;
ULONG size[3],len, i,j,len1,len2,numread;
USHORT retry;
PUSHORT uptr;
USHORT usum,module,keycode;
switch (DeviceData->BoardType) {
case C218ISA :
case C218PCI :
fileName = L"\\SystemRoot\\System32\\c218tnt.cod";
len = 32; // the length of firmware file head
keycode = C218_KeyCode;
break;
case CP204J :
fileName = L"\\SystemRoot\\System32\\cp204jnt.cod";
len = 32; // the length of firmware file head
keycode = CP204J_KeyCode;
break;
case C320ISA :
case C320PCI :
fileName = L"\\SystemRoot\\System32\\c320tnt.cod";
len = 32; // the length of firmware file head
keycode = C320_KeyCode;
break;
default :
return(Fail_Download);
}
if (!DeviceData->BaseAddress)
return(Fail_Download);
status = MxenumOpenFile(fileName, TRUE, &hfile);
if (!NT_SUCCESS(status)) {
MxenumKdPrint (MXENUM_DBG_TRACE,("DownloadFirmware: open fail\n"));
status = Fail_FirmwareCode;
return(status);
}
numread = 0;
status = MxenumReadFile(hfile, fileHead, len, &numread);
if (!NT_SUCCESS(status) || (numread != len)) {
MxenumKdPrint (MXENUM_DBG_TRACE,("DownloadFirmware: read file head fail\n"));
MxenumCloseFile(hfile);
status = Fail_FirmwareCode;
return(status);
}
if ((fileHead[0] != '4') || (fileHead[1] != '0') ||
(fileHead[2] != '4') || (fileHead[3] != '0') ||
(fileHead[7] != FirmwareBoardType[DeviceData->BoardType-1]) ||
(fileHead[6] != 2)) { // fileHead[6] == 2 for NT
MxenumKdPrint (MXENUM_DBG_TRACE,("DownloadFirmware: invalid file head\n"));
status = Fail_FirmwareCode;
MxenumCloseFile(hfile);
return(status);
}
switch (DeviceData->BoardType) {
case C218ISA :
case C218PCI :
case CP204J :
len = 0;
for (i = 0; i < 2; i++) {
size[i] = fileHead[17+i*2];
size[i] <<= 8;
size[i] += fileHead[16+i*2];
if (size[i] <= 0) {
MxenumKdPrint (MXENUM_DBG_TRACE,("DownloadFirmware: invalid file head\n"));
status = Fail_FirmwareCode;
MxenumCloseFile(hfile);
return(status);
}
if (size[i] > len)
len = size[i];
}
break;
default :
len = 0;
for (i = 0; i < 3; i++) {
size[i] = fileHead[17+i*2];
size[i] <<= 8;
size[i] += fileHead[16+i*2];
if (size[i] <= 0) {
MxenumKdPrint (MXENUM_DBG_TRACE,("DownloadFirmware: invalid file head\n"));
status = Fail_FirmwareCode;
MxenumCloseFile(hfile);
return(status);
}
if (size[i] > len)
len = size[i];
}
break;
}
buffer = ExAllocatePool(PagedPool, len);
if (!buffer) {
MxenumKdPrint (MXENUM_DBG_TRACE,("DownloadFirmware: unable to allocate buffer size = %d\n",len));
status = Fail_Download;
MxenumCloseFile(hfile);
return(status);
}
// ****************start to download bios
status = 0;
// the data len of bios code
len = size[BIOS];
status = MxenumReadFile(hfile, buffer, len, &numread);
if (!NT_SUCCESS(status) || (numread != len)) {
MxenumKdPrint (MXENUM_DBG_TRACE,("DownloadFirmware: read bios code fail\n"));
status = Fail_FirmwareCode;
goto DownloadFirmwareDone;
}
base[Control_reg] = HW_reset; /* reset */
MxenumDelay(5); /* delay 10ms */
for (i=0; i<4096; i++)
base[i] = 0;
for (i=0; i<len; i++)
base[i] = buffer[i]; /* download BIOS */
base[Control_reg] = 0; /* release reset */
// start to finding board
MxenumDelay(1000); /* delay 2 secs */
switch (DeviceData->BoardType) {
case C218ISA:
case C218PCI :
case CP204J:
retry = 0;
while (*(PUSHORT)(base + C218_key) != keycode) {
MxenumDelay(1);
if (retry++ > 50) /* wait for 100ms */
break;
}
if (*(PUSHORT)(base + C218_key) != keycode) {
MxenumKdPrint (MXENUM_DBG_TRACE,("DownloadFirmware: unable to find c218 board = %d\n",len));
status = Fail_FindBoard;
goto DownloadFirmwareDone;
}
break;
default:
retry = 0;
while (*(PUSHORT)(base + C320_key) != keycode) {
MxenumDelay(1);
if (retry++ > 50) /* wait for 100ms */
break;
}
if (*(PUSHORT)(base + C320_key) != keycode) {
MxenumKdPrint (MXENUM_DBG_TRACE,("DownloadFirmware: unable to find c320 board = %d\n",len));
status = Fail_FindBoard;
goto DownloadFirmwareDone;
}
retry = 0;
while (*(PUSHORT)(base + C320_status) != STS_init) {
MxenumDelay(1);
if (retry++ > 1500) /* wait for 3s */
break;
}
if (*(PUSHORT)(base + C320_status) != STS_init) {
MxenumKdPrint (MXENUM_DBG_TRACE,("DownloadFirmware: unable to find c320 board = %d\n",len));
status = Fail_FindCpumodule;
goto DownloadFirmwareDone;
}
// start to download firmware of C320 board
len = size[BOARD_FIRMWARE]; // the data len of C320 board firmware code
status = MxenumReadFile(hfile, buffer, len, &numread);
if (!NT_SUCCESS(status) || (numread != len)) {
MxenumKdPrint (MXENUM_DBG_TRACE,("DownloadFirmware: read c320 board firmware code fail\n"));
status = Fail_FirmwareCode;
goto DownloadFirmwareDone;
}
*(PUSHORT)&base[C320bapi_len] = (USHORT)(len - 7168 - 2);
base[Control_reg] = 1; /* Select Page 1 */
for (i=0; i<7168; i++)
base[DynPage_addr + i] = buffer[i];
base[Control_reg] = 2; /* Select Page 2 */
for (i=0; i<(len - 7168); i++)
base[DynPage_addr + i] = buffer[i+7168];
break;
}
// start to downloading firmware
MxenumKdPrint (MXENUM_DBG_TRACE,("DownloadFirmware: start to download firmware\n"));
// the data len of firmware code
switch (DeviceData->BoardType) {
case C218ISA:
case C218PCI :
case CP204J:
len = size[BOARD_FIRMWARE];
break;
default :
len = size[MODULE_FIRMWARE];
break;
}
status = MxenumReadFile(hfile, buffer, len, &numread);
if (!NT_SUCCESS(status) || (numread != len)) {
MxenumKdPrint (MXENUM_DBG_TRACE,("DownloadFirmware: read firmware code fail\n"));
status = Fail_FirmwareCode;
goto DownloadFirmwareDone;
}
retry = 0;
switch (DeviceData->BoardType) {
case C218ISA:
case C218PCI :
case CP204J:
do {
j = 0;
usum = 0;
len1 = len >> 1;
uptr = (PUSHORT)buffer;
for (i=0; i<len1; i++)
usum += uptr[i];
while (len1) {
if (len1 > 2048)
len2 = 2048;
else
len2 = len1;
len1 -= len2;
for (i=0; i<len2<<1; i++)
base[C218_LoadBuf+i] = buffer[j+i];
j += i;
*(PUSHORT)&(base[C218DLoad_len]) = (USHORT)len2;
*(PUSHORT)&(base[C218_key]) = 0;
for (i=0; i<100; i++) {
if (*(PUSHORT)&(base[C218_key]) == keycode)
break;
MxenumDelay(1);
}
if (*(PUSHORT)&(base[C218_key]) != keycode) {
status = Fail_Download;
goto DownloadFirmwareDone;
}
}
*(PUSHORT)&base[C218DLoad_len] = 0;
*(PUSHORT)&base[C218check_sum] = usum;
*(PUSHORT)&base[C218_key] = 0;
for (i=0; i<100; i++) {
if (*(PUSHORT)&base[C218_key] == keycode)
break;
MxenumDelay(1);
}
retry++;
} while ((base[C218chksum_ok] != 1) && (retry < 3));
if (base[C218chksum_ok] != 1) {
status = Fail_Checksum;
goto DownloadFirmwareDone;
}
*(PUSHORT)&base[C218_key] = 0;
for (i=0; i<100; i++) {
if (*(PUSHORT)&base[Magic_no] == Magic_code)
break;
MxenumDelay(1);
}
if (*(PUSHORT)&base[Magic_no] != Magic_code) {
status = Fail_Download;
goto DownloadFirmwareDone;
}
*(PUSHORT)&base[Disable_Irq] = 0;
*(PUSHORT)&base[Magic_no] = 0;
for (i=0; i<100; i++) {
if (*(PUSHORT)&base[Magic_no] == Magic_code)
break;
MxenumDelay(1);
}
if (*(PUSHORT)&base[Magic_no] != Magic_code) {
status = Fail_Download;
goto DownloadFirmwareDone;
}
for (i=0; i<DeviceData->NumPorts; i++) {
ofs = base + Extern_table + Extern_size * i;
*(PUSHORT)(ofs + RX_mask) = C218rx_mask;
*(PUSHORT)(ofs + TX_mask) = C218tx_mask;
*(PUSHORT)(ofs + Page_rxb) = (USHORT)(C218rx_spage + i * C218buf_pageno);
*(PUSHORT)(ofs + EndPage_rxb) = *(PUSHORT)(ofs + Page_rxb) + C218rx_pageno;
*(PUSHORT)(ofs + Page_txb) = (USHORT)(C218tx_spage + i * C218buf_pageno);
*(PUSHORT)(ofs + EndPage_txb) = *(PUSHORT)(ofs + Page_txb) + C218tx_pageno;
}
break;
default :
do {
j = 0;
usum = 0;
len1 = len >> 1;
uptr = (PUSHORT)buffer;
for (i=0; i<len1; i++)
usum += uptr[i];
while (len1) {
if (len1 > 2048)
len2 = 2048;
else
len2 = len1;
len1 -= len2;
for (i=0; i<len2<<1; i++)
base[C320_LoadBuf+i] = buffer[j+i];
j += i;
*(PUSHORT)&(base[C320DLoad_len]) = (USHORT)len2;
*(PUSHORT)&(base[C320_key]) = 0;
for (i=0; i<100; i++) {
if (*(PUSHORT)&(base[C320_key]) == keycode)
break;
MxenumDelay(1);
}
if (*(PUSHORT)&(base[C320_key]) != keycode) {
status = Fail_Download;
goto DownloadFirmwareDone;
}
}
*(PUSHORT)&base[C320DLoad_len] = 0;
*(PUSHORT)&base[C320check_sum] = usum;
*(PUSHORT)&(base[C320_key]) = 0;
for (i=0; i<100; i++) {
if (*(PUSHORT)&(base[C320_key]) == keycode)
break;
MxenumDelay(1);
}
retry++;
} while ((base[C320chksum_ok] != 1) && (retry < 3));
if (base[C320chksum_ok] != 1) {
status = Fail_Checksum;
goto DownloadFirmwareDone;
}
*(PUSHORT)&(base[C320_key]) = 0;
for (i=0; i<100; i++) {
if (*(PUSHORT)&base[Magic_no] == Magic_code)
break;
MxenumDelay(1); /* delay 2 ms */
}
if (*(PUSHORT)&base[Magic_no] != Magic_code) {
status = Fail_Download;
goto DownloadFirmwareDone;
}
*(PUSHORT)&base[Disable_Irq] = 0;
if (DeviceData->InterfaceType == PCIBus) {// ASIC board
*(PUSHORT)&base[TMS320Port1] = 0x3800;
*(PUSHORT)&base[TMS320Port2] = 0x3900;
*(PUSHORT)&base[TMS320Clock] = 28499; // 57 MHZ
}
else {
*(PUSHORT)&base[TMS320Port1] = 0x3200;
*(PUSHORT)&base[TMS320Port2] = 0x3400;
*(PUSHORT)&base[TMS320Clock] = 19999; // 40 MHZ
}
*(PUSHORT)&base[Magic_no] = 0;
for (i=0; i<100; i++) {
if (*(PUSHORT)&base[Magic_no] == Magic_code)
break;
MxenumDelay(1); /* delay 2 ms */
}
if (*(PUSHORT)&base[Magic_no] != Magic_code)
return(Fail_Cpumodule);
if (NumPortDefined == FALSE) {// it means the fisrt time install
DeviceData->NumPorts = 8*base[Module_cnt];
module = base[Module_cnt];
}
else {
module = (USHORT)(DeviceData->NumPorts/8);
if (base[Module_cnt] < module)
return(Fail_Uartmodule);
}
*(PUSHORT)&base[Module_no] = module;
*(PUSHORT)&base[Magic_no] = 0;
for (i=0; i<100; i++) {
if (*(PUSHORT)&base[Magic_no] == Magic_code)
break;
MxenumDelay(1); /* delay 2 ms */
}
if (*(PUSHORT)&base[Magic_no] != Magic_code) {
status = Fail_Download;
goto DownloadFirmwareDone;
}
for (i=0; i<DeviceData->NumPorts; i++) {
ofs = base + Extern_table + Extern_size * i;
*(PUSHORT)(ofs + RX_mask) = C320rx_mask[module-1];
*(PUSHORT)(ofs + TX_mask) = C320tx_mask[module-1];
*(PUSHORT)(ofs + Ofs_txb) = C320tx_ofs[module-1];
*(PUSHORT)(ofs + Page_rxb) = (USHORT)(C320rx_spage[module-1] + i * C320buf_pgno[module-1]);
*(PUSHORT)(ofs + EndPage_rxb) = *(PUSHORT)(ofs + Page_rxb);
*(PUSHORT)(ofs + Page_txb) = (USHORT)(C320tx_spage[module-1] + i * C320buf_pgno[module-1]);
*(PUSHORT)(ofs + EndPage_txb) = *(PUSHORT)(ofs + Page_txb) + C320tx_pgno[module-1];
}
break;
}
DownloadFirmwareDone :;
ExFreePool(buffer);
MxenumCloseFile(hfile);
MxenumKdPrint (MXENUM_DBG_TRACE,("DownloadFirmware: exit=%x\n",status));
return (status);
}