static void getChars(void *user) { Uns8 c; while(1) { double d = DEFAULT_RX_DELAY; // // keep getting chars till we fill the fifo // bhmWaitDelay(d); while (!Rx.full) { Int32 bytes = readInput(&c, 1); if (bytes > 0) { // // We have got a char, so insert to buffer // fifoPush(&Rx, c); eval_interrupts(); } bhmWaitDelay(d); } if (!Rx.empty) { eval_interrupts(); } } }
void CSerial::receive(const char* data, int dsize) { while(dsize) { state.rcvBuffer[state.rcvW++] = *data; if(state.rcvW == FIFO_SIZE) state.rcvW = 0; data++; dsize--; eval_interrupts(); } }
static void putChars() { Bool ok; Uns8 c; // // keep sending characters whilst the TX fifo is not empty // if (!Tx.empty) { ok = fifoPop(&Tx, &c); if (ok) { writeOutput(&c, 1); } } if (Tx.empty) { // // Generate an interrupt if enabled // eval_interrupts(); } else { if (BHM_DIAG_HIGH) bhmMessage("F", PREFIX, "Tx.empty is false !!!"); } }
void CSerial::execute() { fd_set readset; unsigned char buffer[FIFO_SIZE + 1]; unsigned char cbuffer[FIFO_SIZE + 1]; // cooked buffer unsigned char* b; // cooked buffer unsigned char *c; ssize_t size; struct timeval tv; state.serial_cycles++; if(state.serial_cycles >= RECV_TICKS) { FD_ZERO(&readset); FD_SET(connectSocket, &readset); tv.tv_sec = 0; tv.tv_usec = 0; if(select(connectSocket + 1, &readset, NULL, NULL, &tv) > 0) { #if defined(_WIN32) || defined(__VMS) // Windows Sockets has no direct equivalent of BSD's read size = recv(connectSocket, (char*) buffer, FIFO_SIZE, 0); #else size = read(connectSocket, &buffer, FIFO_SIZE); #endif extern int got_sigint; if(size == 0 && !got_sigint) { printf("%%SRL-W-DISCONNECT: Write socket closed on other end for serial port %d.\n", state.iNumber); printf("-SRL-I-WAITFOR: Waiting for a new connection on port %d.\n", listenPort); WaitForConnection(); return; } b = buffer; c = cbuffer; while((ssize_t) (b - buffer) < size) { if(*b == 0x0a) { b++; // skip LF continue; } if(*b == IAC) { if(*(b + 1) == IAC) { // escaped IAC. b++; } else if(*(b + 1) >= WILL) { // will/won't/do/don't b += 3; // skip this byte, and following two. (telnet escape) continue; } else if(*(b + 1) == SB) { // skip until IAC SE b += 2; // now we're at start of subnegotiation. while(*b != IAC && *(b + 1) != SE) b++; b += 2; continue; } else if(*(b + 1) == BREAK) { // break (== halt button?) b += 2; breakHit = true; } else if(*(b + 1) == AYT) { // are you there? } else { // misc single byte command. b += 2; continue; } } *c = *b; c++; b++; } this->receive((const char*) &cbuffer, (c - cbuffer)); } state.serial_cycles = 0; } eval_interrupts(); }
void CSerial::WriteMem(int index, u64 address, int dsize, u64 data) { u8 d; d = (u8) data; switch(address) { case 0: if(state.bLCR & 0x80) // divisor latch access bit set { // LSB of divisor latch state.bBRB_LSB = d; } else { // Transmit Hold Register write((const char*) &d, 1); TRC_DEV4("Write character %02x (%c) on serial port %d\n", d, printable(d), state.iNumber); #if defined(DEBUG_SERIAL) printf("Write character %02x (%c) on serial port %d\n", d, printable(d), state.iNumber); #endif eval_interrupts(); } break; case 1: if(state.bLCR & 0x80) // divisor latch access bit set { // MSB of divisor latch state.bBRB_MSB = d; } else { // Interrupt Enable Register state.bIER = d; eval_interrupts(); } break; case 2: state.bFCR = d; break; case 3: state.bLCR = d; break; case 4: state.bMCR = d; break; default: state.bSPR = d; } }