📄 main.c
字号:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <mem.h>
#include <ctype.h>
#include <dos.h>
#include <conio.h>
typedef unsigned char uint8;
typedef unsigned int uint16;
typedef unsigned long uint32;
typedef char int8;
#define VENDOR_ID 0x1409
#define DEVICE_ID 0x7168
#define OSC_FREQ 14745600
#define SUCCESS 0
#define SET 0
#define PCI_OFFSET_BASE_ADDRESS 0x10
#define COM_OFFSET_LCR 0x3
#define COM_OFFSET_FCR 0x2
#define COM_OFFSET_MCR 0x4
#define COM_OFFSET_IER 0x1
#define COM_OFFSET_IIR 0x2
#define COM_OFFSET_LSR 0x5
#define COM_OFFSET_MSR 0x6
#define COM_OFFSET_RBR 0x0
#define COM_OFFSET_THR 0x0
#define COM_OFFSET_DIVISOR_LSB 0x0
#define COM_OFFSET_DIVISOR_MSB 0x1
#define REG_WR(address, data) outportb(address, data)
#define REG_RD(address) inportb(address)
#define GET_BUAD_DIVISOR(rate) (OSC_FREQ/(rate*16))
#define COM_CHK_DSR(base_address) (((REG_RD(base_address+COM_OFFSET_MSR))&0x20)==0)
#define COM_CHK_DR(base_address) (((REG_RD(base_address+COM_OFFSET_LSR))&0x01)==0)
#define COM_CHK_THRE(base_address) (((REG_RD(base_address+COM_OFFSET_LSR))&0x20)==0)
#define COM_CHK_CTS(base_address) (((REG_RD(base_address+COM_OFFSET_MSR))&0x10)==0)
#define COM_OP_ARG_FIFO 1
#define COM_OP_ARG_INTR 1
#define COM_OP_ARG_AUTOFLOW 1
typedef struct {
uint8 fifo;
uint8 intr;
uint8 autoflow;
uint8 trigger;
uint32 baudrate;
}tCOM_OP_ARG;
typedef struct {
uint8 *pdata;
uint8 offset;
uint8 num_data;
uint8 num_tx_1cycle;
}tDATA_TX_CTRL;
typedef struct {
uint8 *pdata;
uint8 offset;
uint8 num_data;
}tDATA_RX_CTRL;
uint8 find_pci_device(uint16 venid, uint16 devid, uint16 index, uint16 *businfo)
{
uint8 rc;
uint16 temp;
asm{
mov ax, 0xb102;
mov cx, devid;
mov dx, venid;
mov si, index;
int 0x1a;
mov temp, bx;
mov rc, ah;
}
*businfo = temp;
return rc;
}
uint8 read_configuration_word(uint16 businfo, uint16 ofset, uint16 *data)
{
uint8 rc;
uint16 temp;
asm{
mov ax, 0xb109;
mov bx, businfo;
mov di, ofset;
int 0x1a;
mov temp, cx;
mov rc, ah;
}
*data = temp;
return rc;
}
uint8 write_configuration_word(uint16 businfo, uint16 ofset, uint16 data)
{
uint8 rc;
uint16 temp = data;
asm{
mov ax, 0xb10c;
mov bx, businfo;
mov di, ofset;
mov cx, temp;
int 0x1a;
mov rc, ah;
}
return rc;
}
void delay(uint16 delay_time)
{
uint16 i;
uint16 j;
for (i=delay_time;i--;i>0)
{
for (j=0xffff;j--;j>0)
{
;
}
}
}
void com_buad_set(uint16 base_address, uint32 rate)
{
uint16 divisor;
uint8 temp;
divisor = GET_BUAD_DIVISOR(rate);
temp = REG_RD(base_address+COM_OFFSET_LCR);
temp = temp|0x80;
REG_WR(base_address+COM_OFFSET_LCR, temp);
REG_WR(base_address+COM_OFFSET_DIVISOR_LSB, divisor&0x00FF);
REG_WR(base_address+COM_OFFSET_DIVISOR_MSB, ((divisor>>8)*0x00FF));
temp = temp&(~(0x80));
REG_WR(base_address+COM_OFFSET_LCR, temp);
}
void com_init(uint16 base_address, tCOM_OP_ARG *com_op_arg_list)
{
uint8 temp;
com_buad_set(base_address, com_op_arg_list->baudrate);
REG_WR(base_address+COM_OFFSET_LCR, 0x03); // 8bits 1stop no parity
if (com_op_arg_list->fifo == COM_OP_ARG_FIFO)
REG_WR(base_address+COM_OFFSET_FCR, 0x07|((com_op_arg_list->trigger-1)<<6));
else
REG_WR(base_address+COM_OFFSET_FCR, 0);
if (com_op_arg_list->autoflow == COM_OP_ARG_AUTOFLOW)
REG_WR(base_address+COM_OFFSET_MCR, 0x23);
else
REG_WR(base_address+COM_OFFSET_MCR, 0x03);
if (com_op_arg_list->intr == COM_OP_ARG_INTR)
REG_WR(base_address+COM_OFFSET_IER, 0x0f);
else
REG_WR(base_address+COM_OFFSET_IER, 0);
temp = REG_RD(base_address+COM_OFFSET_IIR);
temp = REG_RD(base_address+COM_OFFSET_LSR);
temp = REG_RD(base_address+COM_OFFSET_MSR);
temp++;
}
void com_poll_rx_auto(uint16 base_address, uint8 *data)
{
uint8 i = 0;
// printf("com_poll_rx_auto LSR=%x\n", REG_RD(base_address+COM_OFFSET_LSR));
while (COM_CHK_DR(base_address) == SET)
{
// check errors
if ((((REG_RD(base_address+COM_OFFSET_LSR))>>1)&0x07)==0)
{
*(data+i) = REG_RD(base_address+COM_OFFSET_RBR);
i++;
}
}
if (i != 0)
{
*(data+i+1) = '\0';
}
}
void com_poll_rx_manu(uint16 base_address, uint8 *data)
{
uint8 i = 0;
uint8 temp = 0;
// printf("com_poll_rx_manu LSR=%x\n", REG_RD(base_address+COM_OFFSET_LSR));
temp = REG_RD(base_address+COM_OFFSET_MCR);
temp = temp&(~(0x02));
REG_WR(base_address+COM_OFFSET_MCR, temp);
while (COM_CHK_DR(base_address) == SET)
{
// check errors
if ((((REG_RD(base_address+COM_OFFSET_LSR))>>1)&0x07)==0)
{
*(data+i) = REG_RD(base_address+COM_OFFSET_RBR);
i++;
}
}
temp = temp|0x02;
REG_WR(base_address+COM_OFFSET_MCR, temp);
if (i != 0)
{
*(data+i+1) = '\0';
}
}
void com_poll_tx_manu(uint16 base_address, tDATA_TX_CTRL *data_tx_ctrlbox)
{
uint8 i = 0;
// printf("com_poll_tx_manu LSR=%x\n", REG_RD(base_address+COM_OFFSET_LSR));
if (COM_CHK_THRE(base_address) == SET)
{
i = data_tx_ctrlbox->offset;
while(((i-data_tx_ctrlbox->offset) <= (data_tx_ctrlbox->num_tx_1cycle-1))&&(i <= (data_tx_ctrlbox->num_data-1)))
{
if (COM_CHK_CTS(base_address) != SET)
break;
REG_WR(base_address+COM_OFFSET_THR, *(data_tx_ctrlbox->pdata+i));
i++;
}
data_tx_ctrlbox->offset = i;
}
}
void com_poll_tx_auto(uint16 base_address, tDATA_TX_CTRL *data_tx_ctrlbox)
{
uint8 i = 0;
// printf("com_poll_tx_auto LSR=%x\n", REG_RD(base_address+COM_OFFSET_LSR));
if (COM_CHK_THRE(base_address) == SET)
{
i = data_tx_ctrlbox->offset;
while(((i-data_tx_ctrlbox->offset) <= (data_tx_ctrlbox->num_tx_1cycle-1))&&(i <= (data_tx_ctrlbox->num_data-1)))
{
REG_WR(base_address+COM_OFFSET_THR, *(data_tx_ctrlbox->pdata+i));
i++;
}
data_tx_ctrlbox->offset = i;
}
}
void print_pci_config_space(uint16 businfo)
{
uint16 temp, i, pciconfig[32];
for (i=0;i<0x40;i+=2)
{
if (read_configuration_word(businfo, i, &temp) == SUCCESS)
{
pciconfig[i/2] = temp;
}
}
printf("\n\\**********************************\\");
printf("\n\\**** PCI CONFIGURATION SPACE *****\\");
printf("\n\\**********************************\\\n");
printf("Device ID = %x Vendor ID = %x\n", pciconfig[1], pciconfig[0]);
printf("Status = %x Command = %x\n", pciconfig[3], pciconfig[2]);
printf("Class Code = %x Revision ID = %x\n", (pciconfig[5]<<8)|(pciconfig[4]>>8), pciconfig[4]&0x00ff);
printf("BIST = %x Header Type = %x Latency Timer = %x Cache Line = %x\n", pciconfig[7]>>8, pciconfig[7]&0x00ff, pciconfig[6]>>8, pciconfig[6]&0x00ff);
printf("Base Address 0 = %x\n", (pciconfig[9]<<16)|pciconfig[8]);
printf("Base Address 1 = %x\n", (pciconfig[11]<<16)|pciconfig[10]);
printf("Base Address 2 = %x\n", (pciconfig[13]<<16)|pciconfig[12]);
printf("Base Address 3 = %x\n", (pciconfig[15]<<16)|pciconfig[14]);
printf("Base Address 4 = %x\n", (pciconfig[17]<<16)|pciconfig[16]);
printf("Base Address 5 = %x\n", (pciconfig[19]<<16)|pciconfig[18]);
printf("CardBus CIS pointer = %x\n", (pciconfig[21]<<16)|pciconfig[20]);
printf("Subsystem Device ID = %x Subsystem Vendor ID = %x\n", pciconfig[23], pciconfig[22]);
printf("Expansion ROM Base Address = %x\n", (pciconfig[25]<<16)|pciconfig[24]);
printf("Reserved = %x\n", (pciconfig[27]<<16)|pciconfig[26]);
printf("Reserved = %x\n", (pciconfig[29]<<16)|pciconfig[28]);
printf("Max_Lat = %x Min_Gnt = %x IRQ Pin = %x IRQ Line = %x\n", pciconfig[31]>>8, pciconfig[31]&0x00ff, pciconfig[30]>>8, pciconfig[30]&0x00ff);
}
void get_user_arg(tCOM_OP_ARG *com_op_arg_list)
{
uint32 temp = 0;
uint8 tstr[10];
printf("\n\\**********************************\\");
printf("\n\\*** COM Operation Mode Setting ***\\");
printf("\n\\**********************************\\");
while (1)
{
printf("\nNeed FIFO or not? (y or n)\n");
scanf("%s", &tstr);
if (strcmp(tstr, "y") == SUCCESS)
{
com_op_arg_list->fifo = COM_OP_ARG_FIFO;
break;
}
else if (strcmp(tstr, "n") == SUCCESS)
{
com_op_arg_list->fifo = !COM_OP_ARG_FIFO;
com_op_arg_list->trigger = 0;
break;
}
else
printf("Arg is illegal!\n");
}
if (com_op_arg_list->fifo == COM_OP_ARG_FIFO)
{
while (1)
{
printf("\nSet FIFO trigger level. (1:1Byte; 2:4Bytes; 3:8Bytes; 4:14Bytes)\n");
scanf("%s", &tstr);
temp = atoi(tstr);
if (temp>=1 && temp<=4)
{
com_op_arg_list->trigger = temp;
break;
}
else
printf("Arg is illegal!\n");
}
}
while (1)
{
printf("\nintr mod or polled mod? (intr or polled)\n");
scanf("%s", &tstr);
if (strcmp(tstr, "intr") == SUCCESS)
{
com_op_arg_list->intr = COM_OP_ARG_INTR;
break;
}
else if (strcmp(tstr, "polled") == SUCCESS)
{
com_op_arg_list->intr = !COM_OP_ARG_INTR;
break;
}
else
printf("Arg is illegal!\n");
}
while (1)
{
printf("\nEnable autoflow control or not? (y or n)\n");
scanf("%s", &tstr);
if (strcmp(tstr, "y") == SUCCESS)
{
com_op_arg_list->autoflow = COM_OP_ARG_AUTOFLOW;
break;
}
else if (strcmp(tstr, "n") == SUCCESS)
{
com_op_arg_list->autoflow = !COM_OP_ARG_AUTOFLOW;
break;
}
else
printf("Arg is illegal!\n");
}
while (1)
{
printf("Set com baud rate.\n");
scanf("%s", &tstr);
temp = atol(tstr);
if (temp <= 921600)
{
com_op_arg_list->baudrate = temp;
break;
}
else
printf("Arg is illegal!\n");
}
}
void com_poll_run(uint16 base_address, tCOM_OP_ARG *com_op_arg_list, uint8 *data_tx, uint8 *data_rx)
{
uint8 temp;
tDATA_TX_CTRL data_tx_ctrlbox;
void (*pcom_poll_tx)(uint16 base_address, tDATA_TX_CTRL *data_tx_ctrlbox);
void (*pcom_poll_rx)(uint16 base_address, uint8 *data);
data_tx_ctrlbox.pdata = data_tx;
data_tx_ctrlbox.num_data = strlen(data_tx);
data_tx_ctrlbox.offset = 0;
if (com_op_arg_list->fifo == COM_OP_ARG_FIFO)
data_tx_ctrlbox.num_tx_1cycle = 16;
else
data_tx_ctrlbox.num_tx_1cycle = 1;
if (com_op_arg_list->autoflow == COM_OP_ARG_AUTOFLOW)
{
pcom_poll_tx = com_poll_tx_auto;
pcom_poll_rx = com_poll_rx_auto;
}
else
{
pcom_poll_tx = com_poll_tx_manu;
pcom_poll_rx = com_poll_rx_manu;
}
printf("data_rx=");
while (1)
{
if (data_tx_ctrlbox.offset <= (data_tx_ctrlbox.num_data-1))
(*pcom_poll_tx)(base_address, &data_tx_ctrlbox);
(*pcom_poll_rx)(base_address, data_rx);
if (*data_rx != '\0')
{
printf("%s", data_rx);
memset(data_rx, 0, 31*sizeof(uint8));
}
if (kbhit())
{
temp = getch();
if (temp == 27) // Press Esc
return;
}
}
}
void com_intr_run(uint16 base_address, tCOM_OP_ARG *com_op_arg_list, uint8 *data_tx, uint8 *data_rx)
{
}
void main(void)
{
uint16 temp, businfo, base_address;
uint8 data_tx[31], data_rx[31], tstr[10];
tCOM_OP_ARG com0_op_arg_list;
// find pci device
if(find_pci_device(VENDOR_ID, DEVICE_ID, 0, &temp) == SUCCESS)
businfo = temp;
else
{
printf("Device NOT Found!!!");
return;
}
print_pci_config_space(businfo);
// write_configuration_word(businfo, PCI_OFFSET_BASE_ADDRESS, 0x4001);
if (read_configuration_word(businfo, PCI_OFFSET_BASE_ADDRESS, &temp) == SUCCESS)
{
base_address = temp&(~(0x01));
printf("base_address1=%x\n", base_address);
}
get_user_arg(&com0_op_arg_list);
com_init(base_address, &com0_op_arg_list);
while(1)
{
if (COM_CHK_DSR(base_address) != SET)
{
printf("\nDST is not ready. Wait for a while to check again.");
delay(0xffff);
continue;
}
printf("\n\\**********************************\\");
printf("\n\\*** COM Operation **************\\");
printf("\n\\**********************************\\");
while(1)
{
printf("\nWhat do you want do?");
printf("\n1 Tx a data.");
printf("\n2 Re-set COM operation arguments.");
printf("\n3 Print COM Setting.");
printf("\n4 Exit.");
printf("\nYour choice:");
scanf("%s", &tstr);
temp = atoi(tstr);
if (temp>=1 && temp<=4)
break;
}
switch (temp)
{
case 1:
{
printf("\nPlease enter words you want to tx. (less than 30 words)\n");
scanf("%s", &data_tx);
memset(data_rx, 0, 31*sizeof(uint8));
if (com0_op_arg_list.intr == COM_OP_ARG_INTR)
com_intr_run(base_address, &com0_op_arg_list, data_tx, data_rx);
else
com_poll_run(base_address, &com0_op_arg_list, data_tx, data_rx);
break;
}
case 2:
{
get_user_arg(&com0_op_arg_list);
com_init(base_address, &com0_op_arg_list);
break;
}
case 3:
{
print_pci_config_space(businfo);
break;
}
case 4:
exit(0);
default:;
}
/*
if (com0_op_arg_list.intr == COM_OP_ARG_INTR)
com_intr_run_1cycle(base_address, data_tx, data_rx);
else
com_poll_run_1cycle(base_address, data_tx, data_rx);
*/
}
/*
while(1)
{
if (COM_CHK_DSR(base_address) == SET)
{
com_poll_rx(base_address, data_rx);
com_poll_tx(base_address, data_tx);
if (data_rx != 0)
{
printf("data_tx=%s\n", data_tx);
printf("data_rx=%s\n", data_rx);
}
}
}
*/
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -