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	/*
1177	 * The funny division into multiple delays is to accomodate
1178	 * arches like ARM where udelay() multiplies its argument by
1179	 * a large number to initialize a loop counter.  To avoid
1180	 * overflow, the maximum supported udelay is 2000 microseconds.
1181	 *
1182	 * XXX it would be more polite to find a way to use msleep()
1183	 */
1184	mdelay(2);
1185	udelay(48);
1186	if ((inb(tmport) & 0x80) == 0x00) {	/* bsy ? */
1187		outw(0, tmport--);
1188		outb(0, tmport);
1189		tmport = dev->ioport[0] + 0x15;
1190		outb(0, tmport);
1191		tmport += 0x03;
1192		outb(0x09, tmport);
1193		tmport += 0x07;
1194		while ((inb(tmport) & 0x80) == 0)
1195			cpu_relax();
1196		tmport -= 0x08;
1197		inb(tmport);
1198		return;
1199	}
1200	val &= 0x00ff;		/* synchronization  */
1201	val |= 0x3f00;
1202	fun_scam(dev, &val);
1203	outb(3, 0x80);
1204	val &= 0x00ff;		/* isolation        */
1205	val |= 0x2000;
1206	fun_scam(dev, &val);
1207	outb(4, 0x80);
1208	i = 8;
1209	j = 0;
1210TCM_ID:
1211	if ((inw(tmport) & 0x2000) == 0) {
1212		goto TCM_ID;
1213	}
1214	outb(5, 0x80);
1215	val &= 0x00ff;		/* get ID_STRING */
1216	val |= 0x2000;
1217	k = fun_scam(dev, &val);
1218	if ((k & 0x03) == 0) {
1219		goto TCM_5;
1220	}
1221	mbuf[j] <<= 0x01;
1222	mbuf[j] &= 0xfe;
1223	if ((k & 0x02) != 0) {
1224		mbuf[j] |= 0x01;
1225	}
1226	i--;
1227	if (i > 0) {
1228		goto TCM_ID;
1229	}
1230	j++;
1231	i = 8;
1232	goto TCM_ID;
1233
1234TCM_5:			/* isolation complete..  */
1235/*    mbuf[32]=0;
1236	printk(" \n%x %x %x %s\n ",assignid_map,mbuf[0],mbuf[1],&mbuf[2]); */
1237	i = 15;
1238	j = mbuf[0];
1239	if ((j & 0x20) != 0) {	/* bit5=1:ID up to 7      */
1240		i = 7;
1241	}
1242	if ((j & 0x06) == 0) {	/* IDvalid?             */
1243		goto G2Q5;
1244	}
1245	k = mbuf[1];
1246small_id:
1247	m = 1;
1248	m <<= k;
1249	if ((m & assignid_map) == 0) {
1250		goto G2Q_QUIN;
1251	}
1252	if (k > 0) {
1253		k--;
1254		goto small_id;
1255	}
1256G2Q5:			/* srch from max acceptable ID#  */
1257	k = i;			/* max acceptable ID#            */
1258G2Q_LP:
1259	m = 1;
1260	m <<= k;
1261	if ((m & assignid_map) == 0) {
1262		goto G2Q_QUIN;
1263	}
1264	if (k > 0) {
1265		k--;
1266		goto G2Q_LP;
1267	}
1268G2Q_QUIN:		/* k=binID#,       */
1269	assignid_map |= m;
1270	if (k < 8) {
1271		quintet[0] = 0x38;	/* 1st dft ID<8    */
1272	} else {
1273		quintet[0] = 0x31;	/* 1st  ID>=8      */
1274	}
1275	k &= 0x07;
1276	quintet[1] = g2q_tab[k];
1277
1278	val &= 0x00ff;		/* AssignID 1stQuintet,AH=001xxxxx  */
1279	m = quintet[0] << 8;
1280	val |= m;
1281	fun_scam(dev, &val);
1282	val &= 0x00ff;		/* AssignID 2ndQuintet,AH=001xxxxx */
1283	m = quintet[1] << 8;
1284	val |= m;
1285	fun_scam(dev, &val);
1286
1287	goto TCM_SYNC;
1288
1289}
1290
1291static void is870(struct atp_unit *dev, unsigned int wkport)
1292{
1293	unsigned int tmport;
1294	unsigned char i, j, k, rmb, n;
1295	unsigned short int m;
1296	static unsigned char mbuf[512];
1297	static unsigned char satn[9] = { 0, 0, 0, 0, 0, 0, 0, 6, 6 };
1298	static unsigned char inqd[9] = { 0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6 };
1299	static unsigned char synn[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
1300	static unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0c, 0x0e };
1301	static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x0c, 0x07 };
1302	static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
1303
1304	tmport = wkport + 0x3a;
1305	outb((unsigned char) (inb(tmport) | 0x10), tmport);
1306
1307	for (i = 0; i < 16; i++) {
1308		if ((dev->chip_ver != 4) && (i > 7)) {
1309			break;
1310		}
1311		m = 1;
1312		m = m << i;
1313		if ((m & dev->active_id[0]) != 0) {
1314			continue;
1315		}
1316		if (i == dev->host_id[0]) {
1317			printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_id[0]);
1318			continue;
1319		}
1320		tmport = wkport + 0x1b;
1321		if (dev->chip_ver == 4) {
1322			outb(0x01, tmport);
1323		} else {
1324			outb(0x00, tmport);
1325		}
1326		tmport = wkport + 1;
1327		outb(0x08, tmport++);
1328		outb(0x7f, tmport++);
1329		outb(satn[0], tmport++);
1330		outb(satn[1], tmport++);
1331		outb(satn[2], tmport++);
1332		outb(satn[3], tmport++);
1333		outb(satn[4], tmport++);
1334		outb(satn[5], tmport++);
1335		tmport += 0x06;
1336		outb(0, tmport);
1337		tmport += 0x02;
1338		outb(dev->id[0][i].devsp, tmport++);
1339		outb(0, tmport++);
1340		outb(satn[6], tmport++);
1341		outb(satn[7], tmport++);
1342		j = i;
1343		if ((j & 0x08) != 0) {
1344			j = (j & 0x07) | 0x40;
1345		}
1346		outb(j, tmport);
1347		tmport += 0x03;
1348		outb(satn[8], tmport);
1349		tmport += 0x07;
1350
1351		while ((inb(tmport) & 0x80) == 0x00)
1352			cpu_relax();
1353
1354		tmport -= 0x08;
1355		if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
1356			continue;
1357
1358		while (inb(tmport) != 0x8e)
1359			cpu_relax();
1360
1361		dev->active_id[0] |= m;
1362
1363		tmport = wkport + 0x10;
1364		outb(0x30, tmport);
1365		tmport = wkport + 0x04;
1366		outb(0x00, tmport);
1367
1368phase_cmd:
1369		tmport = wkport + 0x18;
1370		outb(0x08, tmport);
1371		tmport += 0x07;
1372		while ((inb(tmport) & 0x80) == 0x00)
1373			cpu_relax();
1374		tmport -= 0x08;
1375		j = inb(tmport);
1376		if (j != 0x16) {
1377			tmport = wkport + 0x10;
1378			outb(0x41, tmport);
1379			goto phase_cmd;
1380		}
1381sel_ok:
1382		tmport = wkport + 3;
1383		outb(inqd[0], tmport++);
1384		outb(inqd[1], tmport++);
1385		outb(inqd[2], tmport++);
1386		outb(inqd[3], tmport++);
1387		outb(inqd[4], tmport++);
1388		outb(inqd[5], tmport);
1389		tmport += 0x07;
1390		outb(0, tmport);
1391		tmport += 0x02;
1392		outb(dev->id[0][i].devsp, tmport++);
1393		outb(0, tmport++);
1394		outb(inqd[6], tmport++);
1395		outb(inqd[7], tmport++);
1396		tmport += 0x03;
1397		outb(inqd[8], tmport);
1398		tmport += 0x07;
1399
1400		while ((inb(tmport) & 0x80) == 0x00)
1401			cpu_relax();
1402
1403		tmport -= 0x08;
1404		if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
1405			continue;
1406
1407		while (inb(tmport) != 0x8e)
1408			cpu_relax();
1409
1410		tmport = wkport + 0x1b;
1411		if (dev->chip_ver == 4)
1412			outb(0x00, tmport);
1413
1414		tmport = wkport + 0x18;
1415		outb(0x08, tmport);
1416		tmport += 0x07;
1417		j = 0;
1418rd_inq_data:
1419		k = inb(tmport);
1420		if ((k & 0x01) != 0) {
1421			tmport -= 0x06;
1422			mbuf[j++] = inb(tmport);
1423			tmport += 0x06;
1424			goto rd_inq_data;
1425		}
1426		if ((k & 0x80) == 0) {
1427			goto rd_inq_data;
1428		}
1429		tmport -= 0x08;
1430		j = inb(tmport);
1431		if (j == 0x16) {
1432			goto inq_ok;
1433		}
1434		tmport = wkport + 0x10;
1435		outb(0x46, tmport);
1436		tmport += 0x02;
1437		outb(0, tmport++);
1438		outb(0, tmport++);
1439		outb(0, tmport++);
1440		tmport += 0x03;
1441		outb(0x08, tmport);
1442		tmport += 0x07;
1443
1444		while ((inb(tmport) & 0x80) == 0x00)
1445			cpu_relax();
1446
1447		tmport -= 0x08;
1448		if (inb(tmport) != 0x16) {
1449			goto sel_ok;
1450		}
1451inq_ok:
1452		mbuf[36] = 0;
1453		printk(KERN_INFO "         ID: %2d  %s\n", i, &mbuf[8]);
1454		dev->id[0][i].devtype = mbuf[0];
1455		rmb = mbuf[1];
1456		n = mbuf[7];
1457		if (dev->chip_ver != 4) {
1458			goto not_wide;
1459		}
1460		if ((mbuf[7] & 0x60) == 0) {
1461			goto not_wide;
1462		}
1463		if ((dev->global_map[0] & 0x20) == 0) {
1464			goto not_wide;
1465		}
1466		tmport = wkport + 0x1b;
1467		outb(0x01, tmport);
1468		tmport = wkport + 3;
1469		outb(satn[0], tmport++);
1470		outb(satn[1], tmport++);
1471		outb(satn[2], tmport++);
1472		outb(satn[3], tmport++);
1473		outb(satn[4], tmport++);
1474		outb(satn[5], tmport++);
1475		tmport += 0x06;
1476		outb(0, tmport);
1477		tmport += 0x02;
1478		outb(dev->id[0][i].devsp, tmport++);
1479		outb(0, tmport++);
1480		outb(satn[6], tmport++);
1481		outb(satn[7], tmport++);
1482		tmport += 0x03;
1483		outb(satn[8], tmport);
1484		tmport += 0x07;
1485
1486		while ((inb(tmport) & 0x80) == 0x00)
1487			cpu_relax();
1488
1489		tmport -= 0x08;
1490		if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
1491			continue;
1492
1493		while (inb(tmport) != 0x8e)
1494			cpu_relax();
1495
1496try_wide:
1497		j = 0;
1498		tmport = wkport + 0x14;
1499		outb(0x05, tmport);
1500		tmport += 0x04;
1501		outb(0x20, tmport);
1502		tmport += 0x07;
1503
1504		while ((inb(tmport) & 0x80) == 0) {
1505			if ((inb(tmport) & 0x01) != 0) {
1506				tmport -= 0x06;
1507				outb(wide[j++], tmport);
1508				tmport += 0x06;
1509			}
1510		}
1511		tmport -= 0x08;
1512
1513		while ((inb(tmport) & 0x80) == 0x00)
1514			cpu_relax();
1515
1516		j = inb(tmport) & 0x0f;
1517		if (j == 0x0f) {
1518			goto widep_in;
1519		}
1520		if (j == 0x0a) {
1521			goto widep_cmd;
1522		}
1523		if (j == 0x0e) {
1524			goto try_wide;
1525		}
1526		continue;
1527widep_out:
1528		tmport = wkport + 0x18;
1529		outb(0x20, tmport);
1530		tmport += 0x07;
1531		while ((inb(tmport) & 0x80) == 0) {
1532			if ((inb(tmport) & 0x01) != 0) {
1533				tmport -= 0x06;
1534				outb(0, tmport);
1535				tmport += 0x06;
1536			}
1537		}
1538		tmport -= 0x08;
1539		j = inb(tmport) & 0x0f;
1540		if (j == 0x0f) {
1541			goto widep_in;
1542		}
1543		if (j == 0x0a) {
1544			goto widep_cmd;
1545		}
1546		if (j == 0x0e) {
1547			goto widep_out;
1548		}
1549		continue;
1550widep_in:
1551		tmport = wkport + 0x14;
1552		outb(0xff, tmport);
1553		tmport += 0x04;
1554		outb(0x20, tmport);
1555		tmport += 0x07;
1556		k = 0;
1557widep_in1:
1558		j = inb(tmport);
1559		if ((j & 0x01) != 0) {
1560			tmport -= 0x06;
1561			mbuf[k++] = inb(tmport);
1562			tmport += 0x06;
1563			goto widep_in1;
1564		}
1565		if ((j & 0x80) == 0x00) {
1566			goto widep_in1;
1567		}
1568		tmport -= 0x08;
1569		j = inb(tmport) & 0x0f;
1570		if (j == 0x0f) {
1571			goto widep_in;
1572		}
1573		if (j == 0x0a) {
1574			goto widep_cmd;
1575		}
1576		if (j == 0x0e) {
1577			goto widep_out;
1578		}
1579		continue;
1580widep_cmd:
1581		tmport = wkport + 0x10;
1582		outb(0x30, tmport);
1583		tmport = wkport + 0x14;
1584		outb(0x00, tmport);
1585		tmport += 0x04;
1586		outb(0x08, tmport);
1587		tmport += 0x07;
1588
1589		while ((inb(tmport) & 0x80) == 0x00)
1590			cpu_relax();
1591
1592		tmport -= 0x08;
1593		j = inb(tmport);
1594		if (j != 0x16) {
1595			if (j == 0x4e) {
1596				goto widep_out;
1597			}
1598			continue;
1599		}
1600		if (mbuf[0] != 0x01) {
1601			goto not_wide;
1602		}
1603		if (mbuf[1] != 0x02) {
1604			goto not_wide;
1605		}
1606		if (mbuf[2] != 0x03) {
1607			goto not_wide;
1608		}
1609		if (mbuf[3] != 0x01) {
1610			goto not_wide;
1611		}
1612		m = 1;
1613		m = m << i;
1614		dev->wide_id[0] |= m;
1615not_wide:
1616		if ((dev->id[0][i].devtype == 0x00) || (dev->id[0][i].devtype == 0x07) || ((dev->id[0][i].devtype == 0x05) && ((n & 0x10) != 0))) {
1617			goto set_sync;
1618		}
1619		continue;
1620set_sync:
1621		tmport = wkport + 0x1b;
1622		j = 0;
1623		if ((m & dev->wide_id[0]) != 0) {
1624			j |= 0x01;
1625		}
1626		outb(j, tmport);
1627		tmport = wkport + 3;
1628		outb(satn[0], tmport++);
1629		outb(satn[1], tmport++);
1630		outb(satn[2], tmport++);
1631		outb(satn[3], tmport++);
1632		outb(satn[4], tmport++);
1633		outb(satn[5], tmport++);
1634		tmport += 0x06;
1635		outb(0, tmport);
1636		tmport += 0x02;
1637		outb(dev->id[0][i].devsp, tmport++);
1638		outb(0, tmport++);
1639		outb(satn[6], tmport++);
1640		outb(satn[7], tmport++);
1641		tmport += 0x03;
1642		outb(satn[8], tmport);
1643		tmport += 0x07;
1644
1645		while ((inb(tmport) & 0x80) == 0x00)
1646			cpu_relax();
1647
1648		tmport -= 0x08;
1649		if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
1650			continue;
1651
1652		while (inb(tmport) != 0x8e)
1653			cpu_relax();
1654
1655try_sync:
1656		j = 0;
1657		tmport = wkport + 0x14;
1658		outb(0x06, tmport);
1659		tmport += 0x04;
1660		outb(0x20, tmport);
1661		tmport += 0x07;
1662
1663		while ((inb(tmport) & 0x80) == 0) {
1664			if ((inb(tmport) & 0x01) != 0) {
1665				tmport -= 0x06;
1666				if ((m & dev->wide_id[0]) != 0) {
1667					outb(synw[j++], tmport);
1668				} else {
1669					if ((m & dev->ultra_map[0]) != 0) {
1670						outb(synu[j++], tmport);
1671					} else {
1672						outb(synn[j++], tmport);
1673					}
1674				}
1675				tmport += 0x06;
1676			}
1677		}
1678		tmport -= 0x08;
1679
1680		while ((inb(tmport) & 0x80) == 0x00)
1681			cpu_relax();
1682
1683		j = inb(tmport) & 0x0f;
1684		if (j == 0x0f) {
1685			goto phase_ins;
1686		}
1687		if (j == 0x0a) {
1688			goto phase_cmds;
1689		}
1690		if (j == 0x0e) {
1691			goto try_sync;
1692		}
1693		continue;
1694phase_outs:
1695		tmport = wkport + 0x18;
1696		outb(0x20, tmport);
1697		tmport += 0x07;
1698		while ((inb(tmport) & 0x80) == 0x00) {
1699			if ((inb(tmport) & 0x01) != 0x00) {
1700				tmport -= 0x06;
1701				outb(0x00, tmport);
1702				tmport += 0x06;
1703			}
1704		}
1705		tmport -= 0x08;
1706		j = inb(tmport);
1707		if (j == 0x85) {
1708			goto tar_dcons;
1709		}
1710		j &= 0x0f;
1711		if (j == 0x0f) {
1712			goto phase_ins;
1713		}
1714		if (j == 0x0a) {
1715			goto phase_cmds;
1716		}
1717		if (j == 0x0e) {
1718			goto phase_outs;
1719		}
1720		continue;
1721phase_ins:
1722		tmport = wkport + 0x14;
1723		outb(0xff, tmport);
1724		tmport += 0x04;
1725		outb(0x20, tmport);
1726		tmport += 0x07;
1727		k = 0;
1728phase_ins1:
1729		j = inb(tmport);
1730		if ((j & 0x01) != 0x00) {
1731			tmport -= 0x06;
1732			mbuf[k++] = inb(tmport);
1733			tmport += 0x06;
1734			goto phase_ins1;
1735		}
1736		if ((j & 0x80) == 0x00) {
1737			goto phase_ins1;
1738		}
1739		tmport -= 0x08;
1740
1741		while ((inb(tmport) & 0x80) == 0x00)
1742			cpu_relax();
1743
1744		j = inb(tmport);
1745		if (j == 0x85) {
1746			goto tar_dcons;
1747		}
1748		j &= 0x0f;
1749		if (j == 0x0f) {
1750			goto phase_ins;
1751		}
1752		if (j == 0x0a) {
1753			goto phase_cmds;
1754		}
1755		if (j == 0x0e) {
1756			goto phase_outs;
1757		}
1758		continue;
1759phase_cmds:
1760		tmport = wkport + 0x10;
1761		outb(0x30, tmport);
1762tar_dcons:
1763		tmport = wkport + 0x14;
1764		outb(0x00, tmport);
1765		tmport += 0x04;
1766		outb(0x08, tmport);
1767		tmport += 0x07;
1768
1769		while ((inb(tmport) & 0x80) == 0x00)
1770			cpu_relax();
1771
1772		tmport -= 0x08;
1773		j = inb(tmport);
1774		if (j != 0x16) {
1775			continue;
1776		}
1777		if (mbuf[0] != 0x01) {
1778			continue;
1779		}
1780		if (mbuf[1] != 0x03) {
1781			continue;
1782		}
1783		if (mbuf[4] == 0x00) {
1784			continue;
1785		}
1786		if (mbuf[3] > 0x64) {
1787			continue;
1788		}
1789		if (mbuf[4] > 0x0c) {
1790			mbuf[4] = 0x0c;
1791		}
1792		dev->id[0][i].devsp = mbuf[4];
1793		if ((mbuf[3] < 0x0d) && (rmb == 0)) {
1794			j = 0xa0;
1795			goto set_syn_ok;
1796		}
1797		if (mbuf[3] < 0x1a) {
1798			j = 0x20;
1799			goto set_syn_ok;
1800		}
1801		if (mbuf[3] < 0x33) {
1802			j = 0x40;
1803			goto set_syn_ok;
1804		}
1805		if (mbuf[3] < 0x4c) {
1806			j = 0x50;
1807			goto set_syn_ok;
1808		}
1809		j = 0x60;
1810set_syn_ok:
1811		dev->id[0][i].devsp = (dev->id[0][i].devsp & 0x0f) | j;
1812	}
1813	tmport = wkport + 0x3a;
1814	outb((unsigned char) (inb(tmport) & 0xef), tmport);
1815}
1816
1817static void is880(struct atp_unit *dev, unsigned int wkport)
1818{
1819	unsigned int tmport;
1820	unsigned char i, j, k, rmb, n, lvdmode;
1821	unsigned short int m;
1822	static unsigned char mbuf[512];
1823	static unsigned char satn[9] = { 0, 0, 0, 0, 0, 0, 0, 6, 6 };
1824	static unsigned char inqd[9] = { 0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6 };
1825	static unsigned char synn[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
1826	unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
1827	static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
1828	unsigned char synuw[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
1829	static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
1830	static unsigned char u3[9] = { 0x80, 1, 6, 4, 0x09, 00, 0x0e, 0x01, 0x02 };
1831
1832	lvdmode = inb(wkport + 0x3f) & 0x40;
1833
1834	for (i = 0; i < 16; i++) {
1835		m = 1;
1836		m = m << i;
1837		if ((m & dev->active_id[0]) != 0) {
1838			continue;
1839		}
1840		if (i == dev->host_id[0]) {
1841			printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_id[0]);
1842			continue;
1843		}
1844		tmport = wkport + 0x5b;
1845		outb(0x01, tmport);
1846		tmport = wkport + 0x41;
1847		outb(0x08, tmport++);
1848		outb(0x7f, tmport++);
1849		outb(satn[0], tmport++);
1850		outb(satn[1], tmport++);
1851		outb(satn[2], tmport++);
1852		outb(satn[3], tmport++);
1853		outb(satn[4], tmport++);
1854		outb(satn[5], tmport++);
1855		tmport += 0x06;
1856		outb(0, tmport);
1857		tmport += 0x02;
1858		outb(dev->id[0][i].devsp, tmport++);
1859		outb(0, tmport++);
1860		outb(satn[6], tmport++);
1861		outb(satn[7], tmport++);
1862		j = i;
1863		if ((j & 0x08) != 0) {
1864			j = (j & 0x07) | 0x40;
1865		}
1866		outb(j, tmport);
1867		tmport += 0x03;
1868		outb(satn[8], tmport);
1869		tmport += 0x07;
1870
1871		while ((inb(tmport) & 0x80) == 0x00)
1872			cpu_relax();
1873
1874		tmport -= 0x08;
1875		if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
1876			continue;
1877
1878		while (inb(tmport) != 0x8e)
1879			cpu_relax();
1880
1881		dev->active_id[0] |= m;
1882
1883		tmport = wkport + 0x50;
1884		outb(0x30, tmport);
1885		tmport = wkport + 0x54;
1886		outb(0x00, tmport);
1887
1888phase_cmd:
1889		tmport = wkport + 0x58;
1890		outb(0x08, tmport);
1891		tmport += 0x07;
1892
1893		while ((inb(tmport) & 0x80) == 0x00)
1894			cpu_relax();
1895
1896		tmport -= 0x08;
1897		j = inb(tmport);
1898		if (j != 0x16) {
1899			tmport = wkport + 0x50;
1900			outb(0x41, tmport);
1901			goto phase_cmd;
1902		}
1903sel_ok:
1904		tmport = wkport + 0x43;
1905		outb(inqd[0], tmport++);
1906		outb(inqd[1], tmport++);
1907		outb(inqd[2], tmport++);
1908		outb(inqd[3], tmport++);
1909		outb(inqd[4], tmport++);
1910		outb(inqd[5], tmport);
1911		tmport += 0x07;
1912		outb(0, tmport);
1913		tmport += 0x02;
1914		outb(dev->id[0][i].devsp, tmport++);
1915		outb(0, tmport++);
1916		outb(inqd[6], tmport++);
1917		outb(inqd[7], tmport++);
1918		tmport += 0x03;
1919		outb(inqd[8], tmport);
1920		tmport += 0x07;
1921
1922		while ((inb(tmport) & 0x80) == 0x00)
1923			cpu_relax();
1924
1925		tmport -= 0x08;
1926		if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
1927			continue;
1928
1929		while (inb(tmport) != 0x8e)
1930			cpu_relax();
1931
1932		tmport = wkport + 0x5b;
1933		outb(0x00, tmport);
1934		tmport = wkport + 0x58;
1935		outb(0x08, tmport);
1936		tmport += 0x07;
1937		j = 0;
1938rd_inq_data:
1939		k = inb(tmport);
1940		if ((k & 0x01) != 0) {
1941			tmport -= 0x06;
1942			mbuf[j++] = inb(tmport);
1943			tmport += 0x06;
1944			goto rd_inq_data;
1945		}
1946		if ((k & 0x80) == 0) {
1947			goto rd_inq_data;
1948		}
1949		tmport -= 0x08;
1950		j = inb(tmport);
1951		if (j == 0x16) {
1952			goto inq_ok;
1953		}
1954		tmport = wkport + 0x50;
1955		outb(0x46, tmport);
1956		tmport += 0x02;
1957		outb(0, tmport++);
1958		outb(0, tmport++);
1959		outb(0, tmport++);
1960		tmport += 0x03;
1961		outb(0x08, tmport);
1962		tmport += 0x07;
1963		while ((inb(tmport) & 0x80) == 0x00)
1964			cpu_relax();
1965
1966		tmport -= 0x08;
1967		if (inb(tmport) != 0x16)
1968			goto sel_ok;
1969
1970inq_ok:
1971		mbuf[36] = 0;
1972		printk(KERN_INFO "         ID: %2d  %s\n", i, &mbuf[8]);
1973		dev->id[0][i].devtype = mbuf[0];
1974		rmb = mbuf[1];
1975		n = mbuf[7];
1976		if ((mbuf[7] & 0x60) == 0) {
1977			goto not_wide;
1978		}
1979		if ((i < 8) && ((dev->global_map[0] & 0x20) == 0)) {
1980			goto not_wide;
1981		}
1982		if (lvdmode == 0) {
1983			goto chg_wide;
1984		}
1985		if (dev->sp[0][i] != 0x04)	// force u2
1986		{
1987			goto chg_wide;
1988		}
1989
1990		tmport = wkport + 0x5b;
1991		outb(0x01, tmport);
1992		tmport = wkport + 0x43;
1993		outb(satn[0], tmport++);
1994		outb(satn[1], tmport++);
1995		outb(satn[2], tmport++);
1996		outb(satn[3], tmport++);
1997		outb(satn[4], tmport++);
1998		outb(satn[5], tmport++);
1999		tmport += 0x06;
2000		outb(0, tmport);
2001		tmport += 0x02;
2002		outb(dev->id[0][i].devsp, tmport++);
2003		outb(0, tmport++);
2004		outb(satn[6], tmport++);
2005		outb(satn[7], tmport++);
2006		tmport += 0x03;
2007		outb(satn[8], tmport);
2008		tmport += 0x07;
2009
2010		while ((inb(tmport) & 0x80) == 0x00)
2011			cpu_relax();
2012
2013		tmport -= 0x08;
2014
2015		if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
2016			continue;
2017
2018		while (inb(tmport) != 0x8e)
2019			cpu_relax();
2020
2021try_u3:
2022		j = 0;
2023		tmport = wkport + 0x54;
2024		outb(0x09, tmport);
2025		tmport += 0x04;
2026		outb(0x20, tmport);
2027		tmport += 0x07;
2028
2029		while ((inb(tmport) & 0x80) == 0) {
2030			if ((inb(tmport) & 0x01) != 0) {
2031				tmport -= 0x06;
2032				outb(u3[j++], tmport);
2033				tmport += 0x06;
2034			}
2035		}
2036		tmport -= 0x08;
2037
2038		while ((inb(tmport) & 0x80) == 0x00)
2039			cpu_relax();
2040
2041		j = inb(tmport) & 0x0f;
2042		if (j == 0x0f) {
2043			goto u3p_in;
2044		}
2045		if (j == 0x0a) {
2046			goto u3p_cmd;
2047		}
2048		if (j == 0x0e) {
2049			goto try_u3;
2050		}
2051		continue;
2052u3p_out:
2053		tmport = wkport + 0x58;
2054		outb(0x20, tmport);
2055		tmport += 0x07;
2056		while ((inb(tmport) & 0x80) == 0) {
2057			if ((inb(tmport) & 0x01) != 0) {
2058				tmport -= 0x06;
2059				outb(0, tmport);
2060				tmport += 0x06;
2061			}
2062		}
2063		tmport -= 0x08;
2064		j = inb(tmport) & 0x0f;
2065		if (j == 0x0f) {
2066			goto u3p_in;
2067		}
2068		if (j == 0x0a) {
2069			goto u3p_cmd;
2070		}
2071		if (j == 0x0e) {
2072			goto u3p_out;
2073		}
2074		continue;
2075u3p_in:
2076		tmport = wkport + 0x54;
2077		outb(0x09, tmport);
2078		tmport += 0x04;
2079		outb(0x20, tmport);
2080		tmport += 0x07;
2081		k = 0;
2082u3p_in1:
2083		j = inb(tmport);
2084		if ((j & 0x01) != 0) {
2085			tmport -= 0x06;
2086			mbuf[k++] = inb(tmport);
2087			tmport += 0x06;
2088			goto u3p_in1;
2089		}
2090		if ((j & 0x80) == 0x00) {
2091			goto u3p_in1;
2092		}
2093		tmport -= 0x08;
2094		j = inb(tmport) & 0x0f;
2095		if (j == 0x0f) {
2096			goto u3p_in;
2097		}
2098		if (j == 0x0a) {
2099			goto u3p_cmd;
2100		}
2101		if (j == 0x0e) {
2102			goto u3p_out;
2103		}
2104		continue;
2105u3p_cmd:
2106		tmport = wkport + 0x50;
2107		outb(0x30, tmport);
2108		tmport = wkport + 0x54;
2109		outb(0x00, tmport);
2110		tmport += 0x04;
2111		outb(0x08, tmport);
2112		tmport += 0x07;
2113
2114		while ((inb(tmport) & 0x80) == 0x00)
2115			cpu_relax();
2116
2117		tmport -= 0x08;
2118		j = inb(tmport);
2119		if (j != 0x16) {
2120			if (j == 0x4e) {
2121				goto u3p_out;
2122			}
2123			continue;
2124		}
2125		if (mbuf[0] != 0x01) {
2126			goto chg_wide;
2127		}
2128		if (mbuf[1] != 0x06) {
2129			goto chg_wide;
2130		}
2131		if (mbuf[2] != 0x04) {
2132			goto chg_wide;
2133		}
2134		if (mbuf[3] == 0x09) {
2135			m = 1;
2136			m = m << i;
2137			dev->wide_id[0] |= m;
2138			dev->id[0][i].devsp = 0xce;
2139			continue;
2140		}
2141chg_wide:
2142		tmport = wkport + 0x5b;
2143		outb(0x01, tmport);
2144		tmport = wkport + 0x43;
2145		outb(satn[0], tmport++);
2146		outb(satn[1], tmport++);
2147		outb(satn[2], tmport++);
2148		outb(satn[3], tmport++);
2149		outb(satn[4], tmport++);
2150		outb(satn[5], tmport++);
2151		tmport += 0x06;
2152		outb(0, tmport);
2153		tmport += 0x02;
2154		outb(dev->id[0][i].devsp, tmport++);
2155		outb(0, tmport++);
2156		outb(satn[6], tmport++);
2157		outb(satn[7], tmport++);
2158		tmport += 0x03;
2159		outb(satn[8], tmport);
2160		tmport += 0x07;
2161
2162		while ((inb(tmport) & 0x80) == 0x00)
2163			cpu_relax();
2164
2165		tmport -= 0x08;
2166		if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
2167			continue;
2168
2169		while (inb(tmport) != 0x8e)
2170			cpu_relax();
2171
2172try_wide:
2173		j = 0;
2174		tmport = wkport + 0x54;
2175		outb(0x05, tmport);
2176		tmport += 0x04;
2177		outb(0x20, tmport);
2178		tmport += 0x07;
2179
2180		while ((inb(tmport) & 0x80) == 0) {
2181			if ((inb(tmport) & 0x01) != 0) {
2182				tmport -= 0x06;
2183				outb(wide[j++], tmport);
2184				tmport += 0x06;
2185			}
2186		}
2187		tmport -= 0x08;
2188		while ((inb(tmport) & 0x80) == 0x00)
2189			cpu_relax();
2190
2191		j = inb(tmport) & 0x0f;
2192		if (j == 0x0f) {
2193			goto widep_in;
2194		}
2195		if (j == 0x0a) {
2196			goto widep_cmd;
2197		}
2198		if (j == 0x0e) {
2199			goto try_wide;
2200		}
2201		continue;
2202widep_out:
2203		tmport = wkport + 0x58;
2204		outb(0x20, tmport);
2205		tmport += 0x07;
2206		while ((inb(tmport) & 0x80) == 0) {
2207			if ((inb(tmport) & 0x01) != 0) {
2208				tmport -= 0x06;
2209				outb(0, tmport);
2210				tmport += 0x06;
2211			}
2212		}
2213		tmport -= 0x08;
2214		j = inb(tmport) & 0x0f;
2215		if (j == 0x0f) {
2216			goto widep_in;
2217		}
2218		if (j == 0x0a) {
2219			goto widep_cmd;
2220		}
2221		if (j == 0x0e) {
2222			goto widep_out;
2223		}
2224		continue;
2225widep_in:
2226		tmport = wkport + 0x54;
2227		outb(0xff, tmport);
2228		tmport += 0x04;
2229		outb(0x20, tmport);
2230		tmport += 0x07;
2231		k = 0;
2232widep_in1:
2233		j = inb(tmport);
2234		if ((j & 0x01) != 0) {
2235			tmport -= 0x06;
2236			mbuf[k++] = inb(tmport);
2237			tmport += 0x06;
2238			goto widep_in1;
2239		}
2240		if ((j & 0x80) == 0x00) {
2241			goto widep_in1;
2242		}
2243		tmport -= 0x08;
2244		j = inb(tmport) & 0x0f;
2245		if (j == 0x0f) {
2246			goto widep_in;
2247		}
2248		if (j == 0x0a) {
2249			goto widep_cmd;
2250		}
2251		if (j == 0x0e) {
2252			goto widep_out;
2253		}
2254		continue;
2255widep_cmd:
2256		tmport = wkport + 0x50;
2257		outb(0x30, tmport);
2258		tmport = wkport + 0x54;
2259		outb(0x00, tmport);
2260		tmport += 0x04;
2261		outb(0x08, tmport);
2262		tmport += 0x07;
2263
2264		while ((inb(tmport) & 0x80) == 0x00)
2265			cpu_relax();
2266
2267		tmport -= 0x08;
2268		j = inb(tmport);
2269		if (j != 0x16) {
2270			if (j == 0x4e) {
2271				goto widep_out;
2272			}
2273			continue;
2274		}
2275		if (mbuf[0] != 0x01) {
2276			goto not_wide;
2277		}
2278		if (mbuf[1] != 0x02) {
2279			goto not_wide;
2280		}
2281		if (mbuf[2] != 0x03) {
2282			goto not_wide;
2283		}
2284		if (mbuf[3] != 0x01) {
2285			goto not_wide;
2286		}
2287		m = 1;
2288		m = m << i;
2289		dev->wide_id[0] |= m;
2290not_wide:
2291		if ((dev->id[0][i].devtype == 0x00) || (dev->id[0][i].devtype == 0x07) || ((dev->id[0][i].devtype == 0x05) && ((n & 0x10) != 0))) {
2292			m = 1;
2293			m = m << i;
2294			if ((dev->async[0] & m) != 0) {
2295				goto set_sync;
2296			}
2297		}
2298		continue;
2299set_sync:
2300		if (dev->sp[0][i] == 0x02) {
2301			synu[4] = 0x0c;
2302			synuw[4] = 0x0c;
2303		} else {
2304			if (dev->sp[0][i] >= 0x03) {
2305				synu[4] = 0x0a;
2306				synuw[4] = 0x0a;
2307			}
2308		}
2309		tmport = wkport + 0x5b;
2310		j = 0;
2311		if ((m & dev->wide_id[0]) != 0) {
2312			j |= 0x01;
2313		}
2314		outb(j, tmport);
2315		tmport = wkport + 0x43;
2316		outb(satn[0], tmport++);
2317		outb(satn[1], tmport++);
2318		outb(satn[2], tmport++);
2319		outb(satn[3], tmport++);
2320		outb(satn[4], tmport++);
2321		outb(satn[5], tmport++);
2322		tmport += 0x06;
2323		outb(0, tmport);
2324		tmport += 0x02;
2325		outb(dev->id[0][i].devsp, tmport++);
2326		outb(0, tmport++);
2327		outb(satn[6], tmport++);
2328		outb(satn[7], tmport++);
2329		tmport += 0x03;
2330		outb(satn[8], tmport);
2331		tmport += 0x07;
2332
2333		while ((inb(tmport) & 0x80) == 0x00)
2334			cpu_relax();
2335
2336		tmport -= 0x08;
2337		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
2338			continue;
2339		}
2340		while (inb(tmport) != 0x8e)
2341			cpu_relax();
2342
2343try_sync:
2344		j = 0;
2345		tmport = wkport + 0x54;
2346		outb(0x06, tmport);
2347		tmport += 0x04;
2348		outb(0x20, tmport);
2349		tmport += 0x07;
2350
2351		while ((inb(tmport) & 0x80) == 0) {
2352			if ((inb(tmport) & 0x01) != 0) {
2353				tmport -= 0x06;
2354				if ((m & dev->wide_id[0]) != 0) {
2355					if ((m & dev->ultra_map[0]) != 0) {
2356						outb(synuw[j++], tmport);
2357					} else {
2358						outb(synw[j++], tmport);
2359					}
2360				} else {
2361					if ((m & dev->ultra_map[0]) != 0) {
2362						outb(synu[j++], tmport);
2363					} else {
2364						outb(synn[j++], tmport);
2365					}
2366				}
2367				tmport += 0x06;
2368			}
2369		}
2370		tmport -= 0x08;
2371
2372		while ((inb(tmport) & 0x80) == 0x00)
2373			cpu_relax();
2374
2375		j = inb(tmport) & 0x0f;
2376		if (j == 0x0f) {
2377			goto phase_ins;
2378		}
2379		if (j == 0x0a) {
2380			goto phase_cmds;
2381		}
2382		if (j == 0x0e) {
2383			goto try_sync;
2384		}
2385		continue;
2386phase_outs:
2387		tmport = wkport + 0x58;
2388		outb(0x20, tmport);
2389		tmport += 0x07;
2390		while ((inb(tmport) & 0x80) == 0x00) {
2391			if ((inb(tmport) & 0x01) != 0x00) {
2392				tmport -= 0x06;
2393				outb(0x00, tmport);
2394				tmport += 0x06;
2395			}
2396		}
2397		tmport -= 0x08;
2398		j = inb(tmport);
2399		if (j == 0x85) {
2400			goto tar_dcons;
2401		}
2402		j &= 0x0f;
2403		if (j == 0x0f) {
2404			goto phase_ins;
2405		}
2406		if (j == 0x0a) {
2407			goto phase_cmds;
2408		}
2409		if (j == 0x0e) {
2410			goto phase_outs;
2411		}
2412		continue;
2413phase_ins:
2414		tmport = wkport + 0x54;
2415		outb(0x06, tmport);
2416		tmport += 0x04;
2417		outb(0x20, tmport);
2418		tmport += 0x07;
2419		k = 0;
2420phase_ins1:
2421		j = inb(tmport);
2422		if ((j & 0x01) != 0x00) {
2423			tmport -= 0x06;
2424			mbuf[k++] = inb(tmport);
2425			tmport += 0x06;
2426			goto phase_ins1;
2427		}
2428		if ((j & 0x80) == 0x00) {
2429			goto phase_ins1;
2430		}
2431		tmport -= 0x08;
2432
2433		while ((inb(tmport) & 0x80) == 0x00)
2434			cpu_relax();
2435
2436		j = inb(tmport);
2437		if (j == 0x85) {
2438			goto tar_dcons;
2439		}
2440		j &= 0x0f;
2441		if (j == 0x0f) {
2442			goto phase_ins;
2443		}
2444		if (j == 0x0a) {
2445			goto phase_cmds;
2446		}
2447		if (j == 0x0e) {
2448			goto phase_outs;
2449		}
2450		continue;
2451phase_cmds:
2452		tmport = wkport + 0x50;
2453		outb(0x30, tmport);
2454tar_dcons:
2455		tmport = wkport + 0x54;
2456		outb(0x00, tmport);
2457		tmport += 0x04;
2458		outb(0x08, tmport);
2459		tmport += 0x07;
2460
2461		while ((inb(tmport) & 0x80) == 0x00)
2462			cpu_relax();
2463
2464		tmport -= 0x08;
2465		j = inb(tmport);
2466		if (j != 0x16) {
2467			continue;
2468		}
2469		if (mbuf[0] != 0x01) {
2470			continue;
2471		}
2472		if (mbuf[1] != 0x03) {
2473			continue;
2474		}
2475		if (mbuf[4] == 0x00) {
2476			continue;
2477		}
2478		if (mbuf[3] > 0x64) {
2479			continue;
2480		}
2481		if (mbuf[4] > 0x0e) {
2482			mbuf[4] = 0x0e;
2483		}
2484		dev->id[0][i].devsp = mbuf[4];
2485		if (mbuf[3] < 0x0c) {
2486			j = 0xb0;
2487			goto set_syn_ok;
2488		}
2489		if ((mbuf[3] < 0x0d) && (rmb == 0)) {
2490			j = 0xa0;
2491			goto set_syn_ok;
2492		}
2493		if (mbuf[3] < 0x1a) {
2494			j = 0x20;
2495			goto set_syn_ok;
2496		}
2497		if (mbuf[3] < 0x33) {
2498			j = 0x40;
2499			goto set_syn_ok;
2500		}
2501		if (mbuf[3] < 0x4c) {
2502			j = 0x50;
2503			goto set_syn_ok;
2504		}
2505		j = 0x60;
2506set_syn_ok:
2507		dev->id[0][i].devsp = (dev->id[0][i].devsp & 0x0f) | j;
2508	}
2509}
2510
2511static void atp870u_free_tables(struct Scsi_Host *host)
2512{
2513	struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata;
2514	int j, k;
2515	for (j=0; j < 2; j++) {
2516		for (k = 0; k < 16; k++) {
2517			if (!atp_dev->id[j][k].prd_table)
2518				continue;
2519			pci_free_consistent(atp_dev->pdev, 1024, atp_dev->id[j][k].prd_table, atp_dev->id[j][k].prd_bus);
2520			atp_dev->id[j][k].prd_table = NULL;
2521		}
2522	}
2523}
2524
2525static int atp870u_init_tables(struct Scsi_Host *host)
2526{
2527	struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata;
2528	int c,k;
2529	for(c=0;c < 2;c++) {
2530	   	for(k=0;k<16;k++) {
2531	   			atp_dev->id[c][k].prd_table = pci_alloc_consistent(atp_dev->pdev, 1024, &(atp_dev->id[c][k].prd_bus));
2532	   			if (!atp_dev->id[c][k].prd_table) {
2533	   				printk("atp870u_init_tables fail\n");
2534				atp870u_free_tables(host);
2535				return -ENOMEM;
2536			}
2537			atp_dev->id[c][k].prdaddr = atp_dev->id[c][k].prd_bus;
2538			atp_dev->id[c][k].devsp=0x20;
2539			atp_dev->id[c][k].devtype = 0x7f;
2540			atp_dev->id[c][k].curr_req = NULL;
2541	   	}
2542
2543	   	atp_dev->active_id[c] = 0;
2544	   	atp_dev->wide_id[c] = 0;
2545	   	atp_dev->host_id[c] = 0x07;
2546	   	atp_dev->quhd[c] = 0;
2547	   	atp_dev->quend[c] = 0;
2548	   	atp_dev->last_cmd[c] = 0xff;
2549	   	atp_dev->in_snd[c] = 0;
2550	   	atp_dev->in_int[c] = 0;
2551
2552	   	for (k = 0; k < qcnt; k++) {
2553	   		  atp_dev->quereq[c][k] = NULL;
2554	   	}
2555	   	for (k = 0; k < 16; k++) {
2556			   atp_dev->id[c][k].curr_req = NULL;
2557			   atp_dev->sp[c][k] = 0x04;
2558	   	}
2559	}
2560	return 0;
2561}
2562
2563/* return non-zero on detection */
2564static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
2565{
2566	unsigned char k, m, c;
2567	unsigned long flags;
2568	unsigned int base_io, tmport, error,n;
2569	unsigned char host_id;
2570	struct Scsi_Host *shpnt = NULL;
2571	struct atp_unit *atpdev, *p;
2572	unsigned char setupdata[2][16];
2573	int count = 0;
2574
2575	atpdev = kzalloc(sizeof(*atpdev), GFP_KERNEL);
2576	if (!atpdev)
2577		return -ENOMEM;
2578
2579	if (pci_enable_device(pdev))
2580		goto err_eio;
2581
2582        if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
2583                printk(KERN_INFO "atp870u: use 32bit DMA mask.\n");
2584        } else {
2585                printk(KERN_ERR "atp870u: DMA mask required but not available.\n");
2586		goto err_eio;
2587        }
2588
2589	/*
2590	 * It's probably easier to weed out some revisions like
2591	 * this than via the PCI device table
2592	 */
2593	if (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610) {
2594		atpdev->chip_ver = pdev->revision;
2595		if (atpdev->chip_ver < 2)
2596			goto err_eio;
2597	}
2598
2599	switch (ent->device) {
2600	case PCI_DEVICE_ID_ARTOP_AEC7612UW:
2601	case PCI_DEVICE_ID_ARTOP_AEC7612SUW:
2602	case ATP880_DEVID1:
2603	case ATP880_DEVID2:
2604	case ATP885_DEVID:
2605		atpdev->chip_ver = 0x04;
2606	default:
2607		break;
2608	}
2609	base_io = pci_resource_start(pdev, 0);
2610	base_io &= 0xfffffff8;
2611
2612	if ((ent->device == ATP880_DEVID1)||(ent->device == ATP880_DEVID2)) {
2613		atpdev->chip_ver = pdev->revision;
2614		pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80);//JCC082803
2615
2616		host_id = inb(base_io + 0x39);
2617		host_id >>= 0x04;
2618
2619		printk(KERN_INFO "   ACARD AEC-67160 PCI Ultra3 LVD Host Adapter: %d"
2620			"    IO:%x, IRQ:%d.\n", count, base_io, pdev->irq);
2621		atpdev->ioport[0] = base_io + 0x40;
2622		atpdev->pciport[0] = base_io + 0x28;
2623		atpdev->dev_id = ent->device;
2624		atpdev->host_id[0] = host_id;
2625
2626		tmport = base_io + 0x22;
2627		atpdev->scam_on = inb(tmport);
2628		tmport += 0x13;
2629		atpdev->global_map[0] = inb(tmport);
2630		tmport += 0x07;
2631		atpdev->ultra_map[0] = inw(tmport);
2632
2633		n = 0x3f09;
2634next_fblk_880:
2635		if (n >= 0x4000)
2636			goto flash_ok_880;
2637
2638		m = 0;
2639		outw(n, base_io + 0x34);
2640		n += 0x0002;
2641		if (inb(base_io + 0x30) == 0xff)
2642			goto flash_ok_880;
2643
2644		atpdev->sp[0][m++] = inb(base_io + 0x30);
2645		atpdev->sp[0][m++] = inb(base_io + 0x31);
2646		atpdev->sp[0][m++] = inb(base_io + 0x32);
2647		atpdev->sp[0][m++] = inb(base_io + 0x33);
2648		outw(n, base_io + 0x34);
2649		n += 0x0002;
2650		atpdev->sp[0][m++] = inb(base_io + 0x30);
2651		atpdev->sp[0][m++] = inb(base_io + 0x31);
2652		atpdev->sp[0][m++] = inb(base_io + 0x32);
2653		atpdev->sp[0][m++] = inb(base_io + 0x33);
2654		outw(n, base_io + 0x34);
2655		n += 0x0002;
2656		atpdev->sp[0][m++] = inb(base_io + 0x30);
2657		atpdev->sp[0][m++] = inb(base_io + 0x31);
2658		atpdev->sp[0][m++] = inb(base_io + 0x32);
2659		atpdev->sp[0][m++] = inb(base_io + 0x33);
2660		outw(n, base_io + 0x34);
2661		n += 0x0002;
2662		atpdev->sp[0][m++] = inb(base_io + 0x30);
2663		atpdev->sp[0][m++] = inb(base_io + 0x31);
2664		atpdev->sp[0][m++] = inb(base_io + 0x32);
2665		atpdev->sp[0][m++] = inb(base_io + 0x33);
2666		n += 0x0018;
2667		goto next_fblk_880;
2668flash_ok_880:
2669		outw(0, base_io + 0x34);
2670		atpdev->ultra_map[0] = 0;
2671		atpdev->async[0] = 0;
2672		for (k = 0; k < 16; k++) {
2673			n = 1;
2674			n = n << k;
2675			if (atpdev->sp[0][k] > 1) {
2676				atpdev->ultra_map[0] |= n;
2677			} else {
2678				if (atpdev->sp[0][k] == 0)
2679					atpdev->async[0] |= n;
2680 			}
2681	 	}
2682		atpdev->async[0] = ~(atpdev->async[0]);
2683		outb(atpdev->global_map[0], base_io + 0x35);
2684
2685		shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
2686		if (!shpnt)
2687			goto err_nomem;
2688
2689		p = (struct atp_unit *)&shpnt->hostdata;
2690
2691		atpdev->host = shpnt;
2692		atpdev->pdev = pdev;
2693		pci_set_drvdata(pdev, p);
2694		memcpy(p, atpdev, sizeof(*atpdev));
2695		if (atp870u_init_tables(shpnt) < 0) {
2696			printk(KERN_ERR "Unable to allocate tables for Acard controller\n");
2697			goto unregister;
2698		}
2699
2700		if (request_irq(pdev->irq, atp870u_intr_handle, IRQF_SHARED, "atp880i", shpnt)) {
2701 			printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", pdev->irq);
2702			goto free_tables;
2703		}
2704
2705		spin_lock_irqsave(shpnt->host_lock, flags);
2706		tmport = base_io + 0x38;
2707		k = inb(tmport) & 0x80;
2708		outb(k, tmport);
2709		tmport += 0x03;
2710		outb(0x20, tmport);
2711		mdelay(32);
2712		outb(0, tmport);
2713		mdelay(32);
2714		tmport = base_io + 0x5b;
2715		inb(tmport);
2716		tmport -= 0x04;
2717		inb(tmport);
2718		tmport = base_io + 0x40;
2719		outb((host_id | 0x08), tmport);
2720		tmport += 0x18;
2721		outb(0, tmport);
2722		tmport += 0x07;
2723		while ((inb(tmport) & 0x80) == 0)
2724			mdelay(1);
2725		tmport -= 0x08;
2726		inb(tmport);
2727		tmport = base_io + 0x41;
2728		outb(8, tmport++);
2729		outb(0x7f, tmport);
2730		tmport = base_io + 0x51;
2731		outb(0x20, tmport);
2732
2733		tscam(shpnt);
2734		is880(p, base_io);
2735		tmport = base_io + 0x38;
2736		outb(0xb0, tmport);
2737		shpnt->max_id = 16;
2738		shpnt->this_id = host_id;
2739		shpnt->unique_id = base_io;
2740		shpnt->io_port = base_io;
2741		shpnt->n_io_port = 0x60;	/* Number of bytes of I/O space used */
2742		shpnt->irq = pdev->irq;
2743	} else if (ent->device == ATP885_DEVID) {
2744			printk(KERN_INFO "   ACARD AEC-67162 PCI Ultra3 LVD Host Adapter:  IO:%x, IRQ:%d.\n"
2745			       , base_io, pdev->irq);
2746
2747		atpdev->pdev = pdev;
2748		atpdev->dev_id  = ent->device;
2749		atpdev->baseport = base_io;
2750		atpdev->ioport[0] = base_io + 0x80;
2751		atpdev->ioport[1] = base_io + 0xc0;
2752		atpdev->pciport[0] = base_io + 0x40;
2753		atpdev->pciport[1] = base_io + 0x50;
2754
2755		shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
2756		if (!shpnt)
2757			goto err_nomem;
2758
2759		p = (struct atp_unit *)&shpnt->hostdata;
2760
2761		atpdev->host = shpnt;
2762		atpdev->pdev = pdev;
2763		pci_set_drvdata(pdev, p);
2764		memcpy(p, atpdev, sizeof(struct atp_unit));
2765		if (atp870u_init_tables(shpnt) < 0)
2766			goto unregister;
2767
2768#ifdef ED_DBGP
2769	printk("request_irq() shpnt %p hostdata %p\n", shpnt, p);
2770#endif
2771		if (request_irq(pdev->irq, atp870u_intr_handle, IRQF_SHARED, "atp870u", shpnt)) {
2772				printk(KERN_ERR "Unable to allocate IRQ for Acard controller.\n");
2773			goto free_tables;
2774		}
2775
2776		spin_lock_irqsave(shpnt->host_lock, flags);
2777
2778		c=inb(base_io + 0x29);
2779		outb((c | 0x04),base_io + 0x29);
2780
2781		n=0x1f80;
2782next_fblk_885:
2783		if (n >= 0x2000) {
2784		   goto flash_ok_885;
2785		}
2786		outw(n,base_io + 0x3c);
2787		if (inl(base_io + 0x38) == 0xffffffff) {
2788		   goto flash_ok_885;
2789		}
2790		for (m=0; m < 2; m++) {
2791		    p->global_map[m]= 0;
2792		    for (k=0; k < 4; k++) {
2793			outw(n++,base_io + 0x3c);
2794			((unsigned long *)&setupdata[m][0])[k]=inl(base_io + 0x38);
2795		    }
2796		    for (k=0; k < 4; k++) {
2797			outw(n++,base_io + 0x3c);
2798			((unsigned long *)&p->sp[m][0])[k]=inl(base_io + 0x38);
2799		    }
2800		    n += 8;
2801		}
2802		goto next_fblk_885;
2803flash_ok_885:
2804#ifdef ED_DBGP
2805		printk( "Flash Read OK\n");
2806#endif
2807		c=inb(base_io + 0x29);
2808		outb((c & 0xfb),base_io + 0x29);
2809		for (c=0;c < 2;c++) {
2810		    p->ultra_map[c]=0;
2811		    p->async[c] = 0;
2812		    for (k=0; k < 16; k++) {
2813			n=1;
2814			n = n << k;
2815			if (p->sp[c][k] > 1) {
2816			   p->ultra_map[c] |= n;
2817			} else {
2818			   if (p->sp[c][k] == 0) {
2819			      p->async[c] |= n;
2820			   }
2821			}
2822		    }
2823		    p->async[c] = ~(p->async[c]);
2824
2825		    if (p->global_map[c] == 0) {
2826		       k=setupdata[c][1];
2827		       if ((k & 0x40) != 0)
2828			  p->global_map[c] |= 0x20;
2829		       k &= 0x07;
2830		       p->global_map[c] |= k;
2831		       if ((setupdata[c][2] & 0x04) != 0)
2832			  p->global_map[c] |= 0x08;
2833		       p->host_id[c] = setupdata[c][0] & 0x07;
2834		    }
2835		}
2836
2837		k = inb(base_io + 0x28) & 0x8f;
2838		k |= 0x10;
2839		outb(k, base_io + 0x28);
2840		outb(0x80, base_io + 0x41);
2841		outb(0x80, base_io + 0x51);
2842		mdelay(100);
2843		outb(0, base_io + 0x41);
2844		outb(0, base_io + 0x51);
2845		mdelay(1000);
2846		inb(base_io + 0x9b);
2847		inb(base_io + 0x97);
2848		inb(base_io + 0xdb);
2849		inb(base_io + 0xd7);
2850		tmport = base_io + 0x80;
2851		k=p->host_id[0];
2852		if (k > 7)
2853		   k = (k & 0x07) | 0x40;
2854		k |= 0x08;
2855		outb(k, tmport);
2856		tmport += 0x18;
2857		outb(0, tmport);
2858		tmport += 0x07;
2859
2860		while ((inb(tmport) & 0x80) == 0)
2861			cpu_relax();
2862
2863		tmport -= 0x08;
2864		inb(tmport);
2865		tmport = base_io + 0x81;
2866		outb(8, tmport++);
2867		outb(0x7f, tmport);
2868		tmport = base_io + 0x91;
2869		outb(0x20, tmport);
2870
2871		tmport = base_io + 0xc0;
2872		k=p->host_id[1];
2873		if (k > 7)
2874		   k = (k & 0x07) | 0x40;
2875		k |= 0x08;
2876		outb(k, tmport);
2877		tmport += 0x18;
2878		outb(0, tmport);
2879		tmport += 0x07;
2880
2881		while ((inb(tmport) & 0x80) == 0)
2882			cpu_relax();
2883
2884		tmport -= 0x08;
2885		inb(tmport);
2886		tmport = base_io + 0xc1;
2887		outb(8, tmport++);
2888		outb(0x7f, tmport);
2889		tmport = base_io + 0xd1;
2890		outb(0x20, tmport);
2891
2892		tscam_885();
2893		printk(KERN_INFO "   Scanning Channel A SCSI Device ...\n");
2894		is885(p, base_io + 0x80, 0);
2895		printk(KERN_INFO "   Scanning Channel B SCSI Device ...\n");
2896		is885(p, base_io + 0xc0, 1);
2897
2898		k = inb(base_io + 0x28) & 0xcf;
2899		k |= 0xc0;
2900		outb(k, base_io + 0x28);
2901		k = inb(base_io + 0x1f) | 0x80;
2902		outb(k, base_io + 0x1f);
2903		k = inb(base_io + 0x29) | 0x01;
2904		outb(k, base_io + 0x29);
2905#ifdef ED_DBGP
2906		//printk("atp885: atp_host[0] 0x%p\n", atp_host[0]);
2907#endif
2908		shpnt->max_id = 16;
2909		shpnt->max_lun = (p->global_map[0] & 0x07) + 1;
2910		shpnt->max_channel = 1;
2911		shpnt->this_id = p->host_id[0];
2912		shpnt->unique_id = base_io;
2913		shpnt->io_port = base_io;
2914		shpnt->n_io_port = 0xff;	/* Number of bytes of I/O space used */
2915		shpnt->irq = pdev->irq;
2916
2917	} else {
2918		error = pci_read_config_byte(pdev, 0x49, &host_id);
2919
2920		printk(KERN_INFO "   ACARD AEC-671X PCI Ultra/W SCSI-2/3 Host Adapter: %d "
2921			"IO:%x, IRQ:%d.\n", count, base_io, pdev->irq);
2922
2923		atpdev->ioport[0] = base_io;
2924		atpdev->pciport[0] = base_io + 0x20;
2925		atpdev->dev_id = ent->device;
2926		host_id &= 0x07;
2927		atpdev->host_id[0] = host_id;
2928		tmport = base_io + 0x22;
2929		atpdev->scam_on = inb(tmport);
2930		tmport += 0x0b;
2931		atpdev->global_map[0] = inb(tmport++);
2932		atpdev->ultra_map[0] = inw(tmport);
2933
2934		if (atpdev->ultra_map[0] == 0) {
2935			atpdev->scam_on = 0x00;
2936			atpdev->global_map[0] = 0x20;
2937			atpdev->ultra_map[0] = 0xffff;
2938		}
2939
2940		shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
2941		if (!shpnt)
2942			goto err_nomem;
2943
2944		p = (struct atp_unit *)&shpnt->hostdata;
2945
2946		atpdev->host = shpnt;
2947		atpdev->pdev = pdev;
2948		pci_set_drvdata(pdev, p);
2949		memcpy(p, atpdev, sizeof(*atpdev));
2950		if (atp870u_init_tables(shpnt) < 0)
2951			goto unregister;
2952
2953		if (request_irq(pdev->irq, atp870u_intr_handle, IRQF_SHARED, "atp870i", shpnt)) {
2954			printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", pdev->irq);
2955			goto free_tables;
2956		}
2957
2958		spin_lock_irqsave(shpnt->host_lock, flags);
2959		if (atpdev->chip_ver > 0x07) {	/* check if atp876 chip then enable terminator */
2960			tmport = base_io + 0x3e;
2961			outb(0x00, tmport);
2962		}
2963
2964		tmport = base_io + 0x3a;
2965		k = (inb(tmport) & 0xf3) | 0x10;
2966		outb(k, tmport);
2967		outb((k & 0xdf), tmport);
2968		mdelay(32);
2969		outb(k, tmport);
2970		mdelay(32);
2971		tmport = base_io;
2972		outb((host_id | 0x08), tmport);
2973		tmport += 0x18;
2974		outb(0, tmport);
2975		tmport += 0x07;
2976		while ((inb(tmport) & 0x80) == 0)
2977			mdelay(1);
2978
2979		tmport -= 0x08;
2980		inb(tmport);
2981		tmport = base_io + 1;
2982		outb(8, tmport++);
2983		outb(0x7f, tmport);
2984		tmport = base_io + 0x11;
2985		outb(0x20, tmport);
2986
2987		tscam(shpnt);
2988		is870(p, base_io);
2989		tmport = base_io + 0x3a;
2990		outb((inb(tmport) & 0xef), tmport);
2991		tmport++;
2992		outb((inb(tmport) | 0x20), tmport);
2993		if (atpdev->chip_ver == 4)
2994			shpnt->max_id = 16;
2995		else
2996			shpnt->max_id = 8;
2997		shpnt->this_id = host_id;
2998		shpnt->unique_id = base_io;
2999		shpnt->io_port = base_io;
3000		shpnt->n_io_port = 0x40;	/* Number of bytes of I/O space used */
3001		shpnt->irq = pdev->irq;
3002	}
3003		spin_unlock_irqrestore(shpnt->host_lock, flags);
3004		if(ent->device==ATP885_DEVID) {
3005			if(!request_region(base_io, 0xff, "atp870u")) /* Register the IO ports that we use */
3006				goto request_io_fail;
3007		} else if((ent->device==ATP880_DEVID1)||(ent->device==ATP880_DEVID2)) {
3008			if(!request_region(base_io, 0x60, "atp870u")) /* Register the IO ports that we use */
3009				goto request_io_fail;
3010		} else {
3011			if(!request_region(base_io, 0x40, "atp870u")) /* Register the IO ports that we use */
3012				goto request_io_fail;
3013		}
3014		count++;
3015		if (scsi_add_host(shpnt, &pdev->dev))
3016			goto scsi_add_fail;
3017		scsi_scan_host(shpnt);
3018#ifdef ED_DBGP
3019		printk("atp870u_prob : exit\n");
3020#endif
3021		return 0;
3022
3023scsi_add_fail:
3024	printk("atp870u_prob:scsi_add_fail\n");
3025	if(ent->device==ATP885_DEVID) {
3026		release_region(base_io, 0xff);
3027	} else if((ent->device==ATP880_DEVID1)||(ent->device==ATP880_DEVID2)) {
3028		release_region(base_io, 0x60);
3029	} else {
3030		release_region(base_io, 0x40);
3031	}
3032request_io_fail:
3033	printk("atp870u_prob:request_io_fail\n");
3034	free_irq(pdev->irq, shpnt);
3035free_tables:
3036	printk("atp870u_prob:free_table\n");
3037	atp870u_free_tables(shpnt);
3038unregister:
3039	printk("atp870u_prob:unregister\n");
3040	scsi_host_put(shpnt);
3041	return -1;
3042err_eio:
3043	kfree(atpdev);
3044	return -EIO;
3045err_nomem:
3046	kfree(atpdev);
3047	return -ENOMEM;
3048}
3049
3050/* The abort command does not leave the device in a clean state where
3051   it is available to be used again.  Until this gets worked out, we will
3052   leave it commented out.  */
3053
3054static int atp870u_abort(struct scsi_cmnd * SCpnt)
3055{
3056	unsigned char  j, k, c;
3057	struct scsi_cmnd *workrequ;
3058	unsigned int tmport;
3059	struct atp_unit *dev;
3060	struct Scsi_Host *host;
3061	host = SCpnt->device->host;
3062
3063	dev = (struct atp_unit *)&host->hostdata;
3064	c = scmd_channel(SCpnt);
3065	printk(" atp870u: abort Channel = %x \n", c);
3066	printk("working=%x last_cmd=%x ", dev->working[c], dev->last_cmd[c]);
3067	printk(" quhdu=%x quendu=%x ", dev->quhd[c], dev->quend[c]);
3068	tmport = dev->ioport[c];
3069	for (j = 0; j < 0x18; j++) {
3070		printk(" r%2x=%2x", j, inb(tmport++));
3071	}
3072	tmport += 0x04;
3073	printk(" r1c=%2x", inb(tmport));
3074	tmport += 0x03;
3075	printk(" r1f=%2x in_snd=%2x ", inb(tmport), dev->in_snd[c]);
3076	tmport= dev->pciport[c];
3077	printk(" d00=%2x", inb(tmport));
3078	tmport += 0x02;
3079	printk(" d02=%2x", inb(tmport));
3080	for(j=0;j<16;j++) {
3081	   if (dev->id[c][j].curr_req != NULL) {
3082		workrequ = dev->id[c][j].curr_req;
3083		printk("\n que cdb= ");
3084		for (k=0; k < workrequ->cmd_len; k++) {
3085		    printk(" %2x ",workrequ->cmnd[k]);
3086		}
3087		printk(" last_lenu= %x ",(unsigned int)dev->id[c][j].last_len);
3088	   }
3089	}
3090	return SUCCESS;
3091}
3092
3093static const char *atp870u_info(struct Scsi_Host *notused)
3094{
3095	static char buffer[128];
3096
3097	strcpy(buffer, "ACARD AEC-6710/6712/67160 PCI Ultra/W/LVD SCSI-3 Adapter Driver V2.6+ac ");
3098
3099	return buffer;
3100}
3101
3102static int atp870u_show_info(struct seq_file *m, struct Scsi_Host *HBAptr)
3103{
3104	seq_puts(m, "ACARD AEC-671X Driver Version: 2.6+ac\n\n"
3105		"Adapter Configuration:\n");
3106	seq_printf(m, "               Base IO: %#.4lx\n", HBAptr->io_port);
3107	seq_printf(m, "                   IRQ: %d\n", HBAptr->irq);
3108	return 0;
3109}
3110
3111
3112static int atp870u_biosparam(struct scsi_device *disk, struct block_device *dev,
3113			sector_t capacity, int *ip)
3114{
3115	int heads, sectors, cylinders;
3116
3117	heads = 64;
3118	sectors = 32;
3119	cylinders = (unsigned long)capacity / (heads * sectors);
3120	if (cylinders > 1024) {
3121		heads = 255;
3122		sectors = 63;
3123		cylinders = (unsigned long)capacity / (heads * sectors);
3124	}
3125	ip[0] = heads;
3126	ip[1] = sectors;
3127	ip[2] = cylinders;
3128
3129	return 0;
3130}
3131
3132static void atp870u_remove (struct pci_dev *pdev)
3133{
3134	struct atp_unit *devext = pci_get_drvdata(pdev);
3135	struct Scsi_Host *pshost = devext->host;
3136
3137
3138	scsi_remove_host(pshost);
3139	printk(KERN_INFO "free_irq : %d\n",pshost->irq);
3140	free_irq(pshost->irq, pshost);
3141	release_region(pshost->io_port, pshost->n_io_port);
3142	printk(KERN_INFO "atp870u_free_tables : %p\n",pshost);
3143	atp870u_free_tables(pshost);
3144	printk(KERN_INFO "scsi_host_put : %p\n",pshost);
3145	scsi_host_put(pshost);
3146}
3147MODULE_LICENSE("GPL");
3148
3149static struct scsi_host_template atp870u_template = {
3150     .module			= THIS_MODULE,
3151     .name              	= "atp870u"		/* name */,
3152     .proc_name			= "atp870u",
3153     .show_info			= atp870u_show_info,
3154     .info              	= atp870u_info		/* info */,
3155     .queuecommand      	= atp870u_queuecommand	/* queuecommand */,
3156     .eh_abort_handler  	= atp870u_abort		/* abort */,
3157     .bios_param        	= atp870u_biosparam	/* biosparm */,
3158     .can_queue         	= qcnt			/* can_queue */,
3159     .this_id           	= 7			/* SCSI ID */,
3160     .sg_tablesize      	= ATP870U_SCATTER	/*SG_ALL*/ /*SG_NONE*/,
3161     .cmd_per_lun       	= ATP870U_CMDLUN		/* commands per lun */,
3162     .use_clustering    	= ENABLE_CLUSTERING,
3163     .max_sectors		= ATP870U_MAX_SECTORS,
3164};
3165
3166static struct pci_device_id atp870u_id_table[] = {
3167	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP885_DEVID)			  },
3168	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID1)			  },
3169	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID2)			  },
3170	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7610)    },
3171	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612UW)  },
3172	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612U)   },
3173	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612S)   },
3174	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612D)	  },
3175	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612SUW) },
3176	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_8060)	  },
3177	{ 0, },
3178};
3179
3180MODULE_DEVICE_TABLE(pci, atp870u_id_table);
3181
3182static struct pci_driver atp870u_driver = {
3183	.id_table	= atp870u_id_table,
3184	.name		= "atp870u",
3185	.probe		= atp870u_probe,
3186	.remove		= atp870u_remove,
3187};
3188
3189static int __init atp870u_init(void)
3190{
3191#ifdef ED_DBGP
3192	printk("atp870u_init: Entry\n");
3193#endif
3194	return pci_register_driver(&atp870u_driver);
3195}
3196
3197static void __exit atp870u_exit(void)
3198{
3199#ifdef ED_DBGP
3200	printk("atp870u_exit: Entry\n");
3201#endif
3202	pci_unregister_driver(&atp870u_driver);
3203}
3204
3205static void tscam_885(void)
3206{
3207	unsigned char i;
3208
3209	for (i = 0; i < 0x2; i++) {
3210		mdelay(300);
3211	}
3212	return;
3213}
3214
3215
3216
3217static void is885(struct atp_unit *dev, unsigned int wkport,unsigned char c)
3218{
3219	unsigned int tmport;
3220	unsigned char i, j, k, rmb, n, lvdmode;
3221	unsigned short int m;
3222	static unsigned char mbuf[512];
3223	static unsigned char satn[9] =	{0, 0, 0, 0, 0, 0, 0, 6, 6};
3224	static unsigned char inqd[9] =	{0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6};
3225	static unsigned char synn[6] =	{0x80, 1, 3, 1, 0x19, 0x0e};
3226	unsigned char synu[6] =  {0x80, 1, 3, 1, 0x0a, 0x0e};
3227	static unsigned char synw[6] =	{0x80, 1, 3, 1, 0x19, 0x0e};
3228	unsigned char synuw[6] =  {0x80, 1, 3, 1, 0x0a, 0x0e};
3229	static unsigned char wide[6] =	{0x80, 1, 2, 3, 1, 0};
3230	static unsigned char u3[9] = { 0x80,1,6,4,0x09,00,0x0e,0x01,0x02 };
3231
3232	lvdmode=inb(wkport + 0x1b) >> 7;
3233
3234	for (i = 0; i < 16; i++) {
3235		m = 1;
3236		m = m << i;
3237		if ((m & dev->active_id[c]) != 0) {
3238			continue;
3239		}
3240		if (i == dev->host_id[c]) {
3241			printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_id[c]);
3242			continue;
3243		}
3244		tmport = wkport + 0x1b;
3245		outb(0x01, tmport);
3246		tmport = wkport + 0x01;
3247		outb(0x08, tmport++);
3248		outb(0x7f, tmport++);
3249		outb(satn[0], tmport++);
3250		outb(satn[1], tmport++);
3251		outb(satn[2], tmport++);
3252		outb(satn[3], tmport++);
3253		outb(satn[4], tmport++);
3254		outb(satn[5], tmport++);
3255		tmport += 0x06;
3256		outb(0, tmport);
3257		tmport += 0x02;
3258		outb(dev->id[c][i].devsp, tmport++);
3259
3260		outb(0, tmport++);
3261		outb(satn[6], tmport++);
3262		outb(satn[7], tmport++);
3263		j = i;
3264		if ((j & 0x08) != 0) {
3265			j = (j & 0x07) | 0x40;
3266		}
3267		outb(j, tmport);
3268		tmport += 0x03;
3269		outb(satn[8], tmport);
3270		tmport += 0x07;
3271
3272		while ((inb(tmport) & 0x80) == 0x00)
3273			cpu_relax();
3274		tmport -= 0x08;
3275		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
3276			continue;
3277		}
3278		while (inb(tmport) != 0x8e)
3279			cpu_relax();
3280		dev->active_id[c] |= m;
3281
3282		tmport = wkport + 0x10;
3283		outb(0x30, tmport);
3284		tmport = wkport + 0x14;
3285		outb(0x00, tmport);
3286
3287phase_cmd:
3288		tmport = wkport + 0x18;
3289		outb(0x08, tmport);
3290		tmport += 0x07;
3291		while ((inb(tmport) & 0x80) == 0x00)
3292			cpu_relax();
3293		tmport -= 0x08;
3294		j = inb(tmport);
3295		if (j != 0x16) {
3296			tmport = wkport + 0x10;
3297			outb(0x41, tmport);
3298			goto phase_cmd;
3299		}
3300sel_ok:
3301		tmport = wkport + 0x03;
3302		outb(inqd[0], tmport++);
3303		outb(inqd[1], tmport++);
3304		outb(inqd[2], tmport++);
3305		outb(inqd[3], tmport++);
3306		outb(inqd[4], tmport++);
3307		outb(inqd[5], tmport);
3308		tmport += 0x07;
3309		outb(0, tmport);
3310		tmport += 0x02;
3311		outb(dev->id[c][i].devsp, tmport++);
3312		outb(0, tmport++);
3313		outb(inqd[6], tmport++);
3314		outb(inqd[7], tmport++);
3315		tmport += 0x03;
3316		outb(inqd[8], tmport);
3317		tmport += 0x07;
3318		while ((inb(tmport) & 0x80) == 0x00)
3319			cpu_relax();
3320		tmport -= 0x08;
3321		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
3322			continue;
3323		}
3324		while (inb(tmport) != 0x8e)
3325			cpu_relax();
3326		tmport = wkport + 0x1b;
3327		outb(0x00, tmport);
3328		tmport = wkport + 0x18;
3329		outb(0x08, tmport);
3330		tmport += 0x07;
3331		j = 0;
3332rd_inq_data:
3333		k = inb(tmport);
3334		if ((k & 0x01) != 0) {
3335			tmport -= 0x06;
3336			mbuf[j++] = inb(tmport);
3337			tmport += 0x06;
3338			goto rd_inq_data;
3339		}
3340		if ((k & 0x80) == 0) {
3341			goto rd_inq_data;
3342		}
3343		tmport -= 0x08;
3344		j = inb(tmport);
3345		if (j == 0x16) {
3346			goto inq_ok;
3347		}
3348		tmport = wkport + 0x10;
3349		outb(0x46, tmport);
3350		tmport += 0x02;
3351		outb(0, tmport++);
3352		outb(0, tmport++);
3353		outb(0, tmport++);
3354		tmport += 0x03;
3355		outb(0x08, tmport);
3356		tmport += 0x07;
3357		while ((inb(tmport) & 0x80) == 0x00)
3358			cpu_relax();
3359		tmport -= 0x08;
3360		if (inb(tmport) != 0x16) {
3361			goto sel_ok;
3362		}
3363inq_ok:
3364		mbuf[36] = 0;
3365		printk( KERN_INFO"         ID: %2d  %s\n", i, &mbuf[8]);
3366		dev->id[c][i].devtype = mbuf[0];
3367		rmb = mbuf[1];
3368		n = mbuf[7];
3369		if ((mbuf[7] & 0x60) == 0) {
3370			goto not_wide;
3371		}
3372		if ((i < 8) && ((dev->global_map[c] & 0x20) == 0)) {
3373			goto not_wide;
3374		}
3375		if (lvdmode == 0) {
3376		   goto chg_wide;
3377		}
3378		if (dev->sp[c][i] != 0x04) {	// force u2
3379		   goto chg_wide;
3380		}
3381
3382		tmport = wkport + 0x1b;
3383		outb(0x01, tmport);
3384		tmport = wkport + 0x03;
3385		outb(satn[0], tmport++);
3386		outb(satn[1], tmport++);
3387		outb(satn[2], tmport++);
3388		outb(satn[3], tmport++);
3389		outb(satn[4], tmport++);
3390		outb(satn[5], tmport++);
3391		tmport += 0x06;
3392		outb(0, tmport);
3393		tmport += 0x02;
3394		outb(dev->id[c][i].devsp, tmport++);
3395		outb(0, tmport++);
3396		outb(satn[6], tmport++);
3397		outb(satn[7], tmport++);
3398		tmport += 0x03;
3399		outb(satn[8], tmport);
3400		tmport += 0x07;
3401
3402		while ((inb(tmport) & 0x80) == 0x00)
3403			cpu_relax();
3404		tmport -= 0x08;
3405		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
3406			continue;
3407		}
3408		while (inb(tmport) != 0x8e)
3409			cpu_relax();
3410try_u3:
3411		j = 0;
3412		tmport = wkport + 0x14;
3413		outb(0x09, tmport);
3414		tmport += 0x04;
3415		outb(0x20, tmport);
3416		tmport += 0x07;
3417
3418		while ((inb(tmport) & 0x80) == 0) {
3419			if ((inb(tmport) & 0x01) != 0) {
3420				tmport -= 0x06;
3421				outb(u3[j++], tmport);
3422				tmport += 0x06;
3423			}
3424			cpu_relax();
3425		}
3426		tmport -= 0x08;
3427		while ((inb(tmport) & 0x80) == 0x00)
3428			cpu_relax();
3429		j = inb(tmport) & 0x0f;
3430		if (j == 0x0f) {
3431			goto u3p_in;
3432		}
3433		if (j == 0x0a) {
3434			goto u3p_cmd;
3435		}
3436		if (j == 0x0e) {
3437			goto try_u3;
3438		}
3439		continue;
3440u3p_out:
3441		tmport = wkport + 0x18;
3442		outb(0x20, tmport);
3443		tmport += 0x07;
3444		while ((inb(tmport) & 0x80) == 0) {
3445			if ((inb(tmport) & 0x01) != 0) {
3446				tmport -= 0x06;
3447				outb(0, tmport);
3448				tmport += 0x06;
3449			}
3450			cpu_relax();
3451		}
3452		tmport -= 0x08;
3453		j = inb(tmport) & 0x0f;
3454		if (j == 0x0f) {
3455			goto u3p_in;
3456		}
3457		if (j == 0x0a) {
3458			goto u3p_cmd;
3459		}
3460		if (j == 0x0e) {
3461			goto u3p_out;
3462		}
3463		continue;
3464u3p_in:
3465		tmport = wkport + 0x14;
3466		outb(0x09, tmport);
3467		tmport += 0x04;
3468		outb(0x20, tmport);
3469		tmport += 0x07;
3470		k = 0;
3471u3p_in1:
3472		j = inb(tmport);
3473		if ((j & 0x01) != 0) {
3474			tmport -= 0x06;
3475			mbuf[k++] = inb(tmport);
3476			tmport += 0x06;
3477			goto u3p_in1;
3478		}
3479		if ((j & 0x80) == 0x00) {
3480			goto u3p_in1;
3481		}
3482		tmport -= 0x08;
3483		j = inb(tmport) & 0x0f;
3484		if (j == 0x0f) {
3485			goto u3p_in;
3486		}
3487		if (j == 0x0a) {
3488			goto u3p_cmd;
3489		}
3490		if (j == 0x0e) {
3491			goto u3p_out;
3492		}
3493		continue;
3494u3p_cmd:
3495		tmport = wkport + 0x10;
3496		outb(0x30, tmport);
3497		tmport = wkport + 0x14;
3498		outb(0x00, tmport);
3499		tmport += 0x04;
3500		outb(0x08, tmport);
3501		tmport += 0x07;
3502		while ((inb(tmport) & 0x80) == 0x00);
3503		tmport -= 0x08;
3504		j = inb(tmport);
3505		if (j != 0x16) {
3506			if (j == 0x4e) {
3507				goto u3p_out;
3508			}
3509			continue;
3510		}
3511		if (mbuf[0] != 0x01) {
3512			goto chg_wide;
3513		}
3514		if (mbuf[1] != 0x06) {
3515			goto chg_wide;
3516		}
3517		if (mbuf[2] != 0x04) {
3518			goto chg_wide;
3519		}
3520		if (mbuf[3] == 0x09) {
3521			m = 1;
3522			m = m << i;
3523			dev->wide_id[c] |= m;
3524			dev->id[c][i].devsp = 0xce;
3525#ifdef ED_DBGP
3526			printk("dev->id[%2d][%2d].devsp = %2x\n",c,i,dev->id[c][i].devsp);
3527#endif
3528			continue;
3529		}
3530chg_wide:
3531		tmport = wkport + 0x1b;
3532		outb(0x01, tmport);
3533		tmport = wkport + 0x03;
3534		outb(satn[0], tmport++);
3535		outb(satn[1], tmport++);
3536		outb(satn[2], tmport++);
3537		outb(satn[3], tmport++);
3538		outb(satn[4], tmport++);
3539		outb(satn[5], tmport++);
3540		tmport += 0x06;
3541		outb(0, tmport);
3542		tmport += 0x02;
3543		outb(dev->id[c][i].devsp, tmport++);
3544		outb(0, tmport++);
3545		outb(satn[6], tmport++);
3546		outb(satn[7], tmport++);
3547		tmport += 0x03;
3548		outb(satn[8], tmport);
3549		tmport += 0x07;
3550
3551		while ((inb(tmport) & 0x80) == 0x00)
3552			cpu_relax();
3553		tmport -= 0x08;
3554		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
3555			continue;
3556		}
3557		while (inb(tmport) != 0x8e)
3558			cpu_relax();
3559try_wide:
3560		j = 0;
3561		tmport = wkport + 0x14;
3562		outb(0x05, tmport);
3563		tmport += 0x04;
3564		outb(0x20, tmport);
3565		tmport += 0x07;
3566
3567		while ((inb(tmport) & 0x80) == 0) {
3568			if ((inb(tmport) & 0x01) != 0) {
3569				tmport -= 0x06;
3570				outb(wide[j++], tmport);
3571				tmport += 0x06;
3572			}
3573			cpu_relax();
3574		}
3575		tmport -= 0x08;
3576		while ((inb(tmport) & 0x80) == 0x00)
3577			cpu_relax();
3578		j = inb(tmport) & 0x0f;
3579		if (j == 0x0f) {
3580			goto widep_in;
3581		}
3582		if (j == 0x0a) {
3583			goto widep_cmd;
3584		}
3585		if (j == 0x0e) {
3586			goto try_wide;
3587		}
3588		continue;
3589widep_out:
3590		tmport = wkport + 0x18;
3591		outb(0x20, tmport);
3592		tmport += 0x07;
3593		while ((inb(tmport) & 0x80) == 0) {
3594			if ((inb(tmport) & 0x01) != 0) {
3595				tmport -= 0x06;
3596				outb(0, tmport);
3597				tmport += 0x06;
3598			}
3599			cpu_relax();
3600		}
3601		tmport -= 0x08;
3602		j = inb(tmport) & 0x0f;
3603		if (j == 0x0f) {
3604			goto widep_in;
3605		}
3606		if (j == 0x0a) {
3607			goto widep_cmd;
3608		}
3609		if (j == 0x0e) {
3610			goto widep_out;
3611		}
3612		continue;
3613widep_in:
3614		tmport = wkport + 0x14;
3615		outb(0xff, tmport);
3616		tmport += 0x04;
3617		outb(0x20, tmport);
3618		tmport += 0x07;
3619		k = 0;
3620widep_in1:
3621		j = inb(tmport);
3622		if ((j & 0x01) != 0) {
3623			tmport -= 0x06;
3624			mbuf[k++] = inb(tmport);
3625			tmport += 0x06;
3626			goto widep_in1;
3627		}
3628		if ((j & 0x80) == 0x00) {
3629			goto widep_in1;
3630		}
3631		tmport -= 0x08;
3632		j = inb(tmport) & 0x0f;
3633		if (j == 0x0f) {
3634			goto widep_in;
3635		}
3636		if (j == 0x0a) {
3637			goto widep_cmd;
3638		}
3639		if (j == 0x0e) {
3640			goto widep_out;
3641		}
3642		continue;
3643widep_cmd:
3644		tmport = wkport + 0x10;
3645		outb(0x30, tmport);
3646		tmport = wkport + 0x14;
3647		outb(0x00, tmport);
3648		tmport += 0x04;
3649		outb(0x08, tmport);
3650		tmport += 0x07;
3651		while ((inb(tmport) & 0x80) == 0x00)
3652			cpu_relax();
3653		tmport -= 0x08;
3654		j = inb(tmport);
3655		if (j != 0x16) {
3656			if (j == 0x4e) {
3657				goto widep_out;
3658			}
3659			continue;
3660		}
3661		if (mbuf[0] != 0x01) {
3662			goto not_wide;
3663		}
3664		if (mbuf[1] != 0x02) {
3665			goto not_wide;
3666		}
3667		if (mbuf[2] != 0x03) {
3668			goto not_wide;
3669		}
3670		if (mbuf[3] != 0x01) {
3671			goto not_wide;
3672		}
3673		m = 1;
3674		m = m << i;
3675		dev->wide_id[c] |= m;
3676not_wide:
3677		if ((dev->id[c][i].devtype == 0x00) || (dev->id[c][i].devtype == 0x07) ||
3678		    ((dev->id[c][i].devtype == 0x05) && ((n & 0x10) != 0))) {
3679			m = 1;
3680			m = m << i;
3681			if ((dev->async[c] & m) != 0) {
3682			   goto set_sync;
3683			}
3684		}
3685		continue;
3686set_sync:
3687		if (dev->sp[c][i] == 0x02) {
3688		   synu[4]=0x0c;
3689		   synuw[4]=0x0c;
3690		} else {
3691		   if (dev->sp[c][i] >= 0x03) {
3692		      synu[4]=0x0a;
3693		      synuw[4]=0x0a;
3694		   }
3695		}
3696		tmport = wkport + 0x1b;
3697		j = 0;
3698		if ((m & dev->wide_id[c]) != 0) {
3699			j |= 0x01;
3700		}
3701		outb(j, tmport);
3702		tmport = wkport + 0x03;
3703		outb(satn[0], tmport++);
3704		outb(satn[1], tmport++);
3705		outb(satn[2], tmport++);
3706		outb(satn[3], tmport++);
3707		outb(satn[4], tmport++);
3708		outb(satn[5], tmport++);
3709		tmport += 0x06;
3710		outb(0, tmport);
3711		tmport += 0x02;
3712		outb(dev->id[c][i].devsp, tmport++);
3713		outb(0, tmport++);
3714		outb(satn[6], tmport++);
3715		outb(satn[7], tmport++);
3716		tmport += 0x03;
3717		outb(satn[8], tmport);
3718		tmport += 0x07;
3719
3720		while ((inb(tmport) & 0x80) == 0x00)
3721			cpu_relax();
3722		tmport -= 0x08;
3723		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
3724			continue;
3725		}
3726		while (inb(tmport) != 0x8e)
3727			cpu_relax();
3728try_sync:
3729		j = 0;
3730		tmport = wkport + 0x14;
3731		outb(0x06, tmport);
3732		tmport += 0x04;
3733		outb(0x20, tmport);
3734		tmport += 0x07;
3735
3736		while ((inb(tmport) & 0x80) == 0) {
3737			if ((inb(tmport) & 0x01) != 0) {
3738				tmport -= 0x06;
3739				if ((m & dev->wide_id[c]) != 0) {
3740					if ((m & dev->ultra_map[c]) != 0) {
3741						outb(synuw[j++], tmport);
3742					} else {
3743						outb(synw[j++], tmport);
3744					}
3745				} else {
3746					if ((m & dev->ultra_map[c]) != 0) {
3747						outb(synu[j++], tmport);
3748					} else {
3749						outb(synn[j++], tmport);
3750					}
3751				}
3752				tmport += 0x06;
3753			}
3754		}
3755		tmport -= 0x08;
3756		while ((inb(tmport) & 0x80) == 0x00)
3757			cpu_relax();
3758		j = inb(tmport) & 0x0f;
3759		if (j == 0x0f) {
3760			goto phase_ins;
3761		}
3762		if (j == 0x0a) {
3763			goto phase_cmds;
3764		}
3765		if (j == 0x0e) {
3766			goto try_sync;
3767		}
3768		continue;
3769phase_outs:
3770		tmport = wkport + 0x18;
3771		outb(0x20, tmport);
3772		tmport += 0x07;
3773		while ((inb(tmport) & 0x80) == 0x00) {
3774			if ((inb(tmport) & 0x01) != 0x00) {
3775				tmport -= 0x06;
3776				outb(0x00, tmport);
3777				tmport += 0x06;
3778			}
3779			cpu_relax();
3780		}
3781		tmport -= 0x08;
3782		j = inb(tmport);
3783		if (j == 0x85) {
3784			goto tar_dcons;
3785		}
3786		j &= 0x0f;
3787		if (j == 0x0f) {
3788			goto phase_ins;
3789		}
3790		if (j == 0x0a) {
3791			goto phase_cmds;
3792		}
3793		if (j == 0x0e) {
3794			goto phase_outs;
3795		}
3796		continue;
3797phase_ins:
3798		tmport = wkport + 0x14;
3799		outb(0x06, tmport);
3800		tmport += 0x04;
3801		outb(0x20, tmport);
3802		tmport += 0x07;
3803		k = 0;
3804phase_ins1:
3805		j = inb(tmport);
3806		if ((j & 0x01) != 0x00) {
3807			tmport -= 0x06;
3808			mbuf[k++] = inb(tmport);
3809			tmport += 0x06;
3810			goto phase_ins1;
3811		}
3812		if ((j & 0x80) == 0x00) {
3813			goto phase_ins1;
3814		}
3815		tmport -= 0x08;
3816		while ((inb(tmport) & 0x80) == 0x00);
3817		j = inb(tmport);
3818		if (j == 0x85) {
3819			goto tar_dcons;
3820		}
3821		j &= 0x0f;
3822		if (j == 0x0f) {
3823			goto phase_ins;
3824		}
3825		if (j == 0x0a) {
3826			goto phase_cmds;
3827		}
3828		if (j == 0x0e) {
3829			goto phase_outs;
3830		}
3831		continue;
3832phase_cmds:
3833		tmport = wkport + 0x10;
3834		outb(0x30, tmport);
3835tar_dcons:
3836		tmport = wkport + 0x14;
3837		outb(0x00, tmport);
3838		tmport += 0x04;
3839		outb(0x08, tmport);
3840		tmport += 0x07;
3841		while ((inb(tmport) & 0x80) == 0x00)
3842			cpu_relax();
3843		tmport -= 0x08;
3844		j = inb(tmport);
3845		if (j != 0x16) {
3846			continue;
3847		}
3848		if (mbuf[0] != 0x01) {
3849			continue;
3850		}
3851		if (mbuf[1] != 0x03) {
3852			continue;
3853		}
3854		if (mbuf[4] == 0x00) {
3855			continue;
3856		}
3857		if (mbuf[3] > 0x64) {
3858			continue;
3859		}
3860		if (mbuf[4] > 0x0e) {
3861			mbuf[4] = 0x0e;
3862		}
3863		dev->id[c][i].devsp = mbuf[4];
3864		if (mbuf[3] < 0x0c){
3865			j = 0xb0;
3866			goto set_syn_ok;
3867		}
3868		if ((mbuf[3] < 0x0d) && (rmb == 0)) {
3869			j = 0xa0;
3870			goto set_syn_ok;
3871		}
3872		if (mbuf[3] < 0x1a) {
3873			j = 0x20;
3874			goto set_syn_ok;
3875		}
3876		if (mbuf[3] < 0x33) {
3877			j = 0x40;
3878			goto set_syn_ok;
3879		}
3880		if (mbuf[3] < 0x4c) {
3881			j = 0x50;
3882			goto set_syn_ok;
3883		}
3884		j = 0x60;
3885	      set_syn_ok:
3886		dev->id[c][i].devsp = (dev->id[c][i].devsp & 0x0f) | j;
3887#ifdef ED_DBGP
3888		printk("dev->id[%2d][%2d].devsp = %2x\n",c,i,dev->id[c][i].devsp);
3889#endif
3890	}
3891	tmport = wkport + 0x16;
3892	outb(0x80, tmport);
3893}
3894
3895module_init(atp870u_init);
3896module_exit(atp870u_exit);
3897
3898