Forums before death by AOL, social media and spammers... "We can't have nice things"
|    comp.lang.asm.x86    |    Ahh, the lost art of x86 assembly    |    4,675 messages    |
[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]
|    Message 4,582 of 4,675    |
|    Paul Edwards to All    |
|    Re: serial port    |
|    15 Apr 23 07:24:27    |
   
   From: mutazilah@nospicedham.gmail.com   
      
   I finally realized that since I'm getting an interrupt from   
   the TBE enable (for unknown reasons), then if I moved   
   the disable (cli) before that, then by the time I had   
   outputted a byte, the interrupt would still be pending   
   and even if I didn't get one for the outputted byte, it   
   was enough to get one for the TBE call.   
      
   And now it is working, with the simple design.   
      
   I will look into refinements now that the basics are working.   
      
   static void writecomm(int port, int ch)   
   {   
    UART uart;   
    unsigned long old1;   
    unsigned long old2;   
    unsigned long intdesc1;   
    unsigned long intdesc2;   
    unsigned long intaddr;   
    int xch;   
    int intno = 4;   
    int a8259 = 0x20;   
    int imr = 0x21;   
    int id;   
      
    uartInit(&uart);   
    uartAddress(&uart, 0x3f8);   
    PREADB(a8259); /* we don't use the result of this */   
    uartDisableInts(&uart);   
    /* IRQs 0-7 are at 0xb0 instead of 8 now */   
    /* we are using IRQ 4 for COM1 */   
    old1 = G_intloc[(intno + 0xb0) * 2];   
    old2 = G_intloc[(intno + 0xb0) * 2 + 1];   
    intaddr = (unsigned long)hltinthit;   
      
    /* we are interested in this interrupt */   
    xch = PREADB(imr);   
    xch &= ~(1 << (intno % 8));   
    PWRITEB(imr, xch);   
      
    disable();   
    uartEnableGPO2(&uart);   
      
    uartEnableTBE(&uart);   
    /* uartEnableModem(&uart); */   
    /* uartRaiseDTR(&uart); */   
    /* uartRaiseRTS(&uart); */   
    /* uartCTS(&uart); */   
    intdesc1 = (0x8 << 16) | (intaddr & 0xffff);   
    intdesc2 = (intaddr & 0xffff0000)   
    | (1 << 15)   
    | (0 << 13)   
    | (0x0e << 8);   
    G_intloc[(intno + 0xb0) * 2] = intdesc1;   
    G_intloc[(intno + 0xb0) * 2 + 1] = intdesc2;   
    uartTxCh(&uart, ch);   
    hltintgo();   
    enable();   
    do   
    {   
    id = uartGetIntType(&uart);   
    } while (id != UART_NO_PENDING);   
    PWRITEB(0x20, 0x20);   
    uartDisableInts(&uart);   
    uartDisableGPO2(&uart);   
      
    xch = PREADB(imr);   
    xch |= (1 << (intno % 8));   
    PWRITEB(imr, xch);   
      
    uartReset(&uart);   
    uartTerm(&uart);   
      
    disable();   
    G_intloc[(intno + 0xb0) * 2] = old1;   
    G_intloc[(intno + 0xb0) * 2 + 1] = old2;   
    enable();   
   }   
      
      
   / enable interrupts and then halt until interrupt hit   
   _hltintgo:   
   hloop:   
   / I believe hlt will be interrupted by other interrupts, like   
   / the timer interrupt, so we need to do it in a loop   
    sti   
    hlt   
    cli   
    jmp hloop   
   _hltinthit:   
   / remove return address, segment and flags from the stack as we   
   / do not intend to return to the jmp following the hlt instruction   
   / that was likely interrupted   
    add $12, %esp   
   / note that interrupts will be disabled again (I think) by virtue   
   / of the fact that an interrupt occurred. The caller would have   
   / disabled interrupts already, so we are returning to the same   
   / disabled state.   
    ret   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   
|
[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]
(c) 1994, bbs@darkrealms.ca