xref: /openbmc/linux/drivers/scsi/atp870u.c (revision 681fa525)
109c434b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  *  Copyright (C) 1997	Wu Ching Chen
41da177e4SLinus Torvalds  *  2.1.x update (C) 1998  Krzysztof G. Baranowski
5fa195afeSAlan Cox  *  2.5.x update (C) 2002  Red Hat
6fa195afeSAlan Cox  *  2.6.x update (C) 2004  Red Hat
71da177e4SLinus Torvalds  *
81da177e4SLinus Torvalds  * Marcelo Tosatti <marcelo@conectiva.com.br> : SMP fixes
91da177e4SLinus Torvalds  *
101da177e4SLinus Torvalds  * Wu Ching Chen : NULL pointer fixes  2000/06/02
111da177e4SLinus Torvalds  *		   support atp876 chip
121da177e4SLinus Torvalds  *		   enable 32 bit fifo transfer
131da177e4SLinus Torvalds  *		   support cdrom & remove device run ultra speed
141da177e4SLinus Torvalds  *		   fix disconnect bug  2000/12/21
151da177e4SLinus Torvalds  *		   support atp880 chip lvd u160 2001/05/15
161da177e4SLinus Torvalds  *		   fix prd table bug 2001/09/12 (7.1)
171da177e4SLinus Torvalds  *
181da177e4SLinus Torvalds  * atp885 support add by ACARD Hao Ping Lian 2005/01/05
191da177e4SLinus Torvalds  */
201da177e4SLinus Torvalds #include <linux/module.h>
211da177e4SLinus Torvalds #include <linux/init.h>
221da177e4SLinus Torvalds #include <linux/interrupt.h>
231da177e4SLinus Torvalds #include <linux/kernel.h>
241da177e4SLinus Torvalds #include <linux/types.h>
251da177e4SLinus Torvalds #include <linux/string.h>
261da177e4SLinus Torvalds #include <linux/ioport.h>
271da177e4SLinus Torvalds #include <linux/delay.h>
281da177e4SLinus Torvalds #include <linux/proc_fs.h>
291da177e4SLinus Torvalds #include <linux/spinlock.h>
301da177e4SLinus Torvalds #include <linux/pci.h>
311da177e4SLinus Torvalds #include <linux/blkdev.h>
32910638aeSMatthias Gehre #include <linux/dma-mapping.h>
335a0e3ad6STejun Heo #include <linux/slab.h>
341da177e4SLinus Torvalds #include <asm/io.h>
351da177e4SLinus Torvalds 
361da177e4SLinus Torvalds #include <scsi/scsi.h>
371da177e4SLinus Torvalds #include <scsi/scsi_cmnd.h>
381da177e4SLinus Torvalds #include <scsi/scsi_device.h>
391da177e4SLinus Torvalds #include <scsi/scsi_host.h>
401da177e4SLinus Torvalds 
411da177e4SLinus Torvalds #include "atp870u.h"
421da177e4SLinus Torvalds 
431da177e4SLinus Torvalds static struct scsi_host_template atp870u_template;
441da177e4SLinus Torvalds static void send_s870(struct atp_unit *dev,unsigned char c);
45bcd5c59fSHannes Reinecke static void atp_is(struct atp_unit *dev, unsigned char c, bool wide_chip,
46bcd5c59fSHannes Reinecke 		   unsigned char lvdmode);
471da177e4SLinus Torvalds 
486a3cebb6SOndrej Zary static inline void atp_writeb_base(struct atp_unit *atp, u8 reg, u8 val)
496a3cebb6SOndrej Zary {
506a3cebb6SOndrej Zary 	outb(val, atp->baseport + reg);
516a3cebb6SOndrej Zary }
526a3cebb6SOndrej Zary 
53d804bb25SOndrej Zary static inline void atp_writew_base(struct atp_unit *atp, u8 reg, u16 val)
54d804bb25SOndrej Zary {
55d804bb25SOndrej Zary 	outw(val, atp->baseport + reg);
56d804bb25SOndrej Zary }
57d804bb25SOndrej Zary 
586a3cebb6SOndrej Zary static inline void atp_writeb_io(struct atp_unit *atp, u8 channel, u8 reg, u8 val)
596a3cebb6SOndrej Zary {
606a3cebb6SOndrej Zary 	outb(val, atp->ioport[channel] + reg);
616a3cebb6SOndrej Zary }
626a3cebb6SOndrej Zary 
636a3cebb6SOndrej Zary static inline void atp_writew_io(struct atp_unit *atp, u8 channel, u8 reg, u16 val)
646a3cebb6SOndrej Zary {
656a3cebb6SOndrej Zary 	outw(val, atp->ioport[channel] + reg);
666a3cebb6SOndrej Zary }
676a3cebb6SOndrej Zary 
686a3cebb6SOndrej Zary static inline void atp_writeb_pci(struct atp_unit *atp, u8 channel, u8 reg, u8 val)
696a3cebb6SOndrej Zary {
706a3cebb6SOndrej Zary 	outb(val, atp->pciport[channel] + reg);
716a3cebb6SOndrej Zary }
726a3cebb6SOndrej Zary 
736a3cebb6SOndrej Zary static inline void atp_writel_pci(struct atp_unit *atp, u8 channel, u8 reg, u32 val)
746a3cebb6SOndrej Zary {
756a3cebb6SOndrej Zary 	outl(val, atp->pciport[channel] + reg);
766a3cebb6SOndrej Zary }
776a3cebb6SOndrej Zary 
786a3cebb6SOndrej Zary static inline u8 atp_readb_base(struct atp_unit *atp, u8 reg)
796a3cebb6SOndrej Zary {
806a3cebb6SOndrej Zary 	return inb(atp->baseport + reg);
816a3cebb6SOndrej Zary }
826a3cebb6SOndrej Zary 
83d804bb25SOndrej Zary static inline u16 atp_readw_base(struct atp_unit *atp, u8 reg)
84d804bb25SOndrej Zary {
85d804bb25SOndrej Zary 	return inw(atp->baseport + reg);
86d804bb25SOndrej Zary }
87d804bb25SOndrej Zary 
88d804bb25SOndrej Zary static inline u32 atp_readl_base(struct atp_unit *atp, u8 reg)
89d804bb25SOndrej Zary {
90d804bb25SOndrej Zary 	return inl(atp->baseport + reg);
91d804bb25SOndrej Zary }
92d804bb25SOndrej Zary 
936a3cebb6SOndrej Zary static inline u8 atp_readb_io(struct atp_unit *atp, u8 channel, u8 reg)
946a3cebb6SOndrej Zary {
956a3cebb6SOndrej Zary 	return inb(atp->ioport[channel] + reg);
966a3cebb6SOndrej Zary }
976a3cebb6SOndrej Zary 
986a3cebb6SOndrej Zary static inline u16 atp_readw_io(struct atp_unit *atp, u8 channel, u8 reg)
996a3cebb6SOndrej Zary {
1006a3cebb6SOndrej Zary 	return inw(atp->ioport[channel] + reg);
1016a3cebb6SOndrej Zary }
1026a3cebb6SOndrej Zary 
1036a3cebb6SOndrej Zary static inline u8 atp_readb_pci(struct atp_unit *atp, u8 channel, u8 reg)
1046a3cebb6SOndrej Zary {
1056a3cebb6SOndrej Zary 	return inb(atp->pciport[channel] + reg);
1066a3cebb6SOndrej Zary }
1076a3cebb6SOndrej Zary 
108b922a449SOndrej Zary static inline bool is880(struct atp_unit *atp)
109b922a449SOndrej Zary {
110b922a449SOndrej Zary 	return atp->pdev->device == ATP880_DEVID1 ||
111b922a449SOndrej Zary 	       atp->pdev->device == ATP880_DEVID2;
112b922a449SOndrej Zary }
113b922a449SOndrej Zary 
114b922a449SOndrej Zary static inline bool is885(struct atp_unit *atp)
115b922a449SOndrej Zary {
116b922a449SOndrej Zary 	return atp->pdev->device == ATP885_DEVID;
117b922a449SOndrej Zary }
118b922a449SOndrej Zary 
1197d12e780SDavid Howells static irqreturn_t atp870u_intr_handle(int irq, void *dev_id)
1201da177e4SLinus Torvalds {
1211da177e4SLinus Torvalds 	unsigned long flags;
122bc0fe4c9SOndrej Zary 	unsigned short int id;
1231da177e4SLinus Torvalds 	unsigned char i, j, c, target_id, lun,cmdp;
1241da177e4SLinus Torvalds 	unsigned char *prd;
1251da177e4SLinus Torvalds 	struct scsi_cmnd *workreq;
1261da177e4SLinus Torvalds 	unsigned long adrcnt, k;
1271da177e4SLinus Torvalds #ifdef ED_DBGP
1281da177e4SLinus Torvalds 	unsigned long l;
1291da177e4SLinus Torvalds #endif
1301da177e4SLinus Torvalds 	struct Scsi_Host *host = dev_id;
1311da177e4SLinus Torvalds 	struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
1321da177e4SLinus Torvalds 
1331da177e4SLinus Torvalds 	for (c = 0; c < 2; c++) {
1346a3cebb6SOndrej Zary 		j = atp_readb_io(dev, c, 0x1f);
1351da177e4SLinus Torvalds 		if ((j & 0x80) != 0)
13678614ecdSOndrej Zary 			break;
1371da177e4SLinus Torvalds 		dev->in_int[c] = 0;
1381da177e4SLinus Torvalds 	}
13978614ecdSOndrej Zary 	if ((j & 0x80) == 0)
1401da177e4SLinus Torvalds 		return IRQ_NONE;
1411da177e4SLinus Torvalds #ifdef ED_DBGP
1421da177e4SLinus Torvalds 	printk("atp870u_intr_handle enter\n");
1431da177e4SLinus Torvalds #endif
1441da177e4SLinus Torvalds 	dev->in_int[c] = 1;
1456a3cebb6SOndrej Zary 	cmdp = atp_readb_io(dev, c, 0x10);
1461da177e4SLinus Torvalds 	if (dev->working[c] != 0) {
147b922a449SOndrej Zary 		if (is885(dev)) {
1486a3cebb6SOndrej Zary 			if ((atp_readb_io(dev, c, 0x16) & 0x80) == 0)
149bcd5c59fSHannes Reinecke 				atp_writeb_io(dev, c, 0x16,
150bcd5c59fSHannes Reinecke 					      (atp_readb_io(dev, c, 0x16) | 0x80));
1511da177e4SLinus Torvalds 		}
1526a3cebb6SOndrej Zary 		if ((atp_readb_pci(dev, c, 0x00) & 0x08) != 0)
1531da177e4SLinus Torvalds 		{
1541da177e4SLinus Torvalds 			for (k=0; k < 1000; k++) {
1556a3cebb6SOndrej Zary 				if ((atp_readb_pci(dev, c, 2) & 0x08) == 0)
15678614ecdSOndrej Zary 					break;
1576a3cebb6SOndrej Zary 				if ((atp_readb_pci(dev, c, 2) & 0x01) == 0)
15878614ecdSOndrej Zary 					break;
1591da177e4SLinus Torvalds 			}
1601da177e4SLinus Torvalds 		}
1616a3cebb6SOndrej Zary 		atp_writeb_pci(dev, c, 0, 0x00);
1621da177e4SLinus Torvalds 
1636a3cebb6SOndrej Zary 		i = atp_readb_io(dev, c, 0x17);
1641da177e4SLinus Torvalds 
165b922a449SOndrej Zary 		if (is885(dev))
1666a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 2, 0x06);
1671da177e4SLinus Torvalds 
1686a3cebb6SOndrej Zary 		target_id = atp_readb_io(dev, c, 0x15);
1691da177e4SLinus Torvalds 
1701da177e4SLinus Torvalds 		/*
1711da177e4SLinus Torvalds 		 *	Remap wide devices onto id numbers
1721da177e4SLinus Torvalds 		 */
1731da177e4SLinus Torvalds 
1741da177e4SLinus Torvalds 		if ((target_id & 0x40) != 0) {
1751da177e4SLinus Torvalds 			target_id = (target_id & 0x07) | 0x08;
1761da177e4SLinus Torvalds 		} else {
1771da177e4SLinus Torvalds 			target_id &= 0x07;
1781da177e4SLinus Torvalds 		}
1791da177e4SLinus Torvalds 
1801da177e4SLinus Torvalds 		if ((j & 0x40) != 0) {
1811da177e4SLinus Torvalds 		     if (dev->last_cmd[c] == 0xff) {
1821da177e4SLinus Torvalds 			dev->last_cmd[c] = target_id;
1831da177e4SLinus Torvalds 		     }
1841da177e4SLinus Torvalds 		     dev->last_cmd[c] |= 0x40;
1851da177e4SLinus Torvalds 		}
186b922a449SOndrej Zary 		if (is885(dev))
1871da177e4SLinus Torvalds 			dev->r1f[c][target_id] |= j;
1881da177e4SLinus Torvalds #ifdef ED_DBGP
1891da177e4SLinus Torvalds 		printk("atp870u_intr_handle status = %x\n",i);
1901da177e4SLinus Torvalds #endif
1911da177e4SLinus Torvalds 		if (i == 0x85) {
1921da177e4SLinus Torvalds 			if ((dev->last_cmd[c] & 0xf0) != 0x40) {
1931da177e4SLinus Torvalds 			   dev->last_cmd[c] = 0xff;
1941da177e4SLinus Torvalds 			}
195b922a449SOndrej Zary 			if (is885(dev)) {
1961da177e4SLinus Torvalds 				adrcnt = 0;
197bcd5c59fSHannes Reinecke 				((unsigned char *) &adrcnt)[2] =
198bcd5c59fSHannes Reinecke 					atp_readb_io(dev, c, 0x12);
199bcd5c59fSHannes Reinecke 				((unsigned char *) &adrcnt)[1] =
200bcd5c59fSHannes Reinecke 					atp_readb_io(dev, c, 0x13);
201bcd5c59fSHannes Reinecke 				((unsigned char *) &adrcnt)[0] =
202bcd5c59fSHannes Reinecke 					atp_readb_io(dev, c, 0x14);
20322c0738bSColin Ian King 				if (dev->id[c][target_id].last_len != adrcnt) {
2041da177e4SLinus Torvalds 					k = dev->id[c][target_id].last_len;
2051da177e4SLinus Torvalds 					k -= adrcnt;
2061da177e4SLinus Torvalds 					dev->id[c][target_id].tran_len = k;
2071da177e4SLinus Torvalds 					dev->id[c][target_id].last_len = adrcnt;
2081da177e4SLinus Torvalds 				}
2091da177e4SLinus Torvalds #ifdef ED_DBGP
210bcd5c59fSHannes Reinecke 				printk("dev->id[c][target_id].last_len = %d "
211bcd5c59fSHannes Reinecke 				       "dev->id[c][target_id].tran_len = %d\n",
212bcd5c59fSHannes Reinecke 				       dev->id[c][target_id].last_len,
213bcd5c59fSHannes Reinecke 				       dev->id[c][target_id].tran_len);
2141da177e4SLinus Torvalds #endif
2151da177e4SLinus Torvalds 			}
2161da177e4SLinus Torvalds 
2171da177e4SLinus Torvalds 			/*
2181da177e4SLinus Torvalds 			 *      Flip wide
2191da177e4SLinus Torvalds 			 */
2201da177e4SLinus Torvalds 			if (dev->wide_id[c] != 0) {
2216a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x1b, 0x01);
2226a3cebb6SOndrej Zary 				while ((atp_readb_io(dev, c, 0x1b) & 0x01) != 0x01)
2236a3cebb6SOndrej Zary 					atp_writeb_io(dev, c, 0x1b, 0x01);
2241da177e4SLinus Torvalds 			}
2251da177e4SLinus Torvalds 			/*
2261da177e4SLinus Torvalds 			 *	Issue more commands
2271da177e4SLinus Torvalds 			 */
2281da177e4SLinus Torvalds 			spin_lock_irqsave(dev->host->host_lock, flags);
229bcd5c59fSHannes Reinecke 			if (((dev->quhd[c] != dev->quend[c]) ||
230bcd5c59fSHannes Reinecke 			     (dev->last_cmd[c] != 0xff)) &&
2311da177e4SLinus Torvalds 			    (dev->in_snd[c] == 0)) {
2321da177e4SLinus Torvalds #ifdef ED_DBGP
2331da177e4SLinus Torvalds 				printk("Call sent_s870\n");
2341da177e4SLinus Torvalds #endif
2351da177e4SLinus Torvalds 				send_s870(dev,c);
2361da177e4SLinus Torvalds 			}
2371da177e4SLinus Torvalds 			spin_unlock_irqrestore(dev->host->host_lock, flags);
2381da177e4SLinus Torvalds 			/*
2391da177e4SLinus Torvalds 			 *	Done
2401da177e4SLinus Torvalds 			 */
2411da177e4SLinus Torvalds 			dev->in_int[c] = 0;
2421da177e4SLinus Torvalds #ifdef ED_DBGP
2431da177e4SLinus Torvalds 				printk("Status 0x85 return\n");
2441da177e4SLinus Torvalds #endif
24578614ecdSOndrej Zary 			return IRQ_HANDLED;
2461da177e4SLinus Torvalds 		}
2471da177e4SLinus Torvalds 
2481da177e4SLinus Torvalds 		if (i == 0x40) {
2491da177e4SLinus Torvalds 		     dev->last_cmd[c] |= 0x40;
2501da177e4SLinus Torvalds 		     dev->in_int[c] = 0;
25178614ecdSOndrej Zary 		     return IRQ_HANDLED;
2521da177e4SLinus Torvalds 		}
2531da177e4SLinus Torvalds 
2541da177e4SLinus Torvalds 		if (i == 0x21) {
2551da177e4SLinus Torvalds 			if ((dev->last_cmd[c] & 0xf0) != 0x40) {
2561da177e4SLinus Torvalds 			   dev->last_cmd[c] = 0xff;
2571da177e4SLinus Torvalds 			}
2581da177e4SLinus Torvalds 			adrcnt = 0;
259bcd5c59fSHannes Reinecke 			((unsigned char *) &adrcnt)[2] =
260bcd5c59fSHannes Reinecke 				atp_readb_io(dev, c, 0x12);
261bcd5c59fSHannes Reinecke 			((unsigned char *) &adrcnt)[1] =
262bcd5c59fSHannes Reinecke 				atp_readb_io(dev, c, 0x13);
263bcd5c59fSHannes Reinecke 			((unsigned char *) &adrcnt)[0] =
264bcd5c59fSHannes Reinecke 				atp_readb_io(dev, c, 0x14);
2651da177e4SLinus Torvalds 			k = dev->id[c][target_id].last_len;
2661da177e4SLinus Torvalds 			k -= adrcnt;
2671da177e4SLinus Torvalds 			dev->id[c][target_id].tran_len = k;
2681da177e4SLinus Torvalds 			dev->id[c][target_id].last_len = adrcnt;
2696a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x10, 0x41);
2706a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x18, 0x08);
2711da177e4SLinus Torvalds 			dev->in_int[c] = 0;
27278614ecdSOndrej Zary 			return IRQ_HANDLED;
2731da177e4SLinus Torvalds 		}
2741da177e4SLinus Torvalds 
275b922a449SOndrej Zary 		if (is885(dev)) {
2761da177e4SLinus Torvalds 			if ((i == 0x4c) || (i == 0x4d) || (i == 0x8c) || (i == 0x8d)) {
2771da177e4SLinus Torvalds 				if ((i == 0x4c) || (i == 0x8c))
2781da177e4SLinus Torvalds 					i=0x48;
2791da177e4SLinus Torvalds 				else
2801da177e4SLinus Torvalds 					i=0x49;
2811da177e4SLinus Torvalds 			}
2821da177e4SLinus Torvalds 		}
2831da177e4SLinus Torvalds 		if ((i == 0x80) || (i == 0x8f)) {
2841da177e4SLinus Torvalds #ifdef ED_DBGP
2851da177e4SLinus Torvalds 			printk(KERN_DEBUG "Device reselect\n");
2861da177e4SLinus Torvalds #endif
2871da177e4SLinus Torvalds 			lun = 0;
2886a3cebb6SOndrej Zary 			if (cmdp == 0x44 || i == 0x80)
2896a3cebb6SOndrej Zary 				lun = atp_readb_io(dev, c, 0x1d) & 0x07;
2906a3cebb6SOndrej Zary 			else {
2911da177e4SLinus Torvalds 				if ((dev->last_cmd[c] & 0xf0) != 0x40) {
2921da177e4SLinus Torvalds 				   dev->last_cmd[c] = 0xff;
2931da177e4SLinus Torvalds 				}
2941da177e4SLinus Torvalds 				if (cmdp == 0x41) {
2951da177e4SLinus Torvalds #ifdef ED_DBGP
2961da177e4SLinus Torvalds 					printk("cmdp = 0x41\n");
2971da177e4SLinus Torvalds #endif
2981da177e4SLinus Torvalds 					adrcnt = 0;
299bcd5c59fSHannes Reinecke 					((unsigned char *) &adrcnt)[2] =
300bcd5c59fSHannes Reinecke 						atp_readb_io(dev, c, 0x12);
301bcd5c59fSHannes Reinecke 					((unsigned char *) &adrcnt)[1] =
302bcd5c59fSHannes Reinecke 						atp_readb_io(dev, c, 0x13);
303bcd5c59fSHannes Reinecke 					((unsigned char *) &adrcnt)[0] =
304bcd5c59fSHannes Reinecke 						atp_readb_io(dev, c, 0x14);
3051da177e4SLinus Torvalds 					k = dev->id[c][target_id].last_len;
3061da177e4SLinus Torvalds 					k -= adrcnt;
3071da177e4SLinus Torvalds 					dev->id[c][target_id].tran_len = k;
3081da177e4SLinus Torvalds 					dev->id[c][target_id].last_len = adrcnt;
3096a3cebb6SOndrej Zary 					atp_writeb_io(dev, c, 0x18, 0x08);
3101da177e4SLinus Torvalds 					dev->in_int[c] = 0;
31178614ecdSOndrej Zary 					return IRQ_HANDLED;
3121da177e4SLinus Torvalds 				} else {
3131da177e4SLinus Torvalds #ifdef ED_DBGP
3141da177e4SLinus Torvalds 					printk("cmdp != 0x41\n");
3151da177e4SLinus Torvalds #endif
3166a3cebb6SOndrej Zary 					atp_writeb_io(dev, c, 0x10, 0x46);
3171da177e4SLinus Torvalds 					dev->id[c][target_id].dirct = 0x00;
3186a3cebb6SOndrej Zary 					atp_writeb_io(dev, c, 0x12, 0x00);
3196a3cebb6SOndrej Zary 					atp_writeb_io(dev, c, 0x13, 0x00);
3206a3cebb6SOndrej Zary 					atp_writeb_io(dev, c, 0x14, 0x00);
3216a3cebb6SOndrej Zary 					atp_writeb_io(dev, c, 0x18, 0x08);
3221da177e4SLinus Torvalds 					dev->in_int[c] = 0;
32378614ecdSOndrej Zary 					return IRQ_HANDLED;
3241da177e4SLinus Torvalds 				}
3251da177e4SLinus Torvalds 			}
3261da177e4SLinus Torvalds 			if (dev->last_cmd[c] != 0xff) {
3271da177e4SLinus Torvalds 			   dev->last_cmd[c] |= 0x40;
3281da177e4SLinus Torvalds 			}
329b922a449SOndrej Zary 			if (is885(dev)) {
3306a3cebb6SOndrej Zary 				j = atp_readb_base(dev, 0x29) & 0xfe;
3316a3cebb6SOndrej Zary 				atp_writeb_base(dev, 0x29, j);
3323a38e53eSOndrej Zary 			} else
3336a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x10, 0x45);
3341da177e4SLinus Torvalds 
3356a3cebb6SOndrej Zary 			target_id = atp_readb_io(dev, c, 0x16);
3361da177e4SLinus Torvalds 			/*
3371da177e4SLinus Torvalds 			 *	Remap wide identifiers
3381da177e4SLinus Torvalds 			 */
3391da177e4SLinus Torvalds 			if ((target_id & 0x10) != 0) {
3401da177e4SLinus Torvalds 				target_id = (target_id & 0x07) | 0x08;
3411da177e4SLinus Torvalds 			} else {
3421da177e4SLinus Torvalds 				target_id &= 0x07;
3431da177e4SLinus Torvalds 			}
344b922a449SOndrej Zary 			if (is885(dev))
3456a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x10, 0x45);
3461da177e4SLinus Torvalds 			workreq = dev->id[c][target_id].curr_req;
3471da177e4SLinus Torvalds #ifdef ED_DBGP
348017560fcSJeff Garzik 			scmd_printk(KERN_DEBUG, workreq, "CDB");
3491da177e4SLinus Torvalds 			for (l = 0; l < workreq->cmd_len; l++)
3501da177e4SLinus Torvalds 				printk(KERN_DEBUG " %x",workreq->cmnd[l]);
351017560fcSJeff Garzik 			printk("\n");
3521da177e4SLinus Torvalds #endif
3531da177e4SLinus Torvalds 
3546a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x0f, lun);
3556a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x11, dev->id[c][target_id].devsp);
3561da177e4SLinus Torvalds 			adrcnt = dev->id[c][target_id].tran_len;
3571da177e4SLinus Torvalds 			k = dev->id[c][target_id].last_len;
3581da177e4SLinus Torvalds 
3596a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x12, ((unsigned char *) &k)[2]);
3606a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x13, ((unsigned char *) &k)[1]);
3616a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x14, ((unsigned char *) &k)[0]);
3621da177e4SLinus Torvalds #ifdef ED_DBGP
363bcd5c59fSHannes Reinecke 			printk("k %x, k[0] 0x%x k[1] 0x%x k[2] 0x%x\n", k,
364bcd5c59fSHannes Reinecke 			       atp_readb_io(dev, c, 0x14),
365bcd5c59fSHannes Reinecke 			       atp_readb_io(dev, c, 0x13),
366bcd5c59fSHannes Reinecke 			       atp_readb_io(dev, c, 0x12));
3671da177e4SLinus Torvalds #endif
3681da177e4SLinus Torvalds 			/* Remap wide */
3691da177e4SLinus Torvalds 			j = target_id;
3701da177e4SLinus Torvalds 			if (target_id > 7) {
3711da177e4SLinus Torvalds 				j = (j & 0x07) | 0x40;
3721da177e4SLinus Torvalds 			}
3731da177e4SLinus Torvalds 			/* Add direction */
3741da177e4SLinus Torvalds 			j |= dev->id[c][target_id].dirct;
3756a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x15, j);
3766a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x16, 0x80);
3771da177e4SLinus Torvalds 
3781da177e4SLinus Torvalds 			/* enable 32 bit fifo transfer */
379b922a449SOndrej Zary 			if (is885(dev)) {
3806a3cebb6SOndrej Zary 				i = atp_readb_pci(dev, c, 1) & 0xf3;
3811da177e4SLinus Torvalds 				//j=workreq->cmnd[0];
382f3272258SHannes Reinecke 				if ((workreq->cmnd[0] == READ_6) ||
383f3272258SHannes Reinecke 				    (workreq->cmnd[0] == READ_10) ||
384f3272258SHannes Reinecke 				    (workreq->cmnd[0] == WRITE_6) ||
385f3272258SHannes Reinecke 				    (workreq->cmnd[0] == WRITE_10)) {
3861da177e4SLinus Torvalds 				   i |= 0x0c;
3871da177e4SLinus Torvalds 				}
3886a3cebb6SOndrej Zary 				atp_writeb_pci(dev, c, 1, i);
389b922a449SOndrej Zary 			} else if (is880(dev)) {
390f3272258SHannes Reinecke 				if ((workreq->cmnd[0] == READ_6) ||
391f3272258SHannes Reinecke 				    (workreq->cmnd[0] == READ_10) ||
392f3272258SHannes Reinecke 				    (workreq->cmnd[0] == WRITE_6) ||
393f3272258SHannes Reinecke 				    (workreq->cmnd[0] == WRITE_10))
394bcd5c59fSHannes Reinecke 					atp_writeb_base(dev, 0x3b,
395bcd5c59fSHannes Reinecke 							(atp_readb_base(dev, 0x3b) & 0x3f) | 0xc0);
3966a3cebb6SOndrej Zary 				else
397bcd5c59fSHannes Reinecke 					atp_writeb_base(dev, 0x3b,
398bcd5c59fSHannes Reinecke 							atp_readb_base(dev, 0x3b) & 0x3f);
3991da177e4SLinus Torvalds 			} else {
400f3272258SHannes Reinecke 				if ((workreq->cmnd[0] == READ_6) ||
401f3272258SHannes Reinecke 				    (workreq->cmnd[0] == READ_10) ||
402f3272258SHannes Reinecke 				    (workreq->cmnd[0] == WRITE_6) ||
403f3272258SHannes Reinecke 				    (workreq->cmnd[0] == WRITE_10))
404bcd5c59fSHannes Reinecke 					atp_writeb_base(dev, 0x3a,
405bcd5c59fSHannes Reinecke 							(atp_readb_base(dev, 0x3a) & 0xf3) | 0x08);
4066a3cebb6SOndrej Zary 				else
407bcd5c59fSHannes Reinecke 					atp_writeb_base(dev, 0x3a,
408bcd5c59fSHannes Reinecke 							atp_readb_base(dev, 0x3a) & 0xf3);
4091da177e4SLinus Torvalds 			}
4101da177e4SLinus Torvalds 			j = 0;
4111da177e4SLinus Torvalds 			id = 1;
4121da177e4SLinus Torvalds 			id = id << target_id;
4131da177e4SLinus Torvalds 			/*
4141da177e4SLinus Torvalds 			 *	Is this a wide device
4151da177e4SLinus Torvalds 			 */
4161da177e4SLinus Torvalds 			if ((id & dev->wide_id[c]) != 0) {
4171da177e4SLinus Torvalds 				j |= 0x01;
4181da177e4SLinus Torvalds 			}
4196a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x1b, j);
4206a3cebb6SOndrej Zary 			while ((atp_readb_io(dev, c, 0x1b) & 0x01) != j)
4216a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x1b, j);
4221da177e4SLinus Torvalds 			if (dev->id[c][target_id].last_len == 0) {
4236a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x18, 0x08);
4241da177e4SLinus Torvalds 				dev->in_int[c] = 0;
4251da177e4SLinus Torvalds #ifdef ED_DBGP
4261da177e4SLinus Torvalds 				printk("dev->id[c][target_id].last_len = 0\n");
4271da177e4SLinus Torvalds #endif
42878614ecdSOndrej Zary 				return IRQ_HANDLED;
4291da177e4SLinus Torvalds 			}
4301da177e4SLinus Torvalds #ifdef ED_DBGP
4311da177e4SLinus Torvalds 			printk("target_id = %d adrcnt = %d\n",target_id,adrcnt);
4321da177e4SLinus Torvalds #endif
4331da177e4SLinus Torvalds 			prd = dev->id[c][target_id].prd_pos;
4341da177e4SLinus Torvalds 			while (adrcnt != 0) {
4351da177e4SLinus Torvalds 				id = ((unsigned short int *)prd)[2];
4361da177e4SLinus Torvalds 				if (id == 0) {
4371da177e4SLinus Torvalds 					k = 0x10000;
4381da177e4SLinus Torvalds 				} else {
4391da177e4SLinus Torvalds 					k = id;
4401da177e4SLinus Torvalds 				}
4411da177e4SLinus Torvalds 				if (k > adrcnt) {
442bcd5c59fSHannes Reinecke 					((unsigned short int *)prd)[2] =
443bcd5c59fSHannes Reinecke 						(unsigned short int)(k - adrcnt);
4441da177e4SLinus Torvalds 					((unsigned long *)prd)[0] += adrcnt;
4451da177e4SLinus Torvalds 					adrcnt = 0;
4461da177e4SLinus Torvalds 					dev->id[c][target_id].prd_pos = prd;
4471da177e4SLinus Torvalds 				} else {
4481da177e4SLinus Torvalds 					adrcnt -= k;
4491da177e4SLinus Torvalds 					dev->id[c][target_id].prdaddr += 0x08;
4501da177e4SLinus Torvalds 					prd += 0x08;
4511da177e4SLinus Torvalds 					if (adrcnt == 0) {
4521da177e4SLinus Torvalds 						dev->id[c][target_id].prd_pos = prd;
4531da177e4SLinus Torvalds 					}
4541da177e4SLinus Torvalds 				}
4551da177e4SLinus Torvalds 			}
4566a3cebb6SOndrej Zary 			atp_writel_pci(dev, c, 0x04, dev->id[c][target_id].prdaddr);
4571da177e4SLinus Torvalds #ifdef ED_DBGP
458bcd5c59fSHannes Reinecke 			printk("dev->id[%d][%d].prdaddr 0x%8x\n",
459bcd5c59fSHannes Reinecke 			       c, target_id, dev->id[c][target_id].prdaddr);
4601da177e4SLinus Torvalds #endif
461b922a449SOndrej Zary 			if (!is885(dev)) {
4626a3cebb6SOndrej Zary 				atp_writeb_pci(dev, c, 2, 0x06);
4636a3cebb6SOndrej Zary 				atp_writeb_pci(dev, c, 2, 0x00);
4641da177e4SLinus Torvalds 			}
4651da177e4SLinus Torvalds 			/*
4661da177e4SLinus Torvalds 			 *	Check transfer direction
4671da177e4SLinus Torvalds 			 */
4681da177e4SLinus Torvalds 			if (dev->id[c][target_id].dirct != 0) {
4696a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x18, 0x08);
4706a3cebb6SOndrej Zary 				atp_writeb_pci(dev, c, 0, 0x01);
4711da177e4SLinus Torvalds 				dev->in_int[c] = 0;
4721da177e4SLinus Torvalds #ifdef ED_DBGP
4731da177e4SLinus Torvalds 				printk("status 0x80 return dirct != 0\n");
4741da177e4SLinus Torvalds #endif
47578614ecdSOndrej Zary 				return IRQ_HANDLED;
4761da177e4SLinus Torvalds 			}
4776a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x18, 0x08);
4786a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 0, 0x09);
4791da177e4SLinus Torvalds 			dev->in_int[c] = 0;
4801da177e4SLinus Torvalds #ifdef ED_DBGP
4811da177e4SLinus Torvalds 			printk("status 0x80 return dirct = 0\n");
4821da177e4SLinus Torvalds #endif
48378614ecdSOndrej Zary 			return IRQ_HANDLED;
4841da177e4SLinus Torvalds 		}
4851da177e4SLinus Torvalds 
4861da177e4SLinus Torvalds 		/*
4871da177e4SLinus Torvalds 		 *	Current scsi request on this target
4881da177e4SLinus Torvalds 		 */
4891da177e4SLinus Torvalds 
4901da177e4SLinus Torvalds 		workreq = dev->id[c][target_id].curr_req;
4911da177e4SLinus Torvalds 
49278614ecdSOndrej Zary 		if (i == 0x42 || i == 0x16) {
4931da177e4SLinus Torvalds 			if ((dev->last_cmd[c] & 0xf0) != 0x40) {
4941da177e4SLinus Torvalds 			   dev->last_cmd[c] = 0xff;
4951da177e4SLinus Torvalds 			}
49678614ecdSOndrej Zary 			if (i == 0x16) {
4976a3cebb6SOndrej Zary 				workreq->result = atp_readb_io(dev, c, 0x0f);
498b922a449SOndrej Zary 				if (((dev->r1f[c][target_id] & 0x10) != 0) && is885(dev)) {
4991da177e4SLinus Torvalds 					printk(KERN_WARNING "AEC67162 CRC ERROR !\n");
500f3272258SHannes Reinecke 					workreq->result = SAM_STAT_CHECK_CONDITION;
5011da177e4SLinus Torvalds 				}
50278614ecdSOndrej Zary 			} else
503f3272258SHannes Reinecke 				workreq->result = SAM_STAT_CHECK_CONDITION;
50478614ecdSOndrej Zary 
505b922a449SOndrej Zary 			if (is885(dev)) {
5066a3cebb6SOndrej Zary 				j = atp_readb_base(dev, 0x29) | 0x01;
5076a3cebb6SOndrej Zary 				atp_writeb_base(dev, 0x29, j);
5081da177e4SLinus Torvalds 			}
5091da177e4SLinus Torvalds 			/*
5101da177e4SLinus Torvalds 			 *	Complete the command
5111da177e4SLinus Torvalds 			 */
512fe7ed98fSBoaz Harrosh 			scsi_dma_unmap(workreq);
513fe7ed98fSBoaz Harrosh 
5141da177e4SLinus Torvalds 			spin_lock_irqsave(dev->host->host_lock, flags);
515*681fa525SBart Van Assche 			scsi_done(workreq);
5161da177e4SLinus Torvalds #ifdef ED_DBGP
5171da177e4SLinus Torvalds 			   printk("workreq->scsi_done\n");
5181da177e4SLinus Torvalds #endif
5191da177e4SLinus Torvalds 			/*
5201da177e4SLinus Torvalds 			 *	Clear it off the queue
5211da177e4SLinus Torvalds 			 */
5221da177e4SLinus Torvalds 			dev->id[c][target_id].curr_req = NULL;
5231da177e4SLinus Torvalds 			dev->working[c]--;
5241da177e4SLinus Torvalds 			spin_unlock_irqrestore(dev->host->host_lock, flags);
5251da177e4SLinus Torvalds 			/*
5261da177e4SLinus Torvalds 			 *      Take it back wide
5271da177e4SLinus Torvalds 			 */
5281da177e4SLinus Torvalds 			if (dev->wide_id[c] != 0) {
5296a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x1b, 0x01);
5306a3cebb6SOndrej Zary 				while ((atp_readb_io(dev, c, 0x1b) & 0x01) != 0x01)
5316a3cebb6SOndrej Zary 					atp_writeb_io(dev, c, 0x1b, 0x01);
5321da177e4SLinus Torvalds 			}
5331da177e4SLinus Torvalds 			/*
5341da177e4SLinus Torvalds 			 *	If there is stuff to send and nothing going then send it
5351da177e4SLinus Torvalds 			 */
5361da177e4SLinus Torvalds 			spin_lock_irqsave(dev->host->host_lock, flags);
537bcd5c59fSHannes Reinecke 			if (((dev->last_cmd[c] != 0xff) ||
538bcd5c59fSHannes Reinecke 			     (dev->quhd[c] != dev->quend[c])) &&
5391da177e4SLinus Torvalds 			    (dev->in_snd[c] == 0)) {
5401da177e4SLinus Torvalds #ifdef ED_DBGP
5411da177e4SLinus Torvalds 			   printk("Call sent_s870(scsi_done)\n");
5421da177e4SLinus Torvalds #endif
5431da177e4SLinus Torvalds 			   send_s870(dev,c);
5441da177e4SLinus Torvalds 			}
5451da177e4SLinus Torvalds 			spin_unlock_irqrestore(dev->host->host_lock, flags);
5461da177e4SLinus Torvalds 			dev->in_int[c] = 0;
54778614ecdSOndrej Zary 			return IRQ_HANDLED;
5481da177e4SLinus Torvalds 		}
5491da177e4SLinus Torvalds 		if ((dev->last_cmd[c] & 0xf0) != 0x40) {
5501da177e4SLinus Torvalds 		   dev->last_cmd[c] = 0xff;
5511da177e4SLinus Torvalds 		}
5521da177e4SLinus Torvalds 		if (i == 0x4f) {
5531da177e4SLinus Torvalds 			i = 0x89;
5541da177e4SLinus Torvalds 		}
5551da177e4SLinus Torvalds 		i &= 0x0f;
5561da177e4SLinus Torvalds 		if (i == 0x09) {
5576a3cebb6SOndrej Zary 			atp_writel_pci(dev, c, 4, dev->id[c][target_id].prdaddr);
5586a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 2, 0x06);
5596a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 2, 0x00);
5606a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x10, 0x41);
561b922a449SOndrej Zary 			if (is885(dev)) {
5621da177e4SLinus Torvalds 				k = dev->id[c][target_id].last_len;
563bcd5c59fSHannes Reinecke 				atp_writeb_io(dev, c, 0x12,
564bcd5c59fSHannes Reinecke 					      ((unsigned char *) (&k))[2]);
565bcd5c59fSHannes Reinecke 				atp_writeb_io(dev, c, 0x13,
566bcd5c59fSHannes Reinecke 					      ((unsigned char *) (&k))[1]);
567bcd5c59fSHannes Reinecke 				atp_writeb_io(dev, c, 0x14,
568bcd5c59fSHannes Reinecke 					      ((unsigned char *) (&k))[0]);
5691da177e4SLinus Torvalds 				dev->id[c][target_id].dirct = 0x00;
5701da177e4SLinus Torvalds 			} else {
5711da177e4SLinus Torvalds 				dev->id[c][target_id].dirct = 0x00;
5721da177e4SLinus Torvalds 			}
5736a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x18, 0x08);
5746a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 0, 0x09);
5751da177e4SLinus Torvalds 			dev->in_int[c] = 0;
57678614ecdSOndrej Zary 			return IRQ_HANDLED;
5771da177e4SLinus Torvalds 		}
5781da177e4SLinus Torvalds 		if (i == 0x08) {
5796a3cebb6SOndrej Zary 			atp_writel_pci(dev, c, 4, dev->id[c][target_id].prdaddr);
5806a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 2, 0x06);
5816a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 2, 0x00);
5826a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x10, 0x41);
583b922a449SOndrej Zary 			if (is885(dev)) {
5841da177e4SLinus Torvalds 				k = dev->id[c][target_id].last_len;
585bcd5c59fSHannes Reinecke 				atp_writeb_io(dev, c, 0x12,
586bcd5c59fSHannes Reinecke 					      ((unsigned char *) (&k))[2]);
587bcd5c59fSHannes Reinecke 				atp_writeb_io(dev, c, 0x13,
588bcd5c59fSHannes Reinecke 					      ((unsigned char *) (&k))[1]);
589bcd5c59fSHannes Reinecke 				atp_writeb_io(dev, c, 0x14,
590bcd5c59fSHannes Reinecke 					      ((unsigned char *) (&k))[0]);
5911da177e4SLinus Torvalds 			}
592bcd5c59fSHannes Reinecke 			atp_writeb_io(dev, c, 0x15,
593bcd5c59fSHannes Reinecke 				      atp_readb_io(dev, c, 0x15) | 0x20);
5941da177e4SLinus Torvalds 			dev->id[c][target_id].dirct = 0x20;
5956a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x18, 0x08);
5966a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 0, 0x01);
5971da177e4SLinus Torvalds 			dev->in_int[c] = 0;
59878614ecdSOndrej Zary 			return IRQ_HANDLED;
5991da177e4SLinus Torvalds 		}
6006a3cebb6SOndrej Zary 		if (i == 0x0a)
6016a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x10, 0x30);
6026a3cebb6SOndrej Zary 		else
6036a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x10, 0x46);
6041da177e4SLinus Torvalds 		dev->id[c][target_id].dirct = 0x00;
6056a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0x00);
6066a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x13, 0x00);
6076a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x00);
6086a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
6091da177e4SLinus Torvalds 	}
61078614ecdSOndrej Zary 	dev->in_int[c] = 0;
6111da177e4SLinus Torvalds 
6121da177e4SLinus Torvalds 	return IRQ_HANDLED;
6131da177e4SLinus Torvalds }
6141da177e4SLinus Torvalds /**
6156b71f60cSLee Jones  *	atp870u_queuecommand_lck -	Queue SCSI command
6161da177e4SLinus Torvalds  *	@req_p: request block
6171da177e4SLinus Torvalds  *	@done: completion function
6181da177e4SLinus Torvalds  *
6191da177e4SLinus Torvalds  *	Queue a command to the ATP queue. Called with the host lock held.
6201da177e4SLinus Torvalds  */
621f281233dSJeff Garzik static int atp870u_queuecommand_lck(struct scsi_cmnd *req_p,
6221da177e4SLinus Torvalds 			 void (*done) (struct scsi_cmnd *))
6231da177e4SLinus Torvalds {
6241da177e4SLinus Torvalds 	unsigned char c;
6253b836464SOndrej Zary 	unsigned int m;
6261da177e4SLinus Torvalds 	struct atp_unit *dev;
6271da177e4SLinus Torvalds 	struct Scsi_Host *host;
6281da177e4SLinus Torvalds 
629422c0d61SJeff Garzik 	c = scmd_channel(req_p);
6301da177e4SLinus Torvalds 	req_p->sense_buffer[0]=0;
631fe7ed98fSBoaz Harrosh 	scsi_set_resid(req_p, 0);
632422c0d61SJeff Garzik 	if (scmd_channel(req_p) > 1) {
633f3272258SHannes Reinecke 		req_p->result = DID_BAD_TARGET << 16;
6341da177e4SLinus Torvalds 		done(req_p);
6351da177e4SLinus Torvalds #ifdef ED_DBGP
6361da177e4SLinus Torvalds 		printk("atp870u_queuecommand : req_p->device->channel > 1\n");
6371da177e4SLinus Torvalds #endif
6381da177e4SLinus Torvalds 		return 0;
6391da177e4SLinus Torvalds 	}
6401da177e4SLinus Torvalds 
6411da177e4SLinus Torvalds 	host = req_p->device->host;
6421da177e4SLinus Torvalds 	dev = (struct atp_unit *)&host->hostdata;
6431da177e4SLinus Torvalds 
6441da177e4SLinus Torvalds 	m = 1;
645422c0d61SJeff Garzik 	m = m << scmd_id(req_p);
6461da177e4SLinus Torvalds 
6471da177e4SLinus Torvalds 	/*
6481da177e4SLinus Torvalds 	 *      Fake a timeout for missing targets
6491da177e4SLinus Torvalds 	 */
6501da177e4SLinus Torvalds 
6511da177e4SLinus Torvalds 	if ((m & dev->active_id[c]) == 0) {
652f3272258SHannes Reinecke 		req_p->result = DID_BAD_TARGET << 16;
6531da177e4SLinus Torvalds 		done(req_p);
6541da177e4SLinus Torvalds 		return 0;
6551da177e4SLinus Torvalds 	}
6561da177e4SLinus Torvalds 
6571da177e4SLinus Torvalds 	/*
6581da177e4SLinus Torvalds 	 *	Count new command
6591da177e4SLinus Torvalds 	 */
6601da177e4SLinus Torvalds 	dev->quend[c]++;
6611da177e4SLinus Torvalds 	if (dev->quend[c] >= qcnt) {
6621da177e4SLinus Torvalds 		dev->quend[c] = 0;
6631da177e4SLinus Torvalds 	}
6641da177e4SLinus Torvalds 
6651da177e4SLinus Torvalds 	/*
6661da177e4SLinus Torvalds 	 *	Check queue state
6671da177e4SLinus Torvalds 	 */
6681da177e4SLinus Torvalds 	if (dev->quhd[c] == dev->quend[c]) {
6691da177e4SLinus Torvalds 		if (dev->quend[c] == 0) {
6701da177e4SLinus Torvalds 			dev->quend[c] = qcnt;
6711da177e4SLinus Torvalds 		}
6721da177e4SLinus Torvalds #ifdef ED_DBGP
6731da177e4SLinus Torvalds 		printk("atp870u_queuecommand : dev->quhd[c] == dev->quend[c]\n");
6741da177e4SLinus Torvalds #endif
6751da177e4SLinus Torvalds 		dev->quend[c]--;
676f3272258SHannes Reinecke 		req_p->result = DID_BUS_BUSY << 16;
6771da177e4SLinus Torvalds 		done(req_p);
6781da177e4SLinus Torvalds 		return 0;
6791da177e4SLinus Torvalds 	}
6801da177e4SLinus Torvalds 	dev->quereq[c][dev->quend[c]] = req_p;
6811da177e4SLinus Torvalds #ifdef ED_DBGP
682bcd5c59fSHannes Reinecke 	printk("dev->ioport[c] = %x atp_readb_io(dev, c, 0x1c) = %x "
683bcd5c59fSHannes Reinecke 	       "dev->in_int[%d] = %d dev->in_snd[%d] = %d\n",
684bcd5c59fSHannes Reinecke 	       dev->ioport[c], atp_readb_io(dev, c, 0x1c), c,
685bcd5c59fSHannes Reinecke 	       dev->in_int[c],c,dev->in_snd[c]);
6861da177e4SLinus Torvalds #endif
687bcd5c59fSHannes Reinecke 	if ((atp_readb_io(dev, c, 0x1c) == 0) &&
688bcd5c59fSHannes Reinecke 	    (dev->in_int[c] == 0) &&
689bcd5c59fSHannes Reinecke 	    (dev->in_snd[c] == 0)) {
6901da177e4SLinus Torvalds #ifdef ED_DBGP
6911da177e4SLinus Torvalds 		printk("Call sent_s870(atp870u_queuecommand)\n");
6921da177e4SLinus Torvalds #endif
6931da177e4SLinus Torvalds 		send_s870(dev,c);
6941da177e4SLinus Torvalds 	}
6951da177e4SLinus Torvalds #ifdef ED_DBGP
6961da177e4SLinus Torvalds 	printk("atp870u_queuecommand : exit\n");
6971da177e4SLinus Torvalds #endif
6981da177e4SLinus Torvalds 	return 0;
6991da177e4SLinus Torvalds }
7001da177e4SLinus Torvalds 
701f281233dSJeff Garzik static DEF_SCSI_QCMD(atp870u_queuecommand)
702f281233dSJeff Garzik 
7036b71f60cSLee Jones /*
7041da177e4SLinus Torvalds  *	send_s870	-	send a command to the controller
7051da177e4SLinus Torvalds  *
7061da177e4SLinus Torvalds  *	On entry there is work queued to be done. We move some of that work to the
7071da177e4SLinus Torvalds  *	controller itself.
7081da177e4SLinus Torvalds  *
7091da177e4SLinus Torvalds  *	Caller holds the host lock.
7101da177e4SLinus Torvalds  */
7111da177e4SLinus Torvalds static void send_s870(struct atp_unit *dev, unsigned char c)
7121da177e4SLinus Torvalds {
713468b8968SOndrej Zary 	struct scsi_cmnd *workreq = NULL;
7141da177e4SLinus Torvalds 	unsigned int i;//,k;
7151da177e4SLinus Torvalds 	unsigned char  j, target_id;
7161da177e4SLinus Torvalds 	unsigned char *prd;
717c2bab403SOndrej Zary 	unsigned short int w;
7181da177e4SLinus Torvalds 	unsigned long l, bttl = 0;
7191da177e4SLinus Torvalds 	unsigned long  sg_count;
7201da177e4SLinus Torvalds 
7211da177e4SLinus Torvalds 	if (dev->in_snd[c] != 0) {
7221da177e4SLinus Torvalds #ifdef ED_DBGP
7231da177e4SLinus Torvalds 		printk("cmnd in_snd\n");
7241da177e4SLinus Torvalds #endif
7251da177e4SLinus Torvalds 		return;
7261da177e4SLinus Torvalds 	}
7271da177e4SLinus Torvalds #ifdef ED_DBGP
7281da177e4SLinus Torvalds 	printk("Sent_s870 enter\n");
7291da177e4SLinus Torvalds #endif
7301da177e4SLinus Torvalds 	dev->in_snd[c] = 1;
7311da177e4SLinus Torvalds 	if ((dev->last_cmd[c] != 0xff) && ((dev->last_cmd[c] & 0x40) != 0)) {
7321da177e4SLinus Torvalds 		dev->last_cmd[c] &= 0x0f;
7331da177e4SLinus Torvalds 		workreq = dev->id[c][dev->last_cmd[c]].curr_req;
734468b8968SOndrej Zary 		if (!workreq) {
7351da177e4SLinus Torvalds 			dev->last_cmd[c] = 0xff;
7361da177e4SLinus Torvalds 			if (dev->quhd[c] == dev->quend[c]) {
7371da177e4SLinus Torvalds 				dev->in_snd[c] = 0;
7381da177e4SLinus Torvalds 				return;
7391da177e4SLinus Torvalds 			}
7401da177e4SLinus Torvalds 		}
741468b8968SOndrej Zary 	}
742468b8968SOndrej Zary 	if (!workreq) {
7431da177e4SLinus Torvalds 		if ((dev->last_cmd[c] != 0xff) && (dev->working[c] != 0)) {
7441da177e4SLinus Torvalds 			dev->in_snd[c] = 0;
7451da177e4SLinus Torvalds 			return;
7461da177e4SLinus Torvalds 		}
7471da177e4SLinus Torvalds 		dev->working[c]++;
7481da177e4SLinus Torvalds 		j = dev->quhd[c];
7491da177e4SLinus Torvalds 		dev->quhd[c]++;
750468b8968SOndrej Zary 		if (dev->quhd[c] >= qcnt)
7511da177e4SLinus Torvalds 			dev->quhd[c] = 0;
7521da177e4SLinus Torvalds 		workreq = dev->quereq[c][dev->quhd[c]];
753468b8968SOndrej Zary 		if (dev->id[c][scmd_id(workreq)].curr_req != NULL) {
7541da177e4SLinus Torvalds 			dev->quhd[c] = j;
7551da177e4SLinus Torvalds 			dev->working[c]--;
7561da177e4SLinus Torvalds 			dev->in_snd[c] = 0;
7571da177e4SLinus Torvalds 			return;
7581da177e4SLinus Torvalds 		}
759468b8968SOndrej Zary 		dev->id[c][scmd_id(workreq)].curr_req = workreq;
760468b8968SOndrej Zary 		dev->last_cmd[c] = scmd_id(workreq);
7611da177e4SLinus Torvalds 	}
762bcd5c59fSHannes Reinecke 	if ((atp_readb_io(dev, c, 0x1f) & 0xb0) != 0 ||
763bcd5c59fSHannes Reinecke 	    atp_readb_io(dev, c, 0x1c) != 0) {
7641da177e4SLinus Torvalds #ifdef ED_DBGP
7651da177e4SLinus Torvalds 		printk("Abort to Send\n");
7661da177e4SLinus Torvalds #endif
7671da177e4SLinus Torvalds 		dev->last_cmd[c] |= 0x40;
7681da177e4SLinus Torvalds 		dev->in_snd[c] = 0;
7691da177e4SLinus Torvalds 		return;
770468b8968SOndrej Zary 	}
7711da177e4SLinus Torvalds #ifdef ED_DBGP
7721da177e4SLinus Torvalds 	printk("OK to Send\n");
773422c0d61SJeff Garzik 	scmd_printk(KERN_DEBUG, workreq, "CDB");
7741da177e4SLinus Torvalds 	for(i=0;i<workreq->cmd_len;i++) {
7751da177e4SLinus Torvalds 		printk(" %x",workreq->cmnd[i]);
7761da177e4SLinus Torvalds 	}
777422c0d61SJeff Garzik 	printk("\n");
7781da177e4SLinus Torvalds #endif
779fe7ed98fSBoaz Harrosh 	l = scsi_bufflen(workreq);
780fe7ed98fSBoaz Harrosh 
781b922a449SOndrej Zary 	if (is885(dev)) {
7826a3cebb6SOndrej Zary 		j = atp_readb_base(dev, 0x29) & 0xfe;
7836a3cebb6SOndrej Zary 		atp_writeb_base(dev, 0x29, j);
784422c0d61SJeff Garzik 		dev->r1f[c][scmd_id(workreq)] = 0;
7851da177e4SLinus Torvalds 	}
7861da177e4SLinus Torvalds 
7871da177e4SLinus Torvalds 	if (workreq->cmnd[0] == READ_CAPACITY) {
788fe7ed98fSBoaz Harrosh 		if (l > 8)
789fe7ed98fSBoaz Harrosh 			l = 8;
7901da177e4SLinus Torvalds 	}
791f3272258SHannes Reinecke 	if (workreq->cmnd[0] == TEST_UNIT_READY) {
792fe7ed98fSBoaz Harrosh 		l = 0;
7931da177e4SLinus Torvalds 	}
7941da177e4SLinus Torvalds 
7951da177e4SLinus Torvalds 	j = 0;
796422c0d61SJeff Garzik 	target_id = scmd_id(workreq);
7971da177e4SLinus Torvalds 
7981da177e4SLinus Torvalds 	/*
7991da177e4SLinus Torvalds 	 *	Wide ?
8001da177e4SLinus Torvalds 	 */
8011da177e4SLinus Torvalds 	w = 1;
8021da177e4SLinus Torvalds 	w = w << target_id;
8031da177e4SLinus Torvalds 	if ((w & dev->wide_id[c]) != 0) {
8041da177e4SLinus Torvalds 		j |= 0x01;
8051da177e4SLinus Torvalds 	}
8066a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x1b, j);
8076a3cebb6SOndrej Zary 	while ((atp_readb_io(dev, c, 0x1b) & 0x01) != j) {
8086a3cebb6SOndrej Zary 		atp_writeb_pci(dev, c, 0x1b, j);
8091da177e4SLinus Torvalds #ifdef ED_DBGP
8101da177e4SLinus Torvalds 		printk("send_s870 while loop 1\n");
8111da177e4SLinus Torvalds #endif
8121da177e4SLinus Torvalds 	}
8131da177e4SLinus Torvalds 	/*
8141da177e4SLinus Torvalds 	 *	Write the command
8151da177e4SLinus Torvalds 	 */
8161da177e4SLinus Torvalds 
8176a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x00, workreq->cmd_len);
8186a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x01, 0x2c);
819b922a449SOndrej Zary 	if (is885(dev))
8206a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x02, 0x7f);
8216a3cebb6SOndrej Zary 	else
8226a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x02, 0xcf);
8236a3cebb6SOndrej Zary 	for (i = 0; i < workreq->cmd_len; i++)
8246a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x03 + i, workreq->cmnd[i]);
8256a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x0f, workreq->device->lun);
8261da177e4SLinus Torvalds 	/*
8271da177e4SLinus Torvalds 	 *	Write the target
8281da177e4SLinus Torvalds 	 */
8296a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x11, dev->id[c][target_id].devsp);
8301da177e4SLinus Torvalds #ifdef ED_DBGP
831bcd5c59fSHannes Reinecke 	printk("dev->id[%d][%d].devsp = %2x\n",c,target_id,
832bcd5c59fSHannes Reinecke 	       dev->id[c][target_id].devsp);
8331da177e4SLinus Torvalds #endif
8341da177e4SLinus Torvalds 
835fe7ed98fSBoaz Harrosh 	sg_count = scsi_dma_map(workreq);
8361da177e4SLinus Torvalds 	/*
8371da177e4SLinus Torvalds 	 *	Write transfer size
8381da177e4SLinus Torvalds 	 */
8396a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x12, ((unsigned char *) (&l))[2]);
8406a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x13, ((unsigned char *) (&l))[1]);
8416a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x14, ((unsigned char *) (&l))[0]);
8421da177e4SLinus Torvalds 	j = target_id;
8431da177e4SLinus Torvalds 	dev->id[c][j].last_len = l;
8441da177e4SLinus Torvalds 	dev->id[c][j].tran_len = 0;
8451da177e4SLinus Torvalds #ifdef ED_DBGP
8461da177e4SLinus Torvalds 	printk("dev->id[%2d][%2d].last_len = %d\n",c,j,dev->id[c][j].last_len);
8471da177e4SLinus Torvalds #endif
8481da177e4SLinus Torvalds 	/*
8491da177e4SLinus Torvalds 	 *	Flip the wide bits
8501da177e4SLinus Torvalds 	 */
8511da177e4SLinus Torvalds 	if ((j & 0x08) != 0) {
8521da177e4SLinus Torvalds 		j = (j & 0x07) | 0x40;
8531da177e4SLinus Torvalds 	}
8541da177e4SLinus Torvalds 	/*
8551da177e4SLinus Torvalds 	 *	Check transfer direction
8561da177e4SLinus Torvalds 	 */
8576a3cebb6SOndrej Zary 	if (workreq->sc_data_direction == DMA_TO_DEVICE)
8586a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x15, j | 0x20);
8596a3cebb6SOndrej Zary 	else
8606a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x15, j);
8616a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x16, atp_readb_io(dev, c, 0x16) | 0x80);
8626a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x16, 0x80);
8631da177e4SLinus Torvalds 	dev->id[c][target_id].dirct = 0;
8641da177e4SLinus Torvalds 	if (l == 0) {
8656a3cebb6SOndrej Zary 		if (atp_readb_io(dev, c, 0x1c) == 0) {
8661da177e4SLinus Torvalds #ifdef ED_DBGP
8671da177e4SLinus Torvalds 			printk("change SCSI_CMD_REG 0x08\n");
8681da177e4SLinus Torvalds #endif
8696a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x18, 0x08);
8706a3cebb6SOndrej Zary 		} else
8711da177e4SLinus Torvalds 			dev->last_cmd[c] |= 0x40;
8721da177e4SLinus Torvalds 		dev->in_snd[c] = 0;
8731da177e4SLinus Torvalds 		return;
8741da177e4SLinus Torvalds 	}
8751da177e4SLinus Torvalds 	prd = dev->id[c][target_id].prd_table;
8761da177e4SLinus Torvalds 	dev->id[c][target_id].prd_pos = prd;
8771da177e4SLinus Torvalds 
8781da177e4SLinus Torvalds 	/*
8791da177e4SLinus Torvalds 	 *	Now write the request list. Either as scatter/gather or as
8801da177e4SLinus Torvalds 	 *	a linear chain.
8811da177e4SLinus Torvalds 	 */
8821da177e4SLinus Torvalds 
883fe7ed98fSBoaz Harrosh 	if (l) {
884fe7ed98fSBoaz Harrosh 		struct scatterlist *sgpnt;
8851da177e4SLinus Torvalds 		i = 0;
886fe7ed98fSBoaz Harrosh 		scsi_for_each_sg(workreq, sgpnt, sg_count, j) {
887fe7ed98fSBoaz Harrosh 			bttl = sg_dma_address(sgpnt);
888fe7ed98fSBoaz Harrosh 			l=sg_dma_len(sgpnt);
8891da177e4SLinus Torvalds #ifdef ED_DBGP
8901da177e4SLinus Torvalds 			printk("1. bttl %x, l %x\n",bttl, l);
8911da177e4SLinus Torvalds #endif
8921da177e4SLinus Torvalds 			while (l > 0x10000) {
8931da177e4SLinus Torvalds 				(((u16 *) (prd))[i + 3]) = 0x0000;
8941da177e4SLinus Torvalds 				(((u16 *) (prd))[i + 2]) = 0x0000;
8951da177e4SLinus Torvalds 				(((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
8961da177e4SLinus Torvalds 				l -= 0x10000;
8971da177e4SLinus Torvalds 				bttl += 0x10000;
8981da177e4SLinus Torvalds 				i += 0x04;
8991da177e4SLinus Torvalds 			}
9001da177e4SLinus Torvalds 			(((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
9011da177e4SLinus Torvalds 			(((u16 *) (prd))[i + 2]) = cpu_to_le16(l);
9021da177e4SLinus Torvalds 			(((u16 *) (prd))[i + 3]) = 0;
9031da177e4SLinus Torvalds 			i += 0x04;
9041da177e4SLinus Torvalds 		}
9051da177e4SLinus Torvalds 		(((u16 *) (prd))[i - 1]) = cpu_to_le16(0x8000);
9061da177e4SLinus Torvalds #ifdef ED_DBGP
907bcd5c59fSHannes Reinecke 		printk("prd %4x %4x %4x %4x\n",
908bcd5c59fSHannes Reinecke 		       (((unsigned short int *)prd)[0]),
909bcd5c59fSHannes Reinecke 		       (((unsigned short int *)prd)[1]),
910bcd5c59fSHannes Reinecke 		       (((unsigned short int *)prd)[2]),
911bcd5c59fSHannes Reinecke 		       (((unsigned short int *)prd)[3]));
9121da177e4SLinus Torvalds 		printk("2. bttl %x, l %x\n",bttl, l);
9131da177e4SLinus Torvalds #endif
9141da177e4SLinus Torvalds 	}
9151da177e4SLinus Torvalds #ifdef ED_DBGP
916bcd5c59fSHannes Reinecke 	printk("send_s870: prdaddr_2 0x%8x target_id %d\n",
917bcd5c59fSHannes Reinecke 	       dev->id[c][target_id].prdaddr,target_id);
9181da177e4SLinus Torvalds #endif
919b5683557SJames Bottomley 	dev->id[c][target_id].prdaddr = dev->id[c][target_id].prd_bus;
9206a3cebb6SOndrej Zary 	atp_writel_pci(dev, c, 4, dev->id[c][target_id].prdaddr);
9216a3cebb6SOndrej Zary 	atp_writeb_pci(dev, c, 2, 0x06);
9226a3cebb6SOndrej Zary 	atp_writeb_pci(dev, c, 2, 0x00);
923b922a449SOndrej Zary 	if (is885(dev)) {
9246a3cebb6SOndrej Zary 		j = atp_readb_pci(dev, c, 1) & 0xf3;
925f3272258SHannes Reinecke 		if ((workreq->cmnd[0] == READ_6) ||
926f3272258SHannes Reinecke 		    (workreq->cmnd[0] == READ_10) ||
927f3272258SHannes Reinecke 		    (workreq->cmnd[0] == WRITE_6) ||
928f3272258SHannes Reinecke 		    (workreq->cmnd[0] == WRITE_10)) {
9291da177e4SLinus Torvalds 			j |= 0x0c;
9301da177e4SLinus Torvalds 		}
9316a3cebb6SOndrej Zary 		atp_writeb_pci(dev, c, 1, j);
932b922a449SOndrej Zary 	} else if (is880(dev)) {
933f3272258SHannes Reinecke 		if ((workreq->cmnd[0] == READ_6) ||
934f3272258SHannes Reinecke 		    (workreq->cmnd[0] == READ_10) ||
935f3272258SHannes Reinecke 		    (workreq->cmnd[0] == WRITE_6) ||
936f3272258SHannes Reinecke 		    (workreq->cmnd[0] == WRITE_10))
937bcd5c59fSHannes Reinecke 			atp_writeb_base(dev, 0x3b,
938bcd5c59fSHannes Reinecke 					(atp_readb_base(dev, 0x3b) & 0x3f) | 0xc0);
9396a3cebb6SOndrej Zary 		else
940bcd5c59fSHannes Reinecke 			atp_writeb_base(dev, 0x3b,
941bcd5c59fSHannes Reinecke 					atp_readb_base(dev, 0x3b) & 0x3f);
9421da177e4SLinus Torvalds 	} else {
943f3272258SHannes Reinecke 		if ((workreq->cmnd[0] == READ_6) ||
944f3272258SHannes Reinecke 		    (workreq->cmnd[0] == READ_10) ||
945f3272258SHannes Reinecke 		    (workreq->cmnd[0] == WRITE_6) ||
946f3272258SHannes Reinecke 		    (workreq->cmnd[0] == WRITE_10))
947bcd5c59fSHannes Reinecke 			atp_writeb_base(dev, 0x3a,
948bcd5c59fSHannes Reinecke 					(atp_readb_base(dev, 0x3a) & 0xf3) | 0x08);
9496a3cebb6SOndrej Zary 		else
950bcd5c59fSHannes Reinecke 			atp_writeb_base(dev, 0x3a,
951bcd5c59fSHannes Reinecke 					atp_readb_base(dev, 0x3a) & 0xf3);
9521da177e4SLinus Torvalds 	}
9531da177e4SLinus Torvalds 
9541da177e4SLinus Torvalds 	if(workreq->sc_data_direction == DMA_TO_DEVICE) {
9551da177e4SLinus Torvalds 		dev->id[c][target_id].dirct = 0x20;
9566a3cebb6SOndrej Zary 		if (atp_readb_io(dev, c, 0x1c) == 0) {
9576a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x18, 0x08);
9586a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 0, 0x01);
9591da177e4SLinus Torvalds #ifdef ED_DBGP
9601da177e4SLinus Torvalds 		printk( "start DMA(to target)\n");
9611da177e4SLinus Torvalds #endif
9621da177e4SLinus Torvalds 		} else {
9631da177e4SLinus Torvalds 			dev->last_cmd[c] |= 0x40;
9641da177e4SLinus Torvalds 		}
9651da177e4SLinus Torvalds 		dev->in_snd[c] = 0;
9661da177e4SLinus Torvalds 		return;
9671da177e4SLinus Torvalds 	}
9686a3cebb6SOndrej Zary 	if (atp_readb_io(dev, c, 0x1c) == 0) {
9696a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
9706a3cebb6SOndrej Zary 		atp_writeb_pci(dev, c, 0, 0x09);
9711da177e4SLinus Torvalds #ifdef ED_DBGP
9721da177e4SLinus Torvalds 		printk( "start DMA(to host)\n");
9731da177e4SLinus Torvalds #endif
9741da177e4SLinus Torvalds 	} else {
9751da177e4SLinus Torvalds 		dev->last_cmd[c] |= 0x40;
9761da177e4SLinus Torvalds 	}
9771da177e4SLinus Torvalds 	dev->in_snd[c] = 0;
9781da177e4SLinus Torvalds 	return;
9791da177e4SLinus Torvalds 
9801da177e4SLinus Torvalds }
9811da177e4SLinus Torvalds 
9821da177e4SLinus Torvalds static unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val)
9831da177e4SLinus Torvalds {
9841da177e4SLinus Torvalds 	unsigned short int i, k;
9851da177e4SLinus Torvalds 	unsigned char j;
9861da177e4SLinus Torvalds 
9876a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, *val);
9881da177e4SLinus Torvalds 	for (i = 0; i < 10; i++) {	/* stable >= bus settle delay(400 ns)  */
9896a3cebb6SOndrej Zary 		k = atp_readw_io(dev, 0, 0x1c);
9901da177e4SLinus Torvalds 		j = (unsigned char) (k >> 8);
991832e9ac6SOndrej Zary 		if ((k & 0x8000) != 0)	/* DB7 all release?    */
992832e9ac6SOndrej Zary 			i = 0;
9931da177e4SLinus Torvalds 	}
9941da177e4SLinus Torvalds 	*val |= 0x4000;		/* assert DB6           */
9956a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, *val);
9961da177e4SLinus Torvalds 	*val &= 0xdfff;		/* assert DB5           */
9976a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, *val);
9981da177e4SLinus Torvalds 	for (i = 0; i < 10; i++) {	/* stable >= bus settle delay(400 ns) */
9996a3cebb6SOndrej Zary 		if ((atp_readw_io(dev, 0, 0x1c) & 0x2000) != 0)	/* DB5 all release?       */
1000832e9ac6SOndrej Zary 			i = 0;
10011da177e4SLinus Torvalds 	}
10021da177e4SLinus Torvalds 	*val |= 0x8000;		/* no DB4-0, assert DB7    */
10031da177e4SLinus Torvalds 	*val &= 0xe0ff;
10046a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, *val);
10051da177e4SLinus Torvalds 	*val &= 0xbfff;		/* release DB6             */
10066a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, *val);
10071da177e4SLinus Torvalds 	for (i = 0; i < 10; i++) {	/* stable >= bus settle delay(400 ns)  */
10086a3cebb6SOndrej Zary 		if ((atp_readw_io(dev, 0, 0x1c) & 0x4000) != 0)	/* DB6 all release?  */
1009832e9ac6SOndrej Zary 			i = 0;
10101da177e4SLinus Torvalds 	}
10111da177e4SLinus Torvalds 
10121da177e4SLinus Torvalds 	return j;
10131da177e4SLinus Torvalds }
10141da177e4SLinus Torvalds 
10158177c507SOndrej Zary static void tscam(struct Scsi_Host *host, bool wide_chip, u8 scam_on)
10161da177e4SLinus Torvalds {
10171da177e4SLinus Torvalds 
10181da177e4SLinus Torvalds 	unsigned char i, j, k;
10191da177e4SLinus Torvalds 	unsigned long n;
10201da177e4SLinus Torvalds 	unsigned short int m, assignid_map, val;
10211da177e4SLinus Torvalds 	unsigned char mbuf[33], quintet[2];
10221da177e4SLinus Torvalds 	struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
10231da177e4SLinus Torvalds 	static unsigned char g2q_tab[8] = {
10241da177e4SLinus Torvalds 		0x38, 0x31, 0x32, 0x2b, 0x34, 0x2d, 0x2e, 0x27
10251da177e4SLinus Torvalds 	};
10261da177e4SLinus Torvalds 
10271da177e4SLinus Torvalds /*  I can't believe we need this before we've even done anything.  Remove it
10281da177e4SLinus Torvalds  *  and see if anyone bitches.
10291da177e4SLinus Torvalds 	for (i = 0; i < 0x10; i++) {
10301da177e4SLinus Torvalds 		udelay(0xffff);
10311da177e4SLinus Torvalds 	}
10321da177e4SLinus Torvalds  */
10331da177e4SLinus Torvalds 
10346a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 1, 0x08);
10356a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 2, 0x7f);
10366a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x11, 0x20);
10371da177e4SLinus Torvalds 
10388177c507SOndrej Zary 	if ((scam_on & 0x40) == 0) {
10391da177e4SLinus Torvalds 		return;
10401da177e4SLinus Torvalds 	}
10411da177e4SLinus Torvalds 	m = 1;
10421da177e4SLinus Torvalds 	m <<= dev->host_id[0];
10431da177e4SLinus Torvalds 	j = 16;
1044dd5a5f79SOndrej Zary 	if (!wide_chip) {
10451da177e4SLinus Torvalds 		m |= 0xff00;
10461da177e4SLinus Torvalds 		j = 8;
10471da177e4SLinus Torvalds 	}
10481da177e4SLinus Torvalds 	assignid_map = m;
10496a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x02, 0x02);	/* 2*2=4ms,3EH 2/32*3E=3.9ms */
10506a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x03, 0);
10516a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x04, 0);
10526a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x05, 0);
10536a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x06, 0);
10546a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x07, 0);
10556a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x08, 0);
10561da177e4SLinus Torvalds 
10571da177e4SLinus Torvalds 	for (i = 0; i < j; i++) {
10581da177e4SLinus Torvalds 		m = 1;
10591da177e4SLinus Torvalds 		m = m << i;
10601da177e4SLinus Torvalds 		if ((m & assignid_map) != 0) {
10611da177e4SLinus Torvalds 			continue;
10621da177e4SLinus Torvalds 		}
10636a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x0f, 0);
10646a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x12, 0);
10656a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x13, 0);
10666a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x14, 0);
10671da177e4SLinus Torvalds 		if (i > 7) {
10681da177e4SLinus Torvalds 			k = (i & 0x07) | 0x40;
10691da177e4SLinus Torvalds 		} else {
10701da177e4SLinus Torvalds 			k = i;
10711da177e4SLinus Torvalds 		}
10726a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x15, k);
1073dd5a5f79SOndrej Zary 		if (wide_chip)
10746a3cebb6SOndrej Zary 			atp_writeb_io(dev, 0, 0x1b, 0x01);
10756a3cebb6SOndrej Zary 		else
10766a3cebb6SOndrej Zary 			atp_writeb_io(dev, 0, 0x1b, 0x00);
107758c4d046SOndrej Zary 		do {
10786a3cebb6SOndrej Zary 			atp_writeb_io(dev, 0, 0x18, 0x09);
10791da177e4SLinus Torvalds 
10806a3cebb6SOndrej Zary 			while ((atp_readb_io(dev, 0, 0x1f) & 0x80) == 0x00)
10811da177e4SLinus Torvalds 				cpu_relax();
10826a3cebb6SOndrej Zary 			k = atp_readb_io(dev, 0, 0x17);
108358c4d046SOndrej Zary 			if ((k == 0x85) || (k == 0x42))
108458c4d046SOndrej Zary 				break;
108558c4d046SOndrej Zary 			if (k != 0x16)
10866a3cebb6SOndrej Zary 				atp_writeb_io(dev, 0, 0x10, 0x41);
108758c4d046SOndrej Zary 		} while (k != 0x16);
108858c4d046SOndrej Zary 		if ((k == 0x85) || (k == 0x42))
108958c4d046SOndrej Zary 			continue;
10901da177e4SLinus Torvalds 		assignid_map |= m;
10911da177e4SLinus Torvalds 
10921da177e4SLinus Torvalds 	}
10936a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x02, 0x7f);
10946a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x1b, 0x02);
10951da177e4SLinus Torvalds 
10962bbbac45SOndrej Zary 	udelay(2);
10971da177e4SLinus Torvalds 
10981da177e4SLinus Torvalds 	val = 0x0080;		/* bsy  */
10996a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, val);
11001da177e4SLinus Torvalds 	val |= 0x0040;		/* sel  */
11016a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, val);
11021da177e4SLinus Torvalds 	val |= 0x0004;		/* msg  */
11036a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, val);
11042bbbac45SOndrej Zary 	udelay(2);		/* 2 deskew delay(45ns*2=90ns) */
11051da177e4SLinus Torvalds 	val &= 0x007f;		/* no bsy  */
11066a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, val);
1107dcaa0c12SJia-Ju Bai 	msleep(128);
11081da177e4SLinus Torvalds 	val &= 0x00fb;		/* after 1ms no msg */
11096a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, val);
11106a3cebb6SOndrej Zary 	while ((atp_readb_io(dev, 0, 0x1c) & 0x04) != 0)
111158c4d046SOndrej Zary 		;
11122bbbac45SOndrej Zary 	udelay(2);
11131da177e4SLinus Torvalds 	udelay(100);
1114c7fcc089SOndrej Zary 	for (n = 0; n < 0x30000; n++)
11156a3cebb6SOndrej Zary 		if ((atp_readb_io(dev, 0, 0x1c) & 0x80) != 0)	/* bsy ? */
1116c7fcc089SOndrej Zary 			break;
1117c7fcc089SOndrej Zary 	if (n < 0x30000)
1118c7fcc089SOndrej Zary 		for (n = 0; n < 0x30000; n++)
11196a3cebb6SOndrej Zary 			if ((atp_readb_io(dev, 0, 0x1c) & 0x81) == 0x0081) {
11202bbbac45SOndrej Zary 				udelay(2);
11211da177e4SLinus Torvalds 				val |= 0x8003;		/* io,cd,db7  */
11226a3cebb6SOndrej Zary 				atp_writew_io(dev, 0, 0x1c, val);
11232bbbac45SOndrej Zary 				udelay(2);
11241da177e4SLinus Torvalds 				val &= 0x00bf;		/* no sel     */
11256a3cebb6SOndrej Zary 				atp_writew_io(dev, 0, 0x1c, val);
11262bbbac45SOndrej Zary 				udelay(2);
1127c7fcc089SOndrej Zary 				break;
1128c7fcc089SOndrej Zary 			}
1129c7fcc089SOndrej Zary 	while (1) {
11300f6d93aaSMartin Michlmayr 	/*
11310f6d93aaSMartin Michlmayr 	 * The funny division into multiple delays is to accomodate
11320f6d93aaSMartin Michlmayr 	 * arches like ARM where udelay() multiplies its argument by
11330f6d93aaSMartin Michlmayr 	 * a large number to initialize a loop counter.  To avoid
11340f6d93aaSMartin Michlmayr 	 * overflow, the maximum supported udelay is 2000 microseconds.
11350f6d93aaSMartin Michlmayr 	 *
11360f6d93aaSMartin Michlmayr 	 * XXX it would be more polite to find a way to use msleep()
11370f6d93aaSMartin Michlmayr 	 */
11380f6d93aaSMartin Michlmayr 	mdelay(2);
11390f6d93aaSMartin Michlmayr 	udelay(48);
11406a3cebb6SOndrej Zary 	if ((atp_readb_io(dev, 0, 0x1c) & 0x80) == 0x00) {	/* bsy ? */
11416a3cebb6SOndrej Zary 		atp_writew_io(dev, 0, 0x1c, 0);
11426a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x1b, 0);
11436a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x15, 0);
11446a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x18, 0x09);
11456a3cebb6SOndrej Zary 		while ((atp_readb_io(dev, 0, 0x1f) & 0x80) == 0)
11461da177e4SLinus Torvalds 			cpu_relax();
11476a3cebb6SOndrej Zary 		atp_readb_io(dev, 0, 0x17);
11481da177e4SLinus Torvalds 		return;
11491da177e4SLinus Torvalds 	}
11501da177e4SLinus Torvalds 	val &= 0x00ff;		/* synchronization  */
11511da177e4SLinus Torvalds 	val |= 0x3f00;
11521da177e4SLinus Torvalds 	fun_scam(dev, &val);
11532bbbac45SOndrej Zary 	udelay(2);
11541da177e4SLinus Torvalds 	val &= 0x00ff;		/* isolation        */
11551da177e4SLinus Torvalds 	val |= 0x2000;
11561da177e4SLinus Torvalds 	fun_scam(dev, &val);
11572bbbac45SOndrej Zary 	udelay(2);
11581da177e4SLinus Torvalds 	i = 8;
11591da177e4SLinus Torvalds 	j = 0;
1160c7fcc089SOndrej Zary 
1161c7fcc089SOndrej Zary 	while (1) {
11626a3cebb6SOndrej Zary 		if ((atp_readw_io(dev, 0, 0x1c) & 0x2000) == 0)
1163c7fcc089SOndrej Zary 			continue;
11642bbbac45SOndrej Zary 		udelay(2);
11651da177e4SLinus Torvalds 		val &= 0x00ff;		/* get ID_STRING */
11661da177e4SLinus Torvalds 		val |= 0x2000;
11671da177e4SLinus Torvalds 		k = fun_scam(dev, &val);
1168c7fcc089SOndrej Zary 		if ((k & 0x03) == 0)
1169c7fcc089SOndrej Zary 			break;
11701da177e4SLinus Torvalds 		mbuf[j] <<= 0x01;
11711da177e4SLinus Torvalds 		mbuf[j] &= 0xfe;
1172c7fcc089SOndrej Zary 		if ((k & 0x02) != 0)
11731da177e4SLinus Torvalds 			mbuf[j] |= 0x01;
11741da177e4SLinus Torvalds 		i--;
1175c7fcc089SOndrej Zary 		if (i > 0)
1176c7fcc089SOndrej Zary 			continue;
11771da177e4SLinus Torvalds 		j++;
11781da177e4SLinus Torvalds 		i = 8;
1179c7fcc089SOndrej Zary 	}
11801da177e4SLinus Torvalds 
1181c7fcc089SOndrej Zary 	/* isolation complete..  */
11821da177e4SLinus Torvalds /*    mbuf[32]=0;
11831da177e4SLinus Torvalds 	printk(" \n%x %x %x %s\n ",assignid_map,mbuf[0],mbuf[1],&mbuf[2]); */
11841da177e4SLinus Torvalds 	i = 15;
11851da177e4SLinus Torvalds 	j = mbuf[0];
11861da177e4SLinus Torvalds 	if ((j & 0x20) != 0) {	/* bit5=1:ID up to 7      */
11871da177e4SLinus Torvalds 		i = 7;
11881da177e4SLinus Torvalds 	}
1189c7fcc089SOndrej Zary 	if ((j & 0x06) != 0) {	/* IDvalid?             */
11901da177e4SLinus Torvalds 		k = mbuf[1];
1191c7fcc089SOndrej Zary 		while (1) {
11921da177e4SLinus Torvalds 			m = 1;
11931da177e4SLinus Torvalds 			m <<= k;
1194c7fcc089SOndrej Zary 			if ((m & assignid_map) == 0)
1195c7fcc089SOndrej Zary 				break;
1196c7fcc089SOndrej Zary 			if (k > 0)
11971da177e4SLinus Torvalds 				k--;
1198c7fcc089SOndrej Zary 			else
1199c7fcc089SOndrej Zary 				break;
12001da177e4SLinus Torvalds 		}
1201c7fcc089SOndrej Zary 	}
1202c7fcc089SOndrej Zary 	if ((m & assignid_map) != 0) {	/* srch from max acceptable ID#  */
12031da177e4SLinus Torvalds 		k = i;			/* max acceptable ID#            */
1204c7fcc089SOndrej Zary 		while (1) {
12051da177e4SLinus Torvalds 			m = 1;
12061da177e4SLinus Torvalds 			m <<= k;
1207c7fcc089SOndrej Zary 			if ((m & assignid_map) == 0)
1208c7fcc089SOndrej Zary 				break;
1209c7fcc089SOndrej Zary 			if (k > 0)
12101da177e4SLinus Torvalds 				k--;
1211c7fcc089SOndrej Zary 			else
1212c7fcc089SOndrej Zary 				break;
12131da177e4SLinus Torvalds 		}
1214c7fcc089SOndrej Zary 	}
1215c7fcc089SOndrej Zary 	/* k=binID#,       */
12161da177e4SLinus Torvalds 	assignid_map |= m;
12171da177e4SLinus Torvalds 	if (k < 8) {
12181da177e4SLinus Torvalds 		quintet[0] = 0x38;	/* 1st dft ID<8    */
12191da177e4SLinus Torvalds 	} else {
12201da177e4SLinus Torvalds 		quintet[0] = 0x31;	/* 1st  ID>=8      */
12211da177e4SLinus Torvalds 	}
12221da177e4SLinus Torvalds 	k &= 0x07;
12231da177e4SLinus Torvalds 	quintet[1] = g2q_tab[k];
12241da177e4SLinus Torvalds 
12251da177e4SLinus Torvalds 	val &= 0x00ff;		/* AssignID 1stQuintet,AH=001xxxxx  */
12261da177e4SLinus Torvalds 	m = quintet[0] << 8;
12271da177e4SLinus Torvalds 	val |= m;
12281da177e4SLinus Torvalds 	fun_scam(dev, &val);
12291da177e4SLinus Torvalds 	val &= 0x00ff;		/* AssignID 2ndQuintet,AH=001xxxxx */
12301da177e4SLinus Torvalds 	m = quintet[1] << 8;
12311da177e4SLinus Torvalds 	val |= m;
12321da177e4SLinus Torvalds 	fun_scam(dev, &val);
12331da177e4SLinus Torvalds 
1234c7fcc089SOndrej Zary 	}
12351da177e4SLinus Torvalds }
12361da177e4SLinus Torvalds 
12371da177e4SLinus Torvalds static void atp870u_free_tables(struct Scsi_Host *host)
12381da177e4SLinus Torvalds {
12391da177e4SLinus Torvalds 	struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata;
12401da177e4SLinus Torvalds 	int j, k;
12411da177e4SLinus Torvalds 	for (j=0; j < 2; j++) {
12421da177e4SLinus Torvalds 		for (k = 0; k < 16; k++) {
12431da177e4SLinus Torvalds 			if (!atp_dev->id[j][k].prd_table)
12441da177e4SLinus Torvalds 				continue;
1245bcd5c59fSHannes Reinecke 			dma_free_coherent(&atp_dev->pdev->dev, 1024,
1246bcd5c59fSHannes Reinecke 					  atp_dev->id[j][k].prd_table,
1247bcd5c59fSHannes Reinecke 					  atp_dev->id[j][k].prd_bus);
12481da177e4SLinus Torvalds 			atp_dev->id[j][k].prd_table = NULL;
12491da177e4SLinus Torvalds 		}
12501da177e4SLinus Torvalds 	}
12511da177e4SLinus Torvalds }
12521da177e4SLinus Torvalds 
12531da177e4SLinus Torvalds static int atp870u_init_tables(struct Scsi_Host *host)
12541da177e4SLinus Torvalds {
12551da177e4SLinus Torvalds 	struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata;
12561da177e4SLinus Torvalds 	int c,k;
12571da177e4SLinus Torvalds 	for(c=0;c < 2;c++) {
12581da177e4SLinus Torvalds 		for(k=0;k<16;k++) {
1259bcd5c59fSHannes Reinecke 			atp_dev->id[c][k].prd_table =
1260bcd5c59fSHannes Reinecke 				dma_alloc_coherent(&atp_dev->pdev->dev, 1024,
1261bcd5c59fSHannes Reinecke 						   &(atp_dev->id[c][k].prd_bus),
1262bcd5c59fSHannes Reinecke 						   GFP_KERNEL);
12631da177e4SLinus Torvalds 			if (!atp_dev->id[c][k].prd_table) {
12641da177e4SLinus Torvalds 				printk("atp870u_init_tables fail\n");
12651da177e4SLinus Torvalds 				atp870u_free_tables(host);
12661da177e4SLinus Torvalds 				return -ENOMEM;
12671da177e4SLinus Torvalds 			}
1268b5683557SJames Bottomley 			atp_dev->id[c][k].prdaddr = atp_dev->id[c][k].prd_bus;
12691da177e4SLinus Torvalds 			atp_dev->id[c][k].devsp=0x20;
12701da177e4SLinus Torvalds 			atp_dev->id[c][k].devtype = 0x7f;
12711da177e4SLinus Torvalds 			atp_dev->id[c][k].curr_req = NULL;
12721da177e4SLinus Torvalds 		}
12731da177e4SLinus Torvalds 
12741da177e4SLinus Torvalds 		atp_dev->active_id[c] = 0;
12751da177e4SLinus Torvalds 		atp_dev->wide_id[c] = 0;
12761da177e4SLinus Torvalds 		atp_dev->host_id[c] = 0x07;
12771da177e4SLinus Torvalds 		atp_dev->quhd[c] = 0;
12781da177e4SLinus Torvalds 		atp_dev->quend[c] = 0;
12791da177e4SLinus Torvalds 		atp_dev->last_cmd[c] = 0xff;
12801da177e4SLinus Torvalds 		atp_dev->in_snd[c] = 0;
12811da177e4SLinus Torvalds 		atp_dev->in_int[c] = 0;
12821da177e4SLinus Torvalds 
12831da177e4SLinus Torvalds 		for (k = 0; k < qcnt; k++) {
12841da177e4SLinus Torvalds 			atp_dev->quereq[c][k] = NULL;
12851da177e4SLinus Torvalds 		}
12861da177e4SLinus Torvalds 		for (k = 0; k < 16; k++) {
12871da177e4SLinus Torvalds 			   atp_dev->id[c][k].curr_req = NULL;
12881da177e4SLinus Torvalds 			   atp_dev->sp[c][k] = 0x04;
12891da177e4SLinus Torvalds 		}
12901da177e4SLinus Torvalds 	}
12911da177e4SLinus Torvalds 	return 0;
12921da177e4SLinus Torvalds }
12931da177e4SLinus Torvalds 
12946a1961bcSOndrej Zary static void atp_set_host_id(struct atp_unit *atp, u8 c, u8 host_id)
12956a1961bcSOndrej Zary {
12966a1961bcSOndrej Zary 	atp_writeb_io(atp, c, 0, host_id | 0x08);
12976a1961bcSOndrej Zary 	atp_writeb_io(atp, c, 0x18, 0);
12986a1961bcSOndrej Zary 	while ((atp_readb_io(atp, c, 0x1f) & 0x80) == 0)
12996a1961bcSOndrej Zary 		mdelay(1);
13006a1961bcSOndrej Zary 	atp_readb_io(atp, c, 0x17);
13016a1961bcSOndrej Zary 	atp_writeb_io(atp, c, 1, 8);
13026a1961bcSOndrej Zary 	atp_writeb_io(atp, c, 2, 0x7f);
13036a1961bcSOndrej Zary 	atp_writeb_io(atp, c, 0x11, 0x20);
13046a1961bcSOndrej Zary }
13056a1961bcSOndrej Zary 
13064190230eSOndrej Zary static void atp870_init(struct Scsi_Host *shpnt)
13074190230eSOndrej Zary {
13084190230eSOndrej Zary 	struct atp_unit *atpdev = shost_priv(shpnt);
13094190230eSOndrej Zary 	struct pci_dev *pdev = atpdev->pdev;
13104190230eSOndrej Zary 	unsigned char k, host_id;
13114190230eSOndrej Zary 	u8 scam_on;
13124190230eSOndrej Zary 	bool wide_chip =
13134190230eSOndrej Zary 		(pdev->device == PCI_DEVICE_ID_ARTOP_AEC7610 &&
13144190230eSOndrej Zary 		 pdev->revision == 4) ||
13154190230eSOndrej Zary 		(pdev->device == PCI_DEVICE_ID_ARTOP_AEC7612UW) ||
13164190230eSOndrej Zary 		(pdev->device == PCI_DEVICE_ID_ARTOP_AEC7612SUW);
13174190230eSOndrej Zary 
13184190230eSOndrej Zary 	pci_read_config_byte(pdev, 0x49, &host_id);
13194190230eSOndrej Zary 
1320bcd5c59fSHannes Reinecke 	dev_info(&pdev->dev, "ACARD AEC-671X PCI Ultra/W SCSI-2/3 "
1321bcd5c59fSHannes Reinecke 		 "Host Adapter: IO:%lx, IRQ:%d.\n",
13224190230eSOndrej Zary 		 shpnt->io_port, shpnt->irq);
13234190230eSOndrej Zary 
13244190230eSOndrej Zary 	atpdev->ioport[0] = shpnt->io_port;
13254190230eSOndrej Zary 	atpdev->pciport[0] = shpnt->io_port + 0x20;
13264190230eSOndrej Zary 	host_id &= 0x07;
13274190230eSOndrej Zary 	atpdev->host_id[0] = host_id;
13284190230eSOndrej Zary 	scam_on = atp_readb_pci(atpdev, 0, 2);
13294190230eSOndrej Zary 	atpdev->global_map[0] = atp_readb_base(atpdev, 0x2d);
13304190230eSOndrej Zary 	atpdev->ultra_map[0] = atp_readw_base(atpdev, 0x2e);
13314190230eSOndrej Zary 
13324190230eSOndrej Zary 	if (atpdev->ultra_map[0] == 0) {
13334190230eSOndrej Zary 		scam_on = 0x00;
13344190230eSOndrej Zary 		atpdev->global_map[0] = 0x20;
13354190230eSOndrej Zary 		atpdev->ultra_map[0] = 0xffff;
13364190230eSOndrej Zary 	}
13374190230eSOndrej Zary 
13384190230eSOndrej Zary 	if (pdev->revision > 0x07)	/* check if atp876 chip */
13394190230eSOndrej Zary 		atp_writeb_base(atpdev, 0x3e, 0x00); /* enable terminator */
13404190230eSOndrej Zary 
13414190230eSOndrej Zary 	k = (atp_readb_base(atpdev, 0x3a) & 0xf3) | 0x10;
13424190230eSOndrej Zary 	atp_writeb_base(atpdev, 0x3a, k);
13434190230eSOndrej Zary 	atp_writeb_base(atpdev, 0x3a, k & 0xdf);
1344dcaa0c12SJia-Ju Bai 	msleep(32);
13454190230eSOndrej Zary 	atp_writeb_base(atpdev, 0x3a, k);
1346dcaa0c12SJia-Ju Bai 	msleep(32);
13474190230eSOndrej Zary 	atp_set_host_id(atpdev, 0, host_id);
13484190230eSOndrej Zary 
13494190230eSOndrej Zary 	tscam(shpnt, wide_chip, scam_on);
13504190230eSOndrej Zary 	atp_writeb_base(atpdev, 0x3a, atp_readb_base(atpdev, 0x3a) | 0x10);
13514190230eSOndrej Zary 	atp_is(atpdev, 0, wide_chip, 0);
13524190230eSOndrej Zary 	atp_writeb_base(atpdev, 0x3a, atp_readb_base(atpdev, 0x3a) & 0xef);
13534190230eSOndrej Zary 	atp_writeb_base(atpdev, 0x3b, atp_readb_base(atpdev, 0x3b) | 0x20);
13544190230eSOndrej Zary 	shpnt->max_id = wide_chip ? 16 : 8;
13554190230eSOndrej Zary 	shpnt->this_id = host_id;
13564190230eSOndrej Zary }
13574190230eSOndrej Zary 
1358c7e6a029SOndrej Zary static void atp880_init(struct Scsi_Host *shpnt)
1359c7e6a029SOndrej Zary {
1360c7e6a029SOndrej Zary 	struct atp_unit *atpdev = shost_priv(shpnt);
1361c7e6a029SOndrej Zary 	struct pci_dev *pdev = atpdev->pdev;
1362c7e6a029SOndrej Zary 	unsigned char k, m, host_id;
1363c7e6a029SOndrej Zary 	unsigned int n;
1364c7e6a029SOndrej Zary 
1365c7e6a029SOndrej Zary 	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80);
1366c7e6a029SOndrej Zary 
1367c7e6a029SOndrej Zary 	atpdev->ioport[0] = shpnt->io_port + 0x40;
1368c7e6a029SOndrej Zary 	atpdev->pciport[0] = shpnt->io_port + 0x28;
1369c7e6a029SOndrej Zary 
1370c7e6a029SOndrej Zary 	host_id = atp_readb_base(atpdev, 0x39) >> 4;
1371c7e6a029SOndrej Zary 
1372bcd5c59fSHannes Reinecke 	dev_info(&pdev->dev, "ACARD AEC-67160 PCI Ultra3 LVD "
1373bcd5c59fSHannes Reinecke 		 "Host Adapter: IO:%lx, IRQ:%d.\n",
1374c7e6a029SOndrej Zary 		 shpnt->io_port, shpnt->irq);
1375c7e6a029SOndrej Zary 	atpdev->host_id[0] = host_id;
1376c7e6a029SOndrej Zary 
1377c7e6a029SOndrej Zary 	atpdev->global_map[0] = atp_readb_base(atpdev, 0x35);
1378c7e6a029SOndrej Zary 	atpdev->ultra_map[0] = atp_readw_base(atpdev, 0x3c);
1379c7e6a029SOndrej Zary 
1380c7e6a029SOndrej Zary 	n = 0x3f09;
1381c7e6a029SOndrej Zary 	while (n < 0x4000) {
1382c7e6a029SOndrej Zary 		m = 0;
1383c7e6a029SOndrej Zary 		atp_writew_base(atpdev, 0x34, n);
1384c7e6a029SOndrej Zary 		n += 0x0002;
1385c7e6a029SOndrej Zary 		if (atp_readb_base(atpdev, 0x30) == 0xff)
1386c7e6a029SOndrej Zary 			break;
1387c7e6a029SOndrej Zary 
1388c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30);
1389c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31);
1390c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32);
1391c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33);
1392c7e6a029SOndrej Zary 		atp_writew_base(atpdev, 0x34, n);
1393c7e6a029SOndrej Zary 		n += 0x0002;
1394c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30);
1395c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31);
1396c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32);
1397c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33);
1398c7e6a029SOndrej Zary 		atp_writew_base(atpdev, 0x34, n);
1399c7e6a029SOndrej Zary 		n += 0x0002;
1400c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30);
1401c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31);
1402c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32);
1403c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33);
1404c7e6a029SOndrej Zary 		atp_writew_base(atpdev, 0x34, n);
1405c7e6a029SOndrej Zary 		n += 0x0002;
1406c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30);
1407c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31);
1408c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32);
1409c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33);
1410c7e6a029SOndrej Zary 		n += 0x0018;
1411c7e6a029SOndrej Zary 	}
1412c7e6a029SOndrej Zary 	atp_writew_base(atpdev, 0x34, 0);
1413c7e6a029SOndrej Zary 	atpdev->ultra_map[0] = 0;
1414c7e6a029SOndrej Zary 	atpdev->async[0] = 0;
1415c7e6a029SOndrej Zary 	for (k = 0; k < 16; k++) {
1416c7e6a029SOndrej Zary 		n = 1 << k;
1417c7e6a029SOndrej Zary 		if (atpdev->sp[0][k] > 1)
1418c7e6a029SOndrej Zary 			atpdev->ultra_map[0] |= n;
1419c7e6a029SOndrej Zary 		else
1420c7e6a029SOndrej Zary 			if (atpdev->sp[0][k] == 0)
1421c7e6a029SOndrej Zary 				atpdev->async[0] |= n;
1422c7e6a029SOndrej Zary 	}
1423c7e6a029SOndrej Zary 	atpdev->async[0] = ~(atpdev->async[0]);
1424c7e6a029SOndrej Zary 	atp_writeb_base(atpdev, 0x35, atpdev->global_map[0]);
1425c7e6a029SOndrej Zary 
1426c7e6a029SOndrej Zary 	k = atp_readb_base(atpdev, 0x38) & 0x80;
1427c7e6a029SOndrej Zary 	atp_writeb_base(atpdev, 0x38, k);
1428c7e6a029SOndrej Zary 	atp_writeb_base(atpdev, 0x3b, 0x20);
1429dcaa0c12SJia-Ju Bai 	msleep(32);
1430c7e6a029SOndrej Zary 	atp_writeb_base(atpdev, 0x3b, 0);
1431dcaa0c12SJia-Ju Bai 	msleep(32);
1432c7e6a029SOndrej Zary 	atp_readb_io(atpdev, 0, 0x1b);
1433c7e6a029SOndrej Zary 	atp_readb_io(atpdev, 0, 0x17);
1434c7e6a029SOndrej Zary 
1435c7e6a029SOndrej Zary 	atp_set_host_id(atpdev, 0, host_id);
1436c7e6a029SOndrej Zary 
1437c7e6a029SOndrej Zary 	tscam(shpnt, true, atp_readb_base(atpdev, 0x22));
1438c7e6a029SOndrej Zary 	atp_is(atpdev, 0, true, atp_readb_base(atpdev, 0x3f) & 0x40);
1439c7e6a029SOndrej Zary 	atp_writeb_base(atpdev, 0x38, 0xb0);
1440c7e6a029SOndrej Zary 	shpnt->max_id = 16;
1441c7e6a029SOndrej Zary 	shpnt->this_id = host_id;
1442c7e6a029SOndrej Zary }
1443c7e6a029SOndrej Zary 
1444ecc6ff95SOndrej Zary static void atp885_init(struct Scsi_Host *shpnt)
1445ecc6ff95SOndrej Zary {
1446ecc6ff95SOndrej Zary 	struct atp_unit *atpdev = shost_priv(shpnt);
1447ecc6ff95SOndrej Zary 	struct pci_dev *pdev = atpdev->pdev;
1448ecc6ff95SOndrej Zary 	unsigned char k, m, c;
1449ecc6ff95SOndrej Zary 	unsigned int n;
1450ecc6ff95SOndrej Zary 	unsigned char setupdata[2][16];
1451ecc6ff95SOndrej Zary 
1452bcd5c59fSHannes Reinecke 	dev_info(&pdev->dev, "ACARD AEC-67162 PCI Ultra3 LVD "
1453bcd5c59fSHannes Reinecke 		 "Host Adapter: IO:%lx, IRQ:%d.\n",
1454ecc6ff95SOndrej Zary 		 shpnt->io_port, shpnt->irq);
1455ecc6ff95SOndrej Zary 
1456ecc6ff95SOndrej Zary 	atpdev->ioport[0] = shpnt->io_port + 0x80;
1457ecc6ff95SOndrej Zary 	atpdev->ioport[1] = shpnt->io_port + 0xc0;
1458ecc6ff95SOndrej Zary 	atpdev->pciport[0] = shpnt->io_port + 0x40;
1459ecc6ff95SOndrej Zary 	atpdev->pciport[1] = shpnt->io_port + 0x50;
1460ecc6ff95SOndrej Zary 
1461ecc6ff95SOndrej Zary 	c = atp_readb_base(atpdev, 0x29);
1462ecc6ff95SOndrej Zary 	atp_writeb_base(atpdev, 0x29, c | 0x04);
1463ecc6ff95SOndrej Zary 
1464ecc6ff95SOndrej Zary 	n = 0x1f80;
1465ecc6ff95SOndrej Zary 	while (n < 0x2000) {
1466ecc6ff95SOndrej Zary 		atp_writew_base(atpdev, 0x3c, n);
1467ecc6ff95SOndrej Zary 		if (atp_readl_base(atpdev, 0x38) == 0xffffffff)
1468ecc6ff95SOndrej Zary 			break;
1469ecc6ff95SOndrej Zary 		for (m = 0; m < 2; m++) {
1470ecc6ff95SOndrej Zary 			atpdev->global_map[m] = 0;
1471ecc6ff95SOndrej Zary 			for (k = 0; k < 4; k++) {
1472ecc6ff95SOndrej Zary 				atp_writew_base(atpdev, 0x3c, n++);
1473bcd5c59fSHannes Reinecke 				((u32 *)&setupdata[m][0])[k] =
1474bcd5c59fSHannes Reinecke 					atp_readl_base(atpdev, 0x38);
1475ecc6ff95SOndrej Zary 			}
1476ecc6ff95SOndrej Zary 			for (k = 0; k < 4; k++) {
1477ecc6ff95SOndrej Zary 				atp_writew_base(atpdev, 0x3c, n++);
1478bcd5c59fSHannes Reinecke 				((u32 *)&atpdev->sp[m][0])[k] =
1479bcd5c59fSHannes Reinecke 					atp_readl_base(atpdev, 0x38);
1480ecc6ff95SOndrej Zary 			}
1481ecc6ff95SOndrej Zary 			n += 8;
1482ecc6ff95SOndrej Zary 		}
1483ecc6ff95SOndrej Zary 	}
1484ecc6ff95SOndrej Zary 	c = atp_readb_base(atpdev, 0x29);
1485ecc6ff95SOndrej Zary 	atp_writeb_base(atpdev, 0x29, c & 0xfb);
1486ecc6ff95SOndrej Zary 	for (c = 0; c < 2; c++) {
1487ecc6ff95SOndrej Zary 		atpdev->ultra_map[c] = 0;
1488ecc6ff95SOndrej Zary 		atpdev->async[c] = 0;
1489ecc6ff95SOndrej Zary 		for (k = 0; k < 16; k++) {
1490ecc6ff95SOndrej Zary 			n = 1 << k;
1491ecc6ff95SOndrej Zary 			if (atpdev->sp[c][k] > 1)
1492ecc6ff95SOndrej Zary 				atpdev->ultra_map[c] |= n;
1493ecc6ff95SOndrej Zary 			else
1494ecc6ff95SOndrej Zary 				if (atpdev->sp[c][k] == 0)
1495ecc6ff95SOndrej Zary 					atpdev->async[c] |= n;
1496ecc6ff95SOndrej Zary 		}
1497ecc6ff95SOndrej Zary 		atpdev->async[c] = ~(atpdev->async[c]);
1498ecc6ff95SOndrej Zary 
1499ecc6ff95SOndrej Zary 		if (atpdev->global_map[c] == 0) {
1500ecc6ff95SOndrej Zary 			k = setupdata[c][1];
1501ecc6ff95SOndrej Zary 			if ((k & 0x40) != 0)
1502ecc6ff95SOndrej Zary 				atpdev->global_map[c] |= 0x20;
1503ecc6ff95SOndrej Zary 			k &= 0x07;
1504ecc6ff95SOndrej Zary 			atpdev->global_map[c] |= k;
1505ecc6ff95SOndrej Zary 			if ((setupdata[c][2] & 0x04) != 0)
1506ecc6ff95SOndrej Zary 				atpdev->global_map[c] |= 0x08;
1507ecc6ff95SOndrej Zary 			atpdev->host_id[c] = setupdata[c][0] & 0x07;
1508ecc6ff95SOndrej Zary 		}
1509ecc6ff95SOndrej Zary 	}
1510ecc6ff95SOndrej Zary 
1511ecc6ff95SOndrej Zary 	k = atp_readb_base(atpdev, 0x28) & 0x8f;
1512ecc6ff95SOndrej Zary 	k |= 0x10;
1513ecc6ff95SOndrej Zary 	atp_writeb_base(atpdev, 0x28, k);
1514ecc6ff95SOndrej Zary 	atp_writeb_pci(atpdev, 0, 1, 0x80);
1515ecc6ff95SOndrej Zary 	atp_writeb_pci(atpdev, 1, 1, 0x80);
1516dcaa0c12SJia-Ju Bai 	msleep(100);
1517ecc6ff95SOndrej Zary 	atp_writeb_pci(atpdev, 0, 1, 0);
1518ecc6ff95SOndrej Zary 	atp_writeb_pci(atpdev, 1, 1, 0);
1519dcaa0c12SJia-Ju Bai 	msleep(1000);
1520ecc6ff95SOndrej Zary 	atp_readb_io(atpdev, 0, 0x1b);
1521ecc6ff95SOndrej Zary 	atp_readb_io(atpdev, 0, 0x17);
1522ecc6ff95SOndrej Zary 	atp_readb_io(atpdev, 1, 0x1b);
1523ecc6ff95SOndrej Zary 	atp_readb_io(atpdev, 1, 0x17);
1524ecc6ff95SOndrej Zary 
1525ecc6ff95SOndrej Zary 	k = atpdev->host_id[0];
1526ecc6ff95SOndrej Zary 	if (k > 7)
1527ecc6ff95SOndrej Zary 		k = (k & 0x07) | 0x40;
1528ecc6ff95SOndrej Zary 	atp_set_host_id(atpdev, 0, k);
1529ecc6ff95SOndrej Zary 
1530ecc6ff95SOndrej Zary 	k = atpdev->host_id[1];
1531ecc6ff95SOndrej Zary 	if (k > 7)
1532ecc6ff95SOndrej Zary 		k = (k & 0x07) | 0x40;
1533ecc6ff95SOndrej Zary 	atp_set_host_id(atpdev, 1, k);
1534ecc6ff95SOndrej Zary 
1535dcaa0c12SJia-Ju Bai 	msleep(600); /* this delay used to be called tscam_885() */
1536ecc6ff95SOndrej Zary 	dev_info(&pdev->dev, "Scanning Channel A SCSI Device ...\n");
1537ecc6ff95SOndrej Zary 	atp_is(atpdev, 0, true, atp_readb_io(atpdev, 0, 0x1b) >> 7);
1538ecc6ff95SOndrej Zary 	atp_writeb_io(atpdev, 0, 0x16, 0x80);
1539ecc6ff95SOndrej Zary 	dev_info(&pdev->dev, "Scanning Channel B SCSI Device ...\n");
1540ecc6ff95SOndrej Zary 	atp_is(atpdev, 1, true, atp_readb_io(atpdev, 1, 0x1b) >> 7);
1541ecc6ff95SOndrej Zary 	atp_writeb_io(atpdev, 1, 0x16, 0x80);
1542ecc6ff95SOndrej Zary 	k = atp_readb_base(atpdev, 0x28) & 0xcf;
1543ecc6ff95SOndrej Zary 	k |= 0xc0;
1544ecc6ff95SOndrej Zary 	atp_writeb_base(atpdev, 0x28, k);
1545ecc6ff95SOndrej Zary 	k = atp_readb_base(atpdev, 0x1f) | 0x80;
1546ecc6ff95SOndrej Zary 	atp_writeb_base(atpdev, 0x1f, k);
1547ecc6ff95SOndrej Zary 	k = atp_readb_base(atpdev, 0x29) | 0x01;
1548ecc6ff95SOndrej Zary 	atp_writeb_base(atpdev, 0x29, k);
1549ecc6ff95SOndrej Zary 	shpnt->max_id = 16;
1550ecc6ff95SOndrej Zary 	shpnt->max_lun = (atpdev->global_map[0] & 0x07) + 1;
1551ecc6ff95SOndrej Zary 	shpnt->max_channel = 1;
1552ecc6ff95SOndrej Zary 	shpnt->this_id = atpdev->host_id[0];
1553ecc6ff95SOndrej Zary }
1554ecc6ff95SOndrej Zary 
15551da177e4SLinus Torvalds /* return non-zero on detection */
15561da177e4SLinus Torvalds static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
15571da177e4SLinus Torvalds {
15581da177e4SLinus Torvalds 	struct Scsi_Host *shpnt = NULL;
1559bdd5ac40SOndrej Zary 	struct atp_unit *atpdev;
1560bdd5ac40SOndrej Zary 	int err;
15611da177e4SLinus Torvalds 
1562b1e85063SOndrej Zary 	if (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610 && pdev->revision < 2) {
1563b1e85063SOndrej Zary 		dev_err(&pdev->dev, "ATP850S chips (AEC6710L/F cards) are not supported.\n");
1564b1e85063SOndrej Zary 		return -ENODEV;
1565b1e85063SOndrej Zary 	}
1566b1e85063SOndrej Zary 
1567bdd5ac40SOndrej Zary 	err = pci_enable_device(pdev);
1568bdd5ac40SOndrej Zary 	if (err)
1569bdd5ac40SOndrej Zary 		goto fail;
15701da177e4SLinus Torvalds 
157148ecddb4SChristoph Hellwig 	if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) {
15721da177e4SLinus Torvalds 		printk(KERN_ERR "atp870u: DMA mask required but not available.\n");
1573bdd5ac40SOndrej Zary 		err = -EIO;
1574bdd5ac40SOndrej Zary 		goto disable_device;
15751da177e4SLinus Torvalds 	}
15761da177e4SLinus Torvalds 
157711ec1318SOndrej Zary 	err = pci_request_regions(pdev, "atp870u");
157811ec1318SOndrej Zary 	if (err)
157911ec1318SOndrej Zary 		goto disable_device;
158011ec1318SOndrej Zary 	pci_set_master(pdev);
158111ec1318SOndrej Zary 
1582bdd5ac40SOndrej Zary 	err = -ENOMEM;
1583bdd5ac40SOndrej Zary 	shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
1584bdd5ac40SOndrej Zary 	if (!shpnt)
158511ec1318SOndrej Zary 		goto release_region;
1586bdd5ac40SOndrej Zary 
1587bdd5ac40SOndrej Zary 	atpdev = shost_priv(shpnt);
1588bdd5ac40SOndrej Zary 
1589bdd5ac40SOndrej Zary 	atpdev->host = shpnt;
1590bdd5ac40SOndrej Zary 	atpdev->pdev = pdev;
1591bdd5ac40SOndrej Zary 	pci_set_drvdata(pdev, atpdev);
1592bdd5ac40SOndrej Zary 
15936c9b9c55SOndrej Zary 	shpnt->io_port = pci_resource_start(pdev, 0);
15946c9b9c55SOndrej Zary 	shpnt->io_port &= 0xfffffff8;
15956c9b9c55SOndrej Zary 	shpnt->n_io_port = pci_resource_len(pdev, 0);
15966c9b9c55SOndrej Zary 	atpdev->baseport = shpnt->io_port;
15976c9b9c55SOndrej Zary 	shpnt->unique_id = shpnt->io_port;
15986c9b9c55SOndrej Zary 	shpnt->irq = pdev->irq;
15991da177e4SLinus Torvalds 
1600f5f53a38SOndrej Zary 	err = atp870u_init_tables(shpnt);
1601f5f53a38SOndrej Zary 	if (err) {
1602f5f53a38SOndrej Zary 		dev_err(&pdev->dev, "Unable to allocate tables for Acard controller\n");
1603f5f53a38SOndrej Zary 		goto unregister;
1604f5f53a38SOndrej Zary 	}
1605f5f53a38SOndrej Zary 
1606c7e6a029SOndrej Zary 	if (is880(atpdev))
1607c7e6a029SOndrej Zary 		atp880_init(shpnt);
1608ecc6ff95SOndrej Zary 	else if (is885(atpdev))
1609ecc6ff95SOndrej Zary 		atp885_init(shpnt);
16104190230eSOndrej Zary 	else
16114190230eSOndrej Zary 		atp870_init(shpnt);
16121da177e4SLinus Torvalds 
16131729c0d2SOndrej Zary 	err = request_irq(shpnt->irq, atp870u_intr_handle, IRQF_SHARED, "atp870u", shpnt);
16141729c0d2SOndrej Zary 	if (err) {
16151729c0d2SOndrej Zary 		dev_err(&pdev->dev, "Unable to allocate IRQ %d.\n", shpnt->irq);
16161729c0d2SOndrej Zary 		goto free_tables;
16171729c0d2SOndrej Zary 	}
16181729c0d2SOndrej Zary 
1619bdd5ac40SOndrej Zary 	err = scsi_add_host(shpnt, &pdev->dev);
1620bdd5ac40SOndrej Zary 	if (err)
16211da177e4SLinus Torvalds 		goto scsi_add_fail;
16221da177e4SLinus Torvalds 	scsi_scan_host(shpnt);
16231729c0d2SOndrej Zary 
16241da177e4SLinus Torvalds 	return 0;
16251da177e4SLinus Torvalds 
16261da177e4SLinus Torvalds scsi_add_fail:
16276c9b9c55SOndrej Zary 	free_irq(shpnt->irq, shpnt);
16281da177e4SLinus Torvalds free_tables:
16291da177e4SLinus Torvalds 	atp870u_free_tables(shpnt);
16301da177e4SLinus Torvalds unregister:
16311da177e4SLinus Torvalds 	scsi_host_put(shpnt);
163211ec1318SOndrej Zary release_region:
163311ec1318SOndrej Zary 	pci_release_regions(pdev);
1634bdd5ac40SOndrej Zary disable_device:
1635bdd5ac40SOndrej Zary 	pci_disable_device(pdev);
1636bdd5ac40SOndrej Zary fail:
1637bdd5ac40SOndrej Zary 	return err;
16381da177e4SLinus Torvalds }
16391da177e4SLinus Torvalds 
16401da177e4SLinus Torvalds /* The abort command does not leave the device in a clean state where
16411da177e4SLinus Torvalds    it is available to be used again.  Until this gets worked out, we will
16421da177e4SLinus Torvalds    leave it commented out.  */
16431da177e4SLinus Torvalds 
16441da177e4SLinus Torvalds static int atp870u_abort(struct scsi_cmnd * SCpnt)
16451da177e4SLinus Torvalds {
16461da177e4SLinus Torvalds 	unsigned char  j, k, c;
16471da177e4SLinus Torvalds 	struct scsi_cmnd *workrequ;
16481da177e4SLinus Torvalds 	struct atp_unit *dev;
16491da177e4SLinus Torvalds 	struct Scsi_Host *host;
16501da177e4SLinus Torvalds 	host = SCpnt->device->host;
16511da177e4SLinus Torvalds 
16521da177e4SLinus Torvalds 	dev = (struct atp_unit *)&host->hostdata;
1653422c0d61SJeff Garzik 	c = scmd_channel(SCpnt);
16541da177e4SLinus Torvalds 	printk(" atp870u: abort Channel = %x \n", c);
16551da177e4SLinus Torvalds 	printk("working=%x last_cmd=%x ", dev->working[c], dev->last_cmd[c]);
16561da177e4SLinus Torvalds 	printk(" quhdu=%x quendu=%x ", dev->quhd[c], dev->quend[c]);
16571da177e4SLinus Torvalds 	for (j = 0; j < 0x18; j++) {
16586a3cebb6SOndrej Zary 		printk(" r%2x=%2x", j, atp_readb_io(dev, c, j));
16591da177e4SLinus Torvalds 	}
16606a3cebb6SOndrej Zary 	printk(" r1c=%2x", atp_readb_io(dev, c, 0x1c));
16616a3cebb6SOndrej Zary 	printk(" r1f=%2x in_snd=%2x ", atp_readb_io(dev, c, 0x1f), dev->in_snd[c]);
16626a3cebb6SOndrej Zary 	printk(" d00=%2x", atp_readb_pci(dev, c, 0x00));
16636a3cebb6SOndrej Zary 	printk(" d02=%2x", atp_readb_pci(dev, c, 0x02));
16641da177e4SLinus Torvalds 	for(j=0;j<16;j++) {
16651da177e4SLinus Torvalds 	   if (dev->id[c][j].curr_req != NULL) {
16661da177e4SLinus Torvalds 		workrequ = dev->id[c][j].curr_req;
16671da177e4SLinus Torvalds 		printk("\n que cdb= ");
16681da177e4SLinus Torvalds 		for (k=0; k < workrequ->cmd_len; k++) {
16691da177e4SLinus Torvalds 		    printk(" %2x ",workrequ->cmnd[k]);
16701da177e4SLinus Torvalds 		}
16711da177e4SLinus Torvalds 		printk(" last_lenu= %x ",(unsigned int)dev->id[c][j].last_len);
16721da177e4SLinus Torvalds 	   }
16731da177e4SLinus Torvalds 	}
16741da177e4SLinus Torvalds 	return SUCCESS;
16751da177e4SLinus Torvalds }
16761da177e4SLinus Torvalds 
16771da177e4SLinus Torvalds static const char *atp870u_info(struct Scsi_Host *notused)
16781da177e4SLinus Torvalds {
16791da177e4SLinus Torvalds 	static char buffer[128];
16801da177e4SLinus Torvalds 
16811da177e4SLinus Torvalds 	strcpy(buffer, "ACARD AEC-6710/6712/67160 PCI Ultra/W/LVD SCSI-3 Adapter Driver V2.6+ac ");
16821da177e4SLinus Torvalds 
16831da177e4SLinus Torvalds 	return buffer;
16841da177e4SLinus Torvalds }
16851da177e4SLinus Torvalds 
1686d773e422SAl Viro static int atp870u_show_info(struct seq_file *m, struct Scsi_Host *HBAptr)
16871da177e4SLinus Torvalds {
16883d30079cSRasmus Villemoes 	seq_puts(m, "ACARD AEC-671X Driver Version: 2.6+ac\n\n"
16893d30079cSRasmus Villemoes 		"Adapter Configuration:\n");
1690d773e422SAl Viro 	seq_printf(m, "               Base IO: %#.4lx\n", HBAptr->io_port);
1691d773e422SAl Viro 	seq_printf(m, "                   IRQ: %d\n", HBAptr->irq);
1692d773e422SAl Viro 	return 0;
16931da177e4SLinus Torvalds }
16941da177e4SLinus Torvalds 
16951da177e4SLinus Torvalds 
16961da177e4SLinus Torvalds static int atp870u_biosparam(struct scsi_device *disk, struct block_device *dev,
16971da177e4SLinus Torvalds 			sector_t capacity, int *ip)
16981da177e4SLinus Torvalds {
16991da177e4SLinus Torvalds 	int heads, sectors, cylinders;
17001da177e4SLinus Torvalds 
17011da177e4SLinus Torvalds 	heads = 64;
17021da177e4SLinus Torvalds 	sectors = 32;
17031da177e4SLinus Torvalds 	cylinders = (unsigned long)capacity / (heads * sectors);
17041da177e4SLinus Torvalds 	if (cylinders > 1024) {
17051da177e4SLinus Torvalds 		heads = 255;
17061da177e4SLinus Torvalds 		sectors = 63;
17071da177e4SLinus Torvalds 		cylinders = (unsigned long)capacity / (heads * sectors);
17081da177e4SLinus Torvalds 	}
17091da177e4SLinus Torvalds 	ip[0] = heads;
17101da177e4SLinus Torvalds 	ip[1] = sectors;
17111da177e4SLinus Torvalds 	ip[2] = cylinders;
17121da177e4SLinus Torvalds 
17131da177e4SLinus Torvalds 	return 0;
17141da177e4SLinus Torvalds }
17151da177e4SLinus Torvalds 
17161da177e4SLinus Torvalds static void atp870u_remove (struct pci_dev *pdev)
17171da177e4SLinus Torvalds {
17181da177e4SLinus Torvalds 	struct atp_unit *devext = pci_get_drvdata(pdev);
17191da177e4SLinus Torvalds 	struct Scsi_Host *pshost = devext->host;
17201da177e4SLinus Torvalds 
17211da177e4SLinus Torvalds 	scsi_remove_host(pshost);
17221da177e4SLinus Torvalds 	free_irq(pshost->irq, pshost);
172311ec1318SOndrej Zary 	pci_release_regions(pdev);
172411ec1318SOndrej Zary 	pci_disable_device(pdev);
17251da177e4SLinus Torvalds 	atp870u_free_tables(pshost);
17261da177e4SLinus Torvalds 	scsi_host_put(pshost);
17271da177e4SLinus Torvalds }
17281da177e4SLinus Torvalds MODULE_LICENSE("GPL");
17291da177e4SLinus Torvalds 
17301da177e4SLinus Torvalds static struct scsi_host_template atp870u_template = {
17311da177e4SLinus Torvalds      .module			= THIS_MODULE,
17321da177e4SLinus Torvalds      .name			= "atp870u"		/* name */,
17331da177e4SLinus Torvalds      .proc_name			= "atp870u",
1734d773e422SAl Viro      .show_info			= atp870u_show_info,
17351da177e4SLinus Torvalds      .info			= atp870u_info		/* info */,
17361da177e4SLinus Torvalds      .queuecommand		= atp870u_queuecommand	/* queuecommand */,
17371da177e4SLinus Torvalds      .eh_abort_handler		= atp870u_abort		/* abort */,
17381da177e4SLinus Torvalds      .bios_param		= atp870u_biosparam	/* biosparm */,
17391da177e4SLinus Torvalds      .can_queue			= qcnt			/* can_queue */,
17401da177e4SLinus Torvalds      .this_id			= 7			/* SCSI ID */,
174135c33633SFinn Thain      .sg_tablesize		= ATP870U_SCATTER	/*SG_ALL*/,
17421da177e4SLinus Torvalds      .max_sectors		= ATP870U_MAX_SECTORS,
17431da177e4SLinus Torvalds };
17441da177e4SLinus Torvalds 
17451da177e4SLinus Torvalds static struct pci_device_id atp870u_id_table[] = {
17461da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP885_DEVID)			  },
17471da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID1)		  },
17481da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID2)		  },
17491da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7610)    },
17501da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612UW)  },
17511da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612U)   },
17521da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612S)   },
17531da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612D)	  },
17541da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612SUW) },
17551da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_8060)	  },
17561da177e4SLinus Torvalds 	{ 0, },
17571da177e4SLinus Torvalds };
17581da177e4SLinus Torvalds 
17591da177e4SLinus Torvalds MODULE_DEVICE_TABLE(pci, atp870u_id_table);
17601da177e4SLinus Torvalds 
17611da177e4SLinus Torvalds static struct pci_driver atp870u_driver = {
17621da177e4SLinus Torvalds 	.id_table	= atp870u_id_table,
17631da177e4SLinus Torvalds 	.name		= "atp870u",
17641da177e4SLinus Torvalds 	.probe		= atp870u_probe,
17656f039790SGreg Kroah-Hartman 	.remove		= atp870u_remove,
17661da177e4SLinus Torvalds };
17671da177e4SLinus Torvalds 
17681ccd7d68SOndrej Zary module_pci_driver(atp870u_driver);
17691da177e4SLinus Torvalds 
1770bcd5c59fSHannes Reinecke static void atp_is(struct atp_unit *dev, unsigned char c, bool wide_chip,
1771bcd5c59fSHannes Reinecke 		   unsigned char lvdmode)
17721da177e4SLinus Torvalds {
1773fa50b308SOndrej Zary 	unsigned char i, j, k, rmb, n;
17741da177e4SLinus Torvalds 	unsigned short int m;
17751da177e4SLinus Torvalds 	static unsigned char mbuf[512];
17761da177e4SLinus Torvalds 	static unsigned char satn[9] = { 0, 0, 0, 0, 0, 0, 0, 6, 6 };
17771da177e4SLinus Torvalds 	static unsigned char inqd[9] = { 0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6 };
17781da177e4SLinus Torvalds 	static unsigned char synn[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
17791da177e4SLinus Torvalds 	unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
17801da177e4SLinus Torvalds 	static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
1781460da918SOndrej Zary 	static unsigned char synw_870[6] = { 0x80, 1, 3, 1, 0x0c, 0x07 };
17821da177e4SLinus Torvalds 	unsigned char synuw[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
17831da177e4SLinus Torvalds 	static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
17841da177e4SLinus Torvalds 	static unsigned char u3[9] = { 0x80, 1, 6, 4, 0x09, 00, 0x0e, 0x01, 0x02 };
17851da177e4SLinus Torvalds 
17861da177e4SLinus Torvalds 	for (i = 0; i < 16; i++) {
1787197fb8d8SOndrej Zary 		if (!wide_chip && (i > 7))
1788197fb8d8SOndrej Zary 			break;
17891da177e4SLinus Torvalds 		m = 1;
17901da177e4SLinus Torvalds 		m = m << i;
17911da177e4SLinus Torvalds 		if ((m & dev->active_id[c]) != 0) {
17921da177e4SLinus Torvalds 			continue;
17931da177e4SLinus Torvalds 		}
17941da177e4SLinus Torvalds 		if (i == dev->host_id[c]) {
17951da177e4SLinus Torvalds 			printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_id[c]);
17961da177e4SLinus Torvalds 			continue;
17971da177e4SLinus Torvalds 		}
1798197fb8d8SOndrej Zary 		atp_writeb_io(dev, c, 0x1b, wide_chip ? 0x01 : 0x00);
17995d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 1, 0x08);
18005d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 2, 0x7f);
18015d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 3, satn[0]);
18025d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 4, satn[1]);
18035d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 5, satn[2]);
18045d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 6, satn[3]);
18055d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 7, satn[4]);
18065d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 8, satn[5]);
18075d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x0f, 0);
18085d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
18095d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
18105d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, satn[6]);
18115d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, satn[7]);
18121da177e4SLinus Torvalds 		j = i;
18131da177e4SLinus Torvalds 		if ((j & 0x08) != 0) {
18141da177e4SLinus Torvalds 			j = (j & 0x07) | 0x40;
18151da177e4SLinus Torvalds 		}
18165d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x15, j);
18175d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, satn[8]);
18181da177e4SLinus Torvalds 
18195d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
18201da177e4SLinus Torvalds 			cpu_relax();
182180b52a7fSOndrej Zary 
182280b52a7fSOndrej Zary 		if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e)
18231da177e4SLinus Torvalds 			continue;
182480b52a7fSOndrej Zary 
18255d2a5a4fSOndrej Zary 		while (atp_readb_io(dev, c, 0x17) != 0x8e)
18261da177e4SLinus Torvalds 			cpu_relax();
182780b52a7fSOndrej Zary 
18281da177e4SLinus Torvalds 		dev->active_id[c] |= m;
18291da177e4SLinus Torvalds 
18305d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x10, 0x30);
1831b922a449SOndrej Zary 		if (is885(dev) || is880(dev))
18325d2a5a4fSOndrej Zary 			atp_writeb_io(dev, c, 0x14, 0x00);
1833460da918SOndrej Zary 		else /* result of is870() merge - is this a bug? */
1834460da918SOndrej Zary 			atp_writeb_io(dev, c, 0x04, 0x00);
18351da177e4SLinus Torvalds 
18361da177e4SLinus Torvalds phase_cmd:
18375d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
183880b52a7fSOndrej Zary 
18395d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
18401da177e4SLinus Torvalds 			cpu_relax();
184180b52a7fSOndrej Zary 
18425d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
18431da177e4SLinus Torvalds 		if (j != 0x16) {
18445d2a5a4fSOndrej Zary 			atp_writeb_io(dev, c, 0x10, 0x41);
18451da177e4SLinus Torvalds 			goto phase_cmd;
18461da177e4SLinus Torvalds 		}
18471da177e4SLinus Torvalds sel_ok:
18485d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 3, inqd[0]);
18495d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 4, inqd[1]);
18505d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 5, inqd[2]);
18515d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 6, inqd[3]);
18525d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 7, inqd[4]);
18535d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 8, inqd[5]);
18545d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x0f, 0);
18555d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
18565d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
18575d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, inqd[6]);
18585d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, inqd[7]);
18595d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, inqd[8]);
186080b52a7fSOndrej Zary 
18615d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
18621da177e4SLinus Torvalds 			cpu_relax();
186380b52a7fSOndrej Zary 
186480b52a7fSOndrej Zary 		if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e)
18651da177e4SLinus Torvalds 			continue;
186680b52a7fSOndrej Zary 
18675d2a5a4fSOndrej Zary 		while (atp_readb_io(dev, c, 0x17) != 0x8e)
18681da177e4SLinus Torvalds 			cpu_relax();
186980b52a7fSOndrej Zary 
1870197fb8d8SOndrej Zary 		if (wide_chip)
18715d2a5a4fSOndrej Zary 			atp_writeb_io(dev, c, 0x1b, 0x00);
1872197fb8d8SOndrej Zary 
18735d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
18741da177e4SLinus Torvalds 		j = 0;
18751da177e4SLinus Torvalds rd_inq_data:
18765d2a5a4fSOndrej Zary 		k = atp_readb_io(dev, c, 0x1f);
18771da177e4SLinus Torvalds 		if ((k & 0x01) != 0) {
18785d2a5a4fSOndrej Zary 			mbuf[j++] = atp_readb_io(dev, c, 0x19);
18791da177e4SLinus Torvalds 			goto rd_inq_data;
18801da177e4SLinus Torvalds 		}
18811da177e4SLinus Torvalds 		if ((k & 0x80) == 0) {
18821da177e4SLinus Torvalds 			goto rd_inq_data;
18831da177e4SLinus Torvalds 		}
18845d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
18851da177e4SLinus Torvalds 		if (j == 0x16) {
18861da177e4SLinus Torvalds 			goto inq_ok;
18871da177e4SLinus Torvalds 		}
18885d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x10, 0x46);
18895d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
18905d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, 0);
18915d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0);
18925d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
189380b52a7fSOndrej Zary 
18945d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
18951da177e4SLinus Torvalds 			cpu_relax();
189680b52a7fSOndrej Zary 
189780b52a7fSOndrej Zary 		if (atp_readb_io(dev, c, 0x17) != 0x16)
18981da177e4SLinus Torvalds 			goto sel_ok;
189980b52a7fSOndrej Zary 
19001da177e4SLinus Torvalds inq_ok:
19011da177e4SLinus Torvalds 		mbuf[36] = 0;
19021da177e4SLinus Torvalds 		printk(KERN_INFO "         ID: %2d  %s\n", i, &mbuf[8]);
19031da177e4SLinus Torvalds 		dev->id[c][i].devtype = mbuf[0];
19041da177e4SLinus Torvalds 		rmb = mbuf[1];
19051da177e4SLinus Torvalds 		n = mbuf[7];
1906197fb8d8SOndrej Zary 		if (!wide_chip)
1907197fb8d8SOndrej Zary 			goto not_wide;
19081da177e4SLinus Torvalds 		if ((mbuf[7] & 0x60) == 0) {
19091da177e4SLinus Torvalds 			goto not_wide;
19101da177e4SLinus Torvalds 		}
1911b922a449SOndrej Zary 		if (is885(dev) || is880(dev)) {
1912197fb8d8SOndrej Zary 			if ((i < 8) && ((dev->global_map[c] & 0x20) == 0))
1913197fb8d8SOndrej Zary 				goto not_wide;
1914197fb8d8SOndrej Zary 		} else { /* result of is870() merge - is this a bug? */
1915197fb8d8SOndrej Zary 			if ((dev->global_map[c] & 0x20) == 0)
19161da177e4SLinus Torvalds 				goto not_wide;
19171da177e4SLinus Torvalds 		}
19181da177e4SLinus Torvalds 		if (lvdmode == 0) {
19191da177e4SLinus Torvalds 			goto chg_wide;
19201da177e4SLinus Torvalds 		}
192180b52a7fSOndrej Zary 		if (dev->sp[c][i] != 0x04)	// force u2
192280b52a7fSOndrej Zary 		{
19231da177e4SLinus Torvalds 			goto chg_wide;
19241da177e4SLinus Torvalds 		}
19251da177e4SLinus Torvalds 
19265d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x1b, 0x01);
19275d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 3, satn[0]);
19285d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 4, satn[1]);
19295d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 5, satn[2]);
19305d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 6, satn[3]);
19315d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 7, satn[4]);
19325d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 8, satn[5]);
19335d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x0f, 0);
19345d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
19355d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
19365d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, satn[6]);
19375d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, satn[7]);
19385d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, satn[8]);
19391da177e4SLinus Torvalds 
19405d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
19411da177e4SLinus Torvalds 			cpu_relax();
194280b52a7fSOndrej Zary 
194380b52a7fSOndrej Zary 		if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e)
19441da177e4SLinus Torvalds 			continue;
194580b52a7fSOndrej Zary 
19465d2a5a4fSOndrej Zary 		while (atp_readb_io(dev, c, 0x17) != 0x8e)
19471da177e4SLinus Torvalds 			cpu_relax();
194880b52a7fSOndrej Zary 
19491da177e4SLinus Torvalds try_u3:
19501da177e4SLinus Torvalds 		j = 0;
19515d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x09);
19525d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
19531da177e4SLinus Torvalds 
19545d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) {
19555d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0)
19565d2a5a4fSOndrej Zary 				atp_writeb_io(dev, c, 0x19, u3[j++]);
19571da177e4SLinus Torvalds 			cpu_relax();
19581da177e4SLinus Torvalds 		}
195980b52a7fSOndrej Zary 
19605d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00)
19611da177e4SLinus Torvalds 			cpu_relax();
196280b52a7fSOndrej Zary 
19635d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
19641da177e4SLinus Torvalds 		if (j == 0x0f) {
19651da177e4SLinus Torvalds 			goto u3p_in;
19661da177e4SLinus Torvalds 		}
19671da177e4SLinus Torvalds 		if (j == 0x0a) {
19681da177e4SLinus Torvalds 			goto u3p_cmd;
19691da177e4SLinus Torvalds 		}
19701da177e4SLinus Torvalds 		if (j == 0x0e) {
19711da177e4SLinus Torvalds 			goto try_u3;
19721da177e4SLinus Torvalds 		}
19731da177e4SLinus Torvalds 		continue;
19741da177e4SLinus Torvalds u3p_out:
19755d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
19765d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) {
19775d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0)
19785d2a5a4fSOndrej Zary 				atp_writeb_io(dev, c, 0x19, 0);
19791da177e4SLinus Torvalds 			cpu_relax();
19801da177e4SLinus Torvalds 		}
19815d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
19821da177e4SLinus Torvalds 		if (j == 0x0f) {
19831da177e4SLinus Torvalds 			goto u3p_in;
19841da177e4SLinus Torvalds 		}
19851da177e4SLinus Torvalds 		if (j == 0x0a) {
19861da177e4SLinus Torvalds 			goto u3p_cmd;
19871da177e4SLinus Torvalds 		}
19881da177e4SLinus Torvalds 		if (j == 0x0e) {
19891da177e4SLinus Torvalds 			goto u3p_out;
19901da177e4SLinus Torvalds 		}
19911da177e4SLinus Torvalds 		continue;
19921da177e4SLinus Torvalds u3p_in:
19935d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x09);
19945d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
19951da177e4SLinus Torvalds 		k = 0;
19961da177e4SLinus Torvalds u3p_in1:
19975d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x1f);
19981da177e4SLinus Torvalds 		if ((j & 0x01) != 0) {
19995d2a5a4fSOndrej Zary 			mbuf[k++] = atp_readb_io(dev, c, 0x19);
20001da177e4SLinus Torvalds 			goto u3p_in1;
20011da177e4SLinus Torvalds 		}
20021da177e4SLinus Torvalds 		if ((j & 0x80) == 0x00) {
20031da177e4SLinus Torvalds 			goto u3p_in1;
20041da177e4SLinus Torvalds 		}
20055d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
20061da177e4SLinus Torvalds 		if (j == 0x0f) {
20071da177e4SLinus Torvalds 			goto u3p_in;
20081da177e4SLinus Torvalds 		}
20091da177e4SLinus Torvalds 		if (j == 0x0a) {
20101da177e4SLinus Torvalds 			goto u3p_cmd;
20111da177e4SLinus Torvalds 		}
20121da177e4SLinus Torvalds 		if (j == 0x0e) {
20131da177e4SLinus Torvalds 			goto u3p_out;
20141da177e4SLinus Torvalds 		}
20151da177e4SLinus Torvalds 		continue;
20161da177e4SLinus Torvalds u3p_cmd:
20175d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x10, 0x30);
20185d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x00);
20195d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
202080b52a7fSOndrej Zary 
20215d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00);
202280b52a7fSOndrej Zary 
20235d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
20241da177e4SLinus Torvalds 		if (j != 0x16) {
20251da177e4SLinus Torvalds 			if (j == 0x4e) {
20261da177e4SLinus Torvalds 				goto u3p_out;
20271da177e4SLinus Torvalds 			}
20281da177e4SLinus Torvalds 			continue;
20291da177e4SLinus Torvalds 		}
20301da177e4SLinus Torvalds 		if (mbuf[0] != 0x01) {
20311da177e4SLinus Torvalds 			goto chg_wide;
20321da177e4SLinus Torvalds 		}
20331da177e4SLinus Torvalds 		if (mbuf[1] != 0x06) {
20341da177e4SLinus Torvalds 			goto chg_wide;
20351da177e4SLinus Torvalds 		}
20361da177e4SLinus Torvalds 		if (mbuf[2] != 0x04) {
20371da177e4SLinus Torvalds 			goto chg_wide;
20381da177e4SLinus Torvalds 		}
20391da177e4SLinus Torvalds 		if (mbuf[3] == 0x09) {
20401da177e4SLinus Torvalds 			m = 1;
20411da177e4SLinus Torvalds 			m = m << i;
20421da177e4SLinus Torvalds 			dev->wide_id[c] |= m;
20431da177e4SLinus Torvalds 			dev->id[c][i].devsp = 0xce;
20441da177e4SLinus Torvalds #ifdef ED_DBGP
2045bcd5c59fSHannes Reinecke 			printk("dev->id[%2d][%2d].devsp = %2x\n",
2046bcd5c59fSHannes Reinecke 			       c, i, dev->id[c][i].devsp);
20471da177e4SLinus Torvalds #endif
20481da177e4SLinus Torvalds 			continue;
20491da177e4SLinus Torvalds 		}
20501da177e4SLinus Torvalds chg_wide:
20515d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x1b, 0x01);
20525d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 3, satn[0]);
20535d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 4, satn[1]);
20545d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 5, satn[2]);
20555d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 6, satn[3]);
20565d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 7, satn[4]);
20575d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 8, satn[5]);
20585d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x0f, 0);
20595d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
20605d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
20615d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, satn[6]);
20625d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, satn[7]);
20635d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, satn[8]);
20641da177e4SLinus Torvalds 
20655d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
20661da177e4SLinus Torvalds 			cpu_relax();
206780b52a7fSOndrej Zary 
2068bcd5c59fSHannes Reinecke 		if (atp_readb_io(dev, c, 0x17) != 0x11 &&
2069bcd5c59fSHannes Reinecke 		    atp_readb_io(dev, c, 0x17) != 0x8e)
20701da177e4SLinus Torvalds 			continue;
207180b52a7fSOndrej Zary 
20725d2a5a4fSOndrej Zary 		while (atp_readb_io(dev, c, 0x17) != 0x8e)
20731da177e4SLinus Torvalds 			cpu_relax();
207480b52a7fSOndrej Zary 
20751da177e4SLinus Torvalds try_wide:
20761da177e4SLinus Torvalds 		j = 0;
20775d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x05);
20785d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
20791da177e4SLinus Torvalds 
20805d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) {
20815d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0)
20825d2a5a4fSOndrej Zary 				atp_writeb_io(dev, c, 0x19, wide[j++]);
20831da177e4SLinus Torvalds 			cpu_relax();
20841da177e4SLinus Torvalds 		}
208580b52a7fSOndrej Zary 
20865d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00)
20871da177e4SLinus Torvalds 			cpu_relax();
208880b52a7fSOndrej Zary 
20895d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
20901da177e4SLinus Torvalds 		if (j == 0x0f) {
20911da177e4SLinus Torvalds 			goto widep_in;
20921da177e4SLinus Torvalds 		}
20931da177e4SLinus Torvalds 		if (j == 0x0a) {
20941da177e4SLinus Torvalds 			goto widep_cmd;
20951da177e4SLinus Torvalds 		}
20961da177e4SLinus Torvalds 		if (j == 0x0e) {
20971da177e4SLinus Torvalds 			goto try_wide;
20981da177e4SLinus Torvalds 		}
20991da177e4SLinus Torvalds 		continue;
21001da177e4SLinus Torvalds widep_out:
21015d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
21025d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) {
21035d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0)
21045d2a5a4fSOndrej Zary 				atp_writeb_io(dev, c, 0x19, 0);
21051da177e4SLinus Torvalds 			cpu_relax();
21061da177e4SLinus Torvalds 		}
21075d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
21081da177e4SLinus Torvalds 		if (j == 0x0f) {
21091da177e4SLinus Torvalds 			goto widep_in;
21101da177e4SLinus Torvalds 		}
21111da177e4SLinus Torvalds 		if (j == 0x0a) {
21121da177e4SLinus Torvalds 			goto widep_cmd;
21131da177e4SLinus Torvalds 		}
21141da177e4SLinus Torvalds 		if (j == 0x0e) {
21151da177e4SLinus Torvalds 			goto widep_out;
21161da177e4SLinus Torvalds 		}
21171da177e4SLinus Torvalds 		continue;
21181da177e4SLinus Torvalds widep_in:
21195d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0xff);
21205d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
21211da177e4SLinus Torvalds 		k = 0;
21221da177e4SLinus Torvalds widep_in1:
21235d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x1f);
21241da177e4SLinus Torvalds 		if ((j & 0x01) != 0) {
21255d2a5a4fSOndrej Zary 			mbuf[k++] = atp_readb_io(dev, c, 0x19);
21261da177e4SLinus Torvalds 			goto widep_in1;
21271da177e4SLinus Torvalds 		}
21281da177e4SLinus Torvalds 		if ((j & 0x80) == 0x00) {
21291da177e4SLinus Torvalds 			goto widep_in1;
21301da177e4SLinus Torvalds 		}
21315d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
21321da177e4SLinus Torvalds 		if (j == 0x0f) {
21331da177e4SLinus Torvalds 			goto widep_in;
21341da177e4SLinus Torvalds 		}
21351da177e4SLinus Torvalds 		if (j == 0x0a) {
21361da177e4SLinus Torvalds 			goto widep_cmd;
21371da177e4SLinus Torvalds 		}
21381da177e4SLinus Torvalds 		if (j == 0x0e) {
21391da177e4SLinus Torvalds 			goto widep_out;
21401da177e4SLinus Torvalds 		}
21411da177e4SLinus Torvalds 		continue;
21421da177e4SLinus Torvalds widep_cmd:
21435d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x10, 0x30);
21445d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x00);
21455d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
214680b52a7fSOndrej Zary 
21475d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
21481da177e4SLinus Torvalds 			cpu_relax();
214980b52a7fSOndrej Zary 
21505d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
21511da177e4SLinus Torvalds 		if (j != 0x16) {
21521da177e4SLinus Torvalds 			if (j == 0x4e) {
21531da177e4SLinus Torvalds 				goto widep_out;
21541da177e4SLinus Torvalds 			}
21551da177e4SLinus Torvalds 			continue;
21561da177e4SLinus Torvalds 		}
21571da177e4SLinus Torvalds 		if (mbuf[0] != 0x01) {
21581da177e4SLinus Torvalds 			goto not_wide;
21591da177e4SLinus Torvalds 		}
21601da177e4SLinus Torvalds 		if (mbuf[1] != 0x02) {
21611da177e4SLinus Torvalds 			goto not_wide;
21621da177e4SLinus Torvalds 		}
21631da177e4SLinus Torvalds 		if (mbuf[2] != 0x03) {
21641da177e4SLinus Torvalds 			goto not_wide;
21651da177e4SLinus Torvalds 		}
21661da177e4SLinus Torvalds 		if (mbuf[3] != 0x01) {
21671da177e4SLinus Torvalds 			goto not_wide;
21681da177e4SLinus Torvalds 		}
21691da177e4SLinus Torvalds 		m = 1;
21701da177e4SLinus Torvalds 		m = m << i;
21711da177e4SLinus Torvalds 		dev->wide_id[c] |= m;
21721da177e4SLinus Torvalds not_wide:
2173bcd5c59fSHannes Reinecke 		if ((dev->id[c][i].devtype == 0x00) ||
2174bcd5c59fSHannes Reinecke 		    (dev->id[c][i].devtype == 0x07) ||
2175bcd5c59fSHannes Reinecke 		    ((dev->id[c][i].devtype == 0x05) && ((n & 0x10) != 0))) {
21761da177e4SLinus Torvalds 			m = 1;
21771da177e4SLinus Torvalds 			m = m << i;
21781da177e4SLinus Torvalds 			if ((dev->async[c] & m) != 0) {
21791da177e4SLinus Torvalds 				goto set_sync;
21801da177e4SLinus Torvalds 			}
21811da177e4SLinus Torvalds 		}
21821da177e4SLinus Torvalds 		continue;
21831da177e4SLinus Torvalds set_sync:
2184b922a449SOndrej Zary 		if ((!is885(dev) && !is880(dev)) || (dev->sp[c][i] == 0x02)) {
21851da177e4SLinus Torvalds 			synu[4] = 0x0c;
21861da177e4SLinus Torvalds 			synuw[4] = 0x0c;
21871da177e4SLinus Torvalds 		} else {
21881da177e4SLinus Torvalds 			if (dev->sp[c][i] >= 0x03) {
21891da177e4SLinus Torvalds 				synu[4] = 0x0a;
21901da177e4SLinus Torvalds 				synuw[4] = 0x0a;
21911da177e4SLinus Torvalds 			}
21921da177e4SLinus Torvalds 		}
21931da177e4SLinus Torvalds 		j = 0;
21941da177e4SLinus Torvalds 		if ((m & dev->wide_id[c]) != 0) {
21951da177e4SLinus Torvalds 			j |= 0x01;
21961da177e4SLinus Torvalds 		}
21975d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x1b, j);
21985d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 3, satn[0]);
21995d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 4, satn[1]);
22005d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 5, satn[2]);
22015d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 6, satn[3]);
22025d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 7, satn[4]);
22035d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 8, satn[5]);
22045d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x0f, 0);
22055d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
22065d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
22075d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, satn[6]);
22085d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, satn[7]);
22095d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, satn[8]);
22101da177e4SLinus Torvalds 
22115d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
22121da177e4SLinus Torvalds 			cpu_relax();
221380b52a7fSOndrej Zary 
2214bcd5c59fSHannes Reinecke 		if (atp_readb_io(dev, c, 0x17) != 0x11 &&
2215bcd5c59fSHannes Reinecke 		    atp_readb_io(dev, c, 0x17) != 0x8e)
22161da177e4SLinus Torvalds 			continue;
221780b52a7fSOndrej Zary 
22185d2a5a4fSOndrej Zary 		while (atp_readb_io(dev, c, 0x17) != 0x8e)
22191da177e4SLinus Torvalds 			cpu_relax();
222080b52a7fSOndrej Zary 
22211da177e4SLinus Torvalds try_sync:
22221da177e4SLinus Torvalds 		j = 0;
22235d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x06);
22245d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
22251da177e4SLinus Torvalds 
22265d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) {
22275d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0) {
22281da177e4SLinus Torvalds 				if ((m & dev->wide_id[c]) != 0) {
2229b922a449SOndrej Zary 					if (is885(dev) || is880(dev)) {
22301da177e4SLinus Torvalds 						if ((m & dev->ultra_map[c]) != 0) {
22315d2a5a4fSOndrej Zary 							atp_writeb_io(dev, c, 0x19, synuw[j++]);
22321da177e4SLinus Torvalds 						} else {
22335d2a5a4fSOndrej Zary 							atp_writeb_io(dev, c, 0x19, synw[j++]);
22341da177e4SLinus Torvalds 						}
2235460da918SOndrej Zary 					} else
2236460da918SOndrej Zary 						atp_writeb_io(dev, c, 0x19, synw_870[j++]);
22371da177e4SLinus Torvalds 				} else {
22381da177e4SLinus Torvalds 					if ((m & dev->ultra_map[c]) != 0) {
22395d2a5a4fSOndrej Zary 						atp_writeb_io(dev, c, 0x19, synu[j++]);
22401da177e4SLinus Torvalds 					} else {
22415d2a5a4fSOndrej Zary 						atp_writeb_io(dev, c, 0x19, synn[j++]);
22421da177e4SLinus Torvalds 					}
22431da177e4SLinus Torvalds 				}
22441da177e4SLinus Torvalds 			}
22451da177e4SLinus Torvalds 		}
224680b52a7fSOndrej Zary 
22475d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00)
22481da177e4SLinus Torvalds 			cpu_relax();
224980b52a7fSOndrej Zary 
22505d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
22511da177e4SLinus Torvalds 		if (j == 0x0f) {
22521da177e4SLinus Torvalds 			goto phase_ins;
22531da177e4SLinus Torvalds 		}
22541da177e4SLinus Torvalds 		if (j == 0x0a) {
22551da177e4SLinus Torvalds 			goto phase_cmds;
22561da177e4SLinus Torvalds 		}
22571da177e4SLinus Torvalds 		if (j == 0x0e) {
22581da177e4SLinus Torvalds 			goto try_sync;
22591da177e4SLinus Torvalds 		}
22601da177e4SLinus Torvalds 		continue;
22611da177e4SLinus Torvalds phase_outs:
22625d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
22635d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) {
22645d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0x00)
22655d2a5a4fSOndrej Zary 				atp_writeb_io(dev, c, 0x19, 0x00);
22661da177e4SLinus Torvalds 			cpu_relax();
22671da177e4SLinus Torvalds 		}
22685d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
22691da177e4SLinus Torvalds 		if (j == 0x85) {
22701da177e4SLinus Torvalds 			goto tar_dcons;
22711da177e4SLinus Torvalds 		}
22721da177e4SLinus Torvalds 		j &= 0x0f;
22731da177e4SLinus Torvalds 		if (j == 0x0f) {
22741da177e4SLinus Torvalds 			goto phase_ins;
22751da177e4SLinus Torvalds 		}
22761da177e4SLinus Torvalds 		if (j == 0x0a) {
22771da177e4SLinus Torvalds 			goto phase_cmds;
22781da177e4SLinus Torvalds 		}
22791da177e4SLinus Torvalds 		if (j == 0x0e) {
22801da177e4SLinus Torvalds 			goto phase_outs;
22811da177e4SLinus Torvalds 		}
22821da177e4SLinus Torvalds 		continue;
22831da177e4SLinus Torvalds phase_ins:
2284b922a449SOndrej Zary 		if (is885(dev) || is880(dev))
22855d2a5a4fSOndrej Zary 			atp_writeb_io(dev, c, 0x14, 0x06);
2286460da918SOndrej Zary 		else
2287460da918SOndrej Zary 			atp_writeb_io(dev, c, 0x14, 0xff);
22885d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
22891da177e4SLinus Torvalds 		k = 0;
22901da177e4SLinus Torvalds phase_ins1:
22915d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x1f);
22921da177e4SLinus Torvalds 		if ((j & 0x01) != 0x00) {
22935d2a5a4fSOndrej Zary 			mbuf[k++] = atp_readb_io(dev, c, 0x19);
22941da177e4SLinus Torvalds 			goto phase_ins1;
22951da177e4SLinus Torvalds 		}
22961da177e4SLinus Torvalds 		if ((j & 0x80) == 0x00) {
22971da177e4SLinus Torvalds 			goto phase_ins1;
22981da177e4SLinus Torvalds 		}
229980b52a7fSOndrej Zary 
23005d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00);
230180b52a7fSOndrej Zary 
23025d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
23031da177e4SLinus Torvalds 		if (j == 0x85) {
23041da177e4SLinus Torvalds 			goto tar_dcons;
23051da177e4SLinus Torvalds 		}
23061da177e4SLinus Torvalds 		j &= 0x0f;
23071da177e4SLinus Torvalds 		if (j == 0x0f) {
23081da177e4SLinus Torvalds 			goto phase_ins;
23091da177e4SLinus Torvalds 		}
23101da177e4SLinus Torvalds 		if (j == 0x0a) {
23111da177e4SLinus Torvalds 			goto phase_cmds;
23121da177e4SLinus Torvalds 		}
23131da177e4SLinus Torvalds 		if (j == 0x0e) {
23141da177e4SLinus Torvalds 			goto phase_outs;
23151da177e4SLinus Torvalds 		}
23161da177e4SLinus Torvalds 		continue;
23171da177e4SLinus Torvalds phase_cmds:
23185d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x10, 0x30);
23191da177e4SLinus Torvalds tar_dcons:
23205d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x00);
23215d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
232280b52a7fSOndrej Zary 
23235d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
23241da177e4SLinus Torvalds 			cpu_relax();
232580b52a7fSOndrej Zary 
23265d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
23271da177e4SLinus Torvalds 		if (j != 0x16) {
23281da177e4SLinus Torvalds 			continue;
23291da177e4SLinus Torvalds 		}
23301da177e4SLinus Torvalds 		if (mbuf[0] != 0x01) {
23311da177e4SLinus Torvalds 			continue;
23321da177e4SLinus Torvalds 		}
23331da177e4SLinus Torvalds 		if (mbuf[1] != 0x03) {
23341da177e4SLinus Torvalds 			continue;
23351da177e4SLinus Torvalds 		}
23361da177e4SLinus Torvalds 		if (mbuf[4] == 0x00) {
23371da177e4SLinus Torvalds 			continue;
23381da177e4SLinus Torvalds 		}
23391da177e4SLinus Torvalds 		if (mbuf[3] > 0x64) {
23401da177e4SLinus Torvalds 			continue;
23411da177e4SLinus Torvalds 		}
2342b922a449SOndrej Zary 		if (is885(dev) || is880(dev)) {
23431da177e4SLinus Torvalds 			if (mbuf[4] > 0x0e) {
23441da177e4SLinus Torvalds 				mbuf[4] = 0x0e;
23451da177e4SLinus Torvalds 			}
2346460da918SOndrej Zary 		} else {
2347460da918SOndrej Zary 			if (mbuf[4] > 0x0c) {
2348460da918SOndrej Zary 				mbuf[4] = 0x0c;
2349460da918SOndrej Zary 			}
2350460da918SOndrej Zary 		}
23511da177e4SLinus Torvalds 		dev->id[c][i].devsp = mbuf[4];
2352b922a449SOndrej Zary 		if (is885(dev) || is880(dev))
23531da177e4SLinus Torvalds 			if (mbuf[3] < 0x0c) {
23541da177e4SLinus Torvalds 				j = 0xb0;
23551da177e4SLinus Torvalds 				goto set_syn_ok;
23561da177e4SLinus Torvalds 			}
23571da177e4SLinus Torvalds 		if ((mbuf[3] < 0x0d) && (rmb == 0)) {
23581da177e4SLinus Torvalds 			j = 0xa0;
23591da177e4SLinus Torvalds 			goto set_syn_ok;
23601da177e4SLinus Torvalds 		}
23611da177e4SLinus Torvalds 		if (mbuf[3] < 0x1a) {
23621da177e4SLinus Torvalds 			j = 0x20;
23631da177e4SLinus Torvalds 			goto set_syn_ok;
23641da177e4SLinus Torvalds 		}
23651da177e4SLinus Torvalds 		if (mbuf[3] < 0x33) {
23661da177e4SLinus Torvalds 			j = 0x40;
23671da177e4SLinus Torvalds 			goto set_syn_ok;
23681da177e4SLinus Torvalds 		}
23691da177e4SLinus Torvalds 		if (mbuf[3] < 0x4c) {
23701da177e4SLinus Torvalds 			j = 0x50;
23711da177e4SLinus Torvalds 			goto set_syn_ok;
23721da177e4SLinus Torvalds 		}
23731da177e4SLinus Torvalds 		j = 0x60;
23741da177e4SLinus Torvalds set_syn_ok:
23751da177e4SLinus Torvalds 		dev->id[c][i].devsp = (dev->id[c][i].devsp & 0x0f) | j;
23761da177e4SLinus Torvalds #ifdef ED_DBGP
2377bcd5c59fSHannes Reinecke 		printk("dev->id[%2d][%2d].devsp = %2x\n",
2378bcd5c59fSHannes Reinecke 		       c,i,dev->id[c][i].devsp);
23791da177e4SLinus Torvalds #endif
23801da177e4SLinus Torvalds 	}
23811da177e4SLinus Torvalds }
2382