|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * AutoConfig devices
5: *
6: * (c) 1995 Bernd Schmidt
7: */
8:
9: #include <stdio.h>
10: #include <stdlib.h>
11: #include <assert.h>
12:
13: #ifdef __unix
14: #include <unistd.h>
15: #include <fcntl.h>
16: #endif
17:
18: #include "config.h"
19:
20: #ifdef __mac__
21: #include <unix.h>
22: #endif
23:
24: #include "amiga.h"
25: #include "options.h"
26: #include "events.h"
27: #include "memory.h"
28: #include "custom.h"
29: #include "newcpu.h"
30: #include "disk.h"
31: #include "xwin.h"
32: #include "autoconf.h"
33: #include "hardfile.h"
34:
35: static int opencount = 0;
36: static int uaedevfd;
37: static int numtracks = 512;
38:
39: static ULONG dosname, devname;
40:
41: static ULONG hardfile_init(void)
42: {
43: ULONG tmp1, tmp2, tmp3;
44: bool have36 = false;
45: ULONG retval = regs.d[0];
46:
47: if (!automount_uaedev)
48: return retval;
49:
50: regs.d[0] = 88; regs.d[1] = 1; /* MEMF_PUBLIC */
51: tmp1 = CallLib (regs.a[6], -198); /* AllocMem() */
52: if (tmp1 == 0) {
53: fprintf(stderr, "Not enough memory for uae.device!\n");
54: return 0;
55: }
56: /* Open expansion.lib */
57: regs.d[0] = 36; /* Let's try this... */
58: regs.a[1] = explibname;
59: regs.a[4] = CallLib (regs.a[6], -552); /* OpenLibrary() */
60: if (regs.a[4])
61: have36 = true;
62: else {
63: regs.d[0] = 0;
64: regs.a[1] = explibname;
65: regs.a[4] = CallLib (regs.a[6], -552); /* OpenLibrary() */
66: }
67: put_long (tmp1, dosname);
68: put_long (tmp1+4, devname);
69: put_long (tmp1+8, 0); /* Unit no. */
70: put_long (tmp1+12, 0); /* Device flags */
71: put_long (tmp1+16, 16); /* Env. size */
72: put_long (tmp1+20, 128); /* 512 bytes/block */
73: put_long (tmp1+24, 0); /* unused */
74: put_long (tmp1+28, 1); /* heads */
75: put_long (tmp1+32, 1); /* unused */
76: put_long (tmp1+36, 32); /* secs per track */
77: put_long (tmp1+40, 1); /* reserved blocks */
78: put_long (tmp1+44, 0); /* unused */
79: put_long (tmp1+48, 0); /* interleave */
80: put_long (tmp1+52, 0); /* lowCyl */
81: put_long (tmp1+56, 511); /* upperCyl */
82: put_long (tmp1+60, 0); /* Number of buffers */
83: put_long (tmp1+64, 0); /* Buffer mem type */
84: put_long (tmp1+68, 0x7FFFFFFF); /* largest transfer */
85: put_long (tmp1+72, ~1); /* addMask (?) */
86: put_long (tmp1+76, (ULONG)-1); /* bootPri */
87: if (have36)
88: put_long (tmp1+80, 0x444f5301); /* DOS\1 */
89: else
90: put_long (tmp1+80, 0x444f5300); /* DOS\0 */
91:
92: put_long (tmp1+84, 0); /* pad */
93: regs.a[0] = tmp1;
94: tmp2 = CallLib (regs.a[4], -144); /* MakeDosNode() */
95: regs.a[0] = tmp2;
96: regs.d[0] = (ULONG)-1;
97: regs.a[1] = 0;
98: regs.d[1] = 0;
99: CallLib (regs.a[4], -150); /* AddDosNode() */
100: #if 0
101: #if 0
102: if (have36)
103: CallLib (regs.a[4], /*-150*/-36); /* AddDosNode() */
104: else {
105: #endif
106: /* We could also try to call AddBootNode() here - but we don't have
107: * a ConfigDev. */
108: regs.d[0] = 20;
109: regs.d[1] = 0;
110: tmp3 = CallLib (regs.a[6], -198);
111: if (tmp3 == 0) {
112: fprintf(stderr, "Not enough memory for uae.device bootnode!\n");
113: return 0;
114: }
115: put_word (tmp3 + 14, 0);
116: put_long (tmp3 + 16, tmp2);
117: put_word (tmp3 + 8, 0x1005);
118: put_long (tmp3 + 10, 0);
119: put_long (tmp3 + 0, 0);
120: put_long (tmp3 + 4, 0);
121: regs.a[0] = regs.a[4] + 74; /* MountList */
122: regs.a[1] = tmp3;
123: CallLib (regs.a[6], -270); /* Enqueue() */
124: #if 0
125: }
126: #endif
127: #endif
128:
129: regs.a[1] = tmp1;
130: regs.d[0] = 88;
131: CallLib (regs.a[6], -210); /* FreeMem() */
132:
133: regs.a[1] = regs.a[4];
134: CallLib (regs.a[6], -414); /* CloseLibrary() */
135:
136: return retval;
137: }
138:
139: static ULONG hardfile_open(void)
140: {
141: CPTR tmp1 = regs.a[1]; /* IOReq */
142:
143: /* Check unit number */
144: if (regs.d[0] == 0) {
145: opencount++;
146: put_word (regs.a[6]+32, get_word (regs.a[6]+32) + 1);
147: put_long (tmp1+24, 0); /* io_Unit */
148: put_byte (tmp1+31, 0); /* io_Error */
149: put_byte (tmp1+8, 7); /* ln_type = NT_REPLYMSG */
150: return 0;
151: }
152:
153: put_long (tmp1+20, (ULONG)-1);
154: put_byte (tmp1+31, (UBYTE)-1);
155: return (ULONG)-1;
156: }
157:
158: static ULONG hardfile_close(void)
159: {
160: opencount--;
161: put_word (regs.a[6]+32, get_word (regs.a[6]+32) - 1);
162:
163: return regs.d[0];
164: }
165:
166: static ULONG hardfile_expunge(void)
167: {
168: return 0; /* Simply ignore this one... */
169: }
170:
171: static ULONG hardfile_beginio(void)
172: {
173: ULONG tmp1, tmp2, dataptr, offset;
174: ULONG retval = regs.d[0];
175:
176: tmp1 = regs.a[1];
177: put_byte (tmp1+8, 5); /* set ln_type to NT_MESSAGE */
178: put_byte (tmp1+31, 0); /* no error yet */
179: tmp2 = get_word (tmp1+28); /* io_Command */
180: switch (tmp2) {
181: case 2: /* Read */
182: dataptr = get_long (tmp1 + 40);
183: if (dataptr & 1)
184: goto bad_command;
185: offset = get_long (tmp1 + 44);
186: if (offset & 511)
187: goto bad_command;
188: tmp2 = get_long (tmp1 + 36); /* io_Length */
189: if (tmp2 & 511)
190: goto bad_command;
191: if (tmp2 + offset > (ULONG)numtracks * 32 * 512)
192: goto bad_command;
193:
194: put_long (tmp1 + 32, tmp2); /* set io_Actual */
195: lseek (uaedevfd, offset, SEEK_SET);
196: while (tmp2) {
197: int i;
198: char buffer[512];
199: read (uaedevfd, buffer, 512);
200: for (i = 0; i < 512; i++, dataptr++)
201: put_byte(dataptr, buffer[i]);
202: tmp2 -= 512;
203: }
204: break;
205:
206: case 3: /* Write */
207: case 11: /* Format */
208: dataptr = get_long (tmp1 + 40);
209: if (dataptr & 1)
210: goto bad_command;
211: offset = get_long (tmp1 + 44);
212: if (offset & 511)
213: goto bad_command;
214: tmp2 = get_long (tmp1 + 36); /* io_Length */
215: if (tmp2 & 511)
216: goto bad_command;
217: if (tmp2 + offset > (ULONG)numtracks * 32 * 512)
218: goto bad_command;
219:
220: put_long (tmp1 + 32, tmp2); /* set io_Actual */
221: lseek (uaedevfd, offset, SEEK_SET);
222: while (tmp2) {
223: char buffer[512];
224: int i;
225: for (i=0; i < 512; i++, dataptr++)
226: buffer[i] = get_byte(dataptr);
227: write (uaedevfd, buffer, 512);
228: tmp2 -= 512;
229: }
230: break;
231:
232: bad_command:
233: break;
234:
235: case 18: /* GetDriveType */
236: put_long (tmp1 + 32, 1); /* not exactly a 3.5" drive, but... */
237: break;
238:
239: case 19: /* GetNumTracks */
240: put_long (tmp1 + 32, numtracks);
241: break;
242:
243: /* Some commands that just do nothing and return zero */
244: case 4: /* Update */
245: case 5: /* Clear */
246: case 9: /* Motor */
247: case 10: /* Seek */
248: case 12: /* Remove */
249: case 13: /* ChangeNum */
250: case 14: /* ChangeStatus */
251: case 15: /* ProtStatus */
252: case 20: /* AddChangeInt */
253: case 21: /* RemChangeInt */
254: put_long (tmp1+32, 0); /* io_Actual */
255: retval = 0;
256: break;
257:
258: default:
259: /* Command not understood. */
260: put_byte (tmp1+31, (UBYTE)-3); /* io_Error */
261: retval = 0;
262: break;
263: }
264: if ((get_byte (tmp1+30) & 1) == 0) {
265: /* Not IOF_QUICK -- need to ReplyMsg */
266: regs.a[1] = tmp1;
267: CallLib (get_long(4), -378);
268: }
269: return retval;
270: }
271:
272: static ULONG hardfile_abortio(void)
273: {
274: return (ULONG)-3;
275: }
276:
277: void hardfile_install(void)
278: {
279: ULONG devid, functable, datatable, inittable, begin, end;
280: ULONG initroutine, openfunc, closefunc, expungefunc;
281: ULONG nullfunc, beginiofunc, abortiofunc;
282:
283: uaedevfd = open ("hardfile", O_RDWR);
284:
285: if (uaedevfd < 0)
286: return;
287:
288: devname = ds("uae.device");
289: devid = ds("uae 0.4"); /* ID */
290: dosname = ds("UAEHF"); /* This is the DOS name */
291:
292: begin = here();
293: dw(0x4AFC); /* RTC_MATCHWORD */
294: dl(begin); /* our start address */
295: dl(0); /* Continue scan here */
296: dw(0x8101); /* RTF_AUTOINIT|RTF_COLDSTART; Version 1 */
297: dw(0x0305); /* NT_DEVICE; pri 5 */
298: dl(devname); /* name */
299: dl(devid); /* ID */
300: dl(here() + 4); /* Init area: directly after this */
301: /* Init area starts here */
302: dw(0x0000); /* Not really sure what to put here */
303: dw(0x0100);
304: inittable = here();
305: dl(0); dl(0); dl(0); /* skip 3 longs */
306:
307: /* InitRoutine */
308: initroutine = here();
309: calltrap(deftrap(hardfile_init)); dw(RTS);
310:
311: /* Open */
312: openfunc = here();
313: calltrap(deftrap(hardfile_open)); dw(RTS);
314:
315: /* Close */
316: closefunc = here();
317: calltrap(deftrap(hardfile_close)); dw(RTS);
318:
319: /* Expunge */
320: expungefunc = here();
321: calltrap(deftrap(hardfile_expunge)); dw(RTS);
322:
323: /* Null */
324: nullfunc = here();
325: dw(0x7000); /* return 0; */
326: dw(RTS);
327:
328: /* BeginIO */
329: beginiofunc = here();
330: calltrap(deftrap(hardfile_beginio)); dw(RTS);
331:
332: /* AbortIO */
333: abortiofunc = here();
334: calltrap(deftrap(hardfile_abortio)); dw(RTS);
335:
336: /* FuncTable */
337: functable = here();
338: dl(openfunc); /* Open */
339: dl(closefunc); /* Close */
340: dl(expungefunc); /* Expunge */
341: dl(nullfunc); /* Null */
342: dl(beginiofunc); /* BeginIO */
343: dl(abortiofunc); /* AbortIO */
344: dl(0xFFFFFFFF); /* end of table */
345:
346: /* DataTable */
347: datatable = here();
348: dw(0xE000); /* INITBYTE */
349: dw(0x0008); /* LN_TYPE */
350: dw(0x0300); /* NT_DEVICE */
351: dw(0xC000); /* INITLONG */
352: dw(0x000A); /* LN_NAME */
353: dl(devname);
354: dw(0xE000); /* INITBYTE */
355: dw(0x000E); /* LIB_FLAGS */
356: dw(0x0600); /* LIBF_SUMUSED | LIBF_CHANGED */
357: dw(0xD000); /* INITWORD */
358: dw(0x0014); /* LIB_VERSION */
359: dw(0x0004); /* 0.4 */
360: dw(0xD000);
361: dw(0x0016); /* LIB_REVISION */
362: dw(0x0000);
363: dw(0xC000);
364: dw(0x0018); /* LIB_IDSTRING */
365: dl(devid);
366: dw(0x0000); /* end of table */
367:
368: end = here();
369:
370: org(inittable);
371: dl(functable);
372: dl(datatable);
373: dl(initroutine);
374:
375: org(begin + 6);
376: dl(end);
377:
378: org(end);
379: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.