drivers/scsi/ppa.c

Source file repositories/reference/linux-study-clean/drivers/scsi/ppa.c

File Facts

System
Linux kernel
Corpus path
drivers/scsi/ppa.c
Extension
.c
Size
27181 bytes
Lines
1158
Domain
Driver Families
Bucket
drivers/scsi
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

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);

	retv = 2;		/* Failed */

	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 */

	if (retv)
		return -EIO;

	return device_check(dev, autodetect);
}

static inline int ppa_send_command(struct scsi_cmnd *cmd)
{
	ppa_struct *dev = ppa_dev(cmd->device->host);
	int k;

	w_ctr(dev->base, 0x0c);

	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.
 */
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;

	unsigned char 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 != (unsigned char) 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;

		if (scsi_pointer->this_residual <= 0) {
			ppa_fail(dev, DID_ERROR);
			return -1;	/* ERROR_RETURN */

Annotation

Implementation Notes