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,588 of 4,675    |
|    Paul Edwards to Paul Edwards    |
|    Re: serial port    |
|    16 Apr 23 01:37:04    |
   
   From: mutazilah@nospicedham.gmail.com   
      
   On Sunday, April 16, 2023 at 5:21:57 AM UTC+8, Paul Edwards wrote:   
      
   > And now I realize there may be a problem with the    
   > current code.   
      
   I have now managed to test on real hardware.   
      
   I was surprised to see that INT 14H to initialize the   
   port is apparently working, as I was able to transmit   
   characters.   
      
   I was expecting to have to update PDOS to replace   
   the INT 14H initialization functionality.   
      
   However, when I copied a file to com1, most characters   
   were dropped.   
      
   So that bit of the theory was correct.   
      
   If I just copied a 1-byte file to com1, then copied another   
   1-byte file to com1, the characters both went through.   
      
   I then tried moving the disable() below the TBE enable in   
   the hope that the old (default) interrupt handler would   
   take care of that, and I would get my character. But that   
   would have created a timing issue even if it had worked.   
   Instead there was no change in behavior.   
      
   And then I figured that what I needed was consistency,   
   and that there should be two interrupts.   
      
   So I did a second call to hltintgo.   
      
   And this time it hung.   
      
   Fortunately I realized I need to repeat the read of the uart   
   and do the write to 0x20 and it worked on my real hardware.   
      
   And the same code worked on Bochs too.   
      
   So working code now below.   
      
   Thanks everyone for your thoughts.   
      
   BFN. Paul.   
      
      
   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);   
      
    uartEnableGPO2(&uart);   
      
    /* uartEnableModem(&uart); */   
    /* uartRaiseDTR(&uart); */   
    /* uartRaiseRTS(&uart); */   
    /* uartCTS(&uart); */   
    intdesc1 = (0x8 << 16) | (intaddr & 0xffff);   
    intdesc2 = (intaddr & 0xffff0000)   
    | (1 << 15)   
    | (0 << 13)   
    | (0x0e << 8);   
    disable();   
    G_intloc[(intno + 0xb0) * 2] = intdesc1;   
    G_intloc[(intno + 0xb0) * 2 + 1] = intdesc2;   
    /* for some reason just enabling the interrupt causes   
    an interrupt. But transmitting a character doesn't   
    necessarily generate an interrupt for some reason.   
    But by disabling the interrupts while both enabling   
    TBE and sending a character, we 'guarantee' that we   
    will receive an interrupt from at least one of those   
    so that the hlt instruction will be interrupted. */   
    uartEnableTBE(&uart);   
    hltintgo();   
    enable();   
    do   
    {   
    id = uartGetIntType(&uart);   
    } while (id != UART_NO_PENDING);   
    PWRITEB(0x20, 0x20);   
    disable();   
    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();   
   }   
      
   --- 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