1/* $Id: atp870u.c,v 1.1.1.1 2008/10/15 03:26:49 james26_jang Exp $
2 *  linux/kernel/atp870u.c
3 *
4 *  Copyright (C) 1997	Wu Ching Chen
5 *  2.1.x update (C) 1998  Krzysztof G. Baranowski
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
18#include <linux/module.h>
19
20#include <linux/kernel.h>
21#include <linux/types.h>
22#include <linux/string.h>
23#include <linux/ioport.h>
24#include <linux/delay.h>
25#include <linux/sched.h>
26#include <linux/proc_fs.h>
27#include <linux/spinlock.h>
28#include <asm/system.h>
29#include <asm/io.h>
30#include <linux/pci.h>
31#include <linux/blk.h>
32#include "scsi.h"
33#include "hosts.h"
34
35
36#include "atp870u.h"
37
38#include<linux/stat.h>
39
40void mydlyu(unsigned int);
41
42/*
43 *   static const char RCSid[] = "$Header: /home/user/PROJECT/WL-520gu-NewUI/src/linux/linux/drivers/scsi/atp870u.c,v 1.1.1.1 2008/10/15 03:26:49 james26_jang Exp $";
44 */
45
46static unsigned char admaxu = 1;
47static unsigned short int sync_idu;
48
49static unsigned int irqnumu[2] = {0, 0};
50
51struct atp_unit
52{
53	unsigned long ioport;
54	unsigned long irq;
55	unsigned long pciport;
56	unsigned char last_cmd;
57	unsigned char in_snd;
58	unsigned char in_int;
59	unsigned char quhdu;
60	unsigned char quendu;
61	unsigned char scam_on;
62	unsigned char global_map;
63	unsigned char chip_veru;
64	unsigned char host_idu;
65	int working;
66	unsigned short wide_idu;
67	unsigned short active_idu;
68	unsigned short ultra_map;
69	unsigned short async;
70	unsigned short deviceid;
71	unsigned char ata_cdbu[16];
72	unsigned char sp[16];
73	Scsi_Cmnd *querequ[qcnt];
74	struct atp_id
75	{
76		unsigned char dirctu;
77		unsigned char devspu;
78		unsigned char devtypeu;
79		unsigned long prdaddru;
80		unsigned long tran_lenu;
81		unsigned long last_lenu;
82		unsigned char *prd_posu;
83		unsigned char *prd_tableu;
84		Scsi_Cmnd *curr_req;
85	} id[16];
86};
87
88static struct Scsi_Host *atp_host[2] = {NULL, NULL};
89static struct atp_unit atp_unit[2];
90
91static void atp870u_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
92{
93	unsigned long flags;
94	unsigned short int tmpcip, id;
95	unsigned char i, j, h, target_id, lun;
96	unsigned char *prd;
97	Scsi_Cmnd *workrequ;
98	unsigned int workportu, tmport;
99	unsigned long adrcntu, k;
100	int errstus;
101	struct atp_unit *dev = dev_id;
102
103	for (h = 0; h < 2; h++) {
104		if (irq == irqnumu[h]) {
105			goto irq_numok;
106		}
107	}
108	return;
109irq_numok:
110	dev->in_int = 1;
111	workportu = dev->ioport;
112	tmport = workportu;
113
114	if (dev->working != 0)
115	{
116		tmport += 0x1f;
117		j = inb(tmport);
118		if ((j & 0x80) == 0)
119		{
120			dev->in_int = 0;
121			return;
122		}
123
124		tmpcip = dev->pciport;
125		if ((inb(tmpcip) & 0x08) != 0)
126		{
127			tmpcip += 0x2;
128			for (k=0; k < 1000; k++)
129			{
130				if ((inb(tmpcip) & 0x08) == 0)
131				{
132					goto stop_dma;
133				}
134				if ((inb(tmpcip) & 0x01) == 0)
135				{
136					goto stop_dma;
137				}
138			}
139		}
140stop_dma:
141		tmpcip = dev->pciport;
142		outb(0x00, tmpcip);
143		tmport -= 0x08;
144
145		i = inb(tmport);
146
147		tmport -= 0x02;
148		target_id = inb(tmport);
149		tmport += 0x02;
150
151		/*
152		 *	Remap wide devices onto id numbers
153		 */
154
155		if ((target_id & 0x40) != 0) {
156			target_id = (target_id & 0x07) | 0x08;
157		} else {
158			target_id &= 0x07;
159		}
160
161		if ((j & 0x40) != 0)
162		{
163		     if (dev->last_cmd == 0xff)
164		     {
165			dev->last_cmd = target_id;
166		     }
167		     dev->last_cmd |= 0x40;
168		}
169
170		if (i == 0x85)
171		{
172			if ((dev->last_cmd & 0xf0) != 0x40)
173			{
174			   dev->last_cmd = 0xff;
175			}
176			/*
177			 *	Flip wide
178			 */
179			if (dev->wide_idu != 0)
180			{
181				tmport = workportu + 0x1b;
182				outb(0x01,tmport);
183				while ((inb(tmport) & 0x01) != 0x01)
184				{
185				   outb(0x01,tmport);
186				}
187			}
188			/*
189			 *	Issue more commands
190			 */
191			if (((dev->quhdu != dev->quendu) || (dev->last_cmd != 0xff)) &&
192			    (dev->in_snd == 0))
193			{
194				send_s870(h);
195			}
196			/*
197			 *	Done
198			 */
199			dev->in_int = 0;
200			return;
201		}
202
203		if (i == 0x40)
204		{
205		     dev->last_cmd |= 0x40;
206		     dev->in_int = 0;
207		     return;
208		}
209
210		if (i == 0x21)
211		{
212			if ((dev->last_cmd & 0xf0) != 0x40)
213			{
214			   dev->last_cmd = 0xff;
215			}
216			tmport -= 0x05;
217			adrcntu = 0;
218			((unsigned char *) &adrcntu)[2] = inb(tmport++);
219			((unsigned char *) &adrcntu)[1] = inb(tmport++);
220			((unsigned char *) &adrcntu)[0] = inb(tmport);
221			k = dev->id[target_id].last_lenu;
222			k -= adrcntu;
223			dev->id[target_id].tran_lenu = k;
224			dev->id[target_id].last_lenu = adrcntu;
225			tmport -= 0x04;
226			outb(0x41, tmport);
227			tmport += 0x08;
228			outb(0x08, tmport);
229			dev->in_int = 0;
230			return;
231		}
232		if ((i == 0x80) || (i == 0x8f))
233		{
234			lun = 0;
235			tmport -= 0x07;
236			j = inb(tmport);
237			if (j == 0x44 || i==0x80) {
238				tmport += 0x0d;
239				lun = inb(tmport) & 0x07;
240			} else {
241				if ((dev->last_cmd & 0xf0) != 0x40)
242				{
243				   dev->last_cmd = 0xff;
244				}
245				if (j == 0x41)
246				{
247					tmport += 0x02;
248					adrcntu = 0;
249					((unsigned char *) &adrcntu)[2] = inb(tmport++);
250					((unsigned char *) &adrcntu)[1] = inb(tmport++);
251					((unsigned char *) &adrcntu)[0] = inb(tmport);
252					k = dev->id[target_id].last_lenu;
253					k -= adrcntu;
254					dev->id[target_id].tran_lenu = k;
255					dev->id[target_id].last_lenu = adrcntu;
256					tmport += 0x04;
257					outb(0x08, tmport);
258					dev->in_int = 0;
259					return;
260				}
261				else
262				{
263					outb(0x46, tmport);
264					dev->id[target_id].dirctu = 0x00;
265					tmport += 0x02;
266					outb(0x00, tmport++);
267					outb(0x00, tmport++);
268					outb(0x00, tmport++);
269					tmport += 0x03;
270					outb(0x08, tmport);
271					dev->in_int = 0;
272					return;
273				}
274			}
275			if (dev->last_cmd != 0xff)
276			{
277			   dev->last_cmd |= 0x40;
278			}
279			tmport = workportu + 0x10;
280			outb(0x45, tmport);
281			tmport += 0x06;
282			target_id = inb(tmport);
283			/*
284			 *	Remap wide identifiers
285			 */
286			if ((target_id & 0x10) != 0)
287			{
288				target_id = (target_id & 0x07) | 0x08;
289			} else {
290				target_id &= 0x07;
291			}
292			workrequ = dev->id[target_id].curr_req;
293			tmport = workportu + 0x0f;
294			outb(lun, tmport);
295			tmport += 0x02;
296			outb(dev->id[target_id].devspu, tmport++);
297			adrcntu = dev->id[target_id].tran_lenu;
298			k = dev->id[target_id].last_lenu;
299			outb(((unsigned char *) &k)[2], tmport++);
300			outb(((unsigned char *) &k)[1], tmport++);
301			outb(((unsigned char *) &k)[0], tmport++);
302			/* Remap wide */
303			j = target_id;
304			if (target_id > 7) {
305				j = (j & 0x07) | 0x40;
306			}
307			/* Add direction */
308			j |= dev->id[target_id].dirctu;
309			outb(j, tmport++);
310			outb(0x80, tmport);
311
312			/* enable 32 bit fifo transfer */
313			if (dev->deviceid != 0x8081)
314			{
315			   tmport = workportu + 0x3a;
316			   if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) ||
317			       (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a))
318			   {
319			      outb((unsigned char)((inb(tmport) & 0xf3) | 0x08),tmport);
320			   }
321			   else
322			   {
323			      outb((unsigned char)(inb(tmport) & 0xf3),tmport);
324			   }
325			}
326			else
327			{
328			   tmport = workportu - 0x05;
329			   if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) ||
330			       (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a))
331			   {
332			      outb((unsigned char)((inb(tmport) & 0x3f) | 0xc0),tmport);
333			   }
334			   else
335			   {
336			      outb((unsigned char)(inb(tmport) & 0x3f),tmport);
337			   }
338			}
339
340			tmport = workportu + 0x1b;
341			j = 0;
342			id = 1;
343			id = id << target_id;
344			/*
345			 *	Is this a wide device
346			 */
347			if ((id & dev->wide_idu) != 0) {
348				j |= 0x01;
349			}
350			outb(j, tmport);
351			while ((inb(tmport) & 0x01) != j)
352			{
353			   outb(j,tmport);
354			}
355
356			if (dev->id[target_id].last_lenu == 0) {
357				tmport = workportu + 0x18;
358				outb(0x08, tmport);
359				dev->in_int = 0;
360				return;
361			}
362			prd = dev->id[target_id].prd_posu;
363			while (adrcntu != 0)
364			{
365				id = ((unsigned short int *) (prd))[2];
366				if (id == 0) {
367					k = 0x10000;
368				} else {
369					k = id;
370				}
371				if (k > adrcntu) {
372					((unsigned short int *) (prd))[2] = (unsigned short int)
373					    (k - adrcntu);
374					((unsigned long *) (prd))[0] += adrcntu;
375					adrcntu = 0;
376					dev->id[target_id].prd_posu = prd;
377				} else {
378					adrcntu -= k;
379					dev->id[target_id].prdaddru += 0x08;
380					prd += 0x08;
381					if (adrcntu == 0) {
382						dev->id[target_id].prd_posu = prd;
383					}
384				}
385			}
386			tmpcip = dev->pciport + 0x04;
387			outl(dev->id[target_id].prdaddru, tmpcip);
388			tmpcip -= 0x02;
389			outb(0x06, tmpcip);
390			outb(0x00, tmpcip);
391			tmpcip -= 0x02;
392			tmport = workportu + 0x18;
393			/*
394			 *	Check transfer direction
395			 */
396			if (dev->id[target_id].dirctu != 0) {
397				outb(0x08, tmport);
398				outb(0x01, tmpcip);
399				dev->in_int = 0;
400				return;
401			}
402			outb(0x08, tmport);
403			outb(0x09, tmpcip);
404			dev->in_int = 0;
405			return;
406		}
407
408		/*
409		 *	Current scsi request on this target
410		 */
411
412		workrequ = dev->id[target_id].curr_req;
413
414		if (i == 0x42) {
415			if ((dev->last_cmd & 0xf0) != 0x40)
416			{
417			   dev->last_cmd = 0xff;
418			}
419			errstus = 0x02;
420			workrequ->result = errstus;
421			goto go_42;
422		}
423		if (i == 0x16)
424		{
425			if ((dev->last_cmd & 0xf0) != 0x40)
426			{
427			   dev->last_cmd = 0xff;
428			}
429			errstus = 0;
430			tmport -= 0x08;
431			errstus = inb(tmport);
432			workrequ->result = errstus;
433go_42:
434			/*
435			 *	Complete the command
436			 */
437			spin_lock_irqsave(&io_request_lock, flags);
438			(*workrequ->scsi_done) (workrequ);
439
440			/*
441			 *	Clear it off the queue
442			 */
443			dev->id[target_id].curr_req = 0;
444			dev->working--;
445			spin_unlock_irqrestore(&io_request_lock, flags);
446			/*
447			 *	Take it back wide
448			 */
449			if (dev->wide_idu != 0) {
450				tmport = workportu + 0x1b;
451				outb(0x01,tmport);
452				while ((inb(tmport) & 0x01) != 0x01)
453				{
454				   outb(0x01,tmport);
455				}
456			}
457			/*
458			 *	If there is stuff to send and nothing going then send it
459			 */
460			if (((dev->last_cmd != 0xff) || (dev->quhdu != dev->quendu)) &&
461			    (dev->in_snd == 0))
462			{
463			   send_s870(h);
464			}
465			dev->in_int = 0;
466			return;
467		}
468		if ((dev->last_cmd & 0xf0) != 0x40)
469		{
470		   dev->last_cmd = 0xff;
471		}
472		if (i == 0x4f) {
473			i = 0x89;
474		}
475		i &= 0x0f;
476		if (i == 0x09) {
477			tmpcip = tmpcip + 4;
478			outl(dev->id[target_id].prdaddru, tmpcip);
479			tmpcip = tmpcip - 2;
480			outb(0x06, tmpcip);
481			outb(0x00, tmpcip);
482			tmpcip = tmpcip - 2;
483			tmport = workportu + 0x10;
484			outb(0x41, tmport);
485			dev->id[target_id].dirctu = 0x00;
486			tmport += 0x08;
487			outb(0x08, tmport);
488			outb(0x09, tmpcip);
489			dev->in_int = 0;
490			return;
491		}
492		if (i == 0x08) {
493			tmpcip = tmpcip + 4;
494			outl(dev->id[target_id].prdaddru, tmpcip);
495			tmpcip = tmpcip - 2;
496			outb(0x06, tmpcip);
497			outb(0x00, tmpcip);
498			tmpcip = tmpcip - 2;
499			tmport = workportu + 0x10;
500			outb(0x41, tmport);
501			tmport += 0x05;
502			outb((unsigned char) (inb(tmport) | 0x20), tmport);
503			dev->id[target_id].dirctu = 0x20;
504			tmport += 0x03;
505			outb(0x08, tmport);
506			outb(0x01, tmpcip);
507			dev->in_int = 0;
508			return;
509		}
510		tmport -= 0x07;
511		if (i == 0x0a) {
512			outb(0x30, tmport);
513		} else {
514			outb(0x46, tmport);
515		}
516		dev->id[target_id].dirctu = 0x00;
517		tmport += 0x02;
518		outb(0x00, tmport++);
519		outb(0x00, tmport++);
520		outb(0x00, tmport++);
521		tmport += 0x03;
522		outb(0x08, tmport);
523		dev->in_int = 0;
524		return;
525	} else {
526//		tmport = workportu + 0x17;
527//		inb(tmport);
528//		dev->working = 0;
529		dev->in_int = 0;
530		return;
531	}
532}
533
534int atp870u_queuecommand(Scsi_Cmnd * req_p, void (*done) (Scsi_Cmnd *))
535{
536	unsigned char h;
537	unsigned long flags;
538	unsigned short int m;
539	unsigned int tmport;
540	struct atp_unit *dev;
541
542	for (h = 0; h <= admaxu; h++) {
543		if (req_p->host == atp_host[h]) {
544			goto host_ok;
545		}
546	}
547	return 0;
548host_ok:
549	if (req_p->channel != 0) {
550		req_p->result = 0x00040000;
551		done(req_p);
552		return 0;
553	}
554	dev = &atp_unit[h];
555	m = 1;
556	m = m << req_p->target;
557
558	/*
559	 *	Fake a timeout for missing targets
560	 */
561
562	if ((m & dev->active_idu) == 0) {
563		req_p->result = 0x00040000;
564		done(req_p);
565		return 0;
566	}
567	if (done) {
568		req_p->scsi_done = done;
569	} else {
570		printk(KERN_WARNING "atp870u_queuecommand: done can't be NULL\n");
571		req_p->result = 0;
572		done(req_p);
573		return 0;
574	}
575	/*
576	 *	Count new command
577	 */
578	save_flags(flags);
579	cli();
580	dev->quendu++;
581	if (dev->quendu >= qcnt) {
582		dev->quendu = 0;
583	}
584	/*
585	 *	Check queue state
586	 */
587	if (dev->quhdu == dev->quendu) {
588		if (dev->quendu == 0) {
589			dev->quendu = qcnt;
590		}
591		dev->quendu--;
592		req_p->result = 0x00020000;
593		done(req_p);
594		restore_flags(flags);
595		return 0;
596	}
597	dev->querequ[dev->quendu] = req_p;
598	tmport = dev->ioport + 0x1c;
599	restore_flags(flags);
600	if ((inb(tmport) == 0) && (dev->in_int == 0) && (dev->in_snd == 0)) {
601		send_s870(h);
602	}
603	return 0;
604}
605
606void mydlyu(unsigned int dlycnt)
607{
608	unsigned int i;
609	for (i = 0; i < dlycnt; i++) {
610		inb(0x80);
611	}
612}
613
614void send_s870(unsigned char h)
615{
616	unsigned int tmport;
617	Scsi_Cmnd *workrequ;
618	unsigned long flags;
619	unsigned int i;
620	unsigned char j, target_id;
621	unsigned char *prd;
622	unsigned short int tmpcip, w;
623	unsigned long l, bttl;
624	unsigned int workportu;
625	struct scatterlist *sgpnt;
626	struct atp_unit *dev = &atp_unit[h];
627
628	save_flags(flags);
629	cli();
630	if (dev->in_snd != 0) {
631		restore_flags(flags);
632		return;
633	}
634	dev->in_snd = 1;
635	if ((dev->last_cmd != 0xff) && ((dev->last_cmd & 0x40) != 0)) {
636		dev->last_cmd &= 0x0f;
637		workrequ = dev->id[dev->last_cmd].curr_req;
638		if (workrequ != NULL)	     /* check NULL pointer */
639		{
640		   goto cmd_subp;
641		}
642		dev->last_cmd = 0xff;
643		if (dev->quhdu == dev->quendu)
644		{
645		   dev->in_snd = 0;
646		   restore_flags(flags);
647		   return ;
648		}
649	}
650	if ((dev->last_cmd != 0xff) && (dev->working != 0))
651	{
652	     dev->in_snd = 0;
653	     restore_flags(flags);
654	     return ;
655	}
656	dev->working++;
657	j = dev->quhdu;
658	dev->quhdu++;
659	if (dev->quhdu >= qcnt) {
660		dev->quhdu = 0;
661	}
662	workrequ = dev->querequ[dev->quhdu];
663	if (dev->id[workrequ->target].curr_req == 0) {
664		dev->id[workrequ->target].curr_req = workrequ;
665		dev->last_cmd = workrequ->target;
666		goto cmd_subp;
667	}
668	dev->quhdu = j;
669	dev->working--;
670	dev->in_snd = 0;
671	restore_flags(flags);
672	return;
673cmd_subp:
674	workportu = dev->ioport;
675	tmport = workportu + 0x1f;
676	if ((inb(tmport) & 0xb0) != 0) {
677		goto abortsnd;
678	}
679	tmport = workportu + 0x1c;
680	if (inb(tmport) == 0) {
681		goto oktosend;
682	}
683abortsnd:
684	dev->last_cmd |= 0x40;
685	dev->in_snd = 0;
686	restore_flags(flags);
687	return;
688oktosend:
689	memcpy(&dev->ata_cdbu[0], &workrequ->cmnd[0], workrequ->cmd_len);
690	if (dev->ata_cdbu[0] == READ_CAPACITY) {
691		if (workrequ->request_bufflen > 8) {
692			workrequ->request_bufflen = 0x08;
693		}
694	}
695	if (dev->ata_cdbu[0] == 0x00) {
696		workrequ->request_bufflen = 0;
697	}
698
699	tmport = workportu + 0x1b;
700	j = 0;
701	target_id = workrequ->target;
702
703	/*
704	 *	Wide ?
705	 */
706	w = 1;
707	w = w << target_id;
708	if ((w & dev->wide_idu) != 0) {
709		j |= 0x01;
710	}
711	outb(j, tmport);
712	while ((inb(tmport) & 0x01) != j)
713	{
714	   outb(j,tmport);
715	}
716
717	/*
718	 *	Write the command
719	 */
720
721	tmport = workportu;
722	outb(workrequ->cmd_len, tmport++);
723	outb(0x2c, tmport++);
724	outb(0xcf, tmport++);
725	for (i = 0; i < workrequ->cmd_len; i++) {
726		outb(dev->ata_cdbu[i], tmport++);
727	}
728	tmport = workportu + 0x0f;
729	outb(workrequ->lun, tmport);
730	tmport += 0x02;
731	/*
732	 *	Write the target
733	 */
734	outb(dev->id[target_id].devspu, tmport++);
735
736	/*
737	 *	Figure out the transfer size
738	 */
739	if (workrequ->use_sg)
740	{
741		l = 0;
742		sgpnt = (struct scatterlist *) workrequ->request_buffer;
743		for (i = 0; i < workrequ->use_sg; i++)
744		{
745			if (sgpnt[i].length == 0 || workrequ->use_sg > ATP870U_SCATTER)
746			{
747				panic("Foooooooood fight!");
748			}
749			l += sgpnt[i].length;
750		}
751	} else {
752		l = workrequ->request_bufflen;
753	}
754	/*
755	 *	Write transfer size
756	 */
757	outb((unsigned char) (((unsigned char *) (&l))[2]), tmport++);
758	outb((unsigned char) (((unsigned char *) (&l))[1]), tmport++);
759	outb((unsigned char) (((unsigned char *) (&l))[0]), tmport++);
760	j = target_id;
761	dev->id[j].last_lenu = l;
762	dev->id[j].tran_lenu = 0;
763	/*
764	 *	Flip the wide bits
765	 */
766	if ((j & 0x08) != 0) {
767		j = (j & 0x07) | 0x40;
768	}
769	/*
770	 *	Check transfer direction
771	 */
772	if ((dev->ata_cdbu[0] == WRITE_6) || (dev->ata_cdbu[0] == WRITE_10) ||
773	    (dev->ata_cdbu[0] == WRITE_12) || (dev->ata_cdbu[0] == MODE_SELECT)) {
774		outb((unsigned char) (j | 0x20), tmport++);
775	} else {
776		outb(j, tmport++);
777	}
778	outb((unsigned char)(inb(tmport) | 0x80),tmport);
779	outb(0x80, tmport);
780	tmport = workportu + 0x1c;
781	dev->id[target_id].dirctu = 0;
782	if (l == 0) {
783		if (inb(tmport) == 0) {
784			tmport = workportu + 0x18;
785			outb(0x08, tmport);
786		} else {
787			dev->last_cmd |= 0x40;
788		}
789		dev->in_snd = 0;
790		restore_flags(flags);
791		return;
792	}
793	tmpcip = dev->pciport;
794	prd = dev->id[target_id].prd_tableu;
795	dev->id[target_id].prd_posu = prd;
796
797	/*
798	 *	Now write the request list. Either as scatter/gather or as
799	 *	a linear chain.
800	 */
801
802	if (workrequ->use_sg)
803	{
804		sgpnt = (struct scatterlist *) workrequ->request_buffer;
805		i = 0;
806		for (j = 0; j < workrequ->use_sg; j++) {
807			bttl = virt_to_bus(sgpnt[j].address);
808			l = sgpnt[j].length;
809			while (l > 0x10000) {
810				(unsigned short int) (((unsigned short int *) (prd))[i + 3]) = 0x0000;
811				(unsigned short int) (((unsigned short int *) (prd))[i + 2]) = 0x0000;
812				(unsigned long) (((unsigned long *) (prd))[i >> 1]) = bttl;
813				l -= 0x10000;
814				bttl += 0x10000;
815				i += 0x04;
816			}
817			(unsigned long) (((unsigned long *) (prd))[i >> 1]) = bttl;
818			(unsigned short int) (((unsigned short int *) (prd))[i + 2]) = l;
819			(unsigned short int) (((unsigned short int *) (prd))[i + 3]) = 0;
820			i += 0x04;
821		}
822		(unsigned short int) (((unsigned short int *) (prd))[i - 1]) = 0x8000;
823	} else {
824		/*
825		 *	For a linear request write a chain of blocks
826		 */
827		bttl = virt_to_bus(workrequ->request_buffer);
828		l = workrequ->request_bufflen;
829		i = 0;
830		while (l > 0x10000) {
831			(unsigned short int) (((unsigned short int *) (prd))[i + 3]) = 0x0000;
832			(unsigned short int) (((unsigned short int *) (prd))[i + 2]) = 0x0000;
833			(unsigned long) (((unsigned long *) (prd))[i >> 1]) = bttl;
834			l -= 0x10000;
835			bttl += 0x10000;
836			i += 0x04;
837		}
838		(unsigned short int) (((unsigned short int *) (prd))[i + 3]) = 0x8000;
839		(unsigned short int) (((unsigned short int *) (prd))[i + 2]) = l;
840		(unsigned long) (((unsigned long *) (prd))[i >> 1]) = bttl;
841	}
842	tmpcip = tmpcip + 4;
843	dev->id[target_id].prdaddru = virt_to_bus(dev->id[target_id].prd_tableu);
844	outl(dev->id[target_id].prdaddru, tmpcip);
845	tmpcip = tmpcip - 2;
846	outb(0x06, tmpcip);
847	outb(0x00, tmpcip);
848	tmpcip = tmpcip - 2;
849
850	if (dev->deviceid != 0x8081)
851	{
852	   tmport = workportu + 0x3a;
853	   if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) ||
854	       (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a))
855	   {
856	      outb((unsigned char)((inb(tmport) & 0xf3) | 0x08),tmport);
857	   }
858	   else
859	   {
860	      outb((unsigned char)(inb(tmport) & 0xf3),tmport);
861	   }
862	}
863	else
864	{
865	   tmport = workportu - 0x05;
866	   if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) ||
867	       (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a))
868	   {
869	      outb((unsigned char)((inb(tmport) & 0x3f) | 0xc0),tmport);
870	   }
871	   else
872	   {
873	      outb((unsigned char)(inb(tmport) & 0x3f),tmport);
874	   }
875	}
876	tmport = workportu + 0x1c;
877
878	if ((dev->ata_cdbu[0] == WRITE_6) || (dev->ata_cdbu[0] == WRITE_10) ||
879	    (dev->ata_cdbu[0] == WRITE_12) || (dev->ata_cdbu[0] == MODE_SELECT))
880	{
881		dev->id[target_id].dirctu = 0x20;
882		if (inb(tmport) == 0) {
883			tmport = workportu + 0x18;
884			outb(0x08, tmport);
885			outb(0x01, tmpcip);
886		} else {
887			dev->last_cmd |= 0x40;
888		}
889		dev->in_snd = 0;
890		restore_flags(flags);
891		return;
892	}
893	if (inb(tmport) == 0)
894	{
895		tmport = workportu + 0x18;
896		outb(0x08, tmport);
897		outb(0x09, tmpcip);
898	} else {
899		dev->last_cmd |= 0x40;
900	}
901	dev->in_snd = 0;
902	restore_flags(flags);
903	return;
904
905}
906
907static void internal_done(Scsi_Cmnd * SCpnt)
908{
909	SCpnt->SCp.Status++;
910}
911
912int atp870u_command(Scsi_Cmnd * SCpnt)
913{
914
915	atp870u_queuecommand(SCpnt, internal_done);
916
917	SCpnt->SCp.Status = 0;
918	while (!SCpnt->SCp.Status)
919		barrier();
920	return SCpnt->result;
921}
922
923unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val)
924{
925	unsigned int tmport;
926	unsigned short int i, k;
927	unsigned char j;
928
929	tmport = dev->ioport + 0x1c;
930	outw(*val, tmport);
931FUN_D7:
932	for (i = 0; i < 10; i++) {	/* stable >= bus settle delay(400 ns)  */
933		k = inw(tmport);
934		j = (unsigned char) (k >> 8);
935		if ((k & 0x8000) != 0) {	/* DB7 all release?    */
936			goto FUN_D7;
937		}
938	}
939	*val |= 0x4000; 	/* assert DB6		*/
940	outw(*val, tmport);
941	*val &= 0xdfff; 	/* assert DB5		*/
942	outw(*val, tmport);
943FUN_D5:
944	for (i = 0; i < 10; i++) {	/* stable >= bus settle delay(400 ns) */
945		if ((inw(tmport) & 0x2000) != 0) {	/* DB5 all release?	  */
946			goto FUN_D5;
947		}
948	}
949	*val |= 0x8000; 	/* no DB4-0, assert DB7    */
950	*val &= 0xe0ff;
951	outw(*val, tmport);
952	*val &= 0xbfff; 	/* release DB6		   */
953	outw(*val, tmport);
954      FUN_D6:
955	for (i = 0; i < 10; i++) {	/* stable >= bus settle delay(400 ns)  */
956		if ((inw(tmport) & 0x4000) != 0) {	/* DB6 all release?  */
957			goto FUN_D6;
958		}
959	}
960
961	return j;
962}
963
964void tscam(unsigned char host)
965{
966
967	unsigned int tmport;
968	unsigned char i, j, k;
969	unsigned long n;
970	unsigned short int m, assignid_map, val;
971	unsigned char mbuf[33], quintet[2];
972	struct atp_unit *dev = &atp_unit[host];
973	static unsigned char g2q_tab[8] = {
974		0x38, 0x31, 0x32, 0x2b, 0x34, 0x2d, 0x2e, 0x27
975	};
976
977
978	for (i = 0; i < 0x10; i++) {
979		mydlyu(0xffff);
980	}
981
982	tmport = dev->ioport + 1;
983	outb(0x08, tmport++);
984	outb(0x7f, tmport);
985	tmport = dev->ioport + 0x11;
986	outb(0x20, tmport);
987
988	if ((dev->scam_on & 0x40) == 0) {
989		return;
990	}
991	m = 1;
992	m <<= dev->host_idu;
993	j = 16;
994	if (dev->chip_veru < 4) {
995		m |= 0xff00;
996		j = 8;
997	}
998	assignid_map = m;
999	tmport = dev->ioport + 0x02;
1000	outb(0x02, tmport++);	/* 2*2=4ms,3EH 2/32*3E=3.9ms */
1001	outb(0, tmport++);
1002	outb(0, tmport++);
1003	outb(0, tmport++);
1004	outb(0, tmport++);
1005	outb(0, tmport++);
1006	outb(0, tmport++);
1007
1008	for (i = 0; i < j; i++) {
1009		m = 1;
1010		m = m << i;
1011		if ((m & assignid_map) != 0) {
1012			continue;
1013		}
1014		tmport = dev->ioport + 0x0f;
1015		outb(0, tmport++);
1016		tmport += 0x02;
1017		outb(0, tmport++);
1018		outb(0, tmport++);
1019		outb(0, tmport++);
1020		if (i > 7) {
1021			k = (i & 0x07) | 0x40;
1022		} else {
1023			k = i;
1024		}
1025		outb(k, tmport++);
1026		tmport = dev->ioport + 0x1b;
1027		if (dev->chip_veru == 4) {
1028			outb(0x01, tmport);
1029		} else {
1030			outb(0x00, tmport);
1031		}
1032wait_rdyok:
1033		tmport = dev->ioport + 0x18;
1034		outb(0x09, tmport);
1035		tmport += 0x07;
1036
1037		while ((inb(tmport) & 0x80) == 0x00);
1038		tmport -= 0x08;
1039		k = inb(tmport);
1040		if (k != 0x16) {
1041			if ((k == 0x85) || (k == 0x42)) {
1042				continue;
1043			}
1044			tmport = dev->ioport + 0x10;
1045			outb(0x41, tmport);
1046			goto wait_rdyok;
1047		}
1048		assignid_map |= m;
1049
1050	}
1051	tmport = dev->ioport + 0x02;
1052	outb(0x7f, tmport);
1053	tmport = dev->ioport + 0x1b;
1054	outb(0x02, tmport);
1055
1056	outb(0, 0x80);
1057
1058	val = 0x0080;		/* bsy	*/
1059	tmport = dev->ioport + 0x1c;
1060	outw(val, tmport);
1061	val |= 0x0040;		/* sel	*/
1062	outw(val, tmport);
1063	val |= 0x0004;		/* msg	*/
1064	outw(val, tmport);
1065	inb(0x80);		/* 2 deskew delay(45ns*2=90ns) */
1066	val &= 0x007f;		/* no bsy  */
1067	outw(val, tmport);
1068	mydlyu(0xffff); 	/* recommanded SCAM selection response time */
1069	mydlyu(0xffff);
1070	val &= 0x00fb;		/* after 1ms no msg */
1071	outw(val, tmport);
1072wait_nomsg:
1073	if ((inb(tmport) & 0x04) != 0) {
1074		goto wait_nomsg;
1075	}
1076	outb(1, 0x80);
1077	mydlyu(100);
1078	for (n = 0; n < 0x30000; n++) {
1079		if ((inb(tmport) & 0x80) != 0) {	/* bsy ? */
1080			goto wait_io;
1081		}
1082	}
1083	goto TCM_SYNC;
1084wait_io:
1085	for (n = 0; n < 0x30000; n++) {
1086		if ((inb(tmport) & 0x81) == 0x0081) {
1087			goto wait_io1;
1088		}
1089	}
1090	goto TCM_SYNC;
1091wait_io1:
1092	inb(0x80);
1093	val |= 0x8003;		/* io,cd,db7  */
1094	outw(val, tmport);
1095	inb(0x80);
1096	val &= 0x00bf;		/* no sel     */
1097	outw(val, tmport);
1098	outb(2, 0x80);
1099TCM_SYNC:
1100	mydlyu(0x800);
1101	if ((inb(tmport) & 0x80) == 0x00) {	/* bsy ? */
1102		outw(0, tmport--);
1103		outb(0, tmport);
1104		tmport = dev->ioport + 0x15;
1105		outb(0, tmport);
1106		tmport += 0x03;
1107		outb(0x09, tmport);
1108		tmport += 0x07;
1109		while ((inb(tmport) & 0x80) == 0);
1110		tmport -= 0x08;
1111		inb(tmport);
1112		return;
1113	}
1114	val &= 0x00ff;		/* synchronization  */
1115	val |= 0x3f00;
1116	fun_scam(dev, &val);
1117	outb(3, 0x80);
1118	val &= 0x00ff;		/* isolation	    */
1119	val |= 0x2000;
1120	fun_scam(dev, &val);
1121	outb(4, 0x80);
1122	i = 8;
1123	j = 0;
1124TCM_ID:
1125	if ((inw(tmport) & 0x2000) == 0) {
1126		goto TCM_ID;
1127	}
1128	outb(5, 0x80);
1129	val &= 0x00ff;		/* get ID_STRING */
1130	val |= 0x2000;
1131	k = fun_scam(dev, &val);
1132	if ((k & 0x03) == 0) {
1133		goto TCM_5;
1134	}
1135	mbuf[j] <<= 0x01;
1136	mbuf[j] &= 0xfe;
1137	if ((k & 0x02) != 0) {
1138		mbuf[j] |= 0x01;
1139	}
1140	i--;
1141	if (i > 0) {
1142		goto TCM_ID;
1143	}
1144	j++;
1145	i = 8;
1146	goto TCM_ID;
1147
1148TCM_5:			/* isolation complete..  */
1149/*    mbuf[32]=0;
1150	printk(" \n%x %x %x %s\n ",assignid_map,mbuf[0],mbuf[1],&mbuf[2]); */
1151	i = 15;
1152	j = mbuf[0];
1153	if ((j & 0x20) != 0) {	/* bit5=1:ID upto 7	 */
1154		i = 7;
1155	}
1156	if ((j & 0x06) == 0) {	/* IDvalid?		*/
1157		goto G2Q5;
1158	}
1159	k = mbuf[1];
1160small_id:
1161	m = 1;
1162	m <<= k;
1163	if ((m & assignid_map) == 0) {
1164		goto G2Q_QUIN;
1165	}
1166	if (k > 0) {
1167		k--;
1168		goto small_id;
1169	}
1170G2Q5:				/* srch from max acceptable ID#  */
1171	k = i;			/* max acceptable ID#		 */
1172G2Q_LP:
1173	m = 1;
1174	m <<= k;
1175	if ((m & assignid_map) == 0) {
1176		goto G2Q_QUIN;
1177	}
1178	if (k > 0) {
1179		k--;
1180		goto G2Q_LP;
1181	}
1182G2Q_QUIN:		/* k=binID#,	   */
1183	assignid_map |= m;
1184	if (k < 8) {
1185		quintet[0] = 0x38;	/* 1st dft ID<8    */
1186	} else {
1187		quintet[0] = 0x31;	/* 1st	ID>=8	   */
1188	}
1189	k &= 0x07;
1190	quintet[1] = g2q_tab[k];
1191
1192	val &= 0x00ff;		/* AssignID 1stQuintet,AH=001xxxxx  */
1193	m = quintet[0] << 8;
1194	val |= m;
1195	fun_scam(dev, &val);
1196	val &= 0x00ff;		/* AssignID 2ndQuintet,AH=001xxxxx */
1197	m = quintet[1] << 8;
1198	val |= m;
1199	fun_scam(dev, &val);
1200
1201	goto TCM_SYNC;
1202
1203}
1204
1205void is870(unsigned long host, unsigned int wkport)
1206{
1207	unsigned int tmport;
1208	unsigned char i, j, k, rmb, n;
1209	unsigned short int m;
1210	static unsigned char mbuf[512];
1211	static unsigned char satn[9] =	{0, 0, 0, 0, 0, 0, 0, 6, 6};
1212	static unsigned char inqd[9] =	{0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6};
1213	static unsigned char synn[6] =	{0x80, 1, 3, 1, 0x19, 0x0e};
1214	static unsigned char synu[6] =	{0x80, 1, 3, 1, 0x0c, 0x0e};
1215	static unsigned char synw[6] =	{0x80, 1, 3, 1, 0x0c, 0x07};
1216	static unsigned char wide[6] =	{0x80, 1, 2, 3, 1, 0};
1217	struct atp_unit *dev = &atp_unit[host];
1218
1219	sync_idu = 0;
1220	tmport = wkport + 0x3a;
1221	outb((unsigned char) (inb(tmport) | 0x10), tmport);
1222
1223	for (i = 0; i < 16; i++) {
1224		if ((dev->chip_veru != 4) && (i > 7)) {
1225			break;
1226		}
1227		m = 1;
1228		m = m << i;
1229		if ((m & dev->active_idu) != 0) {
1230			continue;
1231		}
1232		if (i == dev->host_idu) {
1233			printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_idu);
1234			continue;
1235		}
1236		tmport = wkport + 0x1b;
1237		if (dev->chip_veru == 4) {
1238		   outb(0x01, tmport);
1239		}
1240		else
1241		{
1242		   outb(0x00, tmport);
1243		}
1244		tmport = wkport + 1;
1245		outb(0x08, tmport++);
1246		outb(0x7f, tmport++);
1247		outb(satn[0], tmport++);
1248		outb(satn[1], tmport++);
1249		outb(satn[2], tmport++);
1250		outb(satn[3], tmport++);
1251		outb(satn[4], tmport++);
1252		outb(satn[5], tmport++);
1253		tmport += 0x06;
1254		outb(0, tmport);
1255		tmport += 0x02;
1256		outb(dev->id[i].devspu, tmport++);
1257		outb(0, tmport++);
1258		outb(satn[6], tmport++);
1259		outb(satn[7], tmport++);
1260		j = i;
1261		if ((j & 0x08) != 0) {
1262			j = (j & 0x07) | 0x40;
1263		}
1264		outb(j, tmport);
1265		tmport += 0x03;
1266		outb(satn[8], tmport);
1267		tmport += 0x07;
1268
1269		while ((inb(tmport) & 0x80) == 0x00);
1270		tmport -= 0x08;
1271		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
1272			continue;
1273		}
1274		while (inb(tmport) != 0x8e);
1275		dev->active_idu |= m;
1276
1277		tmport = wkport + 0x10;
1278		outb(0x30, tmport);
1279		tmport = wkport + 0x04;
1280		outb(0x00, tmport);
1281
1282phase_cmd:
1283		tmport = wkport + 0x18;
1284		outb(0x08, tmport);
1285		tmport += 0x07;
1286		while ((inb(tmport) & 0x80) == 0x00);
1287		tmport -= 0x08;
1288		j = inb(tmport);
1289		if (j != 0x16) {
1290			tmport = wkport + 0x10;
1291			outb(0x41, tmport);
1292			goto phase_cmd;
1293		}
1294sel_ok:
1295		tmport = wkport + 3;
1296		outb(inqd[0], tmport++);
1297		outb(inqd[1], tmport++);
1298		outb(inqd[2], tmport++);
1299		outb(inqd[3], tmport++);
1300		outb(inqd[4], tmport++);
1301		outb(inqd[5], tmport);
1302		tmport += 0x07;
1303		outb(0, tmport);
1304		tmport += 0x02;
1305		outb(dev->id[i].devspu, tmport++);
1306		outb(0, tmport++);
1307		outb(inqd[6], tmport++);
1308		outb(inqd[7], tmport++);
1309		tmport += 0x03;
1310		outb(inqd[8], tmport);
1311		tmport += 0x07;
1312		while ((inb(tmport) & 0x80) == 0x00);
1313		tmport -= 0x08;
1314		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
1315			continue;
1316		}
1317		while (inb(tmport) != 0x8e);
1318		tmport = wkport + 0x1b;
1319		if (dev->chip_veru == 4) {
1320			outb(0x00, tmport);
1321		}
1322		tmport = wkport + 0x18;
1323		outb(0x08, tmport);
1324		tmport += 0x07;
1325		j = 0;
1326rd_inq_data:
1327		k = inb(tmport);
1328		if ((k & 0x01) != 0) {
1329			tmport -= 0x06;
1330			mbuf[j++] = inb(tmport);
1331			tmport += 0x06;
1332			goto rd_inq_data;
1333		}
1334		if ((k & 0x80) == 0) {
1335			goto rd_inq_data;
1336		}
1337		tmport -= 0x08;
1338		j = inb(tmport);
1339		if (j == 0x16) {
1340			goto inq_ok;
1341		}
1342		tmport = wkport + 0x10;
1343		outb(0x46, tmport);
1344		tmport += 0x02;
1345		outb(0, tmport++);
1346		outb(0, tmport++);
1347		outb(0, tmport++);
1348		tmport += 0x03;
1349		outb(0x08, tmport);
1350		tmport += 0x07;
1351		while ((inb(tmport) & 0x80) == 0x00);
1352		tmport -= 0x08;
1353		if (inb(tmport) != 0x16) {
1354			goto sel_ok;
1355		}
1356inq_ok:
1357		mbuf[36] = 0;
1358		printk(KERN_INFO "         ID: %2d  %s\n", i, &mbuf[8]);
1359		dev->id[i].devtypeu = mbuf[0];
1360		rmb = mbuf[1];
1361		n = mbuf[7];
1362		if (dev->chip_veru != 4) {
1363			goto not_wide;
1364		}
1365		if ((mbuf[7] & 0x60) == 0) {
1366			goto not_wide;
1367		}
1368		if ((dev->global_map & 0x20) == 0) {
1369			goto not_wide;
1370		}
1371		tmport = wkport + 0x1b;
1372		outb(0x01, tmport);
1373		tmport = wkport + 3;
1374		outb(satn[0], tmport++);
1375		outb(satn[1], tmport++);
1376		outb(satn[2], tmport++);
1377		outb(satn[3], tmport++);
1378		outb(satn[4], tmport++);
1379		outb(satn[5], tmport++);
1380		tmport += 0x06;
1381		outb(0, tmport);
1382		tmport += 0x02;
1383		outb(dev->id[i].devspu, tmport++);
1384		outb(0, tmport++);
1385		outb(satn[6], tmport++);
1386		outb(satn[7], tmport++);
1387		tmport += 0x03;
1388		outb(satn[8], tmport);
1389		tmport += 0x07;
1390
1391		while ((inb(tmport) & 0x80) == 0x00);
1392		tmport -= 0x08;
1393		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
1394			continue;
1395		}
1396		while (inb(tmport) != 0x8e);
1397try_wide:
1398		j = 0;
1399		tmport = wkport + 0x14;
1400		outb(0x05, tmport);
1401		tmport += 0x04;
1402		outb(0x20, tmport);
1403		tmport += 0x07;
1404
1405		while ((inb(tmport) & 0x80) == 0) {
1406			if ((inb(tmport) & 0x01) != 0) {
1407				tmport -= 0x06;
1408				outb(wide[j++], tmport);
1409				tmport += 0x06;
1410			}
1411		}
1412		tmport -= 0x08;
1413		while ((inb(tmport) & 0x80) == 0x00);
1414		j = inb(tmport) & 0x0f;
1415		if (j == 0x0f) {
1416			goto widep_in;
1417		}
1418		if (j == 0x0a) {
1419			goto widep_cmd;
1420		}
1421		if (j == 0x0e) {
1422			goto try_wide;
1423		}
1424		continue;
1425widep_out:
1426		tmport = wkport + 0x18;
1427		outb(0x20, tmport);
1428		tmport += 0x07;
1429		while ((inb(tmport) & 0x80) == 0) {
1430			if ((inb(tmport) & 0x01) != 0) {
1431				tmport -= 0x06;
1432				outb(0, tmport);
1433				tmport += 0x06;
1434			}
1435		}
1436		tmport -= 0x08;
1437		j = inb(tmport) & 0x0f;
1438		if (j == 0x0f) {
1439			goto widep_in;
1440		}
1441		if (j == 0x0a) {
1442			goto widep_cmd;
1443		}
1444		if (j == 0x0e) {
1445			goto widep_out;
1446		}
1447		continue;
1448widep_in:
1449		tmport = wkport + 0x14;
1450		outb(0xff, tmport);
1451		tmport += 0x04;
1452		outb(0x20, tmport);
1453		tmport += 0x07;
1454		k = 0;
1455widep_in1:
1456		j = inb(tmport);
1457		if ((j & 0x01) != 0) {
1458			tmport -= 0x06;
1459			mbuf[k++] = inb(tmport);
1460			tmport += 0x06;
1461			goto widep_in1;
1462		}
1463		if ((j & 0x80) == 0x00) {
1464			goto widep_in1;
1465		}
1466		tmport -= 0x08;
1467		j = inb(tmport) & 0x0f;
1468		if (j == 0x0f) {
1469			goto widep_in;
1470		}
1471		if (j == 0x0a) {
1472			goto widep_cmd;
1473		}
1474		if (j == 0x0e) {
1475			goto widep_out;
1476		}
1477		continue;
1478widep_cmd:
1479		tmport = wkport + 0x10;
1480		outb(0x30, tmport);
1481		tmport = wkport + 0x14;
1482		outb(0x00, tmport);
1483		tmport += 0x04;
1484		outb(0x08, tmport);
1485		tmport += 0x07;
1486		while ((inb(tmport) & 0x80) == 0x00);
1487		tmport -= 0x08;
1488		j = inb(tmport);
1489		if (j != 0x16) {
1490			if (j == 0x4e) {
1491				goto widep_out;
1492			}
1493			continue;
1494		}
1495		if (mbuf[0] != 0x01) {
1496			goto not_wide;
1497		}
1498		if (mbuf[1] != 0x02) {
1499			goto not_wide;
1500		}
1501		if (mbuf[2] != 0x03) {
1502			goto not_wide;
1503		}
1504		if (mbuf[3] != 0x01) {
1505			goto not_wide;
1506		}
1507		m = 1;
1508		m = m << i;
1509		dev->wide_idu |= m;
1510not_wide:
1511		if ((dev->id[i].devtypeu == 0x00) || (dev->id[i].devtypeu == 0x07) ||
1512		    ((dev->id[i].devtypeu == 0x05) && ((n & 0x10) != 0)))
1513		{
1514			goto set_sync;
1515		}
1516		continue;
1517set_sync:
1518		tmport = wkport + 0x1b;
1519		j = 0;
1520		if ((m & dev->wide_idu) != 0) {
1521			j |= 0x01;
1522		}
1523		outb(j, tmport);
1524		tmport = wkport + 3;
1525		outb(satn[0], tmport++);
1526		outb(satn[1], tmport++);
1527		outb(satn[2], tmport++);
1528		outb(satn[3], tmport++);
1529		outb(satn[4], tmport++);
1530		outb(satn[5], tmport++);
1531		tmport += 0x06;
1532		outb(0, tmport);
1533		tmport += 0x02;
1534		outb(dev->id[i].devspu, tmport++);
1535		outb(0, tmport++);
1536		outb(satn[6], tmport++);
1537		outb(satn[7], tmport++);
1538		tmport += 0x03;
1539		outb(satn[8], tmport);
1540		tmport += 0x07;
1541
1542		while ((inb(tmport) & 0x80) == 0x00);
1543		tmport -= 0x08;
1544		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
1545			continue;
1546		}
1547		while (inb(tmport) != 0x8e);
1548try_sync:
1549		j = 0;
1550		tmport = wkport + 0x14;
1551		outb(0x06, tmport);
1552		tmport += 0x04;
1553		outb(0x20, tmport);
1554		tmport += 0x07;
1555
1556		while ((inb(tmport) & 0x80) == 0) {
1557			if ((inb(tmport) & 0x01) != 0) {
1558				tmport -= 0x06;
1559				if ((m & dev->wide_idu) != 0) {
1560					outb(synw[j++], tmport);
1561				} else {
1562					if ((m & dev->ultra_map) != 0) {
1563						outb(synu[j++], tmport);
1564					} else {
1565						outb(synn[j++], tmport);
1566					}
1567				}
1568				tmport += 0x06;
1569			}
1570		}
1571		tmport -= 0x08;
1572		while ((inb(tmport) & 0x80) == 0x00);
1573		j = inb(tmport) & 0x0f;
1574		if (j == 0x0f) {
1575			goto phase_ins;
1576		}
1577		if (j == 0x0a) {
1578			goto phase_cmds;
1579		}
1580		if (j == 0x0e) {
1581			goto try_sync;
1582		}
1583		continue;
1584phase_outs:
1585		tmport = wkport + 0x18;
1586		outb(0x20, tmport);
1587		tmport += 0x07;
1588		while ((inb(tmport) & 0x80) == 0x00) {
1589			if ((inb(tmport) & 0x01) != 0x00) {
1590				tmport -= 0x06;
1591				outb(0x00, tmport);
1592				tmport += 0x06;
1593			}
1594		}
1595		tmport -= 0x08;
1596		j = inb(tmport);
1597		if (j == 0x85) {
1598			goto tar_dcons;
1599		}
1600		j &= 0x0f;
1601		if (j == 0x0f) {
1602			goto phase_ins;
1603		}
1604		if (j == 0x0a) {
1605			goto phase_cmds;
1606		}
1607		if (j == 0x0e) {
1608			goto phase_outs;
1609		}
1610		continue;
1611phase_ins:
1612		tmport = wkport + 0x14;
1613		outb(0xff, tmport);
1614		tmport += 0x04;
1615		outb(0x20, tmport);
1616		tmport += 0x07;
1617		k = 0;
1618phase_ins1:
1619		j = inb(tmport);
1620		if ((j & 0x01) != 0x00) {
1621			tmport -= 0x06;
1622			mbuf[k++] = inb(tmport);
1623			tmport += 0x06;
1624			goto phase_ins1;
1625		}
1626		if ((j & 0x80) == 0x00) {
1627			goto phase_ins1;
1628		}
1629		tmport -= 0x08;
1630		while ((inb(tmport) & 0x80) == 0x00);
1631		j = inb(tmport);
1632		if (j == 0x85) {
1633			goto tar_dcons;
1634		}
1635		j &= 0x0f;
1636		if (j == 0x0f) {
1637			goto phase_ins;
1638		}
1639		if (j == 0x0a) {
1640			goto phase_cmds;
1641		}
1642		if (j == 0x0e) {
1643			goto phase_outs;
1644		}
1645		continue;
1646phase_cmds:
1647		tmport = wkport + 0x10;
1648		outb(0x30, tmport);
1649tar_dcons:
1650		tmport = wkport + 0x14;
1651		outb(0x00, tmport);
1652		tmport += 0x04;
1653		outb(0x08, tmport);
1654		tmport += 0x07;
1655		while ((inb(tmport) & 0x80) == 0x00);
1656		tmport -= 0x08;
1657		j = inb(tmport);
1658		if (j != 0x16) {
1659			continue;
1660		}
1661		if (mbuf[0] != 0x01) {
1662			continue;
1663		}
1664		if (mbuf[1] != 0x03) {
1665			continue;
1666		}
1667		if (mbuf[4] == 0x00) {
1668			continue;
1669		}
1670		if (mbuf[3] > 0x64) {
1671			continue;
1672		}
1673		if (mbuf[4] > 0x0c) {
1674			mbuf[4] = 0x0c;
1675		}
1676		dev->id[i].devspu = mbuf[4];
1677		if ((mbuf[3] < 0x0d) && (rmb == 0)) {
1678			j = 0xa0;
1679			goto set_syn_ok;
1680		}
1681		if (mbuf[3] < 0x1a) {
1682			j = 0x20;
1683			goto set_syn_ok;
1684		}
1685		if (mbuf[3] < 0x33) {
1686			j = 0x40;
1687			goto set_syn_ok;
1688		}
1689		if (mbuf[3] < 0x4c) {
1690			j = 0x50;
1691			goto set_syn_ok;
1692		}
1693		j = 0x60;
1694	      set_syn_ok:
1695		dev->id[i].devspu = (dev->id[i].devspu & 0x0f) | j;
1696	}
1697	tmport = wkport + 0x3a;
1698	outb((unsigned char) (inb(tmport) & 0xef), tmport);
1699}
1700
1701void is880(unsigned long host, unsigned int wkport)
1702{
1703	unsigned int tmport;
1704	unsigned char i, j, k, rmb, n, lvdmode;
1705	unsigned short int m;
1706	static unsigned char mbuf[512];
1707	static unsigned char satn[9] =	{0, 0, 0, 0, 0, 0, 0, 6, 6};
1708	static unsigned char inqd[9] =	{0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6};
1709	static unsigned char synn[6] =	{0x80, 1, 3, 1, 0x19, 0x0e};
1710	unsigned char synu[6] =  {0x80, 1, 3, 1, 0x0a, 0x0e};
1711	static unsigned char synw[6] =	{0x80, 1, 3, 1, 0x19, 0x0e};
1712	unsigned char synuw[6] =  {0x80, 1, 3, 1, 0x0a, 0x0e};
1713	static unsigned char wide[6] =	{0x80, 1, 2, 3, 1, 0};
1714	static unsigned char u3[9] = { 0x80,1,6,4,0x09,00,0x0e,0x01,0x02 };
1715	struct atp_unit *dev = &atp_unit[host];
1716
1717	sync_idu = 0;
1718	lvdmode=inb(wkport + 0x3f) & 0x40;
1719
1720	for (i = 0; i < 16; i++) {
1721		m = 1;
1722		m = m << i;
1723		if ((m & dev->active_idu) != 0) {
1724			continue;
1725		}
1726		if (i == dev->host_idu) {
1727			printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_idu);
1728			continue;
1729		}
1730		tmport = wkport + 0x5b;
1731		outb(0x01, tmport);
1732		tmport = wkport + 0x41;
1733		outb(0x08, tmport++);
1734		outb(0x7f, tmport++);
1735		outb(satn[0], tmport++);
1736		outb(satn[1], tmport++);
1737		outb(satn[2], tmport++);
1738		outb(satn[3], tmport++);
1739		outb(satn[4], tmport++);
1740		outb(satn[5], tmport++);
1741		tmport += 0x06;
1742		outb(0, tmport);
1743		tmport += 0x02;
1744		outb(dev->id[i].devspu, tmport++);
1745		outb(0, tmport++);
1746		outb(satn[6], tmport++);
1747		outb(satn[7], tmport++);
1748		j = i;
1749		if ((j & 0x08) != 0) {
1750			j = (j & 0x07) | 0x40;
1751		}
1752		outb(j, tmport);
1753		tmport += 0x03;
1754		outb(satn[8], tmport);
1755		tmport += 0x07;
1756
1757		while ((inb(tmport) & 0x80) == 0x00);
1758		tmport -= 0x08;
1759		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
1760			continue;
1761		}
1762		while (inb(tmport) != 0x8e);
1763		dev->active_idu |= m;
1764
1765		tmport = wkport + 0x50;
1766		outb(0x30, tmport);
1767		tmport = wkport + 0x54;
1768		outb(0x00, tmport);
1769
1770phase_cmd:
1771		tmport = wkport + 0x58;
1772		outb(0x08, tmport);
1773		tmport += 0x07;
1774		while ((inb(tmport) & 0x80) == 0x00);
1775		tmport -= 0x08;
1776		j = inb(tmport);
1777		if (j != 0x16) {
1778			tmport = wkport + 0x50;
1779			outb(0x41, tmport);
1780			goto phase_cmd;
1781		}
1782sel_ok:
1783		tmport = wkport + 0x43;
1784		outb(inqd[0], tmport++);
1785		outb(inqd[1], tmport++);
1786		outb(inqd[2], tmport++);
1787		outb(inqd[3], tmport++);
1788		outb(inqd[4], tmport++);
1789		outb(inqd[5], tmport);
1790		tmport += 0x07;
1791		outb(0, tmport);
1792		tmport += 0x02;
1793		outb(dev->id[i].devspu, tmport++);
1794		outb(0, tmport++);
1795		outb(inqd[6], tmport++);
1796		outb(inqd[7], tmport++);
1797		tmport += 0x03;
1798		outb(inqd[8], tmport);
1799		tmport += 0x07;
1800		while ((inb(tmport) & 0x80) == 0x00);
1801		tmport -= 0x08;
1802		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
1803			continue;
1804		}
1805		while (inb(tmport) != 0x8e);
1806		tmport = wkport + 0x5b;
1807		outb(0x00, tmport);
1808		tmport = wkport + 0x58;
1809		outb(0x08, tmport);
1810		tmport += 0x07;
1811		j = 0;
1812rd_inq_data:
1813		k = inb(tmport);
1814		if ((k & 0x01) != 0) {
1815			tmport -= 0x06;
1816			mbuf[j++] = inb(tmport);
1817			tmport += 0x06;
1818			goto rd_inq_data;
1819		}
1820		if ((k & 0x80) == 0) {
1821			goto rd_inq_data;
1822		}
1823		tmport -= 0x08;
1824		j = inb(tmport);
1825		if (j == 0x16) {
1826			goto inq_ok;
1827		}
1828		tmport = wkport + 0x50;
1829		outb(0x46, tmport);
1830		tmport += 0x02;
1831		outb(0, tmport++);
1832		outb(0, tmport++);
1833		outb(0, tmport++);
1834		tmport += 0x03;
1835		outb(0x08, tmport);
1836		tmport += 0x07;
1837		while ((inb(tmport) & 0x80) == 0x00);
1838		tmport -= 0x08;
1839		if (inb(tmport) != 0x16) {
1840			goto sel_ok;
1841		}
1842inq_ok:
1843		mbuf[36] = 0;
1844		printk(KERN_INFO "         ID: %2d  %s\n", i, &mbuf[8]);
1845		dev->id[i].devtypeu = mbuf[0];
1846		rmb = mbuf[1];
1847		n = mbuf[7];
1848		if ((mbuf[7] & 0x60) == 0) {
1849			goto not_wide;
1850		}
1851		if ((i < 8) && ((dev->global_map & 0x20) == 0)) {
1852			goto not_wide;
1853		}
1854		if (lvdmode == 0)
1855		{
1856		   goto chg_wide;
1857		}
1858		if (dev->sp[i] != 0x04) 	 // force u2
1859		{
1860		   goto chg_wide;
1861		}
1862
1863		tmport = wkport + 0x5b;
1864		outb(0x01, tmport);
1865		tmport = wkport + 0x43;
1866		outb(satn[0], tmport++);
1867		outb(satn[1], tmport++);
1868		outb(satn[2], tmport++);
1869		outb(satn[3], tmport++);
1870		outb(satn[4], tmport++);
1871		outb(satn[5], tmport++);
1872		tmport += 0x06;
1873		outb(0, tmport);
1874		tmport += 0x02;
1875		outb(dev->id[i].devspu, tmport++);
1876		outb(0, tmport++);
1877		outb(satn[6], tmport++);
1878		outb(satn[7], tmport++);
1879		tmport += 0x03;
1880		outb(satn[8], tmport);
1881		tmport += 0x07;
1882
1883		while ((inb(tmport) & 0x80) == 0x00);
1884		tmport -= 0x08;
1885		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
1886			continue;
1887		}
1888		while (inb(tmport) != 0x8e);
1889try_u3:
1890		j = 0;
1891		tmport = wkport + 0x54;
1892		outb(0x09, tmport);
1893		tmport += 0x04;
1894		outb(0x20, tmport);
1895		tmport += 0x07;
1896
1897		while ((inb(tmport) & 0x80) == 0) {
1898			if ((inb(tmport) & 0x01) != 0) {
1899				tmport -= 0x06;
1900				outb(u3[j++], tmport);
1901				tmport += 0x06;
1902			}
1903		}
1904		tmport -= 0x08;
1905		while ((inb(tmport) & 0x80) == 0x00);
1906		j = inb(tmport) & 0x0f;
1907		if (j == 0x0f) {
1908			goto u3p_in;
1909		}
1910		if (j == 0x0a) {
1911			goto u3p_cmd;
1912		}
1913		if (j == 0x0e) {
1914			goto try_u3;
1915		}
1916		continue;
1917u3p_out:
1918		tmport = wkport + 0x58;
1919		outb(0x20, tmport);
1920		tmport += 0x07;
1921		while ((inb(tmport) & 0x80) == 0) {
1922			if ((inb(tmport) & 0x01) != 0) {
1923				tmport -= 0x06;
1924				outb(0, tmport);
1925				tmport += 0x06;
1926			}
1927		}
1928		tmport -= 0x08;
1929		j = inb(tmport) & 0x0f;
1930		if (j == 0x0f) {
1931			goto u3p_in;
1932		}
1933		if (j == 0x0a) {
1934			goto u3p_cmd;
1935		}
1936		if (j == 0x0e) {
1937			goto u3p_out;
1938		}
1939		continue;
1940u3p_in:
1941		tmport = wkport + 0x54;
1942		outb(0x09, tmport);
1943		tmport += 0x04;
1944		outb(0x20, tmport);
1945		tmport += 0x07;
1946		k = 0;
1947u3p_in1:
1948		j = inb(tmport);
1949		if ((j & 0x01) != 0) {
1950			tmport -= 0x06;
1951			mbuf[k++] = inb(tmport);
1952			tmport += 0x06;
1953			goto u3p_in1;
1954		}
1955		if ((j & 0x80) == 0x00) {
1956			goto u3p_in1;
1957		}
1958		tmport -= 0x08;
1959		j = inb(tmport) & 0x0f;
1960		if (j == 0x0f) {
1961			goto u3p_in;
1962		}
1963		if (j == 0x0a) {
1964			goto u3p_cmd;
1965		}
1966		if (j == 0x0e) {
1967			goto u3p_out;
1968		}
1969		continue;
1970u3p_cmd:
1971		tmport = wkport + 0x50;
1972		outb(0x30, tmport);
1973		tmport = wkport + 0x54;
1974		outb(0x00, tmport);
1975		tmport += 0x04;
1976		outb(0x08, tmport);
1977		tmport += 0x07;
1978		while ((inb(tmport) & 0x80) == 0x00);
1979		tmport -= 0x08;
1980		j = inb(tmport);
1981		if (j != 0x16) {
1982			if (j == 0x4e) {
1983				goto u3p_out;
1984			}
1985			continue;
1986		}
1987		if (mbuf[0] != 0x01) {
1988			goto chg_wide;
1989		}
1990		if (mbuf[1] != 0x06) {
1991			goto chg_wide;
1992		}
1993		if (mbuf[2] != 0x04) {
1994			goto chg_wide;
1995		}
1996		if (mbuf[3] == 0x09) {
1997		   m = 1;
1998		   m = m << i;
1999		   dev->wide_idu |= m;
2000		   dev->id[i].devspu = 0xce;
2001		   continue;
2002		}
2003chg_wide:
2004		tmport = wkport + 0x5b;
2005		outb(0x01, tmport);
2006		tmport = wkport + 0x43;
2007		outb(satn[0], tmport++);
2008		outb(satn[1], tmport++);
2009		outb(satn[2], tmport++);
2010		outb(satn[3], tmport++);
2011		outb(satn[4], tmport++);
2012		outb(satn[5], tmport++);
2013		tmport += 0x06;
2014		outb(0, tmport);
2015		tmport += 0x02;
2016		outb(dev->id[i].devspu, tmport++);
2017		outb(0, tmport++);
2018		outb(satn[6], tmport++);
2019		outb(satn[7], tmport++);
2020		tmport += 0x03;
2021		outb(satn[8], tmport);
2022		tmport += 0x07;
2023
2024		while ((inb(tmport) & 0x80) == 0x00);
2025		tmport -= 0x08;
2026		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
2027			continue;
2028		}
2029		while (inb(tmport) != 0x8e);
2030try_wide:
2031		j = 0;
2032		tmport = wkport + 0x54;
2033		outb(0x05, tmport);
2034		tmport += 0x04;
2035		outb(0x20, tmport);
2036		tmport += 0x07;
2037
2038		while ((inb(tmport) & 0x80) == 0) {
2039			if ((inb(tmport) & 0x01) != 0) {
2040				tmport -= 0x06;
2041				outb(wide[j++], tmport);
2042				tmport += 0x06;
2043			}
2044		}
2045		tmport -= 0x08;
2046		while ((inb(tmport) & 0x80) == 0x00);
2047		j = inb(tmport) & 0x0f;
2048		if (j == 0x0f) {
2049			goto widep_in;
2050		}
2051		if (j == 0x0a) {
2052			goto widep_cmd;
2053		}
2054		if (j == 0x0e) {
2055			goto try_wide;
2056		}
2057		continue;
2058widep_out:
2059		tmport = wkport + 0x58;
2060		outb(0x20, tmport);
2061		tmport += 0x07;
2062		while ((inb(tmport) & 0x80) == 0) {
2063			if ((inb(tmport) & 0x01) != 0) {
2064				tmport -= 0x06;
2065				outb(0, tmport);
2066				tmport += 0x06;
2067			}
2068		}
2069		tmport -= 0x08;
2070		j = inb(tmport) & 0x0f;
2071		if (j == 0x0f) {
2072			goto widep_in;
2073		}
2074		if (j == 0x0a) {
2075			goto widep_cmd;
2076		}
2077		if (j == 0x0e) {
2078			goto widep_out;
2079		}
2080		continue;
2081widep_in:
2082		tmport = wkport + 0x54;
2083		outb(0xff, tmport);
2084		tmport += 0x04;
2085		outb(0x20, tmport);
2086		tmport += 0x07;
2087		k = 0;
2088widep_in1:
2089		j = inb(tmport);
2090		if ((j & 0x01) != 0) {
2091			tmport -= 0x06;
2092			mbuf[k++] = inb(tmport);
2093			tmport += 0x06;
2094			goto widep_in1;
2095		}
2096		if ((j & 0x80) == 0x00) {
2097			goto widep_in1;
2098		}
2099		tmport -= 0x08;
2100		j = inb(tmport) & 0x0f;
2101		if (j == 0x0f) {
2102			goto widep_in;
2103		}
2104		if (j == 0x0a) {
2105			goto widep_cmd;
2106		}
2107		if (j == 0x0e) {
2108			goto widep_out;
2109		}
2110		continue;
2111widep_cmd:
2112		tmport = wkport + 0x50;
2113		outb(0x30, tmport);
2114		tmport = wkport + 0x54;
2115		outb(0x00, tmport);
2116		tmport += 0x04;
2117		outb(0x08, tmport);
2118		tmport += 0x07;
2119		while ((inb(tmport) & 0x80) == 0x00);
2120		tmport -= 0x08;
2121		j = inb(tmport);
2122		if (j != 0x16) {
2123			if (j == 0x4e) {
2124				goto widep_out;
2125			}
2126			continue;
2127		}
2128		if (mbuf[0] != 0x01) {
2129			goto not_wide;
2130		}
2131		if (mbuf[1] != 0x02) {
2132			goto not_wide;
2133		}
2134		if (mbuf[2] != 0x03) {
2135			goto not_wide;
2136		}
2137		if (mbuf[3] != 0x01) {
2138			goto not_wide;
2139		}
2140		m = 1;
2141		m = m << i;
2142		dev->wide_idu |= m;
2143not_wide:
2144		if ((dev->id[i].devtypeu == 0x00) || (dev->id[i].devtypeu == 0x07) ||
2145		    ((dev->id[i].devtypeu == 0x05) && ((n & 0x10) != 0)))
2146		{
2147			m = 1;
2148			m = m << i;
2149			if ((dev->async & m) != 0)
2150			{
2151			   goto set_sync;
2152			}
2153		}
2154		continue;
2155set_sync:
2156		if (dev->sp[i] == 0x02)
2157		{
2158		   synu[4]=0x0c;
2159		   synuw[4]=0x0c;
2160		}
2161		else
2162		{
2163		   if (dev->sp[i] >= 0x03)
2164		   {
2165		      synu[4]=0x0a;
2166		      synuw[4]=0x0a;
2167		   }
2168		}
2169		tmport = wkport + 0x5b;
2170		j = 0;
2171		if ((m & dev->wide_idu) != 0) {
2172			j |= 0x01;
2173		}
2174		outb(j, tmport);
2175		tmport = wkport + 0x43;
2176		outb(satn[0], tmport++);
2177		outb(satn[1], tmport++);
2178		outb(satn[2], tmport++);
2179		outb(satn[3], tmport++);
2180		outb(satn[4], tmport++);
2181		outb(satn[5], tmport++);
2182		tmport += 0x06;
2183		outb(0, tmport);
2184		tmport += 0x02;
2185		outb(dev->id[i].devspu, tmport++);
2186		outb(0, tmport++);
2187		outb(satn[6], tmport++);
2188		outb(satn[7], tmport++);
2189		tmport += 0x03;
2190		outb(satn[8], tmport);
2191		tmport += 0x07;
2192
2193		while ((inb(tmport) & 0x80) == 0x00);
2194		tmport -= 0x08;
2195		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
2196			continue;
2197		}
2198		while (inb(tmport) != 0x8e);
2199try_sync:
2200		j = 0;
2201		tmport = wkport + 0x54;
2202		outb(0x06, tmport);
2203		tmport += 0x04;
2204		outb(0x20, tmport);
2205		tmport += 0x07;
2206
2207		while ((inb(tmport) & 0x80) == 0) {
2208			if ((inb(tmport) & 0x01) != 0) {
2209				tmport -= 0x06;
2210				if ((m & dev->wide_idu) != 0) {
2211					if ((m & dev->ultra_map) != 0) {
2212						outb(synuw[j++], tmport);
2213					} else {
2214						outb(synw[j++], tmport);
2215					}
2216				} else {
2217					if ((m & dev->ultra_map) != 0) {
2218						outb(synu[j++], tmport);
2219					} else {
2220						outb(synn[j++], tmport);
2221					}
2222				}
2223				tmport += 0x06;
2224			}
2225		}
2226		tmport -= 0x08;
2227		while ((inb(tmport) & 0x80) == 0x00);
2228		j = inb(tmport) & 0x0f;
2229		if (j == 0x0f) {
2230			goto phase_ins;
2231		}
2232		if (j == 0x0a) {
2233			goto phase_cmds;
2234		}
2235		if (j == 0x0e) {
2236			goto try_sync;
2237		}
2238		continue;
2239phase_outs:
2240		tmport = wkport + 0x58;
2241		outb(0x20, tmport);
2242		tmport += 0x07;
2243		while ((inb(tmport) & 0x80) == 0x00) {
2244			if ((inb(tmport) & 0x01) != 0x00) {
2245				tmport -= 0x06;
2246				outb(0x00, tmport);
2247				tmport += 0x06;
2248			}
2249		}
2250		tmport -= 0x08;
2251		j = inb(tmport);
2252		if (j == 0x85) {
2253			goto tar_dcons;
2254		}
2255		j &= 0x0f;
2256		if (j == 0x0f) {
2257			goto phase_ins;
2258		}
2259		if (j == 0x0a) {
2260			goto phase_cmds;
2261		}
2262		if (j == 0x0e) {
2263			goto phase_outs;
2264		}
2265		continue;
2266phase_ins:
2267		tmport = wkport + 0x54;
2268		outb(0x06, tmport);
2269		tmport += 0x04;
2270		outb(0x20, tmport);
2271		tmport += 0x07;
2272		k = 0;
2273phase_ins1:
2274		j = inb(tmport);
2275		if ((j & 0x01) != 0x00) {
2276			tmport -= 0x06;
2277			mbuf[k++] = inb(tmport);
2278			tmport += 0x06;
2279			goto phase_ins1;
2280		}
2281		if ((j & 0x80) == 0x00) {
2282			goto phase_ins1;
2283		}
2284		tmport -= 0x08;
2285		while ((inb(tmport) & 0x80) == 0x00);
2286		j = inb(tmport);
2287		if (j == 0x85) {
2288			goto tar_dcons;
2289		}
2290		j &= 0x0f;
2291		if (j == 0x0f) {
2292			goto phase_ins;
2293		}
2294		if (j == 0x0a) {
2295			goto phase_cmds;
2296		}
2297		if (j == 0x0e) {
2298			goto phase_outs;
2299		}
2300		continue;
2301phase_cmds:
2302		tmport = wkport + 0x50;
2303		outb(0x30, tmport);
2304tar_dcons:
2305		tmport = wkport + 0x54;
2306		outb(0x00, tmport);
2307		tmport += 0x04;
2308		outb(0x08, tmport);
2309		tmport += 0x07;
2310		while ((inb(tmport) & 0x80) == 0x00);
2311		tmport -= 0x08;
2312		j = inb(tmport);
2313		if (j != 0x16) {
2314			continue;
2315		}
2316		if (mbuf[0] != 0x01) {
2317			continue;
2318		}
2319		if (mbuf[1] != 0x03) {
2320			continue;
2321		}
2322		if (mbuf[4] == 0x00) {
2323			continue;
2324		}
2325		if (mbuf[3] > 0x64) {
2326			continue;
2327		}
2328		if (mbuf[4] > 0x0e) {
2329			mbuf[4] = 0x0e;
2330		}
2331		dev->id[i].devspu = mbuf[4];
2332		if (mbuf[3] < 0x0c){
2333			j = 0xb0;
2334			goto set_syn_ok;
2335		}
2336		if ((mbuf[3] < 0x0d) && (rmb == 0)) {
2337			j = 0xa0;
2338			goto set_syn_ok;
2339		}
2340		if (mbuf[3] < 0x1a) {
2341			j = 0x20;
2342			goto set_syn_ok;
2343		}
2344		if (mbuf[3] < 0x33) {
2345			j = 0x40;
2346			goto set_syn_ok;
2347		}
2348		if (mbuf[3] < 0x4c) {
2349			j = 0x50;
2350			goto set_syn_ok;
2351		}
2352		j = 0x60;
2353	      set_syn_ok:
2354		dev->id[i].devspu = (dev->id[i].devspu & 0x0f) | j;
2355	}
2356}
2357
2358/* return non-zero on detection */
2359int atp870u_detect(Scsi_Host_Template * tpnt)
2360{
2361	unsigned char irq, h, k, m;
2362	unsigned long flags;
2363	unsigned int base_io, error, tmport;
2364	unsigned short index = 0;
2365	struct pci_dev *pdev[3];
2366	unsigned char chip_ver[3], host_id;
2367	unsigned short dev_id[3], n;
2368	struct Scsi_Host *shpnt = NULL;
2369	int tmpcnt = 0;
2370	int count = 0;
2371
2372	static unsigned short devid[9] = {
2373	  0x8081, 0x8002, 0x8010, 0x8020, 0x8030, 0x8040, 0x8050, 0x8060, 0
2374	};
2375
2376	printk(KERN_INFO "aec671x_detect: \n");
2377	if (!pci_present()) {
2378		printk(KERN_INFO"   NO PCI SUPPORT.\n");
2379		return count;
2380	}
2381	tpnt->proc_name = "atp870u";
2382
2383	for (h = 0; h < 2; h++) {
2384		struct atp_unit *dev = &atp_unit[h];
2385		for(k=0;k<16;k++)
2386		{
2387			dev->id[k].prd_tableu = kmalloc(1024, GFP_KERNEL);
2388			dev->id[k].devspu=0x20;
2389			dev->id[k].devtypeu = 0;
2390			dev->id[k].curr_req = NULL;
2391		}
2392		dev->active_idu = 0;
2393		dev->wide_idu = 0;
2394		dev->host_idu = 0x07;
2395		dev->quhdu = 0;
2396		dev->quendu = 0;
2397		pdev[h]=NULL;
2398		pdev[2]=NULL;
2399		dev->chip_veru = 0;
2400		dev->last_cmd = 0xff;
2401		dev->in_snd = 0;
2402		dev->in_int = 0;
2403		for (k = 0; k < qcnt; k++) {
2404			dev->querequ[k] = 0;
2405		}
2406		for (k = 0; k < 16; k++) {
2407			dev->id[k].curr_req = 0;
2408			dev->sp[k] = 0x04;
2409		}
2410	}
2411	h = 0;
2412	while (devid[h] != 0) {
2413		pdev[2] = pci_find_device(0x1191, devid[h], pdev[2]);
2414		if (pdev[2] == NULL || pci_enable_device(pdev[2])) {
2415			h++;
2416			index = 0;
2417			continue;
2418		}
2419		chip_ver[2] = 0;
2420		dev_id[2] = devid[h];
2421
2422		if (devid[h] == 0x8002) {
2423			error = pci_read_config_byte(pdev[2], 0x08, &chip_ver[2]);
2424			if (chip_ver[2] < 2) {
2425				goto nxt_devfn;
2426			}
2427		}
2428		if (devid[h] == 0x8010 || devid[h] == 0x8081 || devid[h] == 0x8050)
2429		{
2430			chip_ver[2] = 0x04;
2431		}
2432		pdev[tmpcnt] = pdev[2];
2433		chip_ver[tmpcnt] = chip_ver[2];
2434		dev_id[tmpcnt] = dev_id[2];
2435		tmpcnt++;
2436	      nxt_devfn:
2437		index++;
2438		if (index > 3) {
2439			index = 0;
2440			h++;
2441		}
2442		if(tmpcnt>1)
2443			break;
2444	}
2445	for (h = 0; h < 2; h++) {
2446		struct atp_unit *dev=&atp_unit[h];
2447		if (pdev[h]==NULL) {
2448			return count;
2449		}
2450
2451		/* Found an atp870u/w. */
2452		base_io = pci_resource_start(pdev[h], 0);
2453		irq = pdev[h]->irq;
2454
2455		if (dev_id[h] != 0x8081)
2456		{
2457		   error = pci_read_config_byte(pdev[h],0x49,&host_id);
2458
2459		   base_io &= 0xfffffff8;
2460
2461		   if (check_region(base_io,0x40) != 0)
2462		   {
2463			   return 0;
2464		   }
2465		   printk(KERN_INFO "   ACARD AEC-671X PCI Ultra/W SCSI-3 Host Adapter: %d    IO:%x, IRQ:%d.\n"
2466			  ,h, base_io, irq);
2467		   dev->ioport = base_io;
2468		   dev->pciport = base_io + 0x20;
2469		   dev->deviceid = dev_id[h];
2470		   irqnumu[h] = irq;
2471		   host_id &= 0x07;
2472		   dev->host_idu = host_id;
2473		   dev->chip_veru = chip_ver[h];
2474
2475		   tmport = base_io + 0x22;
2476		   dev->scam_on = inb(tmport);
2477		   tmport += 0x0b;
2478		   dev->global_map = inb(tmport++);
2479		   dev->ultra_map = inw(tmport);
2480		   if (dev->ultra_map == 0) {
2481			   dev->scam_on = 0x00;
2482			   dev->global_map = 0x20;
2483			   dev->ultra_map = 0xffff;
2484		   }
2485		   shpnt = scsi_register(tpnt, 4);
2486		   if(shpnt==NULL)
2487			   return count;
2488
2489		   save_flags(flags);
2490		   cli();
2491		   if (request_irq(irq, atp870u_intr_handle, SA_SHIRQ, "atp870u", dev)) {
2492			   printk(KERN_ERR "Unable to allocate IRQ for Acard controller.\n");
2493			   goto unregister;
2494		   }
2495
2496		   if (chip_ver[h] > 0x07)	     /* check if atp876 chip   */
2497		   {				     /* then enable terminator */
2498		      tmport = base_io + 0x3e;
2499		      outb(0x00, tmport);
2500		   }
2501
2502		   tmport = base_io + 0x3a;
2503		   k = (inb(tmport) & 0xf3) | 0x10;
2504		   outb(k, tmport);
2505		   outb((k & 0xdf), tmport);
2506		   mydlyu(0x8000);
2507		   outb(k, tmport);
2508		   mydlyu(0x8000);
2509		   tmport = base_io;
2510		   outb((host_id | 0x08), tmport);
2511		   tmport += 0x18;
2512		   outb(0, tmport);
2513		   tmport += 0x07;
2514		   while ((inb(tmport) & 0x80) == 0);
2515		   tmport -= 0x08;
2516		   inb(tmport);
2517		   tmport = base_io + 1;
2518		   outb(8, tmport++);
2519		   outb(0x7f, tmport);
2520		   tmport = base_io + 0x11;
2521		   outb(0x20, tmport);
2522
2523		   tscam(h);
2524		   is870(h, base_io);
2525		   tmport = base_io + 0x3a;
2526		   outb((inb(tmport) & 0xef), tmport);
2527		   tmport++;
2528		   outb((inb(tmport) | 0x20),tmport);
2529		}
2530		else
2531		{
2532		   base_io &= 0xfffffff8;
2533
2534		   if (check_region(base_io,0x60) != 0)
2535		   {
2536			   return 0;
2537		   }
2538		   host_id = inb(base_io + 0x39);
2539		   host_id >>= 0x04;
2540
2541		   printk(KERN_INFO "   ACARD AEC-67160 PCI Ultra3 LVD Host Adapter: %d    IO:%x, IRQ:%d.\n"
2542			  ,h, base_io, irq);
2543		   dev->ioport = base_io + 0x40;
2544		   dev->pciport = base_io + 0x28;
2545		   dev->deviceid = dev_id[h];
2546		   irqnumu[h] = irq;
2547		   dev->host_idu = host_id;
2548		   dev->chip_veru = chip_ver[h];
2549
2550		   tmport = base_io + 0x22;
2551		   dev->scam_on = inb(tmport);
2552		   tmport += 0x13;
2553		   dev->global_map = inb(tmport);
2554		   tmport += 0x07;
2555		   dev->ultra_map = inw(tmport);
2556
2557		   n=0x3f09;
2558next_fblk:
2559		   if (n >= 0x4000)
2560		   {
2561		      goto flash_ok;
2562		   }
2563		   m=0;
2564		   outw(n,base_io + 0x34);
2565		   n += 0x0002;
2566		   if (inb(base_io + 0x30) == 0xff)
2567		   {
2568		      goto flash_ok;
2569		   }
2570		   dev->sp[m++]=inb(base_io + 0x30);
2571		   dev->sp[m++]=inb(base_io + 0x31);
2572		   dev->sp[m++]=inb(base_io + 0x32);
2573		   dev->sp[m++]=inb(base_io + 0x33);
2574		   outw(n,base_io + 0x34);
2575		   n += 0x0002;
2576		   dev->sp[m++]=inb(base_io + 0x30);
2577		   dev->sp[m++]=inb(base_io + 0x31);
2578		   dev->sp[m++]=inb(base_io + 0x32);
2579		   dev->sp[m++]=inb(base_io + 0x33);
2580		   outw(n,base_io + 0x34);
2581		   n += 0x0002;
2582		   dev->sp[m++]=inb(base_io + 0x30);
2583		   dev->sp[m++]=inb(base_io + 0x31);
2584		   dev->sp[m++]=inb(base_io + 0x32);
2585		   dev->sp[m++]=inb(base_io + 0x33);
2586		   outw(n,base_io + 0x34);
2587		   n += 0x0002;
2588		   dev->sp[m++]=inb(base_io + 0x30);
2589		   dev->sp[m++]=inb(base_io + 0x31);
2590		   dev->sp[m++]=inb(base_io + 0x32);
2591		   dev->sp[m++]=inb(base_io + 0x33);
2592		   n += 0x0018;
2593		   goto next_fblk;
2594flash_ok:
2595		   outw(0,base_io + 0x34);
2596		   dev->ultra_map=0;
2597		   dev->async = 0;
2598		   for (k=0; k < 16; k++)
2599		   {
2600		       n=1;
2601		       n = n << k;
2602		       if (dev->sp[k] > 1)
2603		       {
2604			  dev->ultra_map |= n;
2605		       }
2606		       else
2607		       {
2608			  if (dev->sp[k] == 0)
2609			  {
2610			     dev->async |= n;
2611			  }
2612		       }
2613		   }
2614		   dev->async = ~(dev->async);
2615		   outb(dev->global_map,base_io + 0x35);
2616
2617		   shpnt = scsi_register(tpnt, 4);
2618		   if(shpnt==NULL)
2619			   return count;
2620
2621		   save_flags(flags);
2622		   cli();
2623		   if (request_irq(irq, atp870u_intr_handle, SA_SHIRQ, "atp870u", dev)) {
2624			   printk(KERN_ERR "Unable to allocate IRQ for Acard controller.\n");
2625			   goto unregister;
2626		   }
2627
2628		   tmport = base_io + 0x38;
2629		   k = inb(tmport) & 0x80;
2630		   outb(k, tmport);
2631		   tmport += 0x03;
2632		   outb(0x20, tmport);
2633		   mydlyu(0x8000);
2634		   outb(0, tmport);
2635		   mydlyu(0x8000);
2636		   tmport = base_io + 0x5b;
2637		   inb(tmport);
2638		   tmport -= 0x04;
2639		   inb(tmport);
2640		   tmport = base_io + 0x40;
2641		   outb((host_id | 0x08), tmport);
2642		   tmport += 0x18;
2643		   outb(0, tmport);
2644		   tmport += 0x07;
2645		   while ((inb(tmport) & 0x80) == 0);
2646		   tmport -= 0x08;
2647		   inb(tmport);
2648		   tmport = base_io + 0x41;
2649		   outb(8, tmport++);
2650		   outb(0x7f, tmport);
2651		   tmport = base_io + 0x51;
2652		   outb(0x20, tmport);
2653
2654		   tscam(h);
2655		   is880(h, base_io);
2656		   tmport = base_io + 0x38;
2657		   outb(0xb0, tmport);
2658		}
2659
2660		atp_host[h] = shpnt;
2661		if (dev->chip_veru == 4) {
2662			shpnt->max_id = 16;
2663		}
2664		shpnt->this_id = host_id;
2665		shpnt->unique_id = base_io;
2666		shpnt->io_port = base_io;
2667		if (dev_id[h] == 0x8081)
2668		{
2669		   shpnt->n_io_port = 0x60;	   /* Number of bytes of I/O space used */
2670		}
2671		else
2672		{
2673		   shpnt->n_io_port = 0x40;	   /* Number of bytes of I/O space used */
2674		}
2675		shpnt->irq = irq;
2676		restore_flags(flags);
2677		if (dev_id[h] == 0x8081)
2678		{
2679		   request_region(base_io, 0x60, "atp870u");       /* Register the IO ports that we use */
2680		}
2681		else
2682		{
2683		   request_region(base_io, 0x40, "atp870u");       /* Register the IO ports that we use */
2684		}
2685		count++;
2686		index++;
2687		continue;
2688unregister:
2689		scsi_unregister(shpnt);
2690		restore_flags(flags);
2691		index++;
2692		continue;
2693	}
2694
2695	return count;
2696}
2697
2698/* The abort command does not leave the device in a clean state where
2699   it is available to be used again.  Until this gets worked out, we will
2700   leave it commented out.  */
2701
2702int atp870u_abort(Scsi_Cmnd * SCpnt)
2703{
2704	unsigned char h, j, k;
2705	Scsi_Cmnd *workrequ;
2706	unsigned int tmport;
2707	struct atp_unit *dev;
2708	for (h = 0; h <= admaxu; h++) {
2709		if (SCpnt->host == atp_host[h]) {
2710			goto find_adp;
2711		}
2712	}
2713	panic("Abort host not found !");
2714find_adp:
2715	dev=&atp_unit[h];
2716	printk(KERN_DEBUG "working=%x last_cmd=%x ", dev->working, dev->last_cmd);
2717	printk(" quhdu=%x quendu=%x ", dev->quhdu, dev->quendu);
2718	tmport = dev->ioport;
2719	for (j = 0; j < 0x17; j++) {
2720		printk(" r%2x=%2x", j, inb(tmport++));
2721	}
2722	tmport += 0x05;
2723	printk(" r1c=%2x", inb(tmport));
2724	tmport += 0x03;
2725	printk(" r1f=%2x in_snd=%2x ", inb(tmport), dev->in_snd);
2726	tmport= dev->pciport;
2727	printk(" r20=%2x", inb(tmport));
2728	tmport += 0x02;
2729	printk(" r22=%2x", inb(tmport));
2730	tmport = dev->ioport + 0x3a;
2731	printk(" r3a=%2x \n",inb(tmport));
2732	tmport = dev->ioport + 0x3b;
2733	printk(" r3b=%2x \n",inb(tmport));
2734	for(j=0;j<16;j++)
2735	{
2736	   if (dev->id[j].curr_req != NULL)
2737	   {
2738		workrequ = dev->id[j].curr_req;
2739		printk("\n que cdb= ");
2740		for (k=0; k < workrequ->cmd_len; k++)
2741		{
2742		    printk(" %2x ",workrequ->cmnd[k]);
2743		}
2744		printk(" last_lenu= %lx ",dev->id[j].last_lenu);
2745	   }
2746	}
2747	return (SCSI_ABORT_SNOOZE);
2748}
2749
2750int atp870u_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
2751{
2752	unsigned char h;
2753	struct atp_unit *dev;
2754	/*
2755	 * See if a bus reset was suggested.
2756	 */
2757	for (h = 0; h <= admaxu; h++) {
2758		if (SCpnt->host == atp_host[h]) {
2759			goto find_host;
2760		}
2761	}
2762	panic("Reset bus host not found !");
2763find_host:
2764	dev=&atp_unit[h];
2765/*	SCpnt->result = 0x00080000;
2766	SCpnt->scsi_done(SCpnt);
2767	dev->working=0;
2768	dev->quhdu=0;
2769	dev->quendu=0;
2770	return (SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET);  */
2771	return (SCSI_RESET_SNOOZE);
2772}
2773
2774const char *atp870u_info(struct Scsi_Host *notused)
2775{
2776	static char buffer[128];
2777
2778	strcpy(buffer, "ACARD AEC-6710/6712/67160 PCI Ultra/W/LVD SCSI-3 Adapter Driver V2.6+ac ");
2779
2780	return buffer;
2781}
2782
2783int atp870u_set_info(char *buffer, int length, struct Scsi_Host *HBAptr)
2784{
2785	return -ENOSYS; 	/* Currently this is a no-op */
2786}
2787
2788#define BLS buffer + len + size
2789int atp870u_proc_info(char *buffer, char **start, off_t offset, int length,
2790		      int hostno, int inout)
2791{
2792	struct Scsi_Host *HBAptr;
2793	static u8 buff[512];
2794	int i;
2795	int size = 0;
2796	int len = 0;
2797	off_t begin = 0;
2798	off_t pos = 0;
2799
2800	HBAptr = NULL;
2801	for (i = 0; i < 2; i++) {
2802		if ((HBAptr = atp_host[i]) != NULL) {
2803			if (HBAptr->host_no == hostno) {
2804				break;
2805			}
2806			HBAptr = NULL;
2807		}
2808	}
2809
2810	if (HBAptr == NULL) {
2811		size += sprintf(BLS, "Can't find adapter for host number %d\n", hostno);
2812		len += size;
2813		pos = begin + len;
2814		size = 0;
2815		goto stop_output;
2816	}
2817	if (inout == TRUE) {	/* Has data been written to the file? */
2818		return (atp870u_set_info(buffer, length, HBAptr));
2819	}
2820	if (offset == 0) {
2821		memset(buff, 0, sizeof(buff));
2822	}
2823	size += sprintf(BLS, "ACARD AEC-671X Driver Version: 2.6+ac\n");
2824	len += size;
2825	pos = begin + len;
2826	size = 0;
2827
2828	size += sprintf(BLS, "\n");
2829	size += sprintf(BLS, "Adapter Configuration:\n");
2830	size += sprintf(BLS, "               Base IO: %#.4lx\n", HBAptr->io_port);
2831	size += sprintf(BLS, "                   IRQ: %d\n", HBAptr->irq);
2832	len += size;
2833	pos = begin + len;
2834	size = 0;
2835
2836stop_output:
2837	*start = buffer + (offset - begin);	/* Start of wanted data */
2838	len -= (offset - begin);	/* Start slop */
2839	if (len > length) {
2840		len = length;	/* Ending slop */
2841	}
2842	return (len);
2843}
2844
2845#include "sd.h"
2846
2847int atp870u_biosparam(Scsi_Disk * disk, kdev_t dev, int *ip)
2848{
2849	int heads, sectors, cylinders;
2850
2851	heads = 64;
2852	sectors = 32;
2853	cylinders = disk->capacity / (heads * sectors);
2854
2855	if (cylinders > 1024) {
2856		heads = 255;
2857		sectors = 63;
2858		cylinders = disk->capacity / (heads * sectors);
2859	}
2860	ip[0] = heads;
2861	ip[1] = sectors;
2862	ip[2] = cylinders;
2863
2864	return 0;
2865}
2866
2867
2868int atp870u_release (struct Scsi_Host *pshost)
2869{
2870	int h;
2871	for (h = 0; h <= admaxu; h++)
2872	{
2873		if (pshost == atp_host[h]) {
2874			int k;
2875			free_irq (pshost->irq, &atp_unit[h]);
2876			release_region (pshost->io_port, pshost->n_io_port);
2877			scsi_unregister(pshost);
2878			for(k=0;k<16;k++)
2879				kfree(atp_unit[h].id[k].prd_tableu);
2880			return 0;
2881		}
2882	}
2883	panic("atp870u: bad scsi host passed.\n");
2884
2885}
2886MODULE_LICENSE("GPL");
2887
2888static Scsi_Host_Template driver_template = ATP870U;
2889#include "scsi_module.c"
2890