Listing 1. sio Library
#include <linux/unistd.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/irq.h>
#define PORT 0x3f8
#define LCR 3
#define MSB 1
#define LSB 0
#define FCR 2
#define SCR 7
int bufferin;
int bufferout;
char buffer[1024];
/****************sioEnable****************/
asmlinkage int sioEnable(int irq)
{
int i;
int myirq=irq;
unsigned long flags;
bufferin = 0;
bufferout = 0;
save_flags(flags); cli();
i=request_irq(myirq,sioHandler,SA_INTERRUPT,"sioJRMS",NULL);
if(i) {
{
restore_flags(flags);
return -1;
}
outb(0,PORT + 1); /* Turn off interrupts -
Port1 */
outb(0,PORT + 1); /* Disable interrupts -
bit 0 ->0 */
outb(0x80,PORT + 3); /* enable DLAB - bit 7 ->1*/
outb(0x0C,PORT + 0); /* Set Divisor LSB */
outb(0x00,PORT + 1); /* Set Divisor MSB */
outb(0x03,PORT + 3); /* 8 Bits, No Parity, 1 Stop
Bit */
outb(0xC7,PORT + 2); /* Enable FIFO if UART is
16500+ */
outb(0x0B,PORT + 4); /* Turn on DTR, RTS, and
OUT2 */
outb(0x01,PORT + 1); /* Interrupt when data
received */
printk("sioEnable --ok ... irq: %d\n", irq);
restore_flags(flags);
return 1;
}
/************* sioHandle ***************/
static void sioHandler(int myirq, void *dev_id, struct pt_regs * regs)
{
int i;
do { i = inb(PORT + 5);
if (i & 1) {
buffer[bufferin] = inb(PORT);
bufferin++;
if (bufferin == 1024) bufferin = 0;
}
}while (i & 1);
}
/************** sioRead ****************/
asmlinkage int sioRead(void)
{
char ch;
if (bufferin != bufferout){
ch = buffer[bufferout];
bufferout++;
if (bufferout == 1024) bufferout = 0;
return ch;
}
}
/***************** sioWrite *******************/
asmlinkage void sioWrite(unsigned char c)
{
outb(c,PORT);
}
/***************** sioEnd *********************/
asmlinkage void sioEnd()
{
unsigned int myirq=4;
free_irq(myirq,NULL);
}
/**************** getLCR ***********************/
unsigned char getLCR(){
return (inb(PORT+LCR));
}
/**************** setLCR *********************/
void setLCR (unsigned char byte){
outb(byte,PORT+LCR);
}
/************ sioGetDivisor *****************/
asmlinkage unsigned sioGetDivisor(){
unsigned divisor;
setLCR(getLCR() | 0x80);
divisor=inb(PORT+MSB);
divisor=divisor << 8;
divisor+=inb(PORT+LSB);
setLCR(getLCR() & 0x7f);
return (divisor);
}
/************* sioSetDivisor ********************/
asmlinkage void sioSetDivisor(unsigned newDiv){
setLCR(getLCR() | 0x80);
outb(newDiv & 0x00ff, PORT+LSB);
outb(newDiv >> 8, PORT+MSB);
setLCR(getLCR() & 0x7f);
}