Esempio n. 1
0
static int __init
ps2mcfs_init()
{
	TRACE("ps2mcfs_init()\n");
	printk("PlayStation 2 Memory Card file system\n");
	init_completion(&thread_comp);

	if ((ps2mcfs_lock = ps2sif_getlock(PS2LOCK_MC)) == NULL) {
		printk(KERN_ERR "ps2mcfs: Can't get lock\n");
		return (-1);
	}
#ifdef PS2MCFS_DEBUG
	if (ps2mcfs_debug & DBG_LOCK) {
		oldflags = ps2sif_getlockflags(ps2mcfs_lock);
		ps2sif_setlockflags(ps2mcfs_lock,
				    (oldflags | PS2LOCK_FLAG_DEBUG));
	}
#endif

	if (ps2sif_lock_interruptible(ps2mcfs_lock, "mcfs init") < 0)
		return (-1);

	if (ps2mcfs_init_filebuf() < 0 ||
	    ps2mcfs_init_pathcache() < 0 ||
	    ps2mcfs_init_fdcache() < 0 ||
	    ps2mcfs_init_dirent() < 0 ||
	    ps2mcfs_init_root() < 0)
		goto error;

	/*
	 * hook block device read/write routine
	 */
	if (ps2mc_blkrw_hook == NULL)
		ps2mc_blkrw_hook = ps2mcfs_blkrw;

	/*
	 * create and start thread
	 */
	kernel_thread(ps2mcfs_thread, NULL, 0);
	wait_for_completion(&thread_comp);	/* wait the thread ready */
                
	if (register_filesystem(&ps2mcfs_fs_type) < 0)
		goto error;

	ps2sif_unlock(ps2mcfs_lock);

	return (0);

 error:
	ps2mcfs_cleanup();
	ps2sif_unlock(ps2mcfs_lock);

	return (-1);
}
Esempio n. 2
0
void
ps2mcfs_cleanup()
{
	TRACE("ps2mcfs_cleanup()\n");

	ps2sif_lock(ps2mcfs_lock, "mcfs cleanup");
#ifdef PS2MCFS_DEBUG
	if (ps2mcfs_debug & DBG_LOCK)
		ps2sif_setlockflags(ps2mcfs_lock, oldflags);
#endif

	/*
	 * un-hook block device read/write routine
	 */
	if (ps2mc_blkrw_hook == ps2mcfs_blkrw)
		ps2mc_blkrw_hook = NULL;

	/*
	 * stop the thread
	 */
	if (thread_task != NULL) {
            send_sig(SIGKILL, thread_task, 1);
	    wait_for_completion(&thread_comp);	/* wait the thread exit */
	}

	unregister_filesystem(&ps2mcfs_fs_type);
	ps2mcfs_exit_root();
	ps2mcfs_exit_pathcache();
	ps2mcfs_exit_fdcache();
	ps2mcfs_exit_filebuf();
	ps2sif_unlock(ps2mcfs_lock);
}
Esempio n. 3
0
static int
ps2cdvd_drive_status(struct cdrom_device_info *cdi, int arg)
{
	int res;

	/* spinup and re-check disc if the state is in IDLE */
	ps2cdvd_ready();

	if (ps2sif_lock(ps2cdvd_lock, "cdvd_drive_status") != 0)
		return CDS_NO_INFO;

	switch (ps2cdvd_state) {
	case STAT_WAIT_DISC:
	case STAT_INVALID_DISC:
		DPRINT(DBG_INFO, "drive_status=NO_DISC\n");
		res = CDS_NO_DISC;
		break;

	case STAT_READY:
	case STAT_READ:
	case STAT_READ_ERROR_CHECK:
		DPRINT(DBG_INFO, "drive_status=DISC_OK\n");
		res = CDS_DISC_OK;
		break;

	case STAT_ERROR:
	default:
		DPRINT(DBG_INFO, "drive_status=NO_INFO\n");
		res = CDS_NO_INFO;
		break;
	}
	ps2sif_unlock(ps2cdvd_lock);

	return res;
}
Esempio n. 4
0
int
ps2mc_close(int fd)
{
	int res, result;

	res = ps2sif_lock_interruptible(ps2mc_lock, "mc close");
	if (res < 0)
		return (res);

	if (fd < 0 || MAXFILEDESC <= fd || !(openedfd & (1 << fd))) {
		ps2sif_unlock(ps2mc_lock);
		return -EBADF;
	}

	res = 0;
	if (ps2mclib_Close(fd, &result) != 0) {
		/* error */
		printk("ps2mclib_Close() failed\n");
		res = -EIO;
		goto out;
	}

	DPRINT(DBG_INFO, "close(): result=%d\n", result);

	switch (result) {
	case 0: /* succeeded */
		break;
	case 4: /* Bad file number */
		res = -EBADF;
		break;
	default:
		res = -EIO;
		break;
	}

 out:
	openedfd &= ~(1 << fd);
	ps2sif_unlock(ps2mc_lock);
	up(&ps2mc_filesem);
	DPRINT(DBG_FILESEM, "UP file sem(->%d)\n",
	       ps2mc_filesem.count.counter);

	return (res);
}
Esempio n. 5
0
int
ps2sdmixer_setvol(struct ps2sd_mixer_channel *ch, int volr, int voll)
{
	int res;

	if (volr < 0) volr = 0;
	if (100 < volr) volr = 100;
	if (voll < 0) voll = 0;
	if (100 < voll) voll = 100;

	if (ch->mixer != NULL)
		ch->mixer->modified++;
	ch->volr = volr;
	ch->voll = voll;
	ch->vol = (volr << 8) | voll;

	volr = volr * ch->scale / 100;
	voll = voll * ch->scale / 100;

	DPRINT(DBG_MIXER, "%14s R=%04x/L=%04x\n", ch->name, volr, voll);

	res = ps2sif_lock_interruptible(ps2sd_mc.lock, "mixer volume");
	if (res < 0)
		return res;

	if (ch->regr != -1) {
	  res = ps2sdcall_set_reg(ch->regr, volr);
	  if (res < 0) {
		DPRINT(DBG_DIAG, "%s R=%04x/L=%04x: failed, res=%d\n",
		       ch->name, volr, voll, res);
		goto unlock_and_return;
	  }
	}
	if (ch->regl != -1) {
	  res = ps2sdcall_set_reg(ch->regl, voll);
	  if (res < 0) {
		DPRINT(DBG_DIAG, "%s R=%04x/L=%04x: failed, res=%d\n",
		       ch->name, volr, voll, res);
		goto unlock_and_return;
	  }
	}

 unlock_and_return:
	ps2sif_unlock(ps2sd_mc.lock);

	return res;
}
Esempio n. 6
0
static int
ps2mcfs_thread(void *arg)
{

	DPRINT(DBG_INFO, "start thread\n");

	lock_kernel();
	/* get rid of all our resources related to user space */
	daemonize();
	siginitsetinv(&current->blocked,
		      sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM));
	/* Set the name of this process. */
	sprintf(current->comm, "ps2mcfs");
	unlock_kernel();

	thread_task = current;
	complete(&thread_comp); /* notify that we are ready */

	/*
	 * loop
	 */
	while(1) {
		if (ps2sif_lock_interruptible(ps2mcfs_lock, "mcfs_thread")==0){
			ps2mcfs_check_fd();
			ps2sif_unlock(ps2mcfs_lock);
		}

		interruptible_sleep_on_timeout(&thread_wq,
					       PS2MCFS_CHECK_INTERVAL);

		if (signal_pending(current) )
			break;
	}

	DPRINT(DBG_INFO, "exit thread\n");

	thread_task = NULL;
	complete(&thread_comp); /* notify that we've exited */

	return (0);
}
Esempio n. 7
0
ssize_t
ps2mc_read(int fd, const void *buf, size_t size)
{
	int res, result;

	res = ps2sif_lock_interruptible(ps2mc_lock, "mc read");
	if (res < 0)
		return (res);

	res = 0;
	if (ps2mclib_Read(fd, (char*)buf, size, &result) != 0) {
		/* error */
		printk("ps2mclib_Read() failed\n");
		res = -EIO;
		goto out;
	}

	DPRINT(DBG_INFO, "read(): result=%d\n", result);

	if (0 <= result) {
		/* succeeded */
		res = result;
	} else {
		switch (result) {
		case -4: /* Bad file number */
			res = -EBADF;
			break;
		case -5: /* Operation not permitted */
			res = -EPERM;
			break;
		default:
			res = -EIO;
			break;
		}
	}

 out:
	ps2sif_unlock(ps2mc_lock);

	return (res);
}
Esempio n. 8
0
static int
ps2cdvd_reset(struct cdrom_device_info *cdi)
{
	unsigned long flags;

	save_flags(flags);
	cli();
	ps2sif_lock(ps2cdvd_lock, "cdvd_reset");
	RESET_TIMER();
#ifdef CONFIG_PS2_SBIOS_VER_CHECK
	if (0x0201 <= sbios(SB_GETVER, NULL))
		ps2cdvdcall_reset();
#else
	ps2cdvdcall_reset();
#endif
	invalidate_discinfo();
	ps2cdvd_state = ps2cdvd_enter(STAT_WAIT_DISC);
	ps2sif_unlock(ps2cdvd_lock);
	restore_flags(flags);
	return 0;
}
Esempio n. 9
0
static void
ps2cdvd_cleanup()
{

	DPRINT(DBG_VERBOSE, "cleanup\n");

	ps2sif_lock(ps2cdvd_lock, "cdvd_cleanup");
	RESET_TIMER();

	if (initialized & INIT_LABELBUF) {
		DPRINT(DBG_VERBOSE, "free labelbuf %p\n", labelbuf);
		kfree(labelbuf);
	}

	if (initialized & INIT_DATABUF) {
		DPRINT(DBG_VERBOSE, "free databuf %p\n", ps2cdvd_databufx);
		kfree(ps2cdvd_databufx);
	}

#if 0
	if (initialized & INIT_IOPSIDE) 
		ps2cdvd_cleanupiop();
#endif

	if (initialized & INIT_BLKDEV) {
		DPRINT(DBG_VERBOSE, "unregister block device\n");
		unregister_blkdev(MAJOR_NR, "ps2cdvd");
	}

	if (initialized & INIT_CDROM) {
		DPRINT(DBG_VERBOSE, "unregister cdrom\n");
		unregister_cdrom(&ps2cdvd_info);
	}

	blksize_size[MAJOR_NR] = NULL;

	initialized = 0;
	ps2sif_unlock(ps2cdvd_lock);
}
Esempio n. 10
0
off_t
ps2mc_lseek(int fd, off_t offset, int whence)
{
	int res, result;

	res = ps2sif_lock_interruptible(ps2mc_lock, "mc lseek");
	if (res < 0)
		return (res);

	res = 0;
	if (ps2mclib_Seek(fd, offset, whence, &result) != 0) {
		/* error */
		printk("ps2mclib_Seek() failed\n");
		res = -EIO;
		goto out;
	}

	DPRINT(DBG_INFO, "lseek(): result=%d\n", result);

	if (0 <= result) {
		/* succeeded */
		res = result;
	} else {
		switch (result) {
		case 4: /* Bad file number */
			res = -EBADF;
			break;
		default:
			res = -EIO;
			break;
		}
	}

 out:
	ps2sif_unlock(ps2mc_lock);

	return (res);
}
Esempio n. 11
0
int
ps2mc_open(int portslot, const char *path, int mode)
{
	int res, result;
	int iopflags;

	switch (mode & O_ACCMODE) {
	case O_RDONLY:
		iopflags = McRDONLY;
		break;
	case O_WRONLY:
		iopflags = McWRONLY;
		break;
	case O_RDWR:
		iopflags = McRDWR;
		break;
	default:
		return -EINVAL;
	}
	if (mode & O_CREAT)
		iopflags |= McCREAT;

	if ((res = down_interruptible(&ps2mc_filesem)) < 0)
		return (res);
	DPRINT(DBG_FILESEM, "DOWN file sem(->%d)\n",
	       ps2mc_filesem.count.counter);
	res = ps2sif_lock_interruptible(ps2mc_lock, "mc open");
	if (res < 0) {
		up(&ps2mc_filesem);
		return (res);
	}
	if (mode & O_CREAT) {
		/*
		 * This might create a new entry, thereby,
		 * invalidate directory cache.
		 */
		ps2mc_dircache_invalidate(portslot);
	}

	res = 0;
	if (ps2mclib_Open(PS2MC_PORT(portslot), PS2MC_SLOT(portslot),
		      (char *)path, iopflags, &result) != 0) {
		/* error */
		printk("ps2mclib_Open() failed\n");
		res = -EIO;
		goto out;
	}

	DPRINT(DBG_INFO, "open(): card%d%d %s result=%d\n",
	       PS2MC_PORT(portslot), PS2MC_SLOT(portslot), path, result);

	if (0 <= result) {
		/* succeeded */
		res = result;
	} else {
		switch (result) {
		case -7: /* Too many open files */
			res = -EMFILE;
			break;
		default:
			res = -EIO;
			break;
		}
	}

 out:
	if (res < 0) {
		ps2sif_unlock(ps2mc_lock);
		up(&ps2mc_filesem);
		DPRINT(DBG_FILESEM, "UP file sem(->%d)\n",
		       ps2mc_filesem.count.counter);
	} else {
		if (MAXFILEDESC <= res) {
			printk(KERN_CRIT "ps2mc: ERROR: unexpected fd=%d\n",
			       res);
			ps2sif_unlock(ps2mc_lock);
			up(&ps2mc_filesem);
			DPRINT(DBG_FILESEM, "UP file sem(->%d)\n",
			       ps2mc_filesem.count.counter);
		} else {
			openedfd |= (1 << res);
			ps2sif_unlock(ps2mc_lock);
		}
	}
	return (res);
}