mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-01 08:04:22 +08:00
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: Alex Henrie <alexhenrie24@gmail.com> Link: https://lore.kernel.org/r/20230807155856.362864-2-alexhenrie24@gmail.com Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
b68442ebda
commit
68a4f84a17
@ -836,7 +836,7 @@ config SCSI_IMM
|
|||||||
|
|
||||||
config SCSI_IZIP_EPP16
|
config SCSI_IZIP_EPP16
|
||||||
bool "ppa/imm option - Use slow (but safe) EPP-16"
|
bool "ppa/imm option - Use slow (but safe) EPP-16"
|
||||||
depends on SCSI_PPA || SCSI_IMM
|
depends on SCSI_IMM
|
||||||
help
|
help
|
||||||
EPP (Enhanced Parallel Port) is a standard for parallel ports which
|
EPP (Enhanced Parallel Port) is a standard for parallel ports which
|
||||||
allows them to act as expansion buses that can handle up to 64
|
allows them to act as expansion buses that can handle up to 64
|
||||||
|
@ -45,6 +45,11 @@ typedef struct {
|
|||||||
|
|
||||||
#include "ppa.h"
|
#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)
|
static struct scsi_pointer *ppa_scsi_pointer(struct scsi_cmnd *cmd)
|
||||||
{
|
{
|
||||||
return scsi_cmd_priv(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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int device_check(ppa_struct *dev);
|
static int device_check(ppa_struct *dev, bool autodetect);
|
||||||
|
|
||||||
#if PPA_DEBUG > 0
|
#if PPA_DEBUG > 0
|
||||||
#define ppa_fail(x,y) printk("ppa: ppa_fail(%i) from %s at line %d\n",\
|
#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:
|
case PPA_EPP_8:
|
||||||
epp_reset(ppb);
|
epp_reset(ppb);
|
||||||
w_ctr(ppb, 0x4);
|
w_ctr(ppb, 0x4);
|
||||||
#ifdef CONFIG_SCSI_IZIP_EPP16
|
if (dev->mode == PPA_EPP_32 && !(((long) buffer | len) & 0x01))
|
||||||
if (!(((long) buffer | len) & 0x01))
|
|
||||||
outsw(ppb + 4, buffer, len >> 1);
|
|
||||||
#else
|
|
||||||
if (!(((long) buffer | len) & 0x03))
|
|
||||||
outsl(ppb + 4, buffer, len >> 2);
|
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
|
else
|
||||||
outsb(ppb + 4, buffer, len);
|
outsb(ppb + 4, buffer, len);
|
||||||
w_ctr(ppb, 0xc);
|
w_ctr(ppb, 0xc);
|
||||||
@ -355,13 +357,10 @@ static int ppa_in(ppa_struct *dev, char *buffer, int len)
|
|||||||
case PPA_EPP_8:
|
case PPA_EPP_8:
|
||||||
epp_reset(ppb);
|
epp_reset(ppb);
|
||||||
w_ctr(ppb, 0x24);
|
w_ctr(ppb, 0x24);
|
||||||
#ifdef CONFIG_SCSI_IZIP_EPP16
|
if (dev->mode == PPA_EPP_32 && !(((long) buffer | len) & 0x03))
|
||||||
if (!(((long) buffer | len) & 0x01))
|
|
||||||
insw(ppb + 4, buffer, len >> 1);
|
|
||||||
#else
|
|
||||||
if (!(((long) buffer | len) & 0x03))
|
|
||||||
insl(ppb + 4, buffer, len >> 2);
|
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
|
else
|
||||||
insb(ppb + 4, buffer, len);
|
insb(ppb + 4, buffer, len);
|
||||||
w_ctr(ppb, 0x2c);
|
w_ctr(ppb, 0x2c);
|
||||||
@ -469,6 +468,27 @@ static int ppa_init(ppa_struct *dev)
|
|||||||
{
|
{
|
||||||
int retv;
|
int retv;
|
||||||
unsigned short ppb = dev->base;
|
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_disconnect(dev);
|
||||||
ppa_connect(dev, CONNECT_NORMAL);
|
ppa_connect(dev, CONNECT_NORMAL);
|
||||||
@ -492,7 +512,7 @@ static int ppa_init(ppa_struct *dev)
|
|||||||
if (retv)
|
if (retv)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
return device_check(dev);
|
return device_check(dev, autodetect);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int ppa_send_command(struct scsi_cmnd *cmd)
|
static inline int ppa_send_command(struct scsi_cmnd *cmd)
|
||||||
@ -883,7 +903,7 @@ static int ppa_reset(struct scsi_cmnd *cmd)
|
|||||||
return SUCCESS;
|
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
|
/* 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. */
|
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;
|
old_mode = dev->mode;
|
||||||
for (loop = 0; loop < 8; loop++) {
|
for (loop = 0; loop < 8; loop++) {
|
||||||
/* Attempt to use EPP for Test Unit Ready */
|
/* Attempt to use EPP for Test Unit Ready */
|
||||||
if ((ppb & 0x0007) == 0x0000)
|
if (autodetect && (ppb & 0x0007) == 0x0000)
|
||||||
dev->mode = PPA_EPP_32;
|
dev->mode = PPA_EPP_8;
|
||||||
|
|
||||||
second_pass:
|
second_pass:
|
||||||
ppa_connect(dev, CONNECT_EPP_MAYBE);
|
ppa_connect(dev, CONNECT_EPP_MAYBE);
|
||||||
@ -924,7 +944,7 @@ second_pass:
|
|||||||
udelay(1000);
|
udelay(1000);
|
||||||
ppa_disconnect(dev);
|
ppa_disconnect(dev);
|
||||||
udelay(1000);
|
udelay(1000);
|
||||||
if (dev->mode == PPA_EPP_32) {
|
if (dev->mode != old_mode) {
|
||||||
dev->mode = old_mode;
|
dev->mode = old_mode;
|
||||||
goto second_pass;
|
goto second_pass;
|
||||||
}
|
}
|
||||||
@ -947,7 +967,7 @@ second_pass:
|
|||||||
udelay(1000);
|
udelay(1000);
|
||||||
ppa_disconnect(dev);
|
ppa_disconnect(dev);
|
||||||
udelay(1000);
|
udelay(1000);
|
||||||
if (dev->mode == PPA_EPP_32) {
|
if (dev->mode != old_mode) {
|
||||||
dev->mode = old_mode;
|
dev->mode = old_mode;
|
||||||
goto second_pass;
|
goto second_pass;
|
||||||
}
|
}
|
||||||
@ -1026,7 +1046,6 @@ static int __ppa_attach(struct parport *pb)
|
|||||||
DEFINE_WAIT(wait);
|
DEFINE_WAIT(wait);
|
||||||
ppa_struct *dev, *temp;
|
ppa_struct *dev, *temp;
|
||||||
int ports;
|
int ports;
|
||||||
int modes, ppb, ppb_hi;
|
|
||||||
int err = -ENOMEM;
|
int err = -ENOMEM;
|
||||||
struct pardev_cb ppa_cb;
|
struct pardev_cb ppa_cb;
|
||||||
|
|
||||||
@ -1034,7 +1053,7 @@ static int __ppa_attach(struct parport *pb)
|
|||||||
if (!dev)
|
if (!dev)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
dev->base = -1;
|
dev->base = -1;
|
||||||
dev->mode = PPA_AUTODETECT;
|
dev->mode = mode < PPA_UNKNOWN ? mode : PPA_AUTODETECT;
|
||||||
dev->recon_tmo = PPA_RECON_TMO;
|
dev->recon_tmo = PPA_RECON_TMO;
|
||||||
init_waitqueue_head(&waiting);
|
init_waitqueue_head(&waiting);
|
||||||
temp = find_parent();
|
temp = find_parent();
|
||||||
@ -1069,25 +1088,8 @@ static int __ppa_attach(struct parport *pb)
|
|||||||
}
|
}
|
||||||
dev->waiting = NULL;
|
dev->waiting = NULL;
|
||||||
finish_wait(&waiting, &wait);
|
finish_wait(&waiting, &wait);
|
||||||
ppb = dev->base = dev->dev->port->base;
|
dev->base = dev->dev->port->base;
|
||||||
ppb_hi = dev->dev->port->base_hi;
|
w_ctr(dev->base, 0x0c);
|
||||||
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);
|
|
||||||
|
|
||||||
/* Done configuration */
|
/* Done configuration */
|
||||||
|
|
||||||
|
@ -107,11 +107,7 @@ static char *PPA_MODE_STRING[] =
|
|||||||
"PS/2",
|
"PS/2",
|
||||||
"EPP 8 bit",
|
"EPP 8 bit",
|
||||||
"EPP 16 bit",
|
"EPP 16 bit",
|
||||||
#ifdef CONFIG_SCSI_IZIP_EPP16
|
|
||||||
"EPP 16 bit",
|
|
||||||
#else
|
|
||||||
"EPP 32 bit",
|
"EPP 32 bit",
|
||||||
#endif
|
|
||||||
"Unknown"};
|
"Unknown"};
|
||||||
|
|
||||||
/* other options */
|
/* other options */
|
||||||
|
Loading…
Reference in New Issue
Block a user