1/*
2 *  Copyright (C) 1997	Wu Ching Chen
3 *  2.1.x update (C) 1998  Krzysztof G. Baranowski
4 *  2.5.x update (C) 2002  Red Hat
5 *  2.6.x update (C) 2004  Red Hat
6 *
7 * Marcelo Tosatti <marcelo@conectiva.com.br> : SMP fixes
8 *
9 * Wu Ching Chen : NULL pointer fixes  2000/06/02
10 *		   support atp876 chip
11 *		   enable 32 bit fifo transfer
12 *		   support cdrom & remove device run ultra speed
13 *		   fix disconnect bug  2000/12/21
14 *		   support atp880 chip lvd u160 2001/05/15
15 *		   fix prd table bug 2001/09/12 (7.1)
16 *
17 * atp885 support add by ACARD Hao Ping Lian 2005/01/05
18 */
19#include <linux/module.h>
20#include <linux/init.h>
21#include <linux/interrupt.h>
22#include <linux/kernel.h>
23#include <linux/types.h>
24#include <linux/string.h>
25#include <linux/ioport.h>
26#include <linux/delay.h>
27#include <linux/proc_fs.h>
28#include <linux/spinlock.h>
29#include <linux/pci.h>
30#include <linux/blkdev.h>
31#include <linux/dma-mapping.h>
32#include <linux/slab.h>
33#include <asm/io.h>
34
35#include <scsi/scsi.h>
36#include <scsi/scsi_cmnd.h>
37#include <scsi/scsi_device.h>
38#include <scsi/scsi_host.h>
39
40#include "atp870u.h"
41
42static struct scsi_host_template atp870u_template;
43static void send_s870(struct atp_unit *dev,unsigned char c);
44static void is885(struct atp_unit *dev, unsigned int wkport,unsigned char c);
45static void tscam_885(void);
46
47static irqreturn_t atp870u_intr_handle(int irq, void *dev_id)
48{
49	unsigned long flags;
50	unsigned short int tmpcip, id;
51	unsigned char i, j, c, target_id, lun,cmdp;
52	unsigned char *prd;
53	struct scsi_cmnd *workreq;
54	unsigned int workport, tmport, tmport1;
55	unsigned long adrcnt, k;
56#ifdef ED_DBGP
57	unsigned long l;
58#endif
59	int errstus;
60	struct Scsi_Host *host = dev_id;
61	struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
62
63	for (c = 0; c < 2; c++) {
64		tmport = dev->ioport[c] + 0x1f;
65		j = inb(tmport);
66		if ((j & 0x80) != 0)
67		{
68	   		goto ch_sel;
69		}
70		dev->in_int[c] = 0;
71	}
72	return IRQ_NONE;
73ch_sel:
74#ifdef ED_DBGP
75	printk("atp870u_intr_handle enter\n");
76#endif
77	dev->in_int[c] = 1;
78	cmdp = inb(dev->ioport[c] + 0x10);
79	workport = dev->ioport[c];
80	if (dev->working[c] != 0) {
81		if (dev->dev_id == ATP885_DEVID) {
82			tmport1 = workport + 0x16;
83			if ((inb(tmport1) & 0x80) == 0)
84				outb((inb(tmport1) | 0x80), tmport1);
85		}
86		tmpcip = dev->pciport[c];
87		if ((inb(tmpcip) & 0x08) != 0)
88		{
89			tmpcip += 0x2;
90			for (k=0; k < 1000; k++) {
91				if ((inb(tmpcip) & 0x08) == 0) {
92					goto stop_dma;
93				}
94				if ((inb(tmpcip) & 0x01) == 0) {
95					goto stop_dma;
96				}
97			}
98		}
99stop_dma:
100		tmpcip = dev->pciport[c];
101		outb(0x00, tmpcip);
102		tmport -= 0x08;
103
104		i = inb(tmport);
105
106		if (dev->dev_id == ATP885_DEVID) {
107			tmpcip += 2;
108			outb(0x06, tmpcip);
109			tmpcip -= 2;
110		}
111
112		tmport -= 0x02;
113		target_id = inb(tmport);
114		tmport += 0x02;
115
116		/*
117		 *	Remap wide devices onto id numbers
118		 */
119
120		if ((target_id & 0x40) != 0) {
121			target_id = (target_id & 0x07) | 0x08;
122		} else {
123			target_id &= 0x07;
124		}
125
126		if ((j & 0x40) != 0) {
127		     if (dev->last_cmd[c] == 0xff) {
128			dev->last_cmd[c] = target_id;
129		     }
130		     dev->last_cmd[c] |= 0x40;
131		}
132		if (dev->dev_id == ATP885_DEVID)
133			dev->r1f[c][target_id] |= j;
134#ifdef ED_DBGP
135		printk("atp870u_intr_handle status = %x\n",i);
136#endif
137		if (i == 0x85) {
138			if ((dev->last_cmd[c] & 0xf0) != 0x40) {
139			   dev->last_cmd[c] = 0xff;
140			}
141			if (dev->dev_id == ATP885_DEVID) {
142				tmport -= 0x05;
143				adrcnt = 0;
144				((unsigned char *) &adrcnt)[2] = inb(tmport++);
145				((unsigned char *) &adrcnt)[1] = inb(tmport++);
146				((unsigned char *) &adrcnt)[0] = inb(tmport);
147				if (dev->id[c][target_id].last_len != adrcnt)
148				{
149			   		k = dev->id[c][target_id].last_len;
150			   		k -= adrcnt;
151			   		dev->id[c][target_id].tran_len = k;
152			   	dev->id[c][target_id].last_len = adrcnt;
153				}
154#ifdef ED_DBGP
155				printk("tmport = %x dev->id[c][target_id].last_len = %d dev->id[c][target_id].tran_len = %d\n",tmport,dev->id[c][target_id].last_len,dev->id[c][target_id].tran_len);
156#endif
157			}
158
159			/*
160			 *      Flip wide
161			 */
162			if (dev->wide_id[c] != 0) {
163				tmport = workport + 0x1b;
164				outb(0x01, tmport);
165				while ((inb(tmport) & 0x01) != 0x01) {
166					outb(0x01, tmport);
167				}
168			}
169			/*
170			 *	Issue more commands
171			 */
172			spin_lock_irqsave(dev->host->host_lock, flags);
173			if (((dev->quhd[c] != dev->quend[c]) || (dev->last_cmd[c] != 0xff)) &&
174			    (dev->in_snd[c] == 0)) {
175#ifdef ED_DBGP
176				printk("Call sent_s870\n");
177#endif
178				send_s870(dev,c);
179			}
180			spin_unlock_irqrestore(dev->host->host_lock, flags);
181			/*
182			 *	Done
183			 */
184			dev->in_int[c] = 0;
185#ifdef ED_DBGP
186				printk("Status 0x85 return\n");
187#endif
188			goto handled;
189		}
190
191		if (i == 0x40) {
192		     dev->last_cmd[c] |= 0x40;
193		     dev->in_int[c] = 0;
194		     goto handled;
195		}
196
197		if (i == 0x21) {
198			if ((dev->last_cmd[c] & 0xf0) != 0x40) {
199			   dev->last_cmd[c] = 0xff;
200			}
201			tmport -= 0x05;
202			adrcnt = 0;
203			((unsigned char *) &adrcnt)[2] = inb(tmport++);
204			((unsigned char *) &adrcnt)[1] = inb(tmport++);
205			((unsigned char *) &adrcnt)[0] = inb(tmport);
206			k = dev->id[c][target_id].last_len;
207			k -= adrcnt;
208			dev->id[c][target_id].tran_len = k;
209			dev->id[c][target_id].last_len = adrcnt;
210			tmport -= 0x04;
211			outb(0x41, tmport);
212			tmport += 0x08;
213			outb(0x08, tmport);
214			dev->in_int[c] = 0;
215			goto handled;
216		}
217
218		if (dev->dev_id == ATP885_DEVID) {
219			if ((i == 0x4c) || (i == 0x4d) || (i == 0x8c) || (i == 0x8d)) {
220		   		if ((i == 0x4c) || (i == 0x8c))
221		      			i=0x48;
222		   		else
223		      			i=0x49;
224		   	}
225
226		}
227		if ((i == 0x80) || (i == 0x8f)) {
228#ifdef ED_DBGP
229			printk(KERN_DEBUG "Device reselect\n");
230#endif
231			lun = 0;
232			tmport -= 0x07;
233			if (cmdp == 0x44 || i==0x80) {
234				tmport += 0x0d;
235				lun = inb(tmport) & 0x07;
236			} else {
237				if ((dev->last_cmd[c] & 0xf0) != 0x40) {
238				   dev->last_cmd[c] = 0xff;
239				}
240				if (cmdp == 0x41) {
241#ifdef ED_DBGP
242					printk("cmdp = 0x41\n");
243#endif
244					tmport += 0x02;
245					adrcnt = 0;
246					((unsigned char *) &adrcnt)[2] = inb(tmport++);
247					((unsigned char *) &adrcnt)[1] = inb(tmport++);
248					((unsigned char *) &adrcnt)[0] = inb(tmport);
249					k = dev->id[c][target_id].last_len;
250					k -= adrcnt;
251					dev->id[c][target_id].tran_len = k;
252					dev->id[c][target_id].last_len = adrcnt;
253					tmport += 0x04;
254					outb(0x08, tmport);
255					dev->in_int[c] = 0;
256					goto handled;
257				} else {
258#ifdef ED_DBGP
259					printk("cmdp != 0x41\n");
260#endif
261					outb(0x46, tmport);
262					dev->id[c][target_id].dirct = 0x00;
263					tmport += 0x02;
264					outb(0x00, tmport++);
265					outb(0x00, tmport++);
266					outb(0x00, tmport++);
267					tmport += 0x03;
268					outb(0x08, tmport);
269					dev->in_int[c] = 0;
270					goto handled;
271				}
272			}
273			if (dev->last_cmd[c] != 0xff) {
274			   dev->last_cmd[c] |= 0x40;
275			}
276			if (dev->dev_id == ATP885_DEVID) {
277				j = inb(dev->baseport + 0x29) & 0xfe;
278				outb(j, dev->baseport + 0x29);
279				tmport = workport + 0x16;
280			} else {
281				tmport = workport + 0x10;
282				outb(0x45, tmport);
283				tmport += 0x06;
284			}
285
286			target_id = inb(tmport);
287			/*
288			 *	Remap wide identifiers
289			 */
290			if ((target_id & 0x10) != 0) {
291				target_id = (target_id & 0x07) | 0x08;
292			} else {
293				target_id &= 0x07;
294			}
295			if (dev->dev_id == ATP885_DEVID) {
296				tmport = workport + 0x10;
297				outb(0x45, tmport);
298			}
299			workreq = dev->id[c][target_id].curr_req;
300#ifdef ED_DBGP
301			scmd_printk(KERN_DEBUG, workreq, "CDB");
302			for (l = 0; l < workreq->cmd_len; l++)
303				printk(KERN_DEBUG " %x",workreq->cmnd[l]);
304			printk("\n");
305#endif
306
307			tmport = workport + 0x0f;
308			outb(lun, tmport);
309			tmport += 0x02;
310			outb(dev->id[c][target_id].devsp, tmport++);
311			adrcnt = dev->id[c][target_id].tran_len;
312			k = dev->id[c][target_id].last_len;
313
314			outb(((unsigned char *) &k)[2], tmport++);
315			outb(((unsigned char *) &k)[1], tmport++);
316			outb(((unsigned char *) &k)[0], tmport++);
317#ifdef ED_DBGP
318			printk("k %x, k[0] 0x%x k[1] 0x%x k[2] 0x%x\n", k, inb(tmport-1), inb(tmport-2), inb(tmport-3));
319#endif
320			/* Remap wide */
321			j = target_id;
322			if (target_id > 7) {
323				j = (j & 0x07) | 0x40;
324			}
325			/* Add direction */
326			j |= dev->id[c][target_id].dirct;
327			outb(j, tmport++);
328			outb(0x80,tmport);
329
330			/* enable 32 bit fifo transfer */
331			if (dev->dev_id == ATP885_DEVID) {
332				tmpcip = dev->pciport[c] + 1;
333				i=inb(tmpcip) & 0xf3;
334				//j=workreq->cmnd[0];
335				if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
336				   i |= 0x0c;
337				}
338				outb(i,tmpcip);
339			} else if ((dev->dev_id == ATP880_DEVID1) ||
340	    		    	   (dev->dev_id == ATP880_DEVID2) ) {
341				tmport = workport - 0x05;
342				if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
343					outb((unsigned char) ((inb(tmport) & 0x3f) | 0xc0), tmport);
344				} else {
345					outb((unsigned char) (inb(tmport) & 0x3f), tmport);
346				}
347			} else {
348				tmport = workport + 0x3a;
349				if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
350					outb((unsigned char) ((inb(tmport) & 0xf3) | 0x08), tmport);
351				} else {
352					outb((unsigned char) (inb(tmport) & 0xf3), tmport);
353				}
354			}
355			tmport = workport + 0x1b;
356			j = 0;
357			id = 1;
358			id = id << target_id;
359			/*
360			 *	Is this a wide device
361			 */
362			if ((id & dev->wide_id[c]) != 0) {
363				j |= 0x01;
364			}
365			outb(j, tmport);
366			while ((inb(tmport) & 0x01) != j) {
367				outb(j,tmport);
368			}
369			if (dev->id[c][target_id].last_len == 0) {
370				tmport = workport + 0x18;
371				outb(0x08, tmport);
372				dev->in_int[c] = 0;
373#ifdef ED_DBGP
374				printk("dev->id[c][target_id].last_len = 0\n");
375#endif
376				goto handled;
377			}
378#ifdef ED_DBGP
379			printk("target_id = %d adrcnt = %d\n",target_id,adrcnt);
380#endif
381			prd = dev->id[c][target_id].prd_pos;
382			while (adrcnt != 0) {
383				id = ((unsigned short int *)prd)[2];
384				if (id == 0) {
385					k = 0x10000;
386				} else {
387					k = id;
388				}
389				if (k > adrcnt) {
390					((unsigned short int *)prd)[2] = (unsigned short int)
391					    (k - adrcnt);
392					((unsigned long *)prd)[0] += adrcnt;
393					adrcnt = 0;
394					dev->id[c][target_id].prd_pos = prd;
395				} else {
396					adrcnt -= k;
397					dev->id[c][target_id].prdaddr += 0x08;
398					prd += 0x08;
399					if (adrcnt == 0) {
400						dev->id[c][target_id].prd_pos = prd;
401					}
402				}
403			}
404			tmpcip = dev->pciport[c] + 0x04;
405			outl(dev->id[c][target_id].prdaddr, tmpcip);
406#ifdef ED_DBGP
407			printk("dev->id[%d][%d].prdaddr 0x%8x\n", c, target_id, dev->id[c][target_id].prdaddr);
408#endif
409			if (dev->dev_id == ATP885_DEVID) {
410				tmpcip -= 0x04;
411			} else {
412				tmpcip -= 0x02;
413				outb(0x06, tmpcip);
414				outb(0x00, tmpcip);
415				tmpcip -= 0x02;
416			}
417			tmport = workport + 0x18;
418			/*
419			 *	Check transfer direction
420			 */
421			if (dev->id[c][target_id].dirct != 0) {
422				outb(0x08, tmport);
423				outb(0x01, tmpcip);
424				dev->in_int[c] = 0;
425#ifdef ED_DBGP
426				printk("status 0x80 return dirct != 0\n");
427#endif
428				goto handled;
429			}
430			outb(0x08, tmport);
431			outb(0x09, tmpcip);
432			dev->in_int[c] = 0;
433#ifdef ED_DBGP
434			printk("status 0x80 return dirct = 0\n");
435#endif
436			goto handled;
437		}
438
439		/*
440		 *	Current scsi request on this target
441		 */
442
443		workreq = dev->id[c][target_id].curr_req;
444
445		if (i == 0x42) {
446			if ((dev->last_cmd[c] & 0xf0) != 0x40)
447			{
448			   dev->last_cmd[c] = 0xff;
449			}
450			errstus = 0x02;
451			workreq->result = errstus;
452			goto go_42;
453		}
454		if (i == 0x16) {
455			if ((dev->last_cmd[c] & 0xf0) != 0x40) {
456			   dev->last_cmd[c] = 0xff;
457			}
458			errstus = 0;
459			tmport -= 0x08;
460			errstus = inb(tmport);
461			if (((dev->r1f[c][target_id] & 0x10) != 0)&&(dev->dev_id==ATP885_DEVID)) {
462			   printk(KERN_WARNING "AEC67162 CRC ERROR !\n");
463			   errstus = 0x02;
464			}
465			workreq->result = errstus;
466go_42:
467			if (dev->dev_id == ATP885_DEVID) {
468				j = inb(dev->baseport + 0x29) | 0x01;
469				outb(j, dev->baseport + 0x29);
470			}
471			/*
472			 *	Complete the command
473			 */
474			scsi_dma_unmap(workreq);
475
476			spin_lock_irqsave(dev->host->host_lock, flags);
477			(*workreq->scsi_done) (workreq);
478#ifdef ED_DBGP
479			   printk("workreq->scsi_done\n");
480#endif
481			/*
482			 *	Clear it off the queue
483			 */
484			dev->id[c][target_id].curr_req = NULL;
485			dev->working[c]--;
486			spin_unlock_irqrestore(dev->host->host_lock, flags);
487			/*
488			 *      Take it back wide
489			 */
490			if (dev->wide_id[c] != 0) {
491				tmport = workport + 0x1b;
492				outb(0x01, tmport);
493				while ((inb(tmport) & 0x01) != 0x01) {
494					outb(0x01, tmport);
495				}
496			}
497			/*
498			 *	If there is stuff to send and nothing going then send it
499			 */
500			spin_lock_irqsave(dev->host->host_lock, flags);
501			if (((dev->last_cmd[c] != 0xff) || (dev->quhd[c] != dev->quend[c])) &&
502			    (dev->in_snd[c] == 0)) {
503#ifdef ED_DBGP
504			   printk("Call sent_s870(scsi_done)\n");
505#endif
506			   send_s870(dev,c);
507			}
508			spin_unlock_irqrestore(dev->host->host_lock, flags);
509			dev->in_int[c] = 0;
510			goto handled;
511		}
512		if ((dev->last_cmd[c] & 0xf0) != 0x40) {
513		   dev->last_cmd[c] = 0xff;
514		}
515		if (i == 0x4f) {
516			i = 0x89;
517		}
518		i &= 0x0f;
519		if (i == 0x09) {
520			tmpcip += 4;
521			outl(dev->id[c][target_id].prdaddr, tmpcip);
522			tmpcip = tmpcip - 2;
523			outb(0x06, tmpcip);
524			outb(0x00, tmpcip);
525			tmpcip = tmpcip - 2;
526			tmport = workport + 0x10;
527			outb(0x41, tmport);
528			if (dev->dev_id == ATP885_DEVID) {
529				tmport += 2;
530				k = dev->id[c][target_id].last_len;
531				outb((unsigned char) (((unsigned char *) (&k))[2]), tmport++);
532				outb((unsigned char) (((unsigned char *) (&k))[1]), tmport++);
533				outb((unsigned char) (((unsigned char *) (&k))[0]), tmport);
534				dev->id[c][target_id].dirct = 0x00;
535				tmport += 0x04;
536			} else {
537				dev->id[c][target_id].dirct = 0x00;
538				tmport += 0x08;
539			}
540			outb(0x08, tmport);
541			outb(0x09, tmpcip);
542			dev->in_int[c] = 0;
543			goto handled;
544		}
545		if (i == 0x08) {
546			tmpcip += 4;
547			outl(dev->id[c][target_id].prdaddr, tmpcip);
548			tmpcip = tmpcip - 2;
549			outb(0x06, tmpcip);
550			outb(0x00, tmpcip);
551			tmpcip = tmpcip - 2;
552			tmport = workport + 0x10;
553			outb(0x41, tmport);
554			if (dev->dev_id == ATP885_DEVID) {
555				tmport += 2;
556				k = dev->id[c][target_id].last_len;
557				outb((unsigned char) (((unsigned char *) (&k))[2]), tmport++);
558				outb((unsigned char) (((unsigned char *) (&k))[1]), tmport++);
559				outb((unsigned char) (((unsigned char *) (&k))[0]), tmport++);
560			} else {
561				tmport += 5;
562			}
563			outb((unsigned char) (inb(tmport) | 0x20), tmport);
564			dev->id[c][target_id].dirct = 0x20;
565			tmport += 0x03;
566			outb(0x08, tmport);
567			outb(0x01, tmpcip);
568			dev->in_int[c] = 0;
569			goto handled;
570		}
571		tmport -= 0x07;
572		if (i == 0x0a) {
573			outb(0x30, tmport);
574		} else {
575			outb(0x46, tmport);
576		}
577		dev->id[c][target_id].dirct = 0x00;
578		tmport += 0x02;
579		outb(0x00, tmport++);
580		outb(0x00, tmport++);
581		outb(0x00, tmport++);
582		tmport += 0x03;
583		outb(0x08, tmport);
584		dev->in_int[c] = 0;
585		goto handled;
586	} else {
587//		tmport = workport + 0x17;
588//		inb(tmport);
589//		dev->working[c] = 0;
590		dev->in_int[c] = 0;
591		goto handled;
592	}
593
594handled:
595#ifdef ED_DBGP
596	printk("atp870u_intr_handle exit\n");
597#endif
598	return IRQ_HANDLED;
599}
600/**
601 *	atp870u_queuecommand	-	Queue SCSI command
602 *	@req_p: request block
603 *	@done: completion function
604 *
605 *	Queue a command to the ATP queue. Called with the host lock held.
606 */
607static int atp870u_queuecommand_lck(struct scsi_cmnd *req_p,
608			 void (*done) (struct scsi_cmnd *))
609{
610	unsigned char c;
611	unsigned int tmport,m;
612	struct atp_unit *dev;
613	struct Scsi_Host *host;
614
615	c = scmd_channel(req_p);
616	req_p->sense_buffer[0]=0;
617	scsi_set_resid(req_p, 0);
618	if (scmd_channel(req_p) > 1) {
619		req_p->result = 0x00040000;
620		done(req_p);
621#ifdef ED_DBGP
622		printk("atp870u_queuecommand : req_p->device->channel > 1\n");
623#endif
624		return 0;
625	}
626
627	host = req_p->device->host;
628	dev = (struct atp_unit *)&host->hostdata;
629
630
631
632	m = 1;
633	m = m << scmd_id(req_p);
634
635	/*
636	 *      Fake a timeout for missing targets
637	 */
638
639	if ((m & dev->active_id[c]) == 0) {
640		req_p->result = 0x00040000;
641		done(req_p);
642		return 0;
643	}
644
645	if (done) {
646		req_p->scsi_done = done;
647	} else {
648#ifdef ED_DBGP
649		printk( "atp870u_queuecommand: done can't be NULL\n");
650#endif
651		req_p->result = 0;
652		done(req_p);
653		return 0;
654	}
655
656	/*
657	 *	Count new command
658	 */
659	dev->quend[c]++;
660	if (dev->quend[c] >= qcnt) {
661		dev->quend[c] = 0;
662	}
663
664	/*
665	 *	Check queue state
666	 */
667	if (dev->quhd[c] == dev->quend[c]) {
668		if (dev->quend[c] == 0) {
669			dev->quend[c] = qcnt;
670		}
671#ifdef ED_DBGP
672		printk("atp870u_queuecommand : dev->quhd[c] == dev->quend[c]\n");
673#endif
674		dev->quend[c]--;
675		req_p->result = 0x00020000;
676		done(req_p);
677		return 0;
678	}
679	dev->quereq[c][dev->quend[c]] = req_p;
680	tmport = dev->ioport[c] + 0x1c;
681#ifdef ED_DBGP
682	printk("dev->ioport[c] = %x inb(tmport) = %x dev->in_int[%d] = %d dev->in_snd[%d] = %d\n",dev->ioport[c],inb(tmport),c,dev->in_int[c],c,dev->in_snd[c]);
683#endif
684	if ((inb(tmport) == 0) && (dev->in_int[c] == 0) && (dev->in_snd[c] == 0)) {
685#ifdef ED_DBGP
686		printk("Call sent_s870(atp870u_queuecommand)\n");
687#endif
688		send_s870(dev,c);
689	}
690#ifdef ED_DBGP
691	printk("atp870u_queuecommand : exit\n");
692#endif
693	return 0;
694}
695
696static DEF_SCSI_QCMD(atp870u_queuecommand)
697
698/**
699 *	send_s870	-	send a command to the controller
700 *	@host: host
701 *
702 *	On entry there is work queued to be done. We move some of that work to the
703 *	controller itself.
704 *
705 *	Caller holds the host lock.
706 */
707static void send_s870(struct atp_unit *dev,unsigned char c)
708{
709	unsigned int tmport;
710	struct scsi_cmnd *workreq;
711	unsigned int i;//,k;
712	unsigned char  j, target_id;
713	unsigned char *prd;
714	unsigned short int tmpcip, w;
715	unsigned long l, bttl = 0;
716	unsigned int workport;
717	unsigned long  sg_count;
718
719	if (dev->in_snd[c] != 0) {
720#ifdef ED_DBGP
721		printk("cmnd in_snd\n");
722#endif
723		return;
724	}
725#ifdef ED_DBGP
726	printk("Sent_s870 enter\n");
727#endif
728	dev->in_snd[c] = 1;
729	if ((dev->last_cmd[c] != 0xff) && ((dev->last_cmd[c] & 0x40) != 0)) {
730		dev->last_cmd[c] &= 0x0f;
731		workreq = dev->id[c][dev->last_cmd[c]].curr_req;
732		if (workreq != NULL) {	/* check NULL pointer */
733		   goto cmd_subp;
734		}
735		dev->last_cmd[c] = 0xff;
736		if (dev->quhd[c] == dev->quend[c]) {
737		   	dev->in_snd[c] = 0;
738		   	return ;
739		}
740	}
741	if ((dev->last_cmd[c] != 0xff) && (dev->working[c] != 0)) {
742	     	dev->in_snd[c] = 0;
743	     	return ;
744	}
745	dev->working[c]++;
746	j = dev->quhd[c];
747	dev->quhd[c]++;
748	if (dev->quhd[c] >= qcnt) {
749		dev->quhd[c] = 0;
750	}
751	workreq = dev->quereq[c][dev->quhd[c]];
752	if (dev->id[c][scmd_id(workreq)].curr_req == NULL) {
753		dev->id[c][scmd_id(workreq)].curr_req = workreq;
754		dev->last_cmd[c] = scmd_id(workreq);
755		goto cmd_subp;
756	}
757	dev->quhd[c] = j;
758	dev->working[c]--;
759	dev->in_snd[c] = 0;
760	return;
761cmd_subp:
762	workport = dev->ioport[c];
763	tmport = workport + 0x1f;
764	if ((inb(tmport) & 0xb0) != 0) {
765		goto abortsnd;
766	}
767	tmport = workport + 0x1c;
768	if (inb(tmport) == 0) {
769		goto oktosend;
770	}
771abortsnd:
772#ifdef ED_DBGP
773	printk("Abort to Send\n");
774#endif
775	dev->last_cmd[c] |= 0x40;
776	dev->in_snd[c] = 0;
777	return;
778oktosend:
779#ifdef ED_DBGP
780	printk("OK to Send\n");
781	scmd_printk(KERN_DEBUG, workreq, "CDB");
782	for(i=0;i<workreq->cmd_len;i++) {
783		printk(" %x",workreq->cmnd[i]);
784	}
785	printk("\n");
786#endif
787	l = scsi_bufflen(workreq);
788
789	if (dev->dev_id == ATP885_DEVID) {
790		j = inb(dev->baseport + 0x29) & 0xfe;
791		outb(j, dev->baseport + 0x29);
792		dev->r1f[c][scmd_id(workreq)] = 0;
793	}
794
795	if (workreq->cmnd[0] == READ_CAPACITY) {
796		if (l > 8)
797			l = 8;
798	}
799	if (workreq->cmnd[0] == 0x00) {
800		l = 0;
801	}
802
803	tmport = workport + 0x1b;
804	j = 0;
805	target_id = scmd_id(workreq);
806
807	/*
808	 *	Wide ?
809	 */
810	w = 1;
811	w = w << target_id;
812	if ((w & dev->wide_id[c]) != 0) {
813		j |= 0x01;
814	}
815	outb(j, tmport);
816	while ((inb(tmport) & 0x01) != j) {
817		outb(j,tmport);
818#ifdef ED_DBGP
819		printk("send_s870 while loop 1\n");
820#endif
821	}
822	/*
823	 *	Write the command
824	 */
825
826	tmport = workport;
827	outb(workreq->cmd_len, tmport++);
828	outb(0x2c, tmport++);
829	if (dev->dev_id == ATP885_DEVID) {
830		outb(0x7f, tmport++);
831	} else {
832		outb(0xcf, tmport++);
833	}
834	for (i = 0; i < workreq->cmd_len; i++) {
835		outb(workreq->cmnd[i], tmport++);
836	}
837	tmport = workport + 0x0f;
838	outb(workreq->device->lun, tmport);
839	tmport += 0x02;
840	/*
841	 *	Write the target
842	 */
843	outb(dev->id[c][target_id].devsp, tmport++);
844#ifdef ED_DBGP
845	printk("dev->id[%d][%d].devsp = %2x\n",c,target_id,dev->id[c][target_id].devsp);
846#endif
847
848	sg_count = scsi_dma_map(workreq);
849	/*
850	 *	Write transfer size
851	 */
852	outb((unsigned char) (((unsigned char *) (&l))[2]), tmport++);
853	outb((unsigned char) (((unsigned char *) (&l))[1]), tmport++);
854	outb((unsigned char) (((unsigned char *) (&l))[0]), tmport++);
855	j = target_id;
856	dev->id[c][j].last_len = l;
857	dev->id[c][j].tran_len = 0;
858#ifdef ED_DBGP
859	printk("dev->id[%2d][%2d].last_len = %d\n",c,j,dev->id[c][j].last_len);
860#endif
861	/*
862	 *	Flip the wide bits
863	 */
864	if ((j & 0x08) != 0) {
865		j = (j & 0x07) | 0x40;
866	}
867	/*
868	 *	Check transfer direction
869	 */
870	if (workreq->sc_data_direction == DMA_TO_DEVICE) {
871		outb((unsigned char) (j | 0x20), tmport++);
872	} else {
873		outb(j, tmport++);
874	}
875	outb((unsigned char) (inb(tmport) | 0x80), tmport);
876	outb(0x80, tmport);
877	tmport = workport + 0x1c;
878	dev->id[c][target_id].dirct = 0;
879	if (l == 0) {
880		if (inb(tmport) == 0) {
881			tmport = workport + 0x18;
882#ifdef ED_DBGP
883			printk("change SCSI_CMD_REG 0x08\n");
884#endif
885			outb(0x08, tmport);
886		} else {
887			dev->last_cmd[c] |= 0x40;
888		}
889		dev->in_snd[c] = 0;
890		return;
891	}
892	tmpcip = dev->pciport[c];
893	prd = dev->id[c][target_id].prd_table;
894	dev->id[c][target_id].prd_pos = prd;
895
896	/*
897	 *	Now write the request list. Either as scatter/gather or as
898	 *	a linear chain.
899	 */
900
901	if (l) {
902		struct scatterlist *sgpnt;
903		i = 0;
904		scsi_for_each_sg(workreq, sgpnt, sg_count, j) {
905			bttl = sg_dma_address(sgpnt);
906			l=sg_dma_len(sgpnt);
907#ifdef ED_DBGP
908			printk("1. bttl %x, l %x\n",bttl, l);
909#endif
910			while (l > 0x10000) {
911				(((u16 *) (prd))[i + 3]) = 0x0000;
912				(((u16 *) (prd))[i + 2]) = 0x0000;
913				(((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
914				l -= 0x10000;
915				bttl += 0x10000;
916				i += 0x04;
917			}
918			(((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
919			(((u16 *) (prd))[i + 2]) = cpu_to_le16(l);
920			(((u16 *) (prd))[i + 3]) = 0;
921			i += 0x04;
922		}
923		(((u16 *) (prd))[i - 1]) = cpu_to_le16(0x8000);
924#ifdef ED_DBGP
925		printk("prd %4x %4x %4x %4x\n",(((unsigned short int *)prd)[0]),(((unsigned short int *)prd)[1]),(((unsigned short int *)prd)[2]),(((unsigned short int *)prd)[3]));
926		printk("2. bttl %x, l %x\n",bttl, l);
927#endif
928	}
929	tmpcip += 4;
930#ifdef ED_DBGP
931	printk("send_s870: prdaddr_2 0x%8x tmpcip %x target_id %d\n", dev->id[c][target_id].prdaddr,tmpcip,target_id);
932#endif
933	dev->id[c][target_id].prdaddr = dev->id[c][target_id].prd_bus;
934	outl(dev->id[c][target_id].prdaddr, tmpcip);
935	tmpcip = tmpcip - 2;
936	outb(0x06, tmpcip);
937	outb(0x00, tmpcip);
938	if (dev->dev_id == ATP885_DEVID) {
939		tmpcip--;
940		j=inb(tmpcip) & 0xf3;
941		if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) ||
942	    	(workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
943	   		j |= 0x0c;
944		}
945		outb(j,tmpcip);
946		tmpcip--;
947	} else if ((dev->dev_id == ATP880_DEVID1) ||
948	    	   (dev->dev_id == ATP880_DEVID2)) {
949		tmpcip =tmpcip -2;
950		tmport = workport - 0x05;
951		if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
952			outb((unsigned char) ((inb(tmport) & 0x3f) | 0xc0), tmport);
953		} else {
954			outb((unsigned char) (inb(tmport) & 0x3f), tmport);
955		}
956	} else {
957		tmpcip =tmpcip -2;
958		tmport = workport + 0x3a;
959		if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
960			outb((inb(tmport) & 0xf3) | 0x08, tmport);
961		} else {
962			outb(inb(tmport) & 0xf3, tmport);
963		}
964	}
965	tmport = workport + 0x1c;
966
967	if(workreq->sc_data_direction == DMA_TO_DEVICE) {
968		dev->id[c][target_id].dirct = 0x20;
969		if (inb(tmport) == 0) {
970			tmport = workport + 0x18;
971			outb(0x08, tmport);
972			outb(0x01, tmpcip);
973#ifdef ED_DBGP
974		printk( "start DMA(to target)\n");
975#endif
976		} else {
977			dev->last_cmd[c] |= 0x40;
978		}
979		dev->in_snd[c] = 0;
980		return;
981	}
982	if (inb(tmport) == 0) {
983		tmport = workport + 0x18;
984		outb(0x08, tmport);
985		outb(0x09, tmpcip);
986#ifdef ED_DBGP
987		printk( "start DMA(to host)\n");
988#endif
989	} else {
990		dev->last_cmd[c] |= 0x40;
991	}
992	dev->in_snd[c] = 0;
993	return;
994
995}
996
997static unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val)
998{
999	unsigned int tmport;
1000	unsigned short int i, k;
1001	unsigned char j;
1002
1003	tmport = dev->ioport[0] + 0x1c;
1004	outw(*val, tmport);
1005FUN_D7:
1006	for (i = 0; i < 10; i++) {	/* stable >= bus settle delay(400 ns)  */
1007		k = inw(tmport);
1008		j = (unsigned char) (k >> 8);
1009		if ((k & 0x8000) != 0) {	/* DB7 all release?    */
1010			goto FUN_D7;
1011		}
1012	}
1013	*val |= 0x4000;		/* assert DB6           */
1014	outw(*val, tmport);
1015	*val &= 0xdfff;		/* assert DB5           */
1016	outw(*val, tmport);
1017FUN_D5:
1018	for (i = 0; i < 10; i++) {	/* stable >= bus settle delay(400 ns) */
1019		if ((inw(tmport) & 0x2000) != 0) {	/* DB5 all release?       */
1020			goto FUN_D5;
1021		}
1022	}
1023	*val |= 0x8000;		/* no DB4-0, assert DB7    */
1024	*val &= 0xe0ff;
1025	outw(*val, tmport);
1026	*val &= 0xbfff;		/* release DB6             */
1027	outw(*val, tmport);
1028FUN_D6:
1029	for (i = 0; i < 10; i++) {	/* stable >= bus settle delay(400 ns)  */
1030		if ((inw(tmport) & 0x4000) != 0) {	/* DB6 all release?  */
1031			goto FUN_D6;
1032		}
1033	}
1034
1035	return j;
1036}
1037
1038static void tscam(struct Scsi_Host *host)
1039{
1040
1041	unsigned int tmport;
1042	unsigned char i, j, k;
1043	unsigned long n;
1044	unsigned short int m, assignid_map, val;
1045	unsigned char mbuf[33], quintet[2];
1046	struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
1047	static unsigned char g2q_tab[8] = {
1048		0x38, 0x31, 0x32, 0x2b, 0x34, 0x2d, 0x2e, 0x27
1049	};
1050
1051/*  I can't believe we need this before we've even done anything.  Remove it
1052 *  and see if anyone bitches.
1053	for (i = 0; i < 0x10; i++) {
1054		udelay(0xffff);
1055	}
1056 */
1057
1058	tmport = dev->ioport[0] + 1;
1059	outb(0x08, tmport++);
1060	outb(0x7f, tmport);
1061	tmport = dev->ioport[0] + 0x11;
1062	outb(0x20, tmport);
1063
1064	if ((dev->scam_on & 0x40) == 0) {
1065		return;
1066	}
1067	m = 1;
1068	m <<= dev->host_id[0];
1069	j = 16;
1070	if (dev->chip_ver < 4) {
1071		m |= 0xff00;
1072		j = 8;
1073	}
1074	assignid_map = m;
1075	tmport = dev->ioport[0] + 0x02;
1076	outb(0x02, tmport++);	/* 2*2=4ms,3EH 2/32*3E=3.9ms */
1077	outb(0, tmport++);
1078	outb(0, tmport++);
1079	outb(0, tmport++);
1080	outb(0, tmport++);
1081	outb(0, tmport++);
1082	outb(0, tmport++);
1083
1084	for (i = 0; i < j; i++) {
1085		m = 1;
1086		m = m << i;
1087		if ((m & assignid_map) != 0) {
1088			continue;
1089		}
1090		tmport = dev->ioport[0] + 0x0f;
1091		outb(0, tmport++);
1092		tmport += 0x02;
1093		outb(0, tmport++);
1094		outb(0, tmport++);
1095		outb(0, tmport++);
1096		if (i > 7) {
1097			k = (i & 0x07) | 0x40;
1098		} else {
1099			k = i;
1100		}
1101		outb(k, tmport++);
1102		tmport = dev->ioport[0] + 0x1b;
1103		if (dev->chip_ver == 4) {
1104			outb(0x01, tmport);
1105		} else {
1106			outb(0x00, tmport);
1107		}
1108wait_rdyok:
1109		tmport = dev->ioport[0] + 0x18;
1110		outb(0x09, tmport);
1111		tmport += 0x07;
1112
1113		while ((inb(tmport) & 0x80) == 0x00)
1114			cpu_relax();
1115		tmport -= 0x08;
1116		k = inb(tmport);
1117		if (k != 0x16) {
1118			if ((k == 0x85) || (k == 0x42)) {
1119				continue;
1120			}
1121			tmport = dev->ioport[0] + 0x10;
1122			outb(0x41, tmport);
1123			goto wait_rdyok;
1124		}
1125		assignid_map |= m;
1126
1127	}
1128	tmport = dev->ioport[0] + 0x02;
1129	outb(0x7f, tmport);
1130	tmport = dev->ioport[0] + 0x1b;
1131	outb(0x02, tmport);
1132
1133	outb(0, 0x80);
1134
1135	val = 0x0080;		/* bsy  */
1136	tmport = dev->ioport[0] + 0x1c;
1137	outw(val, tmport);
1138	val |= 0x0040;		/* sel  */
1139	outw(val, tmport);
1140	val |= 0x0004;		/* msg  */
1141	outw(val, tmport);
1142	inb(0x80);		/* 2 deskew delay(45ns*2=90ns) */
1143	val &= 0x007f;		/* no bsy  */
1144	outw(val, tmport);
1145	mdelay(128);
1146	val &= 0x00fb;		/* after 1ms no msg */
1147	outw(val, tmport);
1148wait_nomsg:
1149	if ((inb(tmport) & 0x04) != 0) {
1150		goto wait_nomsg;
1151	}
1152	outb(1, 0x80);
1153	udelay(100);
1154	for (n = 0; n < 0x30000; n++) {
1155		if ((inb(tmport) & 0x80) != 0) {	/* bsy ? */
1156			goto wait_io;
1157		}
1158	}
1159	goto TCM_SYNC;
1160wait_io:
1161	for (n = 0; n < 0x30000; n++) {
1162		if ((inb(tmport) & 0x81) == 0x0081) {
1163			goto wait_io1;
1164		}
1165	}
1166	goto TCM_SYNC;
1167wait_io1:
1168	inb(0x80);
1169	val |= 0x8003;		/* io,cd,db7  */
1170	outw(val, tmport);
1171	inb(0x80);
1172	val &= 0x00bf;		/* no sel     */
1173	outw(val, tmport);
1174	outb(2, 0x80);
1175TCM_SYNC:
1176	udelay(0x800);
1177	if ((inb(tmport) & 0x80) == 0x00) {	/* bsy ? */
1178		outw(0, tmport--);
1179		outb(0, tmport);
1180		tmport = dev->ioport[0] + 0x15;
1181		outb(0, tmport);
1182		tmport += 0x03;
1183		outb(0x09, tmport);
1184		tmport += 0x07;
1185		while ((inb(tmport) & 0x80) == 0)
1186			cpu_relax();
1187		tmport -= 0x08;
1188		inb(tmport);
1189		return;
1190	}
1191	val &= 0x00ff;		/* synchronization  */
1192	val |= 0x3f00;
1193	fun_scam(dev, &val);
1194	outb(3, 0x80);
1195	val &= 0x00ff;		/* isolation        */
1196	val |= 0x2000;
1197	fun_scam(dev, &val);
1198	outb(4, 0x80);
1199	i = 8;
1200	j = 0;
1201TCM_ID:
1202	if ((inw(tmport) & 0x2000) == 0) {
1203		goto TCM_ID;
1204	}
1205	outb(5, 0x80);
1206	val &= 0x00ff;		/* get ID_STRING */
1207	val |= 0x2000;
1208	k = fun_scam(dev, &val);
1209	if ((k & 0x03) == 0) {
1210		goto TCM_5;
1211	}
1212	mbuf[j] <<= 0x01;
1213	mbuf[j] &= 0xfe;
1214	if ((k & 0x02) != 0) {
1215		mbuf[j] |= 0x01;
1216	}
1217	i--;
1218	if (i > 0) {
1219		goto TCM_ID;
1220	}
1221	j++;
1222	i = 8;
1223	goto TCM_ID;
1224
1225TCM_5:			/* isolation complete..  */
1226/*    mbuf[32]=0;
1227	printk(" \n%x %x %x %s\n ",assignid_map,mbuf[0],mbuf[1],&mbuf[2]); */
1228	i = 15;
1229	j = mbuf[0];
1230	if ((j & 0x20) != 0) {	/* bit5=1:ID up to 7      */
1231		i = 7;
1232	}
1233	if ((j & 0x06) == 0) {	/* IDvalid?             */
1234		goto G2Q5;
1235	}
1236	k = mbuf[1];
1237small_id:
1238	m = 1;
1239	m <<= k;
1240	if ((m & assignid_map) == 0) {
1241		goto G2Q_QUIN;
1242	}
1243	if (k > 0) {
1244		k--;
1245		goto small_id;
1246	}
1247G2Q5:			/* srch from max acceptable ID#  */
1248	k = i;			/* max acceptable ID#            */
1249G2Q_LP:
1250	m = 1;
1251	m <<= k;
1252	if ((m & assignid_map) == 0) {
1253		goto G2Q_QUIN;
1254	}
1255	if (k > 0) {
1256		k--;
1257		goto G2Q_LP;
1258	}
1259G2Q_QUIN:		/* k=binID#,       */
1260	assignid_map |= m;
1261	if (k < 8) {
1262		quintet[0] = 0x38;	/* 1st dft ID<8    */
1263	} else {
1264		quintet[0] = 0x31;	/* 1st  ID>=8      */
1265	}
1266	k &= 0x07;
1267	quintet[1] = g2q_tab[k];
1268
1269	val &= 0x00ff;		/* AssignID 1stQuintet,AH=001xxxxx  */
1270	m = quintet[0] << 8;
1271	val |= m;
1272	fun_scam(dev, &val);
1273	val &= 0x00ff;		/* AssignID 2ndQuintet,AH=001xxxxx */
1274	m = quintet[1] << 8;
1275	val |= m;
1276	fun_scam(dev, &val);
1277
1278	goto TCM_SYNC;
1279
1280}
1281
1282static void is870(struct atp_unit *dev, unsigned int wkport)
1283{
1284	unsigned int tmport;
1285	unsigned char i, j, k, rmb, n;
1286	unsigned short int m;
1287	static unsigned char mbuf[512];
1288	static unsigned char satn[9] = { 0, 0, 0, 0, 0, 0, 0, 6, 6 };
1289	static unsigned char inqd[9] = { 0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6 };
1290	static unsigned char synn[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
1291	static unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0c, 0x0e };
1292	static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x0c, 0x07 };
1293	static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
1294
1295	tmport = wkport + 0x3a;
1296	outb((unsigned char) (inb(tmport) | 0x10), tmport);
1297
1298	for (i = 0; i < 16; i++) {
1299		if ((dev->chip_ver != 4) && (i > 7)) {
1300			break;
1301		}
1302		m = 1;
1303		m = m << i;
1304		if ((m & dev->active_id[0]) != 0) {
1305			continue;
1306		}
1307		if (i == dev->host_id[0]) {
1308			printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_id[0]);
1309			continue;
1310		}
1311		tmport = wkport + 0x1b;
1312		if (dev->chip_ver == 4) {
1313			outb(0x01, tmport);
1314		} else {
1315			outb(0x00, tmport);
1316		}
1317		tmport = wkport + 1;
1318		outb(0x08, tmport++);
1319		outb(0x7f, tmport++);
1320		outb(satn[0], tmport++);
1321		outb(satn[1], tmport++);
1322		outb(satn[2], tmport++);
1323		outb(satn[3], tmport++);
1324		outb(satn[4], tmport++);
1325		outb(satn[5], tmport++);
1326		tmport += 0x06;
1327		outb(0, tmport);
1328		tmport += 0x02;
1329		outb(dev->id[0][i].devsp, tmport++);
1330		outb(0, tmport++);
1331		outb(satn[6], tmport++);
1332		outb(satn[7], tmport++);
1333		j = i;
1334		if ((j & 0x08) != 0) {
1335			j = (j & 0x07) | 0x40;
1336		}
1337		outb(j, tmport);
1338		tmport += 0x03;
1339		outb(satn[8], tmport);
1340		tmport += 0x07;
1341
1342		while ((inb(tmport) & 0x80) == 0x00)
1343			cpu_relax();
1344
1345		tmport -= 0x08;
1346		if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
1347			continue;
1348
1349		while (inb(tmport) != 0x8e)
1350			cpu_relax();
1351
1352		dev->active_id[0] |= m;
1353
1354		tmport = wkport + 0x10;
1355		outb(0x30, tmport);
1356		tmport = wkport + 0x04;
1357		outb(0x00, tmport);
1358
1359phase_cmd:
1360		tmport = wkport + 0x18;
1361		outb(0x08, tmport);
1362		tmport += 0x07;
1363		while ((inb(tmport) & 0x80) == 0x00)
1364			cpu_relax();
1365		tmport -= 0x08;
1366		j = inb(tmport);
1367		if (j != 0x16) {
1368			tmport = wkport + 0x10;
1369			outb(0x41, tmport);
1370			goto phase_cmd;
1371		}
1372sel_ok:
1373		tmport = wkport + 3;
1374		outb(inqd[0], tmport++);
1375		outb(inqd[1], tmport++);
1376		outb(inqd[2], tmport++);
1377		outb(inqd[3], tmport++);
1378		outb(inqd[4], tmport++);
1379		outb(inqd[5], tmport);
1380		tmport += 0x07;
1381		outb(0, tmport);
1382		tmport += 0x02;
1383		outb(dev->id[0][i].devsp, tmport++);
1384		outb(0, tmport++);
1385		outb(inqd[6], tmport++);
1386		outb(inqd[7], tmport++);
1387		tmport += 0x03;
1388		outb(inqd[8], tmport);
1389		tmport += 0x07;
1390
1391		while ((inb(tmport) & 0x80) == 0x00)
1392			cpu_relax();
1393
1394		tmport -= 0x08;
1395		if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
1396			continue;
1397
1398		while (inb(tmport) != 0x8e)
1399			cpu_relax();
1400
1401		tmport = wkport + 0x1b;
1402		if (dev->chip_ver == 4)
1403			outb(0x00, tmport);
1404
1405		tmport = wkport + 0x18;
1406		outb(0x08, tmport);
1407		tmport += 0x07;
1408		j = 0;
1409rd_inq_data:
1410		k = inb(tmport);
1411		if ((k & 0x01) != 0) {
1412			tmport -= 0x06;
1413			mbuf[j++] = inb(tmport);
1414			tmport += 0x06;
1415			goto rd_inq_data;
1416		}
1417		if ((k & 0x80) == 0) {
1418			goto rd_inq_data;
1419		}
1420		tmport -= 0x08;
1421		j = inb(tmport);
1422		if (j == 0x16) {
1423			goto inq_ok;
1424		}
1425		tmport = wkport + 0x10;
1426		outb(0x46, tmport);
1427		tmport += 0x02;
1428		outb(0, tmport++);
1429		outb(0, tmport++);
1430		outb(0, tmport++);
1431		tmport += 0x03;
1432		outb(0x08, tmport);
1433		tmport += 0x07;
1434
1435		while ((inb(tmport) & 0x80) == 0x00)
1436			cpu_relax();
1437
1438		tmport -= 0x08;
1439		if (inb(tmport) != 0x16) {
1440			goto sel_ok;
1441		}
1442inq_ok:
1443		mbuf[36] = 0;
1444		printk(KERN_INFO "         ID: %2d  %s\n", i, &mbuf[8]);
1445		dev->id[0][i].devtype = mbuf[0];
1446		rmb = mbuf[1];
1447		n = mbuf[7];
1448		if (dev->chip_ver != 4) {
1449			goto not_wide;
1450		}
1451		if ((mbuf[7] & 0x60) == 0) {
1452			goto not_wide;
1453		}
1454		if ((dev->global_map[0] & 0x20) == 0) {
1455			goto not_wide;
1456		}
1457		tmport = wkport + 0x1b;
1458		outb(0x01, tmport);
1459		tmport = wkport + 3;
1460		outb(satn[0], tmport++);
1461		outb(satn[1], tmport++);
1462		outb(satn[2], tmport++);
1463		outb(satn[3], tmport++);
1464		outb(satn[4], tmport++);
1465		outb(satn[5], tmport++);
1466		tmport += 0x06;
1467		outb(0, tmport);
1468		tmport += 0x02;
1469		outb(dev->id[0][i].devsp, tmport++);
1470		outb(0, tmport++);
1471		outb(satn[6], tmport++);
1472		outb(satn[7], tmport++);
1473		tmport += 0x03;
1474		outb(satn[8], tmport);
1475		tmport += 0x07;
1476
1477		while ((inb(tmport) & 0x80) == 0x00)
1478			cpu_relax();
1479
1480		tmport -= 0x08;
1481		if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
1482			continue;
1483
1484		while (inb(tmport) != 0x8e)
1485			cpu_relax();
1486
1487try_wide:
1488		j = 0;
1489		tmport = wkport + 0x14;
1490		outb(0x05, tmport);
1491		tmport += 0x04;
1492		outb(0x20, tmport);
1493		tmport += 0x07;
1494
1495		while ((inb(tmport) & 0x80) == 0) {
1496			if ((inb(tmport) & 0x01) != 0) {
1497				tmport -= 0x06;
1498				outb(wide[j++], tmport);
1499				tmport += 0x06;
1500			}
1501		}
1502		tmport -= 0x08;
1503
1504		while ((inb(tmport) & 0x80) == 0x00)
1505			cpu_relax();
1506
1507		j = inb(tmport) & 0x0f;
1508		if (j == 0x0f) {
1509			goto widep_in;
1510		}
1511		if (j == 0x0a) {
1512			goto widep_cmd;
1513		}
1514		if (j == 0x0e) {
1515			goto try_wide;
1516		}
1517		continue;
1518widep_out:
1519		tmport = wkport + 0x18;
1520		outb(0x20, tmport);
1521		tmport += 0x07;
1522		while ((inb(tmport) & 0x80) == 0) {
1523			if ((inb(tmport) & 0x01) != 0) {
1524				tmport -= 0x06;
1525				outb(0, tmport);
1526				tmport += 0x06;
1527			}
1528		}
1529		tmport -= 0x08;
1530		j = inb(tmport) & 0x0f;
1531		if (j == 0x0f) {
1532			goto widep_in;
1533		}
1534		if (j == 0x0a) {
1535			goto widep_cmd;
1536		}
1537		if (j == 0x0e) {
1538			goto widep_out;
1539		}
1540		continue;
1541widep_in:
1542		tmport = wkport + 0x14;
1543		outb(0xff, tmport);
1544		tmport += 0x04;
1545		outb(0x20, tmport);
1546		tmport += 0x07;
1547		k = 0;
1548widep_in1:
1549		j = inb(tmport);
1550		if ((j & 0x01) != 0) {
1551			tmport -= 0x06;
1552			mbuf[k++] = inb(tmport);
1553			tmport += 0x06;
1554			goto widep_in1;
1555		}
1556		if ((j & 0x80) == 0x00) {
1557			goto widep_in1;
1558		}
1559		tmport -= 0x08;
1560		j = inb(tmport) & 0x0f;
1561		if (j == 0x0f) {
1562			goto widep_in;
1563		}
1564		if (j == 0x0a) {
1565			goto widep_cmd;
1566		}
1567		if (j == 0x0e) {
1568			goto widep_out;
1569		}
1570		continue;
1571widep_cmd:
1572		tmport = wkport + 0x10;
1573		outb(0x30, tmport);
1574		tmport = wkport + 0x14;
1575		outb(0x00, tmport);
1576		tmport += 0x04;
1577		outb(0x08, tmport);
1578		tmport += 0x07;
1579
1580		while ((inb(tmport) & 0x80) == 0x00)
1581			cpu_relax();
1582
1583		tmport -= 0x08;
1584		j = inb(tmport);
1585		if (j != 0x16) {
1586			if (j == 0x4e) {
1587				goto widep_out;
1588			}
1589			continue;
1590		}
1591		if (mbuf[0] != 0x01) {
1592			goto not_wide;
1593		}
1594		if (mbuf[1] != 0x02) {
1595			goto not_wide;
1596		}
1597		if (mbuf[2] != 0x03) {
1598			goto not_wide;
1599		}
1600		if (mbuf[3] != 0x01) {
1601			goto not_wide;
1602		}
1603		m = 1;
1604		m = m << i;
1605		dev->wide_id[0] |= m;
1606not_wide:
1607		if ((dev->id[0][i].devtype == 0x00) || (dev->id[0][i].devtype == 0x07) || ((dev->id[0][i].devtype == 0x05) && ((n & 0x10) != 0))) {
1608			goto set_sync;
1609		}
1610		continue;
1611set_sync:
1612		tmport = wkport + 0x1b;
1613		j = 0;
1614		if ((m & dev->wide_id[0]) != 0) {
1615			j |= 0x01;
1616		}
1617		outb(j, tmport);
1618		tmport = wkport + 3;
1619		outb(satn[0], tmport++);
1620		outb(satn[1], tmport++);
1621		outb(satn[2], tmport++);
1622		outb(satn[3], tmport++);
1623		outb(satn[4], tmport++);
1624		outb(satn[5], tmport++);
1625		tmport += 0x06;
1626		outb(0, tmport);
1627		tmport += 0x02;
1628		outb(dev->id[0][i].devsp, tmport++);
1629		outb(0, tmport++);
1630		outb(satn[6], tmport++);
1631		outb(satn[7], tmport++);
1632		tmport += 0x03;
1633		outb(satn[8], tmport);
1634		tmport += 0x07;
1635
1636		while ((inb(tmport) & 0x80) == 0x00)
1637			cpu_relax();
1638
1639		tmport -= 0x08;
1640		if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
1641			continue;
1642
1643		while (inb(tmport) != 0x8e)
1644			cpu_relax();
1645
1646try_sync:
1647		j = 0;
1648		tmport = wkport + 0x14;
1649		outb(0x06, tmport);
1650		tmport += 0x04;
1651		outb(0x20, tmport);
1652		tmport += 0x07;
1653
1654		while ((inb(tmport) & 0x80) == 0) {
1655			if ((inb(tmport) & 0x01) != 0) {
1656				tmport -= 0x06;
1657				if ((m & dev->wide_id[0]) != 0) {
1658					outb(synw[j++], tmport);
1659				} else {
1660					if ((m & dev->ultra_map[0]) != 0) {
1661						outb(synu[j++], tmport);
1662					} else {
1663						outb(synn[j++], tmport);
1664					}
1665				}
1666				tmport += 0x06;
1667			}
1668		}
1669		tmport -= 0x08;
1670
1671		while ((inb(tmport) & 0x80) == 0x00)
1672			cpu_relax();
1673
1674		j = inb(tmport) & 0x0f;
1675		if (j == 0x0f) {
1676			goto phase_ins;
1677		}
1678		if (j == 0x0a) {
1679			goto phase_cmds;
1680		}
1681		if (j == 0x0e) {
1682			goto try_sync;
1683		}
1684		continue;
1685phase_outs:
1686		tmport = wkport + 0x18;
1687		outb(0x20, tmport);
1688		tmport += 0x07;
1689		while ((inb(tmport) & 0x80) == 0x00) {
1690			if ((inb(tmport) & 0x01) != 0x00) {
1691				tmport -= 0x06;
1692				outb(0x00, tmport);
1693				tmport += 0x06;
1694			}
1695		}
1696		tmport -= 0x08;
1697		j = inb(tmport);
1698		if (j == 0x85) {
1699			goto tar_dcons;
1700		}
1701		j &= 0x0f;
1702		if (j == 0x0f) {
1703			goto phase_ins;
1704		}
1705		if (j == 0x0a) {
1706			goto phase_cmds;
1707		}
1708		if (j == 0x0e) {
1709			goto phase_outs;
1710		}
1711		continue;
1712phase_ins:
1713		tmport = wkport + 0x14;
1714		outb(0xff, tmport);
1715		tmport += 0x04;
1716		outb(0x20, tmport);
1717		tmport += 0x07;
1718		k = 0;
1719phase_ins1:
1720		j = inb(tmport);
1721		if ((j & 0x01) != 0x00) {
1722			tmport -= 0x06;
1723			mbuf[k++] = inb(tmport);
1724			tmport += 0x06;
1725			goto phase_ins1;
1726		}
1727		if ((j & 0x80) == 0x00) {
1728			goto phase_ins1;
1729		}
1730		tmport -= 0x08;
1731
1732		while ((inb(tmport) & 0x80) == 0x00)
1733			cpu_relax();
1734
1735		j = inb(tmport);
1736		if (j == 0x85) {
1737			goto tar_dcons;
1738		}
1739		j &= 0x0f;
1740		if (j == 0x0f) {
1741			goto phase_ins;
1742		}
1743		if (j == 0x0a) {
1744			goto phase_cmds;
1745		}
1746		if (j == 0x0e) {
1747			goto phase_outs;
1748		}
1749		continue;
1750phase_cmds:
1751		tmport = wkport + 0x10;
1752		outb(0x30, tmport);
1753tar_dcons:
1754		tmport = wkport + 0x14;
1755		outb(0x00, tmport);
1756		tmport += 0x04;
1757		outb(0x08, tmport);
1758		tmport += 0x07;
1759
1760		while ((inb(tmport) & 0x80) == 0x00)
1761			cpu_relax();
1762
1763		tmport -= 0x08;
1764		j = inb(tmport);
1765		if (j != 0x16) {
1766			continue;
1767		}
1768		if (mbuf[0] != 0x01) {
1769			continue;
1770		}
1771		if (mbuf[1] != 0x03) {
1772			continue;
1773		}
1774		if (mbuf[4] == 0x00) {
1775			continue;
1776		}
1777		if (mbuf[3] > 0x64) {
1778			continue;
1779		}
1780		if (mbuf[4] > 0x0c) {
1781			mbuf[4] = 0x0c;
1782		}
1783		dev->id[0][i].devsp = mbuf[4];
1784		if ((mbuf[3] < 0x0d) && (rmb == 0)) {
1785			j = 0xa0;
1786			goto set_syn_ok;
1787		}
1788		if (mbuf[3] < 0x1a) {
1789			j = 0x20;
1790			goto set_syn_ok;
1791		}
1792		if (mbuf[3] < 0x33) {
1793			j = 0x40;
1794			goto set_syn_ok;
1795		}
1796		if (mbuf[3] < 0x4c) {
1797			j = 0x50;
1798			goto set_syn_ok;
1799		}
1800		j = 0x60;
1801set_syn_ok:
1802		dev->id[0][i].devsp = (dev->id[0][i].devsp & 0x0f) | j;
1803	}
1804	tmport = wkport + 0x3a;
1805	outb((unsigned char) (inb(tmport) & 0xef), tmport);
1806}
1807
1808static void is880(struct atp_unit *dev, unsigned int wkport)
1809{
1810	unsigned int tmport;
1811	unsigned char i, j, k, rmb, n, lvdmode;
1812	unsigned short int m;
1813	static unsigned char mbuf[512];
1814	static unsigned char satn[9] = { 0, 0, 0, 0, 0, 0, 0, 6, 6 };
1815	static unsigned char inqd[9] = { 0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6 };
1816	static unsigned char synn[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
1817	unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
1818	static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
1819	unsigned char synuw[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
1820	static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
1821	static unsigned char u3[9] = { 0x80, 1, 6, 4, 0x09, 00, 0x0e, 0x01, 0x02 };
1822
1823	lvdmode = inb(wkport + 0x3f) & 0x40;
1824
1825	for (i = 0; i < 16; i++) {
1826		m = 1;
1827		m = m << i;
1828		if ((m & dev->active_id[0]) != 0) {
1829			continue;
1830		}
1831		if (i == dev->host_id[0]) {
1832			printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_id[0]);
1833			continue;
1834		}
1835		tmport = wkport + 0x5b;
1836		outb(0x01, tmport);
1837		tmport = wkport + 0x41;
1838		outb(0x08, tmport++);
1839		outb(0x7f, tmport++);
1840		outb(satn[0], tmport++);
1841		outb(satn[1], tmport++);
1842		outb(satn[2], tmport++);
1843		outb(satn[3], tmport++);
1844		outb(satn[4], tmport++);
1845		outb(satn[5], tmport++);
1846		tmport += 0x06;
1847		outb(0, tmport);
1848		tmport += 0x02;
1849		outb(dev->id[0][i].devsp, tmport++);
1850		outb(0, tmport++);
1851		outb(satn[6], tmport++);
1852		outb(satn[7], tmport++);
1853		j = i;
1854		if ((j & 0x08) != 0) {
1855			j = (j & 0x07) | 0x40;
1856		}
1857		outb(j, tmport);
1858		tmport += 0x03;
1859		outb(satn[8], tmport);
1860		tmport += 0x07;
1861
1862		while ((inb(tmport) & 0x80) == 0x00)
1863			cpu_relax();
1864
1865		tmport -= 0x08;
1866		if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
1867			continue;
1868
1869		while (inb(tmport) != 0x8e)
1870			cpu_relax();
1871
1872		dev->active_id[0] |= m;
1873
1874		tmport = wkport + 0x50;
1875		outb(0x30, tmport);
1876		tmport = wkport + 0x54;
1877		outb(0x00, tmport);
1878
1879phase_cmd:
1880		tmport = wkport + 0x58;
1881		outb(0x08, tmport);
1882		tmport += 0x07;
1883
1884		while ((inb(tmport) & 0x80) == 0x00)
1885			cpu_relax();
1886
1887		tmport -= 0x08;
1888		j = inb(tmport);
1889		if (j != 0x16) {
1890			tmport = wkport + 0x50;
1891			outb(0x41, tmport);
1892			goto phase_cmd;
1893		}
1894sel_ok:
1895		tmport = wkport + 0x43;
1896		outb(inqd[0], tmport++);
1897		outb(inqd[1], tmport++);
1898		outb(inqd[2], tmport++);
1899		outb(inqd[3], tmport++);
1900		outb(inqd[4], tmport++);
1901		outb(inqd[5], tmport);
1902		tmport += 0x07;
1903		outb(0, tmport);
1904		tmport += 0x02;
1905		outb(dev->id[0][i].devsp, tmport++);
1906		outb(0, tmport++);
1907		outb(inqd[6], tmport++);
1908		outb(inqd[7], tmport++);
1909		tmport += 0x03;
1910		outb(inqd[8], tmport);
1911		tmport += 0x07;
1912
1913		while ((inb(tmport) & 0x80) == 0x00)
1914			cpu_relax();
1915
1916		tmport -= 0x08;
1917		if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
1918			continue;
1919
1920		while (inb(tmport) != 0x8e)
1921			cpu_relax();
1922
1923		tmport = wkport + 0x5b;
1924		outb(0x00, tmport);
1925		tmport = wkport + 0x58;
1926		outb(0x08, tmport);
1927		tmport += 0x07;
1928		j = 0;
1929rd_inq_data:
1930		k = inb(tmport);
1931		if ((k & 0x01) != 0) {
1932			tmport -= 0x06;
1933			mbuf[j++] = inb(tmport);
1934			tmport += 0x06;
1935			goto rd_inq_data;
1936		}
1937		if ((k & 0x80) == 0) {
1938			goto rd_inq_data;
1939		}
1940		tmport -= 0x08;
1941		j = inb(tmport);
1942		if (j == 0x16) {
1943			goto inq_ok;
1944		}
1945		tmport = wkport + 0x50;
1946		outb(0x46, tmport);
1947		tmport += 0x02;
1948		outb(0, tmport++);
1949		outb(0, tmport++);
1950		outb(0, tmport++);
1951		tmport += 0x03;
1952		outb(0x08, tmport);
1953		tmport += 0x07;
1954		while ((inb(tmport) & 0x80) == 0x00)
1955			cpu_relax();
1956
1957		tmport -= 0x08;
1958		if (inb(tmport) != 0x16)
1959			goto sel_ok;
1960
1961inq_ok:
1962		mbuf[36] = 0;
1963		printk(KERN_INFO "         ID: %2d  %s\n", i, &mbuf[8]);
1964		dev->id[0][i].devtype = mbuf[0];
1965		rmb = mbuf[1];
1966		n = mbuf[7];
1967		if ((mbuf[7] & 0x60) == 0) {
1968			goto not_wide;
1969		}
1970		if ((i < 8) && ((dev->global_map[0] & 0x20) == 0)) {
1971			goto not_wide;
1972		}
1973		if (lvdmode == 0) {
1974			goto chg_wide;
1975		}
1976		if (dev->sp[0][i] != 0x04)	// force u2
1977		{
1978			goto chg_wide;
1979		}
1980
1981		tmport = wkport + 0x5b;
1982		outb(0x01, tmport);
1983		tmport = wkport + 0x43;
1984		outb(satn[0], tmport++);
1985		outb(satn[1], tmport++);
1986		outb(satn[2], tmport++);
1987		outb(satn[3], tmport++);
1988		outb(satn[4], tmport++);
1989		outb(satn[5], tmport++);
1990		tmport += 0x06;
1991		outb(0, tmport);
1992		tmport += 0x02;
1993		outb(dev->id[0][i].devsp, tmport++);
1994		outb(0, tmport++);
1995		outb(satn[6], tmport++);
1996		outb(satn[7], tmport++);
1997		tmport += 0x03;
1998		outb(satn[8], tmport);
1999		tmport += 0x07;
2000
2001		while ((inb(tmport) & 0x80) == 0x00)
2002			cpu_relax();
2003
2004		tmport -= 0x08;
2005
2006		if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
2007			continue;
2008
2009		while (inb(tmport) != 0x8e)
2010			cpu_relax();
2011
2012try_u3:
2013		j = 0;
2014		tmport = wkport + 0x54;
2015		outb(0x09, tmport);
2016		tmport += 0x04;
2017		outb(0x20, tmport);
2018		tmport += 0x07;
2019
2020		while ((inb(tmport) & 0x80) == 0) {
2021			if ((inb(tmport) & 0x01) != 0) {
2022				tmport -= 0x06;
2023				outb(u3[j++], tmport);
2024				tmport += 0x06;
2025			}
2026		}
2027		tmport -= 0x08;
2028
2029		while ((inb(tmport) & 0x80) == 0x00)
2030			cpu_relax();
2031
2032		j = inb(tmport) & 0x0f;
2033		if (j == 0x0f) {
2034			goto u3p_in;
2035		}
2036		if (j == 0x0a) {
2037			goto u3p_cmd;
2038		}
2039		if (j == 0x0e) {
2040			goto try_u3;
2041		}
2042		continue;
2043u3p_out:
2044		tmport = wkport + 0x58;
2045		outb(0x20, tmport);
2046		tmport += 0x07;
2047		while ((inb(tmport) & 0x80) == 0) {
2048			if ((inb(tmport) & 0x01) != 0) {
2049				tmport -= 0x06;
2050				outb(0, tmport);
2051				tmport += 0x06;
2052			}
2053		}
2054		tmport -= 0x08;
2055		j = inb(tmport) & 0x0f;
2056		if (j == 0x0f) {
2057			goto u3p_in;
2058		}
2059		if (j == 0x0a) {
2060			goto u3p_cmd;
2061		}
2062		if (j == 0x0e) {
2063			goto u3p_out;
2064		}
2065		continue;
2066u3p_in:
2067		tmport = wkport + 0x54;
2068		outb(0x09, tmport);
2069		tmport += 0x04;
2070		outb(0x20, tmport);
2071		tmport += 0x07;
2072		k = 0;
2073u3p_in1:
2074		j = inb(tmport);
2075		if ((j & 0x01) != 0) {
2076			tmport -= 0x06;
2077			mbuf[k++] = inb(tmport);
2078			tmport += 0x06;
2079			goto u3p_in1;
2080		}
2081		if ((j & 0x80) == 0x00) {
2082			goto u3p_in1;
2083		}
2084		tmport -= 0x08;
2085		j = inb(tmport) & 0x0f;
2086		if (j == 0x0f) {
2087			goto u3p_in;
2088		}
2089		if (j == 0x0a) {
2090			goto u3p_cmd;
2091		}
2092		if (j == 0x0e) {
2093			goto u3p_out;
2094		}
2095		continue;
2096u3p_cmd:
2097		tmport = wkport + 0x50;
2098		outb(0x30, tmport);
2099		tmport = wkport + 0x54;
2100		outb(0x00, tmport);
2101		tmport += 0x04;
2102		outb(0x08, tmport);
2103		tmport += 0x07;
2104
2105		while ((inb(tmport) & 0x80) == 0x00)
2106			cpu_relax();
2107
2108		tmport -= 0x08;
2109		j = inb(tmport);
2110		if (j != 0x16) {
2111			if (j == 0x4e) {
2112				goto u3p_out;
2113			}
2114			continue;
2115		}
2116		if (mbuf[0] != 0x01) {
2117			goto chg_wide;
2118		}
2119		if (mbuf[1] != 0x06) {
2120			goto chg_wide;
2121		}
2122		if (mbuf[2] != 0x04) {
2123			goto chg_wide;
2124		}
2125		if (mbuf[3] == 0x09) {
2126			m = 1;
2127			m = m << i;
2128			dev->wide_id[0] |= m;
2129			dev->id[0][i].devsp = 0xce;
2130			continue;
2131		}
2132chg_wide:
2133		tmport = wkport + 0x5b;
2134		outb(0x01, tmport);
2135		tmport = wkport + 0x43;
2136		outb(satn[0], tmport++);
2137		outb(satn[1], tmport++);
2138		outb(satn[2], tmport++);
2139		outb(satn[3], tmport++);
2140		outb(satn[4], tmport++);
2141		outb(satn[5], tmport++);
2142		tmport += 0x06;
2143		outb(0, tmport);
2144		tmport += 0x02;
2145		outb(dev->id[0][i].devsp, tmport++);
2146		outb(0, tmport++);
2147		outb(satn[6], tmport++);
2148		outb(satn[7], tmport++);
2149		tmport += 0x03;
2150		outb(satn[8], tmport);
2151		tmport += 0x07;
2152
2153		while ((inb(tmport) & 0x80) == 0x00)
2154			cpu_relax();
2155
2156		tmport -= 0x08;
2157		if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
2158			continue;
2159
2160		while (inb(tmport) != 0x8e)
2161			cpu_relax();
2162
2163try_wide:
2164		j = 0;
2165		tmport = wkport + 0x54;
2166		outb(0x05, tmport);
2167		tmport += 0x04;
2168		outb(0x20, tmport);
2169		tmport += 0x07;
2170
2171		while ((inb(tmport) & 0x80) == 0) {
2172			if ((inb(tmport) & 0x01) != 0) {
2173				tmport -= 0x06;
2174				outb(wide[j++], tmport);
2175				tmport += 0x06;
2176			}
2177		}
2178		tmport -= 0x08;
2179		while ((inb(tmport) & 0x80) == 0x00)
2180			cpu_relax();
2181
2182		j = inb(tmport) & 0x0f;
2183		if (j == 0x0f) {
2184			goto widep_in;
2185		}
2186		if (j == 0x0a) {
2187			goto widep_cmd;
2188		}
2189		if (j == 0x0e) {
2190			goto try_wide;
2191		}
2192		continue;
2193widep_out:
2194		tmport = wkport + 0x58;
2195		outb(0x20, tmport);
2196		tmport += 0x07;
2197		while ((inb(tmport) & 0x80) == 0) {
2198			if ((inb(tmport) & 0x01) != 0) {
2199				tmport -= 0x06;
2200				outb(0, tmport);
2201				tmport += 0x06;
2202			}
2203		}
2204		tmport -= 0x08;
2205		j = inb(tmport) & 0x0f;
2206		if (j == 0x0f) {
2207			goto widep_in;
2208		}
2209		if (j == 0x0a) {
2210			goto widep_cmd;
2211		}
2212		if (j == 0x0e) {
2213			goto widep_out;
2214		}
2215		continue;
2216widep_in:
2217		tmport = wkport + 0x54;
2218		outb(0xff, tmport);
2219		tmport += 0x04;
2220		outb(0x20, tmport);
2221		tmport += 0x07;
2222		k = 0;
2223widep_in1:
2224		j = inb(tmport);
2225		if ((j & 0x01) != 0) {
2226			tmport -= 0x06;
2227			mbuf[k++] = inb(tmport);
2228			tmport += 0x06;
2229			goto widep_in1;
2230		}
2231		if ((j & 0x80) == 0x00) {
2232			goto widep_in1;
2233		}
2234		tmport -= 0x08;
2235		j = inb(tmport) & 0x0f;
2236		if (j == 0x0f) {
2237			goto widep_in;
2238		}
2239		if (j == 0x0a) {
2240			goto widep_cmd;
2241		}
2242		if (j == 0x0e) {
2243			goto widep_out;
2244		}
2245		continue;
2246widep_cmd:
2247		tmport = wkport + 0x50;
2248		outb(0x30, tmport);
2249		tmport = wkport + 0x54;
2250		outb(0x00, tmport);
2251		tmport += 0x04;
2252		outb(0x08, tmport);
2253		tmport += 0x07;
2254
2255		while ((inb(tmport) & 0x80) == 0x00)
2256			cpu_relax();
2257
2258		tmport -= 0x08;
2259		j = inb(tmport);
2260		if (j != 0x16) {
2261			if (j == 0x4e) {
2262				goto widep_out;
2263			}
2264			continue;
2265		}
2266		if (mbuf[0] != 0x01) {
2267			goto not_wide;
2268		}
2269		if (mbuf[1] != 0x02) {
2270			goto not_wide;
2271		}
2272		if (mbuf[2] != 0x03) {
2273			goto not_wide;
2274		}
2275		if (mbuf[3] != 0x01) {
2276			goto not_wide;
2277		}
2278		m = 1;
2279		m = m << i;
2280		dev->wide_id[0] |= m;
2281not_wide:
2282		if ((dev->id[0][i].devtype == 0x00) || (dev->id[0][i].devtype == 0x07) || ((dev->id[0][i].devtype == 0x05) && ((n & 0x10) != 0))) {
2283			m = 1;
2284			m = m << i;
2285			if ((dev->async[0] & m) != 0) {
2286				goto set_sync;
2287			}
2288		}
2289		continue;
2290set_sync:
2291		if (dev->sp[0][i] == 0x02) {
2292			synu[4] = 0x0c;
2293			synuw[4] = 0x0c;
2294		} else {
2295			if (dev->sp[0][i] >= 0x03) {
2296				synu[4] = 0x0a;
2297				synuw[4] = 0x0a;
2298			}
2299		}
2300		tmport = wkport + 0x5b;
2301		j = 0;
2302		if ((m & dev->wide_id[0]) != 0) {
2303			j |= 0x01;
2304		}
2305		outb(j, tmport);
2306		tmport = wkport + 0x43;
2307		outb(satn[0], tmport++);
2308		outb(satn[1], tmport++);
2309		outb(satn[2], tmport++);
2310		outb(satn[3], tmport++);
2311		outb(satn[4], tmport++);
2312		outb(satn[5], tmport++);
2313		tmport += 0x06;
2314		outb(0, tmport);
2315		tmport += 0x02;
2316		outb(dev->id[0][i].devsp, tmport++);
2317		outb(0, tmport++);
2318		outb(satn[6], tmport++);
2319		outb(satn[7], tmport++);
2320		tmport += 0x03;
2321		outb(satn[8], tmport);
2322		tmport += 0x07;
2323
2324		while ((inb(tmport) & 0x80) == 0x00)
2325			cpu_relax();
2326
2327		tmport -= 0x08;
2328		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
2329			continue;
2330		}
2331		while (inb(tmport) != 0x8e)
2332			cpu_relax();
2333
2334try_sync:
2335		j = 0;
2336		tmport = wkport + 0x54;
2337		outb(0x06, tmport);
2338		tmport += 0x04;
2339		outb(0x20, tmport);
2340		tmport += 0x07;
2341
2342		while ((inb(tmport) & 0x80) == 0) {
2343			if ((inb(tmport) & 0x01) != 0) {
2344				tmport -= 0x06;
2345				if ((m & dev->wide_id[0]) != 0) {
2346					if ((m & dev->ultra_map[0]) != 0) {
2347						outb(synuw[j++], tmport);
2348					} else {
2349						outb(synw[j++], tmport);
2350					}
2351				} else {
2352					if ((m & dev->ultra_map[0]) != 0) {
2353						outb(synu[j++], tmport);
2354					} else {
2355						outb(synn[j++], tmport);
2356					}
2357				}
2358				tmport += 0x06;
2359			}
2360		}
2361		tmport -= 0x08;
2362
2363		while ((inb(tmport) & 0x80) == 0x00)
2364			cpu_relax();
2365
2366		j = inb(tmport) & 0x0f;
2367		if (j == 0x0f) {
2368			goto phase_ins;
2369		}
2370		if (j == 0x0a) {
2371			goto phase_cmds;
2372		}
2373		if (j == 0x0e) {
2374			goto try_sync;
2375		}
2376		continue;
2377phase_outs:
2378		tmport = wkport + 0x58;
2379		outb(0x20, tmport);
2380		tmport += 0x07;
2381		while ((inb(tmport) & 0x80) == 0x00) {
2382			if ((inb(tmport) & 0x01) != 0x00) {
2383				tmport -= 0x06;
2384				outb(0x00, tmport);
2385				tmport += 0x06;
2386			}
2387		}
2388		tmport -= 0x08;
2389		j = inb(tmport);
2390		if (j == 0x85) {
2391			goto tar_dcons;
2392		}
2393		j &= 0x0f;
2394		if (j == 0x0f) {
2395			goto phase_ins;
2396		}
2397		if (j == 0x0a) {
2398			goto phase_cmds;
2399		}
2400		if (j == 0x0e) {
2401			goto phase_outs;
2402		}
2403		continue;
2404phase_ins:
2405		tmport = wkport + 0x54;
2406		outb(0x06, tmport);
2407		tmport += 0x04;
2408		outb(0x20, tmport);
2409		tmport += 0x07;
2410		k = 0;
2411phase_ins1:
2412		j = inb(tmport);
2413		if ((j & 0x01) != 0x00) {
2414			tmport -= 0x06;
2415			mbuf[k++] = inb(tmport);
2416			tmport += 0x06;
2417			goto phase_ins1;
2418		}
2419		if ((j & 0x80) == 0x00) {
2420			goto phase_ins1;
2421		}
2422		tmport -= 0x08;
2423
2424		while ((inb(tmport) & 0x80) == 0x00)
2425			cpu_relax();
2426
2427		j = inb(tmport);
2428		if (j == 0x85) {
2429			goto tar_dcons;
2430		}
2431		j &= 0x0f;
2432		if (j == 0x0f) {
2433			goto phase_ins;
2434		}
2435		if (j == 0x0a) {
2436			goto phase_cmds;
2437		}
2438		if (j == 0x0e) {
2439			goto phase_outs;
2440		}
2441		continue;
2442phase_cmds:
2443		tmport = wkport + 0x50;
2444		outb(0x30, tmport);
2445tar_dcons:
2446		tmport = wkport + 0x54;
2447		outb(0x00, tmport);
2448		tmport += 0x04;
2449		outb(0x08, tmport);
2450		tmport += 0x07;
2451
2452		while ((inb(tmport) & 0x80) == 0x00)
2453			cpu_relax();
2454
2455		tmport -= 0x08;
2456		j = inb(tmport);
2457		if (j != 0x16) {
2458			continue;
2459		}
2460		if (mbuf[0] != 0x01) {
2461			continue;
2462		}
2463		if (mbuf[1] != 0x03) {
2464			continue;
2465		}
2466		if (mbuf[4] == 0x00) {
2467			continue;
2468		}
2469		if (mbuf[3] > 0x64) {
2470			continue;
2471		}
2472		if (mbuf[4] > 0x0e) {
2473			mbuf[4] = 0x0e;
2474		}
2475		dev->id[0][i].devsp = mbuf[4];
2476		if (mbuf[3] < 0x0c) {
2477			j = 0xb0;
2478			goto set_syn_ok;
2479		}
2480		if ((mbuf[3] < 0x0d) && (rmb == 0)) {
2481			j = 0xa0;
2482			goto set_syn_ok;
2483		}
2484		if (mbuf[3] < 0x1a) {
2485			j = 0x20;
2486			goto set_syn_ok;
2487		}
2488		if (mbuf[3] < 0x33) {
2489			j = 0x40;
2490			goto set_syn_ok;
2491		}
2492		if (mbuf[3] < 0x4c) {
2493			j = 0x50;
2494			goto set_syn_ok;
2495		}
2496		j = 0x60;
2497set_syn_ok:
2498		dev->id[0][i].devsp = (dev->id[0][i].devsp & 0x0f) | j;
2499	}
2500}
2501
2502static void atp870u_free_tables(struct Scsi_Host *host)
2503{
2504	struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata;
2505	int j, k;
2506	for (j=0; j < 2; j++) {
2507		for (k = 0; k < 16; k++) {
2508			if (!atp_dev->id[j][k].prd_table)
2509				continue;
2510			pci_free_consistent(atp_dev->pdev, 1024, atp_dev->id[j][k].prd_table, atp_dev->id[j][k].prd_bus);
2511			atp_dev->id[j][k].prd_table = NULL;
2512		}
2513	}
2514}
2515
2516static int atp870u_init_tables(struct Scsi_Host *host)
2517{
2518	struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata;
2519	int c,k;
2520	for(c=0;c < 2;c++) {
2521	   	for(k=0;k<16;k++) {
2522	   			atp_dev->id[c][k].prd_table = pci_alloc_consistent(atp_dev->pdev, 1024, &(atp_dev->id[c][k].prd_bus));
2523	   			if (!atp_dev->id[c][k].prd_table) {
2524	   				printk("atp870u_init_tables fail\n");
2525				atp870u_free_tables(host);
2526				return -ENOMEM;
2527			}
2528			atp_dev->id[c][k].prdaddr = atp_dev->id[c][k].prd_bus;
2529			atp_dev->id[c][k].devsp=0x20;
2530			atp_dev->id[c][k].devtype = 0x7f;
2531			atp_dev->id[c][k].curr_req = NULL;
2532	   	}
2533
2534	   	atp_dev->active_id[c] = 0;
2535	   	atp_dev->wide_id[c] = 0;
2536	   	atp_dev->host_id[c] = 0x07;
2537	   	atp_dev->quhd[c] = 0;
2538	   	atp_dev->quend[c] = 0;
2539	   	atp_dev->last_cmd[c] = 0xff;
2540	   	atp_dev->in_snd[c] = 0;
2541	   	atp_dev->in_int[c] = 0;
2542
2543	   	for (k = 0; k < qcnt; k++) {
2544	   		  atp_dev->quereq[c][k] = NULL;
2545	   	}
2546	   	for (k = 0; k < 16; k++) {
2547			   atp_dev->id[c][k].curr_req = NULL;
2548			   atp_dev->sp[c][k] = 0x04;
2549	   	}
2550	}
2551	return 0;
2552}
2553
2554/* return non-zero on detection */
2555static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
2556{
2557	unsigned char k, m, c;
2558	unsigned long flags;
2559	unsigned int base_io, tmport, error,n;
2560	unsigned char host_id;
2561	struct Scsi_Host *shpnt = NULL;
2562	struct atp_unit *atpdev, *p;
2563	unsigned char setupdata[2][16];
2564	int count = 0;
2565
2566	atpdev = kzalloc(sizeof(*atpdev), GFP_KERNEL);
2567	if (!atpdev)
2568		return -ENOMEM;
2569
2570	if (pci_enable_device(pdev))
2571		goto err_eio;
2572
2573        if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
2574                printk(KERN_INFO "atp870u: use 32bit DMA mask.\n");
2575        } else {
2576                printk(KERN_ERR "atp870u: DMA mask required but not available.\n");
2577		goto err_eio;
2578        }
2579
2580	/*
2581	 * It's probably easier to weed out some revisions like
2582	 * this than via the PCI device table
2583	 */
2584	if (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610) {
2585		atpdev->chip_ver = pdev->revision;
2586		if (atpdev->chip_ver < 2)
2587			goto err_eio;
2588	}
2589
2590	switch (ent->device) {
2591	case PCI_DEVICE_ID_ARTOP_AEC7612UW:
2592	case PCI_DEVICE_ID_ARTOP_AEC7612SUW:
2593	case ATP880_DEVID1:
2594	case ATP880_DEVID2:
2595	case ATP885_DEVID:
2596		atpdev->chip_ver = 0x04;
2597	default:
2598		break;
2599	}
2600	base_io = pci_resource_start(pdev, 0);
2601	base_io &= 0xfffffff8;
2602
2603	if ((ent->device == ATP880_DEVID1)||(ent->device == ATP880_DEVID2)) {
2604		atpdev->chip_ver = pdev->revision;
2605		pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80);//JCC082803
2606
2607		host_id = inb(base_io + 0x39);
2608		host_id >>= 0x04;
2609
2610		printk(KERN_INFO "   ACARD AEC-67160 PCI Ultra3 LVD Host Adapter: %d"
2611			"    IO:%x, IRQ:%d.\n", count, base_io, pdev->irq);
2612		atpdev->ioport[0] = base_io + 0x40;
2613		atpdev->pciport[0] = base_io + 0x28;
2614		atpdev->dev_id = ent->device;
2615		atpdev->host_id[0] = host_id;
2616
2617		tmport = base_io + 0x22;
2618		atpdev->scam_on = inb(tmport);
2619		tmport += 0x13;
2620		atpdev->global_map[0] = inb(tmport);
2621		tmport += 0x07;
2622		atpdev->ultra_map[0] = inw(tmport);
2623
2624		n = 0x3f09;
2625next_fblk_880:
2626		if (n >= 0x4000)
2627			goto flash_ok_880;
2628
2629		m = 0;
2630		outw(n, base_io + 0x34);
2631		n += 0x0002;
2632		if (inb(base_io + 0x30) == 0xff)
2633			goto flash_ok_880;
2634
2635		atpdev->sp[0][m++] = inb(base_io + 0x30);
2636		atpdev->sp[0][m++] = inb(base_io + 0x31);
2637		atpdev->sp[0][m++] = inb(base_io + 0x32);
2638		atpdev->sp[0][m++] = inb(base_io + 0x33);
2639		outw(n, base_io + 0x34);
2640		n += 0x0002;
2641		atpdev->sp[0][m++] = inb(base_io + 0x30);
2642		atpdev->sp[0][m++] = inb(base_io + 0x31);
2643		atpdev->sp[0][m++] = inb(base_io + 0x32);
2644		atpdev->sp[0][m++] = inb(base_io + 0x33);
2645		outw(n, base_io + 0x34);
2646		n += 0x0002;
2647		atpdev->sp[0][m++] = inb(base_io + 0x30);
2648		atpdev->sp[0][m++] = inb(base_io + 0x31);
2649		atpdev->sp[0][m++] = inb(base_io + 0x32);
2650		atpdev->sp[0][m++] = inb(base_io + 0x33);
2651		outw(n, base_io + 0x34);
2652		n += 0x0002;
2653		atpdev->sp[0][m++] = inb(base_io + 0x30);
2654		atpdev->sp[0][m++] = inb(base_io + 0x31);
2655		atpdev->sp[0][m++] = inb(base_io + 0x32);
2656		atpdev->sp[0][m++] = inb(base_io + 0x33);
2657		n += 0x0018;
2658		goto next_fblk_880;
2659flash_ok_880:
2660		outw(0, base_io + 0x34);
2661		atpdev->ultra_map[0] = 0;
2662		atpdev->async[0] = 0;
2663		for (k = 0; k < 16; k++) {
2664			n = 1;
2665			n = n << k;
2666			if (atpdev->sp[0][k] > 1) {
2667				atpdev->ultra_map[0] |= n;
2668			} else {
2669				if (atpdev->sp[0][k] == 0)
2670					atpdev->async[0] |= n;
2671 			}
2672	 	}
2673		atpdev->async[0] = ~(atpdev->async[0]);
2674		outb(atpdev->global_map[0], base_io + 0x35);
2675
2676		shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
2677		if (!shpnt)
2678			goto err_nomem;
2679
2680		p = (struct atp_unit *)&shpnt->hostdata;
2681
2682		atpdev->host = shpnt;
2683		atpdev->pdev = pdev;
2684		pci_set_drvdata(pdev, p);
2685		memcpy(p, atpdev, sizeof(*atpdev));
2686		if (atp870u_init_tables(shpnt) < 0) {
2687			printk(KERN_ERR "Unable to allocate tables for Acard controller\n");
2688			goto unregister;
2689		}
2690
2691		if (request_irq(pdev->irq, atp870u_intr_handle, IRQF_SHARED, "atp880i", shpnt)) {
2692 			printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", pdev->irq);
2693			goto free_tables;
2694		}
2695
2696		spin_lock_irqsave(shpnt->host_lock, flags);
2697		tmport = base_io + 0x38;
2698		k = inb(tmport) & 0x80;
2699		outb(k, tmport);
2700		tmport += 0x03;
2701		outb(0x20, tmport);
2702		mdelay(32);
2703		outb(0, tmport);
2704		mdelay(32);
2705		tmport = base_io + 0x5b;
2706		inb(tmport);
2707		tmport -= 0x04;
2708		inb(tmport);
2709		tmport = base_io + 0x40;
2710		outb((host_id | 0x08), tmport);
2711		tmport += 0x18;
2712		outb(0, tmport);
2713		tmport += 0x07;
2714		while ((inb(tmport) & 0x80) == 0)
2715			mdelay(1);
2716		tmport -= 0x08;
2717		inb(tmport);
2718		tmport = base_io + 0x41;
2719		outb(8, tmport++);
2720		outb(0x7f, tmport);
2721		tmport = base_io + 0x51;
2722		outb(0x20, tmport);
2723
2724		tscam(shpnt);
2725		is880(p, base_io);
2726		tmport = base_io + 0x38;
2727		outb(0xb0, tmport);
2728		shpnt->max_id = 16;
2729		shpnt->this_id = host_id;
2730		shpnt->unique_id = base_io;
2731		shpnt->io_port = base_io;
2732		shpnt->n_io_port = 0x60;	/* Number of bytes of I/O space used */
2733		shpnt->irq = pdev->irq;
2734	} else if (ent->device == ATP885_DEVID) {
2735			printk(KERN_INFO "   ACARD AEC-67162 PCI Ultra3 LVD Host Adapter:  IO:%x, IRQ:%d.\n"
2736			       , base_io, pdev->irq);
2737
2738		atpdev->pdev = pdev;
2739		atpdev->dev_id  = ent->device;
2740		atpdev->baseport = base_io;
2741		atpdev->ioport[0] = base_io + 0x80;
2742		atpdev->ioport[1] = base_io + 0xc0;
2743		atpdev->pciport[0] = base_io + 0x40;
2744		atpdev->pciport[1] = base_io + 0x50;
2745
2746		shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
2747		if (!shpnt)
2748			goto err_nomem;
2749
2750		p = (struct atp_unit *)&shpnt->hostdata;
2751
2752		atpdev->host = shpnt;
2753		atpdev->pdev = pdev;
2754		pci_set_drvdata(pdev, p);
2755		memcpy(p, atpdev, sizeof(struct atp_unit));
2756		if (atp870u_init_tables(shpnt) < 0)
2757			goto unregister;
2758
2759#ifdef ED_DBGP
2760	printk("request_irq() shpnt %p hostdata %p\n", shpnt, p);
2761#endif
2762		if (request_irq(pdev->irq, atp870u_intr_handle, IRQF_SHARED, "atp870u", shpnt)) {
2763				printk(KERN_ERR "Unable to allocate IRQ for Acard controller.\n");
2764			goto free_tables;
2765		}
2766
2767		spin_lock_irqsave(shpnt->host_lock, flags);
2768
2769		c=inb(base_io + 0x29);
2770		outb((c | 0x04),base_io + 0x29);
2771
2772		n=0x1f80;
2773next_fblk_885:
2774		if (n >= 0x2000) {
2775		   goto flash_ok_885;
2776		}
2777		outw(n,base_io + 0x3c);
2778		if (inl(base_io + 0x38) == 0xffffffff) {
2779		   goto flash_ok_885;
2780		}
2781		for (m=0; m < 2; m++) {
2782		    p->global_map[m]= 0;
2783		    for (k=0; k < 4; k++) {
2784			outw(n++,base_io + 0x3c);
2785			((unsigned long *)&setupdata[m][0])[k]=inl(base_io + 0x38);
2786		    }
2787		    for (k=0; k < 4; k++) {
2788			outw(n++,base_io + 0x3c);
2789			((unsigned long *)&p->sp[m][0])[k]=inl(base_io + 0x38);
2790		    }
2791		    n += 8;
2792		}
2793		goto next_fblk_885;
2794flash_ok_885:
2795#ifdef ED_DBGP
2796		printk( "Flash Read OK\n");
2797#endif
2798		c=inb(base_io + 0x29);
2799		outb((c & 0xfb),base_io + 0x29);
2800		for (c=0;c < 2;c++) {
2801		    p->ultra_map[c]=0;
2802		    p->async[c] = 0;
2803		    for (k=0; k < 16; k++) {
2804			n=1;
2805			n = n << k;
2806			if (p->sp[c][k] > 1) {
2807			   p->ultra_map[c] |= n;
2808			} else {
2809			   if (p->sp[c][k] == 0) {
2810			      p->async[c] |= n;
2811			   }
2812			}
2813		    }
2814		    p->async[c] = ~(p->async[c]);
2815
2816		    if (p->global_map[c] == 0) {
2817		       k=setupdata[c][1];
2818		       if ((k & 0x40) != 0)
2819			  p->global_map[c] |= 0x20;
2820		       k &= 0x07;
2821		       p->global_map[c] |= k;
2822		       if ((setupdata[c][2] & 0x04) != 0)
2823			  p->global_map[c] |= 0x08;
2824		       p->host_id[c] = setupdata[c][0] & 0x07;
2825		    }
2826		}
2827
2828		k = inb(base_io + 0x28) & 0x8f;
2829		k |= 0x10;
2830		outb(k, base_io + 0x28);
2831		outb(0x80, base_io + 0x41);
2832		outb(0x80, base_io + 0x51);
2833		mdelay(100);
2834		outb(0, base_io + 0x41);
2835		outb(0, base_io + 0x51);
2836		mdelay(1000);
2837		inb(base_io + 0x9b);
2838		inb(base_io + 0x97);
2839		inb(base_io + 0xdb);
2840		inb(base_io + 0xd7);
2841		tmport = base_io + 0x80;
2842		k=p->host_id[0];
2843		if (k > 7)
2844		   k = (k & 0x07) | 0x40;
2845		k |= 0x08;
2846		outb(k, tmport);
2847		tmport += 0x18;
2848		outb(0, tmport);
2849		tmport += 0x07;
2850
2851		while ((inb(tmport) & 0x80) == 0)
2852			cpu_relax();
2853
2854		tmport -= 0x08;
2855		inb(tmport);
2856		tmport = base_io + 0x81;
2857		outb(8, tmport++);
2858		outb(0x7f, tmport);
2859		tmport = base_io + 0x91;
2860		outb(0x20, tmport);
2861
2862		tmport = base_io + 0xc0;
2863		k=p->host_id[1];
2864		if (k > 7)
2865		   k = (k & 0x07) | 0x40;
2866		k |= 0x08;
2867		outb(k, tmport);
2868		tmport += 0x18;
2869		outb(0, tmport);
2870		tmport += 0x07;
2871
2872		while ((inb(tmport) & 0x80) == 0)
2873			cpu_relax();
2874
2875		tmport -= 0x08;
2876		inb(tmport);
2877		tmport = base_io + 0xc1;
2878		outb(8, tmport++);
2879		outb(0x7f, tmport);
2880		tmport = base_io + 0xd1;
2881		outb(0x20, tmport);
2882
2883		tscam_885();
2884		printk(KERN_INFO "   Scanning Channel A SCSI Device ...\n");
2885		is885(p, base_io + 0x80, 0);
2886		printk(KERN_INFO "   Scanning Channel B SCSI Device ...\n");
2887		is885(p, base_io + 0xc0, 1);
2888
2889		k = inb(base_io + 0x28) & 0xcf;
2890		k |= 0xc0;
2891		outb(k, base_io + 0x28);
2892		k = inb(base_io + 0x1f) | 0x80;
2893		outb(k, base_io + 0x1f);
2894		k = inb(base_io + 0x29) | 0x01;
2895		outb(k, base_io + 0x29);
2896#ifdef ED_DBGP
2897		//printk("atp885: atp_host[0] 0x%p\n", atp_host[0]);
2898#endif
2899		shpnt->max_id = 16;
2900		shpnt->max_lun = (p->global_map[0] & 0x07) + 1;
2901		shpnt->max_channel = 1;
2902		shpnt->this_id = p->host_id[0];
2903		shpnt->unique_id = base_io;
2904		shpnt->io_port = base_io;
2905		shpnt->n_io_port = 0xff;	/* Number of bytes of I/O space used */
2906		shpnt->irq = pdev->irq;
2907
2908	} else {
2909		error = pci_read_config_byte(pdev, 0x49, &host_id);
2910
2911		printk(KERN_INFO "   ACARD AEC-671X PCI Ultra/W SCSI-2/3 Host Adapter: %d "
2912			"IO:%x, IRQ:%d.\n", count, base_io, pdev->irq);
2913
2914		atpdev->ioport[0] = base_io;
2915		atpdev->pciport[0] = base_io + 0x20;
2916		atpdev->dev_id = ent->device;
2917		host_id &= 0x07;
2918		atpdev->host_id[0] = host_id;
2919		tmport = base_io + 0x22;
2920		atpdev->scam_on = inb(tmport);
2921		tmport += 0x0b;
2922		atpdev->global_map[0] = inb(tmport++);
2923		atpdev->ultra_map[0] = inw(tmport);
2924
2925		if (atpdev->ultra_map[0] == 0) {
2926			atpdev->scam_on = 0x00;
2927			atpdev->global_map[0] = 0x20;
2928			atpdev->ultra_map[0] = 0xffff;
2929		}
2930
2931		shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
2932		if (!shpnt)
2933			goto err_nomem;
2934
2935		p = (struct atp_unit *)&shpnt->hostdata;
2936
2937		atpdev->host = shpnt;
2938		atpdev->pdev = pdev;
2939		pci_set_drvdata(pdev, p);
2940		memcpy(p, atpdev, sizeof(*atpdev));
2941		if (atp870u_init_tables(shpnt) < 0)
2942			goto unregister;
2943
2944		if (request_irq(pdev->irq, atp870u_intr_handle, IRQF_SHARED, "atp870i", shpnt)) {
2945			printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", pdev->irq);
2946			goto free_tables;
2947		}
2948
2949		spin_lock_irqsave(shpnt->host_lock, flags);
2950		if (atpdev->chip_ver > 0x07) {	/* check if atp876 chip then enable terminator */
2951			tmport = base_io + 0x3e;
2952			outb(0x00, tmport);
2953		}
2954
2955		tmport = base_io + 0x3a;
2956		k = (inb(tmport) & 0xf3) | 0x10;
2957		outb(k, tmport);
2958		outb((k & 0xdf), tmport);
2959		mdelay(32);
2960		outb(k, tmport);
2961		mdelay(32);
2962		tmport = base_io;
2963		outb((host_id | 0x08), tmport);
2964		tmport += 0x18;
2965		outb(0, tmport);
2966		tmport += 0x07;
2967		while ((inb(tmport) & 0x80) == 0)
2968			mdelay(1);
2969
2970		tmport -= 0x08;
2971		inb(tmport);
2972		tmport = base_io + 1;
2973		outb(8, tmport++);
2974		outb(0x7f, tmport);
2975		tmport = base_io + 0x11;
2976		outb(0x20, tmport);
2977
2978		tscam(shpnt);
2979		is870(p, base_io);
2980		tmport = base_io + 0x3a;
2981		outb((inb(tmport) & 0xef), tmport);
2982		tmport++;
2983		outb((inb(tmport) | 0x20), tmport);
2984		if (atpdev->chip_ver == 4)
2985			shpnt->max_id = 16;
2986		else
2987			shpnt->max_id = 8;
2988		shpnt->this_id = host_id;
2989		shpnt->unique_id = base_io;
2990		shpnt->io_port = base_io;
2991		shpnt->n_io_port = 0x40;	/* Number of bytes of I/O space used */
2992		shpnt->irq = pdev->irq;
2993	}
2994		spin_unlock_irqrestore(shpnt->host_lock, flags);
2995		if(ent->device==ATP885_DEVID) {
2996			if(!request_region(base_io, 0xff, "atp870u")) /* Register the IO ports that we use */
2997				goto request_io_fail;
2998		} else if((ent->device==ATP880_DEVID1)||(ent->device==ATP880_DEVID2)) {
2999			if(!request_region(base_io, 0x60, "atp870u")) /* Register the IO ports that we use */
3000				goto request_io_fail;
3001		} else {
3002			if(!request_region(base_io, 0x40, "atp870u")) /* Register the IO ports that we use */
3003				goto request_io_fail;
3004		}
3005		count++;
3006		if (scsi_add_host(shpnt, &pdev->dev))
3007			goto scsi_add_fail;
3008		scsi_scan_host(shpnt);
3009#ifdef ED_DBGP
3010		printk("atp870u_prob : exit\n");
3011#endif
3012		return 0;
3013
3014scsi_add_fail:
3015	printk("atp870u_prob:scsi_add_fail\n");
3016	if(ent->device==ATP885_DEVID) {
3017		release_region(base_io, 0xff);
3018	} else if((ent->device==ATP880_DEVID1)||(ent->device==ATP880_DEVID2)) {
3019		release_region(base_io, 0x60);
3020	} else {
3021		release_region(base_io, 0x40);
3022	}
3023request_io_fail:
3024	printk("atp870u_prob:request_io_fail\n");
3025	free_irq(pdev->irq, shpnt);
3026free_tables:
3027	printk("atp870u_prob:free_table\n");
3028	atp870u_free_tables(shpnt);
3029unregister:
3030	printk("atp870u_prob:unregister\n");
3031	scsi_host_put(shpnt);
3032	return -1;
3033err_eio:
3034	kfree(atpdev);
3035	return -EIO;
3036err_nomem:
3037	kfree(atpdev);
3038	return -ENOMEM;
3039}
3040
3041/* The abort command does not leave the device in a clean state where
3042   it is available to be used again.  Until this gets worked out, we will
3043   leave it commented out.  */
3044
3045static int atp870u_abort(struct scsi_cmnd * SCpnt)
3046{
3047	unsigned char  j, k, c;
3048	struct scsi_cmnd *workrequ;
3049	unsigned int tmport;
3050	struct atp_unit *dev;
3051	struct Scsi_Host *host;
3052	host = SCpnt->device->host;
3053
3054	dev = (struct atp_unit *)&host->hostdata;
3055	c = scmd_channel(SCpnt);
3056	printk(" atp870u: abort Channel = %x \n", c);
3057	printk("working=%x last_cmd=%x ", dev->working[c], dev->last_cmd[c]);
3058	printk(" quhdu=%x quendu=%x ", dev->quhd[c], dev->quend[c]);
3059	tmport = dev->ioport[c];
3060	for (j = 0; j < 0x18; j++) {
3061		printk(" r%2x=%2x", j, inb(tmport++));
3062	}
3063	tmport += 0x04;
3064	printk(" r1c=%2x", inb(tmport));
3065	tmport += 0x03;
3066	printk(" r1f=%2x in_snd=%2x ", inb(tmport), dev->in_snd[c]);
3067	tmport= dev->pciport[c];
3068	printk(" d00=%2x", inb(tmport));
3069	tmport += 0x02;
3070	printk(" d02=%2x", inb(tmport));
3071	for(j=0;j<16;j++) {
3072	   if (dev->id[c][j].curr_req != NULL) {
3073		workrequ = dev->id[c][j].curr_req;
3074		printk("\n que cdb= ");
3075		for (k=0; k < workrequ->cmd_len; k++) {
3076		    printk(" %2x ",workrequ->cmnd[k]);
3077		}
3078		printk(" last_lenu= %x ",(unsigned int)dev->id[c][j].last_len);
3079	   }
3080	}
3081	return SUCCESS;
3082}
3083
3084static const char *atp870u_info(struct Scsi_Host *notused)
3085{
3086	static char buffer[128];
3087
3088	strcpy(buffer, "ACARD AEC-6710/6712/67160 PCI Ultra/W/LVD SCSI-3 Adapter Driver V2.6+ac ");
3089
3090	return buffer;
3091}
3092
3093#define BLS buffer + len + size
3094static int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer,
3095			     char **start, off_t offset, int length, int inout)
3096{
3097	static u8 buff[512];
3098	int size = 0;
3099	int len = 0;
3100	off_t begin = 0;
3101	off_t pos = 0;
3102
3103	if (inout)
3104		return -EINVAL;
3105	if (offset == 0)
3106		memset(buff, 0, sizeof(buff));
3107	size += sprintf(BLS, "ACARD AEC-671X Driver Version: 2.6+ac\n");
3108	len += size;
3109	pos = begin + len;
3110	size = 0;
3111
3112	size += sprintf(BLS, "\n");
3113	size += sprintf(BLS, "Adapter Configuration:\n");
3114	size += sprintf(BLS, "               Base IO: %#.4lx\n", HBAptr->io_port);
3115	size += sprintf(BLS, "                   IRQ: %d\n", HBAptr->irq);
3116	len += size;
3117	pos = begin + len;
3118
3119	*start = buffer + (offset - begin);	/* Start of wanted data */
3120	len -= (offset - begin);	/* Start slop */
3121	if (len > length) {
3122		len = length;	/* Ending slop */
3123	}
3124	return (len);
3125}
3126
3127
3128static int atp870u_biosparam(struct scsi_device *disk, struct block_device *dev,
3129			sector_t capacity, int *ip)
3130{
3131	int heads, sectors, cylinders;
3132
3133	heads = 64;
3134	sectors = 32;
3135	cylinders = (unsigned long)capacity / (heads * sectors);
3136	if (cylinders > 1024) {
3137		heads = 255;
3138		sectors = 63;
3139		cylinders = (unsigned long)capacity / (heads * sectors);
3140	}
3141	ip[0] = heads;
3142	ip[1] = sectors;
3143	ip[2] = cylinders;
3144
3145	return 0;
3146}
3147
3148static void atp870u_remove (struct pci_dev *pdev)
3149{
3150	struct atp_unit *devext = pci_get_drvdata(pdev);
3151	struct Scsi_Host *pshost = devext->host;
3152
3153
3154	scsi_remove_host(pshost);
3155	printk(KERN_INFO "free_irq : %d\n",pshost->irq);
3156	free_irq(pshost->irq, pshost);
3157	release_region(pshost->io_port, pshost->n_io_port);
3158	printk(KERN_INFO "atp870u_free_tables : %p\n",pshost);
3159	atp870u_free_tables(pshost);
3160	printk(KERN_INFO "scsi_host_put : %p\n",pshost);
3161	scsi_host_put(pshost);
3162	printk(KERN_INFO "pci_set_drvdata : %p\n",pdev);
3163	pci_set_drvdata(pdev, NULL);
3164}
3165MODULE_LICENSE("GPL");
3166
3167static struct scsi_host_template atp870u_template = {
3168     .module			= THIS_MODULE,
3169     .name              	= "atp870u"		/* name */,
3170     .proc_name			= "atp870u",
3171     .proc_info			= atp870u_proc_info,
3172     .info              	= atp870u_info		/* info */,
3173     .queuecommand      	= atp870u_queuecommand	/* queuecommand */,
3174     .eh_abort_handler  	= atp870u_abort		/* abort */,
3175     .bios_param        	= atp870u_biosparam	/* biosparm */,
3176     .can_queue         	= qcnt			/* can_queue */,
3177     .this_id           	= 7			/* SCSI ID */,
3178     .sg_tablesize      	= ATP870U_SCATTER	/*SG_ALL*/ /*SG_NONE*/,
3179     .cmd_per_lun       	= ATP870U_CMDLUN		/* commands per lun */,
3180     .use_clustering    	= ENABLE_CLUSTERING,
3181     .max_sectors		= ATP870U_MAX_SECTORS,
3182};
3183
3184static struct pci_device_id atp870u_id_table[] = {
3185	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP885_DEVID)			  },
3186	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID1)			  },
3187	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID2)			  },
3188	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7610)    },
3189	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612UW)  },
3190	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612U)   },
3191	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612S)   },
3192	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612D)	  },
3193	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612SUW) },
3194	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_8060)	  },
3195	{ 0, },
3196};
3197
3198MODULE_DEVICE_TABLE(pci, atp870u_id_table);
3199
3200static struct pci_driver atp870u_driver = {
3201	.id_table	= atp870u_id_table,
3202	.name		= "atp870u",
3203	.probe		= atp870u_probe,
3204	.remove		= __devexit_p(atp870u_remove),
3205};
3206
3207static int __init atp870u_init(void)
3208{
3209#ifdef ED_DBGP
3210	printk("atp870u_init: Entry\n");
3211#endif
3212	return pci_register_driver(&atp870u_driver);
3213}
3214
3215static void __exit atp870u_exit(void)
3216{
3217#ifdef ED_DBGP
3218	printk("atp870u_exit: Entry\n");
3219#endif
3220	pci_unregister_driver(&atp870u_driver);
3221}
3222
3223static void tscam_885(void)
3224{
3225	unsigned char i;
3226
3227	for (i = 0; i < 0x2; i++) {
3228		mdelay(300);
3229	}
3230	return;
3231}
3232
3233
3234
3235static void is885(struct atp_unit *dev, unsigned int wkport,unsigned char c)
3236{
3237	unsigned int tmport;
3238	unsigned char i, j, k, rmb, n, lvdmode;
3239	unsigned short int m;
3240	static unsigned char mbuf[512];
3241	static unsigned char satn[9] =	{0, 0, 0, 0, 0, 0, 0, 6, 6};
3242	static unsigned char inqd[9] =	{0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6};
3243	static unsigned char synn[6] =	{0x80, 1, 3, 1, 0x19, 0x0e};
3244	unsigned char synu[6] =  {0x80, 1, 3, 1, 0x0a, 0x0e};
3245	static unsigned char synw[6] =	{0x80, 1, 3, 1, 0x19, 0x0e};
3246	unsigned char synuw[6] =  {0x80, 1, 3, 1, 0x0a, 0x0e};
3247	static unsigned char wide[6] =	{0x80, 1, 2, 3, 1, 0};
3248	static unsigned char u3[9] = { 0x80,1,6,4,0x09,00,0x0e,0x01,0x02 };
3249
3250	lvdmode=inb(wkport + 0x1b) >> 7;
3251
3252	for (i = 0; i < 16; i++) {
3253		m = 1;
3254		m = m << i;
3255		if ((m & dev->active_id[c]) != 0) {
3256			continue;
3257		}
3258		if (i == dev->host_id[c]) {
3259			printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_id[c]);
3260			continue;
3261		}
3262		tmport = wkport + 0x1b;
3263		outb(0x01, tmport);
3264		tmport = wkport + 0x01;
3265		outb(0x08, tmport++);
3266		outb(0x7f, tmport++);
3267		outb(satn[0], tmport++);
3268		outb(satn[1], tmport++);
3269		outb(satn[2], tmport++);
3270		outb(satn[3], tmport++);
3271		outb(satn[4], tmport++);
3272		outb(satn[5], tmport++);
3273		tmport += 0x06;
3274		outb(0, tmport);
3275		tmport += 0x02;
3276		outb(dev->id[c][i].devsp, tmport++);
3277
3278		outb(0, tmport++);
3279		outb(satn[6], tmport++);
3280		outb(satn[7], tmport++);
3281		j = i;
3282		if ((j & 0x08) != 0) {
3283			j = (j & 0x07) | 0x40;
3284		}
3285		outb(j, tmport);
3286		tmport += 0x03;
3287		outb(satn[8], tmport);
3288		tmport += 0x07;
3289
3290		while ((inb(tmport) & 0x80) == 0x00)
3291			cpu_relax();
3292		tmport -= 0x08;
3293		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
3294			continue;
3295		}
3296		while (inb(tmport) != 0x8e)
3297			cpu_relax();
3298		dev->active_id[c] |= m;
3299
3300		tmport = wkport + 0x10;
3301		outb(0x30, tmport);
3302		tmport = wkport + 0x14;
3303		outb(0x00, tmport);
3304
3305phase_cmd:
3306		tmport = wkport + 0x18;
3307		outb(0x08, tmport);
3308		tmport += 0x07;
3309		while ((inb(tmport) & 0x80) == 0x00)
3310			cpu_relax();
3311		tmport -= 0x08;
3312		j = inb(tmport);
3313		if (j != 0x16) {
3314			tmport = wkport + 0x10;
3315			outb(0x41, tmport);
3316			goto phase_cmd;
3317		}
3318sel_ok:
3319		tmport = wkport + 0x03;
3320		outb(inqd[0], tmport++);
3321		outb(inqd[1], tmport++);
3322		outb(inqd[2], tmport++);
3323		outb(inqd[3], tmport++);
3324		outb(inqd[4], tmport++);
3325		outb(inqd[5], tmport);
3326		tmport += 0x07;
3327		outb(0, tmport);
3328		tmport += 0x02;
3329		outb(dev->id[c][i].devsp, tmport++);
3330		outb(0, tmport++);
3331		outb(inqd[6], tmport++);
3332		outb(inqd[7], tmport++);
3333		tmport += 0x03;
3334		outb(inqd[8], tmport);
3335		tmport += 0x07;
3336		while ((inb(tmport) & 0x80) == 0x00)
3337			cpu_relax();
3338		tmport -= 0x08;
3339		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
3340			continue;
3341		}
3342		while (inb(tmport) != 0x8e)
3343			cpu_relax();
3344		tmport = wkport + 0x1b;
3345		outb(0x00, tmport);
3346		tmport = wkport + 0x18;
3347		outb(0x08, tmport);
3348		tmport += 0x07;
3349		j = 0;
3350rd_inq_data:
3351		k = inb(tmport);
3352		if ((k & 0x01) != 0) {
3353			tmport -= 0x06;
3354			mbuf[j++] = inb(tmport);
3355			tmport += 0x06;
3356			goto rd_inq_data;
3357		}
3358		if ((k & 0x80) == 0) {
3359			goto rd_inq_data;
3360		}
3361		tmport -= 0x08;
3362		j = inb(tmport);
3363		if (j == 0x16) {
3364			goto inq_ok;
3365		}
3366		tmport = wkport + 0x10;
3367		outb(0x46, tmport);
3368		tmport += 0x02;
3369		outb(0, tmport++);
3370		outb(0, tmport++);
3371		outb(0, tmport++);
3372		tmport += 0x03;
3373		outb(0x08, tmport);
3374		tmport += 0x07;
3375		while ((inb(tmport) & 0x80) == 0x00)
3376			cpu_relax();
3377		tmport -= 0x08;
3378		if (inb(tmport) != 0x16) {
3379			goto sel_ok;
3380		}
3381inq_ok:
3382		mbuf[36] = 0;
3383		printk( KERN_INFO"         ID: %2d  %s\n", i, &mbuf[8]);
3384		dev->id[c][i].devtype = mbuf[0];
3385		rmb = mbuf[1];
3386		n = mbuf[7];
3387		if ((mbuf[7] & 0x60) == 0) {
3388			goto not_wide;
3389		}
3390		if ((i < 8) && ((dev->global_map[c] & 0x20) == 0)) {
3391			goto not_wide;
3392		}
3393		if (lvdmode == 0) {
3394		   goto chg_wide;
3395		}
3396		if (dev->sp[c][i] != 0x04) {	// force u2
3397		   goto chg_wide;
3398		}
3399
3400		tmport = wkport + 0x1b;
3401		outb(0x01, tmport);
3402		tmport = wkport + 0x03;
3403		outb(satn[0], tmport++);
3404		outb(satn[1], tmport++);
3405		outb(satn[2], tmport++);
3406		outb(satn[3], tmport++);
3407		outb(satn[4], tmport++);
3408		outb(satn[5], tmport++);
3409		tmport += 0x06;
3410		outb(0, tmport);
3411		tmport += 0x02;
3412		outb(dev->id[c][i].devsp, tmport++);
3413		outb(0, tmport++);
3414		outb(satn[6], tmport++);
3415		outb(satn[7], tmport++);
3416		tmport += 0x03;
3417		outb(satn[8], tmport);
3418		tmport += 0x07;
3419
3420		while ((inb(tmport) & 0x80) == 0x00)
3421			cpu_relax();
3422		tmport -= 0x08;
3423		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
3424			continue;
3425		}
3426		while (inb(tmport) != 0x8e)
3427			cpu_relax();
3428try_u3:
3429		j = 0;
3430		tmport = wkport + 0x14;
3431		outb(0x09, tmport);
3432		tmport += 0x04;
3433		outb(0x20, tmport);
3434		tmport += 0x07;
3435
3436		while ((inb(tmport) & 0x80) == 0) {
3437			if ((inb(tmport) & 0x01) != 0) {
3438				tmport -= 0x06;
3439				outb(u3[j++], tmport);
3440				tmport += 0x06;
3441			}
3442			cpu_relax();
3443		}
3444		tmport -= 0x08;
3445		while ((inb(tmport) & 0x80) == 0x00)
3446			cpu_relax();
3447		j = inb(tmport) & 0x0f;
3448		if (j == 0x0f) {
3449			goto u3p_in;
3450		}
3451		if (j == 0x0a) {
3452			goto u3p_cmd;
3453		}
3454		if (j == 0x0e) {
3455			goto try_u3;
3456		}
3457		continue;
3458u3p_out:
3459		tmport = wkport + 0x18;
3460		outb(0x20, tmport);
3461		tmport += 0x07;
3462		while ((inb(tmport) & 0x80) == 0) {
3463			if ((inb(tmport) & 0x01) != 0) {
3464				tmport -= 0x06;
3465				outb(0, tmport);
3466				tmport += 0x06;
3467			}
3468			cpu_relax();
3469		}
3470		tmport -= 0x08;
3471		j = inb(tmport) & 0x0f;
3472		if (j == 0x0f) {
3473			goto u3p_in;
3474		}
3475		if (j == 0x0a) {
3476			goto u3p_cmd;
3477		}
3478		if (j == 0x0e) {
3479			goto u3p_out;
3480		}
3481		continue;
3482u3p_in:
3483		tmport = wkport + 0x14;
3484		outb(0x09, tmport);
3485		tmport += 0x04;
3486		outb(0x20, tmport);
3487		tmport += 0x07;
3488		k = 0;
3489u3p_in1:
3490		j = inb(tmport);
3491		if ((j & 0x01) != 0) {
3492			tmport -= 0x06;
3493			mbuf[k++] = inb(tmport);
3494			tmport += 0x06;
3495			goto u3p_in1;
3496		}
3497		if ((j & 0x80) == 0x00) {
3498			goto u3p_in1;
3499		}
3500		tmport -= 0x08;
3501		j = inb(tmport) & 0x0f;
3502		if (j == 0x0f) {
3503			goto u3p_in;
3504		}
3505		if (j == 0x0a) {
3506			goto u3p_cmd;
3507		}
3508		if (j == 0x0e) {
3509			goto u3p_out;
3510		}
3511		continue;
3512u3p_cmd:
3513		tmport = wkport + 0x10;
3514		outb(0x30, tmport);
3515		tmport = wkport + 0x14;
3516		outb(0x00, tmport);
3517		tmport += 0x04;
3518		outb(0x08, tmport);
3519		tmport += 0x07;
3520		while ((inb(tmport) & 0x80) == 0x00);
3521		tmport -= 0x08;
3522		j = inb(tmport);
3523		if (j != 0x16) {
3524			if (j == 0x4e) {
3525				goto u3p_out;
3526			}
3527			continue;
3528		}
3529		if (mbuf[0] != 0x01) {
3530			goto chg_wide;
3531		}
3532		if (mbuf[1] != 0x06) {
3533			goto chg_wide;
3534		}
3535		if (mbuf[2] != 0x04) {
3536			goto chg_wide;
3537		}
3538		if (mbuf[3] == 0x09) {
3539			m = 1;
3540			m = m << i;
3541			dev->wide_id[c] |= m;
3542			dev->id[c][i].devsp = 0xce;
3543#ifdef ED_DBGP
3544			printk("dev->id[%2d][%2d].devsp = %2x\n",c,i,dev->id[c][i].devsp);
3545#endif
3546			continue;
3547		}
3548chg_wide:
3549		tmport = wkport + 0x1b;
3550		outb(0x01, tmport);
3551		tmport = wkport + 0x03;
3552		outb(satn[0], tmport++);
3553		outb(satn[1], tmport++);
3554		outb(satn[2], tmport++);
3555		outb(satn[3], tmport++);
3556		outb(satn[4], tmport++);
3557		outb(satn[5], tmport++);
3558		tmport += 0x06;
3559		outb(0, tmport);
3560		tmport += 0x02;
3561		outb(dev->id[c][i].devsp, tmport++);
3562		outb(0, tmport++);
3563		outb(satn[6], tmport++);
3564		outb(satn[7], tmport++);
3565		tmport += 0x03;
3566		outb(satn[8], tmport);
3567		tmport += 0x07;
3568
3569		while ((inb(tmport) & 0x80) == 0x00)
3570			cpu_relax();
3571		tmport -= 0x08;
3572		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
3573			continue;
3574		}
3575		while (inb(tmport) != 0x8e)
3576			cpu_relax();
3577try_wide:
3578		j = 0;
3579		tmport = wkport + 0x14;
3580		outb(0x05, tmport);
3581		tmport += 0x04;
3582		outb(0x20, tmport);
3583		tmport += 0x07;
3584
3585		while ((inb(tmport) & 0x80) == 0) {
3586			if ((inb(tmport) & 0x01) != 0) {
3587				tmport -= 0x06;
3588				outb(wide[j++], tmport);
3589				tmport += 0x06;
3590			}
3591			cpu_relax();
3592		}
3593		tmport -= 0x08;
3594		while ((inb(tmport) & 0x80) == 0x00)
3595			cpu_relax();
3596		j = inb(tmport) & 0x0f;
3597		if (j == 0x0f) {
3598			goto widep_in;
3599		}
3600		if (j == 0x0a) {
3601			goto widep_cmd;
3602		}
3603		if (j == 0x0e) {
3604			goto try_wide;
3605		}
3606		continue;
3607widep_out:
3608		tmport = wkport + 0x18;
3609		outb(0x20, tmport);
3610		tmport += 0x07;
3611		while ((inb(tmport) & 0x80) == 0) {
3612			if ((inb(tmport) & 0x01) != 0) {
3613				tmport -= 0x06;
3614				outb(0, tmport);
3615				tmport += 0x06;
3616			}
3617			cpu_relax();
3618		}
3619		tmport -= 0x08;
3620		j = inb(tmport) & 0x0f;
3621		if (j == 0x0f) {
3622			goto widep_in;
3623		}
3624		if (j == 0x0a) {
3625			goto widep_cmd;
3626		}
3627		if (j == 0x0e) {
3628			goto widep_out;
3629		}
3630		continue;
3631widep_in:
3632		tmport = wkport + 0x14;
3633		outb(0xff, tmport);
3634		tmport += 0x04;
3635		outb(0x20, tmport);
3636		tmport += 0x07;
3637		k = 0;
3638widep_in1:
3639		j = inb(tmport);
3640		if ((j & 0x01) != 0) {
3641			tmport -= 0x06;
3642			mbuf[k++] = inb(tmport);
3643			tmport += 0x06;
3644			goto widep_in1;
3645		}
3646		if ((j & 0x80) == 0x00) {
3647			goto widep_in1;
3648		}
3649		tmport -= 0x08;
3650		j = inb(tmport) & 0x0f;
3651		if (j == 0x0f) {
3652			goto widep_in;
3653		}
3654		if (j == 0x0a) {
3655			goto widep_cmd;
3656		}
3657		if (j == 0x0e) {
3658			goto widep_out;
3659		}
3660		continue;
3661widep_cmd:
3662		tmport = wkport + 0x10;
3663		outb(0x30, tmport);
3664		tmport = wkport + 0x14;
3665		outb(0x00, tmport);
3666		tmport += 0x04;
3667		outb(0x08, tmport);
3668		tmport += 0x07;
3669		while ((inb(tmport) & 0x80) == 0x00)
3670			cpu_relax();
3671		tmport -= 0x08;
3672		j = inb(tmport);
3673		if (j != 0x16) {
3674			if (j == 0x4e) {
3675				goto widep_out;
3676			}
3677			continue;
3678		}
3679		if (mbuf[0] != 0x01) {
3680			goto not_wide;
3681		}
3682		if (mbuf[1] != 0x02) {
3683			goto not_wide;
3684		}
3685		if (mbuf[2] != 0x03) {
3686			goto not_wide;
3687		}
3688		if (mbuf[3] != 0x01) {
3689			goto not_wide;
3690		}
3691		m = 1;
3692		m = m << i;
3693		dev->wide_id[c] |= m;
3694not_wide:
3695		if ((dev->id[c][i].devtype == 0x00) || (dev->id[c][i].devtype == 0x07) ||
3696		    ((dev->id[c][i].devtype == 0x05) && ((n & 0x10) != 0))) {
3697			m = 1;
3698			m = m << i;
3699			if ((dev->async[c] & m) != 0) {
3700			   goto set_sync;
3701			}
3702		}
3703		continue;
3704set_sync:
3705		if (dev->sp[c][i] == 0x02) {
3706		   synu[4]=0x0c;
3707		   synuw[4]=0x0c;
3708		} else {
3709		   if (dev->sp[c][i] >= 0x03) {
3710		      synu[4]=0x0a;
3711		      synuw[4]=0x0a;
3712		   }
3713		}
3714		tmport = wkport + 0x1b;
3715		j = 0;
3716		if ((m & dev->wide_id[c]) != 0) {
3717			j |= 0x01;
3718		}
3719		outb(j, tmport);
3720		tmport = wkport + 0x03;
3721		outb(satn[0], tmport++);
3722		outb(satn[1], tmport++);
3723		outb(satn[2], tmport++);
3724		outb(satn[3], tmport++);
3725		outb(satn[4], tmport++);
3726		outb(satn[5], tmport++);
3727		tmport += 0x06;
3728		outb(0, tmport);
3729		tmport += 0x02;
3730		outb(dev->id[c][i].devsp, tmport++);
3731		outb(0, tmport++);
3732		outb(satn[6], tmport++);
3733		outb(satn[7], tmport++);
3734		tmport += 0x03;
3735		outb(satn[8], tmport);
3736		tmport += 0x07;
3737
3738		while ((inb(tmport) & 0x80) == 0x00)
3739			cpu_relax();
3740		tmport -= 0x08;
3741		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
3742			continue;
3743		}
3744		while (inb(tmport) != 0x8e)
3745			cpu_relax();
3746try_sync:
3747		j = 0;
3748		tmport = wkport + 0x14;
3749		outb(0x06, tmport);
3750		tmport += 0x04;
3751		outb(0x20, tmport);
3752		tmport += 0x07;
3753
3754		while ((inb(tmport) & 0x80) == 0) {
3755			if ((inb(tmport) & 0x01) != 0) {
3756				tmport -= 0x06;
3757				if ((m & dev->wide_id[c]) != 0) {
3758					if ((m & dev->ultra_map[c]) != 0) {
3759						outb(synuw[j++], tmport);
3760					} else {
3761						outb(synw[j++], tmport);
3762					}
3763				} else {
3764					if ((m & dev->ultra_map[c]) != 0) {
3765						outb(synu[j++], tmport);
3766					} else {
3767						outb(synn[j++], tmport);
3768					}
3769				}
3770				tmport += 0x06;
3771			}
3772		}
3773		tmport -= 0x08;
3774		while ((inb(tmport) & 0x80) == 0x00)
3775			cpu_relax();
3776		j = inb(tmport) & 0x0f;
3777		if (j == 0x0f) {
3778			goto phase_ins;
3779		}
3780		if (j == 0x0a) {
3781			goto phase_cmds;
3782		}
3783		if (j == 0x0e) {
3784			goto try_sync;
3785		}
3786		continue;
3787phase_outs:
3788		tmport = wkport + 0x18;
3789		outb(0x20, tmport);
3790		tmport += 0x07;
3791		while ((inb(tmport) & 0x80) == 0x00) {
3792			if ((inb(tmport) & 0x01) != 0x00) {
3793				tmport -= 0x06;
3794				outb(0x00, tmport);
3795				tmport += 0x06;
3796			}
3797			cpu_relax();
3798		}
3799		tmport -= 0x08;
3800		j = inb(tmport);
3801		if (j == 0x85) {
3802			goto tar_dcons;
3803		}
3804		j &= 0x0f;
3805		if (j == 0x0f) {
3806			goto phase_ins;
3807		}
3808		if (j == 0x0a) {
3809			goto phase_cmds;
3810		}
3811		if (j == 0x0e) {
3812			goto phase_outs;
3813		}
3814		continue;
3815phase_ins:
3816		tmport = wkport + 0x14;
3817		outb(0x06, tmport);
3818		tmport += 0x04;
3819		outb(0x20, tmport);
3820		tmport += 0x07;
3821		k = 0;
3822phase_ins1:
3823		j = inb(tmport);
3824		if ((j & 0x01) != 0x00) {
3825			tmport -= 0x06;
3826			mbuf[k++] = inb(tmport);
3827			tmport += 0x06;
3828			goto phase_ins1;
3829		}
3830		if ((j & 0x80) == 0x00) {
3831			goto phase_ins1;
3832		}
3833		tmport -= 0x08;
3834		while ((inb(tmport) & 0x80) == 0x00);
3835		j = inb(tmport);
3836		if (j == 0x85) {
3837			goto tar_dcons;
3838		}
3839		j &= 0x0f;
3840		if (j == 0x0f) {
3841			goto phase_ins;
3842		}
3843		if (j == 0x0a) {
3844			goto phase_cmds;
3845		}
3846		if (j == 0x0e) {
3847			goto phase_outs;
3848		}
3849		continue;
3850phase_cmds:
3851		tmport = wkport + 0x10;
3852		outb(0x30, tmport);
3853tar_dcons:
3854		tmport = wkport + 0x14;
3855		outb(0x00, tmport);
3856		tmport += 0x04;
3857		outb(0x08, tmport);
3858		tmport += 0x07;
3859		while ((inb(tmport) & 0x80) == 0x00)
3860			cpu_relax();
3861		tmport -= 0x08;
3862		j = inb(tmport);
3863		if (j != 0x16) {
3864			continue;
3865		}
3866		if (mbuf[0] != 0x01) {
3867			continue;
3868		}
3869		if (mbuf[1] != 0x03) {
3870			continue;
3871		}
3872		if (mbuf[4] == 0x00) {
3873			continue;
3874		}
3875		if (mbuf[3] > 0x64) {
3876			continue;
3877		}
3878		if (mbuf[4] > 0x0e) {
3879			mbuf[4] = 0x0e;
3880		}
3881		dev->id[c][i].devsp = mbuf[4];
3882		if (mbuf[3] < 0x0c){
3883			j = 0xb0;
3884			goto set_syn_ok;
3885		}
3886		if ((mbuf[3] < 0x0d) && (rmb == 0)) {
3887			j = 0xa0;
3888			goto set_syn_ok;
3889		}
3890		if (mbuf[3] < 0x1a) {
3891			j = 0x20;
3892			goto set_syn_ok;
3893		}
3894		if (mbuf[3] < 0x33) {
3895			j = 0x40;
3896			goto set_syn_ok;
3897		}
3898		if (mbuf[3] < 0x4c) {
3899			j = 0x50;
3900			goto set_syn_ok;
3901		}
3902		j = 0x60;
3903	      set_syn_ok:
3904		dev->id[c][i].devsp = (dev->id[c][i].devsp & 0x0f) | j;
3905#ifdef ED_DBGP
3906		printk("dev->id[%2d][%2d].devsp = %2x\n",c,i,dev->id[c][i].devsp);
3907#endif
3908	}
3909	tmport = wkport + 0x16;
3910	outb(0x80, tmport);
3911}
3912
3913module_init(atp870u_init);
3914module_exit(atp870u_exit);
3915
3916