Most kernel routines return an error code in the accumlator (a), if the carry flag is reset upon return. Otherwise the ac might contain data. ------------------------------------------- $f000 RESET System reset $f003 NMI Non-maskable interrupt $f006 IRQ Interrupt routine ------------------------------------------- $f009 GETMEM Get a free memory block. Returns block number in x. $f00c FREMEM release memory block, parameter: block number in x $f00f GETBLK Tries to allocate a specified memory block, block number in x $f012 ENMEM registers usable memory block to memory subsystem, parameter: block number in x. ------------------------------------------- $f015 GETSTR Get a free stream. increase read and write task counter, returns stream number in x $f018 FRESTR decreases read and write task counter, thus freeing the stream, if both result in zero. parameter: stream number in x $f01b PUTC puts a byte on the stream. parameter: stream number in x, data byte in a. returns errorcode in a $f01e GETC Get a byte from the stream. parameter: stream number in x, returns data byte in a (with carry=0) or error code (carry=1) $f021 UNGETC Gives byte from stream back. parameter: stream number in x, data byte in a, returns error code in a $f024 STRCMD executes a stream command. parameter: stream number in x, stream command in a, returns error code in a. possible stream commands are: SC_GET 0 same as GETSTR SC_REG_RD 1 increase read task counter by one SC_REG_WR 2 increase write task counter by one SC_CLR 3 empty the stream SC_EOF 4 closing the stream from the sender side, i.e. decrease write task counter by one SC_NUL 5 closing the stream from the receiver side, i.e. decrease read task counter. SC_FRE 6 same as FRESTR SC_STAT 7 read stream status SC_GANZ 8 returns number of bytes in stream in a SC_RWANZ 9 returns the stream write pointer in a and the stream read pointer in y Possible stream status are: E_NUL Noone reading from stream (i.e. read task counter is zero) E_EOF stream is empty and noone is writing anymore (i.e. write task counter is zero) E_SEMPTY stream buffer is empty E_SFULL stream buffer is full E_SLWM number of bytes below Low Water Mark (1/4 buffer size) E_SHWM number of bytes above Hogh Water Mark (3/4 buffer size) ------------------------------------------- $f027 DEVCMD executes device commands. parameter: device number in x, device command in a, optional parameter in y. returns error code in a. possible stream commands are: DC_IRQ 0 execute IRQ routine the interrupt routine has to return E_OK if an interrupt source is cleared or E_NOIRQ if not. DC_RES 1 initialize device DC_GS 2 sets the stream (in y) the device reads from DC_PS 3 sets the stream (in y) the device writes to DC_RX_ON 4 switch on receive DC_TX_ON 5 switch off receive DC_RX_OFF 6 switch on send DC_TX_OFF 7 switch off send DC_SPD 8 set speed (in y), device dependend DC_HS 9 set handshake (in y), device dependend DC_ST 10 get device status, device dependend DC_EXIT 11 disable device, including IRQ sources DC_GNAM 16 get the name of a device, parameter: device number in x, returns name PCBUF ($0200) DC_GNUM 17 get number of a device from name, parameter: name in PCBUF, length of name in x, returns device number in x DC_REGDEV 18 register new device(s) With the registration of the device the system has to know what to do with it and where to put it in memory. Therefore you have to put the following struct in PCBUF. REGDEV_MPOS 0 address (position in memory map, i.e. upper 4 bits, 0-14) of device block when being executed REGDEV_MBLK 1 memory block number of device block where the code is in REGDEV_ADR 2 two-byte start address of the following: REGDEV_ADR -> 2 byte pointer to label1 JMP Start_of_1st_device Name_of_device,0 ... label1 2 byte pointer to label2 JMP Start_of_2nd_device Name_of_2nd_device,0 ... labeln $ffff With this method it is possible to register several devices, as long as they are in one memory block, with one call. The devices are started with DC_RESET. In y they get a system feature byte. Currently only bit 7 is defined, where $00 is 1 MHz system clock and $80 is 2 MHz system clock. ------------------------------------------- $f02a GETENV get a free environment and reserve the memory. parameter: wanted memory size in kByte in y, returns env number in x The memory is allocated from address 0 on. $f02d FREENV frees environment. parameter: env number in x $f030 SETBLK carry=1: changes in a specified env. the mapping for a memory block. parameter: env number in x, position in memory map (0-14) in y, new memory block in a, returns old memory block on this position in a $f033 FORK start a new task. parameter: length of the following struct in PCBUF in y FORK_ENV 0 env to start task in the env number is identical to the task id FORK_STDIN 1 stdin stream FORK_STDOUT 2 stdout stream FORK_STDERR 3 stderr stream FORK_ADR 4 start address of task FORK_NAME 6 name of task, ended by a nullbyte. then command line that started the program. The commandline is put into the PCBUF of the starting task. The new task gets its own task id in x The stream read/write task counter are incremented appropriately, i.e. for the out streams the write counter and for STDIN the read counter. $f036 TERM ends to own task. parameter: return code in a, which is given to other tasks waiting on it $f039 KILL ends another task. parameter: return code in a, task id in x $f03c SUSPEND just give control back to the scheduler, as there is nothing to do at the moment - but keep running (not needed for preemtive multitasking, an interrupt interrupts any task!) $f03f WTERM wait for a certain task to end. parameter: task id in x, returns error code. $f042 GETINFO get in info block of the running processes into PCBUF. 16 tasks (ANZ_ENV) a available at maximum and each task structure is 16 byte long TN_ST 0 task status TN_MEM 1 used memory in kByte TN_SP 2 stack pointer TN_IRQ 3 task interrupt routine address (0=none) TN_STDIN 5 stdin stream TN_STDOUT 6 stdout stream TN_STDERR 7 stderr stream TN_NAME 8 name of task (as given with fork) The task status can have the values given below: TS_FRE 0 env is free TS_ENV 1 env in use, but no task TS_IBRK 2 task executed BRK opcode in interrupt routine TS_BRK 3 task executed BRK opcode TS_RDY 4 task is runnable (as after SUSPEND) TS_IRQ 5 task is interrupted TS_WFRX 6 waiting for a receive from another task TS_WFTX 7 waiting for a send from another task TS_WFSEM 8 waiting on semaphore TS_WFTERM 9 waiting on another task to end TS_SIG 10 waiting on semaphore TS_WXTX 11 waiting on send from a specified task $f045 DUP (carry=1): set new STD* stream. parameter: STD* number in x, new stream in a, returns old stream in a read/write task counters are not touched! (carry=0): get redirected STD* stream number. parameter: STD* number in x, returns stream in a $f048 SETIRQ set task interrupt routine address. parameter: in PCBUF: SETIRQ_ENV 0 env number SETIRQ_ADR 1 irq routine address an address of zero disables task interrupt routine. returns E_CONFIG if disabled at compile time. $f04b TRESET sets the program counter of another task to a new address. parameter: in PCBUF: RESET_ENV 0 task id RESET_ADR 1 new address ------------------------------------------- $f04e GETSEM gets a free semaphore. returns semaphore number in x $f051 FRESEM frees a semaphore. parameter: semaphore number in x negative (system) semaphores cannot be freed (nor are they returned by GETSEM) $f054 PSEM 'PSEM' operation on a given semaphore. task waits till semaphore is freed. parameter: semaphore number in x carry=0: block till semaphore is free carry=1: do a test&set operation and return with E_OK if semaphore gotten, or E_SEMSET if semaphore is in use. $f057 VSEM 'VSEM' operation on semaphore, allows other tasks to grab the semaphore. parameter: semaphore number in x ------------------------------------------- $f05a SEND send a message to another task parameter: optional message type in a, target task in x, length of data in PCBUF in y; y=0 means 256 byte in PCBUF The data is in PCBUF ($0200). returns a and y as given and the 'redirected' target (e.g. from filesystem manager) in x $f05d RECEIVE receives a message. (carry=1): waits for any message (carry=0): returns immediately, with an error if no message received. Otherwise if a message is received, return sender task id in x, length of data in PCBUF in y (0 means 256) and the optional message type as given with SEND in a. $f060 WRITE write a byte into another environment. parameter: target env in y, pointer to a zeropage location in own task, where the target address is located, in x, byte to write in a. returns old content in a $f063 READ read data from another environment. parameter as above (without a of course). returns data byte in a. $f066 TDUP register a task for a (negative) system task number. parameter: (negative) task number to replace in x, new task number to be used instead in a $f069 SIGNAL (carry=0) wait for a signal from another task. parameter: awaited signal number in a, returns signal sender task id in a (carry=1) send signal to all tasks listening at the moment. parameter: signal number in a. $f06c XRECEIVE receives a message from a specified task only. parameter as with RECEIVE, plus sender task id in x $f06f SETNMI in systems without MMU, set the system NMI routine address. (carry=1): set the new NMI routine address (in a/y) returns the old NMI address in a/y. The old address is saved in the place pointed to by (newadress-4) (see below) by this routine. (carry=0): clear NMI routine. The NMI routine has to save all registers by itself! At NMI address -2 there must be the address of a ctrl routine that can be called via CTRLNMI. Expect that the ctrlnmi routine is called during this SETNMI with either NMI_ON of NMI_OFF in AC, to set the initial state. The ctrlnmi routines is called with JSR, i.e. return with RTS. At NMI address -4 is a pointer to a memory location where the address of the next NMI routine can be found. If the address found there is $ffff, then the list is at its end. A possible scenario then is: Task calls SETNMI with NEWNMI in a/y. We then have the structure: (NEWNMI-4) address of oldvec --> address of OLDNMI (NEWNMI-2) address of nmictrl NEWNMI --> NMI routine code This way the structure can be held in ROM, and still allow flexible NMI chaining. If CTRLNMI is called, each of the nmictrl routines is called with the given value in AC. $f072 CTRLNMI Send command in AC to all currently chained NMI ctrl routines as described with SETNMI. Possible values are: NMI_ON = allow NMIs NMI_OFF = disallow NMIs This routine is called when initiating and ending an IEC serial bus transfer, for example. ------------------------------------------- $f075 PUTB sends a block of data (address in zeropage, pointed to by yr, length in ac) to stream x returns number of transfered bytes in ac (c=0) or error (c=1) doesn't block, returns 0 instead $f078 GETB reads a block of data (address in zeropage, pointed to by yr, maximum length in ac) from stream x returns number of transfered bytes in ac (c=0) or error (c=1) doesn't block, returns 0 instead ------------------------------------------- On bootup the system is tested and possible errors are detected. On systems with a system port, the hardware error is shown by the number of flashes the LED makes before the system reboots /* Hardware-Errors */ #define HE_ZP <-1 /* zeropage mem test */ #define HE_RAM <-2 /* RAM test (to few RAM) */ #define HE_IMEM <-3 /* init memory */ #define HE_IDEV <-4 /* init device code */ #define HE_ISTR <-5 /* init stream code */ #define HE_IENV <-6 /* init environment code */ #define HE_ROM <-7 /* Couldn't start a program */ #define HE_DEV <-8 /* device returns error upon init */ #define HE_TASK <-9 /* all programs have terminated - reboot */ possible error codes are (from oadef/oa1str.def, where most things, except filesystem stuff are defined): /* Software-Errors */ #define E_OK 0 #define E_NOTIMP <-1 #define E_CONFIG <-2 #define E_ILLPAR <-3 #define E_NOMEM <-4 #define E_NOSTR <-5 #define E_SFULL <-6 #define E_SEMPTY <-7 #define E_SLWM <-8 #define E_SHWM <-9 #define E_EOF <-10 #define E_NUL <-11 #define E_NODEV <-12 #define E_DON <-13 #define E_DOFF <-14 #define E_NOTX <-15 #define E_NOENV <-16 #define E_NOSEM <-17 #define E_SEMSET <-18 #define E_FNODRV <-19 #define E_FNOPATH <-20 #define E_FNONAM <-21 #define E_FNOFIL <-22 #define E_FWPROT <-23 #define E_CMD <-65 #define E_Q <-66 #define E_GT <-67 #define E_RD <-68 #define E_WR <-69 #define E_V <-70 #define E_FT <-71 #define E_NOCLUS <-72 /* kein Cluster mehr frei */ #define E_INVDATA <-73 /* inkonsistente Daten auf der Diskette */ #define E_ILLCLUS <-74 /* Cluster =1 oder > F_CLUS */ #define E_VALBUF <-75 /* versucht gltigen Sektor mit XW zu schreiben */ #define E_FILEXIST <-76 /* Datei gibt es schon */ #define E_DISKFULL <-77 /* Diskette voll */ #define E_DNEMPTY <-78 /* bei rmdir Subdir nicht leer */ #define E_NOFILE <-79 /* keine File-Struktur frei */ #define E_ILLNAM <-80 /* Name mit Sonderzeichen *,?," */ #define E_FOPEN <-81 /* file fr Zugriff locked (file opened)*/ Terminal devices should understand the following terminal control codes (But the used device driver doesn't understand them all, though...) /* Terminal Commands */ #define TC_BEL 7 bell #define TC_BS 8 backspace #define TC_HT 9 horizontal tabulator #define TC_LF 10 line feed #define TC_VT 11 vertical tabulator #define TC_FF 12 form feed #define TC_CR 13 carriage return #define TC_ESC 27 Escape code #define TC_CLFT $80 cursor left #define TC_CRGT $81 cursor right #define TC_CUP $82 cursor up #define TC_CDWN $83 cursor down #define TC_HOME $84 cursor to the upper left edge #define TC_CLR $85 clear screen #define TC_DEL $86 delete char #define TC_INS $87 insert #define TC_WLO $88 set upper left window corner by cursor pos #define TC_WRU $89 set lower right window corner by cursor pos #define TC_WCLS $8a clear window #define TC_EOL $8b put cursor to the end of line #define TC_CLL $8c clear rest of line from cursor FORK, SETIRQ and TRESET can also be called via a SEND system call, when the receiver address is SEND_SYS and the message type is SP_* As with SEND/RECEIVE, all data is put into PCBUF. /* SysProcCalls */ #define SEND_SYS $ff #define PCBUF $200 #define SP_FORK 0 #define SP_SETIRQ 1 #define SP_RESET 2 #define FORK_ENV 0 #define FORK_STDIN 1 #define FORK_STDOUT 2 #define FORK_STDERR 3 #define FORK_ADR 4 #define FORK_NAME 6 /* Ende bei Nullbyte */ #define SETIRQ_ENV 0 #define SETIRQ_ADR 1 #define SETIRQ_SLEN 3 #define RESET_ENV 0 #define RESET_ADR 1 #define RESET_SLEN 3 STD* stream number are replaced by the numbers saved in the environment struct. /* StdStream */ #define STDNUL $fc /* wird ignoriert (z.b. fr FS) */ #define STDIN $fd #define STDOUT $fe #define STDERR $ff Reserved system environment numbers: #define SEND_FM $fe /* filesystem manager */ #define SEND_ERROR $fd /* critical error handler */ #define SEND_TIME $fc /* set/get actual time */