xref: /openbmc/linux/drivers/scsi/atp870u.c (revision 420b4a73)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  *  Copyright (C) 1997	Wu Ching Chen
31da177e4SLinus Torvalds  *  2.1.x update (C) 1998  Krzysztof G. Baranowski
41da177e4SLinus Torvalds  *  2.5.x update (C) 2002  Red Hat <alan@redhat.com>
51da177e4SLinus Torvalds  *  2.6.x update (C) 2004  Red Hat <alan@redhat.com>
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  * Marcelo Tosatti <marcelo@conectiva.com.br> : SMP fixes
81da177e4SLinus Torvalds  *
91da177e4SLinus Torvalds  * Wu Ching Chen : NULL pointer fixes  2000/06/02
101da177e4SLinus Torvalds  *		   support atp876 chip
111da177e4SLinus Torvalds  *		   enable 32 bit fifo transfer
121da177e4SLinus Torvalds  *		   support cdrom & remove device run ultra speed
131da177e4SLinus Torvalds  *		   fix disconnect bug  2000/12/21
141da177e4SLinus Torvalds  *		   support atp880 chip lvd u160 2001/05/15
151da177e4SLinus Torvalds  *		   fix prd table bug 2001/09/12 (7.1)
161da177e4SLinus Torvalds  *
171da177e4SLinus Torvalds  * atp885 support add by ACARD Hao Ping Lian 2005/01/05
181da177e4SLinus Torvalds  */
191da177e4SLinus Torvalds #include <linux/module.h>
201da177e4SLinus Torvalds #include <linux/init.h>
211da177e4SLinus Torvalds #include <linux/interrupt.h>
221da177e4SLinus Torvalds #include <linux/kernel.h>
231da177e4SLinus Torvalds #include <linux/types.h>
241da177e4SLinus Torvalds #include <linux/string.h>
251da177e4SLinus Torvalds #include <linux/ioport.h>
261da177e4SLinus Torvalds #include <linux/delay.h>
271da177e4SLinus Torvalds #include <linux/proc_fs.h>
281da177e4SLinus Torvalds #include <linux/spinlock.h>
291da177e4SLinus Torvalds #include <linux/pci.h>
301da177e4SLinus Torvalds #include <linux/blkdev.h>
311da177e4SLinus Torvalds #include <asm/system.h>
321da177e4SLinus Torvalds #include <asm/io.h>
331da177e4SLinus Torvalds 
341da177e4SLinus Torvalds #include <scsi/scsi.h>
351da177e4SLinus Torvalds #include <scsi/scsi_cmnd.h>
361da177e4SLinus Torvalds #include <scsi/scsi_device.h>
371da177e4SLinus Torvalds #include <scsi/scsi_host.h>
381da177e4SLinus Torvalds 
391da177e4SLinus Torvalds #include "atp870u.h"
401da177e4SLinus Torvalds 
411da177e4SLinus Torvalds static struct scsi_host_template atp870u_template;
421da177e4SLinus Torvalds static void send_s870(struct atp_unit *dev,unsigned char c);
431da177e4SLinus Torvalds static void is885(struct atp_unit *dev, unsigned int wkport,unsigned char c);
441da177e4SLinus Torvalds static void tscam_885(void);
451da177e4SLinus Torvalds 
461da177e4SLinus Torvalds static irqreturn_t atp870u_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
471da177e4SLinus Torvalds {
481da177e4SLinus Torvalds 	unsigned long flags;
491da177e4SLinus Torvalds 	unsigned short int tmpcip, id;
501da177e4SLinus Torvalds 	unsigned char i, j, c, target_id, lun,cmdp;
511da177e4SLinus Torvalds 	unsigned char *prd;
521da177e4SLinus Torvalds 	struct scsi_cmnd *workreq;
531da177e4SLinus Torvalds 	unsigned int workport, tmport, tmport1;
541da177e4SLinus Torvalds 	unsigned long adrcnt, k;
551da177e4SLinus Torvalds #ifdef ED_DBGP
561da177e4SLinus Torvalds 	unsigned long l;
571da177e4SLinus Torvalds #endif
581da177e4SLinus Torvalds 	int errstus;
591da177e4SLinus Torvalds 	struct Scsi_Host *host = dev_id;
601da177e4SLinus Torvalds 	struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
611da177e4SLinus Torvalds 
621da177e4SLinus Torvalds 	for (c = 0; c < 2; c++) {
631da177e4SLinus Torvalds 		tmport = dev->ioport[c] + 0x1f;
641da177e4SLinus Torvalds 		j = inb(tmport);
651da177e4SLinus Torvalds 		if ((j & 0x80) != 0)
661da177e4SLinus Torvalds 		{
671da177e4SLinus Torvalds 	   		goto ch_sel;
681da177e4SLinus Torvalds 		}
691da177e4SLinus Torvalds 		dev->in_int[c] = 0;
701da177e4SLinus Torvalds 	}
711da177e4SLinus Torvalds 	return IRQ_NONE;
721da177e4SLinus Torvalds ch_sel:
731da177e4SLinus Torvalds #ifdef ED_DBGP
741da177e4SLinus Torvalds 	printk("atp870u_intr_handle enter\n");
751da177e4SLinus Torvalds #endif
761da177e4SLinus Torvalds 	dev->in_int[c] = 1;
771da177e4SLinus Torvalds 	cmdp = inb(dev->ioport[c] + 0x10);
781da177e4SLinus Torvalds 	workport = dev->ioport[c];
791da177e4SLinus Torvalds 	if (dev->working[c] != 0) {
801da177e4SLinus Torvalds 		if (dev->dev_id == ATP885_DEVID) {
811da177e4SLinus Torvalds 			tmport1 = workport + 0x16;
821da177e4SLinus Torvalds 			if ((inb(tmport1) & 0x80) == 0)
831da177e4SLinus Torvalds 				outb((inb(tmport1) | 0x80), tmport1);
841da177e4SLinus Torvalds 		}
851da177e4SLinus Torvalds 		tmpcip = dev->pciport[c];
861da177e4SLinus Torvalds 		if ((inb(tmpcip) & 0x08) != 0)
871da177e4SLinus Torvalds 		{
881da177e4SLinus Torvalds 			tmpcip += 0x2;
891da177e4SLinus Torvalds 			for (k=0; k < 1000; k++) {
901da177e4SLinus Torvalds 				if ((inb(tmpcip) & 0x08) == 0) {
911da177e4SLinus Torvalds 					goto stop_dma;
921da177e4SLinus Torvalds 				}
931da177e4SLinus Torvalds 				if ((inb(tmpcip) & 0x01) == 0) {
941da177e4SLinus Torvalds 					goto stop_dma;
951da177e4SLinus Torvalds 				}
961da177e4SLinus Torvalds 			}
971da177e4SLinus Torvalds 		}
981da177e4SLinus Torvalds stop_dma:
991da177e4SLinus Torvalds 		tmpcip = dev->pciport[c];
1001da177e4SLinus Torvalds 		outb(0x00, tmpcip);
1011da177e4SLinus Torvalds 		tmport -= 0x08;
1021da177e4SLinus Torvalds 
1031da177e4SLinus Torvalds 		i = inb(tmport);
1041da177e4SLinus Torvalds 
1051da177e4SLinus Torvalds 		if (dev->dev_id == ATP885_DEVID) {
1061da177e4SLinus Torvalds 			tmpcip += 2;
1071da177e4SLinus Torvalds 			outb(0x06, tmpcip);
1081da177e4SLinus Torvalds 			tmpcip -= 2;
1091da177e4SLinus Torvalds 		}
1101da177e4SLinus Torvalds 
1111da177e4SLinus Torvalds 		tmport -= 0x02;
1121da177e4SLinus Torvalds 		target_id = inb(tmport);
1131da177e4SLinus Torvalds 		tmport += 0x02;
1141da177e4SLinus Torvalds 
1151da177e4SLinus Torvalds 		/*
1161da177e4SLinus Torvalds 		 *	Remap wide devices onto id numbers
1171da177e4SLinus Torvalds 		 */
1181da177e4SLinus Torvalds 
1191da177e4SLinus Torvalds 		if ((target_id & 0x40) != 0) {
1201da177e4SLinus Torvalds 			target_id = (target_id & 0x07) | 0x08;
1211da177e4SLinus Torvalds 		} else {
1221da177e4SLinus Torvalds 			target_id &= 0x07;
1231da177e4SLinus Torvalds 		}
1241da177e4SLinus Torvalds 
1251da177e4SLinus Torvalds 		if ((j & 0x40) != 0) {
1261da177e4SLinus Torvalds 		     if (dev->last_cmd[c] == 0xff) {
1271da177e4SLinus Torvalds 			dev->last_cmd[c] = target_id;
1281da177e4SLinus Torvalds 		     }
1291da177e4SLinus Torvalds 		     dev->last_cmd[c] |= 0x40;
1301da177e4SLinus Torvalds 		}
1311da177e4SLinus Torvalds 		if (dev->dev_id == ATP885_DEVID)
1321da177e4SLinus Torvalds 			dev->r1f[c][target_id] |= j;
1331da177e4SLinus Torvalds #ifdef ED_DBGP
1341da177e4SLinus Torvalds 		printk("atp870u_intr_handle status = %x\n",i);
1351da177e4SLinus Torvalds #endif
1361da177e4SLinus Torvalds 		if (i == 0x85) {
1371da177e4SLinus Torvalds 			if ((dev->last_cmd[c] & 0xf0) != 0x40) {
1381da177e4SLinus Torvalds 			   dev->last_cmd[c] = 0xff;
1391da177e4SLinus Torvalds 			}
1401da177e4SLinus Torvalds 			if (dev->dev_id == ATP885_DEVID) {
1411da177e4SLinus Torvalds 				tmport -= 0x05;
1421da177e4SLinus Torvalds 				adrcnt = 0;
1431da177e4SLinus Torvalds 				((unsigned char *) &adrcnt)[2] = inb(tmport++);
1441da177e4SLinus Torvalds 				((unsigned char *) &adrcnt)[1] = inb(tmport++);
1451da177e4SLinus Torvalds 				((unsigned char *) &adrcnt)[0] = inb(tmport);
1461da177e4SLinus Torvalds 				if (dev->id[c][target_id].last_len != adrcnt)
1471da177e4SLinus Torvalds 				{
1481da177e4SLinus Torvalds 			   		k = dev->id[c][target_id].last_len;
1491da177e4SLinus Torvalds 			   		k -= adrcnt;
1501da177e4SLinus Torvalds 			   		dev->id[c][target_id].tran_len = k;
1511da177e4SLinus Torvalds 			   	dev->id[c][target_id].last_len = adrcnt;
1521da177e4SLinus Torvalds 				}
1531da177e4SLinus Torvalds #ifdef ED_DBGP
1541da177e4SLinus Torvalds 				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);
1551da177e4SLinus Torvalds #endif
1561da177e4SLinus Torvalds 			}
1571da177e4SLinus Torvalds 
1581da177e4SLinus Torvalds 			/*
1591da177e4SLinus Torvalds 			 *      Flip wide
1601da177e4SLinus Torvalds 			 */
1611da177e4SLinus Torvalds 			if (dev->wide_id[c] != 0) {
1621da177e4SLinus Torvalds 				tmport = workport + 0x1b;
1631da177e4SLinus Torvalds 				outb(0x01, tmport);
1641da177e4SLinus Torvalds 				while ((inb(tmport) & 0x01) != 0x01) {
1651da177e4SLinus Torvalds 					outb(0x01, tmport);
1661da177e4SLinus Torvalds 				}
1671da177e4SLinus Torvalds 			}
1681da177e4SLinus Torvalds 			/*
1691da177e4SLinus Torvalds 			 *	Issue more commands
1701da177e4SLinus Torvalds 			 */
1711da177e4SLinus Torvalds 			spin_lock_irqsave(dev->host->host_lock, flags);
1721da177e4SLinus Torvalds 			if (((dev->quhd[c] != dev->quend[c]) || (dev->last_cmd[c] != 0xff)) &&
1731da177e4SLinus Torvalds 			    (dev->in_snd[c] == 0)) {
1741da177e4SLinus Torvalds #ifdef ED_DBGP
1751da177e4SLinus Torvalds 				printk("Call sent_s870\n");
1761da177e4SLinus Torvalds #endif
1771da177e4SLinus Torvalds 				send_s870(dev,c);
1781da177e4SLinus Torvalds 			}
1791da177e4SLinus Torvalds 			spin_unlock_irqrestore(dev->host->host_lock, flags);
1801da177e4SLinus Torvalds 			/*
1811da177e4SLinus Torvalds 			 *	Done
1821da177e4SLinus Torvalds 			 */
1831da177e4SLinus Torvalds 			dev->in_int[c] = 0;
1841da177e4SLinus Torvalds #ifdef ED_DBGP
1851da177e4SLinus Torvalds 				printk("Status 0x85 return\n");
1861da177e4SLinus Torvalds #endif
1871da177e4SLinus Torvalds 			goto handled;
1881da177e4SLinus Torvalds 		}
1891da177e4SLinus Torvalds 
1901da177e4SLinus Torvalds 		if (i == 0x40) {
1911da177e4SLinus Torvalds 		     dev->last_cmd[c] |= 0x40;
1921da177e4SLinus Torvalds 		     dev->in_int[c] = 0;
1931da177e4SLinus Torvalds 		     goto handled;
1941da177e4SLinus Torvalds 		}
1951da177e4SLinus Torvalds 
1961da177e4SLinus Torvalds 		if (i == 0x21) {
1971da177e4SLinus Torvalds 			if ((dev->last_cmd[c] & 0xf0) != 0x40) {
1981da177e4SLinus Torvalds 			   dev->last_cmd[c] = 0xff;
1991da177e4SLinus Torvalds 			}
2001da177e4SLinus Torvalds 			tmport -= 0x05;
2011da177e4SLinus Torvalds 			adrcnt = 0;
2021da177e4SLinus Torvalds 			((unsigned char *) &adrcnt)[2] = inb(tmport++);
2031da177e4SLinus Torvalds 			((unsigned char *) &adrcnt)[1] = inb(tmport++);
2041da177e4SLinus Torvalds 			((unsigned char *) &adrcnt)[0] = inb(tmport);
2051da177e4SLinus Torvalds 			k = dev->id[c][target_id].last_len;
2061da177e4SLinus Torvalds 			k -= adrcnt;
2071da177e4SLinus Torvalds 			dev->id[c][target_id].tran_len = k;
2081da177e4SLinus Torvalds 			dev->id[c][target_id].last_len = adrcnt;
2091da177e4SLinus Torvalds 			tmport -= 0x04;
2101da177e4SLinus Torvalds 			outb(0x41, tmport);
2111da177e4SLinus Torvalds 			tmport += 0x08;
2121da177e4SLinus Torvalds 			outb(0x08, tmport);
2131da177e4SLinus Torvalds 			dev->in_int[c] = 0;
2141da177e4SLinus Torvalds 			goto handled;
2151da177e4SLinus Torvalds 		}
2161da177e4SLinus Torvalds 
2171da177e4SLinus Torvalds 		if (dev->dev_id == ATP885_DEVID) {
2181da177e4SLinus Torvalds 			if ((i == 0x4c) || (i == 0x4d) || (i == 0x8c) || (i == 0x8d)) {
2191da177e4SLinus Torvalds 		   		if ((i == 0x4c) || (i == 0x8c))
2201da177e4SLinus Torvalds 		      			i=0x48;
2211da177e4SLinus Torvalds 		   		else
2221da177e4SLinus Torvalds 		      			i=0x49;
2231da177e4SLinus Torvalds 		   	}
2241da177e4SLinus Torvalds 
2251da177e4SLinus Torvalds 		}
2261da177e4SLinus Torvalds 		if ((i == 0x80) || (i == 0x8f)) {
2271da177e4SLinus Torvalds #ifdef ED_DBGP
2281da177e4SLinus Torvalds 			printk(KERN_DEBUG "Device reselect\n");
2291da177e4SLinus Torvalds #endif
2301da177e4SLinus Torvalds 			lun = 0;
2311da177e4SLinus Torvalds 			tmport -= 0x07;
2321da177e4SLinus Torvalds 			if (cmdp == 0x44 || i==0x80) {
2331da177e4SLinus Torvalds 				tmport += 0x0d;
2341da177e4SLinus Torvalds 				lun = inb(tmport) & 0x07;
2351da177e4SLinus Torvalds 			} else {
2361da177e4SLinus Torvalds 				if ((dev->last_cmd[c] & 0xf0) != 0x40) {
2371da177e4SLinus Torvalds 				   dev->last_cmd[c] = 0xff;
2381da177e4SLinus Torvalds 				}
2391da177e4SLinus Torvalds 				if (cmdp == 0x41) {
2401da177e4SLinus Torvalds #ifdef ED_DBGP
2411da177e4SLinus Torvalds 					printk("cmdp = 0x41\n");
2421da177e4SLinus Torvalds #endif
2431da177e4SLinus Torvalds 					tmport += 0x02;
2441da177e4SLinus Torvalds 					adrcnt = 0;
2451da177e4SLinus Torvalds 					((unsigned char *) &adrcnt)[2] = inb(tmport++);
2461da177e4SLinus Torvalds 					((unsigned char *) &adrcnt)[1] = inb(tmport++);
2471da177e4SLinus Torvalds 					((unsigned char *) &adrcnt)[0] = inb(tmport);
2481da177e4SLinus Torvalds 					k = dev->id[c][target_id].last_len;
2491da177e4SLinus Torvalds 					k -= adrcnt;
2501da177e4SLinus Torvalds 					dev->id[c][target_id].tran_len = k;
2511da177e4SLinus Torvalds 					dev->id[c][target_id].last_len = adrcnt;
2521da177e4SLinus Torvalds 					tmport += 0x04;
2531da177e4SLinus Torvalds 					outb(0x08, tmport);
2541da177e4SLinus Torvalds 					dev->in_int[c] = 0;
2551da177e4SLinus Torvalds 					goto handled;
2561da177e4SLinus Torvalds 				} else {
2571da177e4SLinus Torvalds #ifdef ED_DBGP
2581da177e4SLinus Torvalds 					printk("cmdp != 0x41\n");
2591da177e4SLinus Torvalds #endif
2601da177e4SLinus Torvalds 					outb(0x46, tmport);
2611da177e4SLinus Torvalds 					dev->id[c][target_id].dirct = 0x00;
2621da177e4SLinus Torvalds 					tmport += 0x02;
2631da177e4SLinus Torvalds 					outb(0x00, tmport++);
2641da177e4SLinus Torvalds 					outb(0x00, tmport++);
2651da177e4SLinus Torvalds 					outb(0x00, tmport++);
2661da177e4SLinus Torvalds 					tmport += 0x03;
2671da177e4SLinus Torvalds 					outb(0x08, tmport);
2681da177e4SLinus Torvalds 					dev->in_int[c] = 0;
2691da177e4SLinus Torvalds 					goto handled;
2701da177e4SLinus Torvalds 				}
2711da177e4SLinus Torvalds 			}
2721da177e4SLinus Torvalds 			if (dev->last_cmd[c] != 0xff) {
2731da177e4SLinus Torvalds 			   dev->last_cmd[c] |= 0x40;
2741da177e4SLinus Torvalds 			}
2751da177e4SLinus Torvalds 			if (dev->dev_id == ATP885_DEVID) {
2761da177e4SLinus Torvalds 				j = inb(dev->baseport + 0x29) & 0xfe;
2771da177e4SLinus Torvalds 				outb(j, dev->baseport + 0x29);
2781da177e4SLinus Torvalds 				tmport = workport + 0x16;
2791da177e4SLinus Torvalds 			} else {
2801da177e4SLinus Torvalds 				tmport = workport + 0x10;
2811da177e4SLinus Torvalds 				outb(0x45, tmport);
2821da177e4SLinus Torvalds 				tmport += 0x06;
2831da177e4SLinus Torvalds 			}
2841da177e4SLinus Torvalds 
2851da177e4SLinus Torvalds 			target_id = inb(tmport);
2861da177e4SLinus Torvalds 			/*
2871da177e4SLinus Torvalds 			 *	Remap wide identifiers
2881da177e4SLinus Torvalds 			 */
2891da177e4SLinus Torvalds 			if ((target_id & 0x10) != 0) {
2901da177e4SLinus Torvalds 				target_id = (target_id & 0x07) | 0x08;
2911da177e4SLinus Torvalds 			} else {
2921da177e4SLinus Torvalds 				target_id &= 0x07;
2931da177e4SLinus Torvalds 			}
2941da177e4SLinus Torvalds 			if (dev->dev_id == ATP885_DEVID) {
2951da177e4SLinus Torvalds 				tmport = workport + 0x10;
2961da177e4SLinus Torvalds 				outb(0x45, tmport);
2971da177e4SLinus Torvalds 			}
2981da177e4SLinus Torvalds 			workreq = dev->id[c][target_id].curr_req;
2991da177e4SLinus Torvalds #ifdef ED_DBGP
3001da177e4SLinus Torvalds 			printk(KERN_DEBUG "Channel = %d ID = %d LUN = %d CDB",c,workreq->device->id,workreq->device->lun);
3011da177e4SLinus Torvalds 			for(l=0;l<workreq->cmd_len;l++)
3021da177e4SLinus Torvalds 			{
3031da177e4SLinus Torvalds 				printk(KERN_DEBUG " %x",workreq->cmnd[l]);
3041da177e4SLinus Torvalds 			}
3051da177e4SLinus Torvalds #endif
3061da177e4SLinus Torvalds 
3071da177e4SLinus Torvalds 			tmport = workport + 0x0f;
3081da177e4SLinus Torvalds 			outb(lun, tmport);
3091da177e4SLinus Torvalds 			tmport += 0x02;
3101da177e4SLinus Torvalds 			outb(dev->id[c][target_id].devsp, tmport++);
3111da177e4SLinus Torvalds 			adrcnt = dev->id[c][target_id].tran_len;
3121da177e4SLinus Torvalds 			k = dev->id[c][target_id].last_len;
3131da177e4SLinus Torvalds 
3141da177e4SLinus Torvalds 			outb(((unsigned char *) &k)[2], tmport++);
3151da177e4SLinus Torvalds 			outb(((unsigned char *) &k)[1], tmport++);
3161da177e4SLinus Torvalds 			outb(((unsigned char *) &k)[0], tmport++);
3171da177e4SLinus Torvalds #ifdef ED_DBGP
3181da177e4SLinus Torvalds 			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));
3191da177e4SLinus Torvalds #endif
3201da177e4SLinus Torvalds 			/* Remap wide */
3211da177e4SLinus Torvalds 			j = target_id;
3221da177e4SLinus Torvalds 			if (target_id > 7) {
3231da177e4SLinus Torvalds 				j = (j & 0x07) | 0x40;
3241da177e4SLinus Torvalds 			}
3251da177e4SLinus Torvalds 			/* Add direction */
3261da177e4SLinus Torvalds 			j |= dev->id[c][target_id].dirct;
3271da177e4SLinus Torvalds 			outb(j, tmport++);
3281da177e4SLinus Torvalds 			outb(0x80,tmport);
3291da177e4SLinus Torvalds 
3301da177e4SLinus Torvalds 			/* enable 32 bit fifo transfer */
3311da177e4SLinus Torvalds 			if (dev->dev_id == ATP885_DEVID) {
3321da177e4SLinus Torvalds 				tmpcip = dev->pciport[c] + 1;
3331da177e4SLinus Torvalds 				i=inb(tmpcip) & 0xf3;
3341da177e4SLinus Torvalds 				//j=workreq->cmnd[0];
3351da177e4SLinus Torvalds 				if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
3361da177e4SLinus Torvalds 				   i |= 0x0c;
3371da177e4SLinus Torvalds 				}
3381da177e4SLinus Torvalds 				outb(i,tmpcip);
3391da177e4SLinus Torvalds 			} else if ((dev->dev_id == ATP880_DEVID1) ||
3401da177e4SLinus Torvalds 	    		    	   (dev->dev_id == ATP880_DEVID2) ) {
3411da177e4SLinus Torvalds 				tmport = workport - 0x05;
3421da177e4SLinus Torvalds 				if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
3431da177e4SLinus Torvalds 					outb((unsigned char) ((inb(tmport) & 0x3f) | 0xc0), tmport);
3441da177e4SLinus Torvalds 				} else {
3451da177e4SLinus Torvalds 					outb((unsigned char) (inb(tmport) & 0x3f), tmport);
3461da177e4SLinus Torvalds 				}
3471da177e4SLinus Torvalds 			} else {
3481da177e4SLinus Torvalds 				tmport = workport + 0x3a;
3491da177e4SLinus Torvalds 				if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
3501da177e4SLinus Torvalds 					outb((unsigned char) ((inb(tmport) & 0xf3) | 0x08), tmport);
3511da177e4SLinus Torvalds 				} else {
3521da177e4SLinus Torvalds 					outb((unsigned char) (inb(tmport) & 0xf3), tmport);
3531da177e4SLinus Torvalds 				}
3541da177e4SLinus Torvalds 			}
3551da177e4SLinus Torvalds 			tmport = workport + 0x1b;
3561da177e4SLinus Torvalds 			j = 0;
3571da177e4SLinus Torvalds 			id = 1;
3581da177e4SLinus Torvalds 			id = id << target_id;
3591da177e4SLinus Torvalds 			/*
3601da177e4SLinus Torvalds 			 *	Is this a wide device
3611da177e4SLinus Torvalds 			 */
3621da177e4SLinus Torvalds 			if ((id & dev->wide_id[c]) != 0) {
3631da177e4SLinus Torvalds 				j |= 0x01;
3641da177e4SLinus Torvalds 			}
3651da177e4SLinus Torvalds 			outb(j, tmport);
3661da177e4SLinus Torvalds 			while ((inb(tmport) & 0x01) != j) {
3671da177e4SLinus Torvalds 				outb(j,tmport);
3681da177e4SLinus Torvalds 			}
3691da177e4SLinus Torvalds 			if (dev->id[c][target_id].last_len == 0) {
3701da177e4SLinus Torvalds 				tmport = workport + 0x18;
3711da177e4SLinus Torvalds 				outb(0x08, tmport);
3721da177e4SLinus Torvalds 				dev->in_int[c] = 0;
3731da177e4SLinus Torvalds #ifdef ED_DBGP
3741da177e4SLinus Torvalds 				printk("dev->id[c][target_id].last_len = 0\n");
3751da177e4SLinus Torvalds #endif
3761da177e4SLinus Torvalds 				goto handled;
3771da177e4SLinus Torvalds 			}
3781da177e4SLinus Torvalds #ifdef ED_DBGP
3791da177e4SLinus Torvalds 			printk("target_id = %d adrcnt = %d\n",target_id,adrcnt);
3801da177e4SLinus Torvalds #endif
3811da177e4SLinus Torvalds 			prd = dev->id[c][target_id].prd_pos;
3821da177e4SLinus Torvalds 			while (adrcnt != 0) {
3831da177e4SLinus Torvalds 				id = ((unsigned short int *)prd)[2];
3841da177e4SLinus Torvalds 				if (id == 0) {
3851da177e4SLinus Torvalds 					k = 0x10000;
3861da177e4SLinus Torvalds 				} else {
3871da177e4SLinus Torvalds 					k = id;
3881da177e4SLinus Torvalds 				}
3891da177e4SLinus Torvalds 				if (k > adrcnt) {
3901da177e4SLinus Torvalds 					((unsigned short int *)prd)[2] = (unsigned short int)
3911da177e4SLinus Torvalds 					    (k - adrcnt);
3921da177e4SLinus Torvalds 					((unsigned long *)prd)[0] += adrcnt;
3931da177e4SLinus Torvalds 					adrcnt = 0;
3941da177e4SLinus Torvalds 					dev->id[c][target_id].prd_pos = prd;
3951da177e4SLinus Torvalds 				} else {
3961da177e4SLinus Torvalds 					adrcnt -= k;
3971da177e4SLinus Torvalds 					dev->id[c][target_id].prdaddr += 0x08;
3981da177e4SLinus Torvalds 					prd += 0x08;
3991da177e4SLinus Torvalds 					if (adrcnt == 0) {
4001da177e4SLinus Torvalds 						dev->id[c][target_id].prd_pos = prd;
4011da177e4SLinus Torvalds 					}
4021da177e4SLinus Torvalds 				}
4031da177e4SLinus Torvalds 			}
4041da177e4SLinus Torvalds 			tmpcip = dev->pciport[c] + 0x04;
4051da177e4SLinus Torvalds 			outl(dev->id[c][target_id].prdaddr, tmpcip);
4061da177e4SLinus Torvalds #ifdef ED_DBGP
4071da177e4SLinus Torvalds 			printk("dev->id[%d][%d].prdaddr 0x%8x\n", c, target_id, dev->id[c][target_id].prdaddr);
4081da177e4SLinus Torvalds #endif
4091da177e4SLinus Torvalds 			if (dev->dev_id == ATP885_DEVID) {
4101da177e4SLinus Torvalds 				tmpcip -= 0x04;
4111da177e4SLinus Torvalds 			} else {
4121da177e4SLinus Torvalds 				tmpcip -= 0x02;
4131da177e4SLinus Torvalds 				outb(0x06, tmpcip);
4141da177e4SLinus Torvalds 				outb(0x00, tmpcip);
4151da177e4SLinus Torvalds 				tmpcip -= 0x02;
4161da177e4SLinus Torvalds 			}
4171da177e4SLinus Torvalds 			tmport = workport + 0x18;
4181da177e4SLinus Torvalds 			/*
4191da177e4SLinus Torvalds 			 *	Check transfer direction
4201da177e4SLinus Torvalds 			 */
4211da177e4SLinus Torvalds 			if (dev->id[c][target_id].dirct != 0) {
4221da177e4SLinus Torvalds 				outb(0x08, tmport);
4231da177e4SLinus Torvalds 				outb(0x01, tmpcip);
4241da177e4SLinus Torvalds 				dev->in_int[c] = 0;
4251da177e4SLinus Torvalds #ifdef ED_DBGP
4261da177e4SLinus Torvalds 				printk("status 0x80 return dirct != 0\n");
4271da177e4SLinus Torvalds #endif
4281da177e4SLinus Torvalds 				goto handled;
4291da177e4SLinus Torvalds 			}
4301da177e4SLinus Torvalds 			outb(0x08, tmport);
4311da177e4SLinus Torvalds 			outb(0x09, tmpcip);
4321da177e4SLinus Torvalds 			dev->in_int[c] = 0;
4331da177e4SLinus Torvalds #ifdef ED_DBGP
4341da177e4SLinus Torvalds 			printk("status 0x80 return dirct = 0\n");
4351da177e4SLinus Torvalds #endif
4361da177e4SLinus Torvalds 			goto handled;
4371da177e4SLinus Torvalds 		}
4381da177e4SLinus Torvalds 
4391da177e4SLinus Torvalds 		/*
4401da177e4SLinus Torvalds 		 *	Current scsi request on this target
4411da177e4SLinus Torvalds 		 */
4421da177e4SLinus Torvalds 
4431da177e4SLinus Torvalds 		workreq = dev->id[c][target_id].curr_req;
4441da177e4SLinus Torvalds 
4451da177e4SLinus Torvalds 		if (i == 0x42) {
4461da177e4SLinus Torvalds 			if ((dev->last_cmd[c] & 0xf0) != 0x40)
4471da177e4SLinus Torvalds 			{
4481da177e4SLinus Torvalds 			   dev->last_cmd[c] = 0xff;
4491da177e4SLinus Torvalds 			}
4501da177e4SLinus Torvalds 			errstus = 0x02;
4511da177e4SLinus Torvalds 			workreq->result = errstus;
4521da177e4SLinus Torvalds 			goto go_42;
4531da177e4SLinus Torvalds 		}
4541da177e4SLinus Torvalds 		if (i == 0x16) {
4551da177e4SLinus Torvalds 			if ((dev->last_cmd[c] & 0xf0) != 0x40) {
4561da177e4SLinus Torvalds 			   dev->last_cmd[c] = 0xff;
4571da177e4SLinus Torvalds 			}
4581da177e4SLinus Torvalds 			errstus = 0;
4591da177e4SLinus Torvalds 			tmport -= 0x08;
4601da177e4SLinus Torvalds 			errstus = inb(tmport);
4611da177e4SLinus Torvalds 			if (((dev->r1f[c][target_id] & 0x10) != 0)&&(dev->dev_id==ATP885_DEVID)) {
4621da177e4SLinus Torvalds 			   printk(KERN_WARNING "AEC67162 CRC ERROR !\n");
4631da177e4SLinus Torvalds 			   errstus = 0x02;
4641da177e4SLinus Torvalds 			}
4651da177e4SLinus Torvalds 			workreq->result = errstus;
4661da177e4SLinus Torvalds go_42:
4671da177e4SLinus Torvalds 			if (dev->dev_id == ATP885_DEVID) {
4681da177e4SLinus Torvalds 				j = inb(dev->baseport + 0x29) | 0x01;
4691da177e4SLinus Torvalds 				outb(j, dev->baseport + 0x29);
4701da177e4SLinus Torvalds 			}
4711da177e4SLinus Torvalds 			/*
4721da177e4SLinus Torvalds 			 *	Complete the command
4731da177e4SLinus Torvalds 			 */
4741da177e4SLinus Torvalds 			if (workreq->use_sg) {
4751da177e4SLinus Torvalds 				pci_unmap_sg(dev->pdev,
4761da177e4SLinus Torvalds 					(struct scatterlist *)workreq->buffer,
4771da177e4SLinus Torvalds 					workreq->use_sg,
4781da177e4SLinus Torvalds 					workreq->sc_data_direction);
4791da177e4SLinus Torvalds 			} else if (workreq->request_bufflen &&
4801da177e4SLinus Torvalds 					workreq->sc_data_direction != DMA_NONE) {
4811da177e4SLinus Torvalds 				pci_unmap_single(dev->pdev,
4821da177e4SLinus Torvalds 					workreq->SCp.dma_handle,
4831da177e4SLinus Torvalds 					workreq->request_bufflen,
4841da177e4SLinus Torvalds 					workreq->sc_data_direction);
4851da177e4SLinus Torvalds 			}
4861da177e4SLinus Torvalds 			spin_lock_irqsave(dev->host->host_lock, flags);
4871da177e4SLinus Torvalds 			(*workreq->scsi_done) (workreq);
4881da177e4SLinus Torvalds #ifdef ED_DBGP
4891da177e4SLinus Torvalds 			   printk("workreq->scsi_done\n");
4901da177e4SLinus Torvalds #endif
4911da177e4SLinus Torvalds 			/*
4921da177e4SLinus Torvalds 			 *	Clear it off the queue
4931da177e4SLinus Torvalds 			 */
4941da177e4SLinus Torvalds 			dev->id[c][target_id].curr_req = NULL;
4951da177e4SLinus Torvalds 			dev->working[c]--;
4961da177e4SLinus Torvalds 			spin_unlock_irqrestore(dev->host->host_lock, flags);
4971da177e4SLinus Torvalds 			/*
4981da177e4SLinus Torvalds 			 *      Take it back wide
4991da177e4SLinus Torvalds 			 */
5001da177e4SLinus Torvalds 			if (dev->wide_id[c] != 0) {
5011da177e4SLinus Torvalds 				tmport = workport + 0x1b;
5021da177e4SLinus Torvalds 				outb(0x01, tmport);
5031da177e4SLinus Torvalds 				while ((inb(tmport) & 0x01) != 0x01) {
5041da177e4SLinus Torvalds 					outb(0x01, tmport);
5051da177e4SLinus Torvalds 				}
5061da177e4SLinus Torvalds 			}
5071da177e4SLinus Torvalds 			/*
5081da177e4SLinus Torvalds 			 *	If there is stuff to send and nothing going then send it
5091da177e4SLinus Torvalds 			 */
5101da177e4SLinus Torvalds 			spin_lock_irqsave(dev->host->host_lock, flags);
5111da177e4SLinus Torvalds 			if (((dev->last_cmd[c] != 0xff) || (dev->quhd[c] != dev->quend[c])) &&
5121da177e4SLinus Torvalds 			    (dev->in_snd[c] == 0)) {
5131da177e4SLinus Torvalds #ifdef ED_DBGP
5141da177e4SLinus Torvalds 			   printk("Call sent_s870(scsi_done)\n");
5151da177e4SLinus Torvalds #endif
5161da177e4SLinus Torvalds 			   send_s870(dev,c);
5171da177e4SLinus Torvalds 			}
5181da177e4SLinus Torvalds 			spin_unlock_irqrestore(dev->host->host_lock, flags);
5191da177e4SLinus Torvalds 			dev->in_int[c] = 0;
5201da177e4SLinus Torvalds 			goto handled;
5211da177e4SLinus Torvalds 		}
5221da177e4SLinus Torvalds 		if ((dev->last_cmd[c] & 0xf0) != 0x40) {
5231da177e4SLinus Torvalds 		   dev->last_cmd[c] = 0xff;
5241da177e4SLinus Torvalds 		}
5251da177e4SLinus Torvalds 		if (i == 0x4f) {
5261da177e4SLinus Torvalds 			i = 0x89;
5271da177e4SLinus Torvalds 		}
5281da177e4SLinus Torvalds 		i &= 0x0f;
5291da177e4SLinus Torvalds 		if (i == 0x09) {
5301da177e4SLinus Torvalds 			tmpcip += 4;
5311da177e4SLinus Torvalds 			outl(dev->id[c][target_id].prdaddr, tmpcip);
5321da177e4SLinus Torvalds 			tmpcip = tmpcip - 2;
5331da177e4SLinus Torvalds 			outb(0x06, tmpcip);
5341da177e4SLinus Torvalds 			outb(0x00, tmpcip);
5351da177e4SLinus Torvalds 			tmpcip = tmpcip - 2;
5361da177e4SLinus Torvalds 			tmport = workport + 0x10;
5371da177e4SLinus Torvalds 			outb(0x41, tmport);
5381da177e4SLinus Torvalds 			if (dev->dev_id == ATP885_DEVID) {
5391da177e4SLinus Torvalds 				tmport += 2;
5401da177e4SLinus Torvalds 				k = dev->id[c][target_id].last_len;
5411da177e4SLinus Torvalds 				outb((unsigned char) (((unsigned char *) (&k))[2]), tmport++);
5421da177e4SLinus Torvalds 				outb((unsigned char) (((unsigned char *) (&k))[1]), tmport++);
5431da177e4SLinus Torvalds 				outb((unsigned char) (((unsigned char *) (&k))[0]), tmport);
5441da177e4SLinus Torvalds 				dev->id[c][target_id].dirct = 0x00;
5451da177e4SLinus Torvalds 				tmport += 0x04;
5461da177e4SLinus Torvalds 			} else {
5471da177e4SLinus Torvalds 				dev->id[c][target_id].dirct = 0x00;
5481da177e4SLinus Torvalds 				tmport += 0x08;
5491da177e4SLinus Torvalds 			}
5501da177e4SLinus Torvalds 			outb(0x08, tmport);
5511da177e4SLinus Torvalds 			outb(0x09, tmpcip);
5521da177e4SLinus Torvalds 			dev->in_int[c] = 0;
5531da177e4SLinus Torvalds 			goto handled;
5541da177e4SLinus Torvalds 		}
5551da177e4SLinus Torvalds 		if (i == 0x08) {
5561da177e4SLinus Torvalds 			tmpcip += 4;
5571da177e4SLinus Torvalds 			outl(dev->id[c][target_id].prdaddr, tmpcip);
5581da177e4SLinus Torvalds 			tmpcip = tmpcip - 2;
5591da177e4SLinus Torvalds 			outb(0x06, tmpcip);
5601da177e4SLinus Torvalds 			outb(0x00, tmpcip);
5611da177e4SLinus Torvalds 			tmpcip = tmpcip - 2;
5621da177e4SLinus Torvalds 			tmport = workport + 0x10;
5631da177e4SLinus Torvalds 			outb(0x41, tmport);
5641da177e4SLinus Torvalds 			if (dev->dev_id == ATP885_DEVID) {
5651da177e4SLinus Torvalds 				tmport += 2;
5661da177e4SLinus Torvalds 				k = dev->id[c][target_id].last_len;
5671da177e4SLinus Torvalds 				outb((unsigned char) (((unsigned char *) (&k))[2]), tmport++);
5681da177e4SLinus Torvalds 				outb((unsigned char) (((unsigned char *) (&k))[1]), tmport++);
5691da177e4SLinus Torvalds 				outb((unsigned char) (((unsigned char *) (&k))[0]), tmport++);
5701da177e4SLinus Torvalds 			} else {
5711da177e4SLinus Torvalds 				tmport += 5;
5721da177e4SLinus Torvalds 			}
5731da177e4SLinus Torvalds 			outb((unsigned char) (inb(tmport) | 0x20), tmport);
5741da177e4SLinus Torvalds 			dev->id[c][target_id].dirct = 0x20;
5751da177e4SLinus Torvalds 			tmport += 0x03;
5761da177e4SLinus Torvalds 			outb(0x08, tmport);
5771da177e4SLinus Torvalds 			outb(0x01, tmpcip);
5781da177e4SLinus Torvalds 			dev->in_int[c] = 0;
5791da177e4SLinus Torvalds 			goto handled;
5801da177e4SLinus Torvalds 		}
5811da177e4SLinus Torvalds 		tmport -= 0x07;
5821da177e4SLinus Torvalds 		if (i == 0x0a) {
5831da177e4SLinus Torvalds 			outb(0x30, tmport);
5841da177e4SLinus Torvalds 		} else {
5851da177e4SLinus Torvalds 			outb(0x46, tmport);
5861da177e4SLinus Torvalds 		}
5871da177e4SLinus Torvalds 		dev->id[c][target_id].dirct = 0x00;
5881da177e4SLinus Torvalds 		tmport += 0x02;
5891da177e4SLinus Torvalds 		outb(0x00, tmport++);
5901da177e4SLinus Torvalds 		outb(0x00, tmport++);
5911da177e4SLinus Torvalds 		outb(0x00, tmport++);
5921da177e4SLinus Torvalds 		tmport += 0x03;
5931da177e4SLinus Torvalds 		outb(0x08, tmport);
5941da177e4SLinus Torvalds 		dev->in_int[c] = 0;
5951da177e4SLinus Torvalds 		goto handled;
5961da177e4SLinus Torvalds 	} else {
5971da177e4SLinus Torvalds //		tmport = workport + 0x17;
5981da177e4SLinus Torvalds //		inb(tmport);
5991da177e4SLinus Torvalds //		dev->working[c] = 0;
6001da177e4SLinus Torvalds 		dev->in_int[c] = 0;
6011da177e4SLinus Torvalds 		goto handled;
6021da177e4SLinus Torvalds 	}
6031da177e4SLinus Torvalds 
6041da177e4SLinus Torvalds handled:
6051da177e4SLinus Torvalds #ifdef ED_DBGP
6061da177e4SLinus Torvalds 	printk("atp870u_intr_handle exit\n");
6071da177e4SLinus Torvalds #endif
6081da177e4SLinus Torvalds 	return IRQ_HANDLED;
6091da177e4SLinus Torvalds }
6101da177e4SLinus Torvalds /**
6111da177e4SLinus Torvalds  *	atp870u_queuecommand	-	Queue SCSI command
6121da177e4SLinus Torvalds  *	@req_p: request block
6131da177e4SLinus Torvalds  *	@done: completion function
6141da177e4SLinus Torvalds  *
6151da177e4SLinus Torvalds  *	Queue a command to the ATP queue. Called with the host lock held.
6161da177e4SLinus Torvalds  */
6171da177e4SLinus Torvalds static int atp870u_queuecommand(struct scsi_cmnd * req_p,
6181da177e4SLinus Torvalds 			 void (*done) (struct scsi_cmnd *))
6191da177e4SLinus Torvalds {
6201da177e4SLinus Torvalds 	unsigned char c;
6211da177e4SLinus Torvalds 	unsigned int tmport,m;
6221da177e4SLinus Torvalds 	struct atp_unit *dev;
6231da177e4SLinus Torvalds 	struct Scsi_Host *host;
6241da177e4SLinus Torvalds 
6251da177e4SLinus Torvalds 	c = req_p->device->channel;
6261da177e4SLinus Torvalds 	req_p->sense_buffer[0]=0;
6271da177e4SLinus Torvalds 	req_p->resid = 0;
6281da177e4SLinus Torvalds 	if (req_p->device->channel > 1) {
6291da177e4SLinus Torvalds 		req_p->result = 0x00040000;
6301da177e4SLinus Torvalds 		done(req_p);
6311da177e4SLinus Torvalds #ifdef ED_DBGP
6321da177e4SLinus Torvalds 		printk("atp870u_queuecommand : req_p->device->channel > 1\n");
6331da177e4SLinus Torvalds #endif
6341da177e4SLinus Torvalds 		return 0;
6351da177e4SLinus Torvalds 	}
6361da177e4SLinus Torvalds 
6371da177e4SLinus Torvalds 	host = req_p->device->host;
6381da177e4SLinus Torvalds 	dev = (struct atp_unit *)&host->hostdata;
6391da177e4SLinus Torvalds 
6401da177e4SLinus Torvalds 
6411da177e4SLinus Torvalds 
6421da177e4SLinus Torvalds 	m = 1;
6431da177e4SLinus Torvalds 	m = m << req_p->device->id;
6441da177e4SLinus Torvalds 
6451da177e4SLinus Torvalds 	/*
6461da177e4SLinus Torvalds 	 *      Fake a timeout for missing targets
6471da177e4SLinus Torvalds 	 */
6481da177e4SLinus Torvalds 
6491da177e4SLinus Torvalds 	if ((m & dev->active_id[c]) == 0) {
6501da177e4SLinus Torvalds 		req_p->result = 0x00040000;
6511da177e4SLinus Torvalds 		done(req_p);
6521da177e4SLinus Torvalds 		return 0;
6531da177e4SLinus Torvalds 	}
6541da177e4SLinus Torvalds 
6551da177e4SLinus Torvalds 	if (done) {
6561da177e4SLinus Torvalds 		req_p->scsi_done = done;
6571da177e4SLinus Torvalds 	} else {
6581da177e4SLinus Torvalds #ifdef ED_DBGP
6591da177e4SLinus Torvalds 		printk( "atp870u_queuecommand: done can't be NULL\n");
6601da177e4SLinus Torvalds #endif
6611da177e4SLinus Torvalds 		req_p->result = 0;
6621da177e4SLinus Torvalds 		done(req_p);
6631da177e4SLinus Torvalds 		return 0;
6641da177e4SLinus Torvalds 	}
6651da177e4SLinus Torvalds 
6661da177e4SLinus Torvalds 	/*
6671da177e4SLinus Torvalds 	 *	Count new command
6681da177e4SLinus Torvalds 	 */
6691da177e4SLinus Torvalds 	dev->quend[c]++;
6701da177e4SLinus Torvalds 	if (dev->quend[c] >= qcnt) {
6711da177e4SLinus Torvalds 		dev->quend[c] = 0;
6721da177e4SLinus Torvalds 	}
6731da177e4SLinus Torvalds 
6741da177e4SLinus Torvalds 	/*
6751da177e4SLinus Torvalds 	 *	Check queue state
6761da177e4SLinus Torvalds 	 */
6771da177e4SLinus Torvalds 	if (dev->quhd[c] == dev->quend[c]) {
6781da177e4SLinus Torvalds 		if (dev->quend[c] == 0) {
6791da177e4SLinus Torvalds 			dev->quend[c] = qcnt;
6801da177e4SLinus Torvalds 		}
6811da177e4SLinus Torvalds #ifdef ED_DBGP
6821da177e4SLinus Torvalds 		printk("atp870u_queuecommand : dev->quhd[c] == dev->quend[c]\n");
6831da177e4SLinus Torvalds #endif
6841da177e4SLinus Torvalds 		dev->quend[c]--;
6851da177e4SLinus Torvalds 		req_p->result = 0x00020000;
6861da177e4SLinus Torvalds 		done(req_p);
6871da177e4SLinus Torvalds 		return 0;
6881da177e4SLinus Torvalds 	}
6891da177e4SLinus Torvalds 	dev->quereq[c][dev->quend[c]] = req_p;
6901da177e4SLinus Torvalds 	tmport = dev->ioport[c] + 0x1c;
6911da177e4SLinus Torvalds #ifdef ED_DBGP
6921da177e4SLinus Torvalds 	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]);
6931da177e4SLinus Torvalds #endif
6941da177e4SLinus Torvalds 	if ((inb(tmport) == 0) && (dev->in_int[c] == 0) && (dev->in_snd[c] == 0)) {
6951da177e4SLinus Torvalds #ifdef ED_DBGP
6961da177e4SLinus Torvalds 		printk("Call sent_s870(atp870u_queuecommand)\n");
6971da177e4SLinus Torvalds #endif
6981da177e4SLinus Torvalds 		send_s870(dev,c);
6991da177e4SLinus Torvalds 	}
7001da177e4SLinus Torvalds #ifdef ED_DBGP
7011da177e4SLinus Torvalds 	printk("atp870u_queuecommand : exit\n");
7021da177e4SLinus Torvalds #endif
7031da177e4SLinus Torvalds 	return 0;
7041da177e4SLinus Torvalds }
7051da177e4SLinus Torvalds 
7061da177e4SLinus Torvalds /**
7071da177e4SLinus Torvalds  *	send_s870	-	send a command to the controller
7081da177e4SLinus Torvalds  *	@host: host
7091da177e4SLinus Torvalds  *
7101da177e4SLinus Torvalds  *	On entry there is work queued to be done. We move some of that work to the
7111da177e4SLinus Torvalds  *	controller itself.
7121da177e4SLinus Torvalds  *
7131da177e4SLinus Torvalds  *	Caller holds the host lock.
7141da177e4SLinus Torvalds  */
7151da177e4SLinus Torvalds static void send_s870(struct atp_unit *dev,unsigned char c)
7161da177e4SLinus Torvalds {
7171da177e4SLinus Torvalds 	unsigned int tmport;
7181da177e4SLinus Torvalds 	struct scsi_cmnd *workreq;
7191da177e4SLinus Torvalds 	unsigned int i;//,k;
7201da177e4SLinus Torvalds 	unsigned char  j, target_id;
7211da177e4SLinus Torvalds 	unsigned char *prd;
7221da177e4SLinus Torvalds 	unsigned short int tmpcip, w;
7231da177e4SLinus Torvalds 	unsigned long l, bttl = 0;
7241da177e4SLinus Torvalds 	unsigned int workport;
7251da177e4SLinus Torvalds 	struct scatterlist *sgpnt;
7261da177e4SLinus Torvalds 	unsigned long  sg_count;
7271da177e4SLinus Torvalds 
7281da177e4SLinus Torvalds 	if (dev->in_snd[c] != 0) {
7291da177e4SLinus Torvalds #ifdef ED_DBGP
7301da177e4SLinus Torvalds 		printk("cmnd in_snd\n");
7311da177e4SLinus Torvalds #endif
7321da177e4SLinus Torvalds 		return;
7331da177e4SLinus Torvalds 	}
7341da177e4SLinus Torvalds #ifdef ED_DBGP
7351da177e4SLinus Torvalds 	printk("Sent_s870 enter\n");
7361da177e4SLinus Torvalds #endif
7371da177e4SLinus Torvalds 	dev->in_snd[c] = 1;
7381da177e4SLinus Torvalds 	if ((dev->last_cmd[c] != 0xff) && ((dev->last_cmd[c] & 0x40) != 0)) {
7391da177e4SLinus Torvalds 		dev->last_cmd[c] &= 0x0f;
7401da177e4SLinus Torvalds 		workreq = dev->id[c][dev->last_cmd[c]].curr_req;
7411da177e4SLinus Torvalds 		if (workreq != NULL) {	/* check NULL pointer */
7421da177e4SLinus Torvalds 		   goto cmd_subp;
7431da177e4SLinus Torvalds 		}
7441da177e4SLinus Torvalds 		dev->last_cmd[c] = 0xff;
7451da177e4SLinus Torvalds 		if (dev->quhd[c] == dev->quend[c]) {
7461da177e4SLinus Torvalds 		   	dev->in_snd[c] = 0;
7471da177e4SLinus Torvalds 		   	return ;
7481da177e4SLinus Torvalds 		}
7491da177e4SLinus Torvalds 	}
7501da177e4SLinus Torvalds 	if ((dev->last_cmd[c] != 0xff) && (dev->working[c] != 0)) {
7511da177e4SLinus Torvalds 	     	dev->in_snd[c] = 0;
7521da177e4SLinus Torvalds 	     	return ;
7531da177e4SLinus Torvalds 	}
7541da177e4SLinus Torvalds 	dev->working[c]++;
7551da177e4SLinus Torvalds 	j = dev->quhd[c];
7561da177e4SLinus Torvalds 	dev->quhd[c]++;
7571da177e4SLinus Torvalds 	if (dev->quhd[c] >= qcnt) {
7581da177e4SLinus Torvalds 		dev->quhd[c] = 0;
7591da177e4SLinus Torvalds 	}
7601da177e4SLinus Torvalds 	workreq = dev->quereq[c][dev->quhd[c]];
7611da177e4SLinus Torvalds 	if (dev->id[c][workreq->device->id].curr_req == 0) {
7621da177e4SLinus Torvalds 		dev->id[c][workreq->device->id].curr_req = workreq;
7631da177e4SLinus Torvalds 		dev->last_cmd[c] = workreq->device->id;
7641da177e4SLinus Torvalds 		goto cmd_subp;
7651da177e4SLinus Torvalds 	}
7661da177e4SLinus Torvalds 	dev->quhd[c] = j;
7671da177e4SLinus Torvalds 	dev->working[c]--;
7681da177e4SLinus Torvalds 	dev->in_snd[c] = 0;
7691da177e4SLinus Torvalds 	return;
7701da177e4SLinus Torvalds cmd_subp:
7711da177e4SLinus Torvalds 	workport = dev->ioport[c];
7721da177e4SLinus Torvalds 	tmport = workport + 0x1f;
7731da177e4SLinus Torvalds 	if ((inb(tmport) & 0xb0) != 0) {
7741da177e4SLinus Torvalds 		goto abortsnd;
7751da177e4SLinus Torvalds 	}
7761da177e4SLinus Torvalds 	tmport = workport + 0x1c;
7771da177e4SLinus Torvalds 	if (inb(tmport) == 0) {
7781da177e4SLinus Torvalds 		goto oktosend;
7791da177e4SLinus Torvalds 	}
7801da177e4SLinus Torvalds abortsnd:
7811da177e4SLinus Torvalds #ifdef ED_DBGP
7821da177e4SLinus Torvalds 	printk("Abort to Send\n");
7831da177e4SLinus Torvalds #endif
7841da177e4SLinus Torvalds 	dev->last_cmd[c] |= 0x40;
7851da177e4SLinus Torvalds 	dev->in_snd[c] = 0;
7861da177e4SLinus Torvalds 	return;
7871da177e4SLinus Torvalds oktosend:
7881da177e4SLinus Torvalds #ifdef ED_DBGP
7891da177e4SLinus Torvalds 	printk("OK to Send\n");
7901da177e4SLinus Torvalds 	printk("CDB");
7911da177e4SLinus Torvalds 	for(i=0;i<workreq->cmd_len;i++) {
7921da177e4SLinus Torvalds 		printk(" %x",workreq->cmnd[i]);
7931da177e4SLinus Torvalds 	}
7941da177e4SLinus Torvalds 	printk("\nChannel = %d ID = %d LUN = %d\n",c,workreq->device->id,workreq->device->lun);
7951da177e4SLinus Torvalds #endif
7961da177e4SLinus Torvalds 	if (dev->dev_id == ATP885_DEVID) {
7971da177e4SLinus Torvalds 		j = inb(dev->baseport + 0x29) & 0xfe;
7981da177e4SLinus Torvalds 		outb(j, dev->baseport + 0x29);
7991da177e4SLinus Torvalds 		dev->r1f[c][workreq->device->id] = 0;
8001da177e4SLinus Torvalds 	}
8011da177e4SLinus Torvalds 
8021da177e4SLinus Torvalds 	if (workreq->cmnd[0] == READ_CAPACITY) {
8031da177e4SLinus Torvalds 		if (workreq->request_bufflen > 8) {
8041da177e4SLinus Torvalds 			workreq->request_bufflen = 0x08;
8051da177e4SLinus Torvalds 		}
8061da177e4SLinus Torvalds 	}
8071da177e4SLinus Torvalds 	if (workreq->cmnd[0] == 0x00) {
8081da177e4SLinus Torvalds 		workreq->request_bufflen = 0;
8091da177e4SLinus Torvalds 	}
8101da177e4SLinus Torvalds 
8111da177e4SLinus Torvalds 	tmport = workport + 0x1b;
8121da177e4SLinus Torvalds 	j = 0;
8131da177e4SLinus Torvalds 	target_id = workreq->device->id;
8141da177e4SLinus Torvalds 
8151da177e4SLinus Torvalds 	/*
8161da177e4SLinus Torvalds 	 *	Wide ?
8171da177e4SLinus Torvalds 	 */
8181da177e4SLinus Torvalds 	w = 1;
8191da177e4SLinus Torvalds 	w = w << target_id;
8201da177e4SLinus Torvalds 	if ((w & dev->wide_id[c]) != 0) {
8211da177e4SLinus Torvalds 		j |= 0x01;
8221da177e4SLinus Torvalds 	}
8231da177e4SLinus Torvalds 	outb(j, tmport);
8241da177e4SLinus Torvalds 	while ((inb(tmport) & 0x01) != j) {
8251da177e4SLinus Torvalds 		outb(j,tmport);
8261da177e4SLinus Torvalds #ifdef ED_DBGP
8271da177e4SLinus Torvalds 		printk("send_s870 while loop 1\n");
8281da177e4SLinus Torvalds #endif
8291da177e4SLinus Torvalds 	}
8301da177e4SLinus Torvalds 	/*
8311da177e4SLinus Torvalds 	 *	Write the command
8321da177e4SLinus Torvalds 	 */
8331da177e4SLinus Torvalds 
8341da177e4SLinus Torvalds 	tmport = workport;
8351da177e4SLinus Torvalds 	outb(workreq->cmd_len, tmport++);
8361da177e4SLinus Torvalds 	outb(0x2c, tmport++);
8371da177e4SLinus Torvalds 	if (dev->dev_id == ATP885_DEVID) {
8381da177e4SLinus Torvalds 		outb(0x7f, tmport++);
8391da177e4SLinus Torvalds 	} else {
8401da177e4SLinus Torvalds 		outb(0xcf, tmport++);
8411da177e4SLinus Torvalds 	}
8421da177e4SLinus Torvalds 	for (i = 0; i < workreq->cmd_len; i++) {
8431da177e4SLinus Torvalds 		outb(workreq->cmnd[i], tmport++);
8441da177e4SLinus Torvalds 	}
8451da177e4SLinus Torvalds 	tmport = workport + 0x0f;
8461da177e4SLinus Torvalds 	outb(workreq->device->lun, tmport);
8471da177e4SLinus Torvalds 	tmport += 0x02;
8481da177e4SLinus Torvalds 	/*
8491da177e4SLinus Torvalds 	 *	Write the target
8501da177e4SLinus Torvalds 	 */
8511da177e4SLinus Torvalds 	outb(dev->id[c][target_id].devsp, tmport++);
8521da177e4SLinus Torvalds #ifdef ED_DBGP
8531da177e4SLinus Torvalds 	printk("dev->id[%d][%d].devsp = %2x\n",c,target_id,dev->id[c][target_id].devsp);
8541da177e4SLinus Torvalds #endif
8551da177e4SLinus Torvalds 	/*
8561da177e4SLinus Torvalds 	 *	Figure out the transfer size
8571da177e4SLinus Torvalds 	 */
8581da177e4SLinus Torvalds 	if (workreq->use_sg) {
8591da177e4SLinus Torvalds #ifdef ED_DBGP
8601da177e4SLinus Torvalds 		printk("Using SGL\n");
8611da177e4SLinus Torvalds #endif
8621da177e4SLinus Torvalds 		l = 0;
8631da177e4SLinus Torvalds 
8641da177e4SLinus Torvalds 		sgpnt = (struct scatterlist *) workreq->request_buffer;
8651da177e4SLinus Torvalds 		sg_count = pci_map_sg(dev->pdev, sgpnt, workreq->use_sg,
8661da177e4SLinus Torvalds 	   			workreq->sc_data_direction);
8671da177e4SLinus Torvalds 
8681da177e4SLinus Torvalds 		for (i = 0; i < workreq->use_sg; i++) {
8691da177e4SLinus Torvalds 			if (sgpnt[i].length == 0 || workreq->use_sg > ATP870U_SCATTER) {
8701da177e4SLinus Torvalds 				panic("Foooooooood fight!");
8711da177e4SLinus Torvalds 			}
8721da177e4SLinus Torvalds 			l += sgpnt[i].length;
8731da177e4SLinus Torvalds 		}
8741da177e4SLinus Torvalds #ifdef ED_DBGP
8751da177e4SLinus Torvalds 		printk( "send_s870: workreq->use_sg %d, sg_count %d l %8ld\n", workreq->use_sg, sg_count, l);
8761da177e4SLinus Torvalds #endif
8771da177e4SLinus Torvalds 	} else if(workreq->request_bufflen && workreq->sc_data_direction != PCI_DMA_NONE) {
8781da177e4SLinus Torvalds #ifdef ED_DBGP
8791da177e4SLinus Torvalds 		printk("Not using SGL\n");
8801da177e4SLinus Torvalds #endif
8811da177e4SLinus Torvalds 		workreq->SCp.dma_handle = pci_map_single(dev->pdev, workreq->request_buffer,
8821da177e4SLinus Torvalds 				workreq->request_bufflen,
8831da177e4SLinus Torvalds 				workreq->sc_data_direction);
8841da177e4SLinus Torvalds 		l = workreq->request_bufflen;
8851da177e4SLinus Torvalds #ifdef ED_DBGP
8861da177e4SLinus Torvalds 		printk( "send_s870: workreq->use_sg %d, l %8ld\n", workreq->use_sg, l);
8871da177e4SLinus Torvalds #endif
8881da177e4SLinus Torvalds 	} else l = 0;
8891da177e4SLinus Torvalds 	/*
8901da177e4SLinus Torvalds 	 *	Write transfer size
8911da177e4SLinus Torvalds 	 */
8921da177e4SLinus Torvalds 	outb((unsigned char) (((unsigned char *) (&l))[2]), tmport++);
8931da177e4SLinus Torvalds 	outb((unsigned char) (((unsigned char *) (&l))[1]), tmport++);
8941da177e4SLinus Torvalds 	outb((unsigned char) (((unsigned char *) (&l))[0]), tmport++);
8951da177e4SLinus Torvalds 	j = target_id;
8961da177e4SLinus Torvalds 	dev->id[c][j].last_len = l;
8971da177e4SLinus Torvalds 	dev->id[c][j].tran_len = 0;
8981da177e4SLinus Torvalds #ifdef ED_DBGP
8991da177e4SLinus Torvalds 	printk("dev->id[%2d][%2d].last_len = %d\n",c,j,dev->id[c][j].last_len);
9001da177e4SLinus Torvalds #endif
9011da177e4SLinus Torvalds 	/*
9021da177e4SLinus Torvalds 	 *	Flip the wide bits
9031da177e4SLinus Torvalds 	 */
9041da177e4SLinus Torvalds 	if ((j & 0x08) != 0) {
9051da177e4SLinus Torvalds 		j = (j & 0x07) | 0x40;
9061da177e4SLinus Torvalds 	}
9071da177e4SLinus Torvalds 	/*
9081da177e4SLinus Torvalds 	 *	Check transfer direction
9091da177e4SLinus Torvalds 	 */
9101da177e4SLinus Torvalds 	if (workreq->sc_data_direction == DMA_TO_DEVICE) {
9111da177e4SLinus Torvalds 		outb((unsigned char) (j | 0x20), tmport++);
9121da177e4SLinus Torvalds 	} else {
9131da177e4SLinus Torvalds 		outb(j, tmport++);
9141da177e4SLinus Torvalds 	}
9151da177e4SLinus Torvalds 	outb((unsigned char) (inb(tmport) | 0x80), tmport);
9161da177e4SLinus Torvalds 	outb(0x80, tmport);
9171da177e4SLinus Torvalds 	tmport = workport + 0x1c;
9181da177e4SLinus Torvalds 	dev->id[c][target_id].dirct = 0;
9191da177e4SLinus Torvalds 	if (l == 0) {
9201da177e4SLinus Torvalds 		if (inb(tmport) == 0) {
9211da177e4SLinus Torvalds 			tmport = workport + 0x18;
9221da177e4SLinus Torvalds #ifdef ED_DBGP
9231da177e4SLinus Torvalds 			printk("change SCSI_CMD_REG 0x08\n");
9241da177e4SLinus Torvalds #endif
9251da177e4SLinus Torvalds 			outb(0x08, tmport);
9261da177e4SLinus Torvalds 		} else {
9271da177e4SLinus Torvalds 			dev->last_cmd[c] |= 0x40;
9281da177e4SLinus Torvalds 		}
9291da177e4SLinus Torvalds 		dev->in_snd[c] = 0;
9301da177e4SLinus Torvalds 		return;
9311da177e4SLinus Torvalds 	}
9321da177e4SLinus Torvalds 	tmpcip = dev->pciport[c];
9331da177e4SLinus Torvalds 	prd = dev->id[c][target_id].prd_table;
9341da177e4SLinus Torvalds 	dev->id[c][target_id].prd_pos = prd;
9351da177e4SLinus Torvalds 
9361da177e4SLinus Torvalds 	/*
9371da177e4SLinus Torvalds 	 *	Now write the request list. Either as scatter/gather or as
9381da177e4SLinus Torvalds 	 *	a linear chain.
9391da177e4SLinus Torvalds 	 */
9401da177e4SLinus Torvalds 
9411da177e4SLinus Torvalds 	if (workreq->use_sg) {
9421da177e4SLinus Torvalds 		sgpnt = (struct scatterlist *) workreq->request_buffer;
9431da177e4SLinus Torvalds 		i = 0;
9441da177e4SLinus Torvalds 		for (j = 0; j < workreq->use_sg; j++) {
9451da177e4SLinus Torvalds 			bttl = sg_dma_address(&sgpnt[j]);
9461da177e4SLinus Torvalds 			l=sg_dma_len(&sgpnt[j]);
9471da177e4SLinus Torvalds #ifdef ED_DBGP
9481da177e4SLinus Torvalds 		printk("1. bttl %x, l %x\n",bttl, l);
9491da177e4SLinus Torvalds #endif
9501da177e4SLinus Torvalds 		while (l > 0x10000) {
9511da177e4SLinus Torvalds 				(((u16 *) (prd))[i + 3]) = 0x0000;
9521da177e4SLinus Torvalds 				(((u16 *) (prd))[i + 2]) = 0x0000;
9531da177e4SLinus Torvalds 				(((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
9541da177e4SLinus Torvalds 				l -= 0x10000;
9551da177e4SLinus Torvalds 				bttl += 0x10000;
9561da177e4SLinus Torvalds 				i += 0x04;
9571da177e4SLinus Torvalds 			}
9581da177e4SLinus Torvalds 			(((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
9591da177e4SLinus Torvalds 			(((u16 *) (prd))[i + 2]) = cpu_to_le16(l);
9601da177e4SLinus Torvalds 			(((u16 *) (prd))[i + 3]) = 0;
9611da177e4SLinus Torvalds 			i += 0x04;
9621da177e4SLinus Torvalds 		}
9631da177e4SLinus Torvalds 		(((u16 *) (prd))[i - 1]) = cpu_to_le16(0x8000);
9641da177e4SLinus Torvalds #ifdef ED_DBGP
9651da177e4SLinus Torvalds 		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]));
9661da177e4SLinus Torvalds 		printk("2. bttl %x, l %x\n",bttl, l);
9671da177e4SLinus Torvalds #endif
9681da177e4SLinus Torvalds 	} else {
9691da177e4SLinus Torvalds 		/*
9701da177e4SLinus Torvalds 		 *	For a linear request write a chain of blocks
9711da177e4SLinus Torvalds 		 */
9721da177e4SLinus Torvalds 		bttl = workreq->SCp.dma_handle;
9731da177e4SLinus Torvalds 		l = workreq->request_bufflen;
9741da177e4SLinus Torvalds 		i = 0;
9751da177e4SLinus Torvalds #ifdef ED_DBGP
9761da177e4SLinus Torvalds 		printk("3. bttl %x, l %x\n",bttl, l);
9771da177e4SLinus Torvalds #endif
9781da177e4SLinus Torvalds 		while (l > 0x10000) {
9791da177e4SLinus Torvalds 				(((u16 *) (prd))[i + 3]) = 0x0000;
9801da177e4SLinus Torvalds 				(((u16 *) (prd))[i + 2]) = 0x0000;
9811da177e4SLinus Torvalds 				(((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
9821da177e4SLinus Torvalds 				l -= 0x10000;
9831da177e4SLinus Torvalds 				bttl += 0x10000;
9841da177e4SLinus Torvalds 				i += 0x04;
9851da177e4SLinus Torvalds 			}
9861da177e4SLinus Torvalds 			(((u16 *) (prd))[i + 3]) = cpu_to_le16(0x8000);
9871da177e4SLinus Torvalds 			(((u16 *) (prd))[i + 2]) = cpu_to_le16(l);
9881da177e4SLinus Torvalds 			(((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
9891da177e4SLinus Torvalds #ifdef ED_DBGP
9901da177e4SLinus Torvalds 		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]));
9911da177e4SLinus Torvalds 		printk("4. bttl %x, l %x\n",bttl, l);
9921da177e4SLinus Torvalds #endif
9931da177e4SLinus Torvalds 
9941da177e4SLinus Torvalds 	}
9951da177e4SLinus Torvalds 	tmpcip += 4;
9961da177e4SLinus Torvalds #ifdef ED_DBGP
9971da177e4SLinus Torvalds 	printk("send_s870: prdaddr_2 0x%8x tmpcip %x target_id %d\n", dev->id[c][target_id].prdaddr,tmpcip,target_id);
9981da177e4SLinus Torvalds #endif
9991da177e4SLinus Torvalds 	outl(dev->id[c][target_id].prdaddr, tmpcip);
10001da177e4SLinus Torvalds 	tmpcip = tmpcip - 2;
10011da177e4SLinus Torvalds 	outb(0x06, tmpcip);
10021da177e4SLinus Torvalds 	outb(0x00, tmpcip);
10031da177e4SLinus Torvalds 	if (dev->dev_id == ATP885_DEVID) {
10041da177e4SLinus Torvalds 		tmpcip--;
10051da177e4SLinus Torvalds 		j=inb(tmpcip) & 0xf3;
10061da177e4SLinus Torvalds 		if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) ||
10071da177e4SLinus Torvalds 	    	(workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
10081da177e4SLinus Torvalds 	   		j |= 0x0c;
10091da177e4SLinus Torvalds 		}
10101da177e4SLinus Torvalds 		outb(j,tmpcip);
10111da177e4SLinus Torvalds 		tmpcip--;
10121da177e4SLinus Torvalds 	} else if ((dev->dev_id == ATP880_DEVID1) ||
10131da177e4SLinus Torvalds 	    	   (dev->dev_id == ATP880_DEVID2)) {
10141da177e4SLinus Torvalds 		tmpcip =tmpcip -2;
10151da177e4SLinus Torvalds 		tmport = workport - 0x05;
10161da177e4SLinus Torvalds 		if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
10171da177e4SLinus Torvalds 			outb((unsigned char) ((inb(tmport) & 0x3f) | 0xc0), tmport);
10181da177e4SLinus Torvalds 		} else {
10191da177e4SLinus Torvalds 			outb((unsigned char) (inb(tmport) & 0x3f), tmport);
10201da177e4SLinus Torvalds 		}
10211da177e4SLinus Torvalds 	} else {
10221da177e4SLinus Torvalds 		tmpcip =tmpcip -2;
10231da177e4SLinus Torvalds 		tmport = workport + 0x3a;
10241da177e4SLinus Torvalds 		if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
10251da177e4SLinus Torvalds 			outb((inb(tmport) & 0xf3) | 0x08, tmport);
10261da177e4SLinus Torvalds 		} else {
10271da177e4SLinus Torvalds 			outb(inb(tmport) & 0xf3, tmport);
10281da177e4SLinus Torvalds 		}
10291da177e4SLinus Torvalds 	}
10301da177e4SLinus Torvalds 	tmport = workport + 0x1c;
10311da177e4SLinus Torvalds 
10321da177e4SLinus Torvalds 	if(workreq->sc_data_direction == DMA_TO_DEVICE) {
10331da177e4SLinus Torvalds 		dev->id[c][target_id].dirct = 0x20;
10341da177e4SLinus Torvalds 		if (inb(tmport) == 0) {
10351da177e4SLinus Torvalds 			tmport = workport + 0x18;
10361da177e4SLinus Torvalds 			outb(0x08, tmport);
10371da177e4SLinus Torvalds 			outb(0x01, tmpcip);
10381da177e4SLinus Torvalds #ifdef ED_DBGP
10391da177e4SLinus Torvalds 		printk( "start DMA(to target)\n");
10401da177e4SLinus Torvalds #endif
10411da177e4SLinus Torvalds 		} else {
10421da177e4SLinus Torvalds 			dev->last_cmd[c] |= 0x40;
10431da177e4SLinus Torvalds 		}
10441da177e4SLinus Torvalds 		dev->in_snd[c] = 0;
10451da177e4SLinus Torvalds 		return;
10461da177e4SLinus Torvalds 	}
10471da177e4SLinus Torvalds 	if (inb(tmport) == 0) {
10481da177e4SLinus Torvalds 		tmport = workport + 0x18;
10491da177e4SLinus Torvalds 		outb(0x08, tmport);
10501da177e4SLinus Torvalds 		outb(0x09, tmpcip);
10511da177e4SLinus Torvalds #ifdef ED_DBGP
10521da177e4SLinus Torvalds 		printk( "start DMA(to host)\n");
10531da177e4SLinus Torvalds #endif
10541da177e4SLinus Torvalds 	} else {
10551da177e4SLinus Torvalds 		dev->last_cmd[c] |= 0x40;
10561da177e4SLinus Torvalds 	}
10571da177e4SLinus Torvalds 	dev->in_snd[c] = 0;
10581da177e4SLinus Torvalds 	return;
10591da177e4SLinus Torvalds 
10601da177e4SLinus Torvalds }
10611da177e4SLinus Torvalds 
10621da177e4SLinus Torvalds static unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val)
10631da177e4SLinus Torvalds {
10641da177e4SLinus Torvalds 	unsigned int tmport;
10651da177e4SLinus Torvalds 	unsigned short int i, k;
10661da177e4SLinus Torvalds 	unsigned char j;
10671da177e4SLinus Torvalds 
10681da177e4SLinus Torvalds 	tmport = dev->ioport[0] + 0x1c;
10691da177e4SLinus Torvalds 	outw(*val, tmport);
10701da177e4SLinus Torvalds FUN_D7:
10711da177e4SLinus Torvalds 	for (i = 0; i < 10; i++) {	/* stable >= bus settle delay(400 ns)  */
10721da177e4SLinus Torvalds 		k = inw(tmport);
10731da177e4SLinus Torvalds 		j = (unsigned char) (k >> 8);
10741da177e4SLinus Torvalds 		if ((k & 0x8000) != 0) {	/* DB7 all release?    */
10751da177e4SLinus Torvalds 			goto FUN_D7;
10761da177e4SLinus Torvalds 		}
10771da177e4SLinus Torvalds 	}
10781da177e4SLinus Torvalds 	*val |= 0x4000;		/* assert DB6           */
10791da177e4SLinus Torvalds 	outw(*val, tmport);
10801da177e4SLinus Torvalds 	*val &= 0xdfff;		/* assert DB5           */
10811da177e4SLinus Torvalds 	outw(*val, tmport);
10821da177e4SLinus Torvalds FUN_D5:
10831da177e4SLinus Torvalds 	for (i = 0; i < 10; i++) {	/* stable >= bus settle delay(400 ns) */
10841da177e4SLinus Torvalds 		if ((inw(tmport) & 0x2000) != 0) {	/* DB5 all release?       */
10851da177e4SLinus Torvalds 			goto FUN_D5;
10861da177e4SLinus Torvalds 		}
10871da177e4SLinus Torvalds 	}
10881da177e4SLinus Torvalds 	*val |= 0x8000;		/* no DB4-0, assert DB7    */
10891da177e4SLinus Torvalds 	*val &= 0xe0ff;
10901da177e4SLinus Torvalds 	outw(*val, tmport);
10911da177e4SLinus Torvalds 	*val &= 0xbfff;		/* release DB6             */
10921da177e4SLinus Torvalds 	outw(*val, tmport);
10931da177e4SLinus Torvalds FUN_D6:
10941da177e4SLinus Torvalds 	for (i = 0; i < 10; i++) {	/* stable >= bus settle delay(400 ns)  */
10951da177e4SLinus Torvalds 		if ((inw(tmport) & 0x4000) != 0) {	/* DB6 all release?  */
10961da177e4SLinus Torvalds 			goto FUN_D6;
10971da177e4SLinus Torvalds 		}
10981da177e4SLinus Torvalds 	}
10991da177e4SLinus Torvalds 
11001da177e4SLinus Torvalds 	return j;
11011da177e4SLinus Torvalds }
11021da177e4SLinus Torvalds 
11031da177e4SLinus Torvalds static void tscam(struct Scsi_Host *host)
11041da177e4SLinus Torvalds {
11051da177e4SLinus Torvalds 
11061da177e4SLinus Torvalds 	unsigned int tmport;
11071da177e4SLinus Torvalds 	unsigned char i, j, k;
11081da177e4SLinus Torvalds 	unsigned long n;
11091da177e4SLinus Torvalds 	unsigned short int m, assignid_map, val;
11101da177e4SLinus Torvalds 	unsigned char mbuf[33], quintet[2];
11111da177e4SLinus Torvalds 	struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
11121da177e4SLinus Torvalds 	static unsigned char g2q_tab[8] = {
11131da177e4SLinus Torvalds 		0x38, 0x31, 0x32, 0x2b, 0x34, 0x2d, 0x2e, 0x27
11141da177e4SLinus Torvalds 	};
11151da177e4SLinus Torvalds 
11161da177e4SLinus Torvalds /*  I can't believe we need this before we've even done anything.  Remove it
11171da177e4SLinus Torvalds  *  and see if anyone bitches.
11181da177e4SLinus Torvalds 	for (i = 0; i < 0x10; i++) {
11191da177e4SLinus Torvalds 		udelay(0xffff);
11201da177e4SLinus Torvalds 	}
11211da177e4SLinus Torvalds  */
11221da177e4SLinus Torvalds 
11231da177e4SLinus Torvalds 	tmport = dev->ioport[0] + 1;
11241da177e4SLinus Torvalds 	outb(0x08, tmport++);
11251da177e4SLinus Torvalds 	outb(0x7f, tmport);
11261da177e4SLinus Torvalds 	tmport = dev->ioport[0] + 0x11;
11271da177e4SLinus Torvalds 	outb(0x20, tmport);
11281da177e4SLinus Torvalds 
11291da177e4SLinus Torvalds 	if ((dev->scam_on & 0x40) == 0) {
11301da177e4SLinus Torvalds 		return;
11311da177e4SLinus Torvalds 	}
11321da177e4SLinus Torvalds 	m = 1;
11331da177e4SLinus Torvalds 	m <<= dev->host_id[0];
11341da177e4SLinus Torvalds 	j = 16;
11351da177e4SLinus Torvalds 	if (dev->chip_ver < 4) {
11361da177e4SLinus Torvalds 		m |= 0xff00;
11371da177e4SLinus Torvalds 		j = 8;
11381da177e4SLinus Torvalds 	}
11391da177e4SLinus Torvalds 	assignid_map = m;
11401da177e4SLinus Torvalds 	tmport = dev->ioport[0] + 0x02;
11411da177e4SLinus Torvalds 	outb(0x02, tmport++);	/* 2*2=4ms,3EH 2/32*3E=3.9ms */
11421da177e4SLinus Torvalds 	outb(0, tmport++);
11431da177e4SLinus Torvalds 	outb(0, tmport++);
11441da177e4SLinus Torvalds 	outb(0, tmport++);
11451da177e4SLinus Torvalds 	outb(0, tmport++);
11461da177e4SLinus Torvalds 	outb(0, tmport++);
11471da177e4SLinus Torvalds 	outb(0, tmport++);
11481da177e4SLinus Torvalds 
11491da177e4SLinus Torvalds 	for (i = 0; i < j; i++) {
11501da177e4SLinus Torvalds 		m = 1;
11511da177e4SLinus Torvalds 		m = m << i;
11521da177e4SLinus Torvalds 		if ((m & assignid_map) != 0) {
11531da177e4SLinus Torvalds 			continue;
11541da177e4SLinus Torvalds 		}
11551da177e4SLinus Torvalds 		tmport = dev->ioport[0] + 0x0f;
11561da177e4SLinus Torvalds 		outb(0, tmport++);
11571da177e4SLinus Torvalds 		tmport += 0x02;
11581da177e4SLinus Torvalds 		outb(0, tmport++);
11591da177e4SLinus Torvalds 		outb(0, tmport++);
11601da177e4SLinus Torvalds 		outb(0, tmport++);
11611da177e4SLinus Torvalds 		if (i > 7) {
11621da177e4SLinus Torvalds 			k = (i & 0x07) | 0x40;
11631da177e4SLinus Torvalds 		} else {
11641da177e4SLinus Torvalds 			k = i;
11651da177e4SLinus Torvalds 		}
11661da177e4SLinus Torvalds 		outb(k, tmport++);
11671da177e4SLinus Torvalds 		tmport = dev->ioport[0] + 0x1b;
11681da177e4SLinus Torvalds 		if (dev->chip_ver == 4) {
11691da177e4SLinus Torvalds 			outb(0x01, tmport);
11701da177e4SLinus Torvalds 		} else {
11711da177e4SLinus Torvalds 			outb(0x00, tmport);
11721da177e4SLinus Torvalds 		}
11731da177e4SLinus Torvalds wait_rdyok:
11741da177e4SLinus Torvalds 		tmport = dev->ioport[0] + 0x18;
11751da177e4SLinus Torvalds 		outb(0x09, tmport);
11761da177e4SLinus Torvalds 		tmport += 0x07;
11771da177e4SLinus Torvalds 
11781da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
11791da177e4SLinus Torvalds 			cpu_relax();
11801da177e4SLinus Torvalds 		tmport -= 0x08;
11811da177e4SLinus Torvalds 		k = inb(tmport);
11821da177e4SLinus Torvalds 		if (k != 0x16) {
11831da177e4SLinus Torvalds 			if ((k == 0x85) || (k == 0x42)) {
11841da177e4SLinus Torvalds 				continue;
11851da177e4SLinus Torvalds 			}
11861da177e4SLinus Torvalds 			tmport = dev->ioport[0] + 0x10;
11871da177e4SLinus Torvalds 			outb(0x41, tmport);
11881da177e4SLinus Torvalds 			goto wait_rdyok;
11891da177e4SLinus Torvalds 		}
11901da177e4SLinus Torvalds 		assignid_map |= m;
11911da177e4SLinus Torvalds 
11921da177e4SLinus Torvalds 	}
11931da177e4SLinus Torvalds 	tmport = dev->ioport[0] + 0x02;
11941da177e4SLinus Torvalds 	outb(0x7f, tmport);
11951da177e4SLinus Torvalds 	tmport = dev->ioport[0] + 0x1b;
11961da177e4SLinus Torvalds 	outb(0x02, tmport);
11971da177e4SLinus Torvalds 
11981da177e4SLinus Torvalds 	outb(0, 0x80);
11991da177e4SLinus Torvalds 
12001da177e4SLinus Torvalds 	val = 0x0080;		/* bsy  */
12011da177e4SLinus Torvalds 	tmport = dev->ioport[0] + 0x1c;
12021da177e4SLinus Torvalds 	outw(val, tmport);
12031da177e4SLinus Torvalds 	val |= 0x0040;		/* sel  */
12041da177e4SLinus Torvalds 	outw(val, tmport);
12051da177e4SLinus Torvalds 	val |= 0x0004;		/* msg  */
12061da177e4SLinus Torvalds 	outw(val, tmport);
12071da177e4SLinus Torvalds 	inb(0x80);		/* 2 deskew delay(45ns*2=90ns) */
12081da177e4SLinus Torvalds 	val &= 0x007f;		/* no bsy  */
12091da177e4SLinus Torvalds 	outw(val, tmport);
12101da177e4SLinus Torvalds 	mdelay(128);
12111da177e4SLinus Torvalds 	val &= 0x00fb;		/* after 1ms no msg */
12121da177e4SLinus Torvalds 	outw(val, tmport);
12131da177e4SLinus Torvalds wait_nomsg:
12141da177e4SLinus Torvalds 	if ((inb(tmport) & 0x04) != 0) {
12151da177e4SLinus Torvalds 		goto wait_nomsg;
12161da177e4SLinus Torvalds 	}
12171da177e4SLinus Torvalds 	outb(1, 0x80);
12181da177e4SLinus Torvalds 	udelay(100);
12191da177e4SLinus Torvalds 	for (n = 0; n < 0x30000; n++) {
12201da177e4SLinus Torvalds 		if ((inb(tmport) & 0x80) != 0) {	/* bsy ? */
12211da177e4SLinus Torvalds 			goto wait_io;
12221da177e4SLinus Torvalds 		}
12231da177e4SLinus Torvalds 	}
12241da177e4SLinus Torvalds 	goto TCM_SYNC;
12251da177e4SLinus Torvalds wait_io:
12261da177e4SLinus Torvalds 	for (n = 0; n < 0x30000; n++) {
12271da177e4SLinus Torvalds 		if ((inb(tmport) & 0x81) == 0x0081) {
12281da177e4SLinus Torvalds 			goto wait_io1;
12291da177e4SLinus Torvalds 		}
12301da177e4SLinus Torvalds 	}
12311da177e4SLinus Torvalds 	goto TCM_SYNC;
12321da177e4SLinus Torvalds wait_io1:
12331da177e4SLinus Torvalds 	inb(0x80);
12341da177e4SLinus Torvalds 	val |= 0x8003;		/* io,cd,db7  */
12351da177e4SLinus Torvalds 	outw(val, tmport);
12361da177e4SLinus Torvalds 	inb(0x80);
12371da177e4SLinus Torvalds 	val &= 0x00bf;		/* no sel     */
12381da177e4SLinus Torvalds 	outw(val, tmport);
12391da177e4SLinus Torvalds 	outb(2, 0x80);
12401da177e4SLinus Torvalds TCM_SYNC:
12411da177e4SLinus Torvalds 	udelay(0x800);
12421da177e4SLinus Torvalds 	if ((inb(tmport) & 0x80) == 0x00) {	/* bsy ? */
12431da177e4SLinus Torvalds 		outw(0, tmport--);
12441da177e4SLinus Torvalds 		outb(0, tmport);
12451da177e4SLinus Torvalds 		tmport = dev->ioport[0] + 0x15;
12461da177e4SLinus Torvalds 		outb(0, tmport);
12471da177e4SLinus Torvalds 		tmport += 0x03;
12481da177e4SLinus Torvalds 		outb(0x09, tmport);
12491da177e4SLinus Torvalds 		tmport += 0x07;
12501da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0)
12511da177e4SLinus Torvalds 			cpu_relax();
12521da177e4SLinus Torvalds 		tmport -= 0x08;
12531da177e4SLinus Torvalds 		inb(tmport);
12541da177e4SLinus Torvalds 		return;
12551da177e4SLinus Torvalds 	}
12561da177e4SLinus Torvalds 	val &= 0x00ff;		/* synchronization  */
12571da177e4SLinus Torvalds 	val |= 0x3f00;
12581da177e4SLinus Torvalds 	fun_scam(dev, &val);
12591da177e4SLinus Torvalds 	outb(3, 0x80);
12601da177e4SLinus Torvalds 	val &= 0x00ff;		/* isolation        */
12611da177e4SLinus Torvalds 	val |= 0x2000;
12621da177e4SLinus Torvalds 	fun_scam(dev, &val);
12631da177e4SLinus Torvalds 	outb(4, 0x80);
12641da177e4SLinus Torvalds 	i = 8;
12651da177e4SLinus Torvalds 	j = 0;
12661da177e4SLinus Torvalds TCM_ID:
12671da177e4SLinus Torvalds 	if ((inw(tmport) & 0x2000) == 0) {
12681da177e4SLinus Torvalds 		goto TCM_ID;
12691da177e4SLinus Torvalds 	}
12701da177e4SLinus Torvalds 	outb(5, 0x80);
12711da177e4SLinus Torvalds 	val &= 0x00ff;		/* get ID_STRING */
12721da177e4SLinus Torvalds 	val |= 0x2000;
12731da177e4SLinus Torvalds 	k = fun_scam(dev, &val);
12741da177e4SLinus Torvalds 	if ((k & 0x03) == 0) {
12751da177e4SLinus Torvalds 		goto TCM_5;
12761da177e4SLinus Torvalds 	}
12771da177e4SLinus Torvalds 	mbuf[j] <<= 0x01;
12781da177e4SLinus Torvalds 	mbuf[j] &= 0xfe;
12791da177e4SLinus Torvalds 	if ((k & 0x02) != 0) {
12801da177e4SLinus Torvalds 		mbuf[j] |= 0x01;
12811da177e4SLinus Torvalds 	}
12821da177e4SLinus Torvalds 	i--;
12831da177e4SLinus Torvalds 	if (i > 0) {
12841da177e4SLinus Torvalds 		goto TCM_ID;
12851da177e4SLinus Torvalds 	}
12861da177e4SLinus Torvalds 	j++;
12871da177e4SLinus Torvalds 	i = 8;
12881da177e4SLinus Torvalds 	goto TCM_ID;
12891da177e4SLinus Torvalds 
12901da177e4SLinus Torvalds TCM_5:			/* isolation complete..  */
12911da177e4SLinus Torvalds /*    mbuf[32]=0;
12921da177e4SLinus Torvalds 	printk(" \n%x %x %x %s\n ",assignid_map,mbuf[0],mbuf[1],&mbuf[2]); */
12931da177e4SLinus Torvalds 	i = 15;
12941da177e4SLinus Torvalds 	j = mbuf[0];
12951da177e4SLinus Torvalds 	if ((j & 0x20) != 0) {	/* bit5=1:ID upto 7      */
12961da177e4SLinus Torvalds 		i = 7;
12971da177e4SLinus Torvalds 	}
12981da177e4SLinus Torvalds 	if ((j & 0x06) == 0) {	/* IDvalid?             */
12991da177e4SLinus Torvalds 		goto G2Q5;
13001da177e4SLinus Torvalds 	}
13011da177e4SLinus Torvalds 	k = mbuf[1];
13021da177e4SLinus Torvalds small_id:
13031da177e4SLinus Torvalds 	m = 1;
13041da177e4SLinus Torvalds 	m <<= k;
13051da177e4SLinus Torvalds 	if ((m & assignid_map) == 0) {
13061da177e4SLinus Torvalds 		goto G2Q_QUIN;
13071da177e4SLinus Torvalds 	}
13081da177e4SLinus Torvalds 	if (k > 0) {
13091da177e4SLinus Torvalds 		k--;
13101da177e4SLinus Torvalds 		goto small_id;
13111da177e4SLinus Torvalds 	}
13121da177e4SLinus Torvalds G2Q5:			/* srch from max acceptable ID#  */
13131da177e4SLinus Torvalds 	k = i;			/* max acceptable ID#            */
13141da177e4SLinus Torvalds G2Q_LP:
13151da177e4SLinus Torvalds 	m = 1;
13161da177e4SLinus Torvalds 	m <<= k;
13171da177e4SLinus Torvalds 	if ((m & assignid_map) == 0) {
13181da177e4SLinus Torvalds 		goto G2Q_QUIN;
13191da177e4SLinus Torvalds 	}
13201da177e4SLinus Torvalds 	if (k > 0) {
13211da177e4SLinus Torvalds 		k--;
13221da177e4SLinus Torvalds 		goto G2Q_LP;
13231da177e4SLinus Torvalds 	}
13241da177e4SLinus Torvalds G2Q_QUIN:		/* k=binID#,       */
13251da177e4SLinus Torvalds 	assignid_map |= m;
13261da177e4SLinus Torvalds 	if (k < 8) {
13271da177e4SLinus Torvalds 		quintet[0] = 0x38;	/* 1st dft ID<8    */
13281da177e4SLinus Torvalds 	} else {
13291da177e4SLinus Torvalds 		quintet[0] = 0x31;	/* 1st  ID>=8      */
13301da177e4SLinus Torvalds 	}
13311da177e4SLinus Torvalds 	k &= 0x07;
13321da177e4SLinus Torvalds 	quintet[1] = g2q_tab[k];
13331da177e4SLinus Torvalds 
13341da177e4SLinus Torvalds 	val &= 0x00ff;		/* AssignID 1stQuintet,AH=001xxxxx  */
13351da177e4SLinus Torvalds 	m = quintet[0] << 8;
13361da177e4SLinus Torvalds 	val |= m;
13371da177e4SLinus Torvalds 	fun_scam(dev, &val);
13381da177e4SLinus Torvalds 	val &= 0x00ff;		/* AssignID 2ndQuintet,AH=001xxxxx */
13391da177e4SLinus Torvalds 	m = quintet[1] << 8;
13401da177e4SLinus Torvalds 	val |= m;
13411da177e4SLinus Torvalds 	fun_scam(dev, &val);
13421da177e4SLinus Torvalds 
13431da177e4SLinus Torvalds 	goto TCM_SYNC;
13441da177e4SLinus Torvalds 
13451da177e4SLinus Torvalds }
13461da177e4SLinus Torvalds 
13471da177e4SLinus Torvalds static void is870(struct atp_unit *dev, unsigned int wkport)
13481da177e4SLinus Torvalds {
13491da177e4SLinus Torvalds 	unsigned int tmport;
13501da177e4SLinus Torvalds 	unsigned char i, j, k, rmb, n;
13511da177e4SLinus Torvalds 	unsigned short int m;
13521da177e4SLinus Torvalds 	static unsigned char mbuf[512];
13531da177e4SLinus Torvalds 	static unsigned char satn[9] = { 0, 0, 0, 0, 0, 0, 0, 6, 6 };
13541da177e4SLinus Torvalds 	static unsigned char inqd[9] = { 0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6 };
13551da177e4SLinus Torvalds 	static unsigned char synn[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
13561da177e4SLinus Torvalds 	static unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0c, 0x0e };
13571da177e4SLinus Torvalds 	static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x0c, 0x07 };
13581da177e4SLinus Torvalds 	static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
13591da177e4SLinus Torvalds 
13601da177e4SLinus Torvalds 	tmport = wkport + 0x3a;
13611da177e4SLinus Torvalds 	outb((unsigned char) (inb(tmport) | 0x10), tmport);
13621da177e4SLinus Torvalds 
13631da177e4SLinus Torvalds 	for (i = 0; i < 16; i++) {
13641da177e4SLinus Torvalds 		if ((dev->chip_ver != 4) && (i > 7)) {
13651da177e4SLinus Torvalds 			break;
13661da177e4SLinus Torvalds 		}
13671da177e4SLinus Torvalds 		m = 1;
13681da177e4SLinus Torvalds 		m = m << i;
13691da177e4SLinus Torvalds 		if ((m & dev->active_id[0]) != 0) {
13701da177e4SLinus Torvalds 			continue;
13711da177e4SLinus Torvalds 		}
13721da177e4SLinus Torvalds 		if (i == dev->host_id[0]) {
13731da177e4SLinus Torvalds 			printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_id[0]);
13741da177e4SLinus Torvalds 			continue;
13751da177e4SLinus Torvalds 		}
13761da177e4SLinus Torvalds 		tmport = wkport + 0x1b;
13771da177e4SLinus Torvalds 		if (dev->chip_ver == 4) {
13781da177e4SLinus Torvalds 			outb(0x01, tmport);
13791da177e4SLinus Torvalds 		} else {
13801da177e4SLinus Torvalds 			outb(0x00, tmport);
13811da177e4SLinus Torvalds 		}
13821da177e4SLinus Torvalds 		tmport = wkport + 1;
13831da177e4SLinus Torvalds 		outb(0x08, tmport++);
13841da177e4SLinus Torvalds 		outb(0x7f, tmport++);
13851da177e4SLinus Torvalds 		outb(satn[0], tmport++);
13861da177e4SLinus Torvalds 		outb(satn[1], tmport++);
13871da177e4SLinus Torvalds 		outb(satn[2], tmport++);
13881da177e4SLinus Torvalds 		outb(satn[3], tmport++);
13891da177e4SLinus Torvalds 		outb(satn[4], tmport++);
13901da177e4SLinus Torvalds 		outb(satn[5], tmport++);
13911da177e4SLinus Torvalds 		tmport += 0x06;
13921da177e4SLinus Torvalds 		outb(0, tmport);
13931da177e4SLinus Torvalds 		tmport += 0x02;
13941da177e4SLinus Torvalds 		outb(dev->id[0][i].devsp, tmport++);
13951da177e4SLinus Torvalds 		outb(0, tmport++);
13961da177e4SLinus Torvalds 		outb(satn[6], tmport++);
13971da177e4SLinus Torvalds 		outb(satn[7], tmport++);
13981da177e4SLinus Torvalds 		j = i;
13991da177e4SLinus Torvalds 		if ((j & 0x08) != 0) {
14001da177e4SLinus Torvalds 			j = (j & 0x07) | 0x40;
14011da177e4SLinus Torvalds 		}
14021da177e4SLinus Torvalds 		outb(j, tmport);
14031da177e4SLinus Torvalds 		tmport += 0x03;
14041da177e4SLinus Torvalds 		outb(satn[8], tmport);
14051da177e4SLinus Torvalds 		tmport += 0x07;
14061da177e4SLinus Torvalds 
14071da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
14081da177e4SLinus Torvalds 			cpu_relax();
14091da177e4SLinus Torvalds 
14101da177e4SLinus Torvalds 		tmport -= 0x08;
14111da177e4SLinus Torvalds 		if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
14121da177e4SLinus Torvalds 			continue;
14131da177e4SLinus Torvalds 
14141da177e4SLinus Torvalds 		while (inb(tmport) != 0x8e)
14151da177e4SLinus Torvalds 			cpu_relax();
14161da177e4SLinus Torvalds 
14171da177e4SLinus Torvalds 		dev->active_id[0] |= m;
14181da177e4SLinus Torvalds 
14191da177e4SLinus Torvalds 		tmport = wkport + 0x10;
14201da177e4SLinus Torvalds 		outb(0x30, tmport);
14211da177e4SLinus Torvalds 		tmport = wkport + 0x04;
14221da177e4SLinus Torvalds 		outb(0x00, tmport);
14231da177e4SLinus Torvalds 
14241da177e4SLinus Torvalds phase_cmd:
14251da177e4SLinus Torvalds 		tmport = wkport + 0x18;
14261da177e4SLinus Torvalds 		outb(0x08, tmport);
14271da177e4SLinus Torvalds 		tmport += 0x07;
14281da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
14291da177e4SLinus Torvalds 			cpu_relax();
14301da177e4SLinus Torvalds 		tmport -= 0x08;
14311da177e4SLinus Torvalds 		j = inb(tmport);
14321da177e4SLinus Torvalds 		if (j != 0x16) {
14331da177e4SLinus Torvalds 			tmport = wkport + 0x10;
14341da177e4SLinus Torvalds 			outb(0x41, tmport);
14351da177e4SLinus Torvalds 			goto phase_cmd;
14361da177e4SLinus Torvalds 		}
14371da177e4SLinus Torvalds sel_ok:
14381da177e4SLinus Torvalds 		tmport = wkport + 3;
14391da177e4SLinus Torvalds 		outb(inqd[0], tmport++);
14401da177e4SLinus Torvalds 		outb(inqd[1], tmport++);
14411da177e4SLinus Torvalds 		outb(inqd[2], tmport++);
14421da177e4SLinus Torvalds 		outb(inqd[3], tmport++);
14431da177e4SLinus Torvalds 		outb(inqd[4], tmport++);
14441da177e4SLinus Torvalds 		outb(inqd[5], tmport);
14451da177e4SLinus Torvalds 		tmport += 0x07;
14461da177e4SLinus Torvalds 		outb(0, tmport);
14471da177e4SLinus Torvalds 		tmport += 0x02;
14481da177e4SLinus Torvalds 		outb(dev->id[0][i].devsp, tmport++);
14491da177e4SLinus Torvalds 		outb(0, tmport++);
14501da177e4SLinus Torvalds 		outb(inqd[6], tmport++);
14511da177e4SLinus Torvalds 		outb(inqd[7], tmport++);
14521da177e4SLinus Torvalds 		tmport += 0x03;
14531da177e4SLinus Torvalds 		outb(inqd[8], tmport);
14541da177e4SLinus Torvalds 		tmport += 0x07;
14551da177e4SLinus Torvalds 
14561da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
14571da177e4SLinus Torvalds 			cpu_relax();
14581da177e4SLinus Torvalds 
14591da177e4SLinus Torvalds 		tmport -= 0x08;
14601da177e4SLinus Torvalds 		if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
14611da177e4SLinus Torvalds 			continue;
14621da177e4SLinus Torvalds 
14631da177e4SLinus Torvalds 		while (inb(tmport) != 0x8e)
14641da177e4SLinus Torvalds 			cpu_relax();
14651da177e4SLinus Torvalds 
14661da177e4SLinus Torvalds 		tmport = wkport + 0x1b;
14671da177e4SLinus Torvalds 		if (dev->chip_ver == 4)
14681da177e4SLinus Torvalds 			outb(0x00, tmport);
14691da177e4SLinus Torvalds 
14701da177e4SLinus Torvalds 		tmport = wkport + 0x18;
14711da177e4SLinus Torvalds 		outb(0x08, tmport);
14721da177e4SLinus Torvalds 		tmport += 0x07;
14731da177e4SLinus Torvalds 		j = 0;
14741da177e4SLinus Torvalds rd_inq_data:
14751da177e4SLinus Torvalds 		k = inb(tmport);
14761da177e4SLinus Torvalds 		if ((k & 0x01) != 0) {
14771da177e4SLinus Torvalds 			tmport -= 0x06;
14781da177e4SLinus Torvalds 			mbuf[j++] = inb(tmport);
14791da177e4SLinus Torvalds 			tmport += 0x06;
14801da177e4SLinus Torvalds 			goto rd_inq_data;
14811da177e4SLinus Torvalds 		}
14821da177e4SLinus Torvalds 		if ((k & 0x80) == 0) {
14831da177e4SLinus Torvalds 			goto rd_inq_data;
14841da177e4SLinus Torvalds 		}
14851da177e4SLinus Torvalds 		tmport -= 0x08;
14861da177e4SLinus Torvalds 		j = inb(tmport);
14871da177e4SLinus Torvalds 		if (j == 0x16) {
14881da177e4SLinus Torvalds 			goto inq_ok;
14891da177e4SLinus Torvalds 		}
14901da177e4SLinus Torvalds 		tmport = wkport + 0x10;
14911da177e4SLinus Torvalds 		outb(0x46, tmport);
14921da177e4SLinus Torvalds 		tmport += 0x02;
14931da177e4SLinus Torvalds 		outb(0, tmport++);
14941da177e4SLinus Torvalds 		outb(0, tmport++);
14951da177e4SLinus Torvalds 		outb(0, tmport++);
14961da177e4SLinus Torvalds 		tmport += 0x03;
14971da177e4SLinus Torvalds 		outb(0x08, tmport);
14981da177e4SLinus Torvalds 		tmport += 0x07;
14991da177e4SLinus Torvalds 
15001da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
15011da177e4SLinus Torvalds 			cpu_relax();
15021da177e4SLinus Torvalds 
15031da177e4SLinus Torvalds 		tmport -= 0x08;
15041da177e4SLinus Torvalds 		if (inb(tmport) != 0x16) {
15051da177e4SLinus Torvalds 			goto sel_ok;
15061da177e4SLinus Torvalds 		}
15071da177e4SLinus Torvalds inq_ok:
15081da177e4SLinus Torvalds 		mbuf[36] = 0;
15091da177e4SLinus Torvalds 		printk(KERN_INFO "         ID: %2d  %s\n", i, &mbuf[8]);
15101da177e4SLinus Torvalds 		dev->id[0][i].devtype = mbuf[0];
15111da177e4SLinus Torvalds 		rmb = mbuf[1];
15121da177e4SLinus Torvalds 		n = mbuf[7];
15131da177e4SLinus Torvalds 		if (dev->chip_ver != 4) {
15141da177e4SLinus Torvalds 			goto not_wide;
15151da177e4SLinus Torvalds 		}
15161da177e4SLinus Torvalds 		if ((mbuf[7] & 0x60) == 0) {
15171da177e4SLinus Torvalds 			goto not_wide;
15181da177e4SLinus Torvalds 		}
15191da177e4SLinus Torvalds 		if ((dev->global_map[0] & 0x20) == 0) {
15201da177e4SLinus Torvalds 			goto not_wide;
15211da177e4SLinus Torvalds 		}
15221da177e4SLinus Torvalds 		tmport = wkport + 0x1b;
15231da177e4SLinus Torvalds 		outb(0x01, tmport);
15241da177e4SLinus Torvalds 		tmport = wkport + 3;
15251da177e4SLinus Torvalds 		outb(satn[0], tmport++);
15261da177e4SLinus Torvalds 		outb(satn[1], tmport++);
15271da177e4SLinus Torvalds 		outb(satn[2], tmport++);
15281da177e4SLinus Torvalds 		outb(satn[3], tmport++);
15291da177e4SLinus Torvalds 		outb(satn[4], tmport++);
15301da177e4SLinus Torvalds 		outb(satn[5], tmport++);
15311da177e4SLinus Torvalds 		tmport += 0x06;
15321da177e4SLinus Torvalds 		outb(0, tmport);
15331da177e4SLinus Torvalds 		tmport += 0x02;
15341da177e4SLinus Torvalds 		outb(dev->id[0][i].devsp, tmport++);
15351da177e4SLinus Torvalds 		outb(0, tmport++);
15361da177e4SLinus Torvalds 		outb(satn[6], tmport++);
15371da177e4SLinus Torvalds 		outb(satn[7], tmport++);
15381da177e4SLinus Torvalds 		tmport += 0x03;
15391da177e4SLinus Torvalds 		outb(satn[8], tmport);
15401da177e4SLinus Torvalds 		tmport += 0x07;
15411da177e4SLinus Torvalds 
15421da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
15431da177e4SLinus Torvalds 			cpu_relax();
15441da177e4SLinus Torvalds 
15451da177e4SLinus Torvalds 		tmport -= 0x08;
15461da177e4SLinus Torvalds 		if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
15471da177e4SLinus Torvalds 			continue;
15481da177e4SLinus Torvalds 
15491da177e4SLinus Torvalds 		while (inb(tmport) != 0x8e)
15501da177e4SLinus Torvalds 			cpu_relax();
15511da177e4SLinus Torvalds 
15521da177e4SLinus Torvalds try_wide:
15531da177e4SLinus Torvalds 		j = 0;
15541da177e4SLinus Torvalds 		tmport = wkport + 0x14;
15551da177e4SLinus Torvalds 		outb(0x05, tmport);
15561da177e4SLinus Torvalds 		tmport += 0x04;
15571da177e4SLinus Torvalds 		outb(0x20, tmport);
15581da177e4SLinus Torvalds 		tmport += 0x07;
15591da177e4SLinus Torvalds 
15601da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0) {
15611da177e4SLinus Torvalds 			if ((inb(tmport) & 0x01) != 0) {
15621da177e4SLinus Torvalds 				tmport -= 0x06;
15631da177e4SLinus Torvalds 				outb(wide[j++], tmport);
15641da177e4SLinus Torvalds 				tmport += 0x06;
15651da177e4SLinus Torvalds 			}
15661da177e4SLinus Torvalds 		}
15671da177e4SLinus Torvalds 		tmport -= 0x08;
15681da177e4SLinus Torvalds 
15691da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
15701da177e4SLinus Torvalds 			cpu_relax();
15711da177e4SLinus Torvalds 
15721da177e4SLinus Torvalds 		j = inb(tmport) & 0x0f;
15731da177e4SLinus Torvalds 		if (j == 0x0f) {
15741da177e4SLinus Torvalds 			goto widep_in;
15751da177e4SLinus Torvalds 		}
15761da177e4SLinus Torvalds 		if (j == 0x0a) {
15771da177e4SLinus Torvalds 			goto widep_cmd;
15781da177e4SLinus Torvalds 		}
15791da177e4SLinus Torvalds 		if (j == 0x0e) {
15801da177e4SLinus Torvalds 			goto try_wide;
15811da177e4SLinus Torvalds 		}
15821da177e4SLinus Torvalds 		continue;
15831da177e4SLinus Torvalds widep_out:
15841da177e4SLinus Torvalds 		tmport = wkport + 0x18;
15851da177e4SLinus Torvalds 		outb(0x20, tmport);
15861da177e4SLinus Torvalds 		tmport += 0x07;
15871da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0) {
15881da177e4SLinus Torvalds 			if ((inb(tmport) & 0x01) != 0) {
15891da177e4SLinus Torvalds 				tmport -= 0x06;
15901da177e4SLinus Torvalds 				outb(0, tmport);
15911da177e4SLinus Torvalds 				tmport += 0x06;
15921da177e4SLinus Torvalds 			}
15931da177e4SLinus Torvalds 		}
15941da177e4SLinus Torvalds 		tmport -= 0x08;
15951da177e4SLinus Torvalds 		j = inb(tmport) & 0x0f;
15961da177e4SLinus Torvalds 		if (j == 0x0f) {
15971da177e4SLinus Torvalds 			goto widep_in;
15981da177e4SLinus Torvalds 		}
15991da177e4SLinus Torvalds 		if (j == 0x0a) {
16001da177e4SLinus Torvalds 			goto widep_cmd;
16011da177e4SLinus Torvalds 		}
16021da177e4SLinus Torvalds 		if (j == 0x0e) {
16031da177e4SLinus Torvalds 			goto widep_out;
16041da177e4SLinus Torvalds 		}
16051da177e4SLinus Torvalds 		continue;
16061da177e4SLinus Torvalds widep_in:
16071da177e4SLinus Torvalds 		tmport = wkport + 0x14;
16081da177e4SLinus Torvalds 		outb(0xff, tmport);
16091da177e4SLinus Torvalds 		tmport += 0x04;
16101da177e4SLinus Torvalds 		outb(0x20, tmport);
16111da177e4SLinus Torvalds 		tmport += 0x07;
16121da177e4SLinus Torvalds 		k = 0;
16131da177e4SLinus Torvalds widep_in1:
16141da177e4SLinus Torvalds 		j = inb(tmport);
16151da177e4SLinus Torvalds 		if ((j & 0x01) != 0) {
16161da177e4SLinus Torvalds 			tmport -= 0x06;
16171da177e4SLinus Torvalds 			mbuf[k++] = inb(tmport);
16181da177e4SLinus Torvalds 			tmport += 0x06;
16191da177e4SLinus Torvalds 			goto widep_in1;
16201da177e4SLinus Torvalds 		}
16211da177e4SLinus Torvalds 		if ((j & 0x80) == 0x00) {
16221da177e4SLinus Torvalds 			goto widep_in1;
16231da177e4SLinus Torvalds 		}
16241da177e4SLinus Torvalds 		tmport -= 0x08;
16251da177e4SLinus Torvalds 		j = inb(tmport) & 0x0f;
16261da177e4SLinus Torvalds 		if (j == 0x0f) {
16271da177e4SLinus Torvalds 			goto widep_in;
16281da177e4SLinus Torvalds 		}
16291da177e4SLinus Torvalds 		if (j == 0x0a) {
16301da177e4SLinus Torvalds 			goto widep_cmd;
16311da177e4SLinus Torvalds 		}
16321da177e4SLinus Torvalds 		if (j == 0x0e) {
16331da177e4SLinus Torvalds 			goto widep_out;
16341da177e4SLinus Torvalds 		}
16351da177e4SLinus Torvalds 		continue;
16361da177e4SLinus Torvalds widep_cmd:
16371da177e4SLinus Torvalds 		tmport = wkport + 0x10;
16381da177e4SLinus Torvalds 		outb(0x30, tmport);
16391da177e4SLinus Torvalds 		tmport = wkport + 0x14;
16401da177e4SLinus Torvalds 		outb(0x00, tmport);
16411da177e4SLinus Torvalds 		tmport += 0x04;
16421da177e4SLinus Torvalds 		outb(0x08, tmport);
16431da177e4SLinus Torvalds 		tmport += 0x07;
16441da177e4SLinus Torvalds 
16451da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
16461da177e4SLinus Torvalds 			cpu_relax();
16471da177e4SLinus Torvalds 
16481da177e4SLinus Torvalds 		tmport -= 0x08;
16491da177e4SLinus Torvalds 		j = inb(tmport);
16501da177e4SLinus Torvalds 		if (j != 0x16) {
16511da177e4SLinus Torvalds 			if (j == 0x4e) {
16521da177e4SLinus Torvalds 				goto widep_out;
16531da177e4SLinus Torvalds 			}
16541da177e4SLinus Torvalds 			continue;
16551da177e4SLinus Torvalds 		}
16561da177e4SLinus Torvalds 		if (mbuf[0] != 0x01) {
16571da177e4SLinus Torvalds 			goto not_wide;
16581da177e4SLinus Torvalds 		}
16591da177e4SLinus Torvalds 		if (mbuf[1] != 0x02) {
16601da177e4SLinus Torvalds 			goto not_wide;
16611da177e4SLinus Torvalds 		}
16621da177e4SLinus Torvalds 		if (mbuf[2] != 0x03) {
16631da177e4SLinus Torvalds 			goto not_wide;
16641da177e4SLinus Torvalds 		}
16651da177e4SLinus Torvalds 		if (mbuf[3] != 0x01) {
16661da177e4SLinus Torvalds 			goto not_wide;
16671da177e4SLinus Torvalds 		}
16681da177e4SLinus Torvalds 		m = 1;
16691da177e4SLinus Torvalds 		m = m << i;
16701da177e4SLinus Torvalds 		dev->wide_id[0] |= m;
16711da177e4SLinus Torvalds not_wide:
16721da177e4SLinus Torvalds 		if ((dev->id[0][i].devtype == 0x00) || (dev->id[0][i].devtype == 0x07) || ((dev->id[0][i].devtype == 0x05) && ((n & 0x10) != 0))) {
16731da177e4SLinus Torvalds 			goto set_sync;
16741da177e4SLinus Torvalds 		}
16751da177e4SLinus Torvalds 		continue;
16761da177e4SLinus Torvalds set_sync:
16771da177e4SLinus Torvalds 		tmport = wkport + 0x1b;
16781da177e4SLinus Torvalds 		j = 0;
16791da177e4SLinus Torvalds 		if ((m & dev->wide_id[0]) != 0) {
16801da177e4SLinus Torvalds 			j |= 0x01;
16811da177e4SLinus Torvalds 		}
16821da177e4SLinus Torvalds 		outb(j, tmport);
16831da177e4SLinus Torvalds 		tmport = wkport + 3;
16841da177e4SLinus Torvalds 		outb(satn[0], tmport++);
16851da177e4SLinus Torvalds 		outb(satn[1], tmport++);
16861da177e4SLinus Torvalds 		outb(satn[2], tmport++);
16871da177e4SLinus Torvalds 		outb(satn[3], tmport++);
16881da177e4SLinus Torvalds 		outb(satn[4], tmport++);
16891da177e4SLinus Torvalds 		outb(satn[5], tmport++);
16901da177e4SLinus Torvalds 		tmport += 0x06;
16911da177e4SLinus Torvalds 		outb(0, tmport);
16921da177e4SLinus Torvalds 		tmport += 0x02;
16931da177e4SLinus Torvalds 		outb(dev->id[0][i].devsp, tmport++);
16941da177e4SLinus Torvalds 		outb(0, tmport++);
16951da177e4SLinus Torvalds 		outb(satn[6], tmport++);
16961da177e4SLinus Torvalds 		outb(satn[7], tmport++);
16971da177e4SLinus Torvalds 		tmport += 0x03;
16981da177e4SLinus Torvalds 		outb(satn[8], tmport);
16991da177e4SLinus Torvalds 		tmport += 0x07;
17001da177e4SLinus Torvalds 
17011da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
17021da177e4SLinus Torvalds 			cpu_relax();
17031da177e4SLinus Torvalds 
17041da177e4SLinus Torvalds 		tmport -= 0x08;
17051da177e4SLinus Torvalds 		if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
17061da177e4SLinus Torvalds 			continue;
17071da177e4SLinus Torvalds 
17081da177e4SLinus Torvalds 		while (inb(tmport) != 0x8e)
17091da177e4SLinus Torvalds 			cpu_relax();
17101da177e4SLinus Torvalds 
17111da177e4SLinus Torvalds try_sync:
17121da177e4SLinus Torvalds 		j = 0;
17131da177e4SLinus Torvalds 		tmport = wkport + 0x14;
17141da177e4SLinus Torvalds 		outb(0x06, tmport);
17151da177e4SLinus Torvalds 		tmport += 0x04;
17161da177e4SLinus Torvalds 		outb(0x20, tmport);
17171da177e4SLinus Torvalds 		tmport += 0x07;
17181da177e4SLinus Torvalds 
17191da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0) {
17201da177e4SLinus Torvalds 			if ((inb(tmport) & 0x01) != 0) {
17211da177e4SLinus Torvalds 				tmport -= 0x06;
17221da177e4SLinus Torvalds 				if ((m & dev->wide_id[0]) != 0) {
17231da177e4SLinus Torvalds 					outb(synw[j++], tmport);
17241da177e4SLinus Torvalds 				} else {
17251da177e4SLinus Torvalds 					if ((m & dev->ultra_map[0]) != 0) {
17261da177e4SLinus Torvalds 						outb(synu[j++], tmport);
17271da177e4SLinus Torvalds 					} else {
17281da177e4SLinus Torvalds 						outb(synn[j++], tmport);
17291da177e4SLinus Torvalds 					}
17301da177e4SLinus Torvalds 				}
17311da177e4SLinus Torvalds 				tmport += 0x06;
17321da177e4SLinus Torvalds 			}
17331da177e4SLinus Torvalds 		}
17341da177e4SLinus Torvalds 		tmport -= 0x08;
17351da177e4SLinus Torvalds 
17361da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
17371da177e4SLinus Torvalds 			cpu_relax();
17381da177e4SLinus Torvalds 
17391da177e4SLinus Torvalds 		j = inb(tmport) & 0x0f;
17401da177e4SLinus Torvalds 		if (j == 0x0f) {
17411da177e4SLinus Torvalds 			goto phase_ins;
17421da177e4SLinus Torvalds 		}
17431da177e4SLinus Torvalds 		if (j == 0x0a) {
17441da177e4SLinus Torvalds 			goto phase_cmds;
17451da177e4SLinus Torvalds 		}
17461da177e4SLinus Torvalds 		if (j == 0x0e) {
17471da177e4SLinus Torvalds 			goto try_sync;
17481da177e4SLinus Torvalds 		}
17491da177e4SLinus Torvalds 		continue;
17501da177e4SLinus Torvalds phase_outs:
17511da177e4SLinus Torvalds 		tmport = wkport + 0x18;
17521da177e4SLinus Torvalds 		outb(0x20, tmport);
17531da177e4SLinus Torvalds 		tmport += 0x07;
17541da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00) {
17551da177e4SLinus Torvalds 			if ((inb(tmport) & 0x01) != 0x00) {
17561da177e4SLinus Torvalds 				tmport -= 0x06;
17571da177e4SLinus Torvalds 				outb(0x00, tmport);
17581da177e4SLinus Torvalds 				tmport += 0x06;
17591da177e4SLinus Torvalds 			}
17601da177e4SLinus Torvalds 		}
17611da177e4SLinus Torvalds 		tmport -= 0x08;
17621da177e4SLinus Torvalds 		j = inb(tmport);
17631da177e4SLinus Torvalds 		if (j == 0x85) {
17641da177e4SLinus Torvalds 			goto tar_dcons;
17651da177e4SLinus Torvalds 		}
17661da177e4SLinus Torvalds 		j &= 0x0f;
17671da177e4SLinus Torvalds 		if (j == 0x0f) {
17681da177e4SLinus Torvalds 			goto phase_ins;
17691da177e4SLinus Torvalds 		}
17701da177e4SLinus Torvalds 		if (j == 0x0a) {
17711da177e4SLinus Torvalds 			goto phase_cmds;
17721da177e4SLinus Torvalds 		}
17731da177e4SLinus Torvalds 		if (j == 0x0e) {
17741da177e4SLinus Torvalds 			goto phase_outs;
17751da177e4SLinus Torvalds 		}
17761da177e4SLinus Torvalds 		continue;
17771da177e4SLinus Torvalds phase_ins:
17781da177e4SLinus Torvalds 		tmport = wkport + 0x14;
17791da177e4SLinus Torvalds 		outb(0xff, tmport);
17801da177e4SLinus Torvalds 		tmport += 0x04;
17811da177e4SLinus Torvalds 		outb(0x20, tmport);
17821da177e4SLinus Torvalds 		tmport += 0x07;
17831da177e4SLinus Torvalds 		k = 0;
17841da177e4SLinus Torvalds phase_ins1:
17851da177e4SLinus Torvalds 		j = inb(tmport);
17861da177e4SLinus Torvalds 		if ((j & 0x01) != 0x00) {
17871da177e4SLinus Torvalds 			tmport -= 0x06;
17881da177e4SLinus Torvalds 			mbuf[k++] = inb(tmport);
17891da177e4SLinus Torvalds 			tmport += 0x06;
17901da177e4SLinus Torvalds 			goto phase_ins1;
17911da177e4SLinus Torvalds 		}
17921da177e4SLinus Torvalds 		if ((j & 0x80) == 0x00) {
17931da177e4SLinus Torvalds 			goto phase_ins1;
17941da177e4SLinus Torvalds 		}
17951da177e4SLinus Torvalds 		tmport -= 0x08;
17961da177e4SLinus Torvalds 
17971da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
17981da177e4SLinus Torvalds 			cpu_relax();
17991da177e4SLinus Torvalds 
18001da177e4SLinus Torvalds 		j = inb(tmport);
18011da177e4SLinus Torvalds 		if (j == 0x85) {
18021da177e4SLinus Torvalds 			goto tar_dcons;
18031da177e4SLinus Torvalds 		}
18041da177e4SLinus Torvalds 		j &= 0x0f;
18051da177e4SLinus Torvalds 		if (j == 0x0f) {
18061da177e4SLinus Torvalds 			goto phase_ins;
18071da177e4SLinus Torvalds 		}
18081da177e4SLinus Torvalds 		if (j == 0x0a) {
18091da177e4SLinus Torvalds 			goto phase_cmds;
18101da177e4SLinus Torvalds 		}
18111da177e4SLinus Torvalds 		if (j == 0x0e) {
18121da177e4SLinus Torvalds 			goto phase_outs;
18131da177e4SLinus Torvalds 		}
18141da177e4SLinus Torvalds 		continue;
18151da177e4SLinus Torvalds phase_cmds:
18161da177e4SLinus Torvalds 		tmport = wkport + 0x10;
18171da177e4SLinus Torvalds 		outb(0x30, tmport);
18181da177e4SLinus Torvalds tar_dcons:
18191da177e4SLinus Torvalds 		tmport = wkport + 0x14;
18201da177e4SLinus Torvalds 		outb(0x00, tmport);
18211da177e4SLinus Torvalds 		tmport += 0x04;
18221da177e4SLinus Torvalds 		outb(0x08, tmport);
18231da177e4SLinus Torvalds 		tmport += 0x07;
18241da177e4SLinus Torvalds 
18251da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
18261da177e4SLinus Torvalds 			cpu_relax();
18271da177e4SLinus Torvalds 
18281da177e4SLinus Torvalds 		tmport -= 0x08;
18291da177e4SLinus Torvalds 		j = inb(tmport);
18301da177e4SLinus Torvalds 		if (j != 0x16) {
18311da177e4SLinus Torvalds 			continue;
18321da177e4SLinus Torvalds 		}
18331da177e4SLinus Torvalds 		if (mbuf[0] != 0x01) {
18341da177e4SLinus Torvalds 			continue;
18351da177e4SLinus Torvalds 		}
18361da177e4SLinus Torvalds 		if (mbuf[1] != 0x03) {
18371da177e4SLinus Torvalds 			continue;
18381da177e4SLinus Torvalds 		}
18391da177e4SLinus Torvalds 		if (mbuf[4] == 0x00) {
18401da177e4SLinus Torvalds 			continue;
18411da177e4SLinus Torvalds 		}
18421da177e4SLinus Torvalds 		if (mbuf[3] > 0x64) {
18431da177e4SLinus Torvalds 			continue;
18441da177e4SLinus Torvalds 		}
18451da177e4SLinus Torvalds 		if (mbuf[4] > 0x0c) {
18461da177e4SLinus Torvalds 			mbuf[4] = 0x0c;
18471da177e4SLinus Torvalds 		}
18481da177e4SLinus Torvalds 		dev->id[0][i].devsp = mbuf[4];
18491da177e4SLinus Torvalds 		if ((mbuf[3] < 0x0d) && (rmb == 0)) {
18501da177e4SLinus Torvalds 			j = 0xa0;
18511da177e4SLinus Torvalds 			goto set_syn_ok;
18521da177e4SLinus Torvalds 		}
18531da177e4SLinus Torvalds 		if (mbuf[3] < 0x1a) {
18541da177e4SLinus Torvalds 			j = 0x20;
18551da177e4SLinus Torvalds 			goto set_syn_ok;
18561da177e4SLinus Torvalds 		}
18571da177e4SLinus Torvalds 		if (mbuf[3] < 0x33) {
18581da177e4SLinus Torvalds 			j = 0x40;
18591da177e4SLinus Torvalds 			goto set_syn_ok;
18601da177e4SLinus Torvalds 		}
18611da177e4SLinus Torvalds 		if (mbuf[3] < 0x4c) {
18621da177e4SLinus Torvalds 			j = 0x50;
18631da177e4SLinus Torvalds 			goto set_syn_ok;
18641da177e4SLinus Torvalds 		}
18651da177e4SLinus Torvalds 		j = 0x60;
18661da177e4SLinus Torvalds set_syn_ok:
18671da177e4SLinus Torvalds 		dev->id[0][i].devsp = (dev->id[0][i].devsp & 0x0f) | j;
18681da177e4SLinus Torvalds 	}
18691da177e4SLinus Torvalds 	tmport = wkport + 0x3a;
18701da177e4SLinus Torvalds 	outb((unsigned char) (inb(tmport) & 0xef), tmport);
18711da177e4SLinus Torvalds }
18721da177e4SLinus Torvalds 
18731da177e4SLinus Torvalds static void is880(struct atp_unit *dev, unsigned int wkport)
18741da177e4SLinus Torvalds {
18751da177e4SLinus Torvalds 	unsigned int tmport;
18761da177e4SLinus Torvalds 	unsigned char i, j, k, rmb, n, lvdmode;
18771da177e4SLinus Torvalds 	unsigned short int m;
18781da177e4SLinus Torvalds 	static unsigned char mbuf[512];
18791da177e4SLinus Torvalds 	static unsigned char satn[9] = { 0, 0, 0, 0, 0, 0, 0, 6, 6 };
18801da177e4SLinus Torvalds 	static unsigned char inqd[9] = { 0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6 };
18811da177e4SLinus Torvalds 	static unsigned char synn[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
18821da177e4SLinus Torvalds 	unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
18831da177e4SLinus Torvalds 	static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
18841da177e4SLinus Torvalds 	unsigned char synuw[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
18851da177e4SLinus Torvalds 	static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
18861da177e4SLinus Torvalds 	static unsigned char u3[9] = { 0x80, 1, 6, 4, 0x09, 00, 0x0e, 0x01, 0x02 };
18871da177e4SLinus Torvalds 
18881da177e4SLinus Torvalds 	lvdmode = inb(wkport + 0x3f) & 0x40;
18891da177e4SLinus Torvalds 
18901da177e4SLinus Torvalds 	for (i = 0; i < 16; i++) {
18911da177e4SLinus Torvalds 		m = 1;
18921da177e4SLinus Torvalds 		m = m << i;
18931da177e4SLinus Torvalds 		if ((m & dev->active_id[0]) != 0) {
18941da177e4SLinus Torvalds 			continue;
18951da177e4SLinus Torvalds 		}
18961da177e4SLinus Torvalds 		if (i == dev->host_id[0]) {
18971da177e4SLinus Torvalds 			printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_id[0]);
18981da177e4SLinus Torvalds 			continue;
18991da177e4SLinus Torvalds 		}
19001da177e4SLinus Torvalds 		tmport = wkport + 0x5b;
19011da177e4SLinus Torvalds 		outb(0x01, tmport);
19021da177e4SLinus Torvalds 		tmport = wkport + 0x41;
19031da177e4SLinus Torvalds 		outb(0x08, tmport++);
19041da177e4SLinus Torvalds 		outb(0x7f, tmport++);
19051da177e4SLinus Torvalds 		outb(satn[0], tmport++);
19061da177e4SLinus Torvalds 		outb(satn[1], tmport++);
19071da177e4SLinus Torvalds 		outb(satn[2], tmport++);
19081da177e4SLinus Torvalds 		outb(satn[3], tmport++);
19091da177e4SLinus Torvalds 		outb(satn[4], tmport++);
19101da177e4SLinus Torvalds 		outb(satn[5], tmport++);
19111da177e4SLinus Torvalds 		tmport += 0x06;
19121da177e4SLinus Torvalds 		outb(0, tmport);
19131da177e4SLinus Torvalds 		tmport += 0x02;
19141da177e4SLinus Torvalds 		outb(dev->id[0][i].devsp, tmport++);
19151da177e4SLinus Torvalds 		outb(0, tmport++);
19161da177e4SLinus Torvalds 		outb(satn[6], tmport++);
19171da177e4SLinus Torvalds 		outb(satn[7], tmport++);
19181da177e4SLinus Torvalds 		j = i;
19191da177e4SLinus Torvalds 		if ((j & 0x08) != 0) {
19201da177e4SLinus Torvalds 			j = (j & 0x07) | 0x40;
19211da177e4SLinus Torvalds 		}
19221da177e4SLinus Torvalds 		outb(j, tmport);
19231da177e4SLinus Torvalds 		tmport += 0x03;
19241da177e4SLinus Torvalds 		outb(satn[8], tmport);
19251da177e4SLinus Torvalds 		tmport += 0x07;
19261da177e4SLinus Torvalds 
19271da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
19281da177e4SLinus Torvalds 			cpu_relax();
19291da177e4SLinus Torvalds 
19301da177e4SLinus Torvalds 		tmport -= 0x08;
19311da177e4SLinus Torvalds 		if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
19321da177e4SLinus Torvalds 			continue;
19331da177e4SLinus Torvalds 
19341da177e4SLinus Torvalds 		while (inb(tmport) != 0x8e)
19351da177e4SLinus Torvalds 			cpu_relax();
19361da177e4SLinus Torvalds 
19371da177e4SLinus Torvalds 		dev->active_id[0] |= m;
19381da177e4SLinus Torvalds 
19391da177e4SLinus Torvalds 		tmport = wkport + 0x50;
19401da177e4SLinus Torvalds 		outb(0x30, tmport);
19411da177e4SLinus Torvalds 		tmport = wkport + 0x54;
19421da177e4SLinus Torvalds 		outb(0x00, tmport);
19431da177e4SLinus Torvalds 
19441da177e4SLinus Torvalds phase_cmd:
19451da177e4SLinus Torvalds 		tmport = wkport + 0x58;
19461da177e4SLinus Torvalds 		outb(0x08, tmport);
19471da177e4SLinus Torvalds 		tmport += 0x07;
19481da177e4SLinus Torvalds 
19491da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
19501da177e4SLinus Torvalds 			cpu_relax();
19511da177e4SLinus Torvalds 
19521da177e4SLinus Torvalds 		tmport -= 0x08;
19531da177e4SLinus Torvalds 		j = inb(tmport);
19541da177e4SLinus Torvalds 		if (j != 0x16) {
19551da177e4SLinus Torvalds 			tmport = wkport + 0x50;
19561da177e4SLinus Torvalds 			outb(0x41, tmport);
19571da177e4SLinus Torvalds 			goto phase_cmd;
19581da177e4SLinus Torvalds 		}
19591da177e4SLinus Torvalds sel_ok:
19601da177e4SLinus Torvalds 		tmport = wkport + 0x43;
19611da177e4SLinus Torvalds 		outb(inqd[0], tmport++);
19621da177e4SLinus Torvalds 		outb(inqd[1], tmport++);
19631da177e4SLinus Torvalds 		outb(inqd[2], tmport++);
19641da177e4SLinus Torvalds 		outb(inqd[3], tmport++);
19651da177e4SLinus Torvalds 		outb(inqd[4], tmport++);
19661da177e4SLinus Torvalds 		outb(inqd[5], tmport);
19671da177e4SLinus Torvalds 		tmport += 0x07;
19681da177e4SLinus Torvalds 		outb(0, tmport);
19691da177e4SLinus Torvalds 		tmport += 0x02;
19701da177e4SLinus Torvalds 		outb(dev->id[0][i].devsp, tmport++);
19711da177e4SLinus Torvalds 		outb(0, tmport++);
19721da177e4SLinus Torvalds 		outb(inqd[6], tmport++);
19731da177e4SLinus Torvalds 		outb(inqd[7], tmport++);
19741da177e4SLinus Torvalds 		tmport += 0x03;
19751da177e4SLinus Torvalds 		outb(inqd[8], tmport);
19761da177e4SLinus Torvalds 		tmport += 0x07;
19771da177e4SLinus Torvalds 
19781da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
19791da177e4SLinus Torvalds 			cpu_relax();
19801da177e4SLinus Torvalds 
19811da177e4SLinus Torvalds 		tmport -= 0x08;
19821da177e4SLinus Torvalds 		if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
19831da177e4SLinus Torvalds 			continue;
19841da177e4SLinus Torvalds 
19851da177e4SLinus Torvalds 		while (inb(tmport) != 0x8e)
19861da177e4SLinus Torvalds 			cpu_relax();
19871da177e4SLinus Torvalds 
19881da177e4SLinus Torvalds 		tmport = wkport + 0x5b;
19891da177e4SLinus Torvalds 		outb(0x00, tmport);
19901da177e4SLinus Torvalds 		tmport = wkport + 0x58;
19911da177e4SLinus Torvalds 		outb(0x08, tmport);
19921da177e4SLinus Torvalds 		tmport += 0x07;
19931da177e4SLinus Torvalds 		j = 0;
19941da177e4SLinus Torvalds rd_inq_data:
19951da177e4SLinus Torvalds 		k = inb(tmport);
19961da177e4SLinus Torvalds 		if ((k & 0x01) != 0) {
19971da177e4SLinus Torvalds 			tmport -= 0x06;
19981da177e4SLinus Torvalds 			mbuf[j++] = inb(tmport);
19991da177e4SLinus Torvalds 			tmport += 0x06;
20001da177e4SLinus Torvalds 			goto rd_inq_data;
20011da177e4SLinus Torvalds 		}
20021da177e4SLinus Torvalds 		if ((k & 0x80) == 0) {
20031da177e4SLinus Torvalds 			goto rd_inq_data;
20041da177e4SLinus Torvalds 		}
20051da177e4SLinus Torvalds 		tmport -= 0x08;
20061da177e4SLinus Torvalds 		j = inb(tmport);
20071da177e4SLinus Torvalds 		if (j == 0x16) {
20081da177e4SLinus Torvalds 			goto inq_ok;
20091da177e4SLinus Torvalds 		}
20101da177e4SLinus Torvalds 		tmport = wkport + 0x50;
20111da177e4SLinus Torvalds 		outb(0x46, tmport);
20121da177e4SLinus Torvalds 		tmport += 0x02;
20131da177e4SLinus Torvalds 		outb(0, tmport++);
20141da177e4SLinus Torvalds 		outb(0, tmport++);
20151da177e4SLinus Torvalds 		outb(0, tmport++);
20161da177e4SLinus Torvalds 		tmport += 0x03;
20171da177e4SLinus Torvalds 		outb(0x08, tmport);
20181da177e4SLinus Torvalds 		tmport += 0x07;
20191da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
20201da177e4SLinus Torvalds 			cpu_relax();
20211da177e4SLinus Torvalds 
20221da177e4SLinus Torvalds 		tmport -= 0x08;
20231da177e4SLinus Torvalds 		if (inb(tmport) != 0x16)
20241da177e4SLinus Torvalds 			goto sel_ok;
20251da177e4SLinus Torvalds 
20261da177e4SLinus Torvalds inq_ok:
20271da177e4SLinus Torvalds 		mbuf[36] = 0;
20281da177e4SLinus Torvalds 		printk(KERN_INFO "         ID: %2d  %s\n", i, &mbuf[8]);
20291da177e4SLinus Torvalds 		dev->id[0][i].devtype = mbuf[0];
20301da177e4SLinus Torvalds 		rmb = mbuf[1];
20311da177e4SLinus Torvalds 		n = mbuf[7];
20321da177e4SLinus Torvalds 		if ((mbuf[7] & 0x60) == 0) {
20331da177e4SLinus Torvalds 			goto not_wide;
20341da177e4SLinus Torvalds 		}
20351da177e4SLinus Torvalds 		if ((i < 8) && ((dev->global_map[0] & 0x20) == 0)) {
20361da177e4SLinus Torvalds 			goto not_wide;
20371da177e4SLinus Torvalds 		}
20381da177e4SLinus Torvalds 		if (lvdmode == 0) {
20391da177e4SLinus Torvalds 			goto chg_wide;
20401da177e4SLinus Torvalds 		}
20411da177e4SLinus Torvalds 		if (dev->sp[0][i] != 0x04)	// force u2
20421da177e4SLinus Torvalds 		{
20431da177e4SLinus Torvalds 			goto chg_wide;
20441da177e4SLinus Torvalds 		}
20451da177e4SLinus Torvalds 
20461da177e4SLinus Torvalds 		tmport = wkport + 0x5b;
20471da177e4SLinus Torvalds 		outb(0x01, tmport);
20481da177e4SLinus Torvalds 		tmport = wkport + 0x43;
20491da177e4SLinus Torvalds 		outb(satn[0], tmport++);
20501da177e4SLinus Torvalds 		outb(satn[1], tmport++);
20511da177e4SLinus Torvalds 		outb(satn[2], tmport++);
20521da177e4SLinus Torvalds 		outb(satn[3], tmport++);
20531da177e4SLinus Torvalds 		outb(satn[4], tmport++);
20541da177e4SLinus Torvalds 		outb(satn[5], tmport++);
20551da177e4SLinus Torvalds 		tmport += 0x06;
20561da177e4SLinus Torvalds 		outb(0, tmport);
20571da177e4SLinus Torvalds 		tmport += 0x02;
20581da177e4SLinus Torvalds 		outb(dev->id[0][i].devsp, tmport++);
20591da177e4SLinus Torvalds 		outb(0, tmport++);
20601da177e4SLinus Torvalds 		outb(satn[6], tmport++);
20611da177e4SLinus Torvalds 		outb(satn[7], tmport++);
20621da177e4SLinus Torvalds 		tmport += 0x03;
20631da177e4SLinus Torvalds 		outb(satn[8], tmport);
20641da177e4SLinus Torvalds 		tmport += 0x07;
20651da177e4SLinus Torvalds 
20661da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
20671da177e4SLinus Torvalds 			cpu_relax();
20681da177e4SLinus Torvalds 
20691da177e4SLinus Torvalds 		tmport -= 0x08;
20701da177e4SLinus Torvalds 
20711da177e4SLinus Torvalds 		if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
20721da177e4SLinus Torvalds 			continue;
20731da177e4SLinus Torvalds 
20741da177e4SLinus Torvalds 		while (inb(tmport) != 0x8e)
20751da177e4SLinus Torvalds 			cpu_relax();
20761da177e4SLinus Torvalds 
20771da177e4SLinus Torvalds try_u3:
20781da177e4SLinus Torvalds 		j = 0;
20791da177e4SLinus Torvalds 		tmport = wkport + 0x54;
20801da177e4SLinus Torvalds 		outb(0x09, tmport);
20811da177e4SLinus Torvalds 		tmport += 0x04;
20821da177e4SLinus Torvalds 		outb(0x20, tmport);
20831da177e4SLinus Torvalds 		tmport += 0x07;
20841da177e4SLinus Torvalds 
20851da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0) {
20861da177e4SLinus Torvalds 			if ((inb(tmport) & 0x01) != 0) {
20871da177e4SLinus Torvalds 				tmport -= 0x06;
20881da177e4SLinus Torvalds 				outb(u3[j++], tmport);
20891da177e4SLinus Torvalds 				tmport += 0x06;
20901da177e4SLinus Torvalds 			}
20911da177e4SLinus Torvalds 		}
20921da177e4SLinus Torvalds 		tmport -= 0x08;
20931da177e4SLinus Torvalds 
20941da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
20951da177e4SLinus Torvalds 			cpu_relax();
20961da177e4SLinus Torvalds 
20971da177e4SLinus Torvalds 		j = inb(tmport) & 0x0f;
20981da177e4SLinus Torvalds 		if (j == 0x0f) {
20991da177e4SLinus Torvalds 			goto u3p_in;
21001da177e4SLinus Torvalds 		}
21011da177e4SLinus Torvalds 		if (j == 0x0a) {
21021da177e4SLinus Torvalds 			goto u3p_cmd;
21031da177e4SLinus Torvalds 		}
21041da177e4SLinus Torvalds 		if (j == 0x0e) {
21051da177e4SLinus Torvalds 			goto try_u3;
21061da177e4SLinus Torvalds 		}
21071da177e4SLinus Torvalds 		continue;
21081da177e4SLinus Torvalds u3p_out:
21091da177e4SLinus Torvalds 		tmport = wkport + 0x58;
21101da177e4SLinus Torvalds 		outb(0x20, tmport);
21111da177e4SLinus Torvalds 		tmport += 0x07;
21121da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0) {
21131da177e4SLinus Torvalds 			if ((inb(tmport) & 0x01) != 0) {
21141da177e4SLinus Torvalds 				tmport -= 0x06;
21151da177e4SLinus Torvalds 				outb(0, tmport);
21161da177e4SLinus Torvalds 				tmport += 0x06;
21171da177e4SLinus Torvalds 			}
21181da177e4SLinus Torvalds 		}
21191da177e4SLinus Torvalds 		tmport -= 0x08;
21201da177e4SLinus Torvalds 		j = inb(tmport) & 0x0f;
21211da177e4SLinus Torvalds 		if (j == 0x0f) {
21221da177e4SLinus Torvalds 			goto u3p_in;
21231da177e4SLinus Torvalds 		}
21241da177e4SLinus Torvalds 		if (j == 0x0a) {
21251da177e4SLinus Torvalds 			goto u3p_cmd;
21261da177e4SLinus Torvalds 		}
21271da177e4SLinus Torvalds 		if (j == 0x0e) {
21281da177e4SLinus Torvalds 			goto u3p_out;
21291da177e4SLinus Torvalds 		}
21301da177e4SLinus Torvalds 		continue;
21311da177e4SLinus Torvalds u3p_in:
21321da177e4SLinus Torvalds 		tmport = wkport + 0x54;
21331da177e4SLinus Torvalds 		outb(0x09, tmport);
21341da177e4SLinus Torvalds 		tmport += 0x04;
21351da177e4SLinus Torvalds 		outb(0x20, tmport);
21361da177e4SLinus Torvalds 		tmport += 0x07;
21371da177e4SLinus Torvalds 		k = 0;
21381da177e4SLinus Torvalds u3p_in1:
21391da177e4SLinus Torvalds 		j = inb(tmport);
21401da177e4SLinus Torvalds 		if ((j & 0x01) != 0) {
21411da177e4SLinus Torvalds 			tmport -= 0x06;
21421da177e4SLinus Torvalds 			mbuf[k++] = inb(tmport);
21431da177e4SLinus Torvalds 			tmport += 0x06;
21441da177e4SLinus Torvalds 			goto u3p_in1;
21451da177e4SLinus Torvalds 		}
21461da177e4SLinus Torvalds 		if ((j & 0x80) == 0x00) {
21471da177e4SLinus Torvalds 			goto u3p_in1;
21481da177e4SLinus Torvalds 		}
21491da177e4SLinus Torvalds 		tmport -= 0x08;
21501da177e4SLinus Torvalds 		j = inb(tmport) & 0x0f;
21511da177e4SLinus Torvalds 		if (j == 0x0f) {
21521da177e4SLinus Torvalds 			goto u3p_in;
21531da177e4SLinus Torvalds 		}
21541da177e4SLinus Torvalds 		if (j == 0x0a) {
21551da177e4SLinus Torvalds 			goto u3p_cmd;
21561da177e4SLinus Torvalds 		}
21571da177e4SLinus Torvalds 		if (j == 0x0e) {
21581da177e4SLinus Torvalds 			goto u3p_out;
21591da177e4SLinus Torvalds 		}
21601da177e4SLinus Torvalds 		continue;
21611da177e4SLinus Torvalds u3p_cmd:
21621da177e4SLinus Torvalds 		tmport = wkport + 0x50;
21631da177e4SLinus Torvalds 		outb(0x30, tmport);
21641da177e4SLinus Torvalds 		tmport = wkport + 0x54;
21651da177e4SLinus Torvalds 		outb(0x00, tmport);
21661da177e4SLinus Torvalds 		tmport += 0x04;
21671da177e4SLinus Torvalds 		outb(0x08, tmport);
21681da177e4SLinus Torvalds 		tmport += 0x07;
21691da177e4SLinus Torvalds 
21701da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
21711da177e4SLinus Torvalds 			cpu_relax();
21721da177e4SLinus Torvalds 
21731da177e4SLinus Torvalds 		tmport -= 0x08;
21741da177e4SLinus Torvalds 		j = inb(tmport);
21751da177e4SLinus Torvalds 		if (j != 0x16) {
21761da177e4SLinus Torvalds 			if (j == 0x4e) {
21771da177e4SLinus Torvalds 				goto u3p_out;
21781da177e4SLinus Torvalds 			}
21791da177e4SLinus Torvalds 			continue;
21801da177e4SLinus Torvalds 		}
21811da177e4SLinus Torvalds 		if (mbuf[0] != 0x01) {
21821da177e4SLinus Torvalds 			goto chg_wide;
21831da177e4SLinus Torvalds 		}
21841da177e4SLinus Torvalds 		if (mbuf[1] != 0x06) {
21851da177e4SLinus Torvalds 			goto chg_wide;
21861da177e4SLinus Torvalds 		}
21871da177e4SLinus Torvalds 		if (mbuf[2] != 0x04) {
21881da177e4SLinus Torvalds 			goto chg_wide;
21891da177e4SLinus Torvalds 		}
21901da177e4SLinus Torvalds 		if (mbuf[3] == 0x09) {
21911da177e4SLinus Torvalds 			m = 1;
21921da177e4SLinus Torvalds 			m = m << i;
21931da177e4SLinus Torvalds 			dev->wide_id[0] |= m;
21941da177e4SLinus Torvalds 			dev->id[0][i].devsp = 0xce;
21951da177e4SLinus Torvalds 			continue;
21961da177e4SLinus Torvalds 		}
21971da177e4SLinus Torvalds chg_wide:
21981da177e4SLinus Torvalds 		tmport = wkport + 0x5b;
21991da177e4SLinus Torvalds 		outb(0x01, tmport);
22001da177e4SLinus Torvalds 		tmport = wkport + 0x43;
22011da177e4SLinus Torvalds 		outb(satn[0], tmport++);
22021da177e4SLinus Torvalds 		outb(satn[1], tmport++);
22031da177e4SLinus Torvalds 		outb(satn[2], tmport++);
22041da177e4SLinus Torvalds 		outb(satn[3], tmport++);
22051da177e4SLinus Torvalds 		outb(satn[4], tmport++);
22061da177e4SLinus Torvalds 		outb(satn[5], tmport++);
22071da177e4SLinus Torvalds 		tmport += 0x06;
22081da177e4SLinus Torvalds 		outb(0, tmport);
22091da177e4SLinus Torvalds 		tmport += 0x02;
22101da177e4SLinus Torvalds 		outb(dev->id[0][i].devsp, tmport++);
22111da177e4SLinus Torvalds 		outb(0, tmport++);
22121da177e4SLinus Torvalds 		outb(satn[6], tmport++);
22131da177e4SLinus Torvalds 		outb(satn[7], tmport++);
22141da177e4SLinus Torvalds 		tmport += 0x03;
22151da177e4SLinus Torvalds 		outb(satn[8], tmport);
22161da177e4SLinus Torvalds 		tmport += 0x07;
22171da177e4SLinus Torvalds 
22181da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
22191da177e4SLinus Torvalds 			cpu_relax();
22201da177e4SLinus Torvalds 
22211da177e4SLinus Torvalds 		tmport -= 0x08;
22221da177e4SLinus Torvalds 		if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
22231da177e4SLinus Torvalds 			continue;
22241da177e4SLinus Torvalds 
22251da177e4SLinus Torvalds 		while (inb(tmport) != 0x8e)
22261da177e4SLinus Torvalds 			cpu_relax();
22271da177e4SLinus Torvalds 
22281da177e4SLinus Torvalds try_wide:
22291da177e4SLinus Torvalds 		j = 0;
22301da177e4SLinus Torvalds 		tmport = wkport + 0x54;
22311da177e4SLinus Torvalds 		outb(0x05, tmport);
22321da177e4SLinus Torvalds 		tmport += 0x04;
22331da177e4SLinus Torvalds 		outb(0x20, tmport);
22341da177e4SLinus Torvalds 		tmport += 0x07;
22351da177e4SLinus Torvalds 
22361da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0) {
22371da177e4SLinus Torvalds 			if ((inb(tmport) & 0x01) != 0) {
22381da177e4SLinus Torvalds 				tmport -= 0x06;
22391da177e4SLinus Torvalds 				outb(wide[j++], tmport);
22401da177e4SLinus Torvalds 				tmport += 0x06;
22411da177e4SLinus Torvalds 			}
22421da177e4SLinus Torvalds 		}
22431da177e4SLinus Torvalds 		tmport -= 0x08;
22441da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
22451da177e4SLinus Torvalds 			cpu_relax();
22461da177e4SLinus Torvalds 
22471da177e4SLinus Torvalds 		j = inb(tmport) & 0x0f;
22481da177e4SLinus Torvalds 		if (j == 0x0f) {
22491da177e4SLinus Torvalds 			goto widep_in;
22501da177e4SLinus Torvalds 		}
22511da177e4SLinus Torvalds 		if (j == 0x0a) {
22521da177e4SLinus Torvalds 			goto widep_cmd;
22531da177e4SLinus Torvalds 		}
22541da177e4SLinus Torvalds 		if (j == 0x0e) {
22551da177e4SLinus Torvalds 			goto try_wide;
22561da177e4SLinus Torvalds 		}
22571da177e4SLinus Torvalds 		continue;
22581da177e4SLinus Torvalds widep_out:
22591da177e4SLinus Torvalds 		tmport = wkport + 0x58;
22601da177e4SLinus Torvalds 		outb(0x20, tmport);
22611da177e4SLinus Torvalds 		tmport += 0x07;
22621da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0) {
22631da177e4SLinus Torvalds 			if ((inb(tmport) & 0x01) != 0) {
22641da177e4SLinus Torvalds 				tmport -= 0x06;
22651da177e4SLinus Torvalds 				outb(0, tmport);
22661da177e4SLinus Torvalds 				tmport += 0x06;
22671da177e4SLinus Torvalds 			}
22681da177e4SLinus Torvalds 		}
22691da177e4SLinus Torvalds 		tmport -= 0x08;
22701da177e4SLinus Torvalds 		j = inb(tmport) & 0x0f;
22711da177e4SLinus Torvalds 		if (j == 0x0f) {
22721da177e4SLinus Torvalds 			goto widep_in;
22731da177e4SLinus Torvalds 		}
22741da177e4SLinus Torvalds 		if (j == 0x0a) {
22751da177e4SLinus Torvalds 			goto widep_cmd;
22761da177e4SLinus Torvalds 		}
22771da177e4SLinus Torvalds 		if (j == 0x0e) {
22781da177e4SLinus Torvalds 			goto widep_out;
22791da177e4SLinus Torvalds 		}
22801da177e4SLinus Torvalds 		continue;
22811da177e4SLinus Torvalds widep_in:
22821da177e4SLinus Torvalds 		tmport = wkport + 0x54;
22831da177e4SLinus Torvalds 		outb(0xff, tmport);
22841da177e4SLinus Torvalds 		tmport += 0x04;
22851da177e4SLinus Torvalds 		outb(0x20, tmport);
22861da177e4SLinus Torvalds 		tmport += 0x07;
22871da177e4SLinus Torvalds 		k = 0;
22881da177e4SLinus Torvalds widep_in1:
22891da177e4SLinus Torvalds 		j = inb(tmport);
22901da177e4SLinus Torvalds 		if ((j & 0x01) != 0) {
22911da177e4SLinus Torvalds 			tmport -= 0x06;
22921da177e4SLinus Torvalds 			mbuf[k++] = inb(tmport);
22931da177e4SLinus Torvalds 			tmport += 0x06;
22941da177e4SLinus Torvalds 			goto widep_in1;
22951da177e4SLinus Torvalds 		}
22961da177e4SLinus Torvalds 		if ((j & 0x80) == 0x00) {
22971da177e4SLinus Torvalds 			goto widep_in1;
22981da177e4SLinus Torvalds 		}
22991da177e4SLinus Torvalds 		tmport -= 0x08;
23001da177e4SLinus Torvalds 		j = inb(tmport) & 0x0f;
23011da177e4SLinus Torvalds 		if (j == 0x0f) {
23021da177e4SLinus Torvalds 			goto widep_in;
23031da177e4SLinus Torvalds 		}
23041da177e4SLinus Torvalds 		if (j == 0x0a) {
23051da177e4SLinus Torvalds 			goto widep_cmd;
23061da177e4SLinus Torvalds 		}
23071da177e4SLinus Torvalds 		if (j == 0x0e) {
23081da177e4SLinus Torvalds 			goto widep_out;
23091da177e4SLinus Torvalds 		}
23101da177e4SLinus Torvalds 		continue;
23111da177e4SLinus Torvalds widep_cmd:
23121da177e4SLinus Torvalds 		tmport = wkport + 0x50;
23131da177e4SLinus Torvalds 		outb(0x30, tmport);
23141da177e4SLinus Torvalds 		tmport = wkport + 0x54;
23151da177e4SLinus Torvalds 		outb(0x00, tmport);
23161da177e4SLinus Torvalds 		tmport += 0x04;
23171da177e4SLinus Torvalds 		outb(0x08, tmport);
23181da177e4SLinus Torvalds 		tmport += 0x07;
23191da177e4SLinus Torvalds 
23201da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
23211da177e4SLinus Torvalds 			cpu_relax();
23221da177e4SLinus Torvalds 
23231da177e4SLinus Torvalds 		tmport -= 0x08;
23241da177e4SLinus Torvalds 		j = inb(tmport);
23251da177e4SLinus Torvalds 		if (j != 0x16) {
23261da177e4SLinus Torvalds 			if (j == 0x4e) {
23271da177e4SLinus Torvalds 				goto widep_out;
23281da177e4SLinus Torvalds 			}
23291da177e4SLinus Torvalds 			continue;
23301da177e4SLinus Torvalds 		}
23311da177e4SLinus Torvalds 		if (mbuf[0] != 0x01) {
23321da177e4SLinus Torvalds 			goto not_wide;
23331da177e4SLinus Torvalds 		}
23341da177e4SLinus Torvalds 		if (mbuf[1] != 0x02) {
23351da177e4SLinus Torvalds 			goto not_wide;
23361da177e4SLinus Torvalds 		}
23371da177e4SLinus Torvalds 		if (mbuf[2] != 0x03) {
23381da177e4SLinus Torvalds 			goto not_wide;
23391da177e4SLinus Torvalds 		}
23401da177e4SLinus Torvalds 		if (mbuf[3] != 0x01) {
23411da177e4SLinus Torvalds 			goto not_wide;
23421da177e4SLinus Torvalds 		}
23431da177e4SLinus Torvalds 		m = 1;
23441da177e4SLinus Torvalds 		m = m << i;
23451da177e4SLinus Torvalds 		dev->wide_id[0] |= m;
23461da177e4SLinus Torvalds not_wide:
23471da177e4SLinus Torvalds 		if ((dev->id[0][i].devtype == 0x00) || (dev->id[0][i].devtype == 0x07) || ((dev->id[0][i].devtype == 0x05) && ((n & 0x10) != 0))) {
23481da177e4SLinus Torvalds 			m = 1;
23491da177e4SLinus Torvalds 			m = m << i;
23501da177e4SLinus Torvalds 			if ((dev->async[0] & m) != 0) {
23511da177e4SLinus Torvalds 				goto set_sync;
23521da177e4SLinus Torvalds 			}
23531da177e4SLinus Torvalds 		}
23541da177e4SLinus Torvalds 		continue;
23551da177e4SLinus Torvalds set_sync:
23561da177e4SLinus Torvalds 		if (dev->sp[0][i] == 0x02) {
23571da177e4SLinus Torvalds 			synu[4] = 0x0c;
23581da177e4SLinus Torvalds 			synuw[4] = 0x0c;
23591da177e4SLinus Torvalds 		} else {
23601da177e4SLinus Torvalds 			if (dev->sp[0][i] >= 0x03) {
23611da177e4SLinus Torvalds 				synu[4] = 0x0a;
23621da177e4SLinus Torvalds 				synuw[4] = 0x0a;
23631da177e4SLinus Torvalds 			}
23641da177e4SLinus Torvalds 		}
23651da177e4SLinus Torvalds 		tmport = wkport + 0x5b;
23661da177e4SLinus Torvalds 		j = 0;
23671da177e4SLinus Torvalds 		if ((m & dev->wide_id[0]) != 0) {
23681da177e4SLinus Torvalds 			j |= 0x01;
23691da177e4SLinus Torvalds 		}
23701da177e4SLinus Torvalds 		outb(j, tmport);
23711da177e4SLinus Torvalds 		tmport = wkport + 0x43;
23721da177e4SLinus Torvalds 		outb(satn[0], tmport++);
23731da177e4SLinus Torvalds 		outb(satn[1], tmport++);
23741da177e4SLinus Torvalds 		outb(satn[2], tmport++);
23751da177e4SLinus Torvalds 		outb(satn[3], tmport++);
23761da177e4SLinus Torvalds 		outb(satn[4], tmport++);
23771da177e4SLinus Torvalds 		outb(satn[5], tmport++);
23781da177e4SLinus Torvalds 		tmport += 0x06;
23791da177e4SLinus Torvalds 		outb(0, tmport);
23801da177e4SLinus Torvalds 		tmport += 0x02;
23811da177e4SLinus Torvalds 		outb(dev->id[0][i].devsp, tmport++);
23821da177e4SLinus Torvalds 		outb(0, tmport++);
23831da177e4SLinus Torvalds 		outb(satn[6], tmport++);
23841da177e4SLinus Torvalds 		outb(satn[7], tmport++);
23851da177e4SLinus Torvalds 		tmport += 0x03;
23861da177e4SLinus Torvalds 		outb(satn[8], tmport);
23871da177e4SLinus Torvalds 		tmport += 0x07;
23881da177e4SLinus Torvalds 
23891da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
23901da177e4SLinus Torvalds 			cpu_relax();
23911da177e4SLinus Torvalds 
23921da177e4SLinus Torvalds 		tmport -= 0x08;
23931da177e4SLinus Torvalds 		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
23941da177e4SLinus Torvalds 			continue;
23951da177e4SLinus Torvalds 		}
23961da177e4SLinus Torvalds 		while (inb(tmport) != 0x8e)
23971da177e4SLinus Torvalds 			cpu_relax();
23981da177e4SLinus Torvalds 
23991da177e4SLinus Torvalds try_sync:
24001da177e4SLinus Torvalds 		j = 0;
24011da177e4SLinus Torvalds 		tmport = wkport + 0x54;
24021da177e4SLinus Torvalds 		outb(0x06, tmport);
24031da177e4SLinus Torvalds 		tmport += 0x04;
24041da177e4SLinus Torvalds 		outb(0x20, tmport);
24051da177e4SLinus Torvalds 		tmport += 0x07;
24061da177e4SLinus Torvalds 
24071da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0) {
24081da177e4SLinus Torvalds 			if ((inb(tmport) & 0x01) != 0) {
24091da177e4SLinus Torvalds 				tmport -= 0x06;
24101da177e4SLinus Torvalds 				if ((m & dev->wide_id[0]) != 0) {
24111da177e4SLinus Torvalds 					if ((m & dev->ultra_map[0]) != 0) {
24121da177e4SLinus Torvalds 						outb(synuw[j++], tmport);
24131da177e4SLinus Torvalds 					} else {
24141da177e4SLinus Torvalds 						outb(synw[j++], tmport);
24151da177e4SLinus Torvalds 					}
24161da177e4SLinus Torvalds 				} else {
24171da177e4SLinus Torvalds 					if ((m & dev->ultra_map[0]) != 0) {
24181da177e4SLinus Torvalds 						outb(synu[j++], tmport);
24191da177e4SLinus Torvalds 					} else {
24201da177e4SLinus Torvalds 						outb(synn[j++], tmport);
24211da177e4SLinus Torvalds 					}
24221da177e4SLinus Torvalds 				}
24231da177e4SLinus Torvalds 				tmport += 0x06;
24241da177e4SLinus Torvalds 			}
24251da177e4SLinus Torvalds 		}
24261da177e4SLinus Torvalds 		tmport -= 0x08;
24271da177e4SLinus Torvalds 
24281da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
24291da177e4SLinus Torvalds 			cpu_relax();
24301da177e4SLinus Torvalds 
24311da177e4SLinus Torvalds 		j = inb(tmport) & 0x0f;
24321da177e4SLinus Torvalds 		if (j == 0x0f) {
24331da177e4SLinus Torvalds 			goto phase_ins;
24341da177e4SLinus Torvalds 		}
24351da177e4SLinus Torvalds 		if (j == 0x0a) {
24361da177e4SLinus Torvalds 			goto phase_cmds;
24371da177e4SLinus Torvalds 		}
24381da177e4SLinus Torvalds 		if (j == 0x0e) {
24391da177e4SLinus Torvalds 			goto try_sync;
24401da177e4SLinus Torvalds 		}
24411da177e4SLinus Torvalds 		continue;
24421da177e4SLinus Torvalds phase_outs:
24431da177e4SLinus Torvalds 		tmport = wkport + 0x58;
24441da177e4SLinus Torvalds 		outb(0x20, tmport);
24451da177e4SLinus Torvalds 		tmport += 0x07;
24461da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00) {
24471da177e4SLinus Torvalds 			if ((inb(tmport) & 0x01) != 0x00) {
24481da177e4SLinus Torvalds 				tmport -= 0x06;
24491da177e4SLinus Torvalds 				outb(0x00, tmport);
24501da177e4SLinus Torvalds 				tmport += 0x06;
24511da177e4SLinus Torvalds 			}
24521da177e4SLinus Torvalds 		}
24531da177e4SLinus Torvalds 		tmport -= 0x08;
24541da177e4SLinus Torvalds 		j = inb(tmport);
24551da177e4SLinus Torvalds 		if (j == 0x85) {
24561da177e4SLinus Torvalds 			goto tar_dcons;
24571da177e4SLinus Torvalds 		}
24581da177e4SLinus Torvalds 		j &= 0x0f;
24591da177e4SLinus Torvalds 		if (j == 0x0f) {
24601da177e4SLinus Torvalds 			goto phase_ins;
24611da177e4SLinus Torvalds 		}
24621da177e4SLinus Torvalds 		if (j == 0x0a) {
24631da177e4SLinus Torvalds 			goto phase_cmds;
24641da177e4SLinus Torvalds 		}
24651da177e4SLinus Torvalds 		if (j == 0x0e) {
24661da177e4SLinus Torvalds 			goto phase_outs;
24671da177e4SLinus Torvalds 		}
24681da177e4SLinus Torvalds 		continue;
24691da177e4SLinus Torvalds phase_ins:
24701da177e4SLinus Torvalds 		tmport = wkport + 0x54;
24711da177e4SLinus Torvalds 		outb(0x06, tmport);
24721da177e4SLinus Torvalds 		tmport += 0x04;
24731da177e4SLinus Torvalds 		outb(0x20, tmport);
24741da177e4SLinus Torvalds 		tmport += 0x07;
24751da177e4SLinus Torvalds 		k = 0;
24761da177e4SLinus Torvalds phase_ins1:
24771da177e4SLinus Torvalds 		j = inb(tmport);
24781da177e4SLinus Torvalds 		if ((j & 0x01) != 0x00) {
24791da177e4SLinus Torvalds 			tmport -= 0x06;
24801da177e4SLinus Torvalds 			mbuf[k++] = inb(tmport);
24811da177e4SLinus Torvalds 			tmport += 0x06;
24821da177e4SLinus Torvalds 			goto phase_ins1;
24831da177e4SLinus Torvalds 		}
24841da177e4SLinus Torvalds 		if ((j & 0x80) == 0x00) {
24851da177e4SLinus Torvalds 			goto phase_ins1;
24861da177e4SLinus Torvalds 		}
24871da177e4SLinus Torvalds 		tmport -= 0x08;
24881da177e4SLinus Torvalds 
24891da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
24901da177e4SLinus Torvalds 			cpu_relax();
24911da177e4SLinus Torvalds 
24921da177e4SLinus Torvalds 		j = inb(tmport);
24931da177e4SLinus Torvalds 		if (j == 0x85) {
24941da177e4SLinus Torvalds 			goto tar_dcons;
24951da177e4SLinus Torvalds 		}
24961da177e4SLinus Torvalds 		j &= 0x0f;
24971da177e4SLinus Torvalds 		if (j == 0x0f) {
24981da177e4SLinus Torvalds 			goto phase_ins;
24991da177e4SLinus Torvalds 		}
25001da177e4SLinus Torvalds 		if (j == 0x0a) {
25011da177e4SLinus Torvalds 			goto phase_cmds;
25021da177e4SLinus Torvalds 		}
25031da177e4SLinus Torvalds 		if (j == 0x0e) {
25041da177e4SLinus Torvalds 			goto phase_outs;
25051da177e4SLinus Torvalds 		}
25061da177e4SLinus Torvalds 		continue;
25071da177e4SLinus Torvalds phase_cmds:
25081da177e4SLinus Torvalds 		tmport = wkport + 0x50;
25091da177e4SLinus Torvalds 		outb(0x30, tmport);
25101da177e4SLinus Torvalds tar_dcons:
25111da177e4SLinus Torvalds 		tmport = wkport + 0x54;
25121da177e4SLinus Torvalds 		outb(0x00, tmport);
25131da177e4SLinus Torvalds 		tmport += 0x04;
25141da177e4SLinus Torvalds 		outb(0x08, tmport);
25151da177e4SLinus Torvalds 		tmport += 0x07;
25161da177e4SLinus Torvalds 
25171da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
25181da177e4SLinus Torvalds 			cpu_relax();
25191da177e4SLinus Torvalds 
25201da177e4SLinus Torvalds 		tmport -= 0x08;
25211da177e4SLinus Torvalds 		j = inb(tmport);
25221da177e4SLinus Torvalds 		if (j != 0x16) {
25231da177e4SLinus Torvalds 			continue;
25241da177e4SLinus Torvalds 		}
25251da177e4SLinus Torvalds 		if (mbuf[0] != 0x01) {
25261da177e4SLinus Torvalds 			continue;
25271da177e4SLinus Torvalds 		}
25281da177e4SLinus Torvalds 		if (mbuf[1] != 0x03) {
25291da177e4SLinus Torvalds 			continue;
25301da177e4SLinus Torvalds 		}
25311da177e4SLinus Torvalds 		if (mbuf[4] == 0x00) {
25321da177e4SLinus Torvalds 			continue;
25331da177e4SLinus Torvalds 		}
25341da177e4SLinus Torvalds 		if (mbuf[3] > 0x64) {
25351da177e4SLinus Torvalds 			continue;
25361da177e4SLinus Torvalds 		}
25371da177e4SLinus Torvalds 		if (mbuf[4] > 0x0e) {
25381da177e4SLinus Torvalds 			mbuf[4] = 0x0e;
25391da177e4SLinus Torvalds 		}
25401da177e4SLinus Torvalds 		dev->id[0][i].devsp = mbuf[4];
25411da177e4SLinus Torvalds 		if (mbuf[3] < 0x0c) {
25421da177e4SLinus Torvalds 			j = 0xb0;
25431da177e4SLinus Torvalds 			goto set_syn_ok;
25441da177e4SLinus Torvalds 		}
25451da177e4SLinus Torvalds 		if ((mbuf[3] < 0x0d) && (rmb == 0)) {
25461da177e4SLinus Torvalds 			j = 0xa0;
25471da177e4SLinus Torvalds 			goto set_syn_ok;
25481da177e4SLinus Torvalds 		}
25491da177e4SLinus Torvalds 		if (mbuf[3] < 0x1a) {
25501da177e4SLinus Torvalds 			j = 0x20;
25511da177e4SLinus Torvalds 			goto set_syn_ok;
25521da177e4SLinus Torvalds 		}
25531da177e4SLinus Torvalds 		if (mbuf[3] < 0x33) {
25541da177e4SLinus Torvalds 			j = 0x40;
25551da177e4SLinus Torvalds 			goto set_syn_ok;
25561da177e4SLinus Torvalds 		}
25571da177e4SLinus Torvalds 		if (mbuf[3] < 0x4c) {
25581da177e4SLinus Torvalds 			j = 0x50;
25591da177e4SLinus Torvalds 			goto set_syn_ok;
25601da177e4SLinus Torvalds 		}
25611da177e4SLinus Torvalds 		j = 0x60;
25621da177e4SLinus Torvalds set_syn_ok:
25631da177e4SLinus Torvalds 		dev->id[0][i].devsp = (dev->id[0][i].devsp & 0x0f) | j;
25641da177e4SLinus Torvalds 	}
25651da177e4SLinus Torvalds }
25661da177e4SLinus Torvalds 
25671da177e4SLinus Torvalds static void atp870u_free_tables(struct Scsi_Host *host)
25681da177e4SLinus Torvalds {
25691da177e4SLinus Torvalds 	struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata;
25701da177e4SLinus Torvalds 	int j, k;
25711da177e4SLinus Torvalds 	for (j=0; j < 2; j++) {
25721da177e4SLinus Torvalds 		for (k = 0; k < 16; k++) {
25731da177e4SLinus Torvalds 			if (!atp_dev->id[j][k].prd_table)
25741da177e4SLinus Torvalds 				continue;
25751da177e4SLinus Torvalds 			pci_free_consistent(atp_dev->pdev, 1024, atp_dev->id[j][k].prd_table, atp_dev->id[j][k].prdaddr);
25761da177e4SLinus Torvalds 			atp_dev->id[j][k].prd_table = NULL;
25771da177e4SLinus Torvalds 		}
25781da177e4SLinus Torvalds 	}
25791da177e4SLinus Torvalds }
25801da177e4SLinus Torvalds 
25811da177e4SLinus Torvalds static int atp870u_init_tables(struct Scsi_Host *host)
25821da177e4SLinus Torvalds {
25831da177e4SLinus Torvalds 	struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata;
25841da177e4SLinus Torvalds 	int c,k;
25851da177e4SLinus Torvalds 	for(c=0;c < 2;c++) {
25861da177e4SLinus Torvalds 	   	for(k=0;k<16;k++) {
25871da177e4SLinus Torvalds 	   			atp_dev->id[c][k].prd_table = pci_alloc_consistent(atp_dev->pdev, 1024, &(atp_dev->id[c][k].prdaddr));
25881da177e4SLinus Torvalds 	   			if (!atp_dev->id[c][k].prd_table) {
25891da177e4SLinus Torvalds 	   				printk("atp870u_init_tables fail\n");
25901da177e4SLinus Torvalds 				atp870u_free_tables(host);
25911da177e4SLinus Torvalds 				return -ENOMEM;
25921da177e4SLinus Torvalds 			}
25931da177e4SLinus Torvalds 			atp_dev->id[c][k].devsp=0x20;
25941da177e4SLinus Torvalds 			atp_dev->id[c][k].devtype = 0x7f;
25951da177e4SLinus Torvalds 			atp_dev->id[c][k].curr_req = NULL;
25961da177e4SLinus Torvalds 	   	}
25971da177e4SLinus Torvalds 
25981da177e4SLinus Torvalds 	   	atp_dev->active_id[c] = 0;
25991da177e4SLinus Torvalds 	   	atp_dev->wide_id[c] = 0;
26001da177e4SLinus Torvalds 	   	atp_dev->host_id[c] = 0x07;
26011da177e4SLinus Torvalds 	   	atp_dev->quhd[c] = 0;
26021da177e4SLinus Torvalds 	   	atp_dev->quend[c] = 0;
26031da177e4SLinus Torvalds 	   	atp_dev->last_cmd[c] = 0xff;
26041da177e4SLinus Torvalds 	   	atp_dev->in_snd[c] = 0;
26051da177e4SLinus Torvalds 	   	atp_dev->in_int[c] = 0;
26061da177e4SLinus Torvalds 
26071da177e4SLinus Torvalds 	   	for (k = 0; k < qcnt; k++) {
26081da177e4SLinus Torvalds 	   		  atp_dev->quereq[c][k] = NULL;
26091da177e4SLinus Torvalds 	   	}
26101da177e4SLinus Torvalds 	   	for (k = 0; k < 16; k++) {
26111da177e4SLinus Torvalds 			   atp_dev->id[c][k].curr_req = NULL;
26121da177e4SLinus Torvalds 			   atp_dev->sp[c][k] = 0x04;
26131da177e4SLinus Torvalds 	   	}
26141da177e4SLinus Torvalds 	}
26151da177e4SLinus Torvalds 	return 0;
26161da177e4SLinus Torvalds }
26171da177e4SLinus Torvalds 
26181da177e4SLinus Torvalds /* return non-zero on detection */
26191da177e4SLinus Torvalds static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
26201da177e4SLinus Torvalds {
26211da177e4SLinus Torvalds 	unsigned char k, m, c;
26221da177e4SLinus Torvalds 	unsigned long flags;
26231da177e4SLinus Torvalds 	unsigned int base_io, tmport, error,n;
26241da177e4SLinus Torvalds 	unsigned char host_id;
26251da177e4SLinus Torvalds 	struct Scsi_Host *shpnt = NULL;
26261da177e4SLinus Torvalds 	struct atp_unit atp_dev, *p;
26271da177e4SLinus Torvalds 	unsigned char setupdata[2][16];
26281da177e4SLinus Torvalds 	int count = 0;
26291da177e4SLinus Torvalds 
26301da177e4SLinus Torvalds 	if (pci_enable_device(pdev))
26311da177e4SLinus Torvalds 		return -EIO;
26321da177e4SLinus Torvalds 
26331da177e4SLinus Torvalds         if (!pci_set_dma_mask(pdev, 0xFFFFFFFFUL)) {
26341da177e4SLinus Torvalds                 printk(KERN_INFO "atp870u: use 32bit DMA mask.\n");
26351da177e4SLinus Torvalds         } else {
26361da177e4SLinus Torvalds                 printk(KERN_ERR "atp870u: DMA mask required but not available.\n");
26371da177e4SLinus Torvalds                 return -EIO;
26381da177e4SLinus Torvalds         }
26391da177e4SLinus Torvalds 
26401da177e4SLinus Torvalds 	memset(&atp_dev, 0, sizeof atp_dev);
26411da177e4SLinus Torvalds 	/*
26421da177e4SLinus Torvalds 	 * It's probably easier to weed out some revisions like
26431da177e4SLinus Torvalds 	 * this than via the PCI device table
26441da177e4SLinus Torvalds 	 */
26451da177e4SLinus Torvalds 	if (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610) {
26461da177e4SLinus Torvalds 		error = pci_read_config_byte(pdev, PCI_CLASS_REVISION, &atp_dev.chip_ver);
26471da177e4SLinus Torvalds 		if (atp_dev.chip_ver < 2)
26481da177e4SLinus Torvalds 			return -EIO;
26491da177e4SLinus Torvalds 	}
26501da177e4SLinus Torvalds 
26511da177e4SLinus Torvalds 	switch (ent->device) {
26521da177e4SLinus Torvalds 	case PCI_DEVICE_ID_ARTOP_AEC7612UW:
26531da177e4SLinus Torvalds 	case PCI_DEVICE_ID_ARTOP_AEC7612SUW:
26541da177e4SLinus Torvalds 	case ATP880_DEVID1:
26551da177e4SLinus Torvalds 	case ATP880_DEVID2:
26561da177e4SLinus Torvalds 	case ATP885_DEVID:
26571da177e4SLinus Torvalds 		atp_dev.chip_ver = 0x04;
26581da177e4SLinus Torvalds 	default:
26591da177e4SLinus Torvalds 		break;
26601da177e4SLinus Torvalds 	}
26611da177e4SLinus Torvalds 	base_io = pci_resource_start(pdev, 0);
26621da177e4SLinus Torvalds 	base_io &= 0xfffffff8;
26631da177e4SLinus Torvalds 
26641da177e4SLinus Torvalds 	if ((ent->device == ATP880_DEVID1)||(ent->device == ATP880_DEVID2)) {
26651da177e4SLinus Torvalds 		error = pci_read_config_byte(pdev, PCI_CLASS_REVISION, &atp_dev.chip_ver);
26661da177e4SLinus Torvalds 		pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80);//JCC082803
26671da177e4SLinus Torvalds 
26681da177e4SLinus Torvalds 		host_id = inb(base_io + 0x39);
26691da177e4SLinus Torvalds 		host_id >>= 0x04;
26701da177e4SLinus Torvalds 
26711da177e4SLinus Torvalds 		printk(KERN_INFO "   ACARD AEC-67160 PCI Ultra3 LVD Host Adapter: %d"
26721da177e4SLinus Torvalds 			"    IO:%x, IRQ:%d.\n", count, base_io, pdev->irq);
26731da177e4SLinus Torvalds 		atp_dev.ioport[0] = base_io + 0x40;
26741da177e4SLinus Torvalds 		atp_dev.pciport[0] = base_io + 0x28;
26751da177e4SLinus Torvalds 		atp_dev.dev_id = ent->device;
26761da177e4SLinus Torvalds 		atp_dev.host_id[0] = host_id;
26771da177e4SLinus Torvalds 
26781da177e4SLinus Torvalds 		tmport = base_io + 0x22;
26791da177e4SLinus Torvalds 		atp_dev.scam_on = inb(tmport);
26801da177e4SLinus Torvalds 		tmport += 0x13;
26811da177e4SLinus Torvalds 		atp_dev.global_map[0] = inb(tmport);
26821da177e4SLinus Torvalds 		tmport += 0x07;
26831da177e4SLinus Torvalds 		atp_dev.ultra_map[0] = inw(tmport);
26841da177e4SLinus Torvalds 
26851da177e4SLinus Torvalds 		n = 0x3f09;
26861da177e4SLinus Torvalds next_fblk_880:
26871da177e4SLinus Torvalds 		if (n >= 0x4000)
26881da177e4SLinus Torvalds 			goto flash_ok_880;
26891da177e4SLinus Torvalds 
26901da177e4SLinus Torvalds 		m = 0;
26911da177e4SLinus Torvalds 		outw(n, base_io + 0x34);
26921da177e4SLinus Torvalds 		n += 0x0002;
26931da177e4SLinus Torvalds 		if (inb(base_io + 0x30) == 0xff)
26941da177e4SLinus Torvalds 			goto flash_ok_880;
26951da177e4SLinus Torvalds 
26961da177e4SLinus Torvalds 		atp_dev.sp[0][m++] = inb(base_io + 0x30);
26971da177e4SLinus Torvalds 		atp_dev.sp[0][m++] = inb(base_io + 0x31);
26981da177e4SLinus Torvalds 		atp_dev.sp[0][m++] = inb(base_io + 0x32);
26991da177e4SLinus Torvalds 		atp_dev.sp[0][m++] = inb(base_io + 0x33);
27001da177e4SLinus Torvalds 		outw(n, base_io + 0x34);
27011da177e4SLinus Torvalds 		n += 0x0002;
27021da177e4SLinus Torvalds 		atp_dev.sp[0][m++] = inb(base_io + 0x30);
27031da177e4SLinus Torvalds 		atp_dev.sp[0][m++] = inb(base_io + 0x31);
27041da177e4SLinus Torvalds 		atp_dev.sp[0][m++] = inb(base_io + 0x32);
27051da177e4SLinus Torvalds 		atp_dev.sp[0][m++] = inb(base_io + 0x33);
27061da177e4SLinus Torvalds 		outw(n, base_io + 0x34);
27071da177e4SLinus Torvalds 		n += 0x0002;
27081da177e4SLinus Torvalds 		atp_dev.sp[0][m++] = inb(base_io + 0x30);
27091da177e4SLinus Torvalds 		atp_dev.sp[0][m++] = inb(base_io + 0x31);
27101da177e4SLinus Torvalds 		atp_dev.sp[0][m++] = inb(base_io + 0x32);
27111da177e4SLinus Torvalds 		atp_dev.sp[0][m++] = inb(base_io + 0x33);
27121da177e4SLinus Torvalds 		outw(n, base_io + 0x34);
27131da177e4SLinus Torvalds 		n += 0x0002;
27141da177e4SLinus Torvalds 		atp_dev.sp[0][m++] = inb(base_io + 0x30);
27151da177e4SLinus Torvalds 		atp_dev.sp[0][m++] = inb(base_io + 0x31);
27161da177e4SLinus Torvalds 		atp_dev.sp[0][m++] = inb(base_io + 0x32);
27171da177e4SLinus Torvalds 		atp_dev.sp[0][m++] = inb(base_io + 0x33);
27181da177e4SLinus Torvalds 		n += 0x0018;
27191da177e4SLinus Torvalds 		goto next_fblk_880;
27201da177e4SLinus Torvalds flash_ok_880:
27211da177e4SLinus Torvalds 		outw(0, base_io + 0x34);
27221da177e4SLinus Torvalds 		atp_dev.ultra_map[0] = 0;
27231da177e4SLinus Torvalds 		atp_dev.async[0] = 0;
27241da177e4SLinus Torvalds 		for (k = 0; k < 16; k++) {
27251da177e4SLinus Torvalds 			n = 1;
27261da177e4SLinus Torvalds 			n = n << k;
27271da177e4SLinus Torvalds 			if (atp_dev.sp[0][k] > 1) {
27281da177e4SLinus Torvalds 				atp_dev.ultra_map[0] |= n;
27291da177e4SLinus Torvalds 			} else {
27301da177e4SLinus Torvalds 				if (atp_dev.sp[0][k] == 0)
27311da177e4SLinus Torvalds 					atp_dev.async[0] |= n;
27321da177e4SLinus Torvalds  			}
27331da177e4SLinus Torvalds 	 	}
27341da177e4SLinus Torvalds 		atp_dev.async[0] = ~(atp_dev.async[0]);
27351da177e4SLinus Torvalds 		outb(atp_dev.global_map[0], base_io + 0x35);
27361da177e4SLinus Torvalds 
27371da177e4SLinus Torvalds 		shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
27381da177e4SLinus Torvalds 		if (!shpnt)
27391da177e4SLinus Torvalds 			return -ENOMEM;
27401da177e4SLinus Torvalds 
27411da177e4SLinus Torvalds 		p = (struct atp_unit *)&shpnt->hostdata;
27421da177e4SLinus Torvalds 
27431da177e4SLinus Torvalds 		atp_dev.host = shpnt;
27441da177e4SLinus Torvalds 		atp_dev.pdev = pdev;
27451da177e4SLinus Torvalds 		pci_set_drvdata(pdev, p);
27461da177e4SLinus Torvalds 		memcpy(p, &atp_dev, sizeof atp_dev);
27471da177e4SLinus Torvalds 		if (atp870u_init_tables(shpnt) < 0) {
27481da177e4SLinus Torvalds 			printk(KERN_ERR "Unable to allocate tables for Acard controller\n");
27491da177e4SLinus Torvalds 			goto unregister;
27501da177e4SLinus Torvalds 		}
27511da177e4SLinus Torvalds 
27521da177e4SLinus Torvalds 		if (request_irq(pdev->irq, atp870u_intr_handle, SA_SHIRQ, "atp880i", shpnt)) {
27531da177e4SLinus Torvalds  			printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", pdev->irq);
27541da177e4SLinus Torvalds 			goto free_tables;
27551da177e4SLinus Torvalds 		}
27561da177e4SLinus Torvalds 
27571da177e4SLinus Torvalds 		spin_lock_irqsave(shpnt->host_lock, flags);
27581da177e4SLinus Torvalds 		tmport = base_io + 0x38;
27591da177e4SLinus Torvalds 		k = inb(tmport) & 0x80;
27601da177e4SLinus Torvalds 		outb(k, tmport);
27611da177e4SLinus Torvalds 		tmport += 0x03;
27621da177e4SLinus Torvalds 		outb(0x20, tmport);
27631da177e4SLinus Torvalds 		mdelay(32);
27641da177e4SLinus Torvalds 		outb(0, tmport);
27651da177e4SLinus Torvalds 		mdelay(32);
27661da177e4SLinus Torvalds 		tmport = base_io + 0x5b;
27671da177e4SLinus Torvalds 		inb(tmport);
27681da177e4SLinus Torvalds 		tmport -= 0x04;
27691da177e4SLinus Torvalds 		inb(tmport);
27701da177e4SLinus Torvalds 		tmport = base_io + 0x40;
27711da177e4SLinus Torvalds 		outb((host_id | 0x08), tmport);
27721da177e4SLinus Torvalds 		tmport += 0x18;
27731da177e4SLinus Torvalds 		outb(0, tmport);
27741da177e4SLinus Torvalds 		tmport += 0x07;
27751da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0)
27761da177e4SLinus Torvalds 			mdelay(1);
27771da177e4SLinus Torvalds 		tmport -= 0x08;
27781da177e4SLinus Torvalds 		inb(tmport);
27791da177e4SLinus Torvalds 		tmport = base_io + 0x41;
27801da177e4SLinus Torvalds 		outb(8, tmport++);
27811da177e4SLinus Torvalds 		outb(0x7f, tmport);
27821da177e4SLinus Torvalds 		tmport = base_io + 0x51;
27831da177e4SLinus Torvalds 		outb(0x20, tmport);
27841da177e4SLinus Torvalds 
27851da177e4SLinus Torvalds 		tscam(shpnt);
27861da177e4SLinus Torvalds 		is880(p, base_io);
27871da177e4SLinus Torvalds 		tmport = base_io + 0x38;
27881da177e4SLinus Torvalds 		outb(0xb0, tmport);
27891da177e4SLinus Torvalds 		shpnt->max_id = 16;
27901da177e4SLinus Torvalds 		shpnt->this_id = host_id;
27911da177e4SLinus Torvalds 		shpnt->unique_id = base_io;
27921da177e4SLinus Torvalds 		shpnt->io_port = base_io;
27931da177e4SLinus Torvalds 		shpnt->n_io_port = 0x60;	/* Number of bytes of I/O space used */
27941da177e4SLinus Torvalds 		shpnt->irq = pdev->irq;
27951da177e4SLinus Torvalds 	} else if (ent->device == ATP885_DEVID) {
27961da177e4SLinus Torvalds 			printk(KERN_INFO "   ACARD AEC-67162 PCI Ultra3 LVD Host Adapter:  IO:%x, IRQ:%d.\n"
27971da177e4SLinus Torvalds 			       , base_io, pdev->irq);
27981da177e4SLinus Torvalds 
27991da177e4SLinus Torvalds 		atp_dev.pdev = pdev;
28001da177e4SLinus Torvalds 		atp_dev.dev_id  = ent->device;
28011da177e4SLinus Torvalds 		atp_dev.baseport = base_io;
28021da177e4SLinus Torvalds 		atp_dev.ioport[0] = base_io + 0x80;
28031da177e4SLinus Torvalds 		atp_dev.ioport[1] = base_io + 0xc0;
28041da177e4SLinus Torvalds 		atp_dev.pciport[0] = base_io + 0x40;
28051da177e4SLinus Torvalds 		atp_dev.pciport[1] = base_io + 0x50;
28061da177e4SLinus Torvalds 
28071da177e4SLinus Torvalds 		shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
28081da177e4SLinus Torvalds 		if (!shpnt)
28091da177e4SLinus Torvalds 			return -ENOMEM;
28101da177e4SLinus Torvalds 
28111da177e4SLinus Torvalds 		p = (struct atp_unit *)&shpnt->hostdata;
28121da177e4SLinus Torvalds 
28131da177e4SLinus Torvalds 		atp_dev.host = shpnt;
28141da177e4SLinus Torvalds 		atp_dev.pdev = pdev;
28151da177e4SLinus Torvalds 		pci_set_drvdata(pdev, p);
28161da177e4SLinus Torvalds 		memcpy(p, &atp_dev, sizeof(struct atp_unit));
28171da177e4SLinus Torvalds 		if (atp870u_init_tables(shpnt) < 0)
28181da177e4SLinus Torvalds 			goto unregister;
28191da177e4SLinus Torvalds 
28201da177e4SLinus Torvalds #ifdef ED_DBGP
28211da177e4SLinus Torvalds 	printk("request_irq() shpnt %p hostdata %p\n", shpnt, p);
28221da177e4SLinus Torvalds #endif
28231da177e4SLinus Torvalds 		if (request_irq(pdev->irq, atp870u_intr_handle, SA_SHIRQ, "atp870u", shpnt)) {
28241da177e4SLinus Torvalds 				printk(KERN_ERR "Unable to allocate IRQ for Acard controller.\n");
28251da177e4SLinus Torvalds 			goto free_tables;
28261da177e4SLinus Torvalds 		}
28271da177e4SLinus Torvalds 
28281da177e4SLinus Torvalds 		spin_lock_irqsave(shpnt->host_lock, flags);
28291da177e4SLinus Torvalds 
28301da177e4SLinus Torvalds 		c=inb(base_io + 0x29);
28311da177e4SLinus Torvalds 		outb((c | 0x04),base_io + 0x29);
28321da177e4SLinus Torvalds 
28331da177e4SLinus Torvalds 		n=0x1f80;
28341da177e4SLinus Torvalds next_fblk_885:
28351da177e4SLinus Torvalds 		if (n >= 0x2000) {
28361da177e4SLinus Torvalds 		   goto flash_ok_885;
28371da177e4SLinus Torvalds 		}
28381da177e4SLinus Torvalds 		outw(n,base_io + 0x3c);
28391da177e4SLinus Torvalds 		if (inl(base_io + 0x38) == 0xffffffff) {
28401da177e4SLinus Torvalds 		   goto flash_ok_885;
28411da177e4SLinus Torvalds 		}
28421da177e4SLinus Torvalds 		for (m=0; m < 2; m++) {
28431da177e4SLinus Torvalds 		    p->global_map[m]= 0;
28441da177e4SLinus Torvalds 		    for (k=0; k < 4; k++) {
28451da177e4SLinus Torvalds 			outw(n++,base_io + 0x3c);
28461da177e4SLinus Torvalds 			((unsigned long *)&setupdata[m][0])[k]=inl(base_io + 0x38);
28471da177e4SLinus Torvalds 		    }
28481da177e4SLinus Torvalds 		    for (k=0; k < 4; k++) {
28491da177e4SLinus Torvalds 			outw(n++,base_io + 0x3c);
28501da177e4SLinus Torvalds 			((unsigned long *)&p->sp[m][0])[k]=inl(base_io + 0x38);
28511da177e4SLinus Torvalds 		    }
28521da177e4SLinus Torvalds 		    n += 8;
28531da177e4SLinus Torvalds 		}
28541da177e4SLinus Torvalds 		goto next_fblk_885;
28551da177e4SLinus Torvalds flash_ok_885:
28561da177e4SLinus Torvalds #ifdef ED_DBGP
28571da177e4SLinus Torvalds 		printk( "Flash Read OK\n");
28581da177e4SLinus Torvalds #endif
28591da177e4SLinus Torvalds 		c=inb(base_io + 0x29);
28601da177e4SLinus Torvalds 		outb((c & 0xfb),base_io + 0x29);
28611da177e4SLinus Torvalds 		for (c=0;c < 2;c++) {
28621da177e4SLinus Torvalds 		    p->ultra_map[c]=0;
28631da177e4SLinus Torvalds 		    p->async[c] = 0;
28641da177e4SLinus Torvalds 		    for (k=0; k < 16; k++) {
28651da177e4SLinus Torvalds 			n=1;
28661da177e4SLinus Torvalds 			n = n << k;
28671da177e4SLinus Torvalds 			if (p->sp[c][k] > 1) {
28681da177e4SLinus Torvalds 			   p->ultra_map[c] |= n;
28691da177e4SLinus Torvalds 			} else {
28701da177e4SLinus Torvalds 			   if (p->sp[c][k] == 0) {
28711da177e4SLinus Torvalds 			      p->async[c] |= n;
28721da177e4SLinus Torvalds 			   }
28731da177e4SLinus Torvalds 			}
28741da177e4SLinus Torvalds 		    }
28751da177e4SLinus Torvalds 		    p->async[c] = ~(p->async[c]);
28761da177e4SLinus Torvalds 
28771da177e4SLinus Torvalds 		    if (p->global_map[c] == 0) {
28781da177e4SLinus Torvalds 		       k=setupdata[c][1];
28791da177e4SLinus Torvalds 		       if ((k & 0x40) != 0)
28801da177e4SLinus Torvalds 			  p->global_map[c] |= 0x20;
28811da177e4SLinus Torvalds 		       k &= 0x07;
28821da177e4SLinus Torvalds 		       p->global_map[c] |= k;
28831da177e4SLinus Torvalds 		       if ((setupdata[c][2] & 0x04) != 0)
28841da177e4SLinus Torvalds 			  p->global_map[c] |= 0x08;
28851da177e4SLinus Torvalds 		       p->host_id[c] = setupdata[c][0] & 0x07;
28861da177e4SLinus Torvalds 		    }
28871da177e4SLinus Torvalds 		}
28881da177e4SLinus Torvalds 
28891da177e4SLinus Torvalds 		k = inb(base_io + 0x28) & 0x8f;
28901da177e4SLinus Torvalds 		k |= 0x10;
28911da177e4SLinus Torvalds 		outb(k, base_io + 0x28);
28921da177e4SLinus Torvalds 		outb(0x80, base_io + 0x41);
28931da177e4SLinus Torvalds 		outb(0x80, base_io + 0x51);
28941da177e4SLinus Torvalds 		mdelay(100);
28951da177e4SLinus Torvalds 		outb(0, base_io + 0x41);
28961da177e4SLinus Torvalds 		outb(0, base_io + 0x51);
28971da177e4SLinus Torvalds 		mdelay(1000);
28981da177e4SLinus Torvalds 		inb(base_io + 0x9b);
28991da177e4SLinus Torvalds 		inb(base_io + 0x97);
29001da177e4SLinus Torvalds 		inb(base_io + 0xdb);
29011da177e4SLinus Torvalds 		inb(base_io + 0xd7);
29021da177e4SLinus Torvalds 		tmport = base_io + 0x80;
29031da177e4SLinus Torvalds 		k=p->host_id[0];
29041da177e4SLinus Torvalds 		if (k > 7)
29051da177e4SLinus Torvalds 		   k = (k & 0x07) | 0x40;
29061da177e4SLinus Torvalds 		k |= 0x08;
29071da177e4SLinus Torvalds 		outb(k, tmport);
29081da177e4SLinus Torvalds 		tmport += 0x18;
29091da177e4SLinus Torvalds 		outb(0, tmport);
29101da177e4SLinus Torvalds 		tmport += 0x07;
29111da177e4SLinus Torvalds 
29121da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0)
29131da177e4SLinus Torvalds 			cpu_relax();
29141da177e4SLinus Torvalds 
29151da177e4SLinus Torvalds 		tmport -= 0x08;
29161da177e4SLinus Torvalds 		inb(tmport);
29171da177e4SLinus Torvalds 		tmport = base_io + 0x81;
29181da177e4SLinus Torvalds 		outb(8, tmport++);
29191da177e4SLinus Torvalds 		outb(0x7f, tmport);
29201da177e4SLinus Torvalds 		tmport = base_io + 0x91;
29211da177e4SLinus Torvalds 		outb(0x20, tmport);
29221da177e4SLinus Torvalds 
29231da177e4SLinus Torvalds 		tmport = base_io + 0xc0;
29241da177e4SLinus Torvalds 		k=p->host_id[1];
29251da177e4SLinus Torvalds 		if (k > 7)
29261da177e4SLinus Torvalds 		   k = (k & 0x07) | 0x40;
29271da177e4SLinus Torvalds 		k |= 0x08;
29281da177e4SLinus Torvalds 		outb(k, tmport);
29291da177e4SLinus Torvalds 		tmport += 0x18;
29301da177e4SLinus Torvalds 		outb(0, tmport);
29311da177e4SLinus Torvalds 		tmport += 0x07;
29321da177e4SLinus Torvalds 
29331da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0)
29341da177e4SLinus Torvalds 			cpu_relax();
29351da177e4SLinus Torvalds 
29361da177e4SLinus Torvalds 		tmport -= 0x08;
29371da177e4SLinus Torvalds 		inb(tmport);
29381da177e4SLinus Torvalds 		tmport = base_io + 0xc1;
29391da177e4SLinus Torvalds 		outb(8, tmport++);
29401da177e4SLinus Torvalds 		outb(0x7f, tmport);
29411da177e4SLinus Torvalds 		tmport = base_io + 0xd1;
29421da177e4SLinus Torvalds 		outb(0x20, tmport);
29431da177e4SLinus Torvalds 
29441da177e4SLinus Torvalds 		tscam_885();
29451da177e4SLinus Torvalds 		printk(KERN_INFO "   Scanning Channel A SCSI Device ...\n");
29461da177e4SLinus Torvalds 		is885(p, base_io + 0x80, 0);
29471da177e4SLinus Torvalds 		printk(KERN_INFO "   Scanning Channel B SCSI Device ...\n");
29481da177e4SLinus Torvalds 		is885(p, base_io + 0xc0, 1);
29491da177e4SLinus Torvalds 
29501da177e4SLinus Torvalds 		k = inb(base_io + 0x28) & 0xcf;
29511da177e4SLinus Torvalds 		k |= 0xc0;
29521da177e4SLinus Torvalds 		outb(k, base_io + 0x28);
29531da177e4SLinus Torvalds 		k = inb(base_io + 0x1f) | 0x80;
29541da177e4SLinus Torvalds 		outb(k, base_io + 0x1f);
29551da177e4SLinus Torvalds 		k = inb(base_io + 0x29) | 0x01;
29561da177e4SLinus Torvalds 		outb(k, base_io + 0x29);
29571da177e4SLinus Torvalds #ifdef ED_DBGP
29581da177e4SLinus Torvalds 		//printk("atp885: atp_host[0] 0x%p\n", atp_host[0]);
29591da177e4SLinus Torvalds #endif
29601da177e4SLinus Torvalds 		shpnt->max_id = 16;
29611da177e4SLinus Torvalds 		shpnt->max_lun = (p->global_map[0] & 0x07) + 1;
29621da177e4SLinus Torvalds 		shpnt->max_channel = 1;
29631da177e4SLinus Torvalds 		shpnt->this_id = p->host_id[0];
29641da177e4SLinus Torvalds 		shpnt->unique_id = base_io;
29651da177e4SLinus Torvalds 		shpnt->io_port = base_io;
29661da177e4SLinus Torvalds 		shpnt->n_io_port = 0xff;	/* Number of bytes of I/O space used */
29671da177e4SLinus Torvalds 		shpnt->irq = pdev->irq;
29681da177e4SLinus Torvalds 
29691da177e4SLinus Torvalds 	} else {
29701da177e4SLinus Torvalds 		error = pci_read_config_byte(pdev, 0x49, &host_id);
29711da177e4SLinus Torvalds 
29721da177e4SLinus Torvalds 		printk(KERN_INFO "   ACARD AEC-671X PCI Ultra/W SCSI-2/3 Host Adapter: %d "
29731da177e4SLinus Torvalds 			"IO:%x, IRQ:%d.\n", count, base_io, pdev->irq);
29741da177e4SLinus Torvalds 
29751da177e4SLinus Torvalds 		atp_dev.ioport[0] = base_io;
29761da177e4SLinus Torvalds 		atp_dev.pciport[0] = base_io + 0x20;
29771da177e4SLinus Torvalds 		atp_dev.dev_id = ent->device;
29781da177e4SLinus Torvalds 		host_id &= 0x07;
29791da177e4SLinus Torvalds 		atp_dev.host_id[0] = host_id;
29801da177e4SLinus Torvalds 		tmport = base_io + 0x22;
29811da177e4SLinus Torvalds 		atp_dev.scam_on = inb(tmport);
29821da177e4SLinus Torvalds 		tmport += 0x0b;
29831da177e4SLinus Torvalds 		atp_dev.global_map[0] = inb(tmport++);
29841da177e4SLinus Torvalds 		atp_dev.ultra_map[0] = inw(tmport);
29851da177e4SLinus Torvalds 
29861da177e4SLinus Torvalds 		if (atp_dev.ultra_map[0] == 0) {
29871da177e4SLinus Torvalds 			atp_dev.scam_on = 0x00;
29881da177e4SLinus Torvalds 			atp_dev.global_map[0] = 0x20;
29891da177e4SLinus Torvalds 			atp_dev.ultra_map[0] = 0xffff;
29901da177e4SLinus Torvalds 		}
29911da177e4SLinus Torvalds 
29921da177e4SLinus Torvalds 		shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
29931da177e4SLinus Torvalds 		if (!shpnt)
29941da177e4SLinus Torvalds 			return -ENOMEM;
29951da177e4SLinus Torvalds 
29961da177e4SLinus Torvalds 		p = (struct atp_unit *)&shpnt->hostdata;
29971da177e4SLinus Torvalds 
29981da177e4SLinus Torvalds 		atp_dev.host = shpnt;
29991da177e4SLinus Torvalds 		atp_dev.pdev = pdev;
30001da177e4SLinus Torvalds 		pci_set_drvdata(pdev, p);
30011da177e4SLinus Torvalds 		memcpy(p, &atp_dev, sizeof atp_dev);
30021da177e4SLinus Torvalds 		if (atp870u_init_tables(shpnt) < 0)
30031da177e4SLinus Torvalds 			goto unregister;
30041da177e4SLinus Torvalds 
30051da177e4SLinus Torvalds 		if (request_irq(pdev->irq, atp870u_intr_handle, SA_SHIRQ, "atp870i", shpnt)) {
30061da177e4SLinus Torvalds 			printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", pdev->irq);
30071da177e4SLinus Torvalds 			goto free_tables;
30081da177e4SLinus Torvalds 		}
30091da177e4SLinus Torvalds 
30101da177e4SLinus Torvalds 		spin_lock_irqsave(shpnt->host_lock, flags);
30111da177e4SLinus Torvalds 		if (atp_dev.chip_ver > 0x07) {	/* check if atp876 chip then enable terminator */
30121da177e4SLinus Torvalds 			tmport = base_io + 0x3e;
30131da177e4SLinus Torvalds 			outb(0x00, tmport);
30141da177e4SLinus Torvalds 		}
30151da177e4SLinus Torvalds 
30161da177e4SLinus Torvalds 		tmport = base_io + 0x3a;
30171da177e4SLinus Torvalds 		k = (inb(tmport) & 0xf3) | 0x10;
30181da177e4SLinus Torvalds 		outb(k, tmport);
30191da177e4SLinus Torvalds 		outb((k & 0xdf), tmport);
30201da177e4SLinus Torvalds 		mdelay(32);
30211da177e4SLinus Torvalds 		outb(k, tmport);
30221da177e4SLinus Torvalds 		mdelay(32);
30231da177e4SLinus Torvalds 		tmport = base_io;
30241da177e4SLinus Torvalds 		outb((host_id | 0x08), tmport);
30251da177e4SLinus Torvalds 		tmport += 0x18;
30261da177e4SLinus Torvalds 		outb(0, tmport);
30271da177e4SLinus Torvalds 		tmport += 0x07;
30281da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0)
30291da177e4SLinus Torvalds 			mdelay(1);
30301da177e4SLinus Torvalds 
30311da177e4SLinus Torvalds 		tmport -= 0x08;
30321da177e4SLinus Torvalds 		inb(tmport);
30331da177e4SLinus Torvalds 		tmport = base_io + 1;
30341da177e4SLinus Torvalds 		outb(8, tmport++);
30351da177e4SLinus Torvalds 		outb(0x7f, tmport);
30361da177e4SLinus Torvalds 		tmport = base_io + 0x11;
30371da177e4SLinus Torvalds 		outb(0x20, tmport);
30381da177e4SLinus Torvalds 
30391da177e4SLinus Torvalds 		tscam(shpnt);
30401da177e4SLinus Torvalds 		is870(p, base_io);
30411da177e4SLinus Torvalds 		tmport = base_io + 0x3a;
30421da177e4SLinus Torvalds 		outb((inb(tmport) & 0xef), tmport);
30431da177e4SLinus Torvalds 		tmport++;
30441da177e4SLinus Torvalds 		outb((inb(tmport) | 0x20), tmport);
30451da177e4SLinus Torvalds 		if (atp_dev.chip_ver == 4)
30461da177e4SLinus Torvalds 			shpnt->max_id = 16;
30471da177e4SLinus Torvalds 		else
30481da177e4SLinus Torvalds 			shpnt->max_id = 7;
30491da177e4SLinus Torvalds 		shpnt->this_id = host_id;
30501da177e4SLinus Torvalds 		shpnt->unique_id = base_io;
30511da177e4SLinus Torvalds 		shpnt->io_port = base_io;
30521da177e4SLinus Torvalds 		shpnt->n_io_port = 0x40;	/* Number of bytes of I/O space used */
30531da177e4SLinus Torvalds 		shpnt->irq = pdev->irq;
30541da177e4SLinus Torvalds 	}
30551da177e4SLinus Torvalds 		spin_unlock_irqrestore(shpnt->host_lock, flags);
30561da177e4SLinus Torvalds 		if(ent->device==ATP885_DEVID) {
30571da177e4SLinus Torvalds 			if(!request_region(base_io, 0xff, "atp870u")) /* Register the IO ports that we use */
30581da177e4SLinus Torvalds 				goto request_io_fail;
30591da177e4SLinus Torvalds 		} else if((ent->device==ATP880_DEVID1)||(ent->device==ATP880_DEVID2)) {
30601da177e4SLinus Torvalds 			if(!request_region(base_io, 0x60, "atp870u")) /* Register the IO ports that we use */
30611da177e4SLinus Torvalds 				goto request_io_fail;
30621da177e4SLinus Torvalds 		} else {
30631da177e4SLinus Torvalds 			if(!request_region(base_io, 0x40, "atp870u")) /* Register the IO ports that we use */
30641da177e4SLinus Torvalds 				goto request_io_fail;
30651da177e4SLinus Torvalds 		}
30661da177e4SLinus Torvalds 		count++;
30671da177e4SLinus Torvalds 		if (scsi_add_host(shpnt, &pdev->dev))
30681da177e4SLinus Torvalds 			goto scsi_add_fail;
30691da177e4SLinus Torvalds 		scsi_scan_host(shpnt);
30701da177e4SLinus Torvalds #ifdef ED_DBGP
30711da177e4SLinus Torvalds 		printk("atp870u_prob : exit\n");
30721da177e4SLinus Torvalds #endif
30731da177e4SLinus Torvalds 		return 0;
30741da177e4SLinus Torvalds 
30751da177e4SLinus Torvalds scsi_add_fail:
30761da177e4SLinus Torvalds 	printk("atp870u_prob:scsi_add_fail\n");
30771da177e4SLinus Torvalds 	if(ent->device==ATP885_DEVID) {
30781da177e4SLinus Torvalds 		release_region(base_io, 0xff);
30791da177e4SLinus Torvalds 	} else if((ent->device==ATP880_DEVID1)||(ent->device==ATP880_DEVID2)) {
30801da177e4SLinus Torvalds 		release_region(base_io, 0x60);
30811da177e4SLinus Torvalds 	} else {
30821da177e4SLinus Torvalds 		release_region(base_io, 0x40);
30831da177e4SLinus Torvalds 	}
30841da177e4SLinus Torvalds request_io_fail:
30851da177e4SLinus Torvalds 	printk("atp870u_prob:request_io_fail\n");
30861da177e4SLinus Torvalds 	free_irq(pdev->irq, shpnt);
30871da177e4SLinus Torvalds free_tables:
30881da177e4SLinus Torvalds 	printk("atp870u_prob:free_table\n");
30891da177e4SLinus Torvalds 	atp870u_free_tables(shpnt);
30901da177e4SLinus Torvalds unregister:
30911da177e4SLinus Torvalds 	printk("atp870u_prob:unregister\n");
30921da177e4SLinus Torvalds 	scsi_host_put(shpnt);
30931da177e4SLinus Torvalds 	return -1;
30941da177e4SLinus Torvalds }
30951da177e4SLinus Torvalds 
30961da177e4SLinus Torvalds /* The abort command does not leave the device in a clean state where
30971da177e4SLinus Torvalds    it is available to be used again.  Until this gets worked out, we will
30981da177e4SLinus Torvalds    leave it commented out.  */
30991da177e4SLinus Torvalds 
31001da177e4SLinus Torvalds static int atp870u_abort(struct scsi_cmnd * SCpnt)
31011da177e4SLinus Torvalds {
31021da177e4SLinus Torvalds 	unsigned char  j, k, c;
31031da177e4SLinus Torvalds 	struct scsi_cmnd *workrequ;
31041da177e4SLinus Torvalds 	unsigned int tmport;
31051da177e4SLinus Torvalds 	struct atp_unit *dev;
31061da177e4SLinus Torvalds 	struct Scsi_Host *host;
31071da177e4SLinus Torvalds 	host = SCpnt->device->host;
31081da177e4SLinus Torvalds 
31091da177e4SLinus Torvalds 	dev = (struct atp_unit *)&host->hostdata;
31101da177e4SLinus Torvalds 	c=SCpnt->device->channel;
31111da177e4SLinus Torvalds 	printk(" atp870u: abort Channel = %x \n", c);
31121da177e4SLinus Torvalds 	printk("working=%x last_cmd=%x ", dev->working[c], dev->last_cmd[c]);
31131da177e4SLinus Torvalds 	printk(" quhdu=%x quendu=%x ", dev->quhd[c], dev->quend[c]);
31141da177e4SLinus Torvalds 	tmport = dev->ioport[c];
31151da177e4SLinus Torvalds 	for (j = 0; j < 0x18; j++) {
31161da177e4SLinus Torvalds 		printk(" r%2x=%2x", j, inb(tmport++));
31171da177e4SLinus Torvalds 	}
31181da177e4SLinus Torvalds 	tmport += 0x04;
31191da177e4SLinus Torvalds 	printk(" r1c=%2x", inb(tmport));
31201da177e4SLinus Torvalds 	tmport += 0x03;
31211da177e4SLinus Torvalds 	printk(" r1f=%2x in_snd=%2x ", inb(tmport), dev->in_snd[c]);
31221da177e4SLinus Torvalds 	tmport= dev->pciport[c];
31231da177e4SLinus Torvalds 	printk(" d00=%2x", inb(tmport));
31241da177e4SLinus Torvalds 	tmport += 0x02;
31251da177e4SLinus Torvalds 	printk(" d02=%2x", inb(tmport));
31261da177e4SLinus Torvalds 	for(j=0;j<16;j++) {
31271da177e4SLinus Torvalds 	   if (dev->id[c][j].curr_req != NULL) {
31281da177e4SLinus Torvalds 		workrequ = dev->id[c][j].curr_req;
31291da177e4SLinus Torvalds 		printk("\n que cdb= ");
31301da177e4SLinus Torvalds 		for (k=0; k < workrequ->cmd_len; k++) {
31311da177e4SLinus Torvalds 		    printk(" %2x ",workrequ->cmnd[k]);
31321da177e4SLinus Torvalds 		}
31331da177e4SLinus Torvalds 		printk(" last_lenu= %x ",(unsigned int)dev->id[c][j].last_len);
31341da177e4SLinus Torvalds 	   }
31351da177e4SLinus Torvalds 	}
31361da177e4SLinus Torvalds 	return SUCCESS;
31371da177e4SLinus Torvalds }
31381da177e4SLinus Torvalds 
31391da177e4SLinus Torvalds static const char *atp870u_info(struct Scsi_Host *notused)
31401da177e4SLinus Torvalds {
31411da177e4SLinus Torvalds 	static char buffer[128];
31421da177e4SLinus Torvalds 
31431da177e4SLinus Torvalds 	strcpy(buffer, "ACARD AEC-6710/6712/67160 PCI Ultra/W/LVD SCSI-3 Adapter Driver V2.6+ac ");
31441da177e4SLinus Torvalds 
31451da177e4SLinus Torvalds 	return buffer;
31461da177e4SLinus Torvalds }
31471da177e4SLinus Torvalds 
31481da177e4SLinus Torvalds #define BLS buffer + len + size
3149420b4a73SAdrian Bunk  static int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer,
31501da177e4SLinus Torvalds 			     char **start, off_t offset, int length, int inout)
31511da177e4SLinus Torvalds {
31521da177e4SLinus Torvalds 	static u8 buff[512];
31531da177e4SLinus Torvalds 	int size = 0;
31541da177e4SLinus Torvalds 	int len = 0;
31551da177e4SLinus Torvalds 	off_t begin = 0;
31561da177e4SLinus Torvalds 	off_t pos = 0;
31571da177e4SLinus Torvalds 
31581da177e4SLinus Torvalds 	if (inout)
31591da177e4SLinus Torvalds 		return -EINVAL;
31601da177e4SLinus Torvalds 	if (offset == 0)
31611da177e4SLinus Torvalds 		memset(buff, 0, sizeof(buff));
31621da177e4SLinus Torvalds 	size += sprintf(BLS, "ACARD AEC-671X Driver Version: 2.6+ac\n");
31631da177e4SLinus Torvalds 	len += size;
31641da177e4SLinus Torvalds 	pos = begin + len;
31651da177e4SLinus Torvalds 	size = 0;
31661da177e4SLinus Torvalds 
31671da177e4SLinus Torvalds 	size += sprintf(BLS, "\n");
31681da177e4SLinus Torvalds 	size += sprintf(BLS, "Adapter Configuration:\n");
31691da177e4SLinus Torvalds 	size += sprintf(BLS, "               Base IO: %#.4lx\n", HBAptr->io_port);
31701da177e4SLinus Torvalds 	size += sprintf(BLS, "                   IRQ: %d\n", HBAptr->irq);
31711da177e4SLinus Torvalds 	len += size;
31721da177e4SLinus Torvalds 	pos = begin + len;
31731da177e4SLinus Torvalds 
31741da177e4SLinus Torvalds 	*start = buffer + (offset - begin);	/* Start of wanted data */
31751da177e4SLinus Torvalds 	len -= (offset - begin);	/* Start slop */
31761da177e4SLinus Torvalds 	if (len > length) {
31771da177e4SLinus Torvalds 		len = length;	/* Ending slop */
31781da177e4SLinus Torvalds 	}
31791da177e4SLinus Torvalds 	return (len);
31801da177e4SLinus Torvalds }
31811da177e4SLinus Torvalds 
31821da177e4SLinus Torvalds 
31831da177e4SLinus Torvalds static int atp870u_biosparam(struct scsi_device *disk, struct block_device *dev,
31841da177e4SLinus Torvalds 			sector_t capacity, int *ip)
31851da177e4SLinus Torvalds {
31861da177e4SLinus Torvalds 	int heads, sectors, cylinders;
31871da177e4SLinus Torvalds 
31881da177e4SLinus Torvalds 	heads = 64;
31891da177e4SLinus Torvalds 	sectors = 32;
31901da177e4SLinus Torvalds 	cylinders = (unsigned long)capacity / (heads * sectors);
31911da177e4SLinus Torvalds 	if (cylinders > 1024) {
31921da177e4SLinus Torvalds 		heads = 255;
31931da177e4SLinus Torvalds 		sectors = 63;
31941da177e4SLinus Torvalds 		cylinders = (unsigned long)capacity / (heads * sectors);
31951da177e4SLinus Torvalds 	}
31961da177e4SLinus Torvalds 	ip[0] = heads;
31971da177e4SLinus Torvalds 	ip[1] = sectors;
31981da177e4SLinus Torvalds 	ip[2] = cylinders;
31991da177e4SLinus Torvalds 
32001da177e4SLinus Torvalds 	return 0;
32011da177e4SLinus Torvalds }
32021da177e4SLinus Torvalds 
32031da177e4SLinus Torvalds static void atp870u_remove (struct pci_dev *pdev)
32041da177e4SLinus Torvalds {
32051da177e4SLinus Torvalds 	struct atp_unit *devext = pci_get_drvdata(pdev);
32061da177e4SLinus Torvalds 	struct Scsi_Host *pshost = devext->host;
32071da177e4SLinus Torvalds 
32081da177e4SLinus Torvalds 
32091da177e4SLinus Torvalds 	scsi_remove_host(pshost);
32101da177e4SLinus Torvalds 	printk(KERN_INFO "free_irq : %d\n",pshost->irq);
32111da177e4SLinus Torvalds 	free_irq(pshost->irq, pshost);
32121da177e4SLinus Torvalds 	release_region(pshost->io_port, pshost->n_io_port);
32131da177e4SLinus Torvalds 	printk(KERN_INFO "atp870u_free_tables : %p\n",pshost);
32141da177e4SLinus Torvalds 	atp870u_free_tables(pshost);
32151da177e4SLinus Torvalds 	printk(KERN_INFO "scsi_host_put : %p\n",pshost);
32161da177e4SLinus Torvalds 	scsi_host_put(pshost);
32171da177e4SLinus Torvalds 	printk(KERN_INFO "pci_set_drvdata : %p\n",pdev);
32181da177e4SLinus Torvalds 	pci_set_drvdata(pdev, NULL);
32191da177e4SLinus Torvalds }
32201da177e4SLinus Torvalds MODULE_LICENSE("GPL");
32211da177e4SLinus Torvalds 
32221da177e4SLinus Torvalds static struct scsi_host_template atp870u_template = {
32231da177e4SLinus Torvalds      .module			= THIS_MODULE,
32241da177e4SLinus Torvalds      .name              	= "atp870u"		/* name */,
32251da177e4SLinus Torvalds      .proc_name			= "atp870u",
32261da177e4SLinus Torvalds      .proc_info			= atp870u_proc_info,
32271da177e4SLinus Torvalds      .info              	= atp870u_info		/* info */,
32281da177e4SLinus Torvalds      .queuecommand      	= atp870u_queuecommand	/* queuecommand */,
32291da177e4SLinus Torvalds      .eh_abort_handler  	= atp870u_abort		/* abort */,
32301da177e4SLinus Torvalds      .bios_param        	= atp870u_biosparam	/* biosparm */,
32311da177e4SLinus Torvalds      .can_queue         	= qcnt			/* can_queue */,
32321da177e4SLinus Torvalds      .this_id           	= 7			/* SCSI ID */,
32331da177e4SLinus Torvalds      .sg_tablesize      	= ATP870U_SCATTER	/*SG_ALL*/ /*SG_NONE*/,
32341da177e4SLinus Torvalds      .cmd_per_lun       	= ATP870U_CMDLUN		/* commands per lun */,
32351da177e4SLinus Torvalds      .use_clustering    	= ENABLE_CLUSTERING,
32361da177e4SLinus Torvalds      .max_sectors		= ATP870U_MAX_SECTORS,
32371da177e4SLinus Torvalds };
32381da177e4SLinus Torvalds 
32391da177e4SLinus Torvalds static struct pci_device_id atp870u_id_table[] = {
32401da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP885_DEVID)			  },
32411da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID1)			  },
32421da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID2)			  },
32431da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7610)    },
32441da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612UW)  },
32451da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612U)   },
32461da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612S)   },
32471da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612D)	  },
32481da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612SUW) },
32491da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_8060)	  },
32501da177e4SLinus Torvalds 	{ 0, },
32511da177e4SLinus Torvalds };
32521da177e4SLinus Torvalds 
32531da177e4SLinus Torvalds MODULE_DEVICE_TABLE(pci, atp870u_id_table);
32541da177e4SLinus Torvalds 
32551da177e4SLinus Torvalds static struct pci_driver atp870u_driver = {
32561da177e4SLinus Torvalds 	.id_table	= atp870u_id_table,
32571da177e4SLinus Torvalds 	.name		= "atp870u",
32581da177e4SLinus Torvalds 	.probe		= atp870u_probe,
32591da177e4SLinus Torvalds 	.remove		= __devexit_p(atp870u_remove),
32601da177e4SLinus Torvalds };
32611da177e4SLinus Torvalds 
32621da177e4SLinus Torvalds static int __init atp870u_init(void)
32631da177e4SLinus Torvalds {
32641da177e4SLinus Torvalds #ifdef ED_DBGP
32651da177e4SLinus Torvalds 	printk("atp870u_init: Entry\n");
32661da177e4SLinus Torvalds #endif
32671da177e4SLinus Torvalds 	return pci_register_driver(&atp870u_driver);
32681da177e4SLinus Torvalds }
32691da177e4SLinus Torvalds 
32701da177e4SLinus Torvalds static void __exit atp870u_exit(void)
32711da177e4SLinus Torvalds {
32721da177e4SLinus Torvalds #ifdef ED_DBGP
32731da177e4SLinus Torvalds 	printk("atp870u_exit: Entry\n");
32741da177e4SLinus Torvalds #endif
32751da177e4SLinus Torvalds 	pci_unregister_driver(&atp870u_driver);
32761da177e4SLinus Torvalds }
32771da177e4SLinus Torvalds 
32781da177e4SLinus Torvalds static void tscam_885(void)
32791da177e4SLinus Torvalds {
32801da177e4SLinus Torvalds 	unsigned char i;
32811da177e4SLinus Torvalds 
32821da177e4SLinus Torvalds 	for (i = 0; i < 0x2; i++) {
32831da177e4SLinus Torvalds 		mdelay(300);
32841da177e4SLinus Torvalds 	}
32851da177e4SLinus Torvalds 	return;
32861da177e4SLinus Torvalds }
32871da177e4SLinus Torvalds 
32881da177e4SLinus Torvalds 
32891da177e4SLinus Torvalds 
32901da177e4SLinus Torvalds static void is885(struct atp_unit *dev, unsigned int wkport,unsigned char c)
32911da177e4SLinus Torvalds {
32921da177e4SLinus Torvalds 	unsigned int tmport;
32931da177e4SLinus Torvalds 	unsigned char i, j, k, rmb, n, lvdmode;
32941da177e4SLinus Torvalds 	unsigned short int m;
32951da177e4SLinus Torvalds 	static unsigned char mbuf[512];
32961da177e4SLinus Torvalds 	static unsigned char satn[9] =	{0, 0, 0, 0, 0, 0, 0, 6, 6};
32971da177e4SLinus Torvalds 	static unsigned char inqd[9] =	{0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6};
32981da177e4SLinus Torvalds 	static unsigned char synn[6] =	{0x80, 1, 3, 1, 0x19, 0x0e};
32991da177e4SLinus Torvalds 	unsigned char synu[6] =  {0x80, 1, 3, 1, 0x0a, 0x0e};
33001da177e4SLinus Torvalds 	static unsigned char synw[6] =	{0x80, 1, 3, 1, 0x19, 0x0e};
33011da177e4SLinus Torvalds 	unsigned char synuw[6] =  {0x80, 1, 3, 1, 0x0a, 0x0e};
33021da177e4SLinus Torvalds 	static unsigned char wide[6] =	{0x80, 1, 2, 3, 1, 0};
33031da177e4SLinus Torvalds 	static unsigned char u3[9] = { 0x80,1,6,4,0x09,00,0x0e,0x01,0x02 };
33041da177e4SLinus Torvalds 
33051da177e4SLinus Torvalds 	lvdmode=inb(wkport + 0x1b) >> 7;
33061da177e4SLinus Torvalds 
33071da177e4SLinus Torvalds 	for (i = 0; i < 16; i++) {
33081da177e4SLinus Torvalds 		m = 1;
33091da177e4SLinus Torvalds 		m = m << i;
33101da177e4SLinus Torvalds 		if ((m & dev->active_id[c]) != 0) {
33111da177e4SLinus Torvalds 			continue;
33121da177e4SLinus Torvalds 		}
33131da177e4SLinus Torvalds 		if (i == dev->host_id[c]) {
33141da177e4SLinus Torvalds 			printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_id[c]);
33151da177e4SLinus Torvalds 			continue;
33161da177e4SLinus Torvalds 		}
33171da177e4SLinus Torvalds 		tmport = wkport + 0x1b;
33181da177e4SLinus Torvalds 		outb(0x01, tmport);
33191da177e4SLinus Torvalds 		tmport = wkport + 0x01;
33201da177e4SLinus Torvalds 		outb(0x08, tmport++);
33211da177e4SLinus Torvalds 		outb(0x7f, tmport++);
33221da177e4SLinus Torvalds 		outb(satn[0], tmport++);
33231da177e4SLinus Torvalds 		outb(satn[1], tmport++);
33241da177e4SLinus Torvalds 		outb(satn[2], tmport++);
33251da177e4SLinus Torvalds 		outb(satn[3], tmport++);
33261da177e4SLinus Torvalds 		outb(satn[4], tmport++);
33271da177e4SLinus Torvalds 		outb(satn[5], tmport++);
33281da177e4SLinus Torvalds 		tmport += 0x06;
33291da177e4SLinus Torvalds 		outb(0, tmport);
33301da177e4SLinus Torvalds 		tmport += 0x02;
33311da177e4SLinus Torvalds 		outb(dev->id[c][i].devsp, tmport++);
33321da177e4SLinus Torvalds 
33331da177e4SLinus Torvalds 		outb(0, tmport++);
33341da177e4SLinus Torvalds 		outb(satn[6], tmport++);
33351da177e4SLinus Torvalds 		outb(satn[7], tmport++);
33361da177e4SLinus Torvalds 		j = i;
33371da177e4SLinus Torvalds 		if ((j & 0x08) != 0) {
33381da177e4SLinus Torvalds 			j = (j & 0x07) | 0x40;
33391da177e4SLinus Torvalds 		}
33401da177e4SLinus Torvalds 		outb(j, tmport);
33411da177e4SLinus Torvalds 		tmport += 0x03;
33421da177e4SLinus Torvalds 		outb(satn[8], tmport);
33431da177e4SLinus Torvalds 		tmport += 0x07;
33441da177e4SLinus Torvalds 
33451da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
33461da177e4SLinus Torvalds 			cpu_relax();
33471da177e4SLinus Torvalds 		tmport -= 0x08;
33481da177e4SLinus Torvalds 		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
33491da177e4SLinus Torvalds 			continue;
33501da177e4SLinus Torvalds 		}
33511da177e4SLinus Torvalds 		while (inb(tmport) != 0x8e)
33521da177e4SLinus Torvalds 			cpu_relax();
33531da177e4SLinus Torvalds 		dev->active_id[c] |= m;
33541da177e4SLinus Torvalds 
33551da177e4SLinus Torvalds 		tmport = wkport + 0x10;
33561da177e4SLinus Torvalds 		outb(0x30, tmport);
33571da177e4SLinus Torvalds 		tmport = wkport + 0x14;
33581da177e4SLinus Torvalds 		outb(0x00, tmport);
33591da177e4SLinus Torvalds 
33601da177e4SLinus Torvalds phase_cmd:
33611da177e4SLinus Torvalds 		tmport = wkport + 0x18;
33621da177e4SLinus Torvalds 		outb(0x08, tmport);
33631da177e4SLinus Torvalds 		tmport += 0x07;
33641da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
33651da177e4SLinus Torvalds 			cpu_relax();
33661da177e4SLinus Torvalds 		tmport -= 0x08;
33671da177e4SLinus Torvalds 		j = inb(tmport);
33681da177e4SLinus Torvalds 		if (j != 0x16) {
33691da177e4SLinus Torvalds 			tmport = wkport + 0x10;
33701da177e4SLinus Torvalds 			outb(0x41, tmport);
33711da177e4SLinus Torvalds 			goto phase_cmd;
33721da177e4SLinus Torvalds 		}
33731da177e4SLinus Torvalds sel_ok:
33741da177e4SLinus Torvalds 		tmport = wkport + 0x03;
33751da177e4SLinus Torvalds 		outb(inqd[0], tmport++);
33761da177e4SLinus Torvalds 		outb(inqd[1], tmport++);
33771da177e4SLinus Torvalds 		outb(inqd[2], tmport++);
33781da177e4SLinus Torvalds 		outb(inqd[3], tmport++);
33791da177e4SLinus Torvalds 		outb(inqd[4], tmport++);
33801da177e4SLinus Torvalds 		outb(inqd[5], tmport);
33811da177e4SLinus Torvalds 		tmport += 0x07;
33821da177e4SLinus Torvalds 		outb(0, tmport);
33831da177e4SLinus Torvalds 		tmport += 0x02;
33841da177e4SLinus Torvalds 		outb(dev->id[c][i].devsp, tmport++);
33851da177e4SLinus Torvalds 		outb(0, tmport++);
33861da177e4SLinus Torvalds 		outb(inqd[6], tmport++);
33871da177e4SLinus Torvalds 		outb(inqd[7], tmport++);
33881da177e4SLinus Torvalds 		tmport += 0x03;
33891da177e4SLinus Torvalds 		outb(inqd[8], tmport);
33901da177e4SLinus Torvalds 		tmport += 0x07;
33911da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
33921da177e4SLinus Torvalds 			cpu_relax();
33931da177e4SLinus Torvalds 		tmport -= 0x08;
33941da177e4SLinus Torvalds 		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
33951da177e4SLinus Torvalds 			continue;
33961da177e4SLinus Torvalds 		}
33971da177e4SLinus Torvalds 		while (inb(tmport) != 0x8e)
33981da177e4SLinus Torvalds 			cpu_relax();
33991da177e4SLinus Torvalds 		tmport = wkport + 0x1b;
34001da177e4SLinus Torvalds 		outb(0x00, tmport);
34011da177e4SLinus Torvalds 		tmport = wkport + 0x18;
34021da177e4SLinus Torvalds 		outb(0x08, tmport);
34031da177e4SLinus Torvalds 		tmport += 0x07;
34041da177e4SLinus Torvalds 		j = 0;
34051da177e4SLinus Torvalds rd_inq_data:
34061da177e4SLinus Torvalds 		k = inb(tmport);
34071da177e4SLinus Torvalds 		if ((k & 0x01) != 0) {
34081da177e4SLinus Torvalds 			tmport -= 0x06;
34091da177e4SLinus Torvalds 			mbuf[j++] = inb(tmport);
34101da177e4SLinus Torvalds 			tmport += 0x06;
34111da177e4SLinus Torvalds 			goto rd_inq_data;
34121da177e4SLinus Torvalds 		}
34131da177e4SLinus Torvalds 		if ((k & 0x80) == 0) {
34141da177e4SLinus Torvalds 			goto rd_inq_data;
34151da177e4SLinus Torvalds 		}
34161da177e4SLinus Torvalds 		tmport -= 0x08;
34171da177e4SLinus Torvalds 		j = inb(tmport);
34181da177e4SLinus Torvalds 		if (j == 0x16) {
34191da177e4SLinus Torvalds 			goto inq_ok;
34201da177e4SLinus Torvalds 		}
34211da177e4SLinus Torvalds 		tmport = wkport + 0x10;
34221da177e4SLinus Torvalds 		outb(0x46, tmport);
34231da177e4SLinus Torvalds 		tmport += 0x02;
34241da177e4SLinus Torvalds 		outb(0, tmport++);
34251da177e4SLinus Torvalds 		outb(0, tmport++);
34261da177e4SLinus Torvalds 		outb(0, tmport++);
34271da177e4SLinus Torvalds 		tmport += 0x03;
34281da177e4SLinus Torvalds 		outb(0x08, tmport);
34291da177e4SLinus Torvalds 		tmport += 0x07;
34301da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
34311da177e4SLinus Torvalds 			cpu_relax();
34321da177e4SLinus Torvalds 		tmport -= 0x08;
34331da177e4SLinus Torvalds 		if (inb(tmport) != 0x16) {
34341da177e4SLinus Torvalds 			goto sel_ok;
34351da177e4SLinus Torvalds 		}
34361da177e4SLinus Torvalds inq_ok:
34371da177e4SLinus Torvalds 		mbuf[36] = 0;
34381da177e4SLinus Torvalds 		printk( KERN_INFO"         ID: %2d  %s\n", i, &mbuf[8]);
34391da177e4SLinus Torvalds 		dev->id[c][i].devtype = mbuf[0];
34401da177e4SLinus Torvalds 		rmb = mbuf[1];
34411da177e4SLinus Torvalds 		n = mbuf[7];
34421da177e4SLinus Torvalds 		if ((mbuf[7] & 0x60) == 0) {
34431da177e4SLinus Torvalds 			goto not_wide;
34441da177e4SLinus Torvalds 		}
34451da177e4SLinus Torvalds 		if ((i < 8) && ((dev->global_map[c] & 0x20) == 0)) {
34461da177e4SLinus Torvalds 			goto not_wide;
34471da177e4SLinus Torvalds 		}
34481da177e4SLinus Torvalds 		if (lvdmode == 0) {
34491da177e4SLinus Torvalds 		   goto chg_wide;
34501da177e4SLinus Torvalds 		}
34511da177e4SLinus Torvalds 		if (dev->sp[c][i] != 0x04) {	// force u2
34521da177e4SLinus Torvalds 		   goto chg_wide;
34531da177e4SLinus Torvalds 		}
34541da177e4SLinus Torvalds 
34551da177e4SLinus Torvalds 		tmport = wkport + 0x1b;
34561da177e4SLinus Torvalds 		outb(0x01, tmport);
34571da177e4SLinus Torvalds 		tmport = wkport + 0x03;
34581da177e4SLinus Torvalds 		outb(satn[0], tmport++);
34591da177e4SLinus Torvalds 		outb(satn[1], tmport++);
34601da177e4SLinus Torvalds 		outb(satn[2], tmport++);
34611da177e4SLinus Torvalds 		outb(satn[3], tmport++);
34621da177e4SLinus Torvalds 		outb(satn[4], tmport++);
34631da177e4SLinus Torvalds 		outb(satn[5], tmport++);
34641da177e4SLinus Torvalds 		tmport += 0x06;
34651da177e4SLinus Torvalds 		outb(0, tmport);
34661da177e4SLinus Torvalds 		tmport += 0x02;
34671da177e4SLinus Torvalds 		outb(dev->id[c][i].devsp, tmport++);
34681da177e4SLinus Torvalds 		outb(0, tmport++);
34691da177e4SLinus Torvalds 		outb(satn[6], tmport++);
34701da177e4SLinus Torvalds 		outb(satn[7], tmport++);
34711da177e4SLinus Torvalds 		tmport += 0x03;
34721da177e4SLinus Torvalds 		outb(satn[8], tmport);
34731da177e4SLinus Torvalds 		tmport += 0x07;
34741da177e4SLinus Torvalds 
34751da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
34761da177e4SLinus Torvalds 			cpu_relax();
34771da177e4SLinus Torvalds 		tmport -= 0x08;
34781da177e4SLinus Torvalds 		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
34791da177e4SLinus Torvalds 			continue;
34801da177e4SLinus Torvalds 		}
34811da177e4SLinus Torvalds 		while (inb(tmport) != 0x8e)
34821da177e4SLinus Torvalds 			cpu_relax();
34831da177e4SLinus Torvalds try_u3:
34841da177e4SLinus Torvalds 		j = 0;
34851da177e4SLinus Torvalds 		tmport = wkport + 0x14;
34861da177e4SLinus Torvalds 		outb(0x09, tmport);
34871da177e4SLinus Torvalds 		tmport += 0x04;
34881da177e4SLinus Torvalds 		outb(0x20, tmport);
34891da177e4SLinus Torvalds 		tmport += 0x07;
34901da177e4SLinus Torvalds 
34911da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0) {
34921da177e4SLinus Torvalds 			if ((inb(tmport) & 0x01) != 0) {
34931da177e4SLinus Torvalds 				tmport -= 0x06;
34941da177e4SLinus Torvalds 				outb(u3[j++], tmport);
34951da177e4SLinus Torvalds 				tmport += 0x06;
34961da177e4SLinus Torvalds 			}
34971da177e4SLinus Torvalds 			cpu_relax();
34981da177e4SLinus Torvalds 		}
34991da177e4SLinus Torvalds 		tmport -= 0x08;
35001da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
35011da177e4SLinus Torvalds 			cpu_relax();
35021da177e4SLinus Torvalds 		j = inb(tmport) & 0x0f;
35031da177e4SLinus Torvalds 		if (j == 0x0f) {
35041da177e4SLinus Torvalds 			goto u3p_in;
35051da177e4SLinus Torvalds 		}
35061da177e4SLinus Torvalds 		if (j == 0x0a) {
35071da177e4SLinus Torvalds 			goto u3p_cmd;
35081da177e4SLinus Torvalds 		}
35091da177e4SLinus Torvalds 		if (j == 0x0e) {
35101da177e4SLinus Torvalds 			goto try_u3;
35111da177e4SLinus Torvalds 		}
35121da177e4SLinus Torvalds 		continue;
35131da177e4SLinus Torvalds u3p_out:
35141da177e4SLinus Torvalds 		tmport = wkport + 0x18;
35151da177e4SLinus Torvalds 		outb(0x20, tmport);
35161da177e4SLinus Torvalds 		tmport += 0x07;
35171da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0) {
35181da177e4SLinus Torvalds 			if ((inb(tmport) & 0x01) != 0) {
35191da177e4SLinus Torvalds 				tmport -= 0x06;
35201da177e4SLinus Torvalds 				outb(0, tmport);
35211da177e4SLinus Torvalds 				tmport += 0x06;
35221da177e4SLinus Torvalds 			}
35231da177e4SLinus Torvalds 			cpu_relax();
35241da177e4SLinus Torvalds 		}
35251da177e4SLinus Torvalds 		tmport -= 0x08;
35261da177e4SLinus Torvalds 		j = inb(tmport) & 0x0f;
35271da177e4SLinus Torvalds 		if (j == 0x0f) {
35281da177e4SLinus Torvalds 			goto u3p_in;
35291da177e4SLinus Torvalds 		}
35301da177e4SLinus Torvalds 		if (j == 0x0a) {
35311da177e4SLinus Torvalds 			goto u3p_cmd;
35321da177e4SLinus Torvalds 		}
35331da177e4SLinus Torvalds 		if (j == 0x0e) {
35341da177e4SLinus Torvalds 			goto u3p_out;
35351da177e4SLinus Torvalds 		}
35361da177e4SLinus Torvalds 		continue;
35371da177e4SLinus Torvalds u3p_in:
35381da177e4SLinus Torvalds 		tmport = wkport + 0x14;
35391da177e4SLinus Torvalds 		outb(0x09, tmport);
35401da177e4SLinus Torvalds 		tmport += 0x04;
35411da177e4SLinus Torvalds 		outb(0x20, tmport);
35421da177e4SLinus Torvalds 		tmport += 0x07;
35431da177e4SLinus Torvalds 		k = 0;
35441da177e4SLinus Torvalds u3p_in1:
35451da177e4SLinus Torvalds 		j = inb(tmport);
35461da177e4SLinus Torvalds 		if ((j & 0x01) != 0) {
35471da177e4SLinus Torvalds 			tmport -= 0x06;
35481da177e4SLinus Torvalds 			mbuf[k++] = inb(tmport);
35491da177e4SLinus Torvalds 			tmport += 0x06;
35501da177e4SLinus Torvalds 			goto u3p_in1;
35511da177e4SLinus Torvalds 		}
35521da177e4SLinus Torvalds 		if ((j & 0x80) == 0x00) {
35531da177e4SLinus Torvalds 			goto u3p_in1;
35541da177e4SLinus Torvalds 		}
35551da177e4SLinus Torvalds 		tmport -= 0x08;
35561da177e4SLinus Torvalds 		j = inb(tmport) & 0x0f;
35571da177e4SLinus Torvalds 		if (j == 0x0f) {
35581da177e4SLinus Torvalds 			goto u3p_in;
35591da177e4SLinus Torvalds 		}
35601da177e4SLinus Torvalds 		if (j == 0x0a) {
35611da177e4SLinus Torvalds 			goto u3p_cmd;
35621da177e4SLinus Torvalds 		}
35631da177e4SLinus Torvalds 		if (j == 0x0e) {
35641da177e4SLinus Torvalds 			goto u3p_out;
35651da177e4SLinus Torvalds 		}
35661da177e4SLinus Torvalds 		continue;
35671da177e4SLinus Torvalds u3p_cmd:
35681da177e4SLinus Torvalds 		tmport = wkport + 0x10;
35691da177e4SLinus Torvalds 		outb(0x30, tmport);
35701da177e4SLinus Torvalds 		tmport = wkport + 0x14;
35711da177e4SLinus Torvalds 		outb(0x00, tmport);
35721da177e4SLinus Torvalds 		tmport += 0x04;
35731da177e4SLinus Torvalds 		outb(0x08, tmport);
35741da177e4SLinus Torvalds 		tmport += 0x07;
35751da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00);
35761da177e4SLinus Torvalds 		tmport -= 0x08;
35771da177e4SLinus Torvalds 		j = inb(tmport);
35781da177e4SLinus Torvalds 		if (j != 0x16) {
35791da177e4SLinus Torvalds 			if (j == 0x4e) {
35801da177e4SLinus Torvalds 				goto u3p_out;
35811da177e4SLinus Torvalds 			}
35821da177e4SLinus Torvalds 			continue;
35831da177e4SLinus Torvalds 		}
35841da177e4SLinus Torvalds 		if (mbuf[0] != 0x01) {
35851da177e4SLinus Torvalds 			goto chg_wide;
35861da177e4SLinus Torvalds 		}
35871da177e4SLinus Torvalds 		if (mbuf[1] != 0x06) {
35881da177e4SLinus Torvalds 			goto chg_wide;
35891da177e4SLinus Torvalds 		}
35901da177e4SLinus Torvalds 		if (mbuf[2] != 0x04) {
35911da177e4SLinus Torvalds 			goto chg_wide;
35921da177e4SLinus Torvalds 		}
35931da177e4SLinus Torvalds 		if (mbuf[3] == 0x09) {
35941da177e4SLinus Torvalds 			m = 1;
35951da177e4SLinus Torvalds 			m = m << i;
35961da177e4SLinus Torvalds 			dev->wide_id[c] |= m;
35971da177e4SLinus Torvalds 			dev->id[c][i].devsp = 0xce;
35981da177e4SLinus Torvalds #ifdef ED_DBGP
35991da177e4SLinus Torvalds 			printk("dev->id[%2d][%2d].devsp = %2x\n",c,i,dev->id[c][i].devsp);
36001da177e4SLinus Torvalds #endif
36011da177e4SLinus Torvalds 			continue;
36021da177e4SLinus Torvalds 		}
36031da177e4SLinus Torvalds chg_wide:
36041da177e4SLinus Torvalds 		tmport = wkport + 0x1b;
36051da177e4SLinus Torvalds 		outb(0x01, tmport);
36061da177e4SLinus Torvalds 		tmport = wkport + 0x03;
36071da177e4SLinus Torvalds 		outb(satn[0], tmport++);
36081da177e4SLinus Torvalds 		outb(satn[1], tmport++);
36091da177e4SLinus Torvalds 		outb(satn[2], tmport++);
36101da177e4SLinus Torvalds 		outb(satn[3], tmport++);
36111da177e4SLinus Torvalds 		outb(satn[4], tmport++);
36121da177e4SLinus Torvalds 		outb(satn[5], tmport++);
36131da177e4SLinus Torvalds 		tmport += 0x06;
36141da177e4SLinus Torvalds 		outb(0, tmport);
36151da177e4SLinus Torvalds 		tmport += 0x02;
36161da177e4SLinus Torvalds 		outb(dev->id[c][i].devsp, tmport++);
36171da177e4SLinus Torvalds 		outb(0, tmport++);
36181da177e4SLinus Torvalds 		outb(satn[6], tmport++);
36191da177e4SLinus Torvalds 		outb(satn[7], tmport++);
36201da177e4SLinus Torvalds 		tmport += 0x03;
36211da177e4SLinus Torvalds 		outb(satn[8], tmport);
36221da177e4SLinus Torvalds 		tmport += 0x07;
36231da177e4SLinus Torvalds 
36241da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
36251da177e4SLinus Torvalds 			cpu_relax();
36261da177e4SLinus Torvalds 		tmport -= 0x08;
36271da177e4SLinus Torvalds 		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
36281da177e4SLinus Torvalds 			continue;
36291da177e4SLinus Torvalds 		}
36301da177e4SLinus Torvalds 		while (inb(tmport) != 0x8e)
36311da177e4SLinus Torvalds 			cpu_relax();
36321da177e4SLinus Torvalds try_wide:
36331da177e4SLinus Torvalds 		j = 0;
36341da177e4SLinus Torvalds 		tmport = wkport + 0x14;
36351da177e4SLinus Torvalds 		outb(0x05, tmport);
36361da177e4SLinus Torvalds 		tmport += 0x04;
36371da177e4SLinus Torvalds 		outb(0x20, tmport);
36381da177e4SLinus Torvalds 		tmport += 0x07;
36391da177e4SLinus Torvalds 
36401da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0) {
36411da177e4SLinus Torvalds 			if ((inb(tmport) & 0x01) != 0) {
36421da177e4SLinus Torvalds 				tmport -= 0x06;
36431da177e4SLinus Torvalds 				outb(wide[j++], tmport);
36441da177e4SLinus Torvalds 				tmport += 0x06;
36451da177e4SLinus Torvalds 			}
36461da177e4SLinus Torvalds 			cpu_relax();
36471da177e4SLinus Torvalds 		}
36481da177e4SLinus Torvalds 		tmport -= 0x08;
36491da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
36501da177e4SLinus Torvalds 			cpu_relax();
36511da177e4SLinus Torvalds 		j = inb(tmport) & 0x0f;
36521da177e4SLinus Torvalds 		if (j == 0x0f) {
36531da177e4SLinus Torvalds 			goto widep_in;
36541da177e4SLinus Torvalds 		}
36551da177e4SLinus Torvalds 		if (j == 0x0a) {
36561da177e4SLinus Torvalds 			goto widep_cmd;
36571da177e4SLinus Torvalds 		}
36581da177e4SLinus Torvalds 		if (j == 0x0e) {
36591da177e4SLinus Torvalds 			goto try_wide;
36601da177e4SLinus Torvalds 		}
36611da177e4SLinus Torvalds 		continue;
36621da177e4SLinus Torvalds widep_out:
36631da177e4SLinus Torvalds 		tmport = wkport + 0x18;
36641da177e4SLinus Torvalds 		outb(0x20, tmport);
36651da177e4SLinus Torvalds 		tmport += 0x07;
36661da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0) {
36671da177e4SLinus Torvalds 			if ((inb(tmport) & 0x01) != 0) {
36681da177e4SLinus Torvalds 				tmport -= 0x06;
36691da177e4SLinus Torvalds 				outb(0, tmport);
36701da177e4SLinus Torvalds 				tmport += 0x06;
36711da177e4SLinus Torvalds 			}
36721da177e4SLinus Torvalds 			cpu_relax();
36731da177e4SLinus Torvalds 		}
36741da177e4SLinus Torvalds 		tmport -= 0x08;
36751da177e4SLinus Torvalds 		j = inb(tmport) & 0x0f;
36761da177e4SLinus Torvalds 		if (j == 0x0f) {
36771da177e4SLinus Torvalds 			goto widep_in;
36781da177e4SLinus Torvalds 		}
36791da177e4SLinus Torvalds 		if (j == 0x0a) {
36801da177e4SLinus Torvalds 			goto widep_cmd;
36811da177e4SLinus Torvalds 		}
36821da177e4SLinus Torvalds 		if (j == 0x0e) {
36831da177e4SLinus Torvalds 			goto widep_out;
36841da177e4SLinus Torvalds 		}
36851da177e4SLinus Torvalds 		continue;
36861da177e4SLinus Torvalds widep_in:
36871da177e4SLinus Torvalds 		tmport = wkport + 0x14;
36881da177e4SLinus Torvalds 		outb(0xff, tmport);
36891da177e4SLinus Torvalds 		tmport += 0x04;
36901da177e4SLinus Torvalds 		outb(0x20, tmport);
36911da177e4SLinus Torvalds 		tmport += 0x07;
36921da177e4SLinus Torvalds 		k = 0;
36931da177e4SLinus Torvalds widep_in1:
36941da177e4SLinus Torvalds 		j = inb(tmport);
36951da177e4SLinus Torvalds 		if ((j & 0x01) != 0) {
36961da177e4SLinus Torvalds 			tmport -= 0x06;
36971da177e4SLinus Torvalds 			mbuf[k++] = inb(tmport);
36981da177e4SLinus Torvalds 			tmport += 0x06;
36991da177e4SLinus Torvalds 			goto widep_in1;
37001da177e4SLinus Torvalds 		}
37011da177e4SLinus Torvalds 		if ((j & 0x80) == 0x00) {
37021da177e4SLinus Torvalds 			goto widep_in1;
37031da177e4SLinus Torvalds 		}
37041da177e4SLinus Torvalds 		tmport -= 0x08;
37051da177e4SLinus Torvalds 		j = inb(tmport) & 0x0f;
37061da177e4SLinus Torvalds 		if (j == 0x0f) {
37071da177e4SLinus Torvalds 			goto widep_in;
37081da177e4SLinus Torvalds 		}
37091da177e4SLinus Torvalds 		if (j == 0x0a) {
37101da177e4SLinus Torvalds 			goto widep_cmd;
37111da177e4SLinus Torvalds 		}
37121da177e4SLinus Torvalds 		if (j == 0x0e) {
37131da177e4SLinus Torvalds 			goto widep_out;
37141da177e4SLinus Torvalds 		}
37151da177e4SLinus Torvalds 		continue;
37161da177e4SLinus Torvalds widep_cmd:
37171da177e4SLinus Torvalds 		tmport = wkport + 0x10;
37181da177e4SLinus Torvalds 		outb(0x30, tmport);
37191da177e4SLinus Torvalds 		tmport = wkport + 0x14;
37201da177e4SLinus Torvalds 		outb(0x00, tmport);
37211da177e4SLinus Torvalds 		tmport += 0x04;
37221da177e4SLinus Torvalds 		outb(0x08, tmport);
37231da177e4SLinus Torvalds 		tmport += 0x07;
37241da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
37251da177e4SLinus Torvalds 			cpu_relax();
37261da177e4SLinus Torvalds 		tmport -= 0x08;
37271da177e4SLinus Torvalds 		j = inb(tmport);
37281da177e4SLinus Torvalds 		if (j != 0x16) {
37291da177e4SLinus Torvalds 			if (j == 0x4e) {
37301da177e4SLinus Torvalds 				goto widep_out;
37311da177e4SLinus Torvalds 			}
37321da177e4SLinus Torvalds 			continue;
37331da177e4SLinus Torvalds 		}
37341da177e4SLinus Torvalds 		if (mbuf[0] != 0x01) {
37351da177e4SLinus Torvalds 			goto not_wide;
37361da177e4SLinus Torvalds 		}
37371da177e4SLinus Torvalds 		if (mbuf[1] != 0x02) {
37381da177e4SLinus Torvalds 			goto not_wide;
37391da177e4SLinus Torvalds 		}
37401da177e4SLinus Torvalds 		if (mbuf[2] != 0x03) {
37411da177e4SLinus Torvalds 			goto not_wide;
37421da177e4SLinus Torvalds 		}
37431da177e4SLinus Torvalds 		if (mbuf[3] != 0x01) {
37441da177e4SLinus Torvalds 			goto not_wide;
37451da177e4SLinus Torvalds 		}
37461da177e4SLinus Torvalds 		m = 1;
37471da177e4SLinus Torvalds 		m = m << i;
37481da177e4SLinus Torvalds 		dev->wide_id[c] |= m;
37491da177e4SLinus Torvalds not_wide:
37501da177e4SLinus Torvalds 		if ((dev->id[c][i].devtype == 0x00) || (dev->id[c][i].devtype == 0x07) ||
37511da177e4SLinus Torvalds 		    ((dev->id[c][i].devtype == 0x05) && ((n & 0x10) != 0))) {
37521da177e4SLinus Torvalds 			m = 1;
37531da177e4SLinus Torvalds 			m = m << i;
37541da177e4SLinus Torvalds 			if ((dev->async[c] & m) != 0) {
37551da177e4SLinus Torvalds 			   goto set_sync;
37561da177e4SLinus Torvalds 			}
37571da177e4SLinus Torvalds 		}
37581da177e4SLinus Torvalds 		continue;
37591da177e4SLinus Torvalds set_sync:
37601da177e4SLinus Torvalds 		if (dev->sp[c][i] == 0x02) {
37611da177e4SLinus Torvalds 		   synu[4]=0x0c;
37621da177e4SLinus Torvalds 		   synuw[4]=0x0c;
37631da177e4SLinus Torvalds 		} else {
37641da177e4SLinus Torvalds 		   if (dev->sp[c][i] >= 0x03) {
37651da177e4SLinus Torvalds 		      synu[4]=0x0a;
37661da177e4SLinus Torvalds 		      synuw[4]=0x0a;
37671da177e4SLinus Torvalds 		   }
37681da177e4SLinus Torvalds 		}
37691da177e4SLinus Torvalds 		tmport = wkport + 0x1b;
37701da177e4SLinus Torvalds 		j = 0;
37711da177e4SLinus Torvalds 		if ((m & dev->wide_id[c]) != 0) {
37721da177e4SLinus Torvalds 			j |= 0x01;
37731da177e4SLinus Torvalds 		}
37741da177e4SLinus Torvalds 		outb(j, tmport);
37751da177e4SLinus Torvalds 		tmport = wkport + 0x03;
37761da177e4SLinus Torvalds 		outb(satn[0], tmport++);
37771da177e4SLinus Torvalds 		outb(satn[1], tmport++);
37781da177e4SLinus Torvalds 		outb(satn[2], tmport++);
37791da177e4SLinus Torvalds 		outb(satn[3], tmport++);
37801da177e4SLinus Torvalds 		outb(satn[4], tmport++);
37811da177e4SLinus Torvalds 		outb(satn[5], tmport++);
37821da177e4SLinus Torvalds 		tmport += 0x06;
37831da177e4SLinus Torvalds 		outb(0, tmport);
37841da177e4SLinus Torvalds 		tmport += 0x02;
37851da177e4SLinus Torvalds 		outb(dev->id[c][i].devsp, tmport++);
37861da177e4SLinus Torvalds 		outb(0, tmport++);
37871da177e4SLinus Torvalds 		outb(satn[6], tmport++);
37881da177e4SLinus Torvalds 		outb(satn[7], tmport++);
37891da177e4SLinus Torvalds 		tmport += 0x03;
37901da177e4SLinus Torvalds 		outb(satn[8], tmport);
37911da177e4SLinus Torvalds 		tmport += 0x07;
37921da177e4SLinus Torvalds 
37931da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
37941da177e4SLinus Torvalds 			cpu_relax();
37951da177e4SLinus Torvalds 		tmport -= 0x08;
37961da177e4SLinus Torvalds 		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
37971da177e4SLinus Torvalds 			continue;
37981da177e4SLinus Torvalds 		}
37991da177e4SLinus Torvalds 		while (inb(tmport) != 0x8e)
38001da177e4SLinus Torvalds 			cpu_relax();
38011da177e4SLinus Torvalds try_sync:
38021da177e4SLinus Torvalds 		j = 0;
38031da177e4SLinus Torvalds 		tmport = wkport + 0x14;
38041da177e4SLinus Torvalds 		outb(0x06, tmport);
38051da177e4SLinus Torvalds 		tmport += 0x04;
38061da177e4SLinus Torvalds 		outb(0x20, tmport);
38071da177e4SLinus Torvalds 		tmport += 0x07;
38081da177e4SLinus Torvalds 
38091da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0) {
38101da177e4SLinus Torvalds 			if ((inb(tmport) & 0x01) != 0) {
38111da177e4SLinus Torvalds 				tmport -= 0x06;
38121da177e4SLinus Torvalds 				if ((m & dev->wide_id[c]) != 0) {
38131da177e4SLinus Torvalds 					if ((m & dev->ultra_map[c]) != 0) {
38141da177e4SLinus Torvalds 						outb(synuw[j++], tmport);
38151da177e4SLinus Torvalds 					} else {
38161da177e4SLinus Torvalds 						outb(synw[j++], tmport);
38171da177e4SLinus Torvalds 					}
38181da177e4SLinus Torvalds 				} else {
38191da177e4SLinus Torvalds 					if ((m & dev->ultra_map[c]) != 0) {
38201da177e4SLinus Torvalds 						outb(synu[j++], tmport);
38211da177e4SLinus Torvalds 					} else {
38221da177e4SLinus Torvalds 						outb(synn[j++], tmport);
38231da177e4SLinus Torvalds 					}
38241da177e4SLinus Torvalds 				}
38251da177e4SLinus Torvalds 				tmport += 0x06;
38261da177e4SLinus Torvalds 			}
38271da177e4SLinus Torvalds 		}
38281da177e4SLinus Torvalds 		tmport -= 0x08;
38291da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
38301da177e4SLinus Torvalds 			cpu_relax();
38311da177e4SLinus Torvalds 		j = inb(tmport) & 0x0f;
38321da177e4SLinus Torvalds 		if (j == 0x0f) {
38331da177e4SLinus Torvalds 			goto phase_ins;
38341da177e4SLinus Torvalds 		}
38351da177e4SLinus Torvalds 		if (j == 0x0a) {
38361da177e4SLinus Torvalds 			goto phase_cmds;
38371da177e4SLinus Torvalds 		}
38381da177e4SLinus Torvalds 		if (j == 0x0e) {
38391da177e4SLinus Torvalds 			goto try_sync;
38401da177e4SLinus Torvalds 		}
38411da177e4SLinus Torvalds 		continue;
38421da177e4SLinus Torvalds phase_outs:
38431da177e4SLinus Torvalds 		tmport = wkport + 0x18;
38441da177e4SLinus Torvalds 		outb(0x20, tmport);
38451da177e4SLinus Torvalds 		tmport += 0x07;
38461da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00) {
38471da177e4SLinus Torvalds 			if ((inb(tmport) & 0x01) != 0x00) {
38481da177e4SLinus Torvalds 				tmport -= 0x06;
38491da177e4SLinus Torvalds 				outb(0x00, tmport);
38501da177e4SLinus Torvalds 				tmport += 0x06;
38511da177e4SLinus Torvalds 			}
38521da177e4SLinus Torvalds 			cpu_relax();
38531da177e4SLinus Torvalds 		}
38541da177e4SLinus Torvalds 		tmport -= 0x08;
38551da177e4SLinus Torvalds 		j = inb(tmport);
38561da177e4SLinus Torvalds 		if (j == 0x85) {
38571da177e4SLinus Torvalds 			goto tar_dcons;
38581da177e4SLinus Torvalds 		}
38591da177e4SLinus Torvalds 		j &= 0x0f;
38601da177e4SLinus Torvalds 		if (j == 0x0f) {
38611da177e4SLinus Torvalds 			goto phase_ins;
38621da177e4SLinus Torvalds 		}
38631da177e4SLinus Torvalds 		if (j == 0x0a) {
38641da177e4SLinus Torvalds 			goto phase_cmds;
38651da177e4SLinus Torvalds 		}
38661da177e4SLinus Torvalds 		if (j == 0x0e) {
38671da177e4SLinus Torvalds 			goto phase_outs;
38681da177e4SLinus Torvalds 		}
38691da177e4SLinus Torvalds 		continue;
38701da177e4SLinus Torvalds phase_ins:
38711da177e4SLinus Torvalds 		tmport = wkport + 0x14;
38721da177e4SLinus Torvalds 		outb(0x06, tmport);
38731da177e4SLinus Torvalds 		tmport += 0x04;
38741da177e4SLinus Torvalds 		outb(0x20, tmport);
38751da177e4SLinus Torvalds 		tmport += 0x07;
38761da177e4SLinus Torvalds 		k = 0;
38771da177e4SLinus Torvalds phase_ins1:
38781da177e4SLinus Torvalds 		j = inb(tmport);
38791da177e4SLinus Torvalds 		if ((j & 0x01) != 0x00) {
38801da177e4SLinus Torvalds 			tmport -= 0x06;
38811da177e4SLinus Torvalds 			mbuf[k++] = inb(tmport);
38821da177e4SLinus Torvalds 			tmport += 0x06;
38831da177e4SLinus Torvalds 			goto phase_ins1;
38841da177e4SLinus Torvalds 		}
38851da177e4SLinus Torvalds 		if ((j & 0x80) == 0x00) {
38861da177e4SLinus Torvalds 			goto phase_ins1;
38871da177e4SLinus Torvalds 		}
38881da177e4SLinus Torvalds 		tmport -= 0x08;
38891da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00);
38901da177e4SLinus Torvalds 		j = inb(tmport);
38911da177e4SLinus Torvalds 		if (j == 0x85) {
38921da177e4SLinus Torvalds 			goto tar_dcons;
38931da177e4SLinus Torvalds 		}
38941da177e4SLinus Torvalds 		j &= 0x0f;
38951da177e4SLinus Torvalds 		if (j == 0x0f) {
38961da177e4SLinus Torvalds 			goto phase_ins;
38971da177e4SLinus Torvalds 		}
38981da177e4SLinus Torvalds 		if (j == 0x0a) {
38991da177e4SLinus Torvalds 			goto phase_cmds;
39001da177e4SLinus Torvalds 		}
39011da177e4SLinus Torvalds 		if (j == 0x0e) {
39021da177e4SLinus Torvalds 			goto phase_outs;
39031da177e4SLinus Torvalds 		}
39041da177e4SLinus Torvalds 		continue;
39051da177e4SLinus Torvalds phase_cmds:
39061da177e4SLinus Torvalds 		tmport = wkport + 0x10;
39071da177e4SLinus Torvalds 		outb(0x30, tmport);
39081da177e4SLinus Torvalds tar_dcons:
39091da177e4SLinus Torvalds 		tmport = wkport + 0x14;
39101da177e4SLinus Torvalds 		outb(0x00, tmport);
39111da177e4SLinus Torvalds 		tmport += 0x04;
39121da177e4SLinus Torvalds 		outb(0x08, tmport);
39131da177e4SLinus Torvalds 		tmport += 0x07;
39141da177e4SLinus Torvalds 		while ((inb(tmport) & 0x80) == 0x00)
39151da177e4SLinus Torvalds 			cpu_relax();
39161da177e4SLinus Torvalds 		tmport -= 0x08;
39171da177e4SLinus Torvalds 		j = inb(tmport);
39181da177e4SLinus Torvalds 		if (j != 0x16) {
39191da177e4SLinus Torvalds 			continue;
39201da177e4SLinus Torvalds 		}
39211da177e4SLinus Torvalds 		if (mbuf[0] != 0x01) {
39221da177e4SLinus Torvalds 			continue;
39231da177e4SLinus Torvalds 		}
39241da177e4SLinus Torvalds 		if (mbuf[1] != 0x03) {
39251da177e4SLinus Torvalds 			continue;
39261da177e4SLinus Torvalds 		}
39271da177e4SLinus Torvalds 		if (mbuf[4] == 0x00) {
39281da177e4SLinus Torvalds 			continue;
39291da177e4SLinus Torvalds 		}
39301da177e4SLinus Torvalds 		if (mbuf[3] > 0x64) {
39311da177e4SLinus Torvalds 			continue;
39321da177e4SLinus Torvalds 		}
39331da177e4SLinus Torvalds 		if (mbuf[4] > 0x0e) {
39341da177e4SLinus Torvalds 			mbuf[4] = 0x0e;
39351da177e4SLinus Torvalds 		}
39361da177e4SLinus Torvalds 		dev->id[c][i].devsp = mbuf[4];
39371da177e4SLinus Torvalds 		if (mbuf[3] < 0x0c){
39381da177e4SLinus Torvalds 			j = 0xb0;
39391da177e4SLinus Torvalds 			goto set_syn_ok;
39401da177e4SLinus Torvalds 		}
39411da177e4SLinus Torvalds 		if ((mbuf[3] < 0x0d) && (rmb == 0)) {
39421da177e4SLinus Torvalds 			j = 0xa0;
39431da177e4SLinus Torvalds 			goto set_syn_ok;
39441da177e4SLinus Torvalds 		}
39451da177e4SLinus Torvalds 		if (mbuf[3] < 0x1a) {
39461da177e4SLinus Torvalds 			j = 0x20;
39471da177e4SLinus Torvalds 			goto set_syn_ok;
39481da177e4SLinus Torvalds 		}
39491da177e4SLinus Torvalds 		if (mbuf[3] < 0x33) {
39501da177e4SLinus Torvalds 			j = 0x40;
39511da177e4SLinus Torvalds 			goto set_syn_ok;
39521da177e4SLinus Torvalds 		}
39531da177e4SLinus Torvalds 		if (mbuf[3] < 0x4c) {
39541da177e4SLinus Torvalds 			j = 0x50;
39551da177e4SLinus Torvalds 			goto set_syn_ok;
39561da177e4SLinus Torvalds 		}
39571da177e4SLinus Torvalds 		j = 0x60;
39581da177e4SLinus Torvalds 	      set_syn_ok:
39591da177e4SLinus Torvalds 		dev->id[c][i].devsp = (dev->id[c][i].devsp & 0x0f) | j;
39601da177e4SLinus Torvalds #ifdef ED_DBGP
39611da177e4SLinus Torvalds 		printk("dev->id[%2d][%2d].devsp = %2x\n",c,i,dev->id[c][i].devsp);
39621da177e4SLinus Torvalds #endif
39631da177e4SLinus Torvalds 	}
39641da177e4SLinus Torvalds 	tmport = wkport + 0x16;
39651da177e4SLinus Torvalds 	outb(0x80, tmport);
39661da177e4SLinus Torvalds }
39671da177e4SLinus Torvalds 
39681da177e4SLinus Torvalds module_init(atp870u_init);
39691da177e4SLinus Torvalds module_exit(atp870u_exit);
39701da177e4SLinus Torvalds 
3971