patch-2.1.5 linux/drivers/block/floppy.c
Next file: linux/drivers/block/loop.c
Previous file: linux/arch/i386/mm/init.c
Back to the patch index
Back to the overall index
- Lines: 211
- Date:
Fri Oct 18 13:06:54 1996
- Orig file:
v2.1.4/linux/drivers/block/floppy.c
- Orig date:
Wed Oct 16 10:48:07 1996
diff -u --recursive --new-file v2.1.4/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
@@ -130,7 +130,7 @@
#include <linux/fd.h>
-
+#include <linux/hdreg.h>
#define OLDFDRAWCMD 0x020d /* send a raw command to the FDC */
@@ -918,6 +918,13 @@
static struct tq_struct floppy_tq =
{ 0, 0, 0, 0 };
+static void schedule_bh( void (*handler)(void*) )
+{
+ floppy_tq.routine = (void *)(void *) handler;
+ queue_task_irq(&floppy_tq, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
+}
+
static struct timer_list fd_timer ={ NULL, NULL, 0, 0, 0 };
static void cancel_activity(void)
@@ -1685,12 +1692,9 @@
} while ((ST0 & 0x83) != UNIT(current_drive) && inr == 2);
}
if (handler) {
- if(intr_count >= 2) {
- /* expected interrupt */
- floppy_tq.routine = (void *)(void *) handler;
- queue_task_irq(&floppy_tq, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
- } else
+ if(intr_count >= 2)
+ schedule_bh( (void *)(void *) handler);
+ else
handler();
} else
FDCS->reset = 1;
@@ -1928,9 +1932,7 @@
int ret;
unsigned long flags;
- floppy_tq.routine = (void *)(void *) handler;
- queue_task(&floppy_tq, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
+ schedule_bh((void *)(void *)handler);
INT_OFF;
while(command_status < 2 && NO_SIGNAL){
is_alive("wait_til_done");
@@ -2737,9 +2739,7 @@
if (TESTF(FD_NEED_TWADDLE))
twaddle();
- floppy_tq.routine = (void *)(void *) floppy_start;
- queue_task(&floppy_tq, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
+ schedule_bh( (void *)(void *) floppy_start);
#ifdef DEBUGT
debugt("queue fd request");
#endif
@@ -2754,18 +2754,19 @@
bad_flp_intr,
request_done };
-static struct tq_struct request_tq =
-{ 0, 0, (void *) (void *) redo_fd_request, 0 };
-
static void process_fd_request(void)
{
cont = &rw_cont;
- queue_task(&request_tq, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
+ schedule_bh( (void *)(void *) redo_fd_request);
}
static void do_fd_request(void)
{
+ if(usage_count == 0) {
+ printk("warning: usage count=0, CURRENT=%p exiting\n", CURRENT);
+ printk("sect=%ld cmd=%d\n", CURRENT->sector, CURRENT->cmd);
+ return;
+ }
sti();
if (fdc_busy){
/* fdc busy, this new request will be treated when the
@@ -2839,22 +2840,19 @@
* Misc Ioctl's and support
* ========================
*/
-static int fd_copyout(void *param, const void *address, int size)
+static inline int fd_copyout(void *param, const void *address, int size)
{
- int ret;
-
- ECALL(verify_area(VERIFY_WRITE,param,size));
- copy_to_user(param,(void *) address, size);
- return 0;
+ return copy_to_user(param,address, size) ? -EFAULT : 0;
}
-static int fd_copyin(void *param, void *address, int size)
+static inline int fd_copyin(void *param, void *address, int size)
{
- int ret;
+ return copy_from_user(address, param, size) ? -EFAULT : 0;
+}
- ECALL(verify_area(VERIFY_READ,param,size));
- copy_from_user((void *) address, param, size);
- return 0;
+static inline int write_user_long(unsigned long useraddr, unsigned long value)
+{
+ return put_user(value, (unsigned long *)useraddr) ? -EFAULT : 0;
}
#define COPYOUT(x) ECALL(fd_copyout((void *)param, &(x), sizeof(x)))
@@ -3259,6 +3257,21 @@
return -EINVAL;
}
+static int get_floppy_geometry(int drive, int type, struct floppy_struct **g)
+{
+ if (type)
+ *g = &floppy_type[type];
+ else {
+ LOCK_FDC(drive,0);
+ CALL(poll_drive(0,0));
+ process_fd_request();
+ *g = current_type[drive];
+ }
+ if(!*g)
+ return -ENODEV;
+ return 0;
+}
+
static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long param)
{
@@ -3297,6 +3310,43 @@
cmd = FDEJECT;
}
+ /* generic block device ioctls */
+ switch(cmd) {
+ /* the following have been inspired by the corresponding
+ * code for other block devices. */
+ struct floppy_struct *g;
+ struct hd_geometry *loc;
+
+ case HDIO_GETGEO:
+ loc = (struct hd_geometry *) param;
+ ECALL(get_floppy_geometry(drive, type, &g));
+ ECALL(verify_area(VERIFY_WRITE, loc, sizeof(*loc)));
+ put_user(g->head, &loc->heads);
+ put_user(g->sect, &loc->sectors);
+ put_user(g->track, &loc->cylinders);
+ put_user(0,&loc->start);
+ return 0;
+ case BLKRASET:
+ if(!suser()) return -EACCES;
+ if(param > 0xff) return -EINVAL;
+ read_ahead[MAJOR(inode->i_rdev)] = param;
+ return 0;
+ case BLKRAGET:
+ return write_user_long(param,
+ read_ahead[MAJOR(inode->i_rdev)]);
+ case BLKFLSBUF:
+ if(!suser()) return -EACCES;
+ fsync_dev(inode->i_rdev);
+ invalidate_buffers(inode->i_rdev);
+ return 0;
+
+ case BLKGETSIZE:
+ ECALL(get_floppy_geometry(drive, type, &g));
+ return write_user_long(param, g->size);
+ /* BLKRRPART is not defined as floppies don't have
+ * partition tables */
+ }
+
/* convert the old style command into a new style command */
if ((cmd & 0xff00) == 0x0200) {
ECALL(normalize_0x02xx_ioctl(&cmd, &size));
@@ -3345,15 +3395,9 @@
return set_geometry(cmd, & inparam.g,
drive, type, device);
case FDGETPRM:
- LOCK_FDC(drive,1);
- CALL(poll_drive(1,0));
- process_fd_request();
- if (type)
- outparam = (char *) &floppy_type[type];
- else
- outparam = (char *) current_type[drive];
- if(!outparam)
- return -ENODEV;
+ ECALL(get_floppy_geometry(drive, type,
+ (struct floppy_struct**)
+ &outparam));
break;
case FDMSGON:
@@ -4174,7 +4218,7 @@
j=1;
for (i=current->mm->env_start; i< current->mm->env_end; i ++){
- c= get_fs_byte(i);
+ get_user(c, (char *)i);
if (match){
if (j==99)
c='\0';
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov