|
|
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.