diff options
Diffstat (limited to 'drivers/scsi/ppa.c')
| -rw-r--r-- | drivers/scsi/ppa.c | 84 | 
1 files changed, 43 insertions, 41 deletions
diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c index 909c49541984..19f0b93fa3d8 100644 --- a/drivers/scsi/ppa.c +++ b/drivers/scsi/ppa.c @@ -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) @@ -637,7 +657,7 @@ static void ppa_interrupt(struct work_struct *work)  	case DID_OK:  		break;  	case DID_NO_CONNECT: -		printk(KERN_DEBUG "ppa: no device at SCSI ID %i\n", cmd->device->target); +		printk(KERN_DEBUG "ppa: no device at SCSI ID %i\n", scmd_id(cmd));  		break;  	case DID_BUS_BUSY:  		printk(KERN_DEBUG "ppa: BUS BUSY - EPP timeout detected\n"); @@ -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 @@ second_pass:  			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 @@ second_pass:  			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 */  |