dev_floppy.c revision 5c43205d04ce612cd2940e062ab48365a5b3d42a
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <thread.h>
#include <synch.h>
#include "vold.h"
#include "dev.h"
/* external routines */
/* local routines */
static bool_t floppy_use(char *, char *);
static int floppy_getfd(dev_t);
static void floppy_devmap(vol_t *, int, int);
static void floppy_close(char *, dev_t);
static void floppy_eject(struct devs *);
static int floppy_check(struct devs *);
static bool_t floppy_testpath(char *);
extern bool_t support_nomedia;
#define FLOPPY_MAX 10
static struct devsw floppydevsw = {
floppy_use, /* d_use */
floppy_error, /* d_error */
floppy_getfd, /* d_getfd */
NULL, /* d_poll */
floppy_devmap, /* d_devmap */
floppy_close, /* d_close */
floppy_eject, /* d_eject */
NULL, /* d_find */
floppy_check, /* d_check */
FLOPPY_MTYPE, /* d_mtype */
DRIVE_CLASS, /* d_dtype */
(ulong_t)0, /* d_flags */
(uid_t)0, /* d_uid */
(gid_t)0, /* d_gid */
(mode_t)0, /* d_mode */
floppy_testpath, /* d_test */
floppy_remount /* d_remount */
};
struct fl_priv {
char *fl_blockpath; /* block device for floppy */
char *fl_rawpath; /* character device for floppy */
char *fl_protopath; /* core path */
int fl_tid; /* thread id of watcher thread */
int fl_fd; /* real file descriptor */
int fl_fd_a; /* "hold" exclusive, part a */
int fl_fd_b; /* "hold" exclusive, part b */
char fl_inserted; /* floppy is in the drive */
char fl_pollable; /* true if floppy is pollable */
};
#define FLOPPY_NAMEPROTO "%sc"
/*
* thread stack size
*/
dev_init(void)
{
return (TRUE);
}
static bool_t
{
static void floppy_thread(struct devs *);
static void open_exclusive(struct fl_priv *, int);
char namebuf[MAXPATHLEN];
char *s;
int n;
/*
* we don't do an open for the floppy because it returns ENODEV
* if there isn't a device there. Instead, we just stat the
* device and make sure it's there and is a reasonable type.
*/
/*
* We check to see if the user gave us a "working" path.
* If so, just use it. Else,
* We expect a path of the form:
* /dev/{r}fd#
* We fill in the rest.
*/
/* oh, they gave us a "good" path name */
} else {
/*
* perhaps they gave us "/dev/[r]fdN", and we want
* "/dev/[r]fdNc" (where N <= 0)
*/
return (FALSE);
}
}
/*
* Check to see if vold is already managing the device.
*/
/*
* Remove "nomedia" node if support has changed.
* By sending a HUP signal to vold, dev_use()
* will call here.
*/
}
/*
* Create "nomedia" node if support has changed.
*/
}
return (TRUE);
} else {
return (FALSE);
}
}
"floppy: %s not block or char device (mode 0x%x)\n"),
return (FALSE);
}
/* stick some good stuff in the device hierarchy */
/* he gave us a /dev/[r]diskette# name */
unit = 0;
}
/* assume he's got the old boring name */
} else {
}
} else {
}
/* he gave us a /dev/[r]fd# name */
if (n != 1) {
goto errout;
}
/* make the block name */
/* make the full raw path name */
/* make the full raw path name */
} else {
goto errout;
}
/*
* open them up exclusivly so people can't go around us.
*/
/*
* By default, there will be a "nomedia" node when vold starts
* until volcheck is run.
*/
if (support_nomedia) {
}
if (thr_create(0, FLOPPY_STKSIZE,
return (FALSE);
}
#ifdef DEBUG
#endif
return (TRUE);
return (FALSE);
}
/*ARGSUSED*/
static void
{
}
static int
{
}
/*ARGSUSED*/
static bool_t
{
return (TRUE);
}
/*
* State that must be cleaned up:
* name in the name space
* the "dp"
* any pointers to the media
* eject any existing media
* the priv structure
*/
/*
* XXX: a bug still exists here. we have a thread polling on this
* XXX: device in the kernel, we need to get rid of this also.
* XXX: since we're going to move the waiter thread up to the
* XXX: user level, it'll be easier to kill off as part of the
* XXX: cleanup of the device private data.
*/
static void
{
char namebuf[MAXPATHLEN];
"stat of %s; %m\n"), namebuf);
return;
}
} else {
}
} else {
}
return;
}
/* get our private data */
/*
* Take care of the listner thread.
*/
/* apparently we have to kick it out of the cv_wait */
/*
* If there is a volume inserted in this device...
*/
/*
* Clean up the name space and the device maps
* to remove references to any volume that might
* be in the device right now.
* This crap with the flags is to keep the
* "poll" from being relaunched by this function.
* yes, its a hack and there should be a better way.
*/
} else {
}
return;
}
}
/*
* Clean up the names in the name space.
*/
/*
* close the file descriptors we're holding open.
*/
}
}
/*
* free the private data we've allocated.
*/
/*
* Free the dp, so no one points at us anymore.
*/
dev_freedp(dp);
}
static void
{
extern int vold_running;
extern cond_t running_cv;
extern mutex_t running_mutex;
/* ensure that the main loop is ready */
(void) mutex_lock(&running_mutex);
while (vold_running == 0) {
}
(void) mutex_unlock(&running_mutex);
/* ensure the floppy is open */
flp->fl_rawpath);
return;
}
}
/* get the drive characteristics */
} else {
/* if floppy pollable then set flag */
flp->fl_rawpath);
}
/* if floppy is ejectable then set flag */
if (fdchar.fdd_ejectable == 0) {
flp->fl_rawpath);
}
}
/* if floppy is pollable then go in to a polling loop */
if (flp->fl_pollable) {
}
}
static void
{
static int reopen_floppy(struct fl_priv *);
int rval = 0;
struct vioc_event vie;
/*CONSTCOND*/
while (1) {
(void) sleep(2);
continue;
}
/*
* A floppy is IN the drive
* and we don't think there's anything there...
*/
if (!(rval & FDGC_CURRENT) &&
!dev_present(dp) &&
!flp->fl_inserted) {
}
#ifdef FDGETCHANGE_NOW_WORKING
/*
* A floppy is NOT in the drive
* and we think there's something there...
*/
if (rval & FDGC_CURRENT) {
#ifdef DEBUG
#endif
if (dev_present(dp)) {
sizeof (struct vioc_event));
}
}
#endif /* FDGETCHANGE_NOW_WORKING */
}
/*NOTREACHED*/
}
/*
* clean up after an eject event
*/
static void
{
/* ensure we're alone */
/* clear "inserted" flag */
/* release lock */
}
static int
{
static int reopen_floppy(struct fl_priv *);
int rval = 0;
struct vioc_event vie;
extern int vold_running;
extern cond_t running_cv;
extern mutex_t running_mutex;
int generated_event = 0;
int ret_val = 0;
(void) mutex_lock(&running_mutex);
while (vold_running == 0) {
}
(void) mutex_unlock(&running_mutex);
/*
* If we know the floppy is there, there's no need to check
* again.
*/
goto out;
}
/*
* We only want to do this ioctl every 2 seconds, so we
* do our rate limiting right here.
*/
/*
* check for that corner case where time has been set
* backwards (;-(
*/
"floppy: system time set backwards -- adjusting\n"));
} else {
debug(5,
"floppy_check: skipping volcheck -- too soon\n");
goto out;
}
}
/* ensure floppy is open */
flp->fl_rawpath);
goto out;
}
}
/* find out if floppy's currently in the drive */
goto out;
}
/*
* A floppy is IN the drive
* and we don't think there's anything there...
*/
generated_event = 1;
}
out:
if (generated_event) {
ret_val = 2;
} else if (flp->fl_inserted) {
ret_val = 1;
}
return (ret_val);
}
/*
* Just hang on to these devices. If they aren't there or the
* open fails, don't sweat it.
*/
static void
{
char namebuf[MAXPATHLEN];
}
static int
{
int rdonly = 0;
/*
* XXX: boy, is this a hack. This works around a
* bug in the floppy driver were you can't seem to read
* from a file descriptor you've opened
* O_NDELAY where there
* wasn't any media in the drive.
* This open takes forever, by the way...
*/
rdonly = 1;
} else {
}
}
flp->fl_rawpath);
}
return (rdonly);
}
/*
* Return true if the path points at a floppy device, as it's understood
* by this code.
*/
static bool_t
floppy_testpath(char *p)
{
int fd;
char *rp;
int rval;
return (FALSE);
}
/* see if device already being used */
return (TRUE);
} else {
return (FALSE);
}
}
/* make sure our path is a raw device */
return (FALSE);
}
return (FALSE);
}
return (FALSE);
}
return (TRUE);
}
static bool_t
{
/*
* There's no need to find the new default file
* descriptor for a floppy after it has been
* formatted and repartitioned. The default
* file descriptor for a floppy never changes.
*/
/*
* We need to confound lint while creating a dummy
* function that does nothing with its argument.
*/
return (TRUE);
} else {
return (FALSE);
}
}