Newsgroups: comp.os.msdos.djgpp From: Logan Bowers Subject: Programming IRQs in Svasync Content-Type: multipart/mixed; boundary="------------2E696B3C67FD" 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 #include #include #include #include #include #include #include #include #include #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--