static void pci_uart_drain(int fd, enum ev_type ev, void *arg) { struct pci_uart_softc *sc; int ch; sc = arg; assert(fd == STDIN_FILENO); assert(ev == EVF_READ); /* * This routine is called in the context of the mevent thread * to take out the softc lock to protect against concurrent * access from a vCPU i/o exit */ pthread_mutex_lock(&sc->mtx); if ((sc->mcr & MCR_LOOPBACK) != 0) { (void) ttyread(); } else { while (fifo_available(&sc->rxfifo) && ((ch = ttyread()) != -1)) { fifo_putchar(&sc->rxfifo, ch); } pci_uart_toggle_intr(sc); } pthread_mutex_unlock(&sc->mtx); }
int main(void) { /* Init Clock */ PLLFBD = 126; CLKDIVbits.PLLPOST = 0; CLKDIVbits.PLLPRE = 1; __builtin_write_OSCCONH(0x03); __builtin_write_OSCCONL(OSCCON | 0x01); while (OSCCONbits.COSC != 3) ; while (OSCCONbits.LOCK != 1) ; tx_fifo.head=0; tx_fifo.tail=0; rx_fifo.head=0; rx_fifo.tail=0; /* Init PORT I/O */ init_io(); init_pps(); init_uart(); init_can(); while (true) { counter++; counter_can++; fifo_putchar(&tx_fifo); if (can_test_receive()) print_rom_fifo("received CAN packet\r\n", &tx_fifo); if (counter_can == 30000) { can_test_send(); counter_can = 0; } if (counter == 50000) { print_rom_fifo("Hello dsPIC33 !\r\n", &tx_fifo); //print_debug_fifo(&tx_fifo); // ClrWdt(); counter = 0; } __delay_us(10); __builtin_btg((unsigned int *)&LATA, 0); __builtin_btg((unsigned int *)&LATA, 0); __builtin_btg((unsigned int *)&LATA, 0); __builtin_btg((unsigned int *)&LATA, 0); __builtin_btg((unsigned int *)&LATA, 0); __builtin_btg((unsigned int *)&LATA, 0); __builtin_btg((unsigned int *)&LATA, 0); __builtin_btg((unsigned int *)&LATA, 0); } }
static void pci_uart_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int baridx, uint64_t offset, int size, uint64_t value) { struct pci_uart_softc *sc; int fifosz; uint8_t msr; sc = pi->pi_arg; assert(baridx == 0); assert(size == 1); /* Open terminal */ if (!sc->opened && sc->stdio) { pci_uart_opentty(sc); sc->opened = 1; } pthread_mutex_lock(&sc->mtx); /* * Take care of the special case DLAB accesses first */ if ((sc->lcr & LCR_DLAB) != 0) { if (offset == REG_DLL) { sc->dll = value; goto done; } if (offset == REG_DLH) { sc->dlh = value; goto done; } } switch (offset) { case REG_DATA: if (sc->mcr & MCR_LOOPBACK) { if (fifo_putchar(&sc->rxfifo, value) != 0) sc->lsr |= LSR_OE; } else if (sc->stdio) { ttywrite(value); } /* else drop on floor */ sc->thre_int_pending = true; break; case REG_IER: /* * Apply mask so that bits 4-7 are 0 * Also enables bits 0-3 only if they're 1 */ sc->ier = value & 0x0F; break; case REG_FCR: /* * When moving from FIFO and 16450 mode and vice versa, * the FIFO contents are reset. */ if ((sc->fcr & FCR_ENABLE) ^ (value & FCR_ENABLE)) { fifosz = (value & FCR_ENABLE) ? FIFOSZ : 1; fifo_reset(&sc->rxfifo, fifosz); } /* * The FCR_ENABLE bit must be '1' for the programming * of other FCR bits to be effective. */ if ((value & FCR_ENABLE) == 0) { sc->fcr = 0; } else { if ((value & FCR_RCV_RST) != 0) fifo_reset(&sc->rxfifo, FIFOSZ); sc->fcr = value & (FCR_ENABLE | FCR_DMA | FCR_RX_MASK); } break; case REG_LCR: sc->lcr = value; break; case REG_MCR: /* Apply mask so that bits 5-7 are 0 */ sc->mcr = value & 0x1F; msr = 0; if (sc->mcr & MCR_LOOPBACK) { /* * In the loopback mode certain bits from the * MCR are reflected back into MSR */ if (sc->mcr & MCR_RTS) msr |= MSR_CTS; if (sc->mcr & MCR_DTR) msr |= MSR_DSR; if (sc->mcr & MCR_OUT1) msr |= MSR_RI; if (sc->mcr & MCR_OUT2) msr |= MSR_DCD; } /* * Detect if there has been any change between the * previous and the new value of MSR. If there is * then assert the appropriate MSR delta bit. */ if ((msr & MSR_CTS) ^ (sc->msr & MSR_CTS)) sc->msr |= MSR_DCTS; if ((msr & MSR_DSR) ^ (sc->msr & MSR_DSR)) sc->msr |= MSR_DDSR; if ((msr & MSR_DCD) ^ (sc->msr & MSR_DCD)) sc->msr |= MSR_DDCD; if ((sc->msr & MSR_RI) != 0 && (msr & MSR_RI) == 0) sc->msr |= MSR_TERI; /* * Update the value of MSR while retaining the delta * bits. */ sc->msr &= MSR_DELTA_MASK; sc->msr |= msr; break; case REG_LSR: /* * Line status register is not meant to be written to * during normal operation. */ break; case REG_MSR: /* * As far as I can tell MSR is a read-only register. */ break; case REG_SCR: sc->scr = value; break; default: break; } done: pci_uart_toggle_intr(sc); pthread_mutex_unlock(&sc->mtx); }