Annotation of sbbs/src/sbbs3/sbbsexec.c, revision 1.1.1.2

1.1       root        1: /* sbbsexec.c */
                      2: 
                      3: /* Synchronet Windows NT/2000 VDD for FOSSIL and DOS I/O Interrupts */
                      4: 
1.1.1.2 ! root        5: /* $Id: sbbsexec.c,v 1.39 2007/03/11 01:49:15 rswindell Exp $ */
1.1       root        6: 
                      7: /****************************************************************************
                      8:  * @format.tab-size 4          (Plain Text/Source Code File Header)                    *
                      9:  * @format.use-tabs true       (see http://www.synchro.net/ptsc_hdr.html)              *
                     10:  *                                                                                                                                                     *
                     11:  * Copyright 2006 Rob Swindell - http://www.synchro.net/copyright.html         *
                     12:  *                                                                                                                                                     *
                     13:  * This program is free software; you can redistribute it and/or                       *
                     14:  * modify it under the terms of the GNU General Public License                         *
                     15:  * as published by the Free Software Foundation; either version 2                      *
                     16:  * of the License, or (at your option) any later version.                                      *
                     17:  * See the GNU General Public License for more details: gpl.txt or                     *
                     18:  * http://www.fsf.org/copyleft/gpl.html                                                                                *
                     19:  *                                                                                                                                                     *
                     20:  * Anonymous FTP access to the most recent released source is available at     *
                     21:  * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net     *
                     22:  *                                                                                                                                                     *
                     23:  * Anonymous CVS access to the development source and modification history     *
                     24:  * is available at cvs.synchro.net:/cvsroot/sbbs, example:                                     *
                     25:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs login                       *
                     26:  *     (just hit return, no password is necessary)                                                     *
                     27:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src                *
                     28:  *                                                                                                                                                     *
                     29:  * For Synchronet coding style and modification guidelines, see                                *
                     30:  * http://www.synchro.net/source.html                                                                          *
                     31:  *                                                                                                                                                     *
                     32:  * You are encouraged to submit any modifications (preferably in Unix diff     *
                     33:  * format) via e-mail to [email protected]                                                                      *
                     34:  *                                                                                                                                                     *
                     35:  * Note: If this box doesn't appear square, then you need to fix your tabs.    *
                     36:  ****************************************************************************/
                     37: 
                     38: #include <windows.h> 
                     39: #include <stdio.h>
                     40: #include <vddsvc.h>
                     41: #include "uartdefs.h"
                     42: #include "vdd_func.h"
                     43: #include "ringbuf.h"
                     44: #include "genwrap.h"
                     45: #include "dirwrap.h"
                     46: #include "threadwrap.h"
                     47: #include "ini_file.h"
                     48: 
                     49: #define INI_FILENAME                   "sbbsexec.ini"
                     50: #define RINGBUF_SIZE_IN                        10000
                     51: #define DEFAULT_MAX_MSG_SIZE   4000
                     52: #define LINEAR_RX_BUFLEN               5000
                     53: 
                     54: /* UART Parameters and virtual registers */
                     55: WORD uart_io_base                              = UART_COM1_IO_BASE;    /* COM1 */
                     56: BYTE uart_irq                                  = UART_COM1_IRQ;
                     57: BYTE uart_ier_reg                              = 0;
                     58: BYTE uart_lcr_reg                              = UART_LCR_8_DATA_BITS;
                     59: BYTE uart_mcr_reg                              = UART_MCR_RTS | UART_MCR_DTR;
                     60: BYTE uart_lsr_reg                              = UART_LSR_EMPTY_DATA | UART_LSR_EMPTY_XMIT;
                     61: BYTE uart_msr_reg                              = UART_MSR_CTS | UART_MSR_DSR;
                     62: BYTE uart_scratch_reg                  = 0;
                     63: BYTE uart_divisor_latch_lsb            = 0x03; /* 38400 */
                     64: BYTE uart_divisor_latch_msb            = 0x00;
                     65: 
                     66: #if defined (_DEBUG)
                     67:        int log_level = LOG_DEBUG;
                     68: #else
                     69:        int log_level = LOG_WARNING;
                     70: #endif
                     71: 
                     72: BOOL           virtualize_uart=TRUE;
                     73: double         yield_interval=1.0;
                     74: BOOL           hangup_supported=TRUE;
                     75: HANDLE         hangup_event=NULL;
                     76: HANDLE         hungup_event=NULL;
                     77: HANDLE         interrupt_event=NULL;
                     78: HANDLE         rdslot=INVALID_HANDLE_VALUE;
                     79: HANDLE         wrslot=INVALID_HANDLE_VALUE;
                     80: RingBuf                rdbuf;
                     81: str_list_t     ini;
                     82: char           ini_fname[MAX_PATH+1];
                     83: char           revision[16];
                     84: 
                     85: void lputs(int level, char* msg)
                     86: {      
                     87:        char buf[1024];
                     88:        if(level > log_level)
                     89:                return;
                     90: 
                     91:        SAFEPRINTF(buf,"SBBS: %s\r\n", msg);
                     92:        OutputDebugString(buf);
                     93: }
                     94: 
                     95: static void lprintf(int level, const char *fmt, ...)
                     96: {
                     97:        char sbuf[1024];
                     98:        va_list argptr;
                     99: 
                    100:        if(level > log_level)
                    101:                return;
                    102: 
                    103:     va_start(argptr,fmt);
                    104:     _vsnprintf(sbuf,sizeof(sbuf),fmt,argptr);
                    105:        sbuf[sizeof(sbuf)-1]=0;
                    106:     va_end(argptr);
                    107:     lputs(level,sbuf);
                    108: }
                    109: 
                    110: void hangup()
                    111: {
                    112:        if(hangup_supported && hangup_event!=NULL) {
                    113:                lprintf(LOG_DEBUG,"Hanging-up at application request");
                    114:                SetEvent(hangup_event);
                    115:        }
                    116: }
                    117: 
                    118: void parse_ini(char* program)
                    119: {
                    120:        char section[MAX_PATH+1];
                    121: 
                    122:        if(ini==NULL)   /* no initialization file */
                    123:                return;
                    124: 
                    125:        /* Read the root section of the sbbsexec.ini file */
                    126:        log_level=iniGetLogLevel(ini,program,"LogLevel",log_level);
                    127:        if(iniGetBool(ini,program,"Debug",FALSE))
                    128:                log_level=LOG_DEBUG;
                    129:        yield_interval=iniGetFloat(ini,program,"YieldInterval",yield_interval);
                    130:        hangup_supported=iniGetBool(ini,program,"CanDisconnect",hangup_supported);
                    131: 
                    132:        lprintf(LOG_INFO,"Parsed %s section of %s"
                    133:                ,program==ROOT_SECTION ? "root" : program
                    134:                ,ini_fname);
                    135: 
                    136:        /* [UART] section */
                    137:        if(program==ROOT_SECTION)
                    138:                SAFECOPY(section,"UART");
                    139:        else
                    140:                SAFEPRINTF(section,"%s.UART",program);
                    141: 
                    142:        virtualize_uart=iniGetBool(ini,section,"Virtualize",virtualize_uart);
                    143:        switch(iniGetInteger(ini,section,"ComPort",0)) {
                    144:                case 1: /* COM1 */
                    145:                        uart_irq                =UART_COM1_IRQ;
                    146:                        uart_io_base    =UART_COM1_IO_BASE;
                    147:                        break;
                    148:                case 2: /* COM2 */
                    149:                        uart_irq                =UART_COM2_IRQ;
                    150:                        uart_io_base    =UART_COM2_IO_BASE;
                    151:                        break;
                    152:                case 3: /* COM3 */
                    153:                        uart_irq                =UART_COM3_IRQ;
                    154:                        uart_io_base    =UART_COM3_IO_BASE;
                    155:                        break;
                    156:                case 4: /* COM4 */
                    157:                        uart_irq                =UART_COM4_IRQ;
                    158:                        uart_io_base    =UART_COM4_IO_BASE;
                    159:                        break;
                    160:        }
                    161:        uart_irq=(BYTE)iniGetShortInt(ini,section,"IRQ",uart_irq);
                    162:        uart_io_base=iniGetShortInt(ini,section,"Address",uart_io_base);
                    163: 
                    164:        lprintf(LOG_INFO,"Parsed %s section of %s"
                    165:                ,section
                    166:                ,ini_fname);
                    167: }
                    168: 
                    169: 
                    170: /* Mutex-protected pending interrupt "queue" */
                    171: int pending_interrupts = 0;
                    172: CRITICAL_SECTION interrupt_mutex;
                    173: 
                    174: void set_interrupt_pending(BYTE intr, BOOL assert)
                    175: {
                    176:        EnterCriticalSection(&interrupt_mutex);
                    177:        lprintf(LOG_DEBUG,"%sasserting interrupt %02X (pending: %02X, IER: %02X)"
                    178:                ,assert ? "" : "de-", intr
                    179:                ,pending_interrupts
                    180:                ,uart_ier_reg);
                    181:        if(assert) {
                    182:                if(uart_ier_reg&intr) {                                 /* is interrupt enabled? */
                    183:                        pending_interrupts |= intr;                     /* flag as pending */
                    184:                        SetEvent(interrupt_event);
                    185:                }
                    186:        } else /* de-assert */
                    187:                pending_interrupts &= ~intr;            /* remove as pending */
                    188: 
                    189:        LeaveCriticalSection(&interrupt_mutex);
                    190: }
                    191: 
                    192: #define assert_interrupt(i)            set_interrupt_pending(i, TRUE)
                    193: #define deassert_interrupt(i)  set_interrupt_pending(i, FALSE)
                    194: 
                    195: void _cdecl interrupt_thread(void *arg)
                    196: {
                    197:        while(1) {
                    198:                if(WaitForSingleObject(interrupt_event,INFINITE)!=WAIT_OBJECT_0)
                    199:                        break;
                    200:                if((uart_ier_reg&pending_interrupts) != 0) {
                    201:                        lprintf(LOG_DEBUG,"VDDSimulateInterrupt (pending: %02X) - IER: %02X"
                    202:                                ,pending_interrupts, uart_ier_reg);
                    203:                        VDDSimulateInterrupt(ICA_MASTER, uart_irq, /* count: */1);
                    204:                }
                    205: #if 0
                    206:                /* "Real 16550s should always reassert
                    207:                 *  this interrupt whenever the transmitter is idle and
                    208:                 *  the interrupt is enabled."
                    209:                 */
                    210:                if(pending_interrupts==0 && uart_ier_reg&UART_IER_TX_EMPTY)
                    211:                        pending_interrupts|=UART_IER_TX_EMPTY;
                    212: #endif
                    213:        }
                    214: }
                    215: 
                    216: void _cdecl input_thread(void* arg)
                    217: {
                    218:        char    buf[LINEAR_RX_BUFLEN];
                    219:        int             count;
                    220: 
                    221:        while(1) {
                    222:                count=0;
                    223:                if(!ReadFile(rdslot,buf,sizeof(buf),&count,NULL)) {
                    224:                        if(GetLastError()==ERROR_HANDLE_EOF)    /* closed by VDD_CLOSE */
                    225:                                break;
                    226:                        lprintf(LOG_ERR,"!input_thread: ReadFile Error %d (size=%d)"
                    227:                                ,GetLastError(),count);
                    228:                        continue;
                    229:                }
                    230:                if(count==0) {
                    231:                        lprintf(LOG_ERR,"!input_thread: ReadFile read 0");
                    232:                        continue;
                    233:                }
                    234:                RingBufWrite(&rdbuf,buf,count);
                    235: 
1.1.1.2 ! root      236:                if(virtualize_uart) {
        !           237:                        /* Set the "Data ready" bit in the LSR */
        !           238:                        uart_lsr_reg |= UART_LSR_DATA_READY;
        !           239: 
        !           240:                        assert_interrupt(UART_IER_RX_DATA); /* assert rx data interrupt */
        !           241:                }
1.1       root      242:        }
                    243: }
                    244: 
                    245: unsigned vdd_read(BYTE* p, unsigned count)
                    246: {
                    247:        sem_wait(rdbuf.sem);
                    248:        count=RingBufRead(&rdbuf,p,count);
                    249:        if(count==0)
                    250:                lprintf(LOG_ERR,"!VDD_READ: RingBufRead read 0");
                    251: 
                    252:        return(count);
                    253: }
                    254: 
                    255: unsigned yields=0;
                    256: 
                    257: void yield()
                    258: {
                    259:        yields++;
                    260:        lprintf(LOG_DEBUG,"Yielding (yields=%u)", yields);
                    261:        Sleep(1);
                    262: }
                    263: 
                    264: long double last_yield=0;
                    265: 
                    266: void maybe_yield()
                    267: {
                    268:        long double t;
                    269: 
                    270:        t=xp_timer();
                    271: 
                    272:        if(yield_interval && (t-last_yield)*1000.0 >= yield_interval) {
                    273:                yield();
                    274:                last_yield=t;
                    275:        }
                    276: }
                    277: 
                    278: void reset_yield()
                    279: {
                    280:        last_yield=xp_timer();
                    281: }
                    282: 
                    283: /***********************/
                    284: /* UART Virtualization */
                    285: /***********************/
                    286: 
                    287: static char *chr(uchar ch)
                    288: {
                    289:        static char str[25];
                    290: 
                    291:        if(ch>=' ' && ch<='~')
                    292:                sprintf(str,"'%c' (%02Xh)",ch,ch);
                    293:        else if(ch<' ')
                    294:                sprintf(str,"^%c  (%02Xh)",'@'+ch,ch);
                    295:        else
                    296:                sprintf(str,"%u (%02Xh)",ch,ch);
                    297:        return(str); 
                    298: }
                    299: 
                    300: VOID uart_wrport(WORD port, BYTE data)
                    301: {
                    302:        int reg = port - uart_io_base;
                    303:        int retval;
                    304: 
                    305:        lprintf(LOG_DEBUG,"write of port: %x (%s) <- %02X", port, uart_reg_desc[reg], data);
                    306: 
                    307:        switch(reg) {
                    308:                case UART_BASE:
                    309:                        if(uart_lcr_reg&UART_LCR_DLAB) {
                    310:                                uart_divisor_latch_lsb = data;
                    311:                                lprintf(LOG_DEBUG,"set divisor latch low byte: %02X", data);
                    312:                        } else {
                    313:                                lprintf(LOG_DEBUG,"WRITE DATA: %s", chr(data));
                    314:                                if(!WriteFile(wrslot,&data,sizeof(BYTE),&retval,NULL)) {
                    315:                                        lprintf(LOG_ERR,"!VDD_WRITE: WriteFile Error %d (size=%d)"
                    316:                                                ,GetLastError(),retval);
                    317:                                } else {
                    318:                                        assert_interrupt(UART_IER_TX_EMPTY);
                    319:                                        reset_yield();
                    320:                                }
                    321:                        }
                    322:                        break;
                    323:                case UART_IER:
                    324:                        if(uart_lcr_reg&UART_LCR_DLAB) {
                    325:                                uart_divisor_latch_msb = data;
                    326:                                lprintf(LOG_DEBUG,"set divisor latch high byte: %02X", data);
                    327:                        } else
                    328:                                uart_ier_reg = data;
                    329:                        assert_interrupt(UART_IER_TX_EMPTY);    /* should this be re-asserted for all writes? */
                    330:                        break;
                    331:                case UART_IIR: /* FCR not supported */
                    332:                        break;
                    333:                case UART_LCR:
                    334:                        uart_lcr_reg = data;
                    335:                        break;
                    336:                case UART_MCR:
                    337:                        uart_mcr_reg = data;
                    338:                        if((uart_mcr_reg&UART_MCR_DTR) == 0)    /* Dropping DTR (i.e. "hangup") */
                    339:                                hangup();
                    340:                        break;
                    341:                case UART_SCRATCH:
                    342:                        uart_scratch_reg = data;
                    343:                        break;
                    344:                default:
                    345:                        lprintf(LOG_ERR,"UNSUPPORTED register: %u", reg);
                    346:                        break;
                    347:                        
                    348:        }
                    349: }
                    350: 
                    351: VOID uart_rdport(WORD port, PBYTE data)
                    352: {
                    353:        int reg = port - uart_io_base;
                    354:        DWORD avail;
                    355: 
                    356:        lprintf(LOG_DEBUG,"read of port: %x (%s)", port, uart_reg_desc[reg]);
                    357: 
                    358:        switch(reg) {
                    359:                case UART_BASE:
                    360:                        if(uart_lcr_reg&UART_LCR_DLAB) {
                    361:                                lprintf(LOG_DEBUG,"reading divisor latch LSB");
                    362:                                *data = uart_divisor_latch_lsb;
                    363:                                break;
                    364:                        }
                    365:                        if((avail=RingBufFull(&rdbuf))!=0) {
                    366:                                vdd_read(data,sizeof(BYTE));
                    367:                                lprintf(LOG_DEBUG,"READ DATA: %s", chr(*data));
                    368:                                avail--;
                    369:                                reset_yield();
                    370:                        } else
                    371:                                *data=0;
                    372:                        if(avail==0) {
                    373:                                lprintf(LOG_DEBUG,"No more data");
                    374:                                /* Clear the data ready bit in the LSR */
                    375:                                uart_lsr_reg &= ~UART_LSR_DATA_READY;
                    376: 
                    377:                                /* Clear data ready interrupt identification in IIR */
                    378:                                deassert_interrupt(UART_IER_RX_DATA);
                    379:                        } else  /* re-assert RX data (increment the semaphore) */
                    380:                                assert_interrupt(UART_IER_RX_DATA);
                    381:                        break;
                    382:                case UART_IER:
                    383:                        if(uart_lcr_reg&UART_LCR_DLAB) {
                    384:                                lprintf(LOG_DEBUG,"reading divisor latch MSB");
                    385:                                *data = uart_divisor_latch_msb;
                    386:                        } else
                    387:                                *data = uart_ier_reg;
                    388:                        break;
                    389:                case UART_IIR:
                    390:                        /* Report IIR based on *priority* of pending interrupts */
                    391:                        if(pending_interrupts & UART_IER_LINE_STATUS)
                    392:                                *data = UART_IIR_LINE_STATUS;
                    393:                        else if(pending_interrupts & UART_IER_RX_DATA)
                    394:                                *data = UART_IIR_RX_DATA;
                    395:                        else if(pending_interrupts & UART_IER_TX_EMPTY) {
                    396:                                *data = UART_IIR_TX_EMPTY;
                    397:                                /* "Transmit Holding Register Empty" interrupt */
                    398:                                /*  is reset on read of IIR */
                    399:                                deassert_interrupt(UART_IER_TX_EMPTY);
                    400:                        }
                    401:                        else if(pending_interrupts & UART_IER_MODEM_STATUS)
                    402:                                *data = UART_IIR_MODEM_STATUS;
                    403:                        else
                    404:                                *data = UART_IIR_NONE;
                    405:                        break;
                    406:                case UART_LCR:
                    407:                        *data = uart_lcr_reg;
                    408:                        break;
                    409:                case UART_MCR:
                    410:                        *data = uart_mcr_reg;
                    411:                        break;
                    412:                case UART_LSR:
                    413:                        *data = uart_lsr_reg;
                    414:                        maybe_yield();
                    415:                        /* Clear line status interrupt pending */
                    416:                        deassert_interrupt(UART_IER_LINE_STATUS);
                    417:                        break;
                    418:                case UART_MSR:
                    419:                        if(WaitForSingleObject(hungup_event,0)==WAIT_OBJECT_0)
                    420:                                uart_msr_reg &=~ UART_MSR_DCD;
                    421:                        else
                    422:                                uart_msr_reg |= UART_MSR_DCD;
                    423:                        *data = uart_msr_reg;
                    424:                        maybe_yield();
                    425:                        /* Clear modem status interrupt pending */
                    426:                        deassert_interrupt(UART_IER_MODEM_STATUS);
                    427:                        break;
                    428:                case UART_SCRATCH:
                    429:                        *data = uart_scratch_reg;
                    430:                        break;
                    431:                default:
                    432:                        lprintf(LOG_ERR,"UNSUPPORTED register: %u", reg);
                    433:                        break;
                    434:        }
                    435: 
                    436:        if(reg!=UART_BASE)
                    437:                lprintf(LOG_DEBUG, "returning 0x%02X", *data);
                    438: }
                    439: 
                    440: /* VDD DOS Interface (mainly for FOSSIL driver in dosxtrn.exe) */
                    441: 
                    442: __declspec(dllexport) void __cdecl VDDDispatch(void) 
                    443: {
                    444:        char                    str[512];
                    445:        DWORD                   count;
                    446:        DWORD                   msgs;
                    447:        int                             retval;
                    448:        int                             node_num;
                    449:        BYTE*                   p;
                    450:        vdd_status_t*   status;
                    451:        static  DWORD   writes;
                    452:        static  DWORD   bytes_written;
                    453:        static  DWORD   reads;
                    454:        static  DWORD   bytes_read;
                    455:        static  DWORD   inbuf_poll;
                    456:        static  DWORD   online_poll;
                    457:        static  DWORD   status_poll;
                    458:        static  DWORD   vdd_yields;
                    459:        static  DWORD   vdd_calls;
                    460:        VDD_IO_HANDLERS  IOHandlers = { NULL };
                    461:        static VDD_IO_PORTRANGE PortRange;
                    462: 
                    463:        retval=0;
                    464:        node_num=getBH();
                    465: 
                    466:        lprintf(LOG_DEBUG,"VDD_OP: (handle=%d) %d (arg=%X)", getAX(),getBL(),getCX());
                    467:        vdd_calls++;
                    468: 
                    469:        switch(getBL()) {
                    470: 
                    471:                case VDD_OPEN:
                    472: 
1.1.1.2 ! root      473:                        sscanf("$Revision: 1.39 $", "%*s %s", revision);
1.1       root      474: 
                    475:                        lprintf(LOG_INFO,"Synchronet Virtual Device Driver, rev %s %s %s"
                    476:                                ,revision, __DATE__, __TIME__);
                    477: #if 0
                    478:                        sprintf(str,"sbbsexec%d.log",node_num);
                    479:                        fp=fopen(str,"wb");
                    480: #endif
                    481: 
                    482:                        sprintf(str,"\\\\.\\mailslot\\sbbsexec\\wr%d",node_num);
                    483:                        rdslot=CreateMailslot(str
                    484:                                ,LINEAR_RX_BUFLEN               /* Max message size (0=any) */
                    485:                                ,MAILSLOT_WAIT_FOREVER  /* Read timeout */
                    486:                                ,NULL);
                    487:                        if(rdslot==INVALID_HANDLE_VALUE) {
                    488:                                lprintf(LOG_ERR,"!VDD_OPEN: Error %d opening %s"
                    489:                                        ,GetLastError(),str);
                    490:                                retval=1;
                    491:                                break;
                    492:                        }
                    493: 
                    494:                        sprintf(str,"\\\\.\\mailslot\\sbbsexec\\rd%d",node_num);
                    495:                        wrslot=CreateFile(str
                    496:                                ,GENERIC_WRITE
                    497:                                ,FILE_SHARE_READ
                    498:                                ,NULL
                    499:                                ,OPEN_EXISTING
                    500:                                ,FILE_ATTRIBUTE_NORMAL
                    501:                                ,(HANDLE) NULL);
                    502:                        if(wrslot==INVALID_HANDLE_VALUE) {
                    503:                                lprintf(LOG_ERR,"!VDD_OPEN: Error %d opening %s"
                    504:                                        ,GetLastError(),str);
                    505:                                retval=2;
                    506:                                break;
                    507:                        }
                    508: 
                    509:                        if(RingBufInit(&rdbuf, RINGBUF_SIZE_IN)!=0) {
                    510:                                retval=3;
                    511:                                break;
                    512:                        }
                    513: 
                    514:                        sprintf(str,"sbbsexec_hungup%d",node_num);
                    515:                        hungup_event=OpenEvent(
                    516:                                EVENT_ALL_ACCESS,       /* access flag  */
                    517:                                FALSE,                          /* inherit flag  */
                    518:                                str);                           /* pointer to event-object name  */
                    519:                        if(hungup_event==NULL) {
                    520:                                lprintf(LOG_ERR,"!VDD_OPEN: Error %d opening %s"
                    521:                                        ,GetLastError(),str);
                    522:                                retval=4;
                    523:                                break;
                    524:                        }
                    525: 
                    526:                        sprintf(str,"sbbsexec_hangup%d",node_num);
                    527:                        hangup_event=OpenEvent(
                    528:                                EVENT_ALL_ACCESS,       /* access flag  */
                    529:                                FALSE,                          /* inherit flag  */
                    530:                                str);                           /* pointer to event-object name  */
                    531:                        if(hangup_event==NULL) {
                    532:                                lprintf(LOG_WARNING,"!VDD_OPEN: Error %d opening %s"
                    533:                                        ,GetLastError(),str);
                    534:                        }
                    535: 
                    536:                        status_poll=0;
                    537:                        inbuf_poll=0;
                    538:                        online_poll=0;
                    539:                        yields=0;
                    540: 
                    541:                        lprintf(LOG_INFO,"Yield interval: %f milliseconds", yield_interval);
                    542: 
                    543:                        if(virtualize_uart) {
                    544:                                lprintf(LOG_INFO,"Virtualizing UART (0x%x, IRQ %u)"
                    545:                                        ,uart_io_base, uart_irq);
                    546: 
                    547:                                IOHandlers.inb_handler = uart_rdport;
                    548:                                IOHandlers.outb_handler = uart_wrport;
                    549:                                PortRange.First=uart_io_base;
                    550:                                PortRange.Last=uart_io_base + UART_IO_RANGE;
                    551: 
                    552:                                VDDInstallIOHook((HANDLE)getAX(), 1, &PortRange, &IOHandlers);
                    553: 
                    554:                                interrupt_event=CreateEvent(NULL,FALSE,FALSE,NULL);
                    555:                                InitializeCriticalSection(&interrupt_mutex);
                    556: 
                    557:                                _beginthread(interrupt_thread, 0, NULL);
                    558:                        }
                    559: 
                    560:                        lprintf(LOG_DEBUG,"VDD_OPEN: Opened successfully");
                    561: 
                    562:                        _beginthread(input_thread, 0, NULL);
                    563: 
                    564:                        retval=0;
                    565:                        break;
                    566: 
                    567:                case VDD_CLOSE:
                    568:                        lprintf(LOG_INFO,"VDD_CLOSE: rdbuf=%u "
                    569:                                "status_poll=%u inbuf_poll=%u online_poll=%u yields=%u vdd_yields=%u vdd_calls=%u"
                    570:                                ,RingBufFull(&rdbuf),status_poll,inbuf_poll,online_poll
                    571:                                ,yields,vdd_yields,vdd_calls);
                    572:                        lprintf(LOG_INFO,"           read=%u bytes (in %u calls)",bytes_read,reads);
                    573:                        lprintf(LOG_INFO,"           wrote=%u bytes (in %u calls)",bytes_written,writes);
                    574: 
                    575:                        if(virtualize_uart) {
                    576:                                lprintf(LOG_INFO,"Uninstalling Virtualizaed UART IO Hook");
                    577:                                VDDDeInstallIOHook((HANDLE)getAX(), 1, &PortRange);
                    578:                        }
                    579: 
                    580:                        CloseHandle(rdslot);
                    581:                        CloseHandle(wrslot);
                    582:                        if(hungup_event!=NULL)
                    583:                                CloseHandle(hungup_event);
                    584:                        if(hangup_event!=NULL)
                    585:                                CloseHandle(hangup_event);
                    586: 
                    587: #if 0  /* This isn't strictly necessary... 
                    588:                   and possibly the cause of a NULL dereference in the input_thread */
                    589:                        RingBufDispose(&rdbuf);
                    590: #endif
                    591:                        status_poll=0;
                    592:                        retval=0;
                    593: 
                    594:                        break;
                    595: 
                    596:                case VDD_READ:
                    597:                        count = getCX();
                    598:                        if(count != 1)
                    599:                                lprintf(LOG_DEBUG,"VDD_READ of %d",count);
                    600:                        p = (BYTE*) GetVDMPointer((ULONG)((getES() << 16)|getDI())
                    601:                                ,count,FALSE); 
                    602:                        retval=vdd_read(p, count);
                    603:                        reads++;
                    604:                        bytes_read+=retval;
                    605:                        reset_yield();
                    606:                        break;
                    607: 
                    608:                case VDD_PEEK:
                    609:                        count = getCX();
                    610:                        if(count != 1)
                    611:                                lprintf(LOG_DEBUG,"VDD_PEEK of %d",count);
                    612: 
                    613:                        p = (BYTE*) GetVDMPointer((ULONG)((getES() << 16)|getDI())
                    614:                                ,count,FALSE); 
                    615:                        retval=RingBufPeek(&rdbuf,p,count);
                    616:                        reset_yield();
                    617:                        break;
                    618: 
                    619:                case VDD_WRITE:
                    620:                        count = getCX();
                    621:                        if(count != 1)
                    622:                                lprintf(LOG_DEBUG,"VDD_WRITE of %d",count);
                    623:                        p = (BYTE*) GetVDMPointer((ULONG)((getES() << 16)|getDI())
                    624:                                ,count,FALSE); 
                    625:                        if(!WriteFile(wrslot,p,count,&retval,NULL)) {
                    626:                                lprintf(LOG_ERR,"!VDD_WRITE: WriteFile Error %d (size=%d)"
                    627:                                        ,GetLastError(),retval);
                    628:                                retval=0;
                    629:                        } else {
                    630:                                writes++;
                    631:                                bytes_written+=retval;
                    632:                                reset_yield();
                    633:                        }
                    634:                        break;
                    635: 
                    636:                case VDD_STATUS:
                    637: 
                    638:                        status_poll++;
                    639:                        count = getCX();
                    640:                        if(count != sizeof(vdd_status_t)) {
                    641:                                lprintf(LOG_DEBUG,"!VDD_STATUS: wrong size (%d!=%d)",count,sizeof(vdd_status_t));
                    642:                                retval=sizeof(vdd_status_t);
                    643:                                break;
                    644:                        }
                    645:                        status = (vdd_status_t*) GetVDMPointer((ULONG)((getES() << 16)|getDI())
                    646:                                ,count,FALSE); 
                    647: 
                    648:                        status->inbuf_full=RingBufFull(&rdbuf);
                    649: 
                    650:                        /* OUTBUF FULL/SIZE */
                    651:                        if(!GetMailslotInfo(
                    652:                                wrslot,                                 /* mailslot handle  */
                    653:                                &status->outbuf_size,   /* address of maximum message size  */
                    654:                                &status->outbuf_full,   /* address of size of next message  */
                    655:                                &msgs,                                  /* address of number of messages  */
                    656:                                NULL                                    /* address of read time-out  */
                    657:                                )) {
                    658:                                status->outbuf_full=0;
                    659:                                status->outbuf_size=DEFAULT_MAX_MSG_SIZE;
                    660:                        }
                    661:                        if(status->outbuf_full==MAILSLOT_NO_MESSAGE)
                    662:                                status->outbuf_full=0;
                    663:                        status->outbuf_full*=msgs;
                    664:                        
                    665:                        /* ONLINE */
                    666:                        if(WaitForSingleObject(hungup_event,0)==WAIT_OBJECT_0)
                    667:                                status->online=0;
                    668:                        else
                    669:                                status->online=1;
                    670: 
                    671:                        retval=0;       /* success */
                    672:                        break;
                    673: 
                    674:                case VDD_INBUF_PURGE:
                    675:                        RingBufReInit(&rdbuf);
                    676:                        retval=0;
                    677:                        break;
                    678: 
                    679:                case VDD_OUTBUF_PURGE:
                    680:                        lprintf(LOG_WARNING,"!VDD_OUTBUF_PURGE: NOT IMPLEMENTED");
                    681:                        retval=0;
                    682:                        break;
                    683: 
                    684:                case VDD_INBUF_FULL:
                    685:                        retval=RingBufFull(&rdbuf);
                    686:                        inbuf_poll++;
                    687:                        break;
                    688: 
                    689:                case VDD_INBUF_SIZE:
                    690:                        retval=RINGBUF_SIZE_IN;
                    691:                        break;
                    692: 
                    693:                case VDD_OUTBUF_FULL:
                    694:                        if(!GetMailslotInfo(
                    695:                                wrslot,         /* mailslot handle  */
                    696:                                NULL,           /* address of maximum message size  */
                    697:                                &retval,        /* address of size of next message  */
                    698:                                &msgs,          /* address of number of messages  */
                    699:                                NULL            /* address of read time-out  */
                    700:                                ))
                    701:                                retval=0;
                    702:                        if(retval==MAILSLOT_NO_MESSAGE)
                    703:                                retval=0;
                    704:                        retval*=msgs;
                    705:                        break;
                    706: 
                    707:                case VDD_OUTBUF_SIZE:
                    708:                        if(!GetMailslotInfo(
                    709:                                wrslot,         /* mailslot handle  */
                    710:                                &retval,        /* address of maximum message size  */
                    711:                                NULL,           /* address of size of next message  */
                    712:                                NULL,           /* address of number of messages  */
                    713:                                NULL            /* address of read time-out  */
                    714:                                )) 
                    715:                                retval=DEFAULT_MAX_MSG_SIZE;
                    716:                        break;
                    717: 
                    718:                case VDD_ONLINE:
                    719:                        if(WaitForSingleObject(hungup_event,0)==WAIT_OBJECT_0)
                    720:                                retval=0;
                    721:                        else
                    722:                                retval=1;
                    723:                        online_poll++;
                    724:                        break;
                    725: 
                    726:                case VDD_YIELD:                 /* forced yield */
                    727:                        vdd_yields++;
                    728:                        yield();
                    729:                        break;
                    730: 
                    731:                case VDD_MAYBE_YIELD:   /* yield if YieldInterval is enabled and expired */
                    732:                        maybe_yield();
                    733:                        break;
                    734: 
                    735:                case VDD_LOAD_INI_FILE: /* Load and parse settings file */
                    736:                        {
                    737:                                FILE*   fp;
                    738:                                char    cwd[MAX_PATH+1];
                    739: 
                    740:                                /* Load exec/sbbsexec.ini first (setting default values) */
                    741:                                count = getCX();
                    742:                                p = (BYTE*)GetVDMPointer((ULONG)((getES() << 16)|getDI())
                    743:                                        ,count,FALSE); 
                    744:                                iniFileName(ini_fname, sizeof(ini_fname), p, INI_FILENAME);
                    745:                                if((fp=fopen(ini_fname,"r"))!=NULL) {
                    746:                                        ini=iniReadFile(fp);
                    747:                                        fclose(fp);
                    748:                                        parse_ini(ROOT_SECTION);
                    749:                                }
                    750: 
                    751:                                /* Load cwd/sbbsexec.ini second (over-riding default values) */
                    752:                                GetCurrentDirectory(sizeof(cwd),cwd);
                    753:                                iniFileName(ini_fname, sizeof(ini_fname), cwd, INI_FILENAME);
                    754:                                if((fp=fopen(ini_fname,"r"))!=NULL) {
                    755:                                        ini=iniReadFile(fp);
                    756:                                        fclose(fp);
                    757:                                        parse_ini(ROOT_SECTION);
                    758:                                }
                    759:                        }
                    760:                        break;
                    761: 
                    762:                case VDD_LOAD_INI_SECTION:      /* Parse (program-specific) sub-section of settings file */
                    763:                        count = getCX();
                    764:                        p = (BYTE*)GetVDMPointer((ULONG)((getES() << 16)|getDI())
                    765:                                ,count,FALSE); 
                    766:                        parse_ini(p);
                    767:                        break;
                    768: 
                    769:                case VDD_DEBUG_OUTPUT:  /* Send string to debug output */
                    770:                        count = getCX();
                    771:                        p = (BYTE*)GetVDMPointer((ULONG)((getES() << 16)|getDI())
                    772:                                ,count,FALSE); 
                    773:                        lputs(LOG_INFO, p);
                    774:                        break;
                    775: 
                    776:                case VDD_HANGUP:
                    777:                        hangup();
                    778:                        break;
                    779: 
                    780:                default:
                    781:                        lprintf(LOG_ERR,"!UNKNOWN VDD_OP: %d",getBL());
                    782:                        break;
                    783:        }
                    784:        setAX((WORD)retval);
                    785: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.