--- BasiliskII/src/Unix/sys_unix.cpp 2000/04/10 18:53:07 1.7 +++ BasiliskII/src/Unix/sys_unix.cpp 2004/01/12 15:29:25 1.21 @@ -1,7 +1,7 @@ /* * sys_unix.cpp - System dependent routines, Unix implementation * - * Basilisk II (C) 1997-2000 Christian Bauer + * Basilisk II (C) 1997-2004 Christian Bauer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,11 +31,12 @@ #include #include #include +#include #ifdef __NR__llseek -_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo, loff_t *, res, uint, wh); +_syscall5(int, _llseek, unsigned int, fd, unsigned long, hi, unsigned long, lo, loff_t *, res, unsigned int, wh); #else -static int _llseek(uint fd, ulong hi, ulong lo, loff_t *res, uint wh) +static int _llseek(unsigned int fd, unsigned long hi, unsigned long lo, loff_t *res, unsigned int wh) { if (hi) return -1; @@ -76,6 +77,9 @@ struct file_handle { int cdrom_cap; // CD-ROM capability flags (only valid if is_cdrom is true) #elif defined(__FreeBSD__) struct ioc_capability cdrom_cap; +#elif defined(__APPLE__) && defined(__MACH__) + char *ioctl_name; // For CDs on OS X - a device for special ioctls + int ioctl_fd; #endif }; @@ -120,11 +124,34 @@ void SysMountFirstFloppy(void) void SysAddFloppyPrefs(void) { #if defined(__linux__) - PrefsAddString("floppy", "/dev/fd0H1440"); - PrefsAddString("floppy", "/dev/fd1H1440"); + if (access("/dev/.devfsd", F_OK) < 0) { + PrefsAddString("floppy", "/dev/fd0u1440"); + PrefsAddString("floppy", "/dev/fd1u1440"); + } else { + DIR *fd_dir = opendir("/dev/floppy"); + if (fd_dir) { + struct dirent *floppy_dev; + while ((floppy_dev = readdir(fd_dir)) != NULL) { + if (strstr(floppy_dev->d_name, "u1440") != NULL) { + char fd_dev[20]; + sprintf(fd_dev, "/dev/floppy/%s", floppy_dev->d_name); + PrefsAddString("floppy", fd_dev); + } + } + closedir(fd_dir); + } + } #elif defined(__NetBSD__) PrefsAddString("floppy", "/dev/fd0a"); PrefsAddString("floppy", "/dev/fd1a"); +#elif defined(__APPLE__) && defined(__MACH__) + // FIXME: We assume an Aqua build causes to + // be included, thusly enabling this part of code that would cause + // Basilisk II to hang otherwise. +#ifdef MAC_OS_X_VERSION_10_0 + PrefsAddString("floppy", "/dev/fd/0"); + PrefsAddString("floppy", "/dev/fd/1"); +#endif #else PrefsAddString("floppy", "/dev/fd0"); PrefsAddString("floppy", "/dev/fd1"); @@ -135,6 +162,9 @@ void SysAddFloppyPrefs(void) /* * This gets called when no "disk" prefs items are found * It scans for available HFS volumes and adds appropriate prefs items + * On OS X, we could do the same, but on an OS X machine I think it is + * very unlikely that any mounted volumes would contain a system which + * is old enough to boot a 68k Mac, so we just do nothing here for now. */ void SysAddDiskPrefs(void) @@ -146,7 +176,7 @@ void SysAddDiskPrefs(void) while(fgets(line, 255, f)) { // Read line int len = strlen(line); - if (len == 0) + if (len == 0 || line[0] == '#') continue; line[len-1] = 0; @@ -176,11 +206,28 @@ void SysAddCDROMPrefs(void) return; #if defined(__linux__) - PrefsAddString("cdrom", "/dev/cdrom"); -#elif defined(__FreeBSD__) + if (access("/dev/.devfsd", F_OK) < 0) + PrefsAddString("cdrom", "/dev/cdrom"); + else { + DIR *cd_dir = opendir("/dev/cdroms"); + if (cd_dir) { + struct dirent *cdrom_dev; + while ((cdrom_dev = readdir(cd_dir)) != NULL) { + if (strcmp(cdrom_dev->d_name, ".") != 0 && strcmp(cdrom_dev->d_name, "..") != 0) { + char cd_dev[20]; + sprintf(cd_dev, "/dev/cdroms/%s", cdrom_dev->d_name); + PrefsAddString("cdrom", cd_dev); + } + } + closedir(cd_dir); + } + } +#elif defined(__APPLE__) && defined(__MACH__) && defined(MAC_OS_X_VERSION_10_0) + extern void DarwinAddCDROMPrefs(void); + + DarwinAddCDROMPrefs(); +#elif defined(__FreeBSD__) || defined(__NetBSD__) PrefsAddString("cdrom", "/dev/cd0c"); -#elif defined(__NetBSD__) - PrefsAddString("cdrom", "/dev/cd0d"); #endif } @@ -192,14 +239,29 @@ void SysAddCDROMPrefs(void) void SysAddSerialPrefs(void) { #if defined(__linux__) - PrefsAddString("seriala", "/dev/ttyS0"); - PrefsAddString("serialb", "/dev/ttyS1"); + if (access("/dev/.devfsd", F_OK) < 0) { + PrefsAddString("seriala", "/dev/ttyS0"); + PrefsAddString("serialb", "/dev/ttyS1"); + } else { + PrefsAddString("seriala", "/dev/tts/0"); + PrefsAddString("serialb", "/dev/tts/1"); + } #elif defined(__FreeBSD__) PrefsAddString("seriala", "/dev/cuaa0"); PrefsAddString("serialb", "/dev/cuaa1"); #elif defined(__NetBSD__) PrefsAddString("seriala", "/dev/tty00"); PrefsAddString("serialb", "/dev/tty01"); +#elif defined(__APPLE__) && defined(__MACH__) + // FIXME: We assume an Aqua build causes to + // be included, thusly enabling this part of code that would cause + // Basilisk II to hang otherwise. +#ifdef MAC_OS_X_VERSION_10_0 + PrefsAddString("seriala", "/dev/ttys0"); + PrefsAddString("serialb", "/dev/ttys1"); +#endif +// PrefsAddString("seriala", "/dev/cu.modem"); +// PrefsAddString("serialb", "/dev/cu.IrDA-IrCOMMch-b"); #endif } @@ -252,6 +314,26 @@ void *Sys_open(const char *name, bool re bool is_cdrom = strncmp(name, "/dev/cd", 7) == 0; #endif +#if defined(__APPLE__) && defined(__MACH__) + // + // There is no set filename in /dev which is the cdrom, + // so we have to see if it is any of the devices that we found earlier + // + const char *cdrom; + int tmp = 0; + + while ( (cdrom = PrefsFindString("cdrom", tmp) ) != NULL ) + { + if ( strcmp(name, cdrom) == 0 ) + { + is_cdrom = 1; + read_only = 1; + break; + } + ++tmp; + } +#endif + D(bug("Sys_open(%s, %s)\n", name, read_only ? "read-only" : "read/write")); // Check if write access is allowed, set read-only flag if not @@ -273,7 +355,7 @@ void *Sys_open(const char *name, bool re } // Open file/device -#if defined(__linux__) +#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) int fd = open(name, (read_only ? O_RDONLY : O_RDWR) | (is_cdrom ? O_NONBLOCK : 0)); #else int fd = open(name, read_only ? O_RDONLY : O_RDWR); @@ -334,6 +416,35 @@ void *Sys_open(const char *name, bool re fh->is_floppy = ((st.st_rdev >> 16) == 2); #endif } +#if defined(__APPLE__) && defined(__MACH__) + + // In OS X, the device name is OK for sending ioctls to, + // but not for reading raw CDROM data from. + // (it seems to have extra data padded in) + // + // So, we keep the already opened fiole handle, + // and open a slightly different file for CDROM data + // + if ( is_cdrom ) + { + fh->ioctl_name = fh->name; + fh->ioctl_fd = fh->fd; + + fh->name = (char *) malloc(strlen(name) + 2); + if ( fh->name ) + { + *fh->name = '\0'; + strcat(fh->name, name); + strcat(fh->name, "s1"); + fh->fd = open(fh->name, (read_only ? O_RDONLY : O_RDWR)); + if ( fh->fd < 0 ) { + printf("WARNING: Cannot open %s (%s)\n", + fh->name, strerror(errno)); + return NULL; + } + } + } +#endif } } if (fh->is_floppy && first_floppy == NULL) @@ -456,6 +567,8 @@ void SysEject(void *arg) fsync(fh->fd); ioctl(fh->fd, FDFLUSH); ioctl(fh->fd, FDEJECT); + close(fh->fd); // Close and reopen so the driver will see the media change + fh->fd = open(fh->name, fh->read_only ? O_RDONLY : O_RDWR); } else if (fh->is_cdrom) { ioctl(fh->fd, CDROMEJECT); close(fh->fd); // Close and reopen so the driver will see the media change @@ -464,13 +577,38 @@ void SysEject(void *arg) #elif defined(__FreeBSD__) || defined(__NetBSD__) if (fh->is_floppy) { fsync(fh->fd); - //ioctl(fh->fd, FDFLUSH); - //ioctl(fh->fd, FDEJECT); } else if (fh->is_cdrom) { ioctl(fh->fd, CDIOCEJECT); close(fh->fd); // Close and reopen so the driver will see the media change fh->fd = open(fh->name, O_RDONLY | O_NONBLOCK); } +#elif defined(__APPLE__) && defined(__MACH__) + if ( fh->is_cdrom ) { + + // Stolen from IOKit/storage/IOMediaBSDClient.h + #define DKIOCEJECT _IO('d', 21) + + close(fh->fd); + if ( ioctl(fh->ioctl_fd, DKIOCEJECT) < 0 ) + { + printf("ioctl(DKIOCEJECT) failed on file %s: %s\n", + fh->ioctl_name, strerror(errno)); + + // If we are running OSX, the device may be is busy + // due to the Finder having the disk mounted and open, + // so we have to use another method. + + // The only problem is that this takes about 5 seconds: + + char *cmd = (char *) malloc(30+sizeof(fh->name)); + + if ( ! cmd ) + return; + close(fh->ioctl_fd); + sprintf(cmd, "diskutil eject %s 2>&1 >/dev/null", fh->name); + system(cmd); + } + } #endif } @@ -547,8 +685,25 @@ bool SysIsDiskInserted(void *arg) } else if (fh->is_floppy) { char block[512]; lseek(fh->fd, 0, SEEK_SET); - return read(fh->fd, block, 512) == 512; + ssize_t actual = read(fh->fd, block, 512); + if (actual < 0) { + close(fh->fd); // Close and reopen so the driver will see the media change + fh->fd = open(fh->name, fh->read_only ? O_RDONLY : O_RDWR); + actual = read(fh->fd, block, 512); + } + return actual == 512; } else if (fh->is_cdrom) { +#ifdef CDROM_MEDIA_CHANGED + if (fh->cdrom_cap & CDC_MEDIA_CHANGED) { + // If we don't do this, all attempts to read from a disc fail + // once the tray has been opened (altough the TOC reads fine). + // Can somebody explain this to me? + if (ioctl(fh->fd, CDROM_MEDIA_CHANGED) == 1) { + close(fh->fd); + fh->fd = open(fh->name, O_RDONLY | O_NONBLOCK); + } + } +#endif #ifdef CDROM_DRIVE_STATUS if (fh->cdrom_cap & CDC_DRIVE_STATUS) { return ioctl(fh->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT) == CDS_DISC_OK; @@ -660,6 +815,10 @@ bool SysCDReadTOC(void *arg, uint8 *toc) *toc++ = toc_size >> 8; *toc++ = toc_size & 0xff; return true; +#elif defined(__APPLE__) && defined(__MACH__) && defined(MAC_OS_X_VERSION_10_2) + extern bool DarwinCDReadTOC(char *name, uint8 *toc); + + return DarwinCDReadTOC(fh->name, toc); #elif defined(__FreeBSD__) uint8 *p = toc + 2; @@ -730,6 +889,8 @@ bool SysCDReadTOC(void *arg, uint8 *toc) *toc++ = toc_size >> 8; *toc++ = toc_size & 0xff; return true; +#else + return false; #endif } else return false; @@ -793,6 +954,8 @@ bool SysCDGetPosition(void *arg, uint8 * *pos++ = chan.data->what.position.reladdr.msf.second; *pos++ = chan.data->what.position.reladdr.msf.frame; return true; +#else + return false; #endif } else return false; @@ -828,6 +991,8 @@ bool SysCDPlay(void *arg, uint8 start_m, play.end_s = end_s; play.end_f = end_f; return ioctl(fh->fd, CDIOCPLAYMSF, &play) == 0; +#else + return false; #endif } else return false; @@ -849,6 +1014,8 @@ bool SysCDPause(void *arg) return ioctl(fh->fd, CDROMPAUSE) == 0; #elif defined(__FreeBSD__) || defined(__NetBSD__) return ioctl(fh->fd, CDIOCPAUSE) == 0; +#else + return false; #endif } else return false; @@ -870,6 +1037,8 @@ bool SysCDResume(void *arg) return ioctl(fh->fd, CDROMRESUME) == 0; #elif defined(__FreeBSD__) || defined(__NetBSD__) return ioctl(fh->fd, CDIOCRESUME) == 0; +#else + return false; #endif } else return false; @@ -891,6 +1060,8 @@ bool SysCDStop(void *arg, uint8 lead_out return ioctl(fh->fd, CDROMSTOP) == 0; #elif defined(__FreeBSD__) || defined(__NetBSD__) return ioctl(fh->fd, CDIOCSTOP) == 0; +#else + return false; #endif } else return false;