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