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