Commit 68a4f84a authored by Alex Henrie's avatar Alex Henrie Committed by Martin K. Petersen
Browse files

scsi: ppa: Add a module parameter for the transfer mode



I have an Iomega Z100P2 zip drive, but it does not work with my StarTech
PEX1P2 AX99100 PCIe parallel port, which evidently does not support 16-bit
or 32-bit EPP. Currently the only way to tell the PPA driver to use 8-bit
EPP is to write 'mode=3' to /proc/scsi/ppa/*, but the driver doesn't
actually distinguish between the three EPP modes and still tries to use
16-bit or 32-bit EPP. And even if writing to that file did make the driver
use 8-bit EPP, it still wouldn't do me any good because by the time that
file exists, the drive has already failed to initialize.

Add a new parameter /sys/module/ppa/mode to set the transfer mode before
initializing the drive. This parameter replaces the use of
CONFIG_SCSI_IZIP_EPP16 in the PPA driver.

At the same time, default to 8-bit EPP. 16-bit and 32-bit EPP are not
necessary for the drive to function, nor are they part of the IEEE 1284
standard, so the driver should not assume that they are available.

Signed-off-by: default avatarAlex Henrie <alexhenrie24@gmail.com>
Link: https://lore.kernel.org/r/20230807155856.362864-2-alexhenrie24@gmail.com


Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent b68442eb
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -836,7 +836,7 @@ config SCSI_IMM

config SCSI_IZIP_EPP16
	bool "ppa/imm option - Use slow (but safe) EPP-16"
	depends on SCSI_PPA || SCSI_IMM
	depends on SCSI_IMM
	help
	  EPP (Enhanced Parallel Port) is a standard for parallel ports which
	  allows them to act as expansion buses that can handle up to 64
+42 −40
Original line number Diff line number Diff line
@@ -45,6 +45,11 @@ typedef struct {

#include  "ppa.h"

static unsigned int mode = PPA_AUTODETECT;
module_param(mode, uint, 0644);
MODULE_PARM_DESC(mode, "Transfer mode (0 = Autodetect, 1 = SPP 4-bit, "
	"2 = SPP 8-bit, 3 = EPP 8-bit, 4 = EPP 16-bit, 5 = EPP 32-bit");

static struct scsi_pointer *ppa_scsi_pointer(struct scsi_cmnd *cmd)
{
	return scsi_cmd_priv(cmd);
@@ -157,7 +162,7 @@ static int ppa_show_info(struct seq_file *m, struct Scsi_Host *host)
	return 0;
}

static int device_check(ppa_struct *dev);
static int device_check(ppa_struct *dev, bool autodetect);

#if PPA_DEBUG > 0
#define ppa_fail(x,y) printk("ppa: ppa_fail(%i) from %s at line %d\n",\
@@ -302,13 +307,10 @@ static int ppa_out(ppa_struct *dev, char *buffer, int len)
	case PPA_EPP_8:
		epp_reset(ppb);
		w_ctr(ppb, 0x4);
#ifdef CONFIG_SCSI_IZIP_EPP16
		if (!(((long) buffer | len) & 0x01))
			outsw(ppb + 4, buffer, len >> 1);
#else
		if (!(((long) buffer | len) & 0x03))
		if (dev->mode == PPA_EPP_32 && !(((long) buffer | len) & 0x01))
			outsl(ppb + 4, buffer, len >> 2);
#endif
		else if (dev->mode == PPA_EPP_16 && !(((long) buffer | len) & 0x03))
			outsw(ppb + 4, buffer, len >> 1);
		else
			outsb(ppb + 4, buffer, len);
		w_ctr(ppb, 0xc);
@@ -355,13 +357,10 @@ static int ppa_in(ppa_struct *dev, char *buffer, int len)
	case PPA_EPP_8:
		epp_reset(ppb);
		w_ctr(ppb, 0x24);
#ifdef CONFIG_SCSI_IZIP_EPP16
		if (!(((long) buffer | len) & 0x01))
			insw(ppb + 4, buffer, len >> 1);
#else
		if (!(((long) buffer | len) & 0x03))
		if (dev->mode == PPA_EPP_32 && !(((long) buffer | len) & 0x03))
			insl(ppb + 4, buffer, len >> 2);
#endif
		else if (dev->mode == PPA_EPP_16 && !(((long) buffer | len) & 0x01))
			insw(ppb + 4, buffer, len >> 1);
		else
			insb(ppb + 4, buffer, len);
		w_ctr(ppb, 0x2c);
@@ -469,6 +468,27 @@ static int ppa_init(ppa_struct *dev)
{
	int retv;
	unsigned short ppb = dev->base;
	bool autodetect = dev->mode == PPA_AUTODETECT;

	if (autodetect) {
		int modes = dev->dev->port->modes;
		int ppb_hi = dev->dev->port->base_hi;

		/* Mode detection works up the chain of speed
		 * This avoids a nasty if-then-else-if-... tree
		 */
		dev->mode = PPA_NIBBLE;

		if (modes & PARPORT_MODE_TRISTATE)
			dev->mode = PPA_PS2;

		if (modes & PARPORT_MODE_ECP) {
			w_ecr(ppb_hi, 0x20);
			dev->mode = PPA_PS2;
		}
		if ((modes & PARPORT_MODE_EPP) && (modes & PARPORT_MODE_ECP))
			w_ecr(ppb_hi, 0x80);
	}

	ppa_disconnect(dev);
	ppa_connect(dev, CONNECT_NORMAL);
@@ -492,7 +512,7 @@ static int ppa_init(ppa_struct *dev)
	if (retv)
		return -EIO;

	return device_check(dev);
	return device_check(dev, autodetect);
}

static inline int ppa_send_command(struct scsi_cmnd *cmd)
@@ -883,7 +903,7 @@ static int ppa_reset(struct scsi_cmnd *cmd)
	return SUCCESS;
}

static int device_check(ppa_struct *dev)
static int device_check(ppa_struct *dev, bool autodetect)
{
	/* This routine looks for a device and then attempts to use EPP
	   to send a command. If all goes as planned then EPP is available. */
@@ -895,8 +915,8 @@ static int device_check(ppa_struct *dev)
	old_mode = dev->mode;
	for (loop = 0; loop < 8; loop++) {
		/* Attempt to use EPP for Test Unit Ready */
		if ((ppb & 0x0007) == 0x0000)
			dev->mode = PPA_EPP_32;
		if (autodetect && (ppb & 0x0007) == 0x0000)
			dev->mode = PPA_EPP_8;

second_pass:
		ppa_connect(dev, CONNECT_EPP_MAYBE);
@@ -924,7 +944,7 @@ static int device_check(ppa_struct *dev)
			udelay(1000);
			ppa_disconnect(dev);
			udelay(1000);
			if (dev->mode == PPA_EPP_32) {
			if (dev->mode != old_mode) {
				dev->mode = old_mode;
				goto second_pass;
			}
@@ -947,7 +967,7 @@ static int device_check(ppa_struct *dev)
			udelay(1000);
			ppa_disconnect(dev);
			udelay(1000);
			if (dev->mode == PPA_EPP_32) {
			if (dev->mode != old_mode) {
				dev->mode = old_mode;
				goto second_pass;
			}
@@ -1026,7 +1046,6 @@ static int __ppa_attach(struct parport *pb)
	DEFINE_WAIT(wait);
	ppa_struct *dev, *temp;
	int ports;
	int modes, ppb, ppb_hi;
	int err = -ENOMEM;
	struct pardev_cb ppa_cb;

@@ -1034,7 +1053,7 @@ static int __ppa_attach(struct parport *pb)
	if (!dev)
		return -ENOMEM;
	dev->base = -1;
	dev->mode = PPA_AUTODETECT;
	dev->mode = mode < PPA_UNKNOWN ? mode : PPA_AUTODETECT;
	dev->recon_tmo = PPA_RECON_TMO;
	init_waitqueue_head(&waiting);
	temp = find_parent();
@@ -1069,25 +1088,8 @@ static int __ppa_attach(struct parport *pb)
	}
	dev->waiting = NULL;
	finish_wait(&waiting, &wait);
	ppb = dev->base = dev->dev->port->base;
	ppb_hi = dev->dev->port->base_hi;
	w_ctr(ppb, 0x0c);
	modes = dev->dev->port->modes;

	/* Mode detection works up the chain of speed
	 * This avoids a nasty if-then-else-if-... tree
	 */
	dev->mode = PPA_NIBBLE;

	if (modes & PARPORT_MODE_TRISTATE)
		dev->mode = PPA_PS2;

	if (modes & PARPORT_MODE_ECP) {
		w_ecr(ppb_hi, 0x20);
		dev->mode = PPA_PS2;
	}
	if ((modes & PARPORT_MODE_EPP) && (modes & PARPORT_MODE_ECP))
		w_ecr(ppb_hi, 0x80);
	dev->base = dev->dev->port->base;
	w_ctr(dev->base, 0x0c);

	/* Done configuration */

+0 −4
Original line number Diff line number Diff line
@@ -107,11 +107,7 @@ static char *PPA_MODE_STRING[] =
    "PS/2",
    "EPP 8 bit",
    "EPP 16 bit",
#ifdef CONFIG_SCSI_IZIP_EPP16
    "EPP 16 bit",
#else
    "EPP 32 bit",
#endif
    "Unknown"};

/* other options */