void BSP_uart_termios_isr_com2() { unsigned char buf[40]; int off, ret, vect; off = 0; for(;;) { vect = uread(BSP_UART_COM2, IIR) & 0xf; switch(vect) { case NO_MORE_INTR : /* No more interrupts */ if(off != 0) { /* Update rx buffer */ rtems_termios_enqueue_raw_characters(termios_ttyp_com2, (char *)buf, off); } return; case TRANSMITTER_HODING_REGISTER_EMPTY : /* * TX holding empty: we have to disable these interrupts * if there is nothing more to send. */ ret = rtems_termios_dequeue_characters(termios_ttyp_com2, 1); /* If nothing else to send disable interrupts */ if(ret == 0) { uwrite(BSP_UART_COM2, IER, (RECEIVE_ENABLE | RECEIVER_LINE_ST_ENABLE ) ); termios_tx_active_com2 = 0; } break; case RECEIVER_DATA_AVAIL : case CHARACTER_TIMEOUT_INDICATION: /* RX data ready */ assert(off < sizeof(buf)); buf[off++] = uread(BSP_UART_COM2, RBR); break; case RECEIVER_ERROR: /* RX error: eat character */ uartError(BSP_UART_COM2); break; default: /* Should not happen */ assert(0); return; } } }
inline void uartError(int uart) { unsigned char uartStatus; uartStatus = uread(uart, LSR); uartStatus = uread(uart, RBR); }
static void uartError(int uart, void *termiosPrivate) { unsigned char uartStatus, dummy; BSP_UartBreakCbProc h; uartStatus = uread(uart, LSR); dummy = uread(uart, RBR); #ifdef UARTDEBUG if (uartStatus & OE) printk("********* Over run Error **********\n"); if (uartStatus & PE) printk("********* Parity Error **********\n"); if (uartStatus & FE) printk("********* Framing Error **********\n"); if (uartStatus & BI) { printk("********* BREAK INTERRUPT *********\n"); #endif if ((h=uart_data[uart].breakCallback.handler)) { h(uart, (dummy<<8)|uartStatus, termiosPrivate, uart_data[uart].breakCallback.private); }
/* * Uart initialization, it is hardcoded to 8 bit, no parity, * one stop bit, FIFO, things to be changed * are baud rate and nad hw flow control, * and longest rx fifo setting */ void BSP_uart_init(int uart, int baud, int hwFlow) { unsigned char tmp; /* Sanity check */ assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2); switch(baud) { case 50: case 75: case 110: case 134: case 300: case 600: case 1200: case 2400: case 9600: case 19200: case 38400: case 57600: case 115200: break; default: assert(0); return; } /* Enable UART block */ uwrite(uart, CNT, UART_ENABLE | PAD_ENABLE); /* Set DLAB bit to 1 */ uwrite(uart, LCR, DLAB); /* Set baud rate */ uwrite(uart, DLL, (BSPBaseBaud/baud) & 0xff); uwrite(uart, DLM, ((BSPBaseBaud/baud) >> 8) & 0xff); /* 8-bit, no parity , 1 stop */ uwrite(uart, LCR, CHR_8_BITS); /* Enable FIFO */ uwrite(uart, FCR, FIFO_EN | XMIT_RESET | RCV_RESET | RECEIVE_FIFO_TRIGGER12); /* Disable Interrupts */ uwrite(uart, IER, 0); /* Read status to clear them */ tmp = uread(uart, LSR); tmp = uread(uart, RBR); /* Remember state */ uart_data[uart].hwFlow = hwFlow; uart_data[uart].baud = baud; return; }
int fasttrap_tracepoint_remove(proc_t *p, fasttrap_tracepoint_t *tp) { /* The thumb patch is a 2 byte instruction regardless of the size of the original instruction */ uint32_t instr; int size = tp->ftt_thumb ? 2 : 4; /* * Distinguish between read or write failures and a changed * instruction. */ if (uread(p, &instr, size, tp->ftt_pc) != 0) goto end; if (tp->ftt_thumb) { if (*((uint16_t*) &instr) != FASTTRAP_THUMB_INSTR) goto end; } else { if (instr != FASTTRAP_ARM_INSTR) goto end; } if (uwrite(p, &tp->ftt_instr, size, tp->ftt_pc) != 0) return (-1); end: tp->ftt_installed = 0; return (0); }
static int common_getc(int fd, int timo) { struct linux_timeval tv; fd_set fdset; int nfds, n; char c; for (; timo < 0 || timo > 0; --timo) { tv.tv_sec = 1; tv.tv_usec = 0; FD_ZERO(&fdset); nfds = 1; FD_SET(fd, &fdset); n = uselect(nfds, &fdset, NULL, NULL, &tv); if (n > 0) break; } if (timo > 0) { for (fd = 0; fd < nfds; fd++) { if (FD_ISSET(fd, &fdset)) { return (uread(fd, &c, 1) < 1 ? -1 : c); } } } return -1; }
ssize_t BSP_uart_termios_write_com2(int minor, const char *buf, size_t len) { if(len <= 0) { return 0; } assert(buf != NULL); /* If there TX buffer is busy - something is royally screwed up */ assert((uread(BSP_UART_COM2, LSR) & THRE) != 0); if(termios_stopped_com2) { /* CTS low */ termios_tx_hold_com2 = *buf; termios_tx_hold_valid_com2 = 1; return 0; } /* Write character */ uwrite(BSP_UART_COM2, THR, *buf & 0xff); /* Enable interrupts if necessary */ if ( !termios_tx_active_com2 ) { termios_tx_active_com2 = 1; uart_data[BSP_UART_COM2].ier |= TRANSMIT_ENABLE; uwrite(BSP_UART_COM2, IER, uart_data[BSP_UART_COM2].ier); } return 1; }
/* * Set baud */ void BSP_uart_set_baud(int uart, int baud) { unsigned char ier; /* Sanity check */ assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2); /* * This function may be called whenever TERMIOS parameters * are changed, so we have to make sure that baud change is * indeed required */ if(baud == uart_data[uart].baud) { return; } ier = uread(uart, IER); BSP_uart_init(uart, baud, uart_data[uart].hwFlow); uwrite(uart, IER, ier); return; }
/* * Polled mode write function */ void BSP_uart_polled_write(int uart, int val) { unsigned char val1; /* Sanity check */ assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2); for(;;) { if((val1=uread(uart, LSR)) & THRE) { break; } } if(uart_data[uart].hwFlow) { for(;;) { if(uread(uart, MSR) & CTS) { break; } } } uwrite(uart, THR, val & 0xff); /* * Wait for character to be transmitted. * This ensures that printk and printf play nicely together * when using the same serial port. * Yes, there's a performance hit here, but if we're doing * polled writes to a serial port we're probably not that * interested in efficiency anyway..... */ for(;;) { if((val1=uread(uart, LSR)) & THRE) { break; } } return; }
/* * Set channel parameters */ void BSP_uart_termios_set(int uart, void *ttyp) { struct rtems_termios_tty *p = (struct rtems_termios_tty *)ttyp; unsigned char val; assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2); if(uart == BSP_UART_COM1) { uart_data[uart].ioMode = p->device.outputUsesInterrupts; if(uart_data[uart].hwFlow) { val = uread(uart, MSR); termios_stopped_com1 = (val & CTS) ? 0 : 1; } else { termios_stopped_com1 = 0; } termios_tx_active_com1 = 0; termios_ttyp_com1 = ttyp; termios_tx_hold_com1 = 0; termios_tx_hold_valid_com1 = 0; } else { uart_data[uart].ioMode = p->device.outputUsesInterrupts; if(uart_data[uart].hwFlow) { val = uread(uart, MSR); termios_stopped_com2 = (val & CTS) ? 0 : 1; } else { termios_stopped_com2 = 0; } termios_tx_active_com2 = 0; termios_ttyp_com2 = ttyp; termios_tx_hold_com2 = 0; termios_tx_hold_valid_com2 = 0; } return; }
/* * Polled mode read function */ int BSP_uart_polled_read(int uart) { unsigned char val; assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2); for(;;) { if(uread(uart, LSR) & DR) { break; } } val = uread(uart, RBR); return (int)(val & 0xff); }
static void uartError(int uart) { unsigned char uartStatus, dummy; uartStatus = uread(uart, LSR); dummy = uread(uart, RBR); if (uartStatus & OE) printk("********* Over run Error **********\n"); if (uartStatus & PE) printk("********* Parity Error **********\n"); if (uartStatus & FE) printk("********* Framing Error **********\n"); if (uartStatus & BI) printk("********* Parity Error **********\n"); if (uartStatus & ERFIFO) printk("********* Error receive Fifo **********\n"); }
static void get_sector(int fd, struct part_blk *blk, long sector) { char msg[20]; if (0!=lseek(fd, sector<<9, SEEK_SET)) { perror("device:"); exit(1); } sprintf(msg,"sector %d",sector); uread(fd, blk, sizeof(*blk), msg); chk_magic(blk, msg); }
int BSP_uart_termios_read_com2(int uart) { int off = (int)0; char buf[40]; /* read current byte */ while (( off < sizeof(buf) ) && ( uread(BSP_UART_COM2, LSR) & DR )) { buf[off++] = uread(BSP_UART_COM2, RBR); } /* write out data */ if ( off > 0 ) { rtems_termios_enqueue_raw_characters(termios_ttyp_com2, buf, off); } /* enable receive interrupts */ uart_data[BSP_UART_COM2].ier |= (RECEIVE_ENABLE | RECEIVER_LINE_ST_ENABLE); uwrite(BSP_UART_COM2, IER, uart_data[BSP_UART_COM2].ier); return ( EOF ); }
void BSP_uart_set_attributes ( int uart, unsigned long baud, unsigned long databits, unsigned long parity, unsigned long stopbits ) { unsigned char mcr, ier; /* Sanity check */ assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2); /* * This function may be called whenever TERMIOS parameters * are changed, so we have to make sure that baud change is * indeed required */ if( (baud == uart_data[uart].baud) && (databits == uart_data[uart].databits) && (parity == uart_data[uart].parity) && (stopbits == uart_data[uart].stopbits) ) { return; } mcr = uread(uart, MCR); ier = uread(uart, IER); BSP_uart_init(uart, baud, databits, parity, stopbits, uart_data[uart].hwFlow); uwrite(uart, MCR, mcr); uwrite(uart, IER, ier); return; }
int main( int argc , char **argv ) { unsigned long cliaddr; unsigned short cliport; int ufd , nfd; fprintf( stderr, "start\n"); uinit(INADDR_ANY); fprintf( stderr, "inited\n"); ufd = usocket_serv( 8 ); fprintf( stderr, "socketd %d\n", ufd ); ulisten( ufd ); fprintf( stderr, "listened\n"); while(1){ int r =uproc(); /* fprintf( stderr, "uproced %d\n" , r);*/ nfd = uaccept( ufd , &cliaddr ,&cliport); if( nfd >= 0 ){ fprintf( stderr, "accepted! nfd:%d %x %d\n" , nfd ,cliaddr , ntohs(cliport) ); break; } } while(1){ int r = uproc(); fprintf( stderr,"." ); if( ureadable( nfd ) ){ char buffer[800]; int r; fprintf( stderr, "REadable!!\n"); bzero( buffer ,sizeof(buffer)); if( (r = uread( nfd, buffer , sizeof( buffer ) )) >= 0 ){ int wr; fprintf( stderr , "ReadData %d: [%s]\n" ,r, buffer ); wr = uwrite( nfd , buffer , r ); fprintf( stderr ,"Wrote %dbytes\n",wr ); } } usleep(100*1000); } }
static void uartError(int uart) { unsigned char uartStatus, dummy; uartStatus = uread(uart, LSR); (void) uartStatus; /* avoid set but not used warning */ dummy = uread(uart, RBR); (void) dummy; /* avoid set but not used warning */ #ifdef UARTDEBUG if (uartStatus & OE) printk("********* Over run Error **********\n"); if (uartStatus & PE) printk("********* Parity Error **********\n"); if (uartStatus & FE) printk("********* Framing Error **********\n"); if (uartStatus & BI) printk("********* Parity Error **********\n"); if (uartStatus & ERFIFO) printk("********* Error receive Fifo **********\n"); #endif }
int main(int argc, char *argv[]) { char name[64]; int pid, cmd; int pd[2]; while(1){ printf("\n----------------------------------------------\n"); #ifndef _LAB_3_ printf("I am proc %d in U mode with ppid %d: running segment=%x\n",getpid(), getppid(), getcs()); #else printf("I am proc "); getpid(); printf(" in U mode: running segment=%x\n", getcs()); #endif #ifdef _SLEEPER_ while(1) { printf("PID: %d PPID: %d\n", getpid(), getppid()); sleep(5); return 0; } #endif show_menu(); printf("Command? "); gets(name); printf("\n"); if (name[0]==0) continue; cmd = find_cmd(name); switch(cmd){ case 0: getpid(); break; case 1: ps(); break; case 2: chname(); break; case 3: kswitch(); break; case 4: wait(); break; case 5: ufork(); break; case 6: uexec(); break; case 7: exit(); break; case 8: pipe(pd); break; case 9: pfd(); break; case 10: uclose(); break; case 11: uread(); break; case 12: uwrite(); break; case 13: usleep(); break; default:invalid(name);break; } } }
/* * Status function, -1 if error * detected, 0 if no received chars available, * 1 if received char available, 2 if break * is detected, it will eat break and error * chars. It ignores overruns - we cannot do * anything about - it execpt count statistics * and we are not counting it. */ int BSP_uart_polled_status(int uart) { unsigned char val; assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2); val = uread(uart, LSR); if(val & BI) { /* BREAK found, eat character */ uread(uart, RBR); return BSP_UART_STATUS_BREAK; } if((val & (DR | OE | FE)) == 1) { /* No error, character present */ return BSP_UART_STATUS_CHAR; } if((val & (DR | OE | FE)) == 0) { /* Nothing */ return BSP_UART_STATUS_NOCHAR; } /* * Framing or parity error * eat character */ uread(uart, RBR); return BSP_UART_STATUS_ERROR; }
static inline size_t readall(int fd, void *buf, size_t count) { int len, total; for (len=0, total=0; count-total>0; total+=len) { len = uread(fd, (char*)buf+total, count-total); if (len == -1) { return -1; } if (len == 0) { break; } } return total; }
int fasttrap_tracepoint_remove(proc_t *p, fasttrap_tracepoint_t *tp) { uint8_t instr; /* * Distinguish between read or write failures and a changed * instruction. */ if (uread(p, &instr, 1, tp->ftt_pc) != 0) return (0); if (instr != FASTTRAP_INSTR) return (0); if (uwrite(p, &tp->ftt_instr[0], 1, tp->ftt_pc) != 0) return (-1); return (0); }
/* * Polled mode write function */ void BSP_uart_polled_write(int uart, int val) { unsigned char val1; /* Sanity check */ assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2); for(;;) { if((val1=uread(uart, LSR)) & THRE) { break; } } uwrite(uart, THR, val & 0xff); return; }
void BSP_uart_unthrottle(int uart) { unsigned int mcr; assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2); if(!uart_data[uart].hwFlow) { /* Should not happen */ assert(0); return; } mcr = uread (uart, MCR); /* RTS up */ mcr |= RTS; uwrite(uart, MCR, mcr); return; }
int BSP_uart_termios_write_com1(int minor, const char *buf, int len) { assert(buf != NULL); if(len <= 0) { return 0; } /* If there TX buffer is busy - something is royally screwed up */ assert((uread(BSP_UART_COM1, LSR) & THRE) != 0); if(termios_stopped_com1) { /* CTS low */ termios_tx_hold_com1 = *buf; termios_tx_hold_valid_com1 = 1; return 0; } /* Write character */ uwrite(BSP_UART_COM1, THR, *buf & 0xff); /* Enable interrupts if necessary */ if(!termios_tx_active_com1) { termios_tx_active_com1 = 1; uwrite(BSP_UART_COM1, IER, (RECEIVE_ENABLE | TRANSMIT_ENABLE | RECEIVER_LINE_ST_ENABLE ) ); } return 0; }
int common_getc(dev_t dev) { struct timeval tv; fd_set fdset; int fd, nfds, n; char c; while (1) { tv.tv_sec = 0; tv.tv_usec = 10000; FD_ZERO(&fdset); /* Always read from stdin. */ fd = 0; nfds = 1; FD_SET(fd, &fdset); /* Read from serial if open. */ if (com_fd != -1) { nfds = com_fd+1; FD_SET(com_fd, &fdset); } n = uselect(nfds, &fdset, NULL, NULL, &tv); if ((dev & 0x80) != 0) return (n > 0); if (n > 0) break; } for (fd = 0; fd < nfds; fd++) if (FD_ISSET(fd, &fdset)) break; return (uread(fd, &c, 1) < 1 ? -1 : c); }
/* * Uart initialization, it is hardcoded to 8 bit, no parity, * one stop bit, FIFO, things to be changed * are baud rate and nad hw flow control, * and longest rx fifo setting */ void BSP_uart_init ( int uart, unsigned long baud, unsigned long databits, unsigned long parity, unsigned long stopbits, int hwFlow ) { /* Sanity check */ assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2); switch(baud) { case 50: case 75: case 110: case 134: case 300: case 600: case 1200: case 2400: case 9600: case 19200: case 38400: case 57600: case 115200: break; default: assert(0); return; } /* Set DLAB bit to 1 */ uwrite(uart, LCR, DLAB); /* Set baud rate */ uwrite(uart, DLL, (BSPBaseBaud/baud) & 0xff); uwrite(uart, DLM, ((BSPBaseBaud/baud) >> 8) & 0xff); /* 8-bit, no parity , 1 stop */ uwrite(uart, LCR, databits | parity | stopbits); /* Set DTR, RTS and OUT2 high */ uwrite(uart, MCR, DTR | RTS | OUT_2); /* Enable FIFO */ uwrite(uart, FCR, FIFO_EN | XMIT_RESET | RCV_RESET | RECEIVE_FIFO_TRIGGER12); /* Disable Interrupts */ uwrite(uart, IER, 0); /* Read status to clear them */ uread(uart, LSR); uread(uart, RBR); uread(uart, MSR); /* Remember state */ uart_data[uart].baud = baud; uart_data[uart].databits = databits; uart_data[uart].parity = parity; uart_data[uart].stopbits = stopbits; uart_data[uart].hwFlow = hwFlow; return; }
void BSP_uart_termios_isr_com2(void *ignored) { unsigned char buf[40]; unsigned char val; int off, ret, vect; off = 0; for(;;) { vect = uread(BSP_UART_COM2, IIR) & 0xf; switch(vect) { case MODEM_STATUS : val = uread(BSP_UART_COM2, MSR); if(uart_data[BSP_UART_COM2].hwFlow) { if(val & CTS) { /* CTS high */ termios_stopped_com2 = 0; if(termios_tx_hold_valid_com2) { termios_tx_hold_valid_com2 = 0; BSP_uart_termios_write_com2(0, &termios_tx_hold_com2, 1); } } else { /* CTS low */ termios_stopped_com2 = 1; } } break; case NO_MORE_INTR : /* No more interrupts */ if(off != 0) { /* Update rx buffer */ if( driver_input_handler_com2 ) { driver_input_handler_com2( termios_ttyp_com2, (char *)buf, off ); } else { rtems_termios_enqueue_raw_characters(termios_ttyp_com2, (char *)buf, off); } } return; case TRANSMITTER_HODING_REGISTER_EMPTY : /* * TX holding empty: we have to disable these interrupts * if there is nothing more to send. */ /* If nothing else to send disable interrupts */ ret = rtems_termios_dequeue_characters(termios_ttyp_com2, 1); if ( ret == 0 ) { termios_tx_active_com2 = 0; uart_data[BSP_UART_COM2].ier &= ~(TRANSMIT_ENABLE); uwrite(BSP_UART_COM2, IER, uart_data[BSP_UART_COM2].ier); } break; case RECEIVER_DATA_AVAIL : case CHARACTER_TIMEOUT_INDICATION: if ( uart_data[BSP_UART_COM2].ioMode == TERMIOS_TASK_DRIVEN ) { /* ensure interrupts are enabled */ if ( uart_data[BSP_UART_COM2].ier & RECEIVE_ENABLE ) { /* disable interrupts and notify termios */ uart_data[BSP_UART_COM2].ier &= ~(RECEIVE_ENABLE | RECEIVER_LINE_ST_ENABLE); uwrite(BSP_UART_COM2, IER, uart_data[BSP_UART_COM2].ier); rtems_termios_rxirq_occured(termios_ttyp_com2); } } else { /* RX data ready */ assert(off < sizeof(buf)); buf[off++] = uread(BSP_UART_COM2, RBR); } break; case RECEIVER_ERROR: /* RX error: eat character */ uartError(BSP_UART_COM2); break; default: /* Should not happen */ assert(0); return; } } }
void main(int argc, char **argv) { unsigned long countdown = 0; int wntDiskAdmin = 0; char char0 = 'a'; char defltr = 0; char force = 0; char const *dev_name; int fd_dev; if (argc < 2) { usage(); exit(1); } dev_name = argv[1]; fd_dev = open(dev_name, 0); if (fd_dev < 0) { perror(dev_name); exit(1); } get_sector(fd_dev, &dev_mbr, 0); uread(0, &new_mbr, 5, ".bin hdr"); /* discard header */ uread(0, &new_mbr, sizeof(new_mbr), "new mbr"); /* prototype mbr */ chk_magic(&new_mbr, "new mbr"); for ( (argv+=2), (argc-=2); argc > 0; (++argv), (--argc) ) if ('-'==**argv) { char *value = strchr(*argv, '='); if (0!=value) { *value++ = 0; } if (0==strcmp("-wait", *argv)) { if (0!=value) { countdown = atoi(value); if (0 < countdown && countdown < 4000) { countdown *= 1000000; } } } else if (0==strcmp("-char0", *argv)) { if (0!=value) { char0 = *value; } } else if (0==strcmp("-default", *argv)) { if (0!=value) { defltr = *value; } } else if (0==strcmp("-force", *argv)) { if (0!=value) { force = *value; } } else if (0==strcmp("-WNTDiskAdmin", *argv)) { wntDiskAdmin = 6; } else { fprintf(stderr,"ignoring option %s\n", *argv); } } else { break; } /* Somebody please tell me how to read an .obj symbol table so I can do these magic offsets symbolically! */ #define COUNT 0x184 #define DEFLTR 0x172 #define DESLTR 0x038 #define NAMES 0x19a memcpy(&new_mbr.random[COUNT -4], &countdown, sizeof(countdown)); memcpy(&new_mbr.random[DEFLTR -1], &defltr, sizeof(defltr)); memcpy(&new_mbr.random[DESLTR -2], &char0, sizeof(char0)); memcpy(&new_mbr.random[DESLTR -1], &force, sizeof(force)); if (0==countdown) {/* wait forever: no count at all */ new_mbr.random[COUNT -6] = 0xeb; /* JMP rel8 */ new_mbr.random[COUNT -5] = 0x0d; /* skip to getcWait */ } if (0 < argc) { char *labels = &new_mbr.random[NAMES]; int avail = (0x200 - 2 - 4*16 - wntDiskAdmin) - NAMES; qsort(argv, argc, sizeof(*argv), (qsort_fn_t)strcmp); for ( ; 0!=argc; ++argv, --argc ) { int const len = 1+strlen(2+*argv); if ((avail -= len) < 0) { fprintf(stderr,"Use shorter labels; " "`%c=%s' won't fit.\n", **argv, 2+*argv); } else { strcpy(labels, 2+*argv); labels += len; } if (1 < argc /* not last */ && (1 + *argv[0]) != *argv[1] ) { fprintf(stderr, "letters must be consecutive: %s %s\n", argv[0], argv[1] ); exit(1); } } fprintf(stderr, "%d bytes available.\n", avail); } if (0!=wntDiskAdmin) { /* WindowsNT disk administrator uses these 6 bytes */ memcpy(&new_mbr.random[446-6], &dev_mbr.random[446-6], 6); } memcpy(&new_mbr.part[0], &dev_mbr.part[0], 4*16); uwrite(1, &new_mbr, sizeof(new_mbr), "stdout"); exit(0); }
int main(int argc, char** argv) { #if (defined WIN32 || defined _WIN32) WSADATA wsadata; int rc = WSAStartup(MAKEWORD(2,0), &wsadata); if (rc) return 1; #endif upoll_t* upq = upoll_create(32); intptr_t sd1 = usocket(PF_INET, SOCK_STREAM, IPPROTO_TCP); printf("server: %li\n", sd1); printf("bind: %d\n", ubind(sd1, "127.0.0.1", "1976")); printf("listen: %d\n", ulisten(sd1, 128)); upoll_event_t ev1, ev2; upoll_event_t events[8]; ev1.events = UPOLLIN; ev1.data.fd = sd1; upoll_ctl(upq, UPOLL_CTL_ADD, sd1, &ev1); int r = 0, x = 0; while (1) { int i, e; e = upoll_wait(upq, events, 8, -1); printf("events: %i\n", e); if (x++ == 50) return 0; for (i = 0; i < e; i++) { char buf[4096]; if (events[i].events & UPOLLERR) { printf("ERROR on %li\n", events[i].data.fd); upoll_ctl(upq, UPOLL_CTL_DEL, events[i].data.fd, NULL); uclose(events[i].data.fd); } else if (events[i].events & UPOLLIN) { printf("have POLLIN on %li\n", events[i].data.fd); if (events[i].data.fd == sd1) { int sd2 = uaccept(sd1); printf("uaccept: %i\n", sd2); ev2.events = UPOLLIN; ev2.data.fd = sd2; upoll_ctl(upq, UPOLL_CTL_ADD, sd2, &ev2); } else { int cfd = events[i].data.fd; memset(buf, 0, 4096); printf("client input...\n"); r = uread(cfd, buf, 4096); printf("read %i bytes\n", r); if (r == 0) { printf("EOF DETECTED\n"); upoll_ctl(upq, UPOLL_CTL_DEL, events[i].data.fd, NULL); uclose(events[i].data.fd); } else { ev2.events = UPOLLOUT; upoll_ctl(upq, UPOLL_CTL_MOD, cfd, &ev2); } } } else if (events[i].events & UPOLLOUT) { printf("client writable...\n"); int cfd = events[i].data.fd; int w = uwrite(cfd, buf, r); ev2.events = UPOLLIN; printf("wrote %i bytes, mod for UPOLLIN again\n", w); upoll_ctl(upq, UPOLL_CTL_MOD, cfd, &ev2); } } } #if (defined WIN32 || defined _WIN32) WSACleanup(); #endif return 0; }
/*ARGSUSED*/ int fasttrap_tracepoint_init(proc_t *p, fasttrap_tracepoint_t *tp, uintptr_t pc, fasttrap_probe_type_t type) { uint8_t instr[FASTTRAP_MAX_INSTR_SIZE + 10]; size_t len = FASTTRAP_MAX_INSTR_SIZE; size_t first = MIN(len, PAGESIZE - (pc & PAGEOFFSET)); uint_t start = 0; int rmindex, size; uint8_t seg, rex = 0; /* * Read the instruction at the given address out of the process's * address space. We don't have to worry about a debugger * changing this instruction before we overwrite it with our trap * instruction since P_PR_LOCK is set. Since instructions can span * pages, we potentially read the instruction in two parts. If the * second part fails, we just zero out that part of the instruction. */ if (uread(p, &instr[0], first, pc) != 0) return (-1); if (len > first && uread(p, &instr[first], len - first, pc + first) != 0) { bzero(&instr[first], len - first); len = first; } /* * If the disassembly fails, then we have a malformed instruction. */ if ((size = dtrace_instr_size_isa(instr, p->p_model, &rmindex)) <= 0) return (-1); /* * Make sure the disassembler isn't completely broken. */ ASSERT(-1 <= rmindex && rmindex < size); /* * If the computed size is greater than the number of bytes read, * then it was a malformed instruction possibly because it fell on a * page boundary and the subsequent page was missing or because of * some malicious user. */ if (size > len) return (-1); tp->ftt_size = (uint8_t)size; tp->ftt_segment = FASTTRAP_SEG_NONE; /* * Find the start of the instruction's opcode by processing any * legacy prefixes. */ for (;;) { seg = 0; switch (instr[start]) { case FASTTRAP_PREFIX_SS: seg++; /*FALLTHRU*/ case FASTTRAP_PREFIX_GS: seg++; /*FALLTHRU*/ case FASTTRAP_PREFIX_FS: seg++; /*FALLTHRU*/ case FASTTRAP_PREFIX_ES: seg++; /*FALLTHRU*/ case FASTTRAP_PREFIX_DS: seg++; /*FALLTHRU*/ case FASTTRAP_PREFIX_CS: seg++; /*FALLTHRU*/ case FASTTRAP_PREFIX_OPERAND: case FASTTRAP_PREFIX_ADDRESS: case FASTTRAP_PREFIX_LOCK: case FASTTRAP_PREFIX_REP: case FASTTRAP_PREFIX_REPNE: if (seg != 0) { /* * It's illegal for an instruction to specify * two segment prefixes -- give up on this * illegal instruction. */ if (tp->ftt_segment != FASTTRAP_SEG_NONE) return (-1); tp->ftt_segment = seg; } start++; continue; } break; } #ifdef __amd64 /* * Identify the REX prefix on 64-bit processes. */ if (p->p_model == DATAMODEL_LP64 && (instr[start] & 0xf0) == 0x40) rex = instr[start++]; #endif /* * Now that we're pretty sure that the instruction is okay, copy the * valid part to the tracepoint. */ bcopy(instr, tp->ftt_instr, FASTTRAP_MAX_INSTR_SIZE); tp->ftt_type = FASTTRAP_T_COMMON; if (instr[start] == FASTTRAP_2_BYTE_OP) { switch (instr[start + 1]) { case FASTTRAP_0F_JO: case FASTTRAP_0F_JNO: case FASTTRAP_0F_JB: case FASTTRAP_0F_JAE: case FASTTRAP_0F_JE: case FASTTRAP_0F_JNE: case FASTTRAP_0F_JBE: case FASTTRAP_0F_JA: case FASTTRAP_0F_JS: case FASTTRAP_0F_JNS: case FASTTRAP_0F_JP: case FASTTRAP_0F_JNP: case FASTTRAP_0F_JL: case FASTTRAP_0F_JGE: case FASTTRAP_0F_JLE: case FASTTRAP_0F_JG: tp->ftt_type = FASTTRAP_T_JCC; tp->ftt_code = (instr[start + 1] & 0x0f) | FASTTRAP_JO; tp->ftt_dest = pc + tp->ftt_size + /* LINTED - alignment */ *(int32_t *)&instr[start + 2]; break; } } else if (instr[start] == FASTTRAP_GROUP5_OP) { uint_t mod = FASTTRAP_MODRM_MOD(instr[start + 1]); uint_t reg = FASTTRAP_MODRM_REG(instr[start + 1]); uint_t rm = FASTTRAP_MODRM_RM(instr[start + 1]); if (reg == 2 || reg == 4) { uint_t i, sz; if (reg == 2) tp->ftt_type = FASTTRAP_T_CALL; else tp->ftt_type = FASTTRAP_T_JMP; if (mod == 3) tp->ftt_code = 2; else tp->ftt_code = 1; ASSERT(p->p_model == DATAMODEL_LP64 || rex == 0); /* * See AMD x86-64 Architecture Programmer's Manual * Volume 3, Section 1.2.7, Table 1-12, and * Appendix A.3.1, Table A-15. */ if (mod != 3 && rm == 4) { uint8_t sib = instr[start + 2]; uint_t index = FASTTRAP_SIB_INDEX(sib); uint_t base = FASTTRAP_SIB_BASE(sib); tp->ftt_scale = FASTTRAP_SIB_SCALE(sib); tp->ftt_index = (index == 4) ? FASTTRAP_NOREG : regmap[index | (FASTTRAP_REX_X(rex) << 3)]; tp->ftt_base = (mod == 0 && base == 5) ? FASTTRAP_NOREG : regmap[base | (FASTTRAP_REX_B(rex) << 3)]; i = 3; sz = mod == 1 ? 1 : 4; } else { /* * In 64-bit mode, mod == 0 and r/m == 5 * denotes %rip-relative addressing; in 32-bit * mode, the base register isn't used. In both * modes, there is a 32-bit operand. */ if (mod == 0 && rm == 5) { #ifdef __amd64 if (p->p_model == DATAMODEL_LP64) tp->ftt_base = REG_RIP; else #endif tp->ftt_base = FASTTRAP_NOREG; sz = 4; } else { uint8_t base = rm | (FASTTRAP_REX_B(rex) << 3); tp->ftt_base = regmap[base]; sz = mod == 1 ? 1 : mod == 2 ? 4 : 0; } tp->ftt_index = FASTTRAP_NOREG; i = 2; } if (sz == 1) { tp->ftt_dest = *(int8_t *)&instr[start + i]; } else if (sz == 4) { /* LINTED - alignment */ tp->ftt_dest = *(int32_t *)&instr[start + i]; } else { tp->ftt_dest = 0; } } } else { switch (instr[start]) { case FASTTRAP_RET: tp->ftt_type = FASTTRAP_T_RET; break; case FASTTRAP_RET16: tp->ftt_type = FASTTRAP_T_RET16; /* LINTED - alignment */ tp->ftt_dest = *(uint16_t *)&instr[start + 1]; break; case FASTTRAP_JO: case FASTTRAP_JNO: case FASTTRAP_JB: case FASTTRAP_JAE: case FASTTRAP_JE: case FASTTRAP_JNE: case FASTTRAP_JBE: case FASTTRAP_JA: case FASTTRAP_JS: case FASTTRAP_JNS: case FASTTRAP_JP: case FASTTRAP_JNP: case FASTTRAP_JL: case FASTTRAP_JGE: case FASTTRAP_JLE: case FASTTRAP_JG: tp->ftt_type = FASTTRAP_T_JCC; tp->ftt_code = instr[start]; tp->ftt_dest = pc + tp->ftt_size + (int8_t)instr[start + 1]; break; case FASTTRAP_LOOPNZ: case FASTTRAP_LOOPZ: case FASTTRAP_LOOP: tp->ftt_type = FASTTRAP_T_LOOP; tp->ftt_code = instr[start]; tp->ftt_dest = pc + tp->ftt_size + (int8_t)instr[start + 1]; break; case FASTTRAP_JCXZ: tp->ftt_type = FASTTRAP_T_JCXZ; tp->ftt_dest = pc + tp->ftt_size + (int8_t)instr[start + 1]; break; case FASTTRAP_CALL: tp->ftt_type = FASTTRAP_T_CALL; tp->ftt_dest = pc + tp->ftt_size + /* LINTED - alignment */ *(int32_t *)&instr[start + 1]; tp->ftt_code = 0; break; case FASTTRAP_JMP32: tp->ftt_type = FASTTRAP_T_JMP; tp->ftt_dest = pc + tp->ftt_size + /* LINTED - alignment */ *(int32_t *)&instr[start + 1]; break; case FASTTRAP_JMP8: tp->ftt_type = FASTTRAP_T_JMP; tp->ftt_dest = pc + tp->ftt_size + (int8_t)instr[start + 1]; break; case FASTTRAP_PUSHL_EBP: if (start == 0) tp->ftt_type = FASTTRAP_T_PUSHL_EBP; break; case FASTTRAP_NOP: #ifdef __amd64 ASSERT(p->p_model == DATAMODEL_LP64 || rex == 0); /* * On amd64 we have to be careful not to confuse a nop * (actually xchgl %eax, %eax) with an instruction using * the same opcode, but that does something different * (e.g. xchgl %r8d, %eax or xcghq %r8, %rax). */ if (FASTTRAP_REX_B(rex) == 0) #endif tp->ftt_type = FASTTRAP_T_NOP; break; case FASTTRAP_INT3: /* * The pid provider shares the int3 trap with debugger * breakpoints so we can't instrument them. */ ASSERT(instr[start] == FASTTRAP_INSTR); return (-1); case FASTTRAP_INT: /* * Interrupts seem like they could be traced with * no negative implications, but it's possible that * a thread could be redirected by the trap handling * code which would eventually return to the * instruction after the interrupt. If the interrupt * were in our scratch space, the subsequent * instruction might be overwritten before we return. * Accordingly we refuse to instrument any interrupt. */ return (-1); } } #ifdef __amd64 if (p->p_model == DATAMODEL_LP64 && tp->ftt_type == FASTTRAP_T_COMMON) { /* * If the process is 64-bit and the instruction type is still * FASTTRAP_T_COMMON -- meaning we're going to copy it out an * execute it -- we need to watch for %rip-relative * addressing mode. See the portion of fasttrap_pid_probe() * below where we handle tracepoints with type * FASTTRAP_T_COMMON for how we emulate instructions that * employ %rip-relative addressing. */ if (rmindex != -1) { uint_t mod = FASTTRAP_MODRM_MOD(instr[rmindex]); uint_t reg = FASTTRAP_MODRM_REG(instr[rmindex]); uint_t rm = FASTTRAP_MODRM_RM(instr[rmindex]); ASSERT(rmindex > start); if (mod == 0 && rm == 5) { /* * We need to be sure to avoid other * registers used by this instruction. While * the reg field may determine the op code * rather than denoting a register, assuming * that it denotes a register is always safe. * We leave the REX field intact and use * whatever value's there for simplicity. */ if (reg != 0) { tp->ftt_ripmode = FASTTRAP_RIP_1 | (FASTTRAP_RIP_X * FASTTRAP_REX_B(rex)); rm = 0; } else { tp->ftt_ripmode = FASTTRAP_RIP_2 | (FASTTRAP_RIP_X * FASTTRAP_REX_B(rex)); rm = 1; } tp->ftt_modrm = tp->ftt_instr[rmindex]; tp->ftt_instr[rmindex] = FASTTRAP_MODRM(2, reg, rm); } } } #endif return (0); }