xref: /haiku/src/system/boot/platform/atari_m68k/toscalls.h (revision 16d5c24e533eb14b7b8a99ee9f3ec9ba66335b1e)
1 /*
2  * Copyright 2007, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT license.
4  *
5  * Author:
6  *		François Revol, revol@free.fr.
7  */
8 
9 #ifndef _TOSCALLS_H
10 #define _TOSCALLS_H
11 
12 #ifdef __cplusplus
13 extern "C" {
14 #endif
15 
16 #ifndef __ASSEMBLER__
17 #include <OS.h>
18 
19 /* TOS calls use 16 bit param alignment, so we must generate the calls ourselves.
20  * We then use asm macros, one for each possible arg type and count.
21  * cf. how mint does it in sys/mint/arch/asm_misc.h
22  */
23 //#if __GNUC__ >= 3
24 #define TOS_CLOBBER_LIST "d1", "d2", "a0", "a1", "a2"
25 //#else
26 //#error fixme
27 //#endif
28 
29 /* void (no) arg */
30 #define toscallV(trapnr, callnr)				\
31 ({												\
32 	register int32 retvalue __asm__("d0");		\
33 												\
34 	__asm__ volatile							\
35 	("/* toscall(" #trapnr ", " #callnr ") */\n"	\
36 	"	move.w	%[calln],-(%%sp)\n"				\
37 	"	trap	%[trapn]\n"						\
38 	"	add.l	#2,%%sp\n"						\
39 	: "=r"(retvalue)	/* output */			\
40 	: [trapn]"i"(trapnr),[calln]"i"(callnr) 	\
41 									/* input */	\
42 	: TOS_CLOBBER_LIST /* clobbered regs */		\
43 	);											\
44 	retvalue;									\
45 })
46 
47 #define toscallW(trapnr, callnr, p1)			\
48 ({												\
49 	register int32 retvalue __asm__("d0");		\
50 	int16 _p1 = (int16)(p1);					\
51 												\
52 	__asm__ volatile							\
53 	("/* toscall(" #trapnr ", " #callnr ") */\n"	\
54 	"	move.w	%1,-(%%sp) \n"					\
55 	"	move.w	%[calln],-(%%sp)\n"				\
56 	"	trap	%[trapn]\n"						\
57 	"	add.l	#4,%%sp \n"						\
58 	: "=r"(retvalue)			/* output */	\
59 	: "r"(_p1),						/* input */	\
60 	  [trapn]"i"(trapnr),[calln]"i"(callnr)		\
61 	: TOS_CLOBBER_LIST /* clobbered regs */		\
62 	);											\
63 	retvalue;									\
64 })
65 
66 #define toscallL(trapnr, callnr, p1)			\
67 ({							\
68 	register int32 retvalue __asm__("d0");		\
69 	int32 _p1 = (int32)(p1);			\
70 							\
71 	__asm__ volatile				\
72 	(/*"; toscall(" #trapnr ", " #callnr ")"*/"\n	\
73 		move.l	%1,-(%%sp) \n			\
74 		move.w	%[calln],-(%%sp)\n		\
75 		trap	%[trapn]\n			\
76 		add.l	#6,%%sp \n "			\
77 	: "=r"(retvalue)	/* output */		\
78 	: "r"(_p1),			/* input */	\
79 	  [trapn]"i"(trapnr),[calln]"i"(callnr)		\
80 	: TOS_CLOBBER_LIST /* clobbered regs */		\
81 	);						\
82 	retvalue;					\
83 })
84 
85 #define toscallWW(trapnr, callnr, p1, p2)		\
86 ({							\
87 	register int32 retvalue __asm__("d0");		\
88 	int16 _p1 = (int16)(p1);			\
89 	int16 _p2 = (int16)(p2);			\
90 							\
91 	__asm__ volatile				\
92 	(/*"; toscall(" #trapnr ", " #callnr ")"*/"\n	\
93 		move.w	%2,-(%%sp) \n			\
94 		move.w	%1,-(%%sp) \n			\
95 		move.w	%[calln],-(%%sp)\n		\
96 		trap	%[trapn]\n			\
97 		add.l	#6,%%sp \n "			\
98 	: "=r"(retvalue)	/* output */		\
99 	: "r"(_p1), "r"(_p2),		/* input */	\
100 	  [trapn]"i"(trapnr),[calln]"i"(callnr)		\
101 	: TOS_CLOBBER_LIST /* clobbered regs */		\
102 	);						\
103 	retvalue;					\
104 })
105 
106 #define toscallWLWWWL(trapnr, callnr, p1, p2, p3, p4, p5, p6)	\
107 ({							\
108 	register int32 retvalue __asm__("d0");		\
109 	int16 _p1 = (int16)(p1);			\
110 	int32 _p2 = (int32)(p2);			\
111 	int16 _p3 = (int16)(p3);			\
112 	int16 _p4 = (int16)(p4);			\
113 	int16 _p5 = (int16)(p5);			\
114 	int32 _p6 = (int32)(p6);			\
115 							\
116 	__asm__ volatile				\
117 	(/*"; toscall(" #trapnr ", " #callnr ")"*/"\n	\
118 		move.l	%6,-(%%sp) \n			\
119 		move.w	%5,-(%%sp) \n			\
120 		move.w	%4,-(%%sp) \n			\
121 		move.w	%3,-(%%sp) \n			\
122 		move.l	%2,-(%%sp) \n			\
123 		move.w	%1,-(%%sp) \n			\
124 		move.w	%[calln],-(%%sp)\n		\
125 		trap	%[trapn]\n			\
126 		add.l	#18,%%sp \n "			\
127 	: "=r"(retvalue)	/* output */		\
128 	: "r"(_p1), "r"(_p2),				\
129 	  "r"(_p3), "r"(_p4),				\
130 	  "r"(_p5), "r"(_p6),		/* input */	\
131 	  [trapn]"i"(trapnr),[calln]"i"(callnr)		\
132 	: TOS_CLOBBER_LIST /* clobbered regs */		\
133 	);						\
134 	retvalue;					\
135 })
136 
137 #define toscallLLWWWWW(trapnr, callnr, p1, p2, p3, p4, p5, p6, p7)	\
138 ({							\
139 	register int32 retvalue __asm__("d0");		\
140 	int32 _p1 = (int32)(p1);			\
141 	int32 _p2 = (int32)(p2);			\
142 	int16 _p3 = (int16)(p3);			\
143 	int16 _p4 = (int16)(p4);			\
144 	int16 _p5 = (int16)(p5);			\
145 	int16 _p6 = (int16)(p6);			\
146 	int16 _p7 = (int16)(p7);			\
147 							\
148 	__asm__ volatile				\
149 	(/*"; toscall(" #trapnr ", " #callnr ")"*/"\n	\
150 		move.w	%7,-(%%sp) \n			\
151 		move.w	%6,-(%%sp) \n			\
152 		move.w	%5,-(%%sp) \n			\
153 		move.w	%4,-(%%sp) \n			\
154 		move.w	%3,-(%%sp) \n			\
155 		move.l	%2,-(%%sp) \n			\
156 		move.l	%1,-(%%sp) \n			\
157 		move.w	%[calln],-(%%sp)\n		\
158 		trap	%[trapn]\n			\
159 		add.l	#18,%%sp \n "			\
160 	: "=r"(retvalue)	/* output */		\
161 	: "r"(_p1), "r"(_p2),				\
162 	  "r"(_p3), "r"(_p4),				\
163 	  "r"(_p5), "r"(_p6),				\
164 	  "r"(_p7),					/* input */	\
165 	  [trapn]"i"(trapnr),[calln]"i"(callnr)		\
166 	: TOS_CLOBBER_LIST /* clobbered regs */		\
167 	);						\
168 	retvalue;					\
169 })
170 
171 /* pointer versions */
172 #define toscallP(trapnr, callnr, a) toscallL(trapnr, callnr, (int32)a)
173 #define toscallWPWWWL(trapnr, callnr, p1, p2, p3, p4, p5, p6) \
174 	toscallWLWWWL(trapnr, callnr, p1, (int32)p2, p3, p4, p5, p6)
175 #define toscallPLWWWWW(trapnr, callnr, p1, p2, p3, p4, p5, p6, p7)		\
176 	toscallLLWWWWW(trapnr, callnr, (int32)p1, (int32)p2, p3, p4, p5, p6, p7)
177 
178 
179 
180 #endif /* __ASSEMBLER__ */
181 
182 #ifdef __ASSEMBLER__
183 #define _TOSV_P(a) a
184 #define _TOSV_L(a) a
185 #define _TOSV_W(a) a
186 #define _TOSV_B(a) a
187 #else
188 #define _TOSV_P(a) ((void **)a)
189 #define _TOSV_L(a) ((uint32 *)a)
190 #define _TOSV_W(a) ((uint16 *)a)
191 #define _TOSV_B(a) ((uint8 *)a)
192 #endif
193 
194 /*
195  * TOS Variables
196  * only relevant ones,
197  * see toshyp.atari.org/003004.htm
198  */
199 #define TOSVAR_autopath	_TOSV_P(0x4ca)
200 #define TOSVAR_bootdev	_TOSV_W(0x446)
201 #define TOSVAR_dskbufp	_TOSV_P(0x4c6)
202 #define TOSVAR_drvbits	_TOSV_L(0x4c2)
203 #define TOSVAR_frclock	_TOSV_L(0x466)
204 #define TOSVAR_hz_200	_TOSV_L(0x4ba)
205 #define TOSVAR_membot	_TOSV_L(0x432)
206 #define TOSVAR_memtop	_TOSV_L(0x436)
207 #define TOSVAR_nflops	_TOSV_W(0x4a6)
208 #define TOSVAR_p_cookies	_TOSV_P(0x5A0)
209 #define TOSVAR_sysbase	_TOSV_P(0x4f2)
210 #define TOSVAR_timr_ms	_TOSV_W(0x442)
211 #define TOSVAR_v_bas_ad	_TOSV_P(0x44e)
212 #define TOSVAR_vbclock	_TOSV_L(0x462)
213 #define TOSVARphystop	_TOSV_L(0x42e)
214 #define TOSVARramtop	_TOSV_L(0x5a4)
215 #define TOSVARramvalid	_TOSV_L(0x5a8)
216 #define TOSVARramvalid_MAGIC 0x1357bd13
217 
218 
219 #define BIOS_TRAP	13
220 #define XBIOS_TRAP	14
221 #define GEMDOS_TRAP	1
222 
223 /*
224  * Atari BIOS calls
225  */
226 
227 /* those are used by asm code too */
228 
229 #define DEV_PRINTER	0
230 #define DEV_AUX	1
231 #define DEV_CON	2
232 #define DEV_CONSOLE	2
233 #define DEV_MIDI	3
234 #define DEV_IKBD	4
235 #define DEV_RAW	5
236 
237 #define K_RSHIFT	0x01
238 #define K_LSHIFT	0x02
239 #define K_CTRL	0x04
240 #define K_ALT	0x08
241 #define K_CAPSLOCK	0x10
242 #define K_CLRHOME	0x20
243 #define K_INSERT	0x40
244 
245 #define RW_READ			0x00
246 #define RW_WRITE		0x01
247 #define RW_NOMEDIACH	0x02
248 #define RW_NORETRY		0x04
249 #define RW_NOTRANSLATE	0x08
250 
251 #ifndef __ASSEMBLER__
252 
253 //extern int32 bios(uint16 nr, ...);
254 
255 // cf. http://www.fortunecity.com/skyscraper/apple/308/html/bios.htm
256 
257 struct tos_bpb {
258 	int16 recsiz;
259 	int16 clsiz;
260 	int16 clsizb;
261 	int16 rdlen;
262 	int16 fsiz;
263 	int16 fatrec;
264 	int16 datrec;
265 	int16 numcl;
266 	int16 bflags;
267 };
268 
269 struct tos_pun_info {
270 	int16 puns;
271 	uint8 pun[16];
272 	int32 part_start[16]; // unsigned ??
273 	uint32 p_cookie;
274 	struct tos_pun_info *p_cooptr; // points to itself
275 	uint16 p_version;
276 	uint16 p_max_sector;
277 	int32 reserved[16];
278 };
279 #define PUN_INFO ((struct tos_pun_info *)0x516L)
280 
281 
282 //#define Getmpb() toscallV(BIOS_TRAP, 0)
283 #define Bconstat(dev) toscallW(BIOS_TRAP, 1, (uint16)dev)
284 #define Bconin(dev) toscallW(BIOS_TRAP, 2, (uint16)dev)
285 #define Bconout(dev, chr) toscallWW(BIOS_TRAP, 3, (uint16)dev, (uint16)chr)
286 #define Rwabs(mode, buf, count, recno, dev, lrecno) toscallWPWWWL(BIOS_TRAP, 4, (int16)mode, (void *)buf, (int16)count, (int16)recno, (uint16)dev, (int32)lrecno)
287 //#define Setexc() toscallV(BIOS_TRAP, 5, )
288 #define Tickcal() toscallV(BIOS_TRAP, 6)
289 #define Getbpb(dev) (struct tos_bpb *)toscallW(BIOS_TRAP, 7, (uint16)dev)
290 #define Bcostat(dev) toscallW(BIOS_TRAP, 8, (uint16)dev)
291 #define Mediach(dev) toscallW(BIOS_TRAP, 9, (int16)dev)
292 #define Drvmap() (uint32)toscallV(BIOS_TRAP, 10)
293 #define Kbshift(mode) toscallW(BIOS_TRAP, 11, (uint16)mode)
294 
295 /* handy shortcut */
296 static inline int Bconput(int16 handle, const char *string)
297 {
298 	int i, col, err;
299 	for (i = 0, col = 0; string[i]; i++, col++) {
300 		if (string[i] == '\n') {
301 			Bconout(handle, '\r');
302 			col = 0;
303 		}
304 		/* hard wrap at 80 col as the ST console emulation doesn't do this. */
305 		if (col == 80) {
306 			Bconout(handle, '\r');
307 			Bconout(handle, '\n');
308 			col = 0;
309 		}
310 		err = Bconout(handle, string[i]);
311 		if (err < 0)
312 			break;
313 	}
314 	return i;
315 }
316 
317 static inline int Bconputs(int16 handle, const char *string)
318 {
319 	int err = Bconput(handle, string);
320 	Bconout(handle, '\r');
321 	Bconout(handle, '\n');
322 	return err;
323 }
324 
325 #endif /* __ASSEMBLER__ */
326 
327 /*
328  * Atari XBIOS calls
329  */
330 
331 #define IM_DISABLE	0
332 #define IM_RELATIVE	1
333 #define IM_ABSOLUTE	2
334 #define IM_KEYCODE	4
335 
336 #define NVM_READ	0
337 #define NVM_WRITE	1
338 #define NVM_RESET	2
339 // unofficial
340 #define NVM_R_SEC	0
341 #define NVM_R_MIN	2
342 #define NVM_R_HOUR	4
343 #define NVM_R_MDAY	7
344 #define NVM_R_MON	8	/*+- 1*/
345 #define NVM_R_YEAR	9
346 #define NVM_R_VIDEO	29
347 
348 #define VM_INQUIRE	-1
349 
350 #ifndef __ASSEMBLER__
351 
352 //extern int32 xbios(uint16 nr, ...);
353 
354 
355 #define Initmous(mode, param, vec) toscallWPP(XBIOS_TRAP, 0, (int16)mode, (void *)param, (void *)vec)
356 #define Physbase() (void *)toscallV(XBIOS_TRAP, 2)
357 #define Logbase() (void *)toscallV(XBIOS_TRAP, 3)
358 //#define Getrez() toscallV(XBIOS_TRAP, 4)
359 #define Setscreen(log, phys, mode) toscallPPW(XBIOS_TRAP, 5, (void *)log, (void *)phys, (int16)mode)
360 #define VsetScreen(log, phys, mode, modecode) toscallPPW(XBIOS_TRAP, 5, (void *)log, (void *)phys, (int16)mode)
361 #define Floprd(buf, dummy, dev, sect, track, side, count) toscallPLWWWWW(XBIOS_TRAP, 8, (void *)buf, (int32)dummy, (int16)dev, (int16)sect, (int16)track, (int16)side, (int16)count)
362 //#define Mfpint() toscallV(XBIOS_TRAP, 13, )
363 #define Rsconf(speed, flow, ucr, rsr, tsr, scr) toscallWWWWWW(XBIOS_TRAP, 15, (int16)speed, (int16)flow, (int16)ucr, (int16)rsr, (int16)tsr, (int16)scr)
364 //#define Keytbl(unshift, shift, caps) (KEYTAB *)toscallPPP(XBIOS_TRAP, 16, (char *)unshift, (char *)shift, (char *)caps)
365 #define Random() toscallV(XBIOS_TRAP, 17)
366 #define Gettime() (uint32)toscallV(XBIOS_TRAP, 23)
367 #define Jdisint(intno) toscallW(XBIOS_TRAP, 26, (int16)intno)
368 #define Jenabint(intno) toscallW(XBIOS_TRAP, 27, (int16)intno)
369 #define Supexec(func) toscallP(XBIOS_TRAP, 38, (void *)func)
370 //#define Puntaes() toscallV(XBIOS_TRAP, 39)
371 #define DMAread(sect, count, buf, dev) toscallLWPW(XBIOS_TRAP, 42, (int32)sect, (int16)count, (void *)buf, (int16)dev)
372 #define DMAwrite(sect, count, buf, dev) toscallWPLW(XBIOS_TRAP, 43, (int32)sect, (int16)count, (void *)buf, (int16)dev)
373 #define NVMaccess(op, start, count, buffer) toscallWWWP(XBIOS_TRAP, 46, (int16)op, (int16)start, (int16)count, (char *)buffer)
374 #define VsetMode(mode) toscallW(XBIOS_TRAP, 88, (int16)mode)
375 #define VgetMonitor() toscallV(XBIOS_TRAP, 89)
376 #define Locksnd() toscallV(XBIOS_TRAP, 128)
377 #define Unlocksnd() toscallV(XBIOS_TRAP, 129)
378 
379 #endif /* __ASSEMBLER__ */
380 
381 /*
382  * Atari GEMDOS calls
383  */
384 
385 #define SUP_USER		0
386 #define SUP_SUPER		1
387 
388 
389 #ifdef __ASSEMBLER__
390 #define SUP_SET			0
391 #define SUP_INQUIRE		1
392 #else
393 
394 //extern int32 gemdos(uint16 nr, ...);
395 
396 #define SUP_SET			(void *)0
397 #define SUP_INQUIRE		(void *)1
398 
399 // official names
400 #define Pterm0() toscallV(GEMDOS_TRAP, 0)
401 #define Cconin() toscallV(GEMDOS_TRAP, 1)
402 #define Super(s) toscallP(GEMDOS_TRAP, 0x20, s)
403 #define Pterm(retcode) toscallW(GEMDOS_TRAP, 76, (int16)retcode)
404 
405 #endif /* __ASSEMBLER__ */
406 
407 #ifndef __ASSEMBLER__
408 
409 /*
410  * MetaDOS XBIOS calls
411  */
412 
413 //#define _DISABLE	0
414 
415 #ifndef __ASSEMBLER__
416 
417 #define Metainit(buf) toscallP(XBIOS_TRAP, 48, (void *)buf)
418 #define Metaopen(drive, p) toscall>P(XBIOS_TRAP, 48, (void *)buf)
419 #define Metaclose(drive) toscallW(XBIOS_TRAP, 50, (int16)drive)
420 #define Metagettoc(drive, flag, p) toscallW(XBIOS_TRAP, 62, (int16)drive, (int16)flag, (void *)p)
421 #define Metadiscinfo(drive, p) toscallWP(XBIOS_TRAP, 63, (int16)drive, (void *)p)
422 #define Metaioctl(drive, magic, op, buf) toscallWLWP(XBIOS_TRAP, 55, (int16)drive, (int32)magic, (int16)op, )
423 //#define Meta(drive) toscallW(XBIOS_TRAP, 50, (int16)drive)
424 //#define Meta(drive) toscallW(XBIOS_TRAP, 50, (int16)drive)
425 //#define Meta(drive) toscallW(XBIOS_TRAP, 50, (int16)drive)
426 
427 #endif /* __ASSEMBLER__ */
428 
429 /*
430  * XHDI support
431  * see http://toshyp.atari.org/010008.htm
432  */
433 
434 #define XHDI_COOKIE 'XHDI'
435 #define XHDI_MAGIC 0x27011992
436 //#define XHDI_CLOBBER_LIST "" /* only d0 */
437 #define XHDI_CLOBBER_LIST "d1", "d2", "a0", "a1", "a2"
438 
439 #define XH_TARGET_STOPPABLE		0x00000001L
440 #define XH_TARGET_REMOVABLE		0x00000002L
441 #define XH_TARGET_LOCKABLE		0x00000004L
442 #define XH_TARGET_EJECTABLE		0x00000008L
443 #define XH_TARGET_LOCKED		0x20000000L
444 #define XH_TARGET_STOPPED		0x40000000L
445 #define XH_TARGET_RESERVED		0x80000000L
446 
447 #ifndef __ASSEMBLER__
448 
449 /* pointer to the XHDI dispatch function */
450 extern void *gXHDIEntryPoint;
451 
452 extern status_t init_xhdi(void);
453 
454 /* movem should not needed, but just to be safe. */
455 
456 /* void (no) arg */
457 #define xhdicallV(callnr)						\
458 ({												\
459 	register int32 retvalue __asm__("d0");		\
460 												\
461 	__asm__ volatile							\
462 	("/* xhdicall(" #callnr ") */\n"			\
463 	"	movem.l	%%d3-%%d7/%%a3-%%a6,-(%%sp)\n"		\
464 	"	move.w	%[calln],-(%%sp)\n"				\
465 	"	jbsr	(%[entry])\n"						\
466 	"	add.l	#2,%%sp\n"						\
467 	"	movem.l	(%%sp)+,%%d3-%%d7/%%a3-%%a6\n"		\
468 	: "=r"(retvalue)	/* output */			\
469 	:							/* input */		\
470 	  [entry]"a"(gXHDIEntryPoint),				\
471 	  [calln]"i"(callnr)						\
472 	: XHDI_CLOBBER_LIST /* clobbered regs */	\
473 	);											\
474 	retvalue;									\
475 })
476 
477 #define xhdicallW(callnr, p1)					\
478 ({												\
479 	register int32 retvalue __asm__("d0");		\
480 	int16 _p1 = (int16)(p1);					\
481 												\
482 	__asm__ volatile							\
483 	("/* xhdicall(" #callnr ") */\n"			\
484 	"	movem.l	%%d3-%%d7/%%a3-%%a6,-(%%sp)\n"		\
485 	"	move.w	%1,-(%%sp) \n"					\
486 	"	move.w	%[calln],-(%%sp)\n"				\
487 	"	jbsr	(%[entry])\n"						\
488 	"	add.l	#4,%%sp \n"						\
489 	"	movem.l	(%%sp)+,%%d3-%%d7/%%a3-%%a6\n"		\
490 	: "=r"(retvalue)	/* output */			\
491 	: "r"(_p1),			/* input */				\
492 	  [entry]"a"(gXHDIEntryPoint),				\
493 	  [calln]"i"(callnr)						\
494 	: XHDI_CLOBBER_LIST /* clobbered regs */	\
495 	);											\
496 	retvalue;									\
497 })
498 
499 #define xhdicallWWL(callnr, p1, p2, p3)					\
500 ({												\
501 	register int32 retvalue __asm__("d0");		\
502 	int16 _p1 = (int16)(p1);					\
503 	int16 _p2 = (int16)(p2);					\
504 	int32 _p3 = (int32)(p3);					\
505 												\
506 	__asm__ volatile							\
507 	("/* xhdicall(" #callnr ") */\n"			\
508 	"	movem.l	%%d3-%%d7/%%a3-%%a6,-(%%sp)\n"		\
509 	"	move.l	%3,-(%%sp) \n"					\
510 	"	move.w	%2,-(%%sp) \n"					\
511 	"	move.w	%1,-(%%sp) \n"					\
512 	"	move.w	%[calln],-(%%sp)\n"				\
513 	"	jbsr	(%[entry])\n"						\
514 	"	add.l	#10,%%sp \n"						\
515 	"	movem.l	(%%sp)+,%%d3-%%d7/%%a3-%%a6\n"		\
516 	: "=r"(retvalue)	/* output */			\
517 	: "r"(_p1), "r"(_p2),				\
518 	  "r"(_p3),			/* input */	\
519 	  [entry]"a"(gXHDIEntryPoint),				\
520 	  [calln]"i"(callnr)						\
521 	: XHDI_CLOBBER_LIST /* clobbered regs */	\
522 	);											\
523 	retvalue;									\
524 })
525 
526 #define xhdicallWWLL(callnr, p1, p2, p3, p4)					\
527 ({												\
528 	register int32 retvalue __asm__("d0");		\
529 	int16 _p1 = (int16)(p1);					\
530 	int16 _p2 = (int16)(p2);					\
531 	int32 _p3 = (int32)(p3);					\
532 	int32 _p4 = (int32)(p4);					\
533 												\
534 	__asm__ volatile							\
535 	("/* xhdicall(" #callnr ") */\n"			\
536 	"	movem.l	%%d3-%%d7/%%a3-%%a6,-(%%sp)\n"		\
537 	"	move.l	%4,-(%%sp) \n"					\
538 	"	move.l	%3,-(%%sp) \n"					\
539 	"	move.w	%2,-(%%sp) \n"					\
540 	"	move.w	%1,-(%%sp) \n"					\
541 	"	move.w	%[calln],-(%%sp)\n"				\
542 	"	jbsr	(%[entry])\n"						\
543 	"	add.l	#14,%%sp \n"						\
544 	"	movem.l	(%%sp)+,%%d3-%%d7/%%a3-%%a6\n"		\
545 	: "=r"(retvalue)	/* output */			\
546 	: "r"(_p1), "r"(_p2),				\
547 	  "r"(_p3), "r"(_p4),	/* input */	\
548 	  [entry]"a"(gXHDIEntryPoint),				\
549 	  [calln]"i"(callnr)						\
550 	: XHDI_CLOBBER_LIST /* clobbered regs */	\
551 	);											\
552 	retvalue;									\
553 })
554 
555 #define xhdicallWWLLL(callnr, p1, p2, p3, p4, p5)					\
556 ({												\
557 	register int32 retvalue __asm__("d0");		\
558 	int16 _p1 = (int16)(p1);					\
559 	int16 _p2 = (int16)(p2);					\
560 	int32 _p3 = (int32)(p3);					\
561 	int32 _p4 = (int32)(p4);					\
562 	int32 _p5 = (int32)(p5);					\
563 												\
564 	__asm__ volatile							\
565 	("/* xhdicall(" #callnr ") */\n"			\
566 	"	movem.l	%%d3-%%d7/%%a3-%%a6,-(%%sp)\n"		\
567 	"	move.l	%5,-(%%sp) \n"					\
568 	"	move.l	%4,-(%%sp) \n"					\
569 	"	move.l	%3,-(%%sp) \n"					\
570 	"	move.w	%2,-(%%sp) \n"					\
571 	"	move.w	%1,-(%%sp) \n"					\
572 	"	move.w	%[calln],-(%%sp)\n"				\
573 	"	jbsr	(%[entry])\n"						\
574 	"	add.l	#18,%%sp \n"						\
575 	"	movem.l	(%%sp)+,%%d3-%%d7/%%a3-%%a6\n"		\
576 	: "=r"(retvalue)	/* output */			\
577 	: "r"(_p1), "r"(_p2),				\
578 	  "r"(_p3), "r"(_p4),				\
579 	  "r"(_p5),			/* input */	\
580 	  [entry]"a"(gXHDIEntryPoint),				\
581 	  [calln]"i"(callnr)						\
582 	: XHDI_CLOBBER_LIST /* clobbered regs */	\
583 	);											\
584 	retvalue;									\
585 })
586 
587 #define xhdicallWLLLL(callnr, p1, p2, p3, p4, p5)					\
588 ({												\
589 	register int32 retvalue __asm__("d0");		\
590 	int16 _p1 = (int16)(p1);					\
591 	int32 _p2 = (int32)(p2);					\
592 	int32 _p3 = (int32)(p3);					\
593 	int32 _p4 = (int32)(p4);					\
594 	int32 _p5 = (int32)(p5);					\
595 												\
596 	__asm__ volatile							\
597 	("/* xhdicall(" #callnr ") */\n"			\
598 	"	movem.l	%%d3-%%d7/%%a3-%%a6,-(%%sp)\n"		\
599 	"	move.l	%5,-(%%sp) \n"					\
600 	"	move.l	%4,-(%%sp) \n"					\
601 	"	move.l	%3,-(%%sp) \n"					\
602 	"	move.l	%2,-(%%sp) \n"					\
603 	"	move.w	%1,-(%%sp) \n"					\
604 	"	move.w	%[calln],-(%%sp)\n"				\
605 	"	jbsr	(%[entry])\n"						\
606 	"	add.l	#20,%%sp \n"						\
607 	"	movem.l	(%%sp)+,%%d3-%%d7/%%a3-%%a6\n"		\
608 	: "=r"(retvalue)	/* output */			\
609 	: "r"(_p1), "r"(_p2),				\
610 	  "r"(_p3), "r"(_p4),				\
611 	  "r"(_p5),			/* input */	\
612 	  [entry]"a"(gXHDIEntryPoint),				\
613 	  [calln]"i"(callnr)						\
614 	: XHDI_CLOBBER_LIST /* clobbered regs */	\
615 	);											\
616 	retvalue;									\
617 })
618 
619 #define xhdicallWWWLWL(callnr, p1, p2, p3, p4, p5, p6)					\
620 ({												\
621 	register int32 retvalue __asm__("d0");		\
622 	int16 _p1 = (int16)(p1);					\
623 	int16 _p2 = (int16)(p2);					\
624 	int16 _p3 = (int16)(p3);					\
625 	int32 _p4 = (int32)(p4);					\
626 	int16 _p5 = (int16)(p5);					\
627 	int32 _p6 = (int32)(p6);					\
628 												\
629 	__asm__ volatile							\
630 	("/* xhdicall(" #callnr ") */\n"			\
631 	"	movem.l	%%d3-%%d7/%%a3-%%a6,-(%%sp)\n"		\
632 	"	move.l	%6,-(%%sp) \n"					\
633 	"	move.w	%5,-(%%sp) \n"					\
634 	"	move.l	%4,-(%%sp) \n"					\
635 	"	move.w	%3,-(%%sp) \n"					\
636 	"	move.w	%2,-(%%sp) \n"					\
637 	"	move.w	%1,-(%%sp) \n"					\
638 	"	move.w	%[calln],-(%%sp)\n"				\
639 	"	jbsr	(%[entry])\n"						\
640 	"	add.l	#18,%%sp \n"						\
641 	"	movem.l	(%%sp)+,%%d3-%%d7/%%a3-%%a6\n"		\
642 	: "=r"(retvalue)	/* output */			\
643 	: "r"(_p1), "r"(_p2),				\
644 	  "r"(_p3), "r"(_p4),				\
645 	  "r"(_p5), "r"(_p6),		/* input */	\
646 	  [entry]"a"(gXHDIEntryPoint),				\
647 	  [calln]"i"(callnr)						\
648 	: XHDI_CLOBBER_LIST /* clobbered regs */	\
649 	);											\
650 	retvalue;									\
651 })
652 
653 #define xhdicallWWP(callnr, p1, p2, p3) \
654 	xhdicallWWL(callnr, p1, p2, (int32)(p3))
655 #define xhdicallWWPP(callnr, p1, p2, p3, p4) \
656 	xhdicallWWLL(callnr, p1, p2, (int32)(p3), (int32)(p4))
657 #define xhdicallWWPPP(callnr, p1, p2, p3, p4, p5) \
658 	xhdicallWWLLL(callnr, p1, p2, (int32)(p3), (int32)(p4), (int32)(p5))
659 #define xhdicallWPPPP(callnr, p1, p2, p3, p4, p5) \
660 	xhdicallWLLLL(callnr, p1, (uint32)(p2), (int32)(p3), (int32)(p4), (int32)(p5))
661 #define xhdicallWWWLWP(callnr, p1, p2, p3, p4, p5, p6) \
662 	xhdicallWWWLWL(callnr, p1, p2, p3, (uint32)(p4), p5, (uint32)(p6))
663 #define xhdicallWWWPWP(callnr, p1, p2, p3, p4, p5, p6) \
664 	xhdicallWWWLWL(callnr, p1, p2, p3, (int32)(p4), p5, (uint32)(p6))
665 
666 #define XHGetVersion() (uint16)xhdicallV(0)
667 #define XHInqTarget(major, minor, blocksize, flags, pname) xhdicallWWPPP(1, (uint16)major, (uint16)minor, (uint32 *)(blocksize), (uint32 *)flags, (char *)pname)
668 //XHReserve 2
669 //#define XHLock() 3
670 //#define XHStop() 4
671 #define XHEject(major, minor, doeject, key) xhdicallWWWW(5, (uint16)major, (uint16)minor, (uint16)doeject, (uint16)key)
672 #define XHDrvMap() xhdicallV(6)
673 #define XHInqDev(dev,major,minor,startsect,bpb) xhdicallWPPPP(7,dev,(uint16 *)major,(uint16 *)minor,(uint32 *)startsect,(struct tos_bpb *)bpb)
674 //XHInqDriver 8
675 //XHNewCookie 9
676 #define XHReadWrite(major, minor, rwflags, recno, count, buf) xhdicallWWWLWP(10, (uint16)major, (uint16)minor, (uint16)rwflags, (uint32)recno, (uint16)count, (void *)buf)
677 #define XHInqTarget2(major, minor, bsize, flags, pname, pnlen) xhdicallWWPPPW(11, (uint16)major, (uint16)minor, (uint32 *)bsize, (uint32 *)flags, (char *)pname, (uint16)pnlen)
678 //XHInqDev2 12
679 //XHDriverSpecial 13
680 #define XHGetCapacity(major, minor, blocks, blocksize) xhdicallWWPP(14, (uint16)major, (uint16)minor, (uint32 *)blocks, (uint32 *)blocksize)
681 //#define XHMediumChanged() 15
682 //XHMiNTInfo 16
683 //XHDosLimits 17
684 #define XHLastAccess(major, minor, ms) xhdicallWWP(18, major, minor, (uint32 *)ms)
685 //SHReaccess 19
686 
687 #endif /* __ASSEMBLER__ */
688 
689 
690 /*
691  * error mapping
692  * in debug.c
693  */
694 
695 extern status_t toserror(int32 err);
696 extern status_t xhdierror(int32 err);
697 extern void dump_tos_cookies(void);
698 
699 /*
700  * Cookie Jar access
701  */
702 
703 typedef struct tos_cookie {
704 	uint32 cookie;
705 	union {
706 		int32 ivalue;
707 		void *pvalue;
708 	};
709 } tos_cookie;
710 
711 #define COOKIE_JAR (*((const tos_cookie **)TOSVAR_p_cookies))
712 
713 static inline const tos_cookie *tos_find_cookie(uint32 what)
714 {
715 	const tos_cookie *c = COOKIE_JAR;
716 	while (c && (c->cookie)) {
717 		if (c->cookie == what)
718 			return c;
719 		c++;
720 	}
721 	return NULL;
722 }
723 
724 /*
725  * OSHEADER access
726  */
727 
728 typedef struct tos_osheader {
729 	uint16 os_entry;
730 	uint16 os_version;
731 	void *reseth;
732 	struct tos_osheader *os_beg;
733 	void *os_end;
734 	void *os_rsv1;
735 	void *os_magic;
736 	uint32 os_date;
737 	uint32 os_conf;
738 	//uint32/16? os_dosdate;
739 	// ... more stuff we don't care about
740 } tos_osheader;
741 
742 #define tos_sysbase ((const struct tos_osheader **)0x4F2)
743 
744 static inline const struct tos_osheader *tos_get_osheader()
745 {
746 	if (!(*tos_sysbase))
747 		return NULL;
748 	return (*tos_sysbase)->os_beg;
749 }
750 
751 #endif /* __ASSEMBLER__ */
752 
753 /*
754  * ARAnyM Native Features
755  */
756 
757 #define NF_COOKIE	0x5f5f4e46L	//'__NF'
758 #define NF_MAGIC	0x20021021L
759 
760 #ifndef __ASSEMBLER__
761 
762 typedef struct {
763 	uint32 magic;
764 	uint32 (*nfGetID) (const char *);
765 	int32 (*nfCall) (uint32 ID, ...);
766 } NatFeatCookie;
767 
768 extern NatFeatCookie *gNatFeatCookie;
769 extern uint32 gDebugPrintfNatFeatID;
770 
771 static inline NatFeatCookie *nat_features(void)
772 {
773 	const struct tos_cookie *c;
774 	if (gNatFeatCookie == (void *)-1)
775 		return NULL;
776 	if (gNatFeatCookie)
777 		return gNatFeatCookie;
778 	c = tos_find_cookie(NF_COOKIE);
779 	if (c) {
780 		gNatFeatCookie = (NatFeatCookie *)c->pvalue;
781 		if (gNatFeatCookie && gNatFeatCookie->magic == NF_MAGIC) {
782 			return gNatFeatCookie;
783 		}
784 	}
785 	gNatFeatCookie = (NatFeatCookie *)-1;
786 	return NULL;
787 }
788 
789 extern status_t init_nat_features(void);
790 
791 static inline int32 nat_feat_getid(const char *name)
792 {
793 	NatFeatCookie *c = nat_features();
794 	if (!c)
795 		return 0;
796 	return c->nfGetID(name);
797 }
798 
799 #define nat_feat_call(id, code, a...) \
800 ({						\
801 	int32 ret = -1;				\
802 	NatFeatCookie *c = nat_features();	\
803 	if (c)					\
804 		ret = c->nfCall(id | code, a);	\
805 	ret;					\
806 })
807 
808 extern void nat_feat_debugprintf(const char *str);
809 
810 #endif /* __ASSEMBLER__ */
811 
812 /*
813  * Drive API used by the bootsector
814  * gBootDriveAPI is set to one of those
815  * not all are implemented
816  */
817 #define ATARI_BOOT_DRVAPI_UNKNOWN 0
818 #define ATARI_BOOT_DRVAPI_FLOPPY  1   // Floprd()
819 #define ATARI_BOOT_DRVAPI_BIOS    2   // Rwabs()
820 #define ATARI_BOOT_DRVAPI_XBIOS   3   // DMAread()
821 #define ATARI_BOOT_DRVAPI_XHDI    4   // XHReadWrite()
822 #define ATARI_BOOT_DRVAPI_METADOS 5   // Metaread()
823 
824 #ifdef __cplusplus
825 }
826 #endif
827 
828 #endif /* _TOSCALLS_H */
829