1/*
2 * Copyright 2008-2010, Fran��ois Revol, revol@free.fr. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include <boot/platform.h>
8#include <boot/stage2.h>
9#include <boot/stdio.h>
10#include <stdarg.h>
11
12#include <Errors.h>
13
14#include "toscalls.h"
15
16
17void *gXHDIEntryPoint = NULL;
18uint32 gXHDIVersion = 0;
19
20NatFeatCookie *gNatFeatCookie = NULL;
21uint32 gDebugPrintfNatFeatID = 0;
22uint32 gBootstrapNatFeatID = 0;
23
24
25/*! Maps TOS error codes to native errors
26 */
27extern "C" status_t
28toserror(int32 err)
29{
30	// generated from:
31	// http://www.fortunecity.com/skyscraper/apple/308/html/appendd.htm
32	// with:
33	// while read N; do read V; read L; echo -e "\tcase $V: /* $N - $L */\n\t\treturn B_BAD_VALUE;"; done >> errs
34	switch (err) {
35	/* BIOS errors */
36	case 0: /* E_OK - No error */
37		return B_OK;
38	case -1: /* ERROR - Generic error */
39		return B_ERROR;
40	case -2: /* EDRVNR - Drive not ready */
41		return B_DEV_NOT_READY;
42	case -3: /* EUNCMD - Unknown command */
43		return B_BAD_VALUE;	//XXX
44	case -4: /* E_CRC - CRC error */
45		return B_DEV_CRC_ERROR;
46	case -5: /* EBADRQ - Bad request */
47		return B_BAD_VALUE;	//XXX
48	case -6: /* E_SEEK - Seek error */
49		return B_DEV_SEEK_ERROR;
50	case -7: /* EMEDIA - Unknown media */
51		return B_DEV_UNREADABLE;
52	case -8: /* ESECNF - Sector not found */
53		return B_DEV_FORMAT_ERROR;
54	case -9: /* EPAPER - Out of paper */
55		return B_DEVICE_NOT_FOUND;
56	case -10: /* EWRITF - Write fault */
57		return B_DEV_WRITE_ERROR;
58	case -11: /* EREADF - Read fault */
59		return B_DEV_READ_ERROR;
60	case -12: /* EWRPRO - Device is write protected */
61		return B_READ_ONLY_DEVICE;
62	case -14: /* E_CHNG - Media change detected */
63		return B_DEV_MEDIA_CHANGED;
64	case -15: /* EUNDEV - Unknown device */
65		return B_DEV_BAD_DRIVE_NUM;
66	case -16: /* EBADSF - Bad sectors on format */
67		return B_DEV_UNREADABLE;
68	case -17: /* EOTHER - Insert other disk (request) */
69		return B_DEV_MEDIA_CHANGE_REQUESTED;
70	/* GEMDOS errors */
71	case -32: /* EINVFN - Invalid function */
72		return B_BAD_VALUE;
73	case -33: /* EFILNF - File not found */
74		return B_FILE_NOT_FOUND;
75	case -34: /* EPTHNF - Path not found */
76		return B_ENTRY_NOT_FOUND;
77	case -35: /* ENHNDL - No more handles */
78		return B_NO_MORE_FDS;
79	case -36: /* EACCDN - Access denied */
80		return B_PERMISSION_DENIED;
81	case -37: /* EIHNDL - Invalid handle */
82		return B_FILE_ERROR;
83	case -39: /* ENSMEM - Insufficient memory */
84		return B_NO_MEMORY;
85	case -40: /* EIMBA - Invalid memory block address */
86		return B_BAD_ADDRESS;
87	case -46: /* EDRIVE - Invalid drive specification */
88		return B_DEV_BAD_DRIVE_NUM;
89	case -48: /* ENSAME - Cross device rename */
90		return B_CROSS_DEVICE_LINK;
91	case -49: /* ENMFIL - No more files */
92		return B_NO_MORE_FDS;
93	case -58: /* ELOCKED - Record is already locked */
94		return B_BAD_VALUE;	//XXX
95	case -59: /* ENSLOCK - Invalid lock removal request */
96		return B_BAD_VALUE;	//XXX
97	case -64: /* ERANGE or ENAMETOOLONG - Range error */
98		return B_NAME_TOO_LONG;
99	case -65: /* EINTRN - Internal error */
100		return B_ERROR;
101	case -66: /* EPLFMT - Invalid program load format */
102		return B_NOT_AN_EXECUTABLE;
103	case -67: /* EGSBF - Memory block growth failure */
104		return B_BAD_VALUE;
105	case -80: /* ELOOP - Too many symbolic links */
106		return B_LINK_LIMIT;
107	case -200: /* EMOUNT - Mount point crossed (indicator) */
108		return B_BAD_VALUE;
109	default:
110		return B_ERROR;
111	}
112}
113
114
115/*! Maps XHDI error codes to native errors
116 * cf. http://toshyp.atari.org/010008.htm#XHDI_20error_20codes
117 */
118extern "C" status_t
119xhdierror(int32 err)
120{
121	if (err <= -456) {
122		int ide = -(err + 456);
123		// ide status reg
124		// guessed mapping
125		if (ide & (1 << 1)) {	// track 0 not found
126			return B_DEV_FORMAT_ERROR;
127		} else if (ide & (1 << 0)) {	// DAM not found
128			return B_DEV_FORMAT_ERROR;
129		} else if (ide & (1 << 4)) {	// ID field not found
130			return B_DEV_ID_ERROR;
131		} else if (ide & (1 << 7)) {	// bad block mark
132			return B_DEV_FORMAT_ERROR;
133		} else if (ide & (1 << 6)) {	// uncorrectable error
134			return B_DEV_UNREADABLE;
135		} else if (ide & (1 << 2)) {	// command aborted
136			return B_INTERRUPTED;
137		} else if (ide & (1 << 5)) {	// media change
138			return B_DEV_MEDIA_CHANGED;
139		} else if (ide & (1 << 3)) {	// media change requested
140			return B_DEV_MEDIA_CHANGE_REQUESTED;
141		}
142		return B_ERROR;
143	} else if (err <= -200) {
144		/* SCSI errors */
145		int scsi = -(err + 200);
146		//XXX:
147		switch (scsi) {
148		case 0x06:
149			return B_DEV_FORMAT_ERROR;
150		case 0x10:
151			return B_DEV_FORMAT_ERROR;
152		case 0x11:
153			return B_DEV_UNREADABLE;
154		case 0x12:
155			return B_DEV_ID_ERROR;
156		case 0x13:
157			return B_DEV_FORMAT_ERROR;
158		case 0x20:
159			return B_INTERRUPTED;
160		case 0x28:
161			return B_DEV_FORMAT_ERROR;
162		case 0x5a:
163			return B_DEV_FORMAT_ERROR;
164		}
165	}
166	return toserror(err);
167}
168
169
170static void
171dump_tos_cookie(const struct tos_cookie *c)
172{
173	if (c != NULL) {
174		dprintf("%4.4s: 0x%08lx, %ld\n", (const char *)&c->cookie, c->ivalue,
175			c->ivalue);
176	}
177}
178
179
180extern "C" void
181dump_tos_cookies(void)
182{
183	const tos_cookie *c = COOKIE_JAR;
184	dprintf("Cookies:\n");
185	while (c && (c->cookie)) {
186		dump_tos_cookie(c++);
187	}
188}
189
190
191extern "C" status_t
192init_xhdi(void)
193{
194	const struct tos_cookie *c;
195
196	if (gXHDIEntryPoint)
197		return B_OK;
198
199	c = tos_find_cookie(XHDI_COOKIE);
200	if (!c)
201		return B_ENTRY_NOT_FOUND;
202	if (((uint32 *)c->pvalue)[-1] != XHDI_MAGIC)
203		return B_BAD_VALUE;
204	gXHDIEntryPoint = c->pvalue;
205	gXHDIVersion = XHGetVersion();
206	return B_OK;
207}
208
209
210extern "C" status_t
211init_nat_features(void)
212{
213	gKernelArgs.arch_args.plat_args.atari.nat_feat.nf_get_id = NULL;
214	gKernelArgs.arch_args.plat_args.atari.nat_feat.nf_call = NULL;
215	gKernelArgs.arch_args.plat_args.atari.nat_feat.nf_dprintf_id = 0;
216	if (nat_features()) {
217		// find debugprintf id
218		gDebugPrintfNatFeatID = nat_feat_getid("DEBUGPRINTF");
219		dprintf("DEBUGPRINTF natfeat id 0x%08lx\n", gDebugPrintfNatFeatID);
220		// pass native features infos to the kernel
221		gKernelArgs.arch_args.plat_args.atari.nat_feat.nf_get_id =
222			nat_features()->nfGetID;
223		gKernelArgs.arch_args.plat_args.atari.nat_feat.nf_call =
224			nat_features()->nfCall;
225		gKernelArgs.arch_args.plat_args.atari.nat_feat.nf_dprintf_id =
226			gDebugPrintfNatFeatID;
227		// find other natfeat ids
228		gBootstrapNatFeatID = nat_feat_getid("BOOTSTRAP");
229		dprintf("BOOTSTRAP natfeat id 0x%08lx\n", gBootstrapNatFeatID);
230	}
231	return nat_features() ? B_OK : B_ENTRY_NOT_FOUND;
232}
233
234
235extern "C" void
236nat_feat_debugprintf(const char *str)
237{
238	if (gDebugPrintfNatFeatID)
239		nat_feat_call(gDebugPrintfNatFeatID, 0, str);
240}
241
242extern "C" int
243nat_feat_get_bootdrive(void)
244{
245	if (gBootstrapNatFeatID == 0)
246		return -1;
247	return nat_feat_call(gBootstrapNatFeatID, 1);
248}
249
250extern "C" status_t
251nat_feat_get_bootargs(char *str, long size)
252{
253	status_t err;
254	if (gBootstrapNatFeatID == 0)
255		return B_ERROR;
256	return toserror(nat_feat_call(gBootstrapNatFeatID, 2, str, size));
257}
258