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