/* * io.c -- all the code to make GCC and the libraries run on * a bare target board. */ #include #include #include #include "hppa-defs.h" extern char *_end; /* _end is set in the linker command file */ /* just in case, most boards have at least some memory */ #ifndef RAMSIZE # define RAMSIZE (char *)0x100000 #endif int print(ptr) char *ptr; { while (*ptr) outbyte (*ptr++); } int putnum (Num) unsigned int Num; { char Buffer[9]; int Count; char *BufPtr = Buffer; int Digit; for (Count = 7 ; Count >= 0 ; Count--) { Digit = (Num >> (Count * 4)) & 0xf; if (Digit <= 9) *BufPtr++ = (char) ('0' + Digit); else *BufPtr++ = (char) ('a' - 10 + Digit); } *BufPtr = (char) 0; print (Buffer); return; } int delay (x) int x; { int y = 17; while (x-- !=0) y = y^2; } /* * strobe -- do a zylons thing, toggling each led in sequence forever... */ int zylons() { while (1) { strobe(); } } /* * strobe -- toggle each led in sequence up and back once. */ int strobe() { static unsigned char curled = 1; static unsigned char dir = 0; curled = 1; dir = 0; while (curled != 0) { led_putnum (curled); delay (70000); if (dir) curled >>= 1; else curled <<= 1; if (curled == 128) { dir = ~dir; } } curled = 1; dir = 0; } /* * iodc_io_call -- this makes a call into the IODC routine */ int iodc_io_call(ep_address,arg0,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11) int ep_address, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11; { int (*iodc_entry_point)(); iodc_entry_point = (int (*)())ep_address; return ((*iodc_entry_point)(arg0,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11)); } /* * pdc_call -- this makes a call into the PDC routine */ int pdc_call(arg0,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11) int arg0, arg1, arg2, arg3, arg4, arg5; int arg6, arg7, arg9, arg10, arg11; { return ( CALL_PDC(arg0,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11)); } /* * put_led -- put a bit pattern on the LED's. */ int led_putnum (byte) unsigned short byte; { return (pdc_call(OPT_PDC_CHASSIS,0,byte)); } /* * outbyte -- shove a byte out the serial port */ int outbyte(byte) unsigned char byte; { int status; int R_addr[32]; struct _dev *console = (struct _dev *)PGZ_CONSOLE_STRUCT; status = iodc_io_call(console->iodc_io, console->hpa, IO_CONSOLE_OUTPUT, console->spa, console->layer[0], R_addr, 0, &byte, 1, 0); switch(status) { case 0: return(1); default: return (-1); } } /* * inbyte -- get a byte from the serial port */ unsigned char inbyte() { int status; int R_addr[32]; char inbuf; struct _dev *console = (struct _dev *)PGZ_CONSOLE_STRUCT; while (status == 0) { status = iodc_io_call(console->iodc_io, console->hpa, IO_CONSOLE_INPUT, console->spa, console->layer[0], R_addr, 0, &inbuf, 1, 0); switch (status) { case 0: case 2: /* recoverable error */ if (R_addr[0] != 0) { /* found a character */ return(inbuf); } else break; /* error, no character */ default: /* error, no character */ return(0); } } } /* * read -- read bytes from the serial port. Ignore fd, since * we only have stdin. */ int read(fd, buf, nbytes) int fd; char *buf; int nbytes; { int i = 0; for (i = 0; i < nbytes; i++) { *(buf + i) = inbyte(); if ((*(buf + i) == '\n') || (*(buf + i) == '\r')) { (*(buf + i)) = 0; break; } } return (i); } /* * write -- write bytes to the serial port. Ignore fd, since * stdout and stderr are the same. Since we have no filesystem, * open will only return an error. */ int write(fd, buf, nbytes) int fd; char *buf; int nbytes; { int i; for (i = 0; i < nbytes; i++) { if (*(buf + i) == '\n') { outbyte ('\r'); } outbyte (*(buf + i)); } return (nbytes); } /* * open -- open a file descriptor. We don't have a filesystem, so * we return an error. */ int open(buf, flags, mode) char *buf; int flags; int mode; { errno = EIO; return (-1); } /* * close -- close a file descriptor. We don't need * to do anything, but pretend we did. */ int close(fd) int fd; { return (0); } /* * sbrk -- changes heap size size. Get nbytes more * RAM. We just increment a pointer in what's * left of memory on the board. */ char * sbrk(nbytes) int nbytes; { static char * heap_ptr = NULL; char * base; if (heap_ptr == NULL) { heap_ptr = (char *)&_end; } if ((RAMSIZE - heap_ptr) >= 0) { base = heap_ptr; heap_ptr += nbytes; return (heap_ptr); } else { errno = ENOMEM; return ((char *)-1); } } /* * isatty -- returns 1 if connected to a terminal device, * returns 0 if not. Since we're hooked up to a * serial port, we'll say yes return a 1. */ int isatty(fd) int fd; { return (1); } /* * lseek -- move read/write pointer. Since a serial port * is non-seekable, we return an error. */ off_t lseek(fd, offset, whence) int fd; off_t offset; int whence; { errno = ESPIPE; return ((off_t)-1); } /* * fstat -- get status of a file. Since we have no file * system, we just return an error. */ int fstat(fd, buf) int fd; struct stat *buf; { errno = EIO; return (-1); } /* * getpid -- only one process, so just return 1. */ #define __MYPID 1 int getpid() { return __MYPID; } /* * kill -- assume mvme.S, and go out via exit... */ int kill(pid, sig) int pid; int sig; { if(pid == __MYPID) _exit(sig); return 0; }