|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * ami-disk.c: Creates pseudo dev: handler. Copy tracks to rawfile
5: * (used in zfile.c).
6: *
7: * 08/06/97: Modified to avoid a spilled registers error message
8: * when used with the new fd2inline convention.
9: *
10: * Copyright 1996 Samuel Devulder.
11: */
12:
13: /****************************************************************************/
14:
15: #include <exec/execbase.h>
16: #include <exec/memory.h>
17: #include <exec/devices.h>
18: #include <exec/io.h>
19:
20: #include <dos/dos.h>
21:
22: #include <devices/trackdisk.h>
23:
24: /* This should cure the spilled-register problem. An other solution is to */
25: /* compile with -O2 instead of -O3 */
26: #define NO_INLINE_STDARGS
27: #define __NOINLINES__
28:
29: #include <proto/exec.h>
30: #ifndef __SASC
31: #include <proto/alib.h>
32: #endif
33: #include <proto/dos.h>
34:
35: /****************************************************************************/
36:
37: #include "sysconfig.h"
38: #include "sysdeps.h"
39:
40: #include <ctype.h>
41: #include <signal.h>
42:
43: #include "config.h"
44: #include "options.h"
45: #include "memory.h"
46: #include "custom.h"
47: #include "keyboard.h"
48: #include "keybuf.h"
49: #include "disk.h"
50: #include "debug.h"
51: #include "gui.h"
52:
53: /****************************************************************************/
54:
55: char *amiga_dev_path = "DEV:";
56: char *ixemul_dev_path = "/dev/";
57:
58: int readdevice(char *name, char *dst);
59: void initpseudodevices(void);
60: void closepseudodevices(void);
61: char *to_unix_path(char *s);
62: char *from_unix_path(char *s);
63: void split_dir_file(char *src, char **dir, char **file);
64: static void myDoIO(struct IOStdReq *ioreq, LONG CMD, LONG FLAGS, LONG OFFSET,
65: LONG LENGTH, LONG DATA);
66:
67: /****************************************************************************/
68:
69: static char *pseudo_dev_path = "T:DEV";
70:
71: static char pseudo_dev_created = 0;
72: static char pseudo_dev_assigned = 0;
73: static char dfx_done[4];
74:
75: static int device_exists(char *device_name, int device_unit);
76: static int dev_inhibit(char *dev,int on);
77: static void set_req(int ok);
78:
79: /****************************************************************************/
80: /* support routines to handle unix filename convention
81: */
82: char *to_unix_path(char *s)
83: {
84: char *t,*r,*u;
85: int l;
86:
87: #ifndef __GNUC
88: return my_strdup(s);
89: #endif
90:
91: for(u=s,l=0;*u;++u,++l) if(*u=='/' || *u==':') l+=2;
92:
93: r = t = malloc(1+l);
94: if(!r) return NULL;
95:
96: for(u=s;*u && *u!=':';++u);
97: if(*u) {
98: *t++='/';
99: while(*s!=':') *t++=*s++;
100: *t++='/';++s;
101: }
102: while(*s=='/') {*t++='.';*t++='.';*t++=*s++;}
103: while(*s) {
104: if(s[0]=='/' && s[1]=='/') {*t++=*s++;*t++='.';*t++='.';*t++=*s++;}
105: else *t++=*s++;
106: }
107: *t='\0';
108: return r;
109: }
110:
111: /****************************************************************************/
112:
113: char *from_unix_path(char *s)
114: {
115: char *t,*r;
116:
117: r = t = malloc(strlen(s)+1);
118: if(!r) return NULL;
119: #ifndef __GNUC__
120: strcpy(r,s);
121: return r;
122: #endif
123:
124: if(*s=='/') {
125: ++s;
126: while(*s && *s!='/') *t++=*s++;
127: if(*s=='/') {*t++=':';++s;}
128: }
129:
130: while(*s) {
131: if(s[0]=='.' && s[1]=='.') s+=2;
132: else *t++=*s++;
133: }
134:
135: *t='\0';
136:
137: return r;
138: }
139:
140: /****************************************************************************/
141:
142: void split_dir_file(char *src, char **dir, char **file)
143: { /* note: src is freed() */
144: char *s=src;
145:
146: while(*s) ++s;
147: while(s>src && (*s!=':' && *s!='/')) --s;
148: if(*s==':' || *s=='/') {
149: *file = my_strdup(s+1);
150: s[1] = '\0';
151: *dir = my_strdup(src);
152: free(src);
153: } else {
154: *file = src;
155: *dir = my_strdup("");
156: }
157: }
158:
159: /****************************************************************************/
160: /*
161: * Creates peudo DEV:DFx files.
162: */
163: void initpseudodevices(void)
164: {
165: ULONG lock;
166: int i;
167:
168: pseudo_dev_created = 0;
169: pseudo_dev_assigned = 0;
170: for(i=0;i<4;++i) dfx_done[i]=0;
171:
172: /* check if dev: already exists */
173: set_req(0);lock = Lock(amiga_dev_path,SHARED_LOCK);set_req(1);
174: if(!lock) {
175: char name[80];
176: set_req(0);lock = Lock(pseudo_dev_path,SHARED_LOCK);set_req(1);
177: if(!lock) {
178: /* create it */
179: lock = CreateDir(pseudo_dev_path);
180: if(!lock) goto fail;
181: UnLock(lock);lock = Lock(pseudo_dev_path,SHARED_LOCK);
182: pseudo_dev_created = 1;
183: }
184: strcpy(name,amiga_dev_path);
185: if(*name && name[strlen(name)-1]==':') name[strlen(name)-1]='\0';
186: if(!AssignLock(name,lock)) {UnLock(lock);goto fail;}
187: /* the lock is the assign now */
188: pseudo_dev_assigned = 1;
189: } else UnLock(lock);
190:
191: /* Create the dev:DFi entry */
192: for(i=0;i<4;++i) if(device_exists("trackdisk.device",i)) {
193: ULONG fd;
194: char name[80];
195:
196: sprintf(name,"%sDF%d",amiga_dev_path,i);
197: fd = Open(name,MODE_NEWFILE);
198: if(fd) {Close(fd);dfx_done[i]=1;}
199: }
200:
201: return;
202: fail:
203: fprintf(stderr,"Failed to create pseudo dev: entry!\n");
204: }
205:
206: /****************************************************************************/
207: /*
208: * Cleanup pseudo DEV:DFx
209: */
210: void closepseudodevices(void)
211: {
212: int i;
213: for(i=0;i<4;++i) if(dfx_done[i]) {
214: char name[80];
215: sprintf(name,"%sDF%d",amiga_dev_path,i);
216: DeleteFile(name);
217: dfx_done[i] = 0;
218: }
219:
220: if(pseudo_dev_assigned) {
221: char name[80];
222: strcpy(name,amiga_dev_path);
223: if(*name && name[strlen(name)-1]==':') name[strlen(name)-1]='\0';
224: AssignLock(name,NULL);
225: pseudo_dev_assigned = 0;
226: }
227:
228: if(pseudo_dev_created) {
229: DeleteFile(pseudo_dev_path);
230: pseudo_dev_created = 0;
231: }
232: }
233:
234: /****************************************************************************/
235: /*
236: * Enable/Disable system requester
237: */
238: static void set_req(int ok)
239: {
240: static ULONG wd = 0;
241: struct Process *pr;
242:
243: pr = (void*)FindTask(NULL);
244:
245: if(pr->pr_Task.tc_Node.ln_Type != NT_PROCESS) return;
246:
247: if(ok) {
248: pr->pr_WindowPtr = (APTR)wd;
249: }
250: else {
251: wd = (ULONG)pr->pr_WindowPtr;
252: pr->pr_WindowPtr = (APTR)-1;
253: }
254: }
255:
256: /****************************************************************************/
257: /*
258: * checks if a device exists
259: */
260: static int device_exists(char *device_name, int device_unit)
261: {
262: struct IOStdReq *ioreq = NULL;
263: struct MsgPort *port = NULL;
264: int ret = 0;
265:
266: port = CreatePort(0, 0);
267: if(port) {
268: ioreq = CreateStdIO(port);
269: if(ioreq) {
270: if(!OpenDevice(device_name,device_unit,(void*)ioreq,0)) {
271: CloseDevice((void*)ioreq);
272: ret = 1;
273: }
274: DeleteStdIO(ioreq);
275: }
276: DeletePort(port);
277: }
278: return ret;
279: }
280:
281: /****************************************************************************/
282: /*
283: * extract the device and unit form a filename.
284: */
285: static void extract_dev_unit(char *name, char **dev_name, int *dev_unit)
286: {
287: char *s;
288: if(tolower(name[0])=='d' && tolower(name[1])=='f' &&
289: name[2]>='0' && name[2]<='3' && name[3]=='\0') {
290: /* DF0 */
291: *dev_unit = name[2]-'0';
292: *dev_name = strdup("trackdisk.device");
293: } else if((s = strrchr(name,'/'))) {
294: /* trackdisk[.device]/0 */
295: *dev_unit = atoi(s+1);
296: *dev_name = malloc(1 + s-name);
297: if(*dev_name) {
298: strncpy(*dev_name, name, 1 + s-name);
299: (*dev_name)[s-name]='\0';
300: }
301: } else {
302: /* ?? STRANGEDISK0: ?? */
303: *dev_unit = 0;
304: *dev_name = strdup(name);
305: }
306: if(*dev_name) {
307: char *s;
308: if(!(s = strrchr(*dev_name,'.'))) {
309: /* .device is missing */
310: s = malloc(8+strlen(*dev_name));
311: if(s) {
312: sprintf(s,"%s.device",*dev_name);
313: free(*dev_name);
314: *dev_name = s;
315: }
316: }
317: }
318: }
319:
320: /****************************************************************************/
321: /*
322: * copy a device to a FILE*.
323: */
324: static int raw_copy(char *dev_name, int dev_unit, FILE *dst)
325: {
326: struct MsgPort *port = NULL;
327: struct IOStdReq *ioreq = NULL;
328: int tracklen = 512*11;
329: int retstatus = 1;
330: int inhibited = 0;
331: char *buffer = NULL;
332: static char name[] = {'D','F','0','\0'};
333:
334: if(!strcmp(dev_name, "trackdisk.device")) {
335: inhibited = 1;
336: name[2] = '0'+dev_unit;
337: }
338:
339: /* allocate system stuff */
340: if((port = CreatePort(0, 0))) {
341: if((ioreq = CreateStdIO(port))) {
342: if((buffer = AllocMem(tracklen, MEMF_CHIP))) {
343:
344: /* gain access to the device */
345: if(!OpenDevice(dev_name, dev_unit, (struct IORequest*)ioreq, 0)) {
346:
347: /* check if a disk is present */
348: myDoIO(ioreq, TD_CHANGESTATE, 0, -1, -1, -1);
349: if(!ioreq->io_Error && ioreq->io_Actual) {
350: fprintf(stderr,"No disk in %s unit %d !\n", dev_name, dev_unit);
351: retstatus = 0;
352: } else {
353: int tr = 0;
354: int write_protected = 0;
355: /* check if disk is write-protected:
356: myDoIO(ioreq, TD_PROTSTATUS, 0, -1, -1, -1);
357: if(!ioreq->io_Error && ioreq->io_Actual) write_protected = 1;
358: */
359:
360: /* inhibit device */
361: if(inhibited) inhibited = dev_inhibit(name,1);
362:
363: /* read tracks */
364: for(tr = 0; tr < 160; ++tr) {
365: printf("Reading track %2d side %d of %s unit %d \r",
366: tr/2, tr%2, dev_name, dev_unit);
367: fflush(stdout);
368: myDoIO(ioreq, CMD_READ, -1, tracklen*tr, tracklen, (LONG)buffer);
369: if(ioreq->io_Error) printf("Err. on\n");
370: if(fwrite(buffer, 1, tracklen, dst) != (unsigned int)tracklen) {
371: retstatus = 0;
372: break;
373: }
374: }
375:
376: /* ok everything done! */
377: printf(" \r");
378: fflush(stdout);
379:
380: /* stop motor */
381: myDoIO(ioreq, TD_MOTOR, 0, -1, 0, -1);
382:
383: /* uninhibit */
384: if(inhibited) dev_inhibit(name,0);
385: }
386: CloseDevice((struct IORequest*)ioreq); } else retstatus = 0;
387: FreeMem(buffer,tracklen); } else retstatus = 0;
388: DeleteStdIO(ioreq); } else retstatus = 0;
389: DeletePort(port); } else retstatus = 0;
390: return retstatus;
391: }
392:
393: /****************************************************************************/
394: /*
395: * Copy one raw disk to a file.
396: */
397: int readdevice(char *name, char *dst)
398: { /* erhm, I must admit this code is long and ugly! */
399: FILE *f = NULL;
400: char *device_name;
401: int device_unit;
402: int retstatus = 0;
403: #ifdef HAVE_SIGACTION
404: struct sigaction oldsa;
405: int oldsa_valid;
406:
407: /* disable break */
408: oldsa_valid = (0==sigaction(SIGINT, NULL, &oldsa));
409: signal(SIGINT, SIG_IGN); /* <--- gcc complains about something */
410: /* in there but I don't know why. */
411: #endif
412:
413: /* get device name & unit */
414: extract_dev_unit(name, &device_name, &device_unit);
415: if(device_name) {
416: /* if no destination then just check if the device exists */
417: if(dst == NULL)
418: retstatus = device_exists(device_name, device_unit);
419: else {
420: /* open dest file */
421: if((f = fopen(dst,"wb"))) {
422: retstatus = raw_copy(device_name, device_unit, f);
423: fclose(f);
424: }
425: }
426: free(device_name);
427: }
428:
429: #ifdef HAVE_SIGACTION
430: /* enable break */
431: if(oldsa_valid) sigaction(SIGINT, &oldsa, NULL);
432: #endif
433:
434: return retstatus;
435: }
436:
437: /****************************************************************************/
438:
439: static void myDoIO(struct IOStdReq *ioreq, LONG CMD, LONG FLAGS, LONG OFFSET,
440: LONG LENGTH, LONG DATA)
441: {
442: if(CMD>=0) ioreq->io_Command = CMD;
443: if(FLAGS>=0) ioreq->io_Flags = FLAGS;
444: if(OFFSET>=0) ioreq->io_Offset = OFFSET;
445: if(LENGTH>=0) ioreq->io_Length = LENGTH;
446: if(DATA>=0) ioreq->io_Data = (void*)DATA;
447: DoIO((struct IORequest*)ioreq);
448: }
449:
450: /****************************************************************************/
451: /*
452: * Prevents DOS to access a DFx device.
453: */
454: static int dev_inhibit(char *dev,int on)
455: {
456: char buff[10],*s;
457: struct MsgPort *DevPort;
458:
459: if(!*dev) return 0;
460: s=dev;while(*s++);
461: if(s[-2]==':') strcpy(buff,dev); else sprintf(buff,"%s:",dev);
462: if((DevPort = (struct MsgPort*)DeviceProc((STRPTR)buff))) {
463: if(on) {
464: DoPkt(DevPort,ACTION_INHIBIT,DOSTRUE,NULL,NULL,NULL,NULL);
465: return 1;
466: }
467: else DoPkt(DevPort,ACTION_INHIBIT,DOSFALSE,NULL,NULL,NULL,NULL);
468: }
469: return 0;
470: }
471:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.