📄 genport.c
字号:
DebugPrint ((">>>Port%x %d-%d-%d!\n",pLDI->ComBase[pComSetMode->ComNum],pComSetMode->ComNum ,pComSetMode->Baud,pComSetMode->Data ));
switch(pComSetMode->ComNum)
{
case 0:case 1:case 2:case 3:
case 4:case 5:case 6:case 7:
case 8:case 9:case 10:case 11:
ComIndex = pComSetMode->ComNum;
break;
default:
return STATUS_UNSUCCESSFUL;
}
//----------- 初始化串口 ------------//
//复位
WRITE_SELECT_REGISTER(pLDI->ComBase[ComIndex],CSR); //WritePort(m_SPR,m_CSR);
WRITE_INDEX_REGISTER(pLDI->ComBase[ComIndex],0x00); //WritePort(m_LCR,0x00);
DebugPrint ((">>> 复位!\t"));
// WRITE_SELECT_REGISTER(pLDI->ComBase[ComIndex],TCR); //WritePort(m_SPR,m_CSR);
// OldACR = READ_INDEX_REGISTER(pLDI->ComBase[ComIndex]);
// DebugPrint ((">>> TCR = %X!\t",OldACR));
// OldACR = READ_MODEM_CONTROL(pLDI->ComBase[ComIndex]);
// DebugPrint ((">>> MCR = %X!\n",OldACR));
//设置波特率
if(ComIndex >= 0 && ComIndex <=3)
divisor =(USHORT)(614400/pComSetMode->Baud); // Input frequency is 9.8432Mhz 20060907
else
divisor =(USHORT)(691200/pComSetMode->Baud); // Input frequency is 11.0592Mhz 20060907
// WRITE_LINE_CONTROL(pLDI->ComBase[ComIndex],0xBF); //WritePort(m_LCR, 0xBF) ; // Enable access to the EFR, DLL and DLM registers
// WRITE_DIVISOR_LATCH(pLDI->ComBase[ComIndex],divisor); //WritePort( m_DLL,parameter); // DLL
// UCHAR LineControl; \
// LineControl = READ_PORT_UCHAR((PUCHAR)((ULONG_PTR)Address+LCR));
WRITE_PORT_UCHAR((PUCHAR)((ULONG_PTR)pLDI->ComBase[ComIndex]+LCR),(UCHAR)(0xBF));
WRITE_PORT_UCHAR((PUCHAR)((ULONG_PTR)pLDI->ComBase[ComIndex]+DLL),(UCHAR)(divisor & 0xff));
WRITE_PORT_UCHAR((PUCHAR)((ULONG_PTR)pLDI->ComBase[ComIndex]+DLM),(UCHAR)((divisor & 0xff00) >> 8));
DebugPrint ((">>> divisor = 0x%X!\t",divisor));
//设置模式选择
WRITE_ENHANCED_FEATURE_REGISTER(pLDI->ComBase[ComIndex],0x10); //WritePort( m_EFR, 0x10); // EFR, enhance mode select,disnable RTS CTS flow control
DebugPrint ((">>> 非自动流控制!\n"));
//设置数据位,校验位,停止位
parameter = ((pComSetMode->Data - 5) & 0x03) + (((pComSetMode->Stop-1) & 0x01) << 2) ; // 数据位LCR[1:0]和停止位
parameter |= (pComSetMode->Parity & 0x07) << 3;
WRITE_LINE_CONTROL(pLDI->ComBase[ComIndex],parameter); //WritePort( m_LCR, parameter) ; // LCR ,设置数据位,停止位,校验位
DebugPrint ((">>> parameter = %X !\n",parameter));
//设置工作模式
parameter = (pComSetMode->Mode << 4 ) | 0xa; //0xa 开RTS
WRITE_MODEM_CONTROL(pLDI->ComBase[ComIndex],parameter); //WritePort( m_MCR, parameter) ; //设置模式mode=0正常,mode=1循环,out2=1,out1=0,RTS=1,DTR=0
DebugPrint ((">>> 模式 = %X!\n",parameter));
if(pComSetMode->Count > 0)
{
WRITE_FIFO_CONTROL(pLDI->ComBase[ComIndex],0x07); //WritePort( m_FCR ,0x07 ); // Enable FIFO, Flush THR and RHR
WRITE_SELECT_REGISTER(pLDI->ComBase[ComIndex],ACR); //WritePort( m_SPR ,m_ACR ); // SPR = 0, PT ACR
WRITE_INDEX_REGISTER(pLDI->ComBase[ComIndex],0x60); //WritePort( m_ICR ,0x60 ); // ACR, enable 950 mode,ICR read enable
WRITE_SELECT_REGISTER(pLDI->ComBase[ComIndex],TTL); //WritePort( m_SPR ,m_TTL ); // SPR = 4, PT TTL
WRITE_INDEX_REGISTER(pLDI->ComBase[ComIndex],1); //WritePort( m_ICR ,Count ); // Transmit trigger level
WRITE_SELECT_REGISTER(pLDI->ComBase[ComIndex],RTL); //WritePort( m_SPR ,m_RTL ); // SPR = 5, PT RTL
WRITE_INDEX_REGISTER(pLDI->ComBase[ComIndex],pComSetMode->Count);//WritePort( m_ICR ,Count ); // Receive trigger level
WRITE_SELECT_REGISTER(pLDI->ComBase[ComIndex],FCL); //WritePort( m_SPR ,m_FCL ); // SPR = 6, PT FCL
WRITE_INDEX_REGISTER(pLDI->ComBase[ComIndex],0x01); //WritePort( m_ICR ,1 );
WRITE_SELECT_REGISTER(pLDI->ComBase[ComIndex],FCH); //WritePort( m_SPR ,m_FCH );
WRITE_INDEX_REGISTER(pLDI->ComBase[ComIndex],pComSetMode->Count);//WritePort( m_ICR ,Count );
}
DebugPrint ((">>> FifoLevel = %d!\n",pComSetMode->Count));
//读空接收Fifo
for(i = 0 ;i < 128;i++)
{
READ_RECEIVE_BUFFER(pLDI->ComBase[ComIndex]); //ReadPort(m_RHR,&ReadData);
}
DebugPrint ((">>> 清空接收Fifo!\n"));
//开接收中断
if(pComSetMode->bInterrupt == 1 && pLDI->FoundInterrupt)//如果有中断就置为COM_HAVE_IRQ
{
WRITE_INTERRUPT_ENABLE(pLDI->ComBase[ComIndex],0x01); //WritePort( m_IER ,0x01 ); // IER, enable receive interrupt
pLDI->Com_Have_IRQ = ComIndex;
DebugPrint ((">>>Com%d 开接收中断 %d!\n",ComIndex,pLDI->Com_Have_IRQ));
}
else
{
WRITE_INTERRUPT_ENABLE(pLDI->ComBase[ComIndex],0x00); //WritePort( m_IER ,0x01 ); // IER, enable receive interrupt
DebugPrint ((">>> 关接收,发送空中断 %d!\n",pLDI->Com_Have_IRQ));
}
/**/
// DebugPrint ((">>>Inited[ComIndex] = TRUE %X!\n",pLDI));
pLDI->Inited[ComIndex] = TRUE;
p1 = (UCHAR*)&pLDI->ComState[ComIndex];
p2 = (UCHAR*)pComSetMode;
for(i = 0;i < sizeof(COM_SET_MODE);i++)
p1[i] = p2[i];
//----------- 结束 初始化串口 ------------//
//结束设置
//
pIrp->IoStatus.Information = InBufferSize;
return STATUS_SUCCESS;
}
NTSTATUS
SerialReadData(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP pIrp,
IN PIO_STACK_LOCATION IrpStack,
IN USHORT ComIndex
)
/*++
Routine Description:
Arguments:
DeviceObject - Pointer to the device object for this device
Irp - Pointer to the IRP for the current request
Return Value:
If the io is zero length then it will return STATUS_SUCCESS,
otherwise this routine will return the status returned by
the actual start read routine.
--*/
{
PLOCAL_DEVICE_INFO pLDI = (PLOCAL_DEVICE_INFO)DeviceObject->DeviceExtension;
// NOTE: Use METHOD_BUFFERED ioctls.
PCOM_SET_MODE pComSetMode; //指向InBuffer中的COM_SET_MODE结构体
PUCHAR pIOBuffer; // Pointer to transfer buffer
// (treated as an array of longs).
ULONG InBufferSize; // Amount of data avail. from caller.
ULONG OutBufferSize; // Max data that caller can accept.
ULONG nPort; // Port number to read
int i,RealReadSize;
PAGED_CODE();
// DebugPrint ((">>>Entered SerialReadData! Com%d\n",ComIndex));
// Size of buffer containing data from application
InBufferSize = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
OutBufferSize = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
// NT copies inbuf here before entry and copies this to outbuf after
// return, for METHOD_BUFFERED IOCTL's.
pIOBuffer = (PUCHAR)pIrp->AssociatedIrp.SystemBuffer;
RealReadSize = InBufferSize < pLDI->Buf[REC_INDEX][ComIndex] .Number ?
(InBufferSize): pLDI->Buf[REC_INDEX][ComIndex] .Number;
pIrp->IoStatus.Information = RealReadSize;
if(pIOBuffer == NULL)
{
DebugPrint (("pIOBuffer == NULL InBufferSize=%d RealReadSize=%d\n",InBufferSize,RealReadSize));
return STATUS_UNSUCCESSFUL;
}
else
{
// DebugPrint (("InBufferSize=%d RealReadSize=%d pIOBuffer[3]=%X\n",InBufferSize,RealReadSize,pIOBuffer[3]));
}
if(RealReadSize > 0)
{
for(i = 0;i < RealReadSize;i++)
{
BufPopByte(&pLDI->Buf[REC_INDEX][ComIndex] ,&(UCHAR)pIOBuffer[i]);
// DebugPrint (("%X ",(UCHAR)pIOBuffer[i]));
}
DebugPrint (("Com%d 读 %d \t缓 %d \n",ComIndex,RealReadSize,pLDI->Buf[REC_INDEX][ComIndex].Number));
}
else
{
IoRequestDpc(pLDI->DeviceObject,0,NULL);
}
// Check to ensure input buffer is big enough to hold a port number and
// the output buffer is at least as big as the port data width.
//
return STATUS_SUCCESS;
}
NTSTATUS
SerialWriteData(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP pIrp,
IN PIO_STACK_LOCATION IrpStack,
IN USHORT ComIndex
)
/*++
Routine Description:
Arguments:
DeviceObject - Pointer to the device object for this device
Irp - Pointer to the IRP for the current request
Return Value:
If the io is zero length then it will return STATUS_SUCCESS,
otherwise this routine will return the status returned by
the actual start read routine.
--*/
{
PLOCAL_DEVICE_INFO pLDI = (PLOCAL_DEVICE_INFO)DeviceObject->DeviceExtension;
// NOTE: Use METHOD_BUFFERED ioctls.
PUCHAR pIOBuffer; // Pointer to transfer buffer
// (treated as an array of longs).
ULONG InBufferSize; // Amount of data avail. from caller.
ULONG OutBufferSize; // Max data that caller can accept.
UCHAR OldACR,AL;
int i,RealWriteSize,Count;
PAGED_CODE();
// DebugPrint ((">>>entered SerialWriteData! Com%d\n",ComIndex));
// Size of buffer containing data from application
InBufferSize = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
// Size of buffer for data to be sent to application
OutBufferSize = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
// NT copies inbuf here before entry and copies this to outbuf after
// return, for METHOD_BUFFERED IOCTL's.
pIOBuffer = (PUCHAR)pIrp->AssociatedIrp.SystemBuffer;
// Check to ensure input buffer is big enough to hold a port number and
// the output buffer is at least as big as the port data width.
//
RealWriteSize = InBufferSize < (pLDI->Buf[SEND_INDEX][ComIndex] .MaxSize - pLDI->Buf[SEND_INDEX][ComIndex] .Number) ?
(InBufferSize):(pLDI->Buf[SEND_INDEX][ComIndex] .MaxSize - pLDI->Buf[SEND_INDEX][ComIndex] .Number);
pIrp->IoStatus.Information = RealWriteSize;
if(pIOBuffer == NULL || (unsigned long)RealWriteSize < InBufferSize || RealWriteSize == 0)
{
DebugPrint (("pIOBuffer == NULL InBufferSize=%d RealWriteSize=%d\n",InBufferSize,RealWriteSize));
return STATUS_UNSUCCESSFUL;
}
else
{
// DebugPrint (("InBufferSize=%d RealWriteSize=%d pIOBuffer[3]=%X\n",InBufferSize,RealWriteSize,pIOBuffer[3]));
}
if(RealWriteSize > 0)
{
for(i = 0;i < RealWriteSize;i++)
{
KeWaitForSingleObject(&pLDI->BufSemaphore[SEND_INDEX][ComIndex], Executive, KernelMode,FALSE, NULL);
BufPushByte(&pLDI->Buf[SEND_INDEX][ComIndex] ,(UCHAR)pIOBuffer[i]);//隐患:如果此时发送空中断发生,有可能同时访问发送BUF
KeReleaseSemaphore(&pLDI->BufSemaphore[SEND_INDEX][ComIndex], 0, 1, FALSE);
// DebugPrint (("%X ",(UCHAR)pIOBuffer[i]));
}
// DebugPrint (("Buf[SEND_INDEX][%d].Number = %d\n",ComIndex,pLDI->Buf[SEND_INDEX][ComIndex].Number));
DebugPrint (("Com%d 写 %d \t缓 %d \n",ComIndex,RealWriteSize,pLDI->Buf[SEND_INDEX][ComIndex].Number));
/* if(ComIndex == COM_HAVE_IRQ)
{
//读取发送Fifo中,数据个数,如果没有数,则发送一个,激活发送空中断
WRITE_SELECT_REGISTER(pLDI->ComBase[ComIndex],ACR);
OldACR = READ_INDEX_REGISTER(pLDI->ComBase[ComIndex]);
WRITE_INDEX_REGISTER(pLDI->ComBase[ComIndex],(UCHAR)(OldACR|0x80));
Count = READ_TRANSMITTER_FIFO_LEVEL(pLDI->ComBase[ComIndex]);
//Count2 = READ_RECIEVER_FIFO_LEVEL(pLDI->ComBase[ComIndex]);
OldACR = READ_INDEX_REGISTER(pLDI->ComBase[ComIndex]);
WRITE_INDEX_REGISTER(pLDI->ComBase[ComIndex],(UCHAR)(OldACR & 0x7F));
if(Count == 0)
{
BufPopByte(&(pLDI->Buf[SEND_INDEX][ComIndex]) ,&AL);
WRITE_TRANSMIT_BUFFER(pLDI->ComBase[ComIndex],AL);
// DebugPrint (("%X ",AL));
}
}
*/ }
else
{
DebugPrint (("SendBuf 满 Num = %d 或InBuffSize=%d OutBufferSize=%d\n",pLDI->Buf[SEND_INDEX][ComIndex].Number,InBufferSize,OutBufferSize));
return STATUS_UNSUCCESSFUL;
}
return STATUS_SUCCESS;
}
//读串口硬件的数据
NTSTATUS
SerialReadPort(
IN PDEVICE_OBJECT DeviceObject,
IN USHORT ComIndex,
IN UCHAR *Buf,
IN USHORT BufSize,
OUT USHORT *RealReadSize
)
{
PLOCAL_DEVICE_INFO pLDI = (PLOCAL_DEVICE_INFO)DeviceObject->DeviceExtension;
UCHAR OldACR,AL,CurrentISR;
int Count1,Count2,i;
//test
// PAGED_CODE();
//test end
if((!pLDI->Inited[ComIndex])||
(ComIndex == pLDI->Com_Have_IRQ && pLDI->FoundInterrupt) ||
Buf == NULL ||
BufSize == 0)
// if((!pLDI->Inited[ComIndex])|| Buf == NULL || BufSize == 0)
{
*RealReadSize = 0;
return STATUS_UNSUCCESSFUL;
}
//读取接收Fifo中,数据个数
WRITE_SELECT_REGISTER(pLDI->ComBase[ComIndex],ACR);
OldACR = READ_INDEX_REGISTER(pLDI->ComBase[ComIndex]);
WRITE_INDEX_REGISTER(pLDI->ComBase[ComIndex],(UCHAR)(OldACR|0x80));
Count1 = READ_RECIEVER_FIFO_LEVEL(pLDI->ComBase[ComIndex]);
Count2 = READ_RECIEVER_FIFO_LEVEL(pLDI->ComBase[ComIndex]);
OldACR = READ_INDEX_REGISTER(pLDI->ComBase[ComIndex]);
WRITE_INDEX_REGISTER(pLDI->ComBase[ComIndex],(UCHAR)(OldACR & 0x7F));
if(Count1 == 0 || Count2 == 0)
{
*RealReadSize = 0;
return STATUS_UNSUCCESSFUL;
}
if((Count1 != Count2))
{
//AL = (UCHAR)READ_RECEIVE_BUFFER(pLDI->ComBase[ComIndex]);
DebugPrint (("Count1 != Count2 %d %d\n",Count1,Count2));
Count1 = Count1 < Count2 ? Count1 : Count2;
}
*RealReadSize = Count1 <= BufSize ? Count1 : BufSize;
if(*RealReadSize > 0)
{
//test
// DebugPrint (("Com%d 开始读Port %d 个数%d\n",ComIndex,*RealReadSize,pLDI->Com_Have_IRQ));
//test end
for(i = 0;i < *RealReadSize;i++)
{
AL = (UCHAR)READ_RECEIVE_BUFFER(pLDI->ComBase[ComIndex]);
Buf[i] = AL;
//test
// DebugPrint ((" %X ",AL));
//test end
}
// DebugPrint (("Com%d ReadPort %d 完成!\n",ComIndex,*RealReadSize));
}
return STATUS_SUCCESS;
}
//写串口硬件的数据
NTSTATUS
SerialWritePort(
IN PDEVICE_OBJECT DeviceObject,
IN USHORT ComIndex,
IN UCHAR *Buf,
IN USHORT BufSize,
OUT USHORT *RealWriteSize
)
{
PLOCAL_DEVICE_INFO pLDI = (PLOCAL_DEVICE_INFO)DeviceObject->DeviceExtension;
UCHAR OldACR,AL,CurrentISR;
int Count,i;
// PAGED_CODE();
// if((pLDI->Inited[ComIndex] == FALSE) || ComIndex == COM_HAVE_IRQ || Buf == NULL || BufSize == 0)
if((pLDI->Inited[ComIndex] == FALSE)|| Buf == NULL || BufSize == 0)
{
*RealWriteSize = 0;
return STATUS_UNSUCCESSFUL;
}
WRITE_SELECT_REGISTER(pLDI->ComBase[ComIndex],ACR);
OldACR = READ_INDEX_REGISTER(pLDI->ComBase[ComIndex]);
WRITE_INDEX_REGISTER(pLDI->ComBase[ComIndex],(UCHAR)(OldACR|0x80));
Count = READ_TRANSMITTER_FIFO_LEVEL(pLDI->ComBase[ComIndex]);
OldACR = READ_INDEX_REGISTER(pLDI->ComBase[ComIndex]);
WRITE_INDEX_REGISTER(pLDI->ComBase[ComIndex],(UCHAR)(OldACR & 0x7F));
if(Count == 0)
{
*RealWriteSize = BufSize <= 128 ? BufSize : 128;
// DebugPrint (("Com%d 开始写 %d ",ComIndex,*RealWriteSize));
for(i = 0;i < *RealWriteSize;i ++)
{
WRITE_TRANSMIT_BUFFER(pLDI->ComBase[ComIndex],Buf[i]);
// DebugPrint ((" %X ",Buf[i]));
}
}
else
{
*RealWriteSize = 0;
return STATUS_UNSUCCESSFUL;
}
return STATUS_SUCCESS;
}
BOOLEAN
SerialIsS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -