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