linux/drivers/scsi/imm.c

// SPDX-License-Identifier: GPL-2.0-only
/* imm.c   --  low level driver for the IOMEGA MatchMaker
 * parallel port SCSI host adapter.
 * 
 * (The IMM is the embedded controller in the ZIP Plus drive.)
 * 
 * My unofficial company acronym list is 21 pages long:
 *      FLA:    Four letter acronym with built in facility for
 *              future expansion to five letters.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/blkdev.h>
#include <linux/parport.h>
#include <linux/workqueue.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <asm/io.h>

#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>

/* The following #define is to avoid a clash with hosts.c */
#define IMM_PROBE_SPP
#define IMM_PROBE_PS2
#define IMM_PROBE_ECR
#define IMM_PROBE_EPP17
#define IMM_PROBE_EPP19


imm_struct;

static void imm_reset_pulse(unsigned int base);
static int device_check(imm_struct *dev, bool autodetect);

#include "imm.h"

static unsigned int mode =;
module_param(mode, uint, 0644);
MODULE_PARM_DESC();

static inline imm_struct *imm_dev(struct Scsi_Host *host)
{}

static DEFINE_SPINLOCK(arbitration_lock);

static void got_it(imm_struct *dev)
{}

static void imm_wakeup(void *ref)
{}

static int imm_pb_claim(imm_struct *dev)
{}

static void imm_pb_dismiss(imm_struct *dev)
{}

static inline void imm_pb_release(imm_struct *dev)
{}

/* This is to give the imm driver a way to modify the timings (and other
 * parameters) by writing to the /proc/scsi/imm/0 file.
 * Very simple method really... (Too simple, no error checking :( )
 * Reason: Kernel hackers HATE having to unload and reload modules for
 * testing...
 * Also gives a method to use a script to obtain optimum timings (TODO)
 */
static int imm_write_info(struct Scsi_Host *host, char *buffer, int length)
{}

static int imm_show_info(struct seq_file *m, struct Scsi_Host *host)
{}

#if IMM_DEBUG > 0
#define imm_fail
static inline void
imm_fail_func(imm_struct *dev, int error_code)
#else
static inline void
imm_fail(imm_struct *dev, int error_code)
#endif
{}

/*
 * Wait for the high bit to be set.
 * 
 * In principle, this could be tied to an interrupt, but the adapter
 * doesn't appear to be designed to support interrupts.  We spin on
 * the 0x80 ready bit. 
 */
static unsigned char imm_wait(imm_struct *dev)
{}

static int imm_negotiate(imm_struct * tmp)
{}

/* 
 * Clear EPP timeout bit. 
 */
static inline void epp_reset(unsigned short ppb)
{}

/* 
 * Wait for empty ECP fifo (if we are in ECP fifo mode only)
 */
static inline void ecp_sync(imm_struct *dev)
{}

static int imm_byte_out(unsigned short base, const char *buffer, int len)
{}

static int imm_nibble_in(unsigned short base, char *buffer, int len)
{}

static int imm_byte_in(unsigned short base, char *buffer, int len)
{}

static int imm_out(imm_struct *dev, char *buffer, int len)
{}

static int imm_in(imm_struct *dev, char *buffer, int len)
{}

static int imm_cpp(unsigned short ppb, unsigned char b)
{}

static inline int imm_connect(imm_struct *dev, int flag)
{}

static void imm_disconnect(imm_struct *dev)
{}

static int imm_select(imm_struct *dev, int target)
{}

static int imm_init(imm_struct *dev)
{}

static inline int imm_send_command(struct scsi_cmnd *cmd)
{}

/*
 * The bulk flag enables some optimisations in the data transfer loops,
 * it should be true for any command that transfers data in integral
 * numbers of sectors.
 * 
 * The driver appears to remain stable if we speed up the parallel port
 * i/o in this function, but not elsewhere.
 */
static int imm_completion(struct scsi_cmnd *const cmd)
{}

/*
 * Since the IMM itself doesn't generate interrupts, we use
 * the scheduler's task queue to generate a stream of call-backs and
 * complete the request when the drive is ready.
 */
static void imm_interrupt(struct work_struct *work)
{}

static int imm_engine(imm_struct *dev, struct scsi_cmnd *const cmd)
{}

static int imm_queuecommand_lck(struct scsi_cmnd *cmd)
{}

static DEF_SCSI_QCMD(imm_queuecommand)

/*
 * Apparently the disk->capacity attribute is off by 1 sector 
 * for all disk drives.  We add the one here, but it should really
 * be done in sd.c.  Even if it gets fixed there, this will still
 * work.
 */
static int imm_biosparam(struct scsi_device *sdev, struct block_device *dev,
			 sector_t capacity, int ip[])
{}

static int imm_abort(struct scsi_cmnd *cmd)
{}

static void imm_reset_pulse(unsigned int base)
{}

static int imm_reset(struct scsi_cmnd *cmd)
{}

static int device_check(imm_struct *dev, bool autodetect)
{}

static const struct scsi_host_template imm_template =;

/***************************************************************************
 *                   Parallel port probing routines                        *
 ***************************************************************************/

static LIST_HEAD(imm_hosts);

/*
 * Finds the first available device number that can be alloted to the
 * new imm device and returns the address of the previous node so that
 * we can add to the tail and have a list in the ascending order.
 */

static inline imm_struct *find_parent(void)
{}

static int __imm_attach(struct parport *pb)
{}

static void imm_attach(struct parport *pb)
{}

static void imm_detach(struct parport *pb)
{}

static struct parport_driver imm_driver =;
module_parport_driver();

MODULE_DESCRIPTION();
MODULE_LICENSE();