xref: /haiku/src/system/boot/platform/atari_m68k/toscalls.h (revision 8a04709a1d4086fecf352cc079c97e394f1a4ba3)
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 /* pointer versions */
138 #define toscallP(trapnr, callnr, a) toscallL(trapnr, callnr, (int32)a)
139 #define toscallWPWWWL(trapnr, callnr, p1, p2, p3, p4, p5, p6) \
140 	toscallWLWWWL(trapnr, callnr, p1, (int32)p2, p3, p4, p5, p6)
141 
142 
143 
144 
145 #endif /* __ASSEMBLER__ */
146 
147 #define BIOS_TRAP	13
148 #define XBIOS_TRAP	14
149 #define GEMDOS_TRAP	1
150 
151 /*
152  * Atari BIOS calls
153  */
154 
155 /* those are used by asm code too */
156 
157 #define DEV_PRINTER	0
158 #define DEV_AUX	1
159 #define DEV_CON	2
160 #define DEV_CONSOLE	2
161 #define DEV_MIDI	3
162 #define DEV_IKBD	4
163 #define DEV_RAW	5
164 
165 #define K_RSHIFT	0x01
166 #define K_LSHIFT	0x02
167 #define K_CTRL	0x04
168 #define K_ALT	0x08
169 #define K_CAPSLOCK	0x10
170 #define K_CLRHOME	0x20
171 #define K_INSERT	0x40
172 
173 #define RW_READ			0x00
174 #define RW_WRITE		0x01
175 #define RW_NOMEDIACH	0x02
176 #define RW_NORETRY		0x04
177 #define RW_NOTRANSLATE	0x08
178 
179 #ifndef __ASSEMBLER__
180 
181 //extern int32 bios(uint16 nr, ...);
182 
183 // cf. http://www.fortunecity.com/skyscraper/apple/308/html/bios.htm
184 
185 struct tos_bpb {
186 	int16 recsiz;
187 	int16 clsiz;
188 	int16 clsizb;
189 	int16 rdlen;
190 	int16 fsiz;
191 	int16 fatrec;
192 	int16 datrec;
193 	int16 numcl;
194 	int16 bflags;
195 };
196 
197 struct tos_pun_info {
198 	int16 puns;
199 	uint8 pun[16];
200 	int32 part_start[16]; // unsigned ??
201 	uint32 p_cookie;
202 	struct tos_pun_info *p_cooptr; // points to itself
203 	uint16 p_version;
204 	uint16 p_max_sector;
205 	int32 reserved[16];
206 };
207 #define PUN_INFO ((struct tos_pun_info *)0x516L)
208 
209 
210 //#define Getmpb() toscallV(BIOS_TRAP, 0)
211 #define Bconstat(dev) toscallW(BIOS_TRAP, 1, (uint16)dev)
212 #define Bconin(dev) toscallW(BIOS_TRAP, 2, (uint16)dev)
213 #define Bconout(dev, chr) toscallWW(BIOS_TRAP, 3, (uint16)dev, (uint16)chr)
214 #define Rwabs(mode, buf, count, recno, dev, lrecno) toscallWPWWWL(BIOS_TRAP, 4, (int16)mode, (void *)buf, (int16)count, (int16)recno, (uint16)dev, (int32)lrecno)
215 //#define Setexc() toscallV(BIOS_TRAP, 5, )
216 #define Tickcal() toscallV(BIOS_TRAP, 6)
217 #define Getbpb(dev) (struct tos_bpb *)toscallW(BIOS_TRAP, 7, (uint16)dev)
218 #define Bcostat(dev) toscallW(BIOS_TRAP, 8, (uint16)dev)
219 #define Mediach(dev) toscallW(BIOS_TRAP, 9, (int16)dev)
220 #define Drvmap() (uint32)toscallV(BIOS_TRAP, 10)
221 #define Kbshift(mode) toscallW(BIOS_TRAP, 11, (uint16)mode)
222 
223 /* handy shortcut */
224 static inline int Bconput(int16 handle, const char *string)
225 {
226 	int i, err;
227 	for (i = 0; string[i]; i++) {
228 		if (string[i] == '\n')
229 			Bconout(handle, '\r');
230 		err = Bconout(handle, string[i]);
231 		if (err < 0)
232 			break;
233 	}
234 	return i;
235 }
236 
237 static inline int Bconputs(int16 handle, const char *string)
238 {
239 	int err = Bconput(handle, string);
240 	Bconout(handle, '\r');
241 	Bconout(handle, '\n');
242 	return err;
243 }
244 
245 #endif /* __ASSEMBLER__ */
246 
247 /*
248  * Atari XBIOS calls
249  */
250 
251 #define IM_DISABLE	0
252 #define IM_RELATIVE	1
253 #define IM_ABSOLUTE	2
254 #define IM_KEYCODE	4
255 
256 #define NVM_READ	0
257 #define NVM_WRITE	1
258 #define NVM_RESET	2
259 // unofficial
260 #define NVM_R_SEC	0
261 #define NVM_R_MIN	2
262 #define NVM_R_HOUR	4
263 #define NVM_R_MDAY	7
264 #define NVM_R_MON	8	/*+- 1*/
265 #define NVM_R_YEAR	9
266 #define NVM_R_VIDEO	29
267 
268 
269 #ifndef __ASSEMBLER__
270 
271 //extern int32 xbios(uint16 nr, ...);
272 
273 
274 #define Initmous(mode, param, vec) toscallWPP(XBIOS_TRAP, 0, (int16)mode, (void *)param, (void *)vec)
275 #define Physbase() (void *)toscallV(XBIOS_TRAP, 2)
276 #define Logbase() (void *)toscallV(XBIOS_TRAP, 3)
277 //#define Getrez() toscallV(XBIOS_TRAP, 4)
278 #define Setscreen(log, phys, mode) toscallPPW(XBIOS_TRAP, 5, (void *)log, (void *)phys, (int16)mode)
279 #define VsetScreen(log, phys, mode, modecode) toscallPPW(XBIOS_TRAP, 5, (void *)log, (void *)phys, (int16)mode)
280 //#define Mfpint() toscallV(XBIOS_TRAP, 13, )
281 #define Rsconf(speed, flow, ucr, rsr, tsr, scr) toscallWWWWWW(XBIOS_TRAP, 15, (int16)speed, (int16)flow, (int16)ucr, (int16)rsr, (int16)tsr, (int16)scr)
282 //#define Keytbl(unshift, shift, caps) (KEYTAB *)toscallPPP(XBIOS_TRAP, 16, (char *)unshift, (char *)shift, (char *)caps)
283 #define Random() toscallV(XBIOS_TRAP, 17)
284 #define Gettime() (uint32)toscallV(XBIOS_TRAP, 23)
285 #define Jdisint(intno) toscallW(XBIOS_TRAP, 26, (int16)intno)
286 #define Jenabint(intno) toscallW(XBIOS_TRAP, 27, (int16)intno)
287 #define Supexec(func) toscallP(XBIOS_TRAP, 38, (void *)func)
288 //#define Puntaes() toscallV(XBIOS_TRAP, 39)
289 #define DMAread(sect, count, buf, dev) toscallLWPW(XBIOS_TRAP, 42, (int32)sect, (int16)count, (void *)buf, (int16)dev)
290 #define DMAwrite(sect, count, buf, dev) toscallWPLW(XBIOS_TRAP, 43, (int32)sect, (int16)count, (void *)buf, (int16)dev)
291 #define NVMaccess(op, start, count, buffer) toscallWWWP(XBIOS_TRAP, 46, (int16)op, (int16)start, (int16)count, (char *)buffer)
292 #define VsetMode(mode) toscallW(XBIOS_TRAP, 88, (int16)mode)
293 #define VgetMonitor() toscallV(XBIOS_TRAP, 89)
294 #define Locksnd() toscallV(XBIOS_TRAP, 128)
295 #define Unlocksnd() toscallV(XBIOS_TRAP, 129)
296 
297 #endif /* __ASSEMBLER__ */
298 
299 /*
300  * Atari GEMDOS calls
301  */
302 
303 #define SUP_USER		0
304 #define SUP_SUPER		1
305 
306 
307 #ifdef __ASSEMBLER__
308 #define SUP_SET			0
309 #define SUP_INQUIRE		1
310 #else
311 
312 //extern int32 gemdos(uint16 nr, ...);
313 
314 #define SUP_SET			(void *)0
315 #define SUP_INQUIRE		(void *)1
316 
317 // official names
318 #define Pterm0() toscallV(GEMDOS_TRAP, 0)
319 #define Cconin() toscallV(GEMDOS_TRAP, 1)
320 #define Super(s) toscallP(GEMDOS_TRAP, 0x20, s)
321 #define Pterm(retcode) toscallW(GEMDOS_TRAP, 76, (int16)retcode)
322 
323 #endif /* __ASSEMBLER__ */
324 
325 #ifndef __ASSEMBLER__
326 
327 /*
328  * MetaDOS XBIOS calls
329  */
330 
331 //#define _DISABLE	0
332 
333 #ifndef __ASSEMBLER__
334 
335 #define Metainit(buf) toscallP(XBIOS_TRAP, 48, (void *)buf)
336 #define Metaopen(drive, p) toscall>P(XBIOS_TRAP, 48, (void *)buf)
337 #define Metaclose(drive) toscallW(XBIOS_TRAP, 50, (int16)drive)
338 #define Metagettoc(drive, flag, p) toscallW(XBIOS_TRAP, 62, (int16)drive, (int16)flag, (void *)p)
339 #define Metadiscinfo(drive, p) toscallWP(XBIOS_TRAP, 63, (int16)drive, (void *)p)
340 #define Metaioctl(drive, magic, op, buf) toscallWLWP(XBIOS_TRAP, 55, (int16)drive, (int32)magic, (int16)op, )
341 //#define Meta(drive) toscallW(XBIOS_TRAP, 50, (int16)drive)
342 //#define Meta(drive) toscallW(XBIOS_TRAP, 50, (int16)drive)
343 //#define Meta(drive) toscallW(XBIOS_TRAP, 50, (int16)drive)
344 
345 #endif /* __ASSEMBLER__ */
346 
347 /*
348  * XHDI support
349  * see http://toshyp.atari.org/010008.htm
350  */
351 
352 #define XHDI_COOKIE 'XHDI'
353 #define XHDI_MAGIC 0x27011992
354 //#define XHDI_CLOBBER_LIST "" /* only d0 */
355 #define XHDI_CLOBBER_LIST "d1", "d2", "a0", "a1", "a2"
356 
357 #define XH_TARGET_STOPPABLE		0x00000001L
358 #define XH_TARGET_REMOVABLE		0x00000002L
359 #define XH_TARGET_LOCKABLE		0x00000004L
360 #define XH_TARGET_EJECTABLE		0x00000008L
361 #define XH_TARGET_LOCKED		0x20000000L
362 #define XH_TARGET_STOPPED		0x40000000L
363 #define XH_TARGET_RESERVED		0x80000000L
364 
365 #ifndef __ASSEMBLER__
366 
367 /* pointer to the XHDI dispatch function */
368 extern void *gXHDIEntryPoint;
369 
370 extern status_t init_xhdi(void);
371 
372 /* movem should not needed, but just to be safe. */
373 
374 /* void (no) arg */
375 #define xhdicallV(callnr)						\
376 ({												\
377 	register int32 retvalue __asm__("d0");		\
378 												\
379 	__asm__ volatile							\
380 	("/* xhdicall(" #callnr ") */\n"			\
381 	"	movem.l	%%d3-%%d7/%%a3-%%a6,-(%%sp)\n"		\
382 	"	move.w	%[calln],-(%%sp)\n"				\
383 	"	jbsr	(%[entry])\n"						\
384 	"	add.l	#2,%%sp\n"						\
385 	"	movem.l	(%%sp)+,%%d3-%%d7/%%a3-%%a6\n"		\
386 	: "=r"(retvalue)	/* output */			\
387 	:							/* input */		\
388 	  [entry]"a"(gXHDIEntryPoint),				\
389 	  [calln]"i"(callnr)						\
390 	: XHDI_CLOBBER_LIST /* clobbered regs */	\
391 	);											\
392 	retvalue;									\
393 })
394 
395 #define xhdicallW(callnr, p1)					\
396 ({												\
397 	register int32 retvalue __asm__("d0");		\
398 	int16 _p1 = (int16)(p1);					\
399 												\
400 	__asm__ volatile							\
401 	("/* xhdicall(" #callnr ") */\n"			\
402 	"	movem.l	%%d3-%%d7/%%a3-%%a6,-(%%sp)\n"		\
403 	"	move.w	%1,-(%%sp) \n"					\
404 	"	move.w	%[calln],-(%%sp)\n"				\
405 	"	jbsr	(%[entry])\n"						\
406 	"	add.l	#4,%%sp \n"						\
407 	"	movem.l	(%%sp)+,%%d3-%%d7/%%a3-%%a6\n"		\
408 	: "=r"(retvalue)	/* output */			\
409 	: "r"(_p1),			/* input */				\
410 	  [entry]"a"(gXHDIEntryPoint),				\
411 	  [calln]"i"(callnr)						\
412 	: XHDI_CLOBBER_LIST /* clobbered regs */	\
413 	);											\
414 	retvalue;									\
415 })
416 
417 #define xhdicallWWL(callnr, p1, p2, p3)					\
418 ({												\
419 	register int32 retvalue __asm__("d0");		\
420 	int16 _p1 = (int16)(p1);					\
421 	int16 _p2 = (int16)(p2);					\
422 	int32 _p3 = (int32)(p3);					\
423 												\
424 	__asm__ volatile							\
425 	("/* xhdicall(" #callnr ") */\n"			\
426 	"	movem.l	%%d3-%%d7/%%a3-%%a6,-(%%sp)\n"		\
427 	"	move.l	%3,-(%%sp) \n"					\
428 	"	move.w	%2,-(%%sp) \n"					\
429 	"	move.w	%1,-(%%sp) \n"					\
430 	"	move.w	%[calln],-(%%sp)\n"				\
431 	"	jbsr	(%[entry])\n"						\
432 	"	add.l	#10,%%sp \n"						\
433 	"	movem.l	(%%sp)+,%%d3-%%d7/%%a3-%%a6\n"		\
434 	: "=r"(retvalue)	/* output */			\
435 	: "r"(_p1), "r"(_p2),				\
436 	  "r"(_p3),			/* input */	\
437 	  [entry]"a"(gXHDIEntryPoint),				\
438 	  [calln]"i"(callnr)						\
439 	: XHDI_CLOBBER_LIST /* clobbered regs */	\
440 	);											\
441 	retvalue;									\
442 })
443 
444 #define xhdicallWWLL(callnr, p1, p2, p3, p4)					\
445 ({												\
446 	register int32 retvalue __asm__("d0");		\
447 	int16 _p1 = (int16)(p1);					\
448 	int16 _p2 = (int16)(p2);					\
449 	int32 _p3 = (int32)(p3);					\
450 	int32 _p4 = (int32)(p4);					\
451 												\
452 	__asm__ volatile							\
453 	("/* xhdicall(" #callnr ") */\n"			\
454 	"	movem.l	%%d3-%%d7/%%a3-%%a6,-(%%sp)\n"		\
455 	"	move.l	%4,-(%%sp) \n"					\
456 	"	move.l	%3,-(%%sp) \n"					\
457 	"	move.w	%2,-(%%sp) \n"					\
458 	"	move.w	%1,-(%%sp) \n"					\
459 	"	move.w	%[calln],-(%%sp)\n"				\
460 	"	jbsr	(%[entry])\n"						\
461 	"	add.l	#14,%%sp \n"						\
462 	"	movem.l	(%%sp)+,%%d3-%%d7/%%a3-%%a6\n"		\
463 	: "=r"(retvalue)	/* output */			\
464 	: "r"(_p1), "r"(_p2),				\
465 	  "r"(_p3), "r"(_p4),	/* input */	\
466 	  [entry]"a"(gXHDIEntryPoint),				\
467 	  [calln]"i"(callnr)						\
468 	: XHDI_CLOBBER_LIST /* clobbered regs */	\
469 	);											\
470 	retvalue;									\
471 })
472 
473 #define xhdicallWWLLL(callnr, p1, p2, p3, p4, p5)					\
474 ({												\
475 	register int32 retvalue __asm__("d0");		\
476 	int16 _p1 = (int16)(p1);					\
477 	int16 _p2 = (int16)(p2);					\
478 	int32 _p3 = (int32)(p3);					\
479 	int32 _p4 = (int32)(p4);					\
480 	int32 _p5 = (int32)(p5);					\
481 												\
482 	__asm__ volatile							\
483 	("/* xhdicall(" #callnr ") */\n"			\
484 	"	movem.l	%%d3-%%d7/%%a3-%%a6,-(%%sp)\n"		\
485 	"	move.l	%5,-(%%sp) \n"					\
486 	"	move.l	%4,-(%%sp) \n"					\
487 	"	move.l	%3,-(%%sp) \n"					\
488 	"	move.w	%2,-(%%sp) \n"					\
489 	"	move.w	%1,-(%%sp) \n"					\
490 	"	move.w	%[calln],-(%%sp)\n"				\
491 	"	jbsr	(%[entry])\n"						\
492 	"	add.l	#18,%%sp \n"						\
493 	"	movem.l	(%%sp)+,%%d3-%%d7/%%a3-%%a6\n"		\
494 	: "=r"(retvalue)	/* output */			\
495 	: "r"(_p1), "r"(_p2),				\
496 	  "r"(_p3), "r"(_p4),				\
497 	  "r"(_p5),			/* input */	\
498 	  [entry]"a"(gXHDIEntryPoint),				\
499 	  [calln]"i"(callnr)						\
500 	: XHDI_CLOBBER_LIST /* clobbered regs */	\
501 	);											\
502 	retvalue;									\
503 })
504 
505 #define xhdicallWLLLL(callnr, p1, p2, p3, p4, p5)					\
506 ({												\
507 	register int32 retvalue __asm__("d0");		\
508 	int16 _p1 = (int16)(p1);					\
509 	int32 _p2 = (int32)(p2);					\
510 	int32 _p3 = (int32)(p3);					\
511 	int32 _p4 = (int32)(p4);					\
512 	int32 _p5 = (int32)(p5);					\
513 												\
514 	__asm__ volatile							\
515 	("/* xhdicall(" #callnr ") */\n"			\
516 	"	movem.l	%%d3-%%d7/%%a3-%%a6,-(%%sp)\n"		\
517 	"	move.l	%5,-(%%sp) \n"					\
518 	"	move.l	%4,-(%%sp) \n"					\
519 	"	move.l	%3,-(%%sp) \n"					\
520 	"	move.l	%2,-(%%sp) \n"					\
521 	"	move.w	%1,-(%%sp) \n"					\
522 	"	move.w	%[calln],-(%%sp)\n"				\
523 	"	jbsr	(%[entry])\n"						\
524 	"	add.l	#20,%%sp \n"						\
525 	"	movem.l	(%%sp)+,%%d3-%%d7/%%a3-%%a6\n"		\
526 	: "=r"(retvalue)	/* output */			\
527 	: "r"(_p1), "r"(_p2),				\
528 	  "r"(_p3), "r"(_p4),				\
529 	  "r"(_p5),			/* input */	\
530 	  [entry]"a"(gXHDIEntryPoint),				\
531 	  [calln]"i"(callnr)						\
532 	: XHDI_CLOBBER_LIST /* clobbered regs */	\
533 	);											\
534 	retvalue;									\
535 })
536 
537 #define xhdicallWWWLWL(callnr, p1, p2, p3, p4, p5, p6)					\
538 ({												\
539 	register int32 retvalue __asm__("d0");		\
540 	int16 _p1 = (int16)(p1);					\
541 	int16 _p2 = (int16)(p2);					\
542 	int16 _p3 = (int16)(p3);					\
543 	int32 _p4 = (int32)(p4);					\
544 	int16 _p5 = (int16)(p5);					\
545 	int32 _p6 = (int32)(p6);					\
546 												\
547 	__asm__ volatile							\
548 	("/* xhdicall(" #callnr ") */\n"			\
549 	"	movem.l	%%d3-%%d7/%%a3-%%a6,-(%%sp)\n"		\
550 	"	move.l	%6,-(%%sp) \n"					\
551 	"	move.w	%5,-(%%sp) \n"					\
552 	"	move.l	%4,-(%%sp) \n"					\
553 	"	move.w	%3,-(%%sp) \n"					\
554 	"	move.w	%2,-(%%sp) \n"					\
555 	"	move.w	%1,-(%%sp) \n"					\
556 	"	move.w	%[calln],-(%%sp)\n"				\
557 	"	jbsr	(%[entry])\n"						\
558 	"	add.l	#18,%%sp \n"						\
559 	"	movem.l	(%%sp)+,%%d3-%%d7/%%a3-%%a6\n"		\
560 	: "=r"(retvalue)	/* output */			\
561 	: "r"(_p1), "r"(_p2),				\
562 	  "r"(_p3), "r"(_p4),				\
563 	  "r"(_p5), "r"(_p6),		/* input */	\
564 	  [entry]"a"(gXHDIEntryPoint),				\
565 	  [calln]"i"(callnr)						\
566 	: XHDI_CLOBBER_LIST /* clobbered regs */	\
567 	);											\
568 	retvalue;									\
569 })
570 
571 #define xhdicallWWP(callnr, p1, p2, p3) \
572 	xhdicallWWL(callnr, p1, p2, (int32)(p3))
573 #define xhdicallWWPP(callnr, p1, p2, p3, p4) \
574 	xhdicallWWLL(callnr, p1, p2, (int32)(p3), (int32)(p4))
575 #define xhdicallWWPPP(callnr, p1, p2, p3, p4, p5) \
576 	xhdicallWWLLL(callnr, p1, p2, (int32)(p3), (int32)(p4), (int32)(p5))
577 #define xhdicallWPPPP(callnr, p1, p2, p3, p4, p5) \
578 	xhdicallWLLLL(callnr, p1, (uint32)(p2), (int32)(p3), (int32)(p4), (int32)(p5))
579 #define xhdicallWWWLWP(callnr, p1, p2, p3, p4, p5, p6) \
580 	xhdicallWWWLWL(callnr, p1, p2, p3, (uint32)(p4), p5, (uint32)(p6))
581 #define xhdicallWWWPWP(callnr, p1, p2, p3, p4, p5, p6) \
582 	xhdicallWWWLWL(callnr, p1, p2, p3, (int32)(p4), p5, (uint32)(p6))
583 
584 #define XHGetVersion() (uint16)xhdicallV(0)
585 #define XHInqTarget(major, minor, blocksize, flags, pname) xhdicallWWPPP(1, (uint16)major, (uint16)minor, (uint32 *)(blocksize), (uint32 *)flags, (char *)pname)
586 //XHReserve 2
587 //#define XHLock() 3
588 //#define XHStop() 4
589 #define XHEject(major, minor, doeject, key) xhdicallWWWW(5, (uint16)major, (uint16)minor, (uint16)doeject, (uint16)key)
590 #define XHDrvMap() xhdicallV(6)
591 #define XHInqDev(dev,major,minor,startsect,bpb) xhdicallWPPPP(7,dev,(uint16 *)major,(uint16 *)minor,(uint32 *)startsect,(struct tos_bpb *)bpb)
592 //XHInqDriver 8
593 //XHNewCookie 9
594 #define XHReadWrite(major, minor, rwflags, recno, count, buf) xhdicallWWWLWP(10, (uint16)major, (uint16)minor, (uint16)rwflags, (uint32)recno, (uint16)count, (void *)buf)
595 #define XHInqTarget2(major, minor, bsize, flags, pname, pnlen) xhdicallWWPPPW(11, (uint16)major, (uint16)minor, (uint32 *)bsize, (uint32 *)flags, (char *)pname, (uint16)pnlen)
596 //XHInqDev2 12
597 //XHDriverSpecial 13
598 #define XHGetCapacity(major, minor, blocks, blocksize) xhdicallWWPP(14, (uint16)major, (uint16)minor, (uint32 *)blocks, (uint32 *)blocksize)
599 //#define XHMediumChanged() 15
600 //XHMiNTInfo 16
601 //XHDosLimits 17
602 #define XHLastAccess(major, minor, ms) xhdicallWWP(18, major, minor, (uint32 *)ms)
603 //SHReaccess 19
604 
605 #endif /* __ASSEMBLER__ */
606 
607 
608 /*
609  * error mapping
610  * in debug.c
611  */
612 
613 extern status_t toserror(int32 err);
614 extern status_t xhdierror(int32 err);
615 extern void dump_tos_cookies(void);
616 
617 /*
618  * Cookie Jar access
619  */
620 
621 typedef struct tos_cookie {
622 	uint32 cookie;
623 	union {
624 		int32 ivalue;
625 		void *pvalue;
626 	};
627 } tos_cookie;
628 
629 #define COOKIE_JAR (*((const tos_cookie **)0x5A0))
630 
631 static inline const tos_cookie *tos_find_cookie(uint32 what)
632 {
633 	const tos_cookie *c = COOKIE_JAR;
634 	while (c && (c->cookie)) {
635 		if (c->cookie == what)
636 			return c;
637 		c++;
638 	}
639 	return NULL;
640 }
641 
642 /*
643  * OSHEADER access
644  */
645 
646 typedef struct tos_osheader {
647 	uint16 os_entry;
648 	uint16 os_version;
649 	void *reseth;
650 	struct tos_osheader *os_beg;
651 	void *os_end;
652 	void *os_rsv1;
653 	void *os_magic;
654 	uint32 os_date;
655 	uint32 os_conf;
656 	//uint32/16? os_dosdate;
657 	// ... more stuff we don't care about
658 } tos_osheader;
659 
660 #define tos_sysbase ((const struct tos_osheader **)0x4F2)
661 
662 static inline const struct tos_osheader *tos_get_osheader()
663 {
664 	if (!(*tos_sysbase))
665 		return NULL;
666 	return (*tos_sysbase)->os_beg;
667 }
668 
669 #endif /* __ASSEMBLER__ */
670 
671 /*
672  * ARAnyM Native Features
673  */
674 
675 #define NF_COOKIE	0x5f5f4e46L	//'__NF'
676 #define NF_MAGIC	0x20021021L
677 
678 #ifndef __ASSEMBLER__
679 
680 typedef struct {
681 	uint32 magic;
682 	int32 (*nfGetID) (const char *);
683 	int32 (*nfCall) (int32 ID, ...);
684 } NatFeatCookie;
685 
686 extern NatFeatCookie *gNatFeatCookie;
687 extern int32 gDebugPrintfNatFeatID;
688 
689 static inline NatFeatCookie *nat_features(void)
690 {
691 	const struct tos_cookie *c;
692 	if (gNatFeatCookie == (void *)-1)
693 		return NULL;
694 	if (gNatFeatCookie)
695 		return gNatFeatCookie;
696 	c = tos_find_cookie(NF_COOKIE);
697 	if (c) {
698 		gNatFeatCookie = (NatFeatCookie *)c->pvalue;
699 		if (gNatFeatCookie && gNatFeatCookie->magic == NF_MAGIC) {
700 			return gNatFeatCookie;
701 		}
702 	}
703 	gNatFeatCookie = (NatFeatCookie *)-1;
704 	return NULL;
705 }
706 
707 extern status_t init_nat_features(void);
708 
709 static inline int32 nat_feat_getid(const char *name)
710 {
711 	NatFeatCookie *c = nat_features();
712 	if (!c)
713 		return 0;
714 	return c->nfGetID(name);
715 }
716 
717 #define nat_feat_call(id, code, a...) \
718 ({						\
719 	int32 ret = -1;				\
720 	NatFeatCookie *c = nat_features();	\
721 	if (c)					\
722 		ret = c->nfCall(id | code, a);	\
723 	ret;					\
724 })
725 
726 extern void nat_feat_debugprintf(const char *str);
727 
728 #endif /* __ASSEMBLER__ */
729 
730 #ifdef __cplusplus
731 }
732 #endif
733 
734 #endif /* _TOSCALLS_H */
735