串口驱动内部实现机制串行设备系统内部实现架构串行设备系统内部实现架构图:串行通信各层使用的结构体及调用关系I/O层I/O层是指7个操作系统提供的API函数的实现过程,即这7个API函数调用中间层提供的函数实现自身功能。
I/O层使用的结构体(三个)一.驱动程序描述符驱动程序描述表:驱动程序描述符数组(iosLibP.h文件)typedef struct /* DRV_ENTRY - entries in driver jump table */{FUNCPTR de_create;FUNCPTR de_delete;FUNCPTR de_open;FUNCPTR de_close;FUNCPTR de_read;FUNCPTR de_write;FUNCPTR de_ioctl;BOOL de_inuse;} DRV_ENTRY;DRV_ENTRY * drvTable;devTable指向驱动程序描述表的首地址,在iosInit()函数中初始化。
二.设备描述符设备列表:(iosLib.h文件)typedef struct /* DEV_HDR - device header for all device structures */{DL_NODE node; /* device linked list node */short drvNum; /* driver number for this device */char * name; /* device name */} DEV_HDR;三.文件描述符文件描述表:(iosLibP.h文件)typedef struct /* FD_ENTRY - entries in file table */{DEV_HDR * pDevHdr;/* device header for this file */int value; /* driver's id for this file */char * name; /* actual file name */BOOL inuse; /* active entry */} FD_ENTRY;I/O层的调用关系I/O层的调用关系和一般的I/O系统的调用关系相同。
中间层(包括TY层和TTY层)中间层是指ttyDrv和tyLib组成的一层。
在一般的字符设备中,没有这一层。
由I/O层直接调用底层驱动,实现字符设备的功能。
中间层使用的结构体TYCO_DEV:typedef struct /* TYCO_DEV */{TY_DEV tyDev;SIO_CHAN * pSioChan;} TYCO_DEV;TY_DEV:typedef struct /* TY_DEV - tty device descriptor */ {DEV_HDR devHdr; /* I/O device header */RING_ID rdBuf; /* ring buffer for read */SEMAPHORE rdSyncSem; /* reader synchronization semaphore */SEMAPHORE mutexSem; /* mutual exclusion semaphore */struct /* current state of the read channel */{unsigned char xoff; /* input has been XOFF'd */unsigned char pending; /* XON/XOFF will be sent when xmtr is free*/unsigned char canceled; /* read has been canceled */unsigned char flushingRdBuf; /* critical section marker */} rdState;RING_ID wrtBuf; /* ring buffer for write */SEMAPHORE wrtSyncSem; /* writer synchronization semaphore */struct /* current state of the write channel */{unsigned char busy; /* transmitter is busy sending character */unsigned char xoff; /* output has been XOFF'd */unsigned char cr; /* CR should be inserted next (after LF) */unsigned char canceled; /* write has been canceled */unsigned char flushingWrtBuf; /* critical section marker */unsigned char wrtBufBusy; /* task level writing to buffer */} wrtState;UINT8 lnNBytes; /* number of bytes in unfinished new line */UINT8 lnBytesLeft; /* number of bytes left in incompletely dequeued line */ unsigned short options; /* options in effect for this channel */FUNCPTR txStartup; /* pointer to routine to start xmitter */FUNCPTR protoHook; /* protocol specific hook routine */int protoArg; /* protocol specific argument */SEL_WAKEUP_LIST selWakeupList; /* tasks that are selected on this dev */int numOpen; /* number of open paths to device */} TY_DEV;SIO_CHAN:typedef struct sio_drv_funcs SIO_DRV_FUNCS;typedef struct sio_chan /* a serial channel */ {SIO_DRV_FUNCS * pDrvFuncs;/* device data */} SIO_CHAN;struct sio_drv_funcs /* driver functions */ {int (*ioctl)(SIO_CHAN * pSioChan,int cmd,void * arg);int (*txStartup)(SIO_CHAN * pSioChan);int (*callbackInstall)(SIO_CHAN * pSioChan,int callbackType,STA TUS (*callback)(),void * callbackArg);int (*pollInput)(SIO_CHAN * pSioChan,char * inChar);int (*pollOutput)(SIO_CHAN * pSioChan,char outChar);};中间层的函数模板(1)驱动安装(ttyDrv.c)STA TUS ttyDrv (void){/* check if driver already installed */if (ttyDrvNum > 0)return (OK);/*安装驱动程序,返回“驱动程序描述表”索引*/ttyDrvNum = iosDrvInstall (ttyOpen, (FUNCPTR) NULL, ttyOpen,ttyClose, tyRead, tyWrite, ttyIoctl);return (ttyDrvNum == ERROR ? ERROR : OK);}(2)设备安装(ttyDrv.c)STA TUS ttyDevCreate(char * name, /* name to use for this device */SIO_CHAN * pSioChan, /* pointer to core driver structure */int rdBufSize, /* read buffer size, in bytes */int wrtBufSize /* write buffer size, in bytes */){TYCO_DEV *pTyCoDev;/*判断驱动是否已经安装*/if (ttyDrvNum <= 0){errnoSet (S_ioLib_NO_DRIVER);return (ERROR);}/*判断参数是否符合要求*/if (pSioChan == (SIO_CHAN *) ERROR){return (ERROR);}/*创建TYCO_DEV结构体*/if ((pTyCoDev = (TYCO_DEV *) malloc (sizeof (TYCO_DEV))) == NULL) return (ERROR);/* 初始化刚刚创建好的TYCO_DEV结构体的TY_DEV结构体*/if (tyDevInit (&pTyCoDev->tyDev, rdBufSize, wrtBufSize,(FUNCPTR) ttyStartup) != OK){free (pTyCoDev);return (ERROR);}/*初始化刚刚创建好的TYCO_DEV结构体的SIO_CHAN结构体*/pTyCoDev->pSioChan = pSioChan;sioCallbackInstall (pSioChan, SIO_CALLBACK_GET_TX_CHAR,tyITx, (void *)pTyCoDev);sioCallbackInstall (pSioChan, SIO_CALLBACK_PUT_RCV_CHAR,tyIRd, (void *)pTyCoDev);/* start the device cranking */sioIoctl (pSioChan, SIO_MODE_SET, (void *)SIO_MODE_INT);/*将创建好、并初始化好的TYCO_DEV结构体安装到“设备列表”中*/ return (iosDevAdd (&pTyCoDev->tyDev.devHdr, name, ttyDrvNum));}底层驱动使用的结构体:(i8250Sio.h文件)typedef struct /* I8250_CHAN */{SIO_DRV_FUNCS * pDrvFuncs; /* driver functions */STATUS (*getTxChar) (); /* pointer to xmitr function */STATUS (*putRcvChar) (); /* pointer tp rcvr function */void * getTxArg;void * putRcvArg;UINT16 int_vec; /* interrupt vector number */UINT16 channelMode; /* SIO_MODE_[INT | POLL] */UCHAR (*inByte) (int); /* routine to read a byte from register */ void (*outByte)(int,char); /* routine to write a byte to register */ULONG lcr; /* UART line control register */ULONG lst; /* UART line status register */ULONG mdc; /* UART modem control register */ ULONG msr; /* UART modem status register */ ULONG ier; /* UART interrupt enable register */ ULONG iid; /* UART interrupt ID register */ULONG brdl; /* UART baud rate register */ULONG brdh; /* UART baud rate register */ULONG data; /* UART data register */ULONG options; /* UART hardware options */} I8250_CHAN;3串口初始化过程一usrInit()函数(bootConfig.c):调用sysHwInit();调用usrKernelInit()kernelInit() sysHwInit()函数(sysLib.c):调用sysSerialHwInit();sysSerialHwInit()函数(sysSerial.c)在sysSerial.c文件中,定义I8250_CHAN i8250Chan[N_UART_CHANNELS];即:为每一个串口定义一个串口描述结构体(I8250_CHAN)(见上)。