113546Sjulian// SPDX-License-Identifier: GPL-2.0-only
2113658Sdeischen/* imm.c   --  low level driver for the IOMEGA MatchMaker
3113658Sdeischen * parallel port SCSI host adapter.
435509Sjb *
513546Sjulian * (The IMM is the embedded controller in the ZIP Plus drive.)
613546Sjulian *
713546Sjulian * My unofficial company acronym list is 21 pages long:
813546Sjulian *      FLA:    Four letter acronym with built in facility for
913546Sjulian *              future expansion to five letters.
1013546Sjulian */
1113546Sjulian
1213546Sjulian#include <linux/init.h>
1313546Sjulian#include <linux/kernel.h>
1413546Sjulian#include <linux/module.h>
1513546Sjulian#include <linux/blkdev.h>
1613546Sjulian#include <linux/parport.h>
1713546Sjulian#include <linux/workqueue.h>
1813546Sjulian#include <linux/delay.h>
1913546Sjulian#include <linux/slab.h>
2013546Sjulian#include <asm/io.h>
2113546Sjulian
2213546Sjulian#include <scsi/scsi.h>
2313546Sjulian#include <scsi/scsi_cmnd.h>
2413546Sjulian#include <scsi/scsi_device.h>
2544963Sjb#include <scsi/scsi_host.h>
2613546Sjulian
2713546Sjulian/* The following #define is to avoid a clash with hosts.c */
2813546Sjulian#define IMM_PROBE_SPP   0x0001
2913546Sjulian#define IMM_PROBE_PS2   0x0002
3013546Sjulian#define IMM_PROBE_ECR   0x0010
3113546Sjulian#define IMM_PROBE_EPP17 0x0100
3213546Sjulian#define IMM_PROBE_EPP19 0x0200
3313546Sjulian
3413546Sjulian
35113658Sdeischentypedef struct {
36113662Sdeischen	struct pardevice *dev;	/* Parport device entry         */
37113658Sdeischen	int base;		/* Actual port address          */
38113658Sdeischen	int base_hi;		/* Hi Base address for ECP-ISA chipset */
39113658Sdeischen	int mode;		/* Transfer mode                */
40132120Sdavidxu	struct scsi_cmnd *cur_cmd;	/* Current queued command       */
41113658Sdeischen	struct delayed_work imm_tq;	/* Polling interrupt stuff       */
42113658Sdeischen	unsigned long jstart;	/* Jiffies at start             */
43113658Sdeischen	unsigned failed:1;	/* Failure flag                 */
44116977Sdavidxu	unsigned dp:1;		/* Data phase present           */
45113658Sdeischen	unsigned rd:1;		/* Read data in data phase      */
46113658Sdeischen	unsigned wanted:1;	/* Parport sharing busy flag    */
47113870Sdeischen	unsigned int dev_no;	/* Device number		*/
48113658Sdeischen	wait_queue_head_t *waiting;
4913546Sjulian	struct Scsi_Host *host;
5013546Sjulian	struct list_head list;
51113658Sdeischen} imm_struct;
52113658Sdeischen
5313546Sjulianstatic void imm_reset_pulse(unsigned int base);
54113658Sdeischenstatic int device_check(imm_struct *dev, bool autodetect);
55113658Sdeischen
56103388Smini#include "imm.h"
57113658Sdeischen
58150499Sbrianstatic unsigned int mode = IMM_AUTODETECT;
59150499Sbrianmodule_param(mode, uint, 0644);
60150499SbrianMODULE_PARM_DESC(mode, "Transfer mode (0 = Autodetect, 1 = SPP 4-bit, "
6113546Sjulian	"2 = SPP 8-bit, 3 = EPP 8-bit, 4 = EPP 16-bit, 5 = EPP 32-bit");
62139023Sdeischen
6367097Sdeischenstatic inline imm_struct *imm_dev(struct Scsi_Host *host)
6467097Sdeischen{
6567097Sdeischen	return *(imm_struct **)&host->hostdata;
6667097Sdeischen}
6767097Sdeischen
6867097Sdeischenstatic DEFINE_SPINLOCK(arbitration_lock);
69113658Sdeischen
70113658Sdeischenstatic void got_it(imm_struct *dev)
71113658Sdeischen{
72113658Sdeischen	dev->base = dev->dev->port->base;
73113658Sdeischen	if (dev->cur_cmd)
74113658Sdeischen		imm_scsi_pointer(dev->cur_cmd)->phase = 1;
75118676Sdavidxu	else
76118676Sdavidxu		wake_up(dev->waiting);
77118676Sdavidxu}
78118676Sdavidxu
79118676Sdavidxustatic void imm_wakeup(void *ref)
80118676Sdavidxu{
81133563Sdeischen	imm_struct *dev = (imm_struct *) ref;
82133563Sdeischen	unsigned long flags;
83118676Sdavidxu
84113658Sdeischen	spin_lock_irqsave(&arbitration_lock, flags);
85118510Sdeischen	if (dev->wanted) {
8613546Sjulian		if (parport_claim(dev->dev) == 0) {
87113658Sdeischen			got_it(dev);
8848046Sjb			dev->wanted = 0;
89113658Sdeischen		}
90113658Sdeischen	}
91113658Sdeischen	spin_unlock_irqrestore(&arbitration_lock, flags);
92113658Sdeischen}
93113658Sdeischen
94113658Sdeischenstatic int imm_pb_claim(imm_struct *dev)
95113658Sdeischen{
96113658Sdeischen	unsigned long flags;
97113658Sdeischen	int res = 1;
98113658Sdeischen	spin_lock_irqsave(&arbitration_lock, flags);
99113658Sdeischen	if (parport_claim(dev->dev) == 0) {
100132120Sdavidxu		got_it(dev);
101132120Sdavidxu		res = 0;
102132120Sdavidxu	}
103132120Sdavidxu	dev->wanted = res;
104113658Sdeischen	spin_unlock_irqrestore(&arbitration_lock, flags);
105114187Sdeischen	return res;
106113658Sdeischen}
107120896Sdavidxu
108120896Sdavidxustatic void imm_pb_dismiss(imm_struct *dev)
109120896Sdavidxu{
110120896Sdavidxu	unsigned long flags;
111120896Sdavidxu	int wanted;
112120896Sdavidxu	spin_lock_irqsave(&arbitration_lock, flags);
113120896Sdavidxu	wanted = dev->wanted;
114120896Sdavidxu	dev->wanted = 0;
115120896Sdavidxu	spin_unlock_irqrestore(&arbitration_lock, flags);
116120896Sdavidxu	if (!wanted)
117120896Sdavidxu		parport_release(dev->dev);
118120896Sdavidxu}
119113658Sdeischen
120113658Sdeischenstatic inline void imm_pb_release(imm_struct *dev)
121113658Sdeischen{
122113658Sdeischen	parport_release(dev->dev);
123113658Sdeischen}
124113658Sdeischen
125113658Sdeischen/* This is to give the imm driver a way to modify the timings (and other
126113658Sdeischen * parameters) by writing to the /proc/scsi/imm/0 file.
127113658Sdeischen * Very simple method really... (Too simple, no error checking :( )
128113661Sdeischen * Reason: Kernel hackers HATE having to unload and reload modules for
129113658Sdeischen * testing...
130113658Sdeischen * Also gives a method to use a script to obtain optimum timings (TODO)
131113658Sdeischen */
132113658Sdeischenstatic int imm_write_info(struct Scsi_Host *host, char *buffer, int length)
133113658Sdeischen{
134113658Sdeischen	imm_struct *dev = imm_dev(host);
135113658Sdeischen
136113658Sdeischen	if ((length > 5) && (strncmp(buffer, "mode=", 5) == 0)) {
137113658Sdeischen		dev->mode = simple_strtoul(buffer + 5, NULL, 0);
138115278Sdeischen		return length;
139113658Sdeischen	}
140117706Sdavidxu	printk("imm /proc: invalid variable\n");
141117706Sdavidxu	return -EINVAL;
142117706Sdavidxu}
143117706Sdavidxu
144115278Sdeischenstatic int imm_show_info(struct seq_file *m, struct Scsi_Host *host)
145136846Sdavidxu{
146136846Sdavidxu	imm_struct *dev = imm_dev(host);
147136846Sdavidxu
148115173Sdeischen	seq_printf(m, "Version : %s\n", IMM_VERSION);
149115173Sdeischen	seq_printf(m, "Parport : %s\n", dev->dev->port->name);
150115173Sdeischen	seq_printf(m, "Mode    : %s\n", IMM_MODE_STRING[dev->mode]);
151113658Sdeischen	return 0;
152113658Sdeischen}
153113658Sdeischen
154117706Sdavidxu#if IMM_DEBUG > 0
155118510Sdeischen#define imm_fail(x,y) printk("imm: imm_fail(%i) from %s at line %d\n",\
156118510Sdeischen	   y, __func__, __LINE__); imm_fail_func(x,y);
157113658Sdeischenstatic inline void
158117706Sdavidxuimm_fail_func(imm_struct *dev, int error_code)
159113661Sdeischen#else
160118676Sdavidxustatic inline void
161113870Sdeischenimm_fail(imm_struct *dev, int error_code)
162113658Sdeischen#endif
163113786Sdeischen{
164118676Sdavidxu	/* If we fail a device then we trash status / message bytes */
165113658Sdeischen	if (dev->cur_cmd) {
166114187Sdeischen		dev->cur_cmd->result = error_code << 16;
167117907Sdeischen		dev->failed = 1;
168113658Sdeischen	}
169115278Sdeischen}
170116977Sdavidxu
171139023Sdeischen/*
172113658Sdeischen * Wait for the high bit to be set.
173115278Sdeischen *
174136846Sdavidxu * In principle, this could be tied to an interrupt, but the adapter
175118676Sdavidxu * doesn't appear to be designed to support interrupts.  We spin on
176118676Sdavidxu * the 0x80 ready bit.
177118676Sdavidxu */
178113658Sdeischenstatic unsigned char imm_wait(imm_struct *dev)
179117715Sdeischen{
180117715Sdeischen	int k;
181117715Sdeischen	unsigned short ppb = dev->base;
182117715Sdeischen	unsigned char r;
183117715Sdeischen
184117715Sdeischen	w_ctr(ppb, 0x0c);
185118510Sdeischen
186118510Sdeischen	k = IMM_SPIN_TMO;
187117715Sdeischen	do {
188117715Sdeischen		r = r_str(ppb);
189117715Sdeischen		k--;
190117715Sdeischen		udelay(1);
191118510Sdeischen	}
192118510Sdeischen	while (!(r & 0x80) && (k));
193117715Sdeischen
194117715Sdeischen	/*
195113658Sdeischen	 * STR register (LPT base+1) to SCSI mapping:
196113658Sdeischen	 *
197113658Sdeischen	 * STR      imm     imm
198113658Sdeischen	 * ===================================
199116977Sdavidxu	 * 0x80     S_REQ   S_REQ
200116977Sdavidxu	 * 0x40     !S_BSY  (????)
201116977Sdavidxu	 * 0x20     !S_CD   !S_CD
202116977Sdavidxu	 * 0x10     !S_IO   !S_IO
203116977Sdavidxu	 * 0x08     (????)  !S_BSY
204116977Sdavidxu	 *
205116977Sdavidxu	 * imm      imm     meaning
206123668Sdavidxu	 * ==================================
207123668Sdavidxu	 * 0xf0     0xb8    Bit mask
208113658Sdeischen	 * 0xc0     0x88    ZIP wants more data
20913546Sjulian	 * 0xd0     0x98    ZIP wants to send more data
210113658Sdeischen	 * 0xe0     0xa8    ZIP is expecting SCSI command data
21113546Sjulian	 * 0xf0     0xb8    end of transfer, ZIP is sending status
212116977Sdavidxu	 */
213115278Sdeischen	w_ctr(ppb, 0x04);
214115278Sdeischen	if (k)
215115278Sdeischen		return (r & 0xb8);
21671581Sdeischen
217150499Sbrian	/* Counter expired - Time out occurred */
218150499Sbrian	imm_fail(dev, DID_TIME_OUT);
219118747Sdavidxu	printk("imm timeout in imm_wait\n");
220118747Sdavidxu	return 0;		/* command timed out */
221118747Sdavidxu}
222118747Sdavidxu
223118747Sdavidxustatic int imm_negotiate(imm_struct * tmp)
22467097Sdeischen{
225118747Sdavidxu	/*
226118747Sdavidxu	 * The following is supposedly the IEEE 1284-1994 negotiate
227118747Sdavidxu	 * sequence. I have yet to obtain a copy of the above standard
228118747Sdavidxu	 * so this is a bit of a guess...
229132120Sdavidxu	 *
23013546Sjulian	 * A fair chunk of this is based on the Linux parport implementation
231106191Smini	 * of IEEE 1284.
232113658Sdeischen	 *
233113658Sdeischen	 * Return 0 if data available
234106191Smini	 *        1 if no data available
235115278Sdeischen	 */
236115278Sdeischen
237106191Smini	unsigned short base = tmp->base;
238113658Sdeischen	unsigned char a, mode;
239113658Sdeischen
240113658Sdeischen	switch (tmp->mode) {
241106191Smini	case IMM_NIBBLE:
242113658Sdeischen		mode = 0x00;
243113658Sdeischen		break;
244113658Sdeischen	case IMM_PS2:
245113658Sdeischen		mode = 0x01;
246113658Sdeischen		break;
247113658Sdeischen	default:
248136846Sdavidxu		return 0;
249106191Smini	}
250106191Smini
251106191Smini	w_ctr(base, 0x04);
252113658Sdeischen	udelay(5);
253113658Sdeischen	w_dtr(base, mode);
254115278Sdeischen	udelay(100);
255116977Sdavidxu	w_ctr(base, 0x06);
256113658Sdeischen	udelay(5);
257150499Sbrian	a = (r_str(base) & 0x20) ? 0 : 1;
258150499Sbrian	udelay(5);
259113658Sdeischen	w_ctr(base, 0x07);
260113658Sdeischen	udelay(5);
261113658Sdeischen	w_ctr(base, 0x06);
262120074Sdavidxu
263113658Sdeischen	if (a) {
264113658Sdeischen		printk
265113658Sdeischen		    ("IMM: IEEE1284 negotiate indicates no data available.\n");
266113658Sdeischen		imm_fail(tmp, DID_ERROR);
267115278Sdeischen	}
268113658Sdeischen	return a;
269120074Sdavidxu}
270113658Sdeischen
271113658Sdeischen/*
272113658Sdeischen * Clear EPP timeout bit.
273113658Sdeischen */
274113658Sdeischenstatic inline void epp_reset(unsigned short ppb)
275113658Sdeischen{
276120074Sdavidxu	int i;
277113658Sdeischen
278113658Sdeischen	i = r_str(ppb);
279113658Sdeischen	w_str(ppb, i);
280113658Sdeischen	w_str(ppb, i & 0xfe);
281115278Sdeischen}
282113658Sdeischen
283120074Sdavidxu/*
284113658Sdeischen * Wait for empty ECP fifo (if we are in ECP fifo mode only)
285113658Sdeischen */
286113658Sdeischenstatic inline void ecp_sync(imm_struct *dev)
287113658Sdeischen{
288113658Sdeischen	int i, ppb_hi = dev->base_hi;
289113658Sdeischen
290136846Sdavidxu	if (ppb_hi == 0)
291113658Sdeischen		return;
292113658Sdeischen
293113658Sdeischen	if ((r_ecr(ppb_hi) & 0xe0) == 0x60) {	/* mode 011 == ECP fifo mode */
294113658Sdeischen		for (i = 0; i < 100; i++) {
295113658Sdeischen			if (r_ecr(ppb_hi) & 0x01)
296113661Sdeischen				return;
297136846Sdavidxu			udelay(5);
298113658Sdeischen		}
299113661Sdeischen		printk("imm: ECP sync failed as data still present in FIFO.\n");
300113661Sdeischen	}
301113658Sdeischen}
302113658Sdeischen
303113658Sdeischenstatic int imm_byte_out(unsigned short base, const char *buffer, int len)
304113658Sdeischen{
305113658Sdeischen	int i;
306113658Sdeischen
307113658Sdeischen	w_ctr(base, 0x4);	/* apparently a sane mode */
308113658Sdeischen	for (i = len >> 1; i; i--) {
309113658Sdeischen		w_dtr(base, *buffer++);
310113658Sdeischen		w_ctr(base, 0x5);	/* Drop STROBE low */
311113658Sdeischen		w_dtr(base, *buffer++);
312113658Sdeischen		w_ctr(base, 0x0);	/* STROBE high + INIT low */
313106191Smini	}
314113658Sdeischen	w_ctr(base, 0x4);	/* apparently a sane mode */
315113658Sdeischen	return 1;		/* All went well - we hope! */
316106191Smini}
317113658Sdeischen
318113658Sdeischenstatic int imm_nibble_in(unsigned short base, char *buffer, int len)
319113658Sdeischen{
320150499Sbrian	unsigned char l;
321150499Sbrian	int i;
322150499Sbrian
323113658Sdeischen	/*
324113658Sdeischen	 * The following is based on documented timing signals
325113658Sdeischen	 */
326113658Sdeischen	w_ctr(base, 0x4);
327113658Sdeischen	for (i = len; i; i--) {
328113658Sdeischen		w_ctr(base, 0x6);
329113658Sdeischen		l = (r_str(base) & 0xf0) >> 4;
330113658Sdeischen		w_ctr(base, 0x5);
331113658Sdeischen		*buffer++ = (r_str(base) & 0xf0) | l;
332113658Sdeischen		w_ctr(base, 0x4);
333113658Sdeischen	}
334116977Sdavidxu	return 1;		/* All went well - we hope! */
335122075Sdeischen}
336122075Sdeischen
337122075Sdeischenstatic int imm_byte_in(unsigned short base, char *buffer, int len)
338122075Sdeischen{
339122075Sdeischen	int i;
340122075Sdeischen
341122075Sdeischen	/*
342122075Sdeischen	 * The following is based on documented timing signals
343122075Sdeischen	 */
344122075Sdeischen	w_ctr(base, 0x4);
345122075Sdeischen	for (i = len; i; i--) {
346122075Sdeischen		w_ctr(base, 0x26);
347122075Sdeischen		*buffer++ = r_dtr(base);
348122075Sdeischen		w_ctr(base, 0x25);
349118747Sdavidxu	}
350118747Sdavidxu	return 1;		/* All went well - we hope! */
351117345Sdavidxu}
352118747Sdavidxu
353118747Sdavidxustatic int imm_out(imm_struct *dev, char *buffer, int len)
354128041Sdeischen{
355128041Sdeischen	unsigned short ppb = dev->base;
356128041Sdeischen	int r = imm_wait(dev);
357139023Sdeischen
358139023Sdeischen	/*
359139023Sdeischen	 * Make sure that:
360118747Sdavidxu	 * a) the SCSI bus is BUSY (device still listening)
361118747Sdavidxu	 * b) the device is listening
362118747Sdavidxu	 */
363118747Sdavidxu	if ((r & 0x18) != 0x08) {
364118747Sdavidxu		imm_fail(dev, DID_ERROR);
365132120Sdavidxu		printk("IMM: returned SCSI status %2x\n", r);
366116977Sdavidxu		return 0;
367113658Sdeischen	}
368113658Sdeischen	switch (dev->mode) {
369113658Sdeischen	case IMM_EPP_32:
370113658Sdeischen	case IMM_EPP_16:
371113658Sdeischen	case IMM_EPP_8:
372113658Sdeischen		epp_reset(ppb);
373113658Sdeischen		w_ctr(ppb, 0x4);
374113658Sdeischen		if (dev->mode == IMM_EPP_32 && !(((long) buffer | len) & 0x03))
375113658Sdeischen			outsl(ppb + 4, buffer, len >> 2);
376113658Sdeischen		else if (dev->mode == IMM_EPP_16 && !(((long) buffer | len) & 0x01))
377113658Sdeischen			outsw(ppb + 4, buffer, len >> 1);
378113658Sdeischen		else
379113658Sdeischen			outsb(ppb + 4, buffer, len);
380113658Sdeischen		w_ctr(ppb, 0xc);
381113658Sdeischen		r = !(r_str(ppb) & 0x01);
382113661Sdeischen		w_ctr(ppb, 0xc);
383113658Sdeischen		ecp_sync(dev);
384113658Sdeischen		break;
385113658Sdeischen
386113658Sdeischen	case IMM_NIBBLE:
387113658Sdeischen	case IMM_PS2:
388113658Sdeischen		/* 8 bit output, with a loop */
389113658Sdeischen		r = imm_byte_out(ppb, buffer, len);
390113658Sdeischen		break;
391113658Sdeischen
392136846Sdavidxu	default:
393113658Sdeischen		printk("IMM: bug in imm_out()\n");
394113658Sdeischen		r = 0;
395113661Sdeischen	}
396113658Sdeischen	return r;
397113658Sdeischen}
398113658Sdeischen
399113658Sdeischenstatic int imm_in(imm_struct *dev, char *buffer, int len)
400113658Sdeischen{
401113658Sdeischen	unsigned short ppb = dev->base;
402113658Sdeischen	int r = imm_wait(dev);
403113658Sdeischen
404113786Sdeischen	/*
405113658Sdeischen	 * Make sure that:
406113658Sdeischen	 * a) the SCSI bus is BUSY (device still listening)
407118747Sdavidxu	 * b) the device is sending data
408118747Sdavidxu	 */
409113658Sdeischen	if ((r & 0x18) != 0x18) {
410119063Sdavidxu		imm_fail(dev, DID_ERROR);
411119063Sdavidxu		return 0;
412119063Sdavidxu	}
413106191Smini	switch (dev->mode) {
414113658Sdeischen	case IMM_NIBBLE:
415113658Sdeischen		/* 4 bit input, with a loop */
416113658Sdeischen		r = imm_nibble_in(ppb, buffer, len);
417113786Sdeischen		w_ctr(ppb, 0xc);
418117706Sdavidxu		break;
419133563Sdeischen
420133269Sdeischen	case IMM_PS2:
421133269Sdeischen		/* 8 bit input, with a loop */
422133269Sdeischen		r = imm_byte_in(ppb, buffer, len);
423133269Sdeischen		w_ctr(ppb, 0xc);
424133269Sdeischen		break;
425133269Sdeischen
426133269Sdeischen	case IMM_EPP_32:
427133269Sdeischen	case IMM_EPP_16:
428133269Sdeischen	case IMM_EPP_8:
429133269Sdeischen		epp_reset(ppb);
430133269Sdeischen		w_ctr(ppb, 0x24);
431133269Sdeischen		if (dev->mode == IMM_EPP_32 && !(((long) buffer | len) & 0x03))
432133269Sdeischen			insw(ppb + 4, buffer, len >> 2);
433117706Sdavidxu		else if (dev->mode == IMM_EPP_16 && !(((long) buffer | len) & 0x01))
434118747Sdavidxu			insl(ppb + 4, buffer, len >> 1);
435118747Sdavidxu		else
436118747Sdavidxu			insb(ppb + 4, buffer, len);
437118747Sdavidxu		w_ctr(ppb, 0x2c);
438118747Sdavidxu		r = !(r_str(ppb) & 0x01);
439118747Sdavidxu		w_ctr(ppb, 0x2c);
440118747Sdavidxu		ecp_sync(dev);
441118510Sdeischen		break;
442113786Sdeischen
443114187Sdeischen	default:
444116977Sdavidxu		printk("IMM: bug in imm_ins()\n");
445113786Sdeischen		r = 0;
446113786Sdeischen		break;
447132120Sdavidxu	}
448132120Sdavidxu	return r;
449132120Sdavidxu}
450117706Sdavidxu
451135714Sssouhlalstatic int imm_cpp(unsigned short ppb, unsigned char b)
452133563Sdeischen{
453133269Sdeischen	/*
454133269Sdeischen	 * Comments on udelay values refer to the
455133269Sdeischen	 * Command Packet Protocol (CPP) timing diagram.
456133269Sdeischen	 */
457133269Sdeischen
458133269Sdeischen	unsigned char s1, s2, s3;
459135714Sssouhlal	w_ctr(ppb, 0x0c);
460135714Sssouhlal	udelay(2);		/* 1 usec - infinite */
461133269Sdeischen	w_dtr(ppb, 0xaa);
462133269Sdeischen	udelay(10);		/* 7 usec - infinite */
463113658Sdeischen	w_dtr(ppb, 0x55);
464113786Sdeischen	udelay(10);		/* 7 usec - infinite */
465113658Sdeischen	w_dtr(ppb, 0x00);
466113658Sdeischen	udelay(10);		/* 7 usec - infinite */
467113658Sdeischen	w_dtr(ppb, 0xff);
468113658Sdeischen	udelay(10);		/* 7 usec - infinite */
469113658Sdeischen	s1 = r_str(ppb) & 0xb8;
470113658Sdeischen	w_dtr(ppb, 0x87);
471113658Sdeischen	udelay(10);		/* 7 usec - infinite */
472113658Sdeischen	s2 = r_str(ppb) & 0xb8;
473113658Sdeischen	w_dtr(ppb, 0x78);
474113658Sdeischen	udelay(10);		/* 7 usec - infinite */
475113658Sdeischen	s3 = r_str(ppb) & 0x38;
476113658Sdeischen	/*
477113658Sdeischen	 * Values for b are:
478113658Sdeischen	 * 0000 00aa    Assign address aa to current device
479113658Sdeischen	 * 0010 00aa    Select device aa in EPP Winbond mode
480113658Sdeischen	 * 0010 10aa    Select device aa in EPP mode
481113658Sdeischen	 * 0011 xxxx    Deselect all devices
482113658Sdeischen	 * 0110 00aa    Test device aa
483113658Sdeischen	 * 1101 00aa    Select device aa in ECP mode
484113786Sdeischen	 * 1110 00aa    Select device aa in Compatible mode
485113658Sdeischen	 */
486118510Sdeischen	w_dtr(ppb, b);
487113786Sdeischen	udelay(2);		/* 1 usec - infinite */
488113658Sdeischen	w_ctr(ppb, 0x0c);
489113658Sdeischen	udelay(10);		/* 7 usec - infinite */
490113658Sdeischen	w_ctr(ppb, 0x0d);
491113658Sdeischen	udelay(2);		/* 1 usec - infinite */
492113658Sdeischen	w_ctr(ppb, 0x0c);
493115278Sdeischen	udelay(10);		/* 7 usec - infinite */
494113658Sdeischen	w_dtr(ppb, 0xff);
495113658Sdeischen	udelay(10);		/* 7 usec - infinite */
496113658Sdeischen
497113658Sdeischen	/*
498118510Sdeischen	 * The following table is electrical pin values.
499118510Sdeischen	 * (BSY is inverted at the CTR register)
500118510Sdeischen	 *
501113786Sdeischen	 *       BSY  ACK  POut SEL  Fault
502118510Sdeischen	 * S1    0    X    1    1    1
503113658Sdeischen	 * S2    1    X    0    1    1
504113658Sdeischen	 * S3    L    X    1    1    S
505113658Sdeischen	 *
506113658Sdeischen	 * L => Last device in chain
507113658Sdeischen	 * S => Selected
508113658Sdeischen	 *
509113658Sdeischen	 * Observered values for S1,S2,S3 are:
510113658Sdeischen	 * Disconnect => f8/58/78
511115080Sdeischen	 * Connect    => f8/58/70
512113658Sdeischen	 */
513113658Sdeischen	if ((s1 == 0xb8) && (s2 == 0x18) && (s3 == 0x30))
514113658Sdeischen		return 1;	/* Connected */
515113658Sdeischen	if ((s1 == 0xb8) && (s2 == 0x18) && (s3 == 0x38))
516113658Sdeischen		return 0;	/* Disconnected */
517113658Sdeischen
518115080Sdeischen	return -1;		/* No device present */
519118510Sdeischen}
520115080Sdeischen
521113658Sdeischenstatic inline int imm_connect(imm_struct *dev, int flag)
522113658Sdeischen{
523115080Sdeischen	unsigned short ppb = dev->base;
524115080Sdeischen
525115080Sdeischen	imm_cpp(ppb, 0xe0);	/* Select device 0 in compatible mode */
526113658Sdeischen	imm_cpp(ppb, 0x30);	/* Disconnect all devices */
527115080Sdeischen
528113658Sdeischen	if ((dev->mode == IMM_EPP_8) ||
529113658Sdeischen	    (dev->mode == IMM_EPP_16) ||
530113658Sdeischen	    (dev->mode == IMM_EPP_32))
531113658Sdeischen		return imm_cpp(ppb, 0x28);	/* Select device 0 in EPP mode */
532113658Sdeischen	return imm_cpp(ppb, 0xe0);	/* Select device 0 in compatible mode */
533113658Sdeischen}
534113658Sdeischen
535113658Sdeischenstatic void imm_disconnect(imm_struct *dev)
536113658Sdeischen{
537113658Sdeischen	imm_cpp(dev->base, 0x30);	/* Disconnect all devices */
538113658Sdeischen}
539113658Sdeischen
540113658Sdeischenstatic int imm_select(imm_struct *dev, int target)
541115080Sdeischen{
542117907Sdeischen	int k;
543115080Sdeischen	unsigned short ppb = dev->base;
544117907Sdeischen
545115278Sdeischen	/*
546113658Sdeischen	 * Firstly we want to make sure there is nothing
547106191Smini	 * holding onto the SCSI bus.
548113658Sdeischen	 */
549113658Sdeischen	w_ctr(ppb, 0xc);
550113658Sdeischen
551113658Sdeischen	k = IMM_SELECT_TMO;
552113658Sdeischen	do {
553117907Sdeischen		k--;
554113658Sdeischen	} while ((r_str(ppb) & 0x08) && (k));
555113658Sdeischen
556113658Sdeischen	if (!k)
557113658Sdeischen		return 0;
558115080Sdeischen
559115080Sdeischen	/*
560117907Sdeischen	 * Now assert the SCSI ID (HOST and TARGET) on the data bus
561115080Sdeischen	 */
562117907Sdeischen	w_ctr(ppb, 0x4);
563117907Sdeischen	w_dtr(ppb, 0x80 | (1 << target));
564113658Sdeischen	udelay(1);
565113658Sdeischen
566113658Sdeischen	/*
567113658Sdeischen	 * Deassert SELIN first followed by STROBE
568113658Sdeischen	 */
569113658Sdeischen	w_ctr(ppb, 0xc);
570113658Sdeischen	w_ctr(ppb, 0xd);
571118510Sdeischen
572113658Sdeischen	/*
573113658Sdeischen	 * ACK should drop low while SELIN is deasserted.
574113658Sdeischen	 * FAULT should drop low when the SCSI device latches the bus.
575113658Sdeischen	 */
576113658Sdeischen	k = IMM_SELECT_TMO;
577113658Sdeischen	do {
578113658Sdeischen		k--;
579113658Sdeischen	}
580118510Sdeischen	while (!(r_str(ppb) & 0x08) && (k));
581113658Sdeischen
582113658Sdeischen	/*
583113658Sdeischen	 * Place the interface back into a sane state (status mode)
584113658Sdeischen	 */
585113942Sdeischen	w_ctr(ppb, 0xc);
586113942Sdeischen	return (k) ? 1 : 0;
587113942Sdeischen}
588118510Sdeischen
589113942Sdeischenstatic int imm_init(imm_struct *dev)
590113942Sdeischen{
591113658Sdeischen	bool autodetect = dev->mode == IMM_AUTODETECT;
592113658Sdeischen
593113658Sdeischen	if (autodetect) {
594113658Sdeischen		int modes = dev->dev->port->modes;
595113658Sdeischen
596113658Sdeischen		/* Mode detection works up the chain of speed
597113658Sdeischen		 * This avoids a nasty if-then-else-if-... tree
598113658Sdeischen		 */
599113658Sdeischen		dev->mode = IMM_NIBBLE;
600113658Sdeischen
601113658Sdeischen		if (modes & PARPORT_MODE_TRISTATE)
602113658Sdeischen			dev->mode = IMM_PS2;
603113658Sdeischen	}
604115080Sdeischen
605115080Sdeischen	if (imm_connect(dev, 0) != 1)
606115080Sdeischen		return -EIO;
607115080Sdeischen	imm_reset_pulse(dev->base);
608115080Sdeischen	mdelay(1);	/* Delay to allow devices to settle */
609115080Sdeischen	imm_disconnect(dev);
610115080Sdeischen	mdelay(1);	/* Another delay to allow devices to settle */
611115080Sdeischen
612115080Sdeischen	return device_check(dev, autodetect);
613115080Sdeischen}
614115080Sdeischen
615113658Sdeischenstatic inline int imm_send_command(struct scsi_cmnd *cmd)
616113658Sdeischen{
617113658Sdeischen	imm_struct *dev = imm_dev(cmd->device->host);
618113658Sdeischen	int k;
619113658Sdeischen
620113658Sdeischen	/* NOTE: IMM uses byte pairs */
621115080Sdeischen	for (k = 0; k < cmd->cmd_len; k += 2)
622113658Sdeischen		if (!imm_out(dev, &cmd->cmnd[k], 2))
623113658Sdeischen			return 0;
624115080Sdeischen	return 1;
625123048Sdavidxu}
626113658Sdeischen
627113658Sdeischen/*
628139023Sdeischen * The bulk flag enables some optimisations in the data transfer loops,
629113658Sdeischen * it should be true for any command that transfers data in integral
630113658Sdeischen * numbers of sectors.
631113658Sdeischen *
632113658Sdeischen * The driver appears to remain stable if we speed up the parallel port
633115080Sdeischen * i/o in this function, but not elsewhere.
634115080Sdeischen */
635115080Sdeischenstatic int imm_completion(struct scsi_cmnd *const cmd)
636117706Sdavidxu{
637118510Sdeischen	/* Return codes:
638123048Sdavidxu	 * -1     Error
639132120Sdavidxu	 *  0     Told to schedule
640132120Sdavidxu	 *  1     Finished data transfer
641132120Sdavidxu	 */
642132120Sdavidxu	struct scsi_pointer *scsi_pointer = imm_scsi_pointer(cmd);
643132120Sdavidxu	imm_struct *dev = imm_dev(cmd->device->host);
644132120Sdavidxu	unsigned short ppb = dev->base;
645132120Sdavidxu	unsigned long start_jiffies = jiffies;
646132120Sdavidxu
647132120Sdavidxu	unsigned char r, v;
648132120Sdavidxu	int fast, bulk, status;
649132120Sdavidxu
650132120Sdavidxu	v = cmd->cmnd[0];
651132120Sdavidxu	bulk = ((v == READ_6) ||
652123312Sdavidxu		(v == READ_10) || (v == WRITE_6) || (v == WRITE_10));
653118510Sdeischen
654116977Sdavidxu	/*
655123048Sdavidxu	 * We only get here if the drive is ready to comunicate,
656123048Sdavidxu	 * hence no need for a full imm_wait.
657123048Sdavidxu	 */
658123048Sdavidxu	w_ctr(ppb, 0x0c);
659123048Sdavidxu	r = (r_str(ppb) & 0xb8);
660123048Sdavidxu
661139023Sdeischen	/*
662115080Sdeischen	 * while (device is not ready to send status byte)
663123048Sdavidxu	 *     loop;
664123048Sdavidxu	 */
665123048Sdavidxu	while (r != (unsigned char) 0xb8) {
666115080Sdeischen		/*
667113658Sdeischen		 * If we have been running for more than a full timer tick
668113658Sdeischen		 * then take a rest.
669113658Sdeischen		 */
670139023Sdeischen		if (time_after(jiffies, start_jiffies + 1))
671123048Sdavidxu			return 0;
672116977Sdavidxu
673123048Sdavidxu		/*
674116977Sdavidxu		 * FAIL if:
675116977Sdavidxu		 * a) Drive status is screwy (!ready && !present)
676116977Sdavidxu		 * b) Drive is requesting/sending more data than expected
677139023Sdeischen		 */
678116977Sdavidxu		if ((r & 0x88) != 0x88 || scsi_pointer->this_residual <= 0) {
679113658Sdeischen			imm_fail(dev, DID_ERROR);
680115080Sdeischen			return -1;	/* ERROR_RETURN */
681113658Sdeischen		}
682113658Sdeischen		/* determine if we should use burst I/O */
683113658Sdeischen		if (dev->rd == 0) {
684113658Sdeischen			fast = bulk && scsi_pointer->this_residual >=
685113658Sdeischen				IMM_BURST_SIZE ? IMM_BURST_SIZE : 2;
686113658Sdeischen			status = imm_out(dev, scsi_pointer->ptr, fast);
687113658Sdeischen		} else {
688113658Sdeischen			fast = bulk && scsi_pointer->this_residual >=
689113658Sdeischen				IMM_BURST_SIZE ? IMM_BURST_SIZE : 1;
690117706Sdavidxu			status = imm_in(dev, scsi_pointer->ptr, fast);
691113658Sdeischen		}
692118510Sdeischen
693113658Sdeischen		scsi_pointer->ptr += fast;
694118510Sdeischen		scsi_pointer->this_residual -= fast;
695118510Sdeischen
696113658Sdeischen		if (!status) {
697117706Sdavidxu			imm_fail(dev, DID_BUS_BUSY);
698117706Sdavidxu			return -1;	/* ERROR_RETURN */
699113658Sdeischen		}
700118510Sdeischen		if (scsi_pointer->buffer && !scsi_pointer->this_residual) {
701118510Sdeischen			/* if scatter/gather, advance to the next segment */
702118510Sdeischen			if (scsi_pointer->buffers_residual--) {
703123312Sdavidxu				scsi_pointer->buffer =
704117706Sdavidxu					sg_next(scsi_pointer->buffer);
705118510Sdeischen				scsi_pointer->this_residual =
706118510Sdeischen				    scsi_pointer->buffer->length;
707117706Sdavidxu				scsi_pointer->ptr = sg_virt(scsi_pointer->buffer);
708117706Sdavidxu
709117706Sdavidxu				/*
710132120Sdavidxu				 * Make sure that we transfer even number of bytes
711117706Sdavidxu				 * otherwise it makes imm_byte_out() messy.
712117706Sdavidxu				 */
713117706Sdavidxu				if (scsi_pointer->this_residual & 0x01)
714117706Sdavidxu					scsi_pointer->this_residual++;
715117706Sdavidxu			}
716117706Sdavidxu		}
717117706Sdavidxu		/* Now check to see if the drive is ready to comunicate */
718118510Sdeischen		w_ctr(ppb, 0x0c);
719118850Sdavidxu		r = (r_str(ppb) & 0xb8);
720118850Sdavidxu
721118850Sdavidxu		/* If not, drop back down to the scheduler and wait a timer tick */
722118850Sdavidxu		if (!(r & 0x80))
723118850Sdavidxu			return 0;
724118850Sdavidxu	}
725118850Sdavidxu	return 1;		/* FINISH_RETURN */
726118850Sdavidxu}
727106191Smini
728113786Sdeischen/*
729113786Sdeischen * Since the IMM itself doesn't generate interrupts, we use
730113658Sdeischen * the scheduler's task queue to generate a stream of call-backs and
731113786Sdeischen * complete the request when the drive is ready.
732113786Sdeischen */
733113786Sdeischenstatic void imm_interrupt(struct work_struct *work)
734113786Sdeischen{
735113786Sdeischen	imm_struct *dev = container_of(work, imm_struct, imm_tq.work);
736113786Sdeischen	struct scsi_cmnd *cmd = dev->cur_cmd;
737117706Sdavidxu	struct Scsi_Host *host = cmd->device->host;
738117706Sdavidxu	unsigned long flags;
739113786Sdeischen
740113786Sdeischen	if (imm_engine(dev, cmd)) {
741113786Sdeischen		schedule_delayed_work(&dev->imm_tq, 1);
742113786Sdeischen		return;
743113786Sdeischen	}
744113786Sdeischen	/* Command must of completed hence it is safe to let go... */
745113786Sdeischen#if IMM_DEBUG > 0
746120896Sdavidxu	switch ((cmd->result >> 16) & 0xff) {
747113786Sdeischen	case DID_OK:
748120896Sdavidxu		break;
749120896Sdavidxu	case DID_NO_CONNECT:
750120896Sdavidxu		printk("imm: no device at SCSI ID %i\n", cmd->device->id);
751120896Sdavidxu		break;
752120896Sdavidxu	case DID_BUS_BUSY:
753113786Sdeischen		printk("imm: BUS BUSY - EPP timeout detected\n");
754113786Sdeischen		break;
755113786Sdeischen	case DID_TIME_OUT:
756117706Sdavidxu		printk("imm: unknown timeout\n");
757117706Sdavidxu		break;
758117706Sdavidxu	case DID_ABORT:
759117706Sdavidxu		printk("imm: told to abort\n");
760117706Sdavidxu		break;
761113786Sdeischen	case DID_PARITY:
762117706Sdavidxu		printk("imm: parity error (???)\n");
763113786Sdeischen		break;
764113786Sdeischen	case DID_ERROR:
765113786Sdeischen		printk("imm: internal driver error\n");
766120896Sdavidxu		break;
767120896Sdavidxu	case DID_RESET:
768120896Sdavidxu		printk("imm: told to reset device\n");
769120896Sdavidxu		break;
770120896Sdavidxu	case DID_BAD_INTR:
771120896Sdavidxu		printk("imm: bad interrupt (???)\n");
772120896Sdavidxu		break;
773120896Sdavidxu	default:
774120896Sdavidxu		printk("imm: bad return code (%02x)\n",
775120896Sdavidxu		       (cmd->result >> 16) & 0xff);
776120896Sdavidxu	}
777120896Sdavidxu#endif
778120896Sdavidxu
779120896Sdavidxu	if (imm_scsi_pointer(cmd)->phase > 1)
780120896Sdavidxu		imm_disconnect(dev);
781120896Sdavidxu
782120896Sdavidxu	imm_pb_dismiss(dev);
783120896Sdavidxu
784120896Sdavidxu	spin_lock_irqsave(host->host_lock, flags);
785120896Sdavidxu	dev->cur_cmd = NULL;
786120896Sdavidxu	scsi_done(cmd);
787120896Sdavidxu	spin_unlock_irqrestore(host->host_lock, flags);
788120896Sdavidxu	return;
789120896Sdavidxu}
790120896Sdavidxu
791120896Sdavidxustatic int imm_engine(imm_struct *dev, struct scsi_cmnd *const cmd)
792120896Sdavidxu{
793120896Sdavidxu	struct scsi_pointer *scsi_pointer = imm_scsi_pointer(cmd);
794120896Sdavidxu	unsigned short ppb = dev->base;
795120896Sdavidxu	unsigned char l = 0, h = 0;
796120896Sdavidxu	int retv, x;
797120896Sdavidxu
798120896Sdavidxu	/* First check for any errors that may have occurred
799120896Sdavidxu	 * Here we check for internal errors
800117706Sdavidxu	 */
801120896Sdavidxu	if (dev->failed)
802120896Sdavidxu		return 0;
803117706Sdavidxu
804120896Sdavidxu	switch (scsi_pointer->phase) {
805120896Sdavidxu	case 0:		/* Phase 0 - Waiting for parport */
806120896Sdavidxu		if (time_after(jiffies, dev->jstart + HZ)) {
807120896Sdavidxu			/*
808120896Sdavidxu			 * We waited more than a second
809117706Sdavidxu			 * for parport to call us
810117706Sdavidxu			 */
811117706Sdavidxu			imm_fail(dev, DID_BUS_BUSY);
812120896Sdavidxu			return 0;
813120896Sdavidxu		}
814120896Sdavidxu		return 1;	/* wait until imm_wakeup claims parport */
815120896Sdavidxu
816120896Sdavidxu	case 1:		/* Phase 1 - Connected */
817120896Sdavidxu		imm_connect(dev, CONNECT_EPP_MAYBE);
818120896Sdavidxu		scsi_pointer->phase++;
819120896Sdavidxu		fallthrough;
820120896Sdavidxu
821113786Sdeischen	case 2:		/* Phase 2 - We are now talking to the scsi bus */
822113658Sdeischen		if (!imm_select(dev, scmd_id(cmd))) {
823113786Sdeischen			imm_fail(dev, DID_NO_CONNECT);
824113786Sdeischen			return 0;
825113658Sdeischen		}
826117706Sdavidxu		scsi_pointer->phase++;
827117706Sdavidxu		fallthrough;
828113786Sdeischen
829120896Sdavidxu	case 3:		/* Phase 3 - Ready to accept a command */
830120896Sdavidxu		w_ctr(ppb, 0x0c);
831120896Sdavidxu		if (!(r_str(ppb) & 0x80))
832120896Sdavidxu			return 1;
833113786Sdeischen
834117706Sdavidxu		if (!imm_send_command(cmd))
835113786Sdeischen			return 0;
836117706Sdavidxu		scsi_pointer->phase++;
837117706Sdavidxu		fallthrough;
838117706Sdavidxu
839117706Sdavidxu	case 4:		/* Phase 4 - Setup scatter/gather buffers */
840117706Sdavidxu		if (scsi_bufflen(cmd)) {
841117706Sdavidxu			scsi_pointer->buffer = scsi_sglist(cmd);
842117706Sdavidxu			scsi_pointer->this_residual = scsi_pointer->buffer->length;
843117706Sdavidxu			scsi_pointer->ptr = sg_virt(scsi_pointer->buffer);
844113658Sdeischen		} else {
845117706Sdavidxu			scsi_pointer->buffer = NULL;
846117706Sdavidxu			scsi_pointer->this_residual = 0;
847117706Sdavidxu			scsi_pointer->ptr = NULL;
848117706Sdavidxu		}
849117706Sdavidxu		scsi_pointer->buffers_residual = scsi_sg_count(cmd) - 1;
850117706Sdavidxu		scsi_pointer->phase++;
851117706Sdavidxu		if (scsi_pointer->this_residual & 0x01)
852117706Sdavidxu			scsi_pointer->this_residual++;
853117706Sdavidxu		fallthrough;
854117706Sdavidxu
855117907Sdeischen	case 5:		/* Phase 5 - Pre-Data transfer stage */
856117907Sdeischen		/* Spin lock for BUSY */
857113658Sdeischen		w_ctr(ppb, 0x0c);
858117706Sdavidxu		if (!(r_str(ppb) & 0x80))
859117706Sdavidxu			return 1;
860117706Sdavidxu
861117706Sdavidxu		/* Require negotiation for read requests */
862117706Sdavidxu		x = (r_str(ppb) & 0xb8);
863106191Smini		dev->rd = (x & 0x10) ? 1 : 0;
864117706Sdavidxu		dev->dp = (x & 0x20) ? 0 : 1;
865117706Sdavidxu
866117706Sdavidxu		if ((dev->dp) && (dev->rd))
867136286Sdavidxu			if (imm_negotiate(dev))
868136286Sdavidxu				return 0;
869136286Sdavidxu		scsi_pointer->phase++;
870136286Sdavidxu		fallthrough;
871136286Sdavidxu
872136286Sdavidxu	case 6:		/* Phase 6 - Data transfer stage */
873136286Sdavidxu		/* Spin lock for BUSY */
874136286Sdavidxu		w_ctr(ppb, 0x0c);
875117706Sdavidxu		if (!(r_str(ppb) & 0x80))
876113658Sdeischen			return 1;
877107202Smini
878117706Sdavidxu		if (dev->dp) {
879117706Sdavidxu			retv = imm_completion(cmd);
880117706Sdavidxu			if (retv == -1)
881117706Sdavidxu				return 0;
882107202Smini			if (retv == 0)
883113786Sdeischen				return 1;
884117706Sdavidxu		}
885118510Sdeischen		scsi_pointer->phase++;
886117706Sdavidxu		fallthrough;
887117706Sdavidxu
888113658Sdeischen	case 7:		/* Phase 7 - Post data transfer stage */
889106191Smini		if ((dev->dp) && (dev->rd)) {
890115173Sdeischen			if ((dev->mode == IMM_NIBBLE) || (dev->mode == IMM_PS2)) {
891115173Sdeischen				w_ctr(ppb, 0x4);
892113658Sdeischen				w_ctr(ppb, 0xc);
893113658Sdeischen				w_ctr(ppb, 0xe);
894113658Sdeischen				w_ctr(ppb, 0x4);
895106191Smini			}
896113658Sdeischen		}
897113658Sdeischen		scsi_pointer->phase++;
898113658Sdeischen		fallthrough;
899113658Sdeischen
900113658Sdeischen	case 8:		/* Phase 8 - Read status/message */
901113658Sdeischen		/* Check for data overrun */
902115173Sdeischen		if (imm_wait(dev) != (unsigned char) 0xb8) {
903106191Smini			imm_fail(dev, DID_ERROR);
904113658Sdeischen			return 0;
905113658Sdeischen		}
906113658Sdeischen		if (imm_negotiate(dev))
907113658Sdeischen			return 0;
908118510Sdeischen		if (imm_in(dev, &l, 1)) {	/* read status byte */
909113658Sdeischen			/* Check for optional message byte */
910118510Sdeischen			if (imm_wait(dev) == (unsigned char) 0xb8)
911113786Sdeischen				imm_in(dev, &h, 1);
912113658Sdeischen			cmd->result = (DID_OK << 16) | (l & STATUS_MASK);
913113658Sdeischen		}
914118510Sdeischen		if ((dev->mode == IMM_NIBBLE) || (dev->mode == IMM_PS2)) {
915118510Sdeischen			w_ctr(ppb, 0x4);
916113870Sdeischen			w_ctr(ppb, 0xc);
917113870Sdeischen			w_ctr(ppb, 0xe);
918113786Sdeischen			w_ctr(ppb, 0x4);
919123312Sdavidxu		}
920113786Sdeischen		return 0;	/* Finished */
921118510Sdeischen
922113786Sdeischen	default:
923113786Sdeischen		printk("imm: Invalid scsi phase\n");
924113786Sdeischen	}
925113786Sdeischen	return 0;
926113786Sdeischen}
927118850Sdavidxu
928118850Sdavidxustatic int imm_queuecommand_lck(struct scsi_cmnd *cmd)
929118850Sdavidxu{
930118850Sdavidxu	imm_struct *dev = imm_dev(cmd->device->host);
931118850Sdavidxu
932118850Sdavidxu	if (dev->cur_cmd) {
933118817Sdavidxu		printk("IMM: bug in imm_queuecommand\n");
934123312Sdavidxu		return 0;
935114187Sdeischen	}
936123312Sdavidxu	dev->failed = 0;
937123312Sdavidxu	dev->jstart = jiffies;
938113658Sdeischen	dev->cur_cmd = cmd;
939123312Sdavidxu	cmd->result = DID_ERROR << 16;	/* default return code */
940123312Sdavidxu	imm_scsi_pointer(cmd)->phase = 0;	/* bus free */
941123312Sdavidxu
942123312Sdavidxu	schedule_delayed_work(&dev->imm_tq, 0);
943123312Sdavidxu
944118510Sdeischen	imm_pb_claim(dev);
945118510Sdeischen
946118510Sdeischen	return 0;
947118510Sdeischen}
948118510Sdeischen
949118510Sdeischenstatic DEF_SCSI_QCMD(imm_queuecommand)
950116977Sdavidxu
951116977Sdavidxu/*
952113658Sdeischen * Apparently the disk->capacity attribute is off by 1 sector
953113658Sdeischen * for all disk drives.  We add the one here, but it should really
954113658Sdeischen * be done in sd.c.  Even if it gets fixed there, this will still
955113658Sdeischen * work.
956114187Sdeischen */
957113658Sdeischenstatic int imm_biosparam(struct scsi_device *sdev, struct block_device *dev,
958113658Sdeischen			 sector_t capacity, int ip[])
959113658Sdeischen{
960113658Sdeischen	ip[0] = 0x40;
961113658Sdeischen	ip[1] = 0x20;
962113658Sdeischen	ip[2] = ((unsigned long) capacity + 1) / (ip[0] * ip[1]);
963113658Sdeischen	if (ip[2] > 1024) {
964113658Sdeischen		ip[0] = 0xff;
965113658Sdeischen		ip[1] = 0x3f;
966139023Sdeischen		ip[2] = ((unsigned long) capacity + 1) / (ip[0] * ip[1]);
967139023Sdeischen	}
968106191Smini	return 0;
969106191Smini}
970113658Sdeischen
971113658Sdeischenstatic int imm_abort(struct scsi_cmnd *cmd)
97267097Sdeischen{
97335509Sjb	imm_struct *dev = imm_dev(cmd->device->host);
974113658Sdeischen	/*
97535509Sjb	 * There is no method for aborting commands since Iomega
976113658Sdeischen	 * have tied the SCSI_MESSAGE line high in the interface
97713546Sjulian	 */
978113658Sdeischen
979113658Sdeischen	switch (imm_scsi_pointer(cmd)->phase) {
980113658Sdeischen	case 0:		/* Do not have access to parport */
981113658Sdeischen	case 1:		/* Have not connected to interface */
982113658Sdeischen		dev->cur_cmd = NULL;	/* Forget the problem */
983113658Sdeischen		return SUCCESS;
984113658Sdeischen	default:		/* SCSI command sent, can not abort */
985132120Sdavidxu		return FAILED;
986113658Sdeischen	}
987113658Sdeischen}
988113658Sdeischen
989113658Sdeischenstatic void imm_reset_pulse(unsigned int base)
990113658Sdeischen{
991114187Sdeischen	w_ctr(base, 0x04);
992113658Sdeischen	w_dtr(base, 0x40);
993113658Sdeischen	udelay(1);
994113658Sdeischen	w_ctr(base, 0x0c);
995118817Sdavidxu	w_ctr(base, 0x0d);
996113658Sdeischen	udelay(50);
997113658Sdeischen	w_ctr(base, 0x0c);
998113658Sdeischen	w_ctr(base, 0x04);
999114267Sdavidxu}
1000115080Sdeischen
1001118510Sdeischenstatic int imm_reset(struct scsi_cmnd *cmd)
1002113658Sdeischen{
1003113658Sdeischen	imm_struct *dev = imm_dev(cmd->device->host);
1004103419Smini
1005132120Sdavidxu	if (imm_scsi_pointer(cmd)->phase)
1006132120Sdavidxu		imm_disconnect(dev);
1007113658Sdeischen	dev->cur_cmd = NULL;	/* Forget the problem */
1008132120Sdavidxu
1009118817Sdavidxu	imm_connect(dev, CONNECT_NORMAL);
101053812Salfred	imm_reset_pulse(dev->base);
1011114688Sdavidxu	mdelay(1);		/* device settle delay */
1012113658Sdeischen	imm_disconnect(dev);
1013114688Sdavidxu	mdelay(1);		/* device settle delay */
1014113658Sdeischen	return SUCCESS;
1015113658Sdeischen}
1016113658Sdeischen
1017119577Sdeischenstatic int device_check(imm_struct *dev, bool autodetect)
1018119577Sdeischen{
1019113658Sdeischen	/* This routine looks for a device and then attempts to use EPP
1020113658Sdeischen	   to send a command. If all goes as planned then EPP is available. */
1021113658Sdeischen
1022113658Sdeischen	static char cmd[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1023113786Sdeischen	int loop, old_mode, status, k, ppb = dev->base;
1024117706Sdavidxu	unsigned char l;
1025113786Sdeischen
1026113658Sdeischen	old_mode = dev->mode;
102767097Sdeischen	for (loop = 0; loop < 8; loop++) {
1028113658Sdeischen		/* Attempt to use EPP for Test Unit Ready */
1029113658Sdeischen		if (autodetect && (ppb & 0x0007) == 0x0000)
1030119577Sdeischen			dev->mode = IMM_EPP_8;
1031119577Sdeischen
1032113658Sdeischen	      second_pass:
1033113658Sdeischen		imm_connect(dev, CONNECT_EPP_MAYBE);
1034113658Sdeischen		/* Select SCSI device */
1035113658Sdeischen		if (!imm_select(dev, loop)) {
1036113658Sdeischen			imm_disconnect(dev);
1037113658Sdeischen			continue;
1038113658Sdeischen		}
1039113658Sdeischen		printk("imm: Found device at ID %i, Attempting to use %s\n",
1040113658Sdeischen		       loop, IMM_MODE_STRING[dev->mode]);
1041119700Sdavidxu
1042113658Sdeischen		/* Send SCSI command */
1043113658Sdeischen		status = 1;
1044115278Sdeischen		w_ctr(ppb, 0x0c);
1045113658Sdeischen		for (l = 0; (l < 3) && (status); l++)
1046113658Sdeischen			status = imm_out(dev, &cmd[l << 1], 2);
1047113658Sdeischen
1048113658Sdeischen		if (!status) {
1049113658Sdeischen			imm_disconnect(dev);
1050113658Sdeischen			imm_connect(dev, CONNECT_EPP_MAYBE);
1051113658Sdeischen			imm_reset_pulse(dev->base);
1052113658Sdeischen			udelay(1000);
1053113658Sdeischen			imm_disconnect(dev);
1054113658Sdeischen			udelay(1000);
1055113658Sdeischen			if (dev->mode != old_mode) {
1056118817Sdavidxu				dev->mode = old_mode;
1057113658Sdeischen				goto second_pass;
1058113658Sdeischen			}
1059113658Sdeischen			printk("imm: Unable to establish communication\n");
1060113658Sdeischen			return -EIO;
1061113658Sdeischen		}
1062113658Sdeischen		w_ctr(ppb, 0x0c);
1063113658Sdeischen
1064113658Sdeischen		k = 1000000;	/* 1 Second */
1065113658Sdeischen		do {
1066113658Sdeischen			l = r_str(ppb);
1067113658Sdeischen			k--;
1068113658Sdeischen			udelay(1);
1069113658Sdeischen		} while (!(l & 0x80) && (k));
1070113658Sdeischen
1071113658Sdeischen		l &= 0xb8;
1072113658Sdeischen
1073113658Sdeischen		if (l != 0xb8) {
1074113658Sdeischen			imm_disconnect(dev);
1075113658Sdeischen			imm_connect(dev, CONNECT_EPP_MAYBE);
1076113658Sdeischen			imm_reset_pulse(dev->base);
1077113658Sdeischen			udelay(1000);
1078113658Sdeischen			imm_disconnect(dev);
1079113658Sdeischen			udelay(1000);
1080139023Sdeischen			if (dev->mode != old_mode) {
1081120896Sdavidxu				dev->mode = old_mode;
1082120896Sdavidxu				goto second_pass;
1083120896Sdavidxu			}
1084116977Sdavidxu			printk
1085118510Sdeischen			    ("imm: Unable to establish communication\n");
1086114187Sdeischen			return -EIO;
1087116977Sdavidxu		}
1088119700Sdavidxu		imm_disconnect(dev);
1089113658Sdeischen		printk
1090113658Sdeischen		    ("imm: Communication established at 0x%x with ID %i using %s\n",
1091113658Sdeischen		     ppb, loop, IMM_MODE_STRING[dev->mode]);
1092115080Sdeischen		imm_connect(dev, CONNECT_EPP_MAYBE);
1093115080Sdeischen		imm_reset_pulse(dev->base);
1094115080Sdeischen		udelay(1000);
1095115080Sdeischen		imm_disconnect(dev);
1096115080Sdeischen		udelay(1000);
1097118510Sdeischen		return 0;
1098114187Sdeischen	}
1099115080Sdeischen	printk("imm: No devices found\n");
1100115080Sdeischen	return -ENODEV;
1101118510Sdeischen}
1102114187Sdeischen
1103113658Sdeischen/*
1104113658Sdeischen * imm cannot deal with highmem, so this causes all IO pages for this host
1105113658Sdeischen * to reside in low memory (hence mapped)
1106113658Sdeischen */
1107113658Sdeischenstatic int imm_adjust_queue(struct scsi_device *device)
110867097Sdeischen{
110948046Sjb	blk_queue_bounce_limit(device->request_queue, BLK_BOUNCE_HIGH);
1110113658Sdeischen	return 0;
1111116977Sdavidxu}
111267097Sdeischen
1113113658Sdeischenstatic const struct scsi_host_template imm_template = {
1114116977Sdavidxu	.module			= THIS_MODULE,
1115119063Sdavidxu	.proc_name		= "imm",
111613546Sjulian	.show_info		= imm_show_info,
1117116977Sdavidxu	.write_info		= imm_write_info,
1118116977Sdavidxu	.name			= "Iomega VPI2 (imm) interface",
1119116977Sdavidxu	.queuecommand		= imm_queuecommand,
1120139023Sdeischen	.eh_abort_handler	= imm_abort,
1121119063Sdavidxu	.eh_host_reset_handler	= imm_reset,
1122116977Sdavidxu	.bios_param		= imm_biosparam,
1123139023Sdeischen	.this_id		= 7,
1124118510Sdeischen	.sg_tablesize		= SG_ALL,
1125118510Sdeischen	.can_queue		= 1,
1126116977Sdavidxu	.slave_alloc		= imm_adjust_queue,
1127116977Sdavidxu	.cmd_size		= sizeof(struct scsi_pointer),
1128116977Sdavidxu};
1129116977Sdavidxu
1130113658Sdeischen/***************************************************************************
1131113658Sdeischen *                   Parallel port probing routines                        *
1132113658Sdeischen ***************************************************************************/
1133139023Sdeischen
1134113658Sdeischenstatic LIST_HEAD(imm_hosts);
1135139023Sdeischen
1136113658Sdeischen/*
1137120896Sdavidxu * Finds the first available device number that can be alloted to the
1138113658Sdeischen * new imm device and returns the address of the previous node so that
1139113658Sdeischen * we can add to the tail and have a list in the ascending order.
1140113658Sdeischen */
1141113658Sdeischen
1142113658Sdeischenstatic inline imm_struct *find_parent(void)
1143113658Sdeischen{
1144113658Sdeischen	imm_struct *dev, *par = NULL;
1145113658Sdeischen	unsigned int cnt = 0;
1146113658Sdeischen
1147113658Sdeischen	if (list_empty(&imm_hosts))
1148113658Sdeischen		return NULL;
1149113658Sdeischen
1150117907Sdeischen	list_for_each_entry(dev, &imm_hosts, list) {
1151115278Sdeischen		if (dev->dev_no != cnt)
1152113658Sdeischen			return par;
1153113658Sdeischen		cnt++;
1154115278Sdeischen		par = dev;
1155115278Sdeischen	}
1156115278Sdeischen
1157115278Sdeischen	return par;
1158115278Sdeischen}
1159117907Sdeischen
1160115278Sdeischenstatic int __imm_attach(struct parport *pb)
1161115278Sdeischen{
1162115278Sdeischen	struct Scsi_Host *host;
1163115278Sdeischen	imm_struct *dev, *temp;
1164115278Sdeischen	DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waiting);
1165113658Sdeischen	DEFINE_WAIT(wait);
1166115278Sdeischen	int ports;
1167115278Sdeischen	int err = -ENOMEM;
1168115278Sdeischen	struct pardev_cb imm_cb;
1169117907Sdeischen
1170115278Sdeischen	init_waitqueue_head(&waiting);
1171113658Sdeischen
1172115278Sdeischen	dev = kzalloc(sizeof(imm_struct), GFP_KERNEL);
1173117907Sdeischen	if (!dev)
1174117907Sdeischen		return -ENOMEM;
1175106786Smini
1176115278Sdeischen
117713546Sjulian	dev->base = -1;
1178113658Sdeischen	dev->mode = mode < IMM_UNKNOWN ? mode : IMM_AUTODETECT;
1179113658Sdeischen	INIT_LIST_HEAD(&dev->list);
118013546Sjulian
1181115278Sdeischen	temp = find_parent();
1182113661Sdeischen	if (temp)
1183113661Sdeischen		dev->dev_no = temp->dev_no + 1;
1184113661Sdeischen
1185113661Sdeischen	memset(&imm_cb, 0, sizeof(imm_cb));
1186113661Sdeischen	imm_cb.private = dev;
1187113661Sdeischen	imm_cb.wakeup = imm_wakeup;
1188113661Sdeischen
1189113661Sdeischen	dev->dev = parport_register_dev_model(pb, "imm", &imm_cb, dev->dev_no);
1190113661Sdeischen	if (!dev->dev)
1191113661Sdeischen		goto out;
1192113661Sdeischen
1193113661Sdeischen
1194113661Sdeischen	/* Claim the bus so it remembers what we do to the control
1195113661Sdeischen	 * registers. [ CTR and ECP ]
1196113661Sdeischen	 */
1197113661Sdeischen	err = -EBUSY;
1198113661Sdeischen	dev->waiting = &waiting;
1199113661Sdeischen	prepare_to_wait(&waiting, &wait, TASK_UNINTERRUPTIBLE);
1200113661Sdeischen	if (imm_pb_claim(dev))
1201113658Sdeischen		schedule_timeout(3 * HZ);
1202136846Sdavidxu	if (dev->wanted) {
1203119732Sdavidxu		printk(KERN_ERR "imm%d: failed to claim parport because "
1204113658Sdeischen			"a pardevice is owning the port for too long "
1205115278Sdeischen			"time!\n", pb->number);
1206115278Sdeischen		imm_pb_dismiss(dev);
1207115278Sdeischen		dev->waiting = NULL;
1208115278Sdeischen		finish_wait(&waiting, &wait);
1209115278Sdeischen		goto out1;
1210117706Sdavidxu	}
1211115278Sdeischen	dev->waiting = NULL;
1212117706Sdavidxu	finish_wait(&waiting, &wait);
1213117706Sdavidxu	dev->base = dev->dev->port->base;
1214115278Sdeischen	dev->base_hi = dev->dev->port->base_hi;
1215115278Sdeischen	w_ctr(dev->base, 0x0c);
1216115278Sdeischen
1217113661Sdeischen	/* Done configuration */
1218113658Sdeischen
121967097Sdeischen	err = imm_init(dev);
1220113658Sdeischen
1221113661Sdeischen	imm_pb_release(dev);
1222113658Sdeischen
1223118676Sdavidxu	if (err)
1224118676Sdavidxu		goto out1;
1225118676Sdavidxu
1226118676Sdavidxu	/* now the glue ... */
1227118676Sdavidxu	if (dev->mode == IMM_NIBBLE || dev->mode == IMM_PS2)
1228118676Sdavidxu		ports = 3;
1229118676Sdavidxu	else
1230118676Sdavidxu		ports = 8;
1231113661Sdeischen
1232113661Sdeischen	INIT_DELAYED_WORK(&dev->imm_tq, imm_interrupt);
1233113786Sdeischen
1234106786Smini	err = -ENOMEM;
1235113786Sdeischen	host = scsi_host_alloc(&imm_template, sizeof(imm_struct *));
1236113661Sdeischen	if (!host)
1237113661Sdeischen		goto out1;
1238113661Sdeischen	host->io_port = pb->base;
1239113661Sdeischen	host->n_io_port = ports;
1240113661Sdeischen	host->dma_channel = -1;
1241113661Sdeischen	host->unique_id = pb->number;
1242136846Sdavidxu	*(imm_struct **)&host->hostdata = dev;
1243113661Sdeischen	dev->host = host;
1244115278Sdeischen	if (!temp)
1245118510Sdeischen		list_add_tail(&dev->list, &imm_hosts);
1246113661Sdeischen	else
1247113661Sdeischen		list_add_tail(&dev->list, &temp->list);
1248113661Sdeischen	err = scsi_add_host(host, NULL);
1249113661Sdeischen	if (err)
1250113661Sdeischen		goto out2;
1251113661Sdeischen	scsi_scan_host(host);
1252113661Sdeischen	return 0;
1253113786Sdeischen
1254113786Sdeischenout2:
1255113786Sdeischen	list_del_init(&dev->list);
1256113786Sdeischen	scsi_host_put(host);
1257113786Sdeischenout1:
1258113658Sdeischen	parport_unregister_device(dev->dev);
1259113786Sdeischenout:
1260113786Sdeischen	kfree(dev);
1261113786Sdeischen	return err;
1262113786Sdeischen}
1263113786Sdeischen
1264113661Sdeischenstatic void imm_attach(struct parport *pb)
1265113786Sdeischen{
1266113786Sdeischen	__imm_attach(pb);
1267113786Sdeischen}
1268113786Sdeischen
1269113786Sdeischenstatic void imm_detach(struct parport *pb)
1270113786Sdeischen{
1271113786Sdeischen	imm_struct *dev;
1272114187Sdeischen	list_for_each_entry(dev, &imm_hosts, list) {
1273113786Sdeischen		if (dev->dev->port == pb) {
1274113786Sdeischen			list_del_init(&dev->list);
1275113786Sdeischen			scsi_remove_host(dev->host);
1276113786Sdeischen			scsi_host_put(dev->host);
1277113786Sdeischen			parport_unregister_device(dev->dev);
1278113658Sdeischen			kfree(dev);
1279113786Sdeischen			break;
1280113786Sdeischen		}
1281118985Sdavidxu	}
1282118985Sdavidxu}
1283118985Sdavidxu
1284118985Sdavidxustatic struct parport_driver imm_driver = {
1285118985Sdavidxu	.name		= "imm",
1286118985Sdavidxu	.match_port	= imm_attach,
1287118985Sdavidxu	.detach		= imm_detach,
1288118985Sdavidxu	.devmodel	= true,
1289118985Sdavidxu};
1290113786Sdeischenmodule_parport_driver(imm_driver);
1291115278Sdeischen
1292113786SdeischenMODULE_LICENSE("GPL");
1293113661Sdeischen