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