diff options
Diffstat (limited to 'drivers/scsi/ppa.c')
| -rw-r--r-- | drivers/scsi/ppa.c | 247 |
1 files changed, 136 insertions, 111 deletions
diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c index 1db8b26063b4..ea682f3044b6 100644 --- a/drivers/scsi/ppa.c +++ b/drivers/scsi/ppa.c @@ -37,6 +37,7 @@ typedef struct { unsigned long recon_tmo; /* How many usecs to wait for reconnection (6th bit) */ unsigned int failed:1; /* Failure flag */ unsigned wanted:1; /* Parport sharing busy flag */ + unsigned int dev_no; /* Device number */ wait_queue_head_t *waiting; struct Scsi_Host *host; struct list_head list; @@ -44,6 +45,16 @@ 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); +} + static inline ppa_struct *ppa_dev(struct Scsi_Host *host) { return *(ppa_struct **)&host->hostdata; @@ -55,7 +66,7 @@ static void got_it(ppa_struct *dev) { dev->base = dev->dev->port->base; if (dev->cur_cmd) - dev->cur_cmd->SCp.phase = 1; + ppa_scsi_pointer(dev->cur_cmd)->phase = 1; else wake_up(dev->waiting); } @@ -151,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",\ @@ -296,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) & 0x03)) outsl(ppb + 4, buffer, len >> 2); -#endif + else if (dev->mode == PPA_EPP_16 && !(((long) buffer | len) & 0x01)) + outsw(ppb + 4, buffer, len >> 1); else outsb(ppb + 4, buffer, len); w_ctr(ppb, 0xc); @@ -349,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); @@ -463,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); @@ -486,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) @@ -510,13 +536,14 @@ static inline int ppa_send_command(struct scsi_cmnd *cmd) * The driver appears to remain stable if we speed up the parallel port * i/o in this function, but not elsewhere. */ -static int ppa_completion(struct scsi_cmnd *cmd) +static int ppa_completion(struct scsi_cmnd *const cmd) { /* Return codes: * -1 Error * 0 Told to schedule * 1 Finished data transfer */ + struct scsi_pointer *scsi_pointer = ppa_scsi_pointer(cmd); ppa_struct *dev = ppa_dev(cmd->device->host); unsigned short ppb = dev->base; unsigned long start_jiffies = jiffies; @@ -542,7 +569,7 @@ static int ppa_completion(struct scsi_cmnd *cmd) if (time_after(jiffies, start_jiffies + 1)) return 0; - if ((cmd->SCp.this_residual <= 0)) { + if (scsi_pointer->this_residual <= 0) { ppa_fail(dev, DID_ERROR); return -1; /* ERROR_RETURN */ } @@ -571,28 +598,30 @@ static int ppa_completion(struct scsi_cmnd *cmd) } /* determine if we should use burst I/O */ - fast = (bulk && (cmd->SCp.this_residual >= PPA_BURST_SIZE)) - ? PPA_BURST_SIZE : 1; + fast = bulk && scsi_pointer->this_residual >= PPA_BURST_SIZE ? + PPA_BURST_SIZE : 1; if (r == (unsigned char) 0xc0) - status = ppa_out(dev, cmd->SCp.ptr, fast); + status = ppa_out(dev, scsi_pointer->ptr, fast); else - status = ppa_in(dev, cmd->SCp.ptr, fast); + status = ppa_in(dev, scsi_pointer->ptr, fast); - cmd->SCp.ptr += fast; - cmd->SCp.this_residual -= fast; + scsi_pointer->ptr += fast; + scsi_pointer->this_residual -= fast; if (!status) { ppa_fail(dev, DID_BUS_BUSY); return -1; /* ERROR_RETURN */ } - if (cmd->SCp.buffer && !cmd->SCp.this_residual) { + if (scsi_pointer->buffer && !scsi_pointer->this_residual) { /* if scatter/gather, advance to the next segment */ - if (cmd->SCp.buffers_residual--) { - cmd->SCp.buffer++; - cmd->SCp.this_residual = - cmd->SCp.buffer->length; - cmd->SCp.ptr = sg_virt(cmd->SCp.buffer); + if (scsi_pointer->buffers_residual--) { + scsi_pointer->buffer = + sg_next(scsi_pointer->buffer); + scsi_pointer->this_residual = + scsi_pointer->buffer->length; + scsi_pointer->ptr = + sg_virt(scsi_pointer->buffer); } } /* Now check to see if the drive is ready to comunicate */ @@ -628,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"); @@ -657,18 +686,19 @@ static void ppa_interrupt(struct work_struct *work) } #endif - if (cmd->SCp.phase > 1) + if (ppa_scsi_pointer(cmd)->phase > 1) ppa_disconnect(dev); ppa_pb_dismiss(dev); dev->cur_cmd = NULL; - cmd->scsi_done(cmd); + scsi_done(cmd); } static int ppa_engine(ppa_struct *dev, struct scsi_cmnd *cmd) { + struct scsi_pointer *scsi_pointer = ppa_scsi_pointer(cmd); unsigned short ppb = dev->base; unsigned char l = 0, h = 0; int retv; @@ -679,7 +709,7 @@ static int ppa_engine(ppa_struct *dev, struct scsi_cmnd *cmd) if (dev->failed) return 0; - switch (cmd->SCp.phase) { + switch (scsi_pointer->phase) { case 0: /* Phase 0 - Waiting for parport */ if (time_after(jiffies, dev->jstart + HZ)) { /* @@ -714,15 +744,17 @@ static int ppa_engine(ppa_struct *dev, struct scsi_cmnd *cmd) return 1; /* Try again in a jiffy */ } } - cmd->SCp.phase++; + scsi_pointer->phase++; } + fallthrough; case 2: /* Phase 2 - We are now talking to the scsi bus */ if (!ppa_select(dev, scmd_id(cmd))) { ppa_fail(dev, DID_NO_CONNECT); return 0; } - cmd->SCp.phase++; + scsi_pointer->phase++; + fallthrough; case 3: /* Phase 3 - Ready to accept a command */ w_ctr(ppb, 0x0c); @@ -731,20 +763,23 @@ static int ppa_engine(ppa_struct *dev, struct scsi_cmnd *cmd) if (!ppa_send_command(cmd)) return 0; - cmd->SCp.phase++; + scsi_pointer->phase++; + fallthrough; case 4: /* Phase 4 - Setup scatter/gather buffers */ if (scsi_bufflen(cmd)) { - cmd->SCp.buffer = scsi_sglist(cmd); - cmd->SCp.this_residual = cmd->SCp.buffer->length; - cmd->SCp.ptr = sg_virt(cmd->SCp.buffer); + scsi_pointer->buffer = scsi_sglist(cmd); + scsi_pointer->this_residual = + scsi_pointer->buffer->length; + scsi_pointer->ptr = sg_virt(scsi_pointer->buffer); } else { - cmd->SCp.buffer = NULL; - cmd->SCp.this_residual = 0; - cmd->SCp.ptr = NULL; + scsi_pointer->buffer = NULL; + scsi_pointer->this_residual = 0; + scsi_pointer->ptr = NULL; } - cmd->SCp.buffers_residual = scsi_sg_count(cmd) - 1; - cmd->SCp.phase++; + scsi_pointer->buffers_residual = scsi_sg_count(cmd) - 1; + scsi_pointer->phase++; + fallthrough; case 5: /* Phase 5 - Data transfer stage */ w_ctr(ppb, 0x0c); @@ -756,7 +791,8 @@ static int ppa_engine(ppa_struct *dev, struct scsi_cmnd *cmd) return 0; if (retv == 0) return 1; - cmd->SCp.phase++; + scsi_pointer->phase++; + fallthrough; case 6: /* Phase 6 - Read status/message */ cmd->result = DID_OK << 16; @@ -773,7 +809,6 @@ static int ppa_engine(ppa_struct *dev, struct scsi_cmnd *cmd) (DID_OK << 16) + (h << 8) + (l & STATUS_MASK); } return 0; /* Finished */ - break; default: printk(KERN_ERR "ppa: Invalid scsi phase\n"); @@ -781,8 +816,7 @@ static int ppa_engine(ppa_struct *dev, struct scsi_cmnd *cmd) return 0; } -static int ppa_queuecommand_lck(struct scsi_cmnd *cmd, - void (*done) (struct scsi_cmnd *)) +static int ppa_queuecommand_lck(struct scsi_cmnd *cmd) { ppa_struct *dev = ppa_dev(cmd->device->host); @@ -793,9 +827,8 @@ static int ppa_queuecommand_lck(struct scsi_cmnd *cmd, dev->failed = 0; dev->jstart = jiffies; dev->cur_cmd = cmd; - cmd->scsi_done = done; cmd->result = DID_ERROR << 16; /* default return code */ - cmd->SCp.phase = 0; /* bus free */ + ppa_scsi_pointer(cmd)->phase = 0; /* bus free */ schedule_delayed_work(&dev->ppa_tq, 0); @@ -812,7 +845,7 @@ static DEF_SCSI_QCMD(ppa_queuecommand) * be done in sd.c. Even if it gets fixed there, this will still * work. */ -static int ppa_biosparam(struct scsi_device *sdev, struct block_device *dev, +static int ppa_biosparam(struct scsi_device *sdev, struct gendisk *unused, sector_t capacity, int ip[]) { ip[0] = 0x40; @@ -836,15 +869,13 @@ static int ppa_abort(struct scsi_cmnd *cmd) * have tied the SCSI_MESSAGE line high in the interface */ - switch (cmd->SCp.phase) { + switch (ppa_scsi_pointer(cmd)->phase) { case 0: /* Do not have access to parport */ case 1: /* Have not connected to interface */ dev->cur_cmd = NULL; /* Forget the problem */ return SUCCESS; - break; default: /* SCSI command sent, can not abort */ return FAILED; - break; } } @@ -860,7 +891,7 @@ static int ppa_reset(struct scsi_cmnd *cmd) { ppa_struct *dev = ppa_dev(cmd->device->host); - if (cmd->SCp.phase) + if (ppa_scsi_pointer(cmd)->phase) ppa_disconnect(dev); dev->cur_cmd = NULL; /* Forget the problem */ @@ -872,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. */ @@ -884,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); @@ -913,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; } @@ -936,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; } @@ -955,13 +986,7 @@ second_pass: return -ENODEV; } -static int ppa_adjust_queue(struct scsi_device *device) -{ - blk_queue_bounce_limit(device->request_queue, BLK_BOUNCE_HIGH); - return 0; -} - -static struct scsi_host_template ppa_template = { +static const struct scsi_host_template ppa_template = { .module = THIS_MODULE, .proc_name = "ppa", .show_info = ppa_show_info, @@ -969,15 +994,12 @@ static struct scsi_host_template ppa_template = { .name = "Iomega VPI0 (ppa) interface", .queuecommand = ppa_queuecommand, .eh_abort_handler = ppa_abort, - .eh_bus_reset_handler = ppa_reset, .eh_host_reset_handler = ppa_reset, .bios_param = ppa_biosparam, .this_id = -1, .sg_tablesize = SG_ALL, - .cmd_per_lun = 1, - .use_clustering = ENABLE_CLUSTERING, .can_queue = 1, - .slave_alloc = ppa_adjust_queue, + .cmd_size = sizeof(struct scsi_pointer), }; /*************************************************************************** @@ -986,25 +1008,56 @@ static struct scsi_host_template ppa_template = { static LIST_HEAD(ppa_hosts); +/* + * Finds the first available device number that can be alloted to the + * new ppa 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 ppa_struct *find_parent(void) +{ + ppa_struct *dev, *par = NULL; + unsigned int cnt = 0; + + if (list_empty(&ppa_hosts)) + return NULL; + + list_for_each_entry(dev, &ppa_hosts, list) { + if (dev->dev_no != cnt) + return par; + cnt++; + par = dev; + } + + return par; +} + static int __ppa_attach(struct parport *pb) { struct Scsi_Host *host; DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waiting); DEFINE_WAIT(wait); - ppa_struct *dev; + ppa_struct *dev, *temp; int ports; - int modes, ppb, ppb_hi; int err = -ENOMEM; + struct pardev_cb ppa_cb; dev = kzalloc(sizeof(ppa_struct), GFP_KERNEL); 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); - dev->dev = parport_register_device(pb, "ppa", NULL, ppa_wakeup, - NULL, 0, dev); + temp = find_parent(); + if (temp) + dev->dev_no = temp->dev_no + 1; + + memset(&ppa_cb, 0, sizeof(ppa_cb)); + ppa_cb.private = dev; + ppa_cb.wakeup = ppa_wakeup; + + dev->dev = parport_register_dev_model(pb, "ppa", &ppa_cb, dev->dev_no); if (!dev->dev) goto out; @@ -1028,25 +1081,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 */ @@ -1111,22 +1147,11 @@ static void ppa_detach(struct parport *pb) } static struct parport_driver ppa_driver = { - .name = "ppa", - .attach = ppa_attach, - .detach = ppa_detach, + .name = "ppa", + .match_port = ppa_attach, + .detach = ppa_detach, }; +module_parport_driver(ppa_driver); -static int __init ppa_driver_init(void) -{ - printk(KERN_INFO "ppa: Version %s\n", PPA_VERSION); - return parport_register_driver(&ppa_driver); -} - -static void __exit ppa_driver_exit(void) -{ - parport_unregister_driver(&ppa_driver); -} - -module_init(ppa_driver_init); -module_exit(ppa_driver_exit); +MODULE_DESCRIPTION("IOMEGA PPA3 parallel port SCSI host adapter driver"); MODULE_LICENSE("GPL"); |
