/*
* IDE ATAPI floppy driver.
*
* Copyright (C) 1996-1999 Gadi Oxman <gadio@netvision.net.il>
* Copyright (C) 2000-2002 Paul Bristow <paul@paulbristow.net>
* Copyright (C) 2005 Bartlomiej Zolnierkiewicz
*
* This driver supports the following IDE floppy drives:
*
* LS-120/240 SuperDisk
* Iomega Zip 100/250
* Iomega PC Card Clik!/PocketZip
*
* For a historical changelog see
* Documentation/ide/ChangeLog.ide-floppy.1996-2002
*/
#define DRV_NAME "ide-floppy"
#define IDEFLOPPY_VERSION "1.00"
#include <linux/module.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/major.h>
#include <linux/errno.h>
#include <linux/genhd.h>
#include <linux/slab.h>
#include <linux/cdrom.h>
#include <linux/ide.h>
#include <linux/hdreg.h>
#include <linux/bitops.h>
#include <linux/mutex.h>
#include <linux/scatterlist.h>
#include <scsi/scsi_ioctl.h>
#include <asm/byteorder.h>
#include <linux/irq.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <asm/unaligned.h>
#include "ide-floppy.h"
/* define to see debug info */
#define IDEFLOPPY_DEBUG_LOG 0
/* #define IDEFLOPPY_DEBUG(fmt, args...) printk(KERN_INFO fmt, ## args) */
#define IDEFLOPPY_DEBUG(fmt, args...)
#if IDEFLOPPY_DEBUG_LOG
#define debug_log(fmt, args...) \
printk(KERN_INFO "ide-floppy: " fmt, ## args)
#else
#define debug_log(fmt, args...) do {} while (0)
#endif
/* Some drives require a longer irq timeout. */
#define IDEFLOPPY_WAIT_CMD (5 * WAIT_CMD)
/*
* After each failed packet command we issue a request sense command and retry
* the packet command IDEFLOPPY_MAX_PC_RETRIES times.
*/
#define IDEFLOPPY_MAX_PC_RETRIES 3
/* format capacities descriptor codes */
#define CAPACITY_INVALID 0x00
#define CAPACITY_UNFORMATTED 0x01
#define CAPACITY_CURRENT 0x02
#define CAPACITY_NO_CARTRIDGE 0x03
#define IDEFLOPPY_TICKS_DELAY HZ/20 /* default delay for ZIP 100 (50ms) */
/* Error code returned in rq->errors to the higher part of the driver. */
#define IDEFLOPPY_ERROR_GENERAL 101
static DEFINE_MUTEX(idefloppy_ref_mutex);
#define to_ide_floppy(obj) container_of(obj, struct ide_floppy_obj, kref)
#define ide_floppy_g(disk) \
container_of((disk)->private_data, struct ide_floppy_obj, driver)
static void idefloppy_cleanup_obj(struct kref *);
static struct ide_floppy_obj *ide_floppy_get(struct gendisk *disk)
{
struct ide_floppy_obj *floppy = NULL;
mutex_lock(&idefloppy_ref_mutex);
floppy = ide_floppy_g(disk);
if (floppy) {
if (ide_device_get(floppy->drive))
floppy = NULL;
else
kref_get(&floppy->kref);
}
mutex_unlock(&idefloppy_ref_mutex);
return floppy;
}
static void ide_floppy_put(struct ide_floppy_obj *floppy)
{
ide_drive_t *drive = floppy->drive;
mutex_lock(&idefloppy_ref_mutex);
kref_put(&floppy->kref, idefloppy_cleanup_obj);
ide_device_put(drive);
mutex_unlock(&idefloppy_ref_mutex);
}
/*
* Used to finish servicing a request. For read/write requests, we will call
* ide_end_request to pass to the next buffer.
*/
static int idefloppy_end_request(ide_drive_t *drive, int uptodate, int nsecs)
{
idefloppy_floppy_t *floppy = drive->driver_data;
struct request *rq = HWGROUP(drive)->rq;
int error;
debug_log("Reached %s\n", __func__);
switch (uptodate) {
case 0: error = IDEFLOPPY_ERROR_GENERAL; break;
case 1: error = 0; break;
default: error = uptodate;
}
if (error)
floppy->failed_pc = NULL;
/* Why does this happen? */
if (!rq)
return 0;
if (!blk_special_request(rq)) {
/* our real local end request function */
ide_end_request(drive, uptodate, nsecs);
return 0;
}
rq->errors = error;
/* fixme: need to move this local also */
ide_end_drive_cmd(drive, 0, 0);
return 0;
}
static void idefloppy_update_buffers(ide_drive_t *drive,
struct ide_atapi_pc *pc)
{
struct request *rq = pc->rq;
struct bio *bio = rq->bio;
while ((bio = rq->bio) != NULL)
idefloppy_end_request(drive, 1, 0);
}
static void ide_floppy_callback(ide_drive_t *drive)
{
idefloppy_floppy_t *floppy = drive->driver_data;
struct ide_atapi_pc *pc = floppy->pc;
int uptodate = pc->error ? 0 : 1;
debug_log("Reached %s\n", __func__);
if (floppy->failed_pc == pc)
floppy->failed_pc = NULL;
if (pc->c[0] == GPCMD_READ_10 || pc->c[0] == GPCMD_WRITE_10 ||
(pc->rq && blk_pc_request(pc->rq)))
uptodate = 1; /* FIXME */
else if (pc->c[0] == GPCMD_REQUEST_SENSE) {
u8 *buf = floppy->pc->buf;
if (!pc->error) {
floppy->sense_key = buf[2]