OS/A65 Kernel Interface Description

(c) 1989-96 Andre Fachat


OS/A65 Version 1.3.6g


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 gltigen 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 fr 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. fr 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 */