www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1997/04/01/22:48:16

Newsgroups: comp.os.msdos.djgpp
From: Logan Bowers <LegoB AT juno DOT com>
Subject: Programming IRQs in Svasync
Message-ID: <3341A28F.5527@juno.com>
Sender: news AT linex6 DOT linex DOT com (news admin)
Reply-To: LegoB AT juno DOT com
Organization: LineX Communications (415) 455-1650
Mime-Version: 1.0
Date: Wed, 2 Apr 1997 00:04:31 GMT
Lines: 469
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp

This is a multi-part message in MIME format.

--------------2E696B3C67FD
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

I am attempting to access two comm ports on non-standard IRQs (5 and 9)
and failing miserably.  In the source code (attached) four settings are
made for each port:

Com2: 
  Port = 0x02F8
  VectorNum = 0x0B
  EnableIRQ = 0xF7
  DisableIRQ = 0x08
Com3:
  Port = 0x03E8
  VectorNum= 0x0C
  EnableIRQ = 0xEF
  DisableIRQ = 0x10

I know what the port setting is, and I know the values are in hex, but I
can't figure out how to change them so that a comm port on a different
IRQ works.  Any help would be really appriciated.  Thanks.


Logan Bowers
LegoB AT juno DOT com

--------------2E696B3C67FD
Content-Type: text/plain; charset=us-ascii; name="Svasync.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="Svasync.c"

/*
 * SVAsync 0.10
 * Copyright (c) 1996 Samuel Vincent, 7337 Carioca Ct, Rohnert Park, Ca 94928
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <dos.h>
#include <dpmi.h>
#include <pc.h>
#include <go32.h>
#include <sys/farptr.h>
#include <sys/movedata.h>
#include <conio.h>

#include "svasync.h"

extern unsigned short __djgpp_ds_alias;
extern void SVAsyncProtISR(void);

#define Ctrl8259_0 0x020                /* 8259 port */
#define Ctrl8259_1 0x021                /* 8259 port (Masks) */
#define BufSize 32768                   /* Buffer Size */

/* Globals to be set in SVAsyncInit() */

static unsigned char VectorNum;                /* Vector Number */
static unsigned char EnableIRQ;                /* Mask to enable 8259 IRQ */
static unsigned char DisableIRQ;               /* Mask to disable 8259 IRQ */
static _go32_dpmi_seginfo ProtVector;          /* Old Protmode Vector */
static _go32_dpmi_seginfo info;                /* New Protmode Vector */

/* Register Addresses for the UART */
static unsigned short Port;                    /* Port Base Address */

unsigned short THR;                     /* Transmitter Holding Register */
unsigned short RDR;                     /* Reciever Data Register */
unsigned short BRDL;                    /* Baud Rate Divisor, Low byte */
unsigned short BRDH;                    /* Baud Rate Divisor, High Byte */
unsigned short IER;                     /* Interupt Enable Register */
unsigned short IIR;                     /* Interupt Identification Register */
unsigned short FCR;                     /* FIFO Control Register */
unsigned short LCR;                     /* Line Control Register */
unsigned short MCR;                     /* Modem Control Register */
unsigned short LSR;                     /* Line Status Register */
unsigned short MSR;                     /* Modem Status Register */
unsigned short SCR;                     /* SCR Register */

/* Buffer Data */
unsigned volatile char RecBuffer[BufSize] = { 0 };
unsigned volatile int RecHead, RecTail;

static unsigned char SVAsyncStatus=0;

static void lock_interrupt_memory(void);
static void unlock_interrupt_memory(void);


/**************************************
*  This will empty the recieve buffer *
***************************************/
void SVAsyncClear(void) {
	disable();
	RecHead = 0;
	RecTail = 0;
	enable();
}


/********************************************************
*  This initalizes the serial port and installs the ISR *
*  CommPort maps out to the following:                  *
*        0  =  COM1                                     *
*        1  =  COM2                                     *
*        2  =  COM3                                     *
*        3  =  COM4                                     *
*********************************************************/
int SVAsyncInit(unsigned int CommPort) {

/**** Set various things according to com port number */
	if(!CommPort) {      /* com 1 */
		Port = 0x03F8;
		VectorNum = 0x0C;
		EnableIRQ = 0xEF;
		DisableIRQ = 0x10;
	}
	else
		if(CommPort == 1) {       /* com 2 */
			Port = 0x02F8;
			VectorNum = 0x0B;
			EnableIRQ = 0xF7;
			DisableIRQ = 0x08;
		}
		else        
			if(CommPort == 2) {     /* com 3 */
				Port = 0x03E8;
				VectorNum = 0x0C;
				EnableIRQ = 0xEF;
				DisableIRQ = 0x10;
			}
			else {           /* com 4 */
				Port = 0x02E8;
				VectorNum = 0x0B;
				EnableIRQ = 0xF7;
				DisableIRQ = 0x08;
			}

/**** Compute Register locations */
	
	THR = Port;
	RDR = Port;
	BRDL = Port;
	BRDH = 1 + Port;
	IER = 1 + Port;
	IIR = 2 + Port;
	FCR = 2 + Port;
	LCR = 3 + Port;
	MCR = 4 + Port;
	LSR = 5 + Port;
	MSR = 6 + Port;
	SCR = 7 + Port;


/***** Initalize Buffer */
	SVAsyncClear();
	
	lock_interrupt_memory();
	atexit(unlock_interrupt_memory);

/***** Set bit 3 in MCR to 0 */
	outportb(MCR, (inportb(MCR) & 0xF7));

/*** Save and reassign interrupt vectors */
	
	_go32_dpmi_get_protected_mode_interrupt_vector(VectorNum, &ProtVector);
	
	info.pm_offset = (int) SVAsyncProtISR;
	info.pm_selector = _my_cs();
	_go32_dpmi_set_protected_mode_interrupt_vector(VectorNum, &info);
	
	atexit(SVAsyncStop);

/***** Enable 8259 interrupt (IRQ) line for this async adapter */
	outportb(Ctrl8259_1, (inportb(Ctrl8259_1) & EnableIRQ));

/***** Enable 8250 Interrupt-on-data-ready */
	outportb(LCR, (inportb(LCR) & 0x7F));
	
	outportb(IER, 0);
	if(inportb(IER)) {
		SVAsyncStatus = 0;
		return 1;
	}
	outportb(IER, 0x01);

/***** Clear 8250 Status and data registers */
	{
		unsigned char temp;

		do {
			temp=inportb(RDR);
			temp=inportb(LSR);
			temp=inportb(MSR);
			temp=inportb(IIR);
		} while(!(temp & 1));
	}

/***** Set Bit 3 of MCR -- Enable interupts */
	outportb(MCR, (inportb(MCR) | 0x08));

	SVAsyncStatus = 1;
/***** Clear Buffer Just in case */
	SVAsyncClear();

	return 0;
}




/*******************************************************
*  This uninstalls the ISR and resets the serial port. *
********************************************************/
void SVAsyncStop(void) {
	if(!SVAsyncStatus)
		return;
	SVAsyncStatus = 0;

/***** Mask (disable) 8259 IRQ Interrupt */
	outportb(Ctrl8259_1, (inportb(Ctrl8259_1) | DisableIRQ));

/***** Disable 8250 interrupt */
	outportb(LCR, (inportb(LCR) & 0x7F));
	outportb(IER, 0);

/***** Set bit 3 in MCR to 0 */
	outportb(MCR, (inportb(MCR) & 0xF7));

/***** Interrupts are disabled.  Restore saved interrupt vector. */
	_go32_dpmi_set_protected_mode_interrupt_vector(VectorNum, &ProtVector);
}


/*************************************
*  Gets a byte from the input buffer *
**************************************/
unsigned char SVAsyncIn(void) {
	unsigned char retvalue;

	if(RecTail == RecHead) {
		return 0;
	}
	
	disable();
	retvalue = RecBuffer[RecTail++];
	if(RecTail >= BufSize)
		RecTail = 0;
	enable();
	return retvalue;
}


/**************************************************
*  This simply outputs a byte to the serial port. *
***************************************************/
void SVAsyncOut(unsigned char CharOut) {
	while(~inportb(LSR) & 0x20);
	outportb(THR, CharOut);
}


/****************************************************************************
*  Sets communication parameters                                            *
*  Baud = 150, 300, 600, 1200, 2400, 4800, 9600, 19200, 28800, 38400, 57600 *
*  Control = The value to place in the LCR                                  *
*****************************************************************************/
void SVAsyncSet(unsigned int Baud, unsigned int Control) {
	int divisor;
	unsigned char divlow, divhigh;

	if(!Baud)
		return;
	
	divisor = 115200 / Baud;

	disable();
	
	outportb(LCR, Control | 0x80); /* Set Port Toggle to BRDL/BRDH registers */
	divlow = divisor & 0x000000ff;
	divhigh = (divisor >> 8) & 0x000000ff;
	outportb(BRDL, divlow);     /* Set Baud Rate */
	outportb(BRDH, divhigh);

	outportb(LCR, Control & 0x007F);          /* Set LCR and Port Toggle */

	enable();
}



/*************************************************
*  Returns the # of characters in input buffer   *
*  waiting to be read.                           *
**************************************************/
int SVAsyncInStat(void) {
	int retvalue;

	if(RecHead >= RecTail)
		retvalue = RecHead - RecTail;
	else
		retvalue = (RecHead - RecTail) + BufSize;
	return retvalue;
}


/***************************************************************
*  Returns the # of characters in output buffer.               *
*  This will only be useful once interrupt driven transmitting *
*  is implemented.                                             *
*  Now, it returns 1 if it cannot instantly send a character   *
*  and 0 otherwise.                                            *
****************************************************************/
int SVAsyncOutStat(void) {
	if(~inportb(LSR) & 0x20)
		return 1;
	else
		return 0;
}


/**********************************
*  Sets various handshaking lines *
*  Returns nothing.               *
***********************************/
void SVAsyncHand(unsigned int Hand) {
	outportb(MCR, Hand | 0x08);  /* Keep interrupt enable ON */
}

unsigned int SVAsyncStat(void) {
	return 0;
}
/*

;-----------------------------------------------------------------------------
;       SVAsyncStat                                       Returns Async/Modem status
;-----------------------------------------------------------------------------
;       unsigned        SVAsyncStat( void)
;
;       MSR is returned in the high byte, LSR in the low byte
;-----------------------------------------------------------------------------
PROC    _SVAsyncStat
	push    bp
	mov     bp, sp

	mov     dx, [MSR]
	in      al, dx
	mov     cl, al
	mov     dx, [LSR]
	in      al, dx                  ; LSR in low byte
	mov     ah, cl                  ; MSR in high byte

	pop     bp
	ret
ENDP    _SVAsyncStat


	END

*/


/**********************
 * Internal function  *
 **********************/
static void lock_interrupt_memory(void) {
	int errval;
	__dpmi_meminfo info;
	unsigned long address;
	
	__dpmi_get_segment_base_address(_my_ds(), &address);
	info.address = (int) address + (int) &RDR;
	info.size = sizeof(RDR);
	errval = __dpmi_lock_linear_region(&info);
	if(errval == -1)
		printf("Error in locking memory\n!");
	info.address = (int) address + (int) &LSR;
	info.size = sizeof(LSR);
	errval = __dpmi_lock_linear_region(&info);
	if(errval == -1)
		printf("Error in locking memory\n!");
	info.address = (int) address + (int) &RecHead;
	info.size = sizeof(RecHead);
	errval = __dpmi_lock_linear_region(&info);
	if(errval == -1)
		printf("Error in locking memory\n!");
	info.address = (int) address + (int) &RecBuffer;
	info.size = sizeof(RecBuffer);
	errval = __dpmi_lock_linear_region(&info);
	if(errval == -1)
		printf("Error in locking memory\n!");
	info.address = (int) address + (int) RecBuffer;
	info.size = BufSize;
	errval = __dpmi_lock_linear_region(&info);
	if(errval == -1)
		printf("Error in locking memory\n!");
	
	__dpmi_get_segment_base_address(_my_cs(), &address);
	
	info.address = (int) address + (int) SVAsyncProtISR;
	info.size = 4096; /* 4096 bytes is probably overkill. */
	errval = __dpmi_lock_linear_region(&info);
	if(errval == -1)
		printf("Error in locking memory\n!");
	info.address = (int) address + (int) __djgpp_ds_alias;
	info.size = 2;
	errval = __dpmi_lock_linear_region(&info);
	if(errval == -1)
		printf("Error in locking memory\n!");
}

/**********************
 * Internal function  *
 **********************/
static void unlock_interrupt_memory(void) {
	__dpmi_meminfo info;
	unsigned long address;
	
	__dpmi_get_segment_base_address(_my_ds(), &address);
	info.address = (int) address + (int) &RDR;
	info.size = sizeof(RDR);
	__dpmi_unlock_linear_region(&info);
	info.address = (int) address + (int) &LSR;
	info.size = sizeof(LSR);
	__dpmi_unlock_linear_region(&info);
	info.address = (int) address + (int) &RecHead;
	info.size = sizeof(RecHead);
	__dpmi_unlock_linear_region(&info);
	info.address = (int) address + (int) &RecBuffer;
	info.size = sizeof(RecBuffer);
	__dpmi_unlock_linear_region(&info);
	info.address = (int) address + (int) RecBuffer;
	info.size = BufSize;
	__dpmi_unlock_linear_region(&info);
	
	__dpmi_get_segment_base_address(_my_cs(), &address);
	
	info.address = (int) address + (int) SVAsyncProtISR;
	info.size = 4096; /* probably overkill */
	__dpmi_unlock_linear_region(&info);
	info.address = (int) address + (int) __djgpp_ds_alias;
	info.size = 2;
	__dpmi_unlock_linear_region(&info);
}

/**************************************************
 * Detects UART type, enables FIFO if it exists.  *
 * Returns 0 if 16550 UART and FIFO enabled.      *
 * Returns 1 if 16450 UART.                       *
 * Returns 2 if less than 16450 UART.             *
 **************************************************/

int SVAsyncFifoInit(void) {
	outportb(SCR, 0x55);
	if(inportb(SCR) != 0x55)
		return 2;
	outportb(FCR, 0x0f);
	if( (inportb(IIR)&0xC0) != 0xC0)
		return 1;
	outportb(FCR, 1 | 2 | 64); /* 8 byte trigger level on receive. */
	return 0;
}

--------------2E696B3C67FD--

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019