/* ppa.c -- low level driver for the IOMEGA PPA3 * parallel port SCSI host adapter. * * (The PPA3 is the embedded controller in the ZIP drive.) * * (c) 1995,1996 Grant R. Guenther, grant@torque.net, * under the terms of the GNU General Public License. *
*/
/* This is to give the ppa driver a way to modify the timings (and other * parameters) by writing to the /proc/scsi/ppa/0 file. * Very simple method really... (To 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)
*/
#if PPA_DEBUG > 0 #define ppa_fail(x,y) printk("ppa: ppa_fail(%i) from %s at line %d\n",\
y, __func__, __LINE__); ppa_fail_func(x,y); staticinlinevoid ppa_fail_func(ppa_struct *dev, int error_code) #else staticinlinevoid ppa_fail(ppa_struct *dev, int error_code) #endif
{ /* If we fail a device then we trash status / message bytes */ if (dev->cur_cmd) {
dev->cur_cmd->result = error_code << 16;
dev->failed = 1;
}
}
/* * 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.
*/ staticunsignedchar ppa_wait(ppa_struct *dev)
{ int k; unsignedshort ppb = dev->base; unsignedchar r;
k = PPA_SPIN_TMO; /* Wait for bit 6 and 7 - PJC */ for (r = r_str(ppb); ((r & 0xc0) != 0xc0) && (k); k--) {
udelay(1);
r = r_str(ppb);
}
/* * return some status information. * Semantics: 0xc0 = ZIP wants more data * 0xd0 = ZIP wants to send more data * 0xe0 = ZIP is expecting SCSI command data * 0xf0 = end of transfer, ZIP is sending status
*/ if (k) return (r & 0xf0);
/* Counter expired - Time out occurred */
ppa_fail(dev, DID_TIME_OUT);
printk(KERN_WARNING "ppa timeout in ppa_wait\n"); return 0; /* command timed out */
}
/* * Clear EPP Timeout Bit
*/ staticinlinevoid epp_reset(unsignedshort ppb)
{ int i;
i = r_str(ppb);
w_str(ppb, i);
w_str(ppb, i & 0xfe);
}
/* * Wait for empty ECP fifo (if we are in ECP fifo mode only)
*/ staticinlinevoid ecp_sync(ppa_struct *dev)
{ int i, ppb_hi = dev->dev->port->base_hi;
if (ppb_hi == 0) return;
if ((r_ecr(ppb_hi) & 0xe0) == 0x60) { /* mode 011 == ECP fifo mode */ for (i = 0; i < 100; i++) { if (r_ecr(ppb_hi) & 0x01) return;
udelay(5);
}
printk(KERN_WARNING "ppa: ECP sync failed as data still present in FIFO.\n");
}
}
staticint ppa_byte_out(unsignedshort base, constchar *buffer, int len)
{ int i;
for (i = len; i; i--) {
w_dtr(base, *buffer++);
w_ctr(base, 0xe);
w_ctr(base, 0xc);
} return 1; /* All went well - we hope! */
}
staticint ppa_byte_in(unsignedshort base, char *buffer, int len)
{ int i;
for (i = len; i; i--) {
*buffer++ = r_dtr(base);
w_ctr(base, 0x27);
w_ctr(base, 0x25);
} return 1; /* All went well - we hope! */
}
staticint ppa_nibble_in(unsignedshort base, char *buffer, int len)
{ for (; len; len--) { unsignedchar h;
w_ctr(base, 0x4);
h = r_str(base) & 0xf0;
w_ctr(base, 0x6);
*buffer++ = h | ((r_str(base) & 0xf0) >> 4);
} return 1; /* All went well - we hope! */
}
staticint ppa_out(ppa_struct *dev, char *buffer, int len)
{ int r; unsignedshort ppb = dev->base;
r = ppa_wait(dev);
if ((r & 0x50) != 0x40) {
ppa_fail(dev, DID_ERROR); return 0;
} switch (dev->mode) { case PPA_NIBBLE: case PPA_PS2: /* 8 bit output, with a loop */
r = ppa_byte_out(ppb, buffer, len); break;
case PPA_EPP_32: case PPA_EPP_16: case PPA_EPP_8:
epp_reset(ppb);
w_ctr(ppb, 0x4); if (dev->mode == PPA_EPP_32 && !(((long) buffer | len) & 0x03))
outsl(ppb + 4, buffer, len >> 2); elseif (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);
r = !(r_str(ppb) & 0x01);
w_ctr(ppb, 0xc);
ecp_sync(dev); break;
default:
printk(KERN_ERR "PPA: bug in ppa_out()\n");
r = 0;
} return r;
}
staticint ppa_in(ppa_struct *dev, char *buffer, int len)
{ int r; unsignedshort ppb = dev->base;
r = ppa_wait(dev);
if ((r & 0x50) != 0x50) {
ppa_fail(dev, DID_ERROR); return 0;
} switch (dev->mode) { case PPA_NIBBLE: /* 4 bit input, with a loop */
r = ppa_nibble_in(ppb, buffer, len);
w_ctr(ppb, 0xc); break;
case PPA_PS2: /* 8 bit input, with a loop */
w_ctr(ppb, 0x25);
r = ppa_byte_in(ppb, buffer, len);
w_ctr(ppb, 0x4);
w_ctr(ppb, 0xc); break;
case PPA_EPP_32: case PPA_EPP_16: case PPA_EPP_8:
epp_reset(ppb);
w_ctr(ppb, 0x24); if (dev->mode == PPA_EPP_32 && !(((long) buffer | len) & 0x03))
insl(ppb + 4, buffer, len >> 2); elseif (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);
r = !(r_str(ppb) & 0x01);
w_ctr(ppb, 0x2c);
ecp_sync(dev); break;
default:
printk(KERN_ERR "PPA: bug in ppa_ins()\n");
r = 0; break;
} return r;
}
/* end of ppa_io.h */ staticinlinevoid ppa_d_pulse(unsignedshort ppb, unsignedchar b)
{
w_dtr(ppb, b);
w_ctr(ppb, 0xc);
w_ctr(ppb, 0xe);
w_ctr(ppb, 0xc);
w_ctr(ppb, 0x4);
w_ctr(ppb, 0xc);
}
staticint ppa_select(ppa_struct *dev, int target)
{ int k; unsignedshort ppb = dev->base;
/* * Bit 6 (0x40) is the device selected bit. * First we must wait till the current device goes off line...
*/
k = PPA_SELECT_TMO; do {
k--;
udelay(1);
} while ((r_str(ppb) & 0x40) && (k)); if (!k) return 0;
w_dtr(ppb, (1 << target));
w_ctr(ppb, 0xe);
w_ctr(ppb, 0xc);
w_dtr(ppb, 0x80); /* This is NOT the initator */
w_ctr(ppb, 0x8);
k = PPA_SELECT_TMO; do {
k--;
udelay(1);
} while (!(r_str(ppb) & 0x40) && (k)); if (!k) return 0;
return 1;
}
/* * This is based on a trace of what the Iomega DOS 'guest' driver does. * I've tried several different kinds of parallel ports with guest and * coded this to react in the same ways that it does. * * The return value from this function is just a hint about where the * handshaking failed. *
*/ staticint ppa_init(ppa_struct *dev)
{ int retv; unsignedshort 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;
w_ctr(ppb, 0xe); if ((r_str(ppb) & 0x08) == 0x08)
retv--;
w_ctr(ppb, 0xc); if ((r_str(ppb) & 0x08) == 0x00)
retv--;
if (!retv)
ppa_reset_pulse(ppb);
udelay(1000); /* Allow devices to settle down */
ppa_disconnect(dev);
udelay(1000); /* Another delay to allow devices to settle */
for (k = 0; k < cmd->cmd_len; k++) if (!ppa_out(dev, &cmd->cmnd[k], 1)) return 0; return 1;
}
/* * 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.
*/ staticint 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); unsignedshort ppb = dev->base; unsignedlong start_jiffies = jiffies;
unsignedchar r, v; int fast, bulk, status;
v = cmd->cmnd[0];
bulk = ((v == READ_6) ||
(v == READ_10) || (v == WRITE_6) || (v == WRITE_10));
/* * We only get here if the drive is ready to comunicate, * hence no need for a full ppa_wait.
*/
r = (r_str(ppb) & 0xf0);
while (r != (unsignedchar) 0xf0) { /* * If we have been running for more than a full timer tick * then take a rest.
*/ if (time_after(jiffies, start_jiffies + 1)) return 0;
/* On some hardware we have SCSI disconnected (6th bit low) * for about 100usecs. It is too expensive to wait a * tick on every loop so we busy wait for no more than * 500usecs to give the drive a chance first. We do not * change things for "normal" hardware since generally * the 6th bit is always high. * This makes the CPU load higher on some hardware * but otherwise we can not get more than 50K/secs * on this problem hardware.
*/ if ((r & 0xc0) != 0xc0) { /* Wait for reconnection should be no more than * jiffy/2 = 5ms = 5000 loops
*/ unsignedlong k = dev->recon_tmo; for (; k && ((r = (r_str(ppb) & 0xf0)) & 0xc0) != 0xc0;
k--)
udelay(1);
if (!k) return 0;
}
/* determine if we should use burst I/O */
fast = bulk && scsi_pointer->this_residual >= PPA_BURST_SIZE ?
PPA_BURST_SIZE : 1;
if (r == (unsignedchar) 0xc0)
status = ppa_out(dev, scsi_pointer->ptr, fast); else
status = ppa_in(dev, scsi_pointer->ptr, fast);
if (!status) {
ppa_fail(dev, DID_BUS_BUSY); return -1; /* ERROR_RETURN */
} if (scsi_pointer->buffer && !scsi_pointer->this_residual) { /* if scatter/gather, advance to the next segment */ 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 */
r = (r_str(ppb) & 0xf0); /* If not, drop back down to the scheduler and wait a timer tick */ if (!(r & 0x80)) return 0;
} return 1; /* FINISH_RETURN */
}
/* * Since the PPA 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.
*/ staticvoid ppa_interrupt(struct work_struct *work)
{
ppa_struct *dev = container_of(work, ppa_struct, ppa_tq.work); struct scsi_cmnd *cmd = dev->cur_cmd;
if (!cmd) {
printk(KERN_ERR "PPA: bug in ppa_interrupt\n"); return;
} if (ppa_engine(dev, cmd)) {
schedule_delayed_work(&dev->ppa_tq, 1); return;
} /* Command must of completed hence it is safe to let go... */ #if PPA_DEBUG > 0 switch ((cmd->result >> 16) & 0xff) { case DID_OK: break; case DID_NO_CONNECT:
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"); break; case DID_TIME_OUT:
printk(KERN_DEBUG "ppa: unknown timeout\n"); break; case DID_ABORT:
printk(KERN_DEBUG "ppa: told to abort\n"); break; case DID_PARITY:
printk(KERN_DEBUG "ppa: parity error (???)\n"); break; case DID_ERROR:
printk(KERN_DEBUG "ppa: internal driver error\n"); break; case DID_RESET:
printk(KERN_DEBUG "ppa: told to reset device\n"); break; case DID_BAD_INTR:
printk(KERN_WARNING "ppa: bad interrupt (???)\n"); break; default:
printk(KERN_WARNING "ppa: bad return code (%02x)\n",
(cmd->result >> 16) & 0xff);
} #endif
if (ppa_scsi_pointer(cmd)->phase > 1)
ppa_disconnect(dev);
ppa_pb_dismiss(dev);
dev->cur_cmd = NULL;
scsi_done(cmd);
}
staticint ppa_engine(ppa_struct *dev, struct scsi_cmnd *cmd)
{ struct scsi_pointer *scsi_pointer = ppa_scsi_pointer(cmd); unsignedshort ppb = dev->base; unsignedchar l = 0, h = 0; int retv;
/* First check for any errors that may of occurred * Here we check for internal errors
*/ if (dev->failed) return 0;
switch (scsi_pointer->phase) { case 0: /* Phase 0 - Waiting for parport */ if (time_after(jiffies, dev->jstart + HZ)) { /* * We waited more than a second * for parport to call us
*/
ppa_fail(dev, DID_BUS_BUSY); return 0;
} return 1; /* wait until ppa_wakeup claims parport */ case 1: /* Phase 1 - Connected */
{ /* Perform a sanity check for cable unplugged */ int retv = 2; /* Failed */
ppa_connect(dev, CONNECT_EPP_MAYBE);
w_ctr(ppb, 0xe); if ((r_str(ppb) & 0x08) == 0x08)
retv--;
w_ctr(ppb, 0xc); if ((r_str(ppb) & 0x08) == 0x00)
retv--;
if (retv) { if (time_after(jiffies, dev->jstart + (1 * HZ))) {
printk(KERN_ERR "ppa: Parallel port cable is unplugged.\n");
ppa_fail(dev, DID_BUS_BUSY); return 0;
} else {
ppa_disconnect(dev); return 1; /* Try again in a jiffy */
}
}
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;
}
scsi_pointer->phase++;
fallthrough;
case 3: /* Phase 3 - Ready to accept a command */
w_ctr(ppb, 0x0c); if (!(r_str(ppb) & 0x80)) return 1;
if (!ppa_send_command(cmd)) return 0;
scsi_pointer->phase++;
fallthrough;
/* * 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.
*/ staticint ppa_biosparam(struct scsi_device *sdev, struct block_device *dev,
sector_t capacity, int ip[])
{
ip[0] = 0x40;
ip[1] = 0x20;
ip[2] = ((unsignedlong) capacity + 1) / (ip[0] * ip[1]); if (ip[2] > 1024) {
ip[0] = 0xff;
ip[1] = 0x3f;
ip[2] = ((unsignedlong) capacity + 1) / (ip[0] * ip[1]); if (ip[2] > 1023)
ip[2] = 1023;
} return 0;
}
staticint ppa_abort(struct scsi_cmnd *cmd)
{
ppa_struct *dev = ppa_dev(cmd->device->host); /* * There is no method for aborting commands since Iomega * have tied the SCSI_MESSAGE line high in the interface
*/
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; default: /* SCSI command sent, can not abort */ return FAILED;
}
}
staticint 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. */
old_mode = dev->mode; for (loop = 0; loop < 8; loop++) { /* Attempt to use EPP for Test Unit Ready */ if (autodetect && (ppb & 0x0007) == 0x0000)
dev->mode = PPA_EPP_8;
second_pass:
ppa_connect(dev, CONNECT_EPP_MAYBE); /* Select SCSI device */ if (!ppa_select(dev, loop)) {
ppa_disconnect(dev); continue;
}
printk(KERN_INFO "ppa: Found device at ID %i, Attempting to use %s\n",
loop, PPA_MODE_STRING[dev->mode]);
/* Send SCSI command */
status = 1;
w_ctr(ppb, 0x0c); for (l = 0; (l < 6) && (status); l++)
status = ppa_out(dev, cmd, 1);
if (!status) {
ppa_disconnect(dev);
ppa_connect(dev, CONNECT_EPP_MAYBE);
w_dtr(ppb, 0x40);
w_ctr(ppb, 0x08);
udelay(30);
w_ctr(ppb, 0x0c);
udelay(1000);
ppa_disconnect(dev);
udelay(1000); if (dev->mode != old_mode) {
dev->mode = old_mode; goto second_pass;
} return -EIO;
}
w_ctr(ppb, 0x0c);
k = 1000000; /* 1 Second */ do {
l = r_str(ppb);
k--;
udelay(1);
} while (!(l & 0x80) && (k));
l &= 0xf0;
if (l != 0xf0) {
ppa_disconnect(dev);
ppa_connect(dev, CONNECT_EPP_MAYBE);
ppa_reset_pulse(ppb);
udelay(1000);
ppa_disconnect(dev);
udelay(1000); if (dev->mode != old_mode) {
dev->mode = old_mode; goto second_pass;
} return -EIO;
}
ppa_disconnect(dev);
printk(KERN_INFO "ppa: Communication established with ID %i using %s\n",
loop, PPA_MODE_STRING[dev->mode]);
ppa_connect(dev, CONNECT_EPP_MAYBE);
ppa_reset_pulse(ppb);
udelay(1000);
ppa_disconnect(dev);
udelay(1000); return 0;
} return -ENODEV;
}
/*************************************************************************** * Parallel port probing routines *
***************************************************************************/
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.
*/
/* Claim the bus so it remembers what we do to the control * registers. [ CTR and ECP ]
*/
err = -EBUSY;
dev->waiting = &waiting;
prepare_to_wait(&waiting, &wait, TASK_UNINTERRUPTIBLE); if (ppa_pb_claim(dev))
schedule_timeout(3 * HZ); if (dev->wanted) {
printk(KERN_ERR "ppa%d: failed to claim parport because " "a pardevice is owning the port for too long " "time!\n", pb->number);
ppa_pb_dismiss(dev);
dev->waiting = NULL;
finish_wait(&waiting, &wait); goto out1;
}
dev->waiting = NULL;
finish_wait(&waiting, &wait);
dev->base = dev->dev->port->base;
w_ctr(dev->base, 0x0c);
/* Done configuration */
err = ppa_init(dev);
ppa_pb_release(dev);
if (err) goto out1;
/* now the glue ... */ if (dev->mode == PPA_NIBBLE || dev->mode == PPA_PS2)
ports = 3; else
ports = 8;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.