xref: /openbmc/linux/drivers/scsi/atp870u.c (revision 6b71f60c)
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);
5151da177e4SLinus Torvalds 			(*workreq->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 /**
615*6b71f60cSLee 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 	if (done) {
6581da177e4SLinus Torvalds 		req_p->scsi_done = done;
6591da177e4SLinus Torvalds 	} else {
6601da177e4SLinus Torvalds #ifdef ED_DBGP
6611da177e4SLinus Torvalds 		printk( "atp870u_queuecommand: done can't be NULL\n");
6621da177e4SLinus Torvalds #endif
6631da177e4SLinus Torvalds 		req_p->result = 0;
6641da177e4SLinus Torvalds 		done(req_p);
6651da177e4SLinus Torvalds 		return 0;
6661da177e4SLinus Torvalds 	}
6671da177e4SLinus Torvalds 
6681da177e4SLinus Torvalds 	/*
6691da177e4SLinus Torvalds 	 *	Count new command
6701da177e4SLinus Torvalds 	 */
6711da177e4SLinus Torvalds 	dev->quend[c]++;
6721da177e4SLinus Torvalds 	if (dev->quend[c] >= qcnt) {
6731da177e4SLinus Torvalds 		dev->quend[c] = 0;
6741da177e4SLinus Torvalds 	}
6751da177e4SLinus Torvalds 
6761da177e4SLinus Torvalds 	/*
6771da177e4SLinus Torvalds 	 *	Check queue state
6781da177e4SLinus Torvalds 	 */
6791da177e4SLinus Torvalds 	if (dev->quhd[c] == dev->quend[c]) {
6801da177e4SLinus Torvalds 		if (dev->quend[c] == 0) {
6811da177e4SLinus Torvalds 			dev->quend[c] = qcnt;
6821da177e4SLinus Torvalds 		}
6831da177e4SLinus Torvalds #ifdef ED_DBGP
6841da177e4SLinus Torvalds 		printk("atp870u_queuecommand : dev->quhd[c] == dev->quend[c]\n");
6851da177e4SLinus Torvalds #endif
6861da177e4SLinus Torvalds 		dev->quend[c]--;
687f3272258SHannes Reinecke 		req_p->result = DID_BUS_BUSY << 16;
6881da177e4SLinus Torvalds 		done(req_p);
6891da177e4SLinus Torvalds 		return 0;
6901da177e4SLinus Torvalds 	}
6911da177e4SLinus Torvalds 	dev->quereq[c][dev->quend[c]] = req_p;
6921da177e4SLinus Torvalds #ifdef ED_DBGP
693bcd5c59fSHannes Reinecke 	printk("dev->ioport[c] = %x atp_readb_io(dev, c, 0x1c) = %x "
694bcd5c59fSHannes Reinecke 	       "dev->in_int[%d] = %d dev->in_snd[%d] = %d\n",
695bcd5c59fSHannes Reinecke 	       dev->ioport[c], atp_readb_io(dev, c, 0x1c), c,
696bcd5c59fSHannes Reinecke 	       dev->in_int[c],c,dev->in_snd[c]);
6971da177e4SLinus Torvalds #endif
698bcd5c59fSHannes Reinecke 	if ((atp_readb_io(dev, c, 0x1c) == 0) &&
699bcd5c59fSHannes Reinecke 	    (dev->in_int[c] == 0) &&
700bcd5c59fSHannes Reinecke 	    (dev->in_snd[c] == 0)) {
7011da177e4SLinus Torvalds #ifdef ED_DBGP
7021da177e4SLinus Torvalds 		printk("Call sent_s870(atp870u_queuecommand)\n");
7031da177e4SLinus Torvalds #endif
7041da177e4SLinus Torvalds 		send_s870(dev,c);
7051da177e4SLinus Torvalds 	}
7061da177e4SLinus Torvalds #ifdef ED_DBGP
7071da177e4SLinus Torvalds 	printk("atp870u_queuecommand : exit\n");
7081da177e4SLinus Torvalds #endif
7091da177e4SLinus Torvalds 	return 0;
7101da177e4SLinus Torvalds }
7111da177e4SLinus Torvalds 
712f281233dSJeff Garzik static DEF_SCSI_QCMD(atp870u_queuecommand)
713f281233dSJeff Garzik 
714*6b71f60cSLee Jones /*
7151da177e4SLinus Torvalds  *	send_s870	-	send a command to the controller
7161da177e4SLinus Torvalds  *
7171da177e4SLinus Torvalds  *	On entry there is work queued to be done. We move some of that work to the
7181da177e4SLinus Torvalds  *	controller itself.
7191da177e4SLinus Torvalds  *
7201da177e4SLinus Torvalds  *	Caller holds the host lock.
7211da177e4SLinus Torvalds  */
7221da177e4SLinus Torvalds static void send_s870(struct atp_unit *dev, unsigned char c)
7231da177e4SLinus Torvalds {
724468b8968SOndrej Zary 	struct scsi_cmnd *workreq = NULL;
7251da177e4SLinus Torvalds 	unsigned int i;//,k;
7261da177e4SLinus Torvalds 	unsigned char  j, target_id;
7271da177e4SLinus Torvalds 	unsigned char *prd;
728c2bab403SOndrej Zary 	unsigned short int w;
7291da177e4SLinus Torvalds 	unsigned long l, bttl = 0;
7301da177e4SLinus Torvalds 	unsigned long  sg_count;
7311da177e4SLinus Torvalds 
7321da177e4SLinus Torvalds 	if (dev->in_snd[c] != 0) {
7331da177e4SLinus Torvalds #ifdef ED_DBGP
7341da177e4SLinus Torvalds 		printk("cmnd in_snd\n");
7351da177e4SLinus Torvalds #endif
7361da177e4SLinus Torvalds 		return;
7371da177e4SLinus Torvalds 	}
7381da177e4SLinus Torvalds #ifdef ED_DBGP
7391da177e4SLinus Torvalds 	printk("Sent_s870 enter\n");
7401da177e4SLinus Torvalds #endif
7411da177e4SLinus Torvalds 	dev->in_snd[c] = 1;
7421da177e4SLinus Torvalds 	if ((dev->last_cmd[c] != 0xff) && ((dev->last_cmd[c] & 0x40) != 0)) {
7431da177e4SLinus Torvalds 		dev->last_cmd[c] &= 0x0f;
7441da177e4SLinus Torvalds 		workreq = dev->id[c][dev->last_cmd[c]].curr_req;
745468b8968SOndrej Zary 		if (!workreq) {
7461da177e4SLinus Torvalds 			dev->last_cmd[c] = 0xff;
7471da177e4SLinus Torvalds 			if (dev->quhd[c] == dev->quend[c]) {
7481da177e4SLinus Torvalds 				dev->in_snd[c] = 0;
7491da177e4SLinus Torvalds 				return;
7501da177e4SLinus Torvalds 			}
7511da177e4SLinus Torvalds 		}
752468b8968SOndrej Zary 	}
753468b8968SOndrej Zary 	if (!workreq) {
7541da177e4SLinus Torvalds 		if ((dev->last_cmd[c] != 0xff) && (dev->working[c] != 0)) {
7551da177e4SLinus Torvalds 			dev->in_snd[c] = 0;
7561da177e4SLinus Torvalds 			return;
7571da177e4SLinus Torvalds 		}
7581da177e4SLinus Torvalds 		dev->working[c]++;
7591da177e4SLinus Torvalds 		j = dev->quhd[c];
7601da177e4SLinus Torvalds 		dev->quhd[c]++;
761468b8968SOndrej Zary 		if (dev->quhd[c] >= qcnt)
7621da177e4SLinus Torvalds 			dev->quhd[c] = 0;
7631da177e4SLinus Torvalds 		workreq = dev->quereq[c][dev->quhd[c]];
764468b8968SOndrej Zary 		if (dev->id[c][scmd_id(workreq)].curr_req != NULL) {
7651da177e4SLinus Torvalds 			dev->quhd[c] = j;
7661da177e4SLinus Torvalds 			dev->working[c]--;
7671da177e4SLinus Torvalds 			dev->in_snd[c] = 0;
7681da177e4SLinus Torvalds 			return;
7691da177e4SLinus Torvalds 		}
770468b8968SOndrej Zary 		dev->id[c][scmd_id(workreq)].curr_req = workreq;
771468b8968SOndrej Zary 		dev->last_cmd[c] = scmd_id(workreq);
7721da177e4SLinus Torvalds 	}
773bcd5c59fSHannes Reinecke 	if ((atp_readb_io(dev, c, 0x1f) & 0xb0) != 0 ||
774bcd5c59fSHannes Reinecke 	    atp_readb_io(dev, c, 0x1c) != 0) {
7751da177e4SLinus Torvalds #ifdef ED_DBGP
7761da177e4SLinus Torvalds 		printk("Abort to Send\n");
7771da177e4SLinus Torvalds #endif
7781da177e4SLinus Torvalds 		dev->last_cmd[c] |= 0x40;
7791da177e4SLinus Torvalds 		dev->in_snd[c] = 0;
7801da177e4SLinus Torvalds 		return;
781468b8968SOndrej Zary 	}
7821da177e4SLinus Torvalds #ifdef ED_DBGP
7831da177e4SLinus Torvalds 	printk("OK to Send\n");
784422c0d61SJeff Garzik 	scmd_printk(KERN_DEBUG, workreq, "CDB");
7851da177e4SLinus Torvalds 	for(i=0;i<workreq->cmd_len;i++) {
7861da177e4SLinus Torvalds 		printk(" %x",workreq->cmnd[i]);
7871da177e4SLinus Torvalds 	}
788422c0d61SJeff Garzik 	printk("\n");
7891da177e4SLinus Torvalds #endif
790fe7ed98fSBoaz Harrosh 	l = scsi_bufflen(workreq);
791fe7ed98fSBoaz Harrosh 
792b922a449SOndrej Zary 	if (is885(dev)) {
7936a3cebb6SOndrej Zary 		j = atp_readb_base(dev, 0x29) & 0xfe;
7946a3cebb6SOndrej Zary 		atp_writeb_base(dev, 0x29, j);
795422c0d61SJeff Garzik 		dev->r1f[c][scmd_id(workreq)] = 0;
7961da177e4SLinus Torvalds 	}
7971da177e4SLinus Torvalds 
7981da177e4SLinus Torvalds 	if (workreq->cmnd[0] == READ_CAPACITY) {
799fe7ed98fSBoaz Harrosh 		if (l > 8)
800fe7ed98fSBoaz Harrosh 			l = 8;
8011da177e4SLinus Torvalds 	}
802f3272258SHannes Reinecke 	if (workreq->cmnd[0] == TEST_UNIT_READY) {
803fe7ed98fSBoaz Harrosh 		l = 0;
8041da177e4SLinus Torvalds 	}
8051da177e4SLinus Torvalds 
8061da177e4SLinus Torvalds 	j = 0;
807422c0d61SJeff Garzik 	target_id = scmd_id(workreq);
8081da177e4SLinus Torvalds 
8091da177e4SLinus Torvalds 	/*
8101da177e4SLinus Torvalds 	 *	Wide ?
8111da177e4SLinus Torvalds 	 */
8121da177e4SLinus Torvalds 	w = 1;
8131da177e4SLinus Torvalds 	w = w << target_id;
8141da177e4SLinus Torvalds 	if ((w & dev->wide_id[c]) != 0) {
8151da177e4SLinus Torvalds 		j |= 0x01;
8161da177e4SLinus Torvalds 	}
8176a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x1b, j);
8186a3cebb6SOndrej Zary 	while ((atp_readb_io(dev, c, 0x1b) & 0x01) != j) {
8196a3cebb6SOndrej Zary 		atp_writeb_pci(dev, c, 0x1b, j);
8201da177e4SLinus Torvalds #ifdef ED_DBGP
8211da177e4SLinus Torvalds 		printk("send_s870 while loop 1\n");
8221da177e4SLinus Torvalds #endif
8231da177e4SLinus Torvalds 	}
8241da177e4SLinus Torvalds 	/*
8251da177e4SLinus Torvalds 	 *	Write the command
8261da177e4SLinus Torvalds 	 */
8271da177e4SLinus Torvalds 
8286a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x00, workreq->cmd_len);
8296a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x01, 0x2c);
830b922a449SOndrej Zary 	if (is885(dev))
8316a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x02, 0x7f);
8326a3cebb6SOndrej Zary 	else
8336a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x02, 0xcf);
8346a3cebb6SOndrej Zary 	for (i = 0; i < workreq->cmd_len; i++)
8356a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x03 + i, workreq->cmnd[i]);
8366a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x0f, workreq->device->lun);
8371da177e4SLinus Torvalds 	/*
8381da177e4SLinus Torvalds 	 *	Write the target
8391da177e4SLinus Torvalds 	 */
8406a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x11, dev->id[c][target_id].devsp);
8411da177e4SLinus Torvalds #ifdef ED_DBGP
842bcd5c59fSHannes Reinecke 	printk("dev->id[%d][%d].devsp = %2x\n",c,target_id,
843bcd5c59fSHannes Reinecke 	       dev->id[c][target_id].devsp);
8441da177e4SLinus Torvalds #endif
8451da177e4SLinus Torvalds 
846fe7ed98fSBoaz Harrosh 	sg_count = scsi_dma_map(workreq);
8471da177e4SLinus Torvalds 	/*
8481da177e4SLinus Torvalds 	 *	Write transfer size
8491da177e4SLinus Torvalds 	 */
8506a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x12, ((unsigned char *) (&l))[2]);
8516a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x13, ((unsigned char *) (&l))[1]);
8526a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x14, ((unsigned char *) (&l))[0]);
8531da177e4SLinus Torvalds 	j = target_id;
8541da177e4SLinus Torvalds 	dev->id[c][j].last_len = l;
8551da177e4SLinus Torvalds 	dev->id[c][j].tran_len = 0;
8561da177e4SLinus Torvalds #ifdef ED_DBGP
8571da177e4SLinus Torvalds 	printk("dev->id[%2d][%2d].last_len = %d\n",c,j,dev->id[c][j].last_len);
8581da177e4SLinus Torvalds #endif
8591da177e4SLinus Torvalds 	/*
8601da177e4SLinus Torvalds 	 *	Flip the wide bits
8611da177e4SLinus Torvalds 	 */
8621da177e4SLinus Torvalds 	if ((j & 0x08) != 0) {
8631da177e4SLinus Torvalds 		j = (j & 0x07) | 0x40;
8641da177e4SLinus Torvalds 	}
8651da177e4SLinus Torvalds 	/*
8661da177e4SLinus Torvalds 	 *	Check transfer direction
8671da177e4SLinus Torvalds 	 */
8686a3cebb6SOndrej Zary 	if (workreq->sc_data_direction == DMA_TO_DEVICE)
8696a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x15, j | 0x20);
8706a3cebb6SOndrej Zary 	else
8716a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x15, j);
8726a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x16, atp_readb_io(dev, c, 0x16) | 0x80);
8736a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x16, 0x80);
8741da177e4SLinus Torvalds 	dev->id[c][target_id].dirct = 0;
8751da177e4SLinus Torvalds 	if (l == 0) {
8766a3cebb6SOndrej Zary 		if (atp_readb_io(dev, c, 0x1c) == 0) {
8771da177e4SLinus Torvalds #ifdef ED_DBGP
8781da177e4SLinus Torvalds 			printk("change SCSI_CMD_REG 0x08\n");
8791da177e4SLinus Torvalds #endif
8806a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x18, 0x08);
8816a3cebb6SOndrej Zary 		} else
8821da177e4SLinus Torvalds 			dev->last_cmd[c] |= 0x40;
8831da177e4SLinus Torvalds 		dev->in_snd[c] = 0;
8841da177e4SLinus Torvalds 		return;
8851da177e4SLinus Torvalds 	}
8861da177e4SLinus Torvalds 	prd = dev->id[c][target_id].prd_table;
8871da177e4SLinus Torvalds 	dev->id[c][target_id].prd_pos = prd;
8881da177e4SLinus Torvalds 
8891da177e4SLinus Torvalds 	/*
8901da177e4SLinus Torvalds 	 *	Now write the request list. Either as scatter/gather or as
8911da177e4SLinus Torvalds 	 *	a linear chain.
8921da177e4SLinus Torvalds 	 */
8931da177e4SLinus Torvalds 
894fe7ed98fSBoaz Harrosh 	if (l) {
895fe7ed98fSBoaz Harrosh 		struct scatterlist *sgpnt;
8961da177e4SLinus Torvalds 		i = 0;
897fe7ed98fSBoaz Harrosh 		scsi_for_each_sg(workreq, sgpnt, sg_count, j) {
898fe7ed98fSBoaz Harrosh 			bttl = sg_dma_address(sgpnt);
899fe7ed98fSBoaz Harrosh 			l=sg_dma_len(sgpnt);
9001da177e4SLinus Torvalds #ifdef ED_DBGP
9011da177e4SLinus Torvalds 			printk("1. bttl %x, l %x\n",bttl, l);
9021da177e4SLinus Torvalds #endif
9031da177e4SLinus Torvalds 			while (l > 0x10000) {
9041da177e4SLinus Torvalds 				(((u16 *) (prd))[i + 3]) = 0x0000;
9051da177e4SLinus Torvalds 				(((u16 *) (prd))[i + 2]) = 0x0000;
9061da177e4SLinus Torvalds 				(((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
9071da177e4SLinus Torvalds 				l -= 0x10000;
9081da177e4SLinus Torvalds 				bttl += 0x10000;
9091da177e4SLinus Torvalds 				i += 0x04;
9101da177e4SLinus Torvalds 			}
9111da177e4SLinus Torvalds 			(((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
9121da177e4SLinus Torvalds 			(((u16 *) (prd))[i + 2]) = cpu_to_le16(l);
9131da177e4SLinus Torvalds 			(((u16 *) (prd))[i + 3]) = 0;
9141da177e4SLinus Torvalds 			i += 0x04;
9151da177e4SLinus Torvalds 		}
9161da177e4SLinus Torvalds 		(((u16 *) (prd))[i - 1]) = cpu_to_le16(0x8000);
9171da177e4SLinus Torvalds #ifdef ED_DBGP
918bcd5c59fSHannes Reinecke 		printk("prd %4x %4x %4x %4x\n",
919bcd5c59fSHannes Reinecke 		       (((unsigned short int *)prd)[0]),
920bcd5c59fSHannes Reinecke 		       (((unsigned short int *)prd)[1]),
921bcd5c59fSHannes Reinecke 		       (((unsigned short int *)prd)[2]),
922bcd5c59fSHannes Reinecke 		       (((unsigned short int *)prd)[3]));
9231da177e4SLinus Torvalds 		printk("2. bttl %x, l %x\n",bttl, l);
9241da177e4SLinus Torvalds #endif
9251da177e4SLinus Torvalds 	}
9261da177e4SLinus Torvalds #ifdef ED_DBGP
927bcd5c59fSHannes Reinecke 	printk("send_s870: prdaddr_2 0x%8x target_id %d\n",
928bcd5c59fSHannes Reinecke 	       dev->id[c][target_id].prdaddr,target_id);
9291da177e4SLinus Torvalds #endif
930b5683557SJames Bottomley 	dev->id[c][target_id].prdaddr = dev->id[c][target_id].prd_bus;
9316a3cebb6SOndrej Zary 	atp_writel_pci(dev, c, 4, dev->id[c][target_id].prdaddr);
9326a3cebb6SOndrej Zary 	atp_writeb_pci(dev, c, 2, 0x06);
9336a3cebb6SOndrej Zary 	atp_writeb_pci(dev, c, 2, 0x00);
934b922a449SOndrej Zary 	if (is885(dev)) {
9356a3cebb6SOndrej Zary 		j = atp_readb_pci(dev, c, 1) & 0xf3;
936f3272258SHannes Reinecke 		if ((workreq->cmnd[0] == READ_6) ||
937f3272258SHannes Reinecke 		    (workreq->cmnd[0] == READ_10) ||
938f3272258SHannes Reinecke 		    (workreq->cmnd[0] == WRITE_6) ||
939f3272258SHannes Reinecke 		    (workreq->cmnd[0] == WRITE_10)) {
9401da177e4SLinus Torvalds 			j |= 0x0c;
9411da177e4SLinus Torvalds 		}
9426a3cebb6SOndrej Zary 		atp_writeb_pci(dev, c, 1, j);
943b922a449SOndrej Zary 	} else if (is880(dev)) {
944f3272258SHannes Reinecke 		if ((workreq->cmnd[0] == READ_6) ||
945f3272258SHannes Reinecke 		    (workreq->cmnd[0] == READ_10) ||
946f3272258SHannes Reinecke 		    (workreq->cmnd[0] == WRITE_6) ||
947f3272258SHannes Reinecke 		    (workreq->cmnd[0] == WRITE_10))
948bcd5c59fSHannes Reinecke 			atp_writeb_base(dev, 0x3b,
949bcd5c59fSHannes Reinecke 					(atp_readb_base(dev, 0x3b) & 0x3f) | 0xc0);
9506a3cebb6SOndrej Zary 		else
951bcd5c59fSHannes Reinecke 			atp_writeb_base(dev, 0x3b,
952bcd5c59fSHannes Reinecke 					atp_readb_base(dev, 0x3b) & 0x3f);
9531da177e4SLinus Torvalds 	} else {
954f3272258SHannes Reinecke 		if ((workreq->cmnd[0] == READ_6) ||
955f3272258SHannes Reinecke 		    (workreq->cmnd[0] == READ_10) ||
956f3272258SHannes Reinecke 		    (workreq->cmnd[0] == WRITE_6) ||
957f3272258SHannes Reinecke 		    (workreq->cmnd[0] == WRITE_10))
958bcd5c59fSHannes Reinecke 			atp_writeb_base(dev, 0x3a,
959bcd5c59fSHannes Reinecke 					(atp_readb_base(dev, 0x3a) & 0xf3) | 0x08);
9606a3cebb6SOndrej Zary 		else
961bcd5c59fSHannes Reinecke 			atp_writeb_base(dev, 0x3a,
962bcd5c59fSHannes Reinecke 					atp_readb_base(dev, 0x3a) & 0xf3);
9631da177e4SLinus Torvalds 	}
9641da177e4SLinus Torvalds 
9651da177e4SLinus Torvalds 	if(workreq->sc_data_direction == DMA_TO_DEVICE) {
9661da177e4SLinus Torvalds 		dev->id[c][target_id].dirct = 0x20;
9676a3cebb6SOndrej Zary 		if (atp_readb_io(dev, c, 0x1c) == 0) {
9686a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x18, 0x08);
9696a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 0, 0x01);
9701da177e4SLinus Torvalds #ifdef ED_DBGP
9711da177e4SLinus Torvalds 		printk( "start DMA(to target)\n");
9721da177e4SLinus Torvalds #endif
9731da177e4SLinus Torvalds 		} else {
9741da177e4SLinus Torvalds 			dev->last_cmd[c] |= 0x40;
9751da177e4SLinus Torvalds 		}
9761da177e4SLinus Torvalds 		dev->in_snd[c] = 0;
9771da177e4SLinus Torvalds 		return;
9781da177e4SLinus Torvalds 	}
9796a3cebb6SOndrej Zary 	if (atp_readb_io(dev, c, 0x1c) == 0) {
9806a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
9816a3cebb6SOndrej Zary 		atp_writeb_pci(dev, c, 0, 0x09);
9821da177e4SLinus Torvalds #ifdef ED_DBGP
9831da177e4SLinus Torvalds 		printk( "start DMA(to host)\n");
9841da177e4SLinus Torvalds #endif
9851da177e4SLinus Torvalds 	} else {
9861da177e4SLinus Torvalds 		dev->last_cmd[c] |= 0x40;
9871da177e4SLinus Torvalds 	}
9881da177e4SLinus Torvalds 	dev->in_snd[c] = 0;
9891da177e4SLinus Torvalds 	return;
9901da177e4SLinus Torvalds 
9911da177e4SLinus Torvalds }
9921da177e4SLinus Torvalds 
9931da177e4SLinus Torvalds static unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val)
9941da177e4SLinus Torvalds {
9951da177e4SLinus Torvalds 	unsigned short int i, k;
9961da177e4SLinus Torvalds 	unsigned char j;
9971da177e4SLinus Torvalds 
9986a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, *val);
9991da177e4SLinus Torvalds 	for (i = 0; i < 10; i++) {	/* stable >= bus settle delay(400 ns)  */
10006a3cebb6SOndrej Zary 		k = atp_readw_io(dev, 0, 0x1c);
10011da177e4SLinus Torvalds 		j = (unsigned char) (k >> 8);
1002832e9ac6SOndrej Zary 		if ((k & 0x8000) != 0)	/* DB7 all release?    */
1003832e9ac6SOndrej Zary 			i = 0;
10041da177e4SLinus Torvalds 	}
10051da177e4SLinus Torvalds 	*val |= 0x4000;		/* assert DB6           */
10066a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, *val);
10071da177e4SLinus Torvalds 	*val &= 0xdfff;		/* assert DB5           */
10086a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, *val);
10091da177e4SLinus Torvalds 	for (i = 0; i < 10; i++) {	/* stable >= bus settle delay(400 ns) */
10106a3cebb6SOndrej Zary 		if ((atp_readw_io(dev, 0, 0x1c) & 0x2000) != 0)	/* DB5 all release?       */
1011832e9ac6SOndrej Zary 			i = 0;
10121da177e4SLinus Torvalds 	}
10131da177e4SLinus Torvalds 	*val |= 0x8000;		/* no DB4-0, assert DB7    */
10141da177e4SLinus Torvalds 	*val &= 0xe0ff;
10156a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, *val);
10161da177e4SLinus Torvalds 	*val &= 0xbfff;		/* release DB6             */
10176a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, *val);
10181da177e4SLinus Torvalds 	for (i = 0; i < 10; i++) {	/* stable >= bus settle delay(400 ns)  */
10196a3cebb6SOndrej Zary 		if ((atp_readw_io(dev, 0, 0x1c) & 0x4000) != 0)	/* DB6 all release?  */
1020832e9ac6SOndrej Zary 			i = 0;
10211da177e4SLinus Torvalds 	}
10221da177e4SLinus Torvalds 
10231da177e4SLinus Torvalds 	return j;
10241da177e4SLinus Torvalds }
10251da177e4SLinus Torvalds 
10268177c507SOndrej Zary static void tscam(struct Scsi_Host *host, bool wide_chip, u8 scam_on)
10271da177e4SLinus Torvalds {
10281da177e4SLinus Torvalds 
10291da177e4SLinus Torvalds 	unsigned char i, j, k;
10301da177e4SLinus Torvalds 	unsigned long n;
10311da177e4SLinus Torvalds 	unsigned short int m, assignid_map, val;
10321da177e4SLinus Torvalds 	unsigned char mbuf[33], quintet[2];
10331da177e4SLinus Torvalds 	struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
10341da177e4SLinus Torvalds 	static unsigned char g2q_tab[8] = {
10351da177e4SLinus Torvalds 		0x38, 0x31, 0x32, 0x2b, 0x34, 0x2d, 0x2e, 0x27
10361da177e4SLinus Torvalds 	};
10371da177e4SLinus Torvalds 
10381da177e4SLinus Torvalds /*  I can't believe we need this before we've even done anything.  Remove it
10391da177e4SLinus Torvalds  *  and see if anyone bitches.
10401da177e4SLinus Torvalds 	for (i = 0; i < 0x10; i++) {
10411da177e4SLinus Torvalds 		udelay(0xffff);
10421da177e4SLinus Torvalds 	}
10431da177e4SLinus Torvalds  */
10441da177e4SLinus Torvalds 
10456a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 1, 0x08);
10466a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 2, 0x7f);
10476a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x11, 0x20);
10481da177e4SLinus Torvalds 
10498177c507SOndrej Zary 	if ((scam_on & 0x40) == 0) {
10501da177e4SLinus Torvalds 		return;
10511da177e4SLinus Torvalds 	}
10521da177e4SLinus Torvalds 	m = 1;
10531da177e4SLinus Torvalds 	m <<= dev->host_id[0];
10541da177e4SLinus Torvalds 	j = 16;
1055dd5a5f79SOndrej Zary 	if (!wide_chip) {
10561da177e4SLinus Torvalds 		m |= 0xff00;
10571da177e4SLinus Torvalds 		j = 8;
10581da177e4SLinus Torvalds 	}
10591da177e4SLinus Torvalds 	assignid_map = m;
10606a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x02, 0x02);	/* 2*2=4ms,3EH 2/32*3E=3.9ms */
10616a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x03, 0);
10626a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x04, 0);
10636a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x05, 0);
10646a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x06, 0);
10656a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x07, 0);
10666a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x08, 0);
10671da177e4SLinus Torvalds 
10681da177e4SLinus Torvalds 	for (i = 0; i < j; i++) {
10691da177e4SLinus Torvalds 		m = 1;
10701da177e4SLinus Torvalds 		m = m << i;
10711da177e4SLinus Torvalds 		if ((m & assignid_map) != 0) {
10721da177e4SLinus Torvalds 			continue;
10731da177e4SLinus Torvalds 		}
10746a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x0f, 0);
10756a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x12, 0);
10766a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x13, 0);
10776a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x14, 0);
10781da177e4SLinus Torvalds 		if (i > 7) {
10791da177e4SLinus Torvalds 			k = (i & 0x07) | 0x40;
10801da177e4SLinus Torvalds 		} else {
10811da177e4SLinus Torvalds 			k = i;
10821da177e4SLinus Torvalds 		}
10836a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x15, k);
1084dd5a5f79SOndrej Zary 		if (wide_chip)
10856a3cebb6SOndrej Zary 			atp_writeb_io(dev, 0, 0x1b, 0x01);
10866a3cebb6SOndrej Zary 		else
10876a3cebb6SOndrej Zary 			atp_writeb_io(dev, 0, 0x1b, 0x00);
108858c4d046SOndrej Zary 		do {
10896a3cebb6SOndrej Zary 			atp_writeb_io(dev, 0, 0x18, 0x09);
10901da177e4SLinus Torvalds 
10916a3cebb6SOndrej Zary 			while ((atp_readb_io(dev, 0, 0x1f) & 0x80) == 0x00)
10921da177e4SLinus Torvalds 				cpu_relax();
10936a3cebb6SOndrej Zary 			k = atp_readb_io(dev, 0, 0x17);
109458c4d046SOndrej Zary 			if ((k == 0x85) || (k == 0x42))
109558c4d046SOndrej Zary 				break;
109658c4d046SOndrej Zary 			if (k != 0x16)
10976a3cebb6SOndrej Zary 				atp_writeb_io(dev, 0, 0x10, 0x41);
109858c4d046SOndrej Zary 		} while (k != 0x16);
109958c4d046SOndrej Zary 		if ((k == 0x85) || (k == 0x42))
110058c4d046SOndrej Zary 			continue;
11011da177e4SLinus Torvalds 		assignid_map |= m;
11021da177e4SLinus Torvalds 
11031da177e4SLinus Torvalds 	}
11046a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x02, 0x7f);
11056a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x1b, 0x02);
11061da177e4SLinus Torvalds 
11072bbbac45SOndrej Zary 	udelay(2);
11081da177e4SLinus Torvalds 
11091da177e4SLinus Torvalds 	val = 0x0080;		/* bsy  */
11106a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, val);
11111da177e4SLinus Torvalds 	val |= 0x0040;		/* sel  */
11126a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, val);
11131da177e4SLinus Torvalds 	val |= 0x0004;		/* msg  */
11146a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, val);
11152bbbac45SOndrej Zary 	udelay(2);		/* 2 deskew delay(45ns*2=90ns) */
11161da177e4SLinus Torvalds 	val &= 0x007f;		/* no bsy  */
11176a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, val);
1118dcaa0c12SJia-Ju Bai 	msleep(128);
11191da177e4SLinus Torvalds 	val &= 0x00fb;		/* after 1ms no msg */
11206a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, val);
11216a3cebb6SOndrej Zary 	while ((atp_readb_io(dev, 0, 0x1c) & 0x04) != 0)
112258c4d046SOndrej Zary 		;
11232bbbac45SOndrej Zary 	udelay(2);
11241da177e4SLinus Torvalds 	udelay(100);
1125c7fcc089SOndrej Zary 	for (n = 0; n < 0x30000; n++)
11266a3cebb6SOndrej Zary 		if ((atp_readb_io(dev, 0, 0x1c) & 0x80) != 0)	/* bsy ? */
1127c7fcc089SOndrej Zary 			break;
1128c7fcc089SOndrej Zary 	if (n < 0x30000)
1129c7fcc089SOndrej Zary 		for (n = 0; n < 0x30000; n++)
11306a3cebb6SOndrej Zary 			if ((atp_readb_io(dev, 0, 0x1c) & 0x81) == 0x0081) {
11312bbbac45SOndrej Zary 				udelay(2);
11321da177e4SLinus Torvalds 				val |= 0x8003;		/* io,cd,db7  */
11336a3cebb6SOndrej Zary 				atp_writew_io(dev, 0, 0x1c, val);
11342bbbac45SOndrej Zary 				udelay(2);
11351da177e4SLinus Torvalds 				val &= 0x00bf;		/* no sel     */
11366a3cebb6SOndrej Zary 				atp_writew_io(dev, 0, 0x1c, val);
11372bbbac45SOndrej Zary 				udelay(2);
1138c7fcc089SOndrej Zary 				break;
1139c7fcc089SOndrej Zary 			}
1140c7fcc089SOndrej Zary 	while (1) {
11410f6d93aaSMartin Michlmayr 	/*
11420f6d93aaSMartin Michlmayr 	 * The funny division into multiple delays is to accomodate
11430f6d93aaSMartin Michlmayr 	 * arches like ARM where udelay() multiplies its argument by
11440f6d93aaSMartin Michlmayr 	 * a large number to initialize a loop counter.  To avoid
11450f6d93aaSMartin Michlmayr 	 * overflow, the maximum supported udelay is 2000 microseconds.
11460f6d93aaSMartin Michlmayr 	 *
11470f6d93aaSMartin Michlmayr 	 * XXX it would be more polite to find a way to use msleep()
11480f6d93aaSMartin Michlmayr 	 */
11490f6d93aaSMartin Michlmayr 	mdelay(2);
11500f6d93aaSMartin Michlmayr 	udelay(48);
11516a3cebb6SOndrej Zary 	if ((atp_readb_io(dev, 0, 0x1c) & 0x80) == 0x00) {	/* bsy ? */
11526a3cebb6SOndrej Zary 		atp_writew_io(dev, 0, 0x1c, 0);
11536a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x1b, 0);
11546a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x15, 0);
11556a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x18, 0x09);
11566a3cebb6SOndrej Zary 		while ((atp_readb_io(dev, 0, 0x1f) & 0x80) == 0)
11571da177e4SLinus Torvalds 			cpu_relax();
11586a3cebb6SOndrej Zary 		atp_readb_io(dev, 0, 0x17);
11591da177e4SLinus Torvalds 		return;
11601da177e4SLinus Torvalds 	}
11611da177e4SLinus Torvalds 	val &= 0x00ff;		/* synchronization  */
11621da177e4SLinus Torvalds 	val |= 0x3f00;
11631da177e4SLinus Torvalds 	fun_scam(dev, &val);
11642bbbac45SOndrej Zary 	udelay(2);
11651da177e4SLinus Torvalds 	val &= 0x00ff;		/* isolation        */
11661da177e4SLinus Torvalds 	val |= 0x2000;
11671da177e4SLinus Torvalds 	fun_scam(dev, &val);
11682bbbac45SOndrej Zary 	udelay(2);
11691da177e4SLinus Torvalds 	i = 8;
11701da177e4SLinus Torvalds 	j = 0;
1171c7fcc089SOndrej Zary 
1172c7fcc089SOndrej Zary 	while (1) {
11736a3cebb6SOndrej Zary 		if ((atp_readw_io(dev, 0, 0x1c) & 0x2000) == 0)
1174c7fcc089SOndrej Zary 			continue;
11752bbbac45SOndrej Zary 		udelay(2);
11761da177e4SLinus Torvalds 		val &= 0x00ff;		/* get ID_STRING */
11771da177e4SLinus Torvalds 		val |= 0x2000;
11781da177e4SLinus Torvalds 		k = fun_scam(dev, &val);
1179c7fcc089SOndrej Zary 		if ((k & 0x03) == 0)
1180c7fcc089SOndrej Zary 			break;
11811da177e4SLinus Torvalds 		mbuf[j] <<= 0x01;
11821da177e4SLinus Torvalds 		mbuf[j] &= 0xfe;
1183c7fcc089SOndrej Zary 		if ((k & 0x02) != 0)
11841da177e4SLinus Torvalds 			mbuf[j] |= 0x01;
11851da177e4SLinus Torvalds 		i--;
1186c7fcc089SOndrej Zary 		if (i > 0)
1187c7fcc089SOndrej Zary 			continue;
11881da177e4SLinus Torvalds 		j++;
11891da177e4SLinus Torvalds 		i = 8;
1190c7fcc089SOndrej Zary 	}
11911da177e4SLinus Torvalds 
1192c7fcc089SOndrej Zary 	/* isolation complete..  */
11931da177e4SLinus Torvalds /*    mbuf[32]=0;
11941da177e4SLinus Torvalds 	printk(" \n%x %x %x %s\n ",assignid_map,mbuf[0],mbuf[1],&mbuf[2]); */
11951da177e4SLinus Torvalds 	i = 15;
11961da177e4SLinus Torvalds 	j = mbuf[0];
11971da177e4SLinus Torvalds 	if ((j & 0x20) != 0) {	/* bit5=1:ID up to 7      */
11981da177e4SLinus Torvalds 		i = 7;
11991da177e4SLinus Torvalds 	}
1200c7fcc089SOndrej Zary 	if ((j & 0x06) != 0) {	/* IDvalid?             */
12011da177e4SLinus Torvalds 		k = mbuf[1];
1202c7fcc089SOndrej Zary 		while (1) {
12031da177e4SLinus Torvalds 			m = 1;
12041da177e4SLinus Torvalds 			m <<= k;
1205c7fcc089SOndrej Zary 			if ((m & assignid_map) == 0)
1206c7fcc089SOndrej Zary 				break;
1207c7fcc089SOndrej Zary 			if (k > 0)
12081da177e4SLinus Torvalds 				k--;
1209c7fcc089SOndrej Zary 			else
1210c7fcc089SOndrej Zary 				break;
12111da177e4SLinus Torvalds 		}
1212c7fcc089SOndrej Zary 	}
1213c7fcc089SOndrej Zary 	if ((m & assignid_map) != 0) {	/* srch from max acceptable ID#  */
12141da177e4SLinus Torvalds 		k = i;			/* max acceptable ID#            */
1215c7fcc089SOndrej Zary 		while (1) {
12161da177e4SLinus Torvalds 			m = 1;
12171da177e4SLinus Torvalds 			m <<= k;
1218c7fcc089SOndrej Zary 			if ((m & assignid_map) == 0)
1219c7fcc089SOndrej Zary 				break;
1220c7fcc089SOndrej Zary 			if (k > 0)
12211da177e4SLinus Torvalds 				k--;
1222c7fcc089SOndrej Zary 			else
1223c7fcc089SOndrej Zary 				break;
12241da177e4SLinus Torvalds 		}
1225c7fcc089SOndrej Zary 	}
1226c7fcc089SOndrej Zary 	/* k=binID#,       */
12271da177e4SLinus Torvalds 	assignid_map |= m;
12281da177e4SLinus Torvalds 	if (k < 8) {
12291da177e4SLinus Torvalds 		quintet[0] = 0x38;	/* 1st dft ID<8    */
12301da177e4SLinus Torvalds 	} else {
12311da177e4SLinus Torvalds 		quintet[0] = 0x31;	/* 1st  ID>=8      */
12321da177e4SLinus Torvalds 	}
12331da177e4SLinus Torvalds 	k &= 0x07;
12341da177e4SLinus Torvalds 	quintet[1] = g2q_tab[k];
12351da177e4SLinus Torvalds 
12361da177e4SLinus Torvalds 	val &= 0x00ff;		/* AssignID 1stQuintet,AH=001xxxxx  */
12371da177e4SLinus Torvalds 	m = quintet[0] << 8;
12381da177e4SLinus Torvalds 	val |= m;
12391da177e4SLinus Torvalds 	fun_scam(dev, &val);
12401da177e4SLinus Torvalds 	val &= 0x00ff;		/* AssignID 2ndQuintet,AH=001xxxxx */
12411da177e4SLinus Torvalds 	m = quintet[1] << 8;
12421da177e4SLinus Torvalds 	val |= m;
12431da177e4SLinus Torvalds 	fun_scam(dev, &val);
12441da177e4SLinus Torvalds 
1245c7fcc089SOndrej Zary 	}
12461da177e4SLinus Torvalds }
12471da177e4SLinus Torvalds 
12481da177e4SLinus Torvalds static void atp870u_free_tables(struct Scsi_Host *host)
12491da177e4SLinus Torvalds {
12501da177e4SLinus Torvalds 	struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata;
12511da177e4SLinus Torvalds 	int j, k;
12521da177e4SLinus Torvalds 	for (j=0; j < 2; j++) {
12531da177e4SLinus Torvalds 		for (k = 0; k < 16; k++) {
12541da177e4SLinus Torvalds 			if (!atp_dev->id[j][k].prd_table)
12551da177e4SLinus Torvalds 				continue;
1256bcd5c59fSHannes Reinecke 			dma_free_coherent(&atp_dev->pdev->dev, 1024,
1257bcd5c59fSHannes Reinecke 					  atp_dev->id[j][k].prd_table,
1258bcd5c59fSHannes Reinecke 					  atp_dev->id[j][k].prd_bus);
12591da177e4SLinus Torvalds 			atp_dev->id[j][k].prd_table = NULL;
12601da177e4SLinus Torvalds 		}
12611da177e4SLinus Torvalds 	}
12621da177e4SLinus Torvalds }
12631da177e4SLinus Torvalds 
12641da177e4SLinus Torvalds static int atp870u_init_tables(struct Scsi_Host *host)
12651da177e4SLinus Torvalds {
12661da177e4SLinus Torvalds 	struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata;
12671da177e4SLinus Torvalds 	int c,k;
12681da177e4SLinus Torvalds 	for(c=0;c < 2;c++) {
12691da177e4SLinus Torvalds 		for(k=0;k<16;k++) {
1270bcd5c59fSHannes Reinecke 			atp_dev->id[c][k].prd_table =
1271bcd5c59fSHannes Reinecke 				dma_alloc_coherent(&atp_dev->pdev->dev, 1024,
1272bcd5c59fSHannes Reinecke 						   &(atp_dev->id[c][k].prd_bus),
1273bcd5c59fSHannes Reinecke 						   GFP_KERNEL);
12741da177e4SLinus Torvalds 			if (!atp_dev->id[c][k].prd_table) {
12751da177e4SLinus Torvalds 				printk("atp870u_init_tables fail\n");
12761da177e4SLinus Torvalds 				atp870u_free_tables(host);
12771da177e4SLinus Torvalds 				return -ENOMEM;
12781da177e4SLinus Torvalds 			}
1279b5683557SJames Bottomley 			atp_dev->id[c][k].prdaddr = atp_dev->id[c][k].prd_bus;
12801da177e4SLinus Torvalds 			atp_dev->id[c][k].devsp=0x20;
12811da177e4SLinus Torvalds 			atp_dev->id[c][k].devtype = 0x7f;
12821da177e4SLinus Torvalds 			atp_dev->id[c][k].curr_req = NULL;
12831da177e4SLinus Torvalds 		}
12841da177e4SLinus Torvalds 
12851da177e4SLinus Torvalds 		atp_dev->active_id[c] = 0;
12861da177e4SLinus Torvalds 		atp_dev->wide_id[c] = 0;
12871da177e4SLinus Torvalds 		atp_dev->host_id[c] = 0x07;
12881da177e4SLinus Torvalds 		atp_dev->quhd[c] = 0;
12891da177e4SLinus Torvalds 		atp_dev->quend[c] = 0;
12901da177e4SLinus Torvalds 		atp_dev->last_cmd[c] = 0xff;
12911da177e4SLinus Torvalds 		atp_dev->in_snd[c] = 0;
12921da177e4SLinus Torvalds 		atp_dev->in_int[c] = 0;
12931da177e4SLinus Torvalds 
12941da177e4SLinus Torvalds 		for (k = 0; k < qcnt; k++) {
12951da177e4SLinus Torvalds 			atp_dev->quereq[c][k] = NULL;
12961da177e4SLinus Torvalds 		}
12971da177e4SLinus Torvalds 		for (k = 0; k < 16; k++) {
12981da177e4SLinus Torvalds 			   atp_dev->id[c][k].curr_req = NULL;
12991da177e4SLinus Torvalds 			   atp_dev->sp[c][k] = 0x04;
13001da177e4SLinus Torvalds 		}
13011da177e4SLinus Torvalds 	}
13021da177e4SLinus Torvalds 	return 0;
13031da177e4SLinus Torvalds }
13041da177e4SLinus Torvalds 
13056a1961bcSOndrej Zary static void atp_set_host_id(struct atp_unit *atp, u8 c, u8 host_id)
13066a1961bcSOndrej Zary {
13076a1961bcSOndrej Zary 	atp_writeb_io(atp, c, 0, host_id | 0x08);
13086a1961bcSOndrej Zary 	atp_writeb_io(atp, c, 0x18, 0);
13096a1961bcSOndrej Zary 	while ((atp_readb_io(atp, c, 0x1f) & 0x80) == 0)
13106a1961bcSOndrej Zary 		mdelay(1);
13116a1961bcSOndrej Zary 	atp_readb_io(atp, c, 0x17);
13126a1961bcSOndrej Zary 	atp_writeb_io(atp, c, 1, 8);
13136a1961bcSOndrej Zary 	atp_writeb_io(atp, c, 2, 0x7f);
13146a1961bcSOndrej Zary 	atp_writeb_io(atp, c, 0x11, 0x20);
13156a1961bcSOndrej Zary }
13166a1961bcSOndrej Zary 
13174190230eSOndrej Zary static void atp870_init(struct Scsi_Host *shpnt)
13184190230eSOndrej Zary {
13194190230eSOndrej Zary 	struct atp_unit *atpdev = shost_priv(shpnt);
13204190230eSOndrej Zary 	struct pci_dev *pdev = atpdev->pdev;
13214190230eSOndrej Zary 	unsigned char k, host_id;
13224190230eSOndrej Zary 	u8 scam_on;
13234190230eSOndrej Zary 	bool wide_chip =
13244190230eSOndrej Zary 		(pdev->device == PCI_DEVICE_ID_ARTOP_AEC7610 &&
13254190230eSOndrej Zary 		 pdev->revision == 4) ||
13264190230eSOndrej Zary 		(pdev->device == PCI_DEVICE_ID_ARTOP_AEC7612UW) ||
13274190230eSOndrej Zary 		(pdev->device == PCI_DEVICE_ID_ARTOP_AEC7612SUW);
13284190230eSOndrej Zary 
13294190230eSOndrej Zary 	pci_read_config_byte(pdev, 0x49, &host_id);
13304190230eSOndrej Zary 
1331bcd5c59fSHannes Reinecke 	dev_info(&pdev->dev, "ACARD AEC-671X PCI Ultra/W SCSI-2/3 "
1332bcd5c59fSHannes Reinecke 		 "Host Adapter: IO:%lx, IRQ:%d.\n",
13334190230eSOndrej Zary 		 shpnt->io_port, shpnt->irq);
13344190230eSOndrej Zary 
13354190230eSOndrej Zary 	atpdev->ioport[0] = shpnt->io_port;
13364190230eSOndrej Zary 	atpdev->pciport[0] = shpnt->io_port + 0x20;
13374190230eSOndrej Zary 	host_id &= 0x07;
13384190230eSOndrej Zary 	atpdev->host_id[0] = host_id;
13394190230eSOndrej Zary 	scam_on = atp_readb_pci(atpdev, 0, 2);
13404190230eSOndrej Zary 	atpdev->global_map[0] = atp_readb_base(atpdev, 0x2d);
13414190230eSOndrej Zary 	atpdev->ultra_map[0] = atp_readw_base(atpdev, 0x2e);
13424190230eSOndrej Zary 
13434190230eSOndrej Zary 	if (atpdev->ultra_map[0] == 0) {
13444190230eSOndrej Zary 		scam_on = 0x00;
13454190230eSOndrej Zary 		atpdev->global_map[0] = 0x20;
13464190230eSOndrej Zary 		atpdev->ultra_map[0] = 0xffff;
13474190230eSOndrej Zary 	}
13484190230eSOndrej Zary 
13494190230eSOndrej Zary 	if (pdev->revision > 0x07)	/* check if atp876 chip */
13504190230eSOndrej Zary 		atp_writeb_base(atpdev, 0x3e, 0x00); /* enable terminator */
13514190230eSOndrej Zary 
13524190230eSOndrej Zary 	k = (atp_readb_base(atpdev, 0x3a) & 0xf3) | 0x10;
13534190230eSOndrej Zary 	atp_writeb_base(atpdev, 0x3a, k);
13544190230eSOndrej Zary 	atp_writeb_base(atpdev, 0x3a, k & 0xdf);
1355dcaa0c12SJia-Ju Bai 	msleep(32);
13564190230eSOndrej Zary 	atp_writeb_base(atpdev, 0x3a, k);
1357dcaa0c12SJia-Ju Bai 	msleep(32);
13584190230eSOndrej Zary 	atp_set_host_id(atpdev, 0, host_id);
13594190230eSOndrej Zary 
13604190230eSOndrej Zary 	tscam(shpnt, wide_chip, scam_on);
13614190230eSOndrej Zary 	atp_writeb_base(atpdev, 0x3a, atp_readb_base(atpdev, 0x3a) | 0x10);
13624190230eSOndrej Zary 	atp_is(atpdev, 0, wide_chip, 0);
13634190230eSOndrej Zary 	atp_writeb_base(atpdev, 0x3a, atp_readb_base(atpdev, 0x3a) & 0xef);
13644190230eSOndrej Zary 	atp_writeb_base(atpdev, 0x3b, atp_readb_base(atpdev, 0x3b) | 0x20);
13654190230eSOndrej Zary 	shpnt->max_id = wide_chip ? 16 : 8;
13664190230eSOndrej Zary 	shpnt->this_id = host_id;
13674190230eSOndrej Zary }
13684190230eSOndrej Zary 
1369c7e6a029SOndrej Zary static void atp880_init(struct Scsi_Host *shpnt)
1370c7e6a029SOndrej Zary {
1371c7e6a029SOndrej Zary 	struct atp_unit *atpdev = shost_priv(shpnt);
1372c7e6a029SOndrej Zary 	struct pci_dev *pdev = atpdev->pdev;
1373c7e6a029SOndrej Zary 	unsigned char k, m, host_id;
1374c7e6a029SOndrej Zary 	unsigned int n;
1375c7e6a029SOndrej Zary 
1376c7e6a029SOndrej Zary 	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80);
1377c7e6a029SOndrej Zary 
1378c7e6a029SOndrej Zary 	atpdev->ioport[0] = shpnt->io_port + 0x40;
1379c7e6a029SOndrej Zary 	atpdev->pciport[0] = shpnt->io_port + 0x28;
1380c7e6a029SOndrej Zary 
1381c7e6a029SOndrej Zary 	host_id = atp_readb_base(atpdev, 0x39) >> 4;
1382c7e6a029SOndrej Zary 
1383bcd5c59fSHannes Reinecke 	dev_info(&pdev->dev, "ACARD AEC-67160 PCI Ultra3 LVD "
1384bcd5c59fSHannes Reinecke 		 "Host Adapter: IO:%lx, IRQ:%d.\n",
1385c7e6a029SOndrej Zary 		 shpnt->io_port, shpnt->irq);
1386c7e6a029SOndrej Zary 	atpdev->host_id[0] = host_id;
1387c7e6a029SOndrej Zary 
1388c7e6a029SOndrej Zary 	atpdev->global_map[0] = atp_readb_base(atpdev, 0x35);
1389c7e6a029SOndrej Zary 	atpdev->ultra_map[0] = atp_readw_base(atpdev, 0x3c);
1390c7e6a029SOndrej Zary 
1391c7e6a029SOndrej Zary 	n = 0x3f09;
1392c7e6a029SOndrej Zary 	while (n < 0x4000) {
1393c7e6a029SOndrej Zary 		m = 0;
1394c7e6a029SOndrej Zary 		atp_writew_base(atpdev, 0x34, n);
1395c7e6a029SOndrej Zary 		n += 0x0002;
1396c7e6a029SOndrej Zary 		if (atp_readb_base(atpdev, 0x30) == 0xff)
1397c7e6a029SOndrej Zary 			break;
1398c7e6a029SOndrej Zary 
1399c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30);
1400c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31);
1401c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32);
1402c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33);
1403c7e6a029SOndrej Zary 		atp_writew_base(atpdev, 0x34, n);
1404c7e6a029SOndrej Zary 		n += 0x0002;
1405c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30);
1406c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31);
1407c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32);
1408c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33);
1409c7e6a029SOndrej Zary 		atp_writew_base(atpdev, 0x34, n);
1410c7e6a029SOndrej Zary 		n += 0x0002;
1411c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30);
1412c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31);
1413c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32);
1414c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33);
1415c7e6a029SOndrej Zary 		atp_writew_base(atpdev, 0x34, n);
1416c7e6a029SOndrej Zary 		n += 0x0002;
1417c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30);
1418c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31);
1419c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32);
1420c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33);
1421c7e6a029SOndrej Zary 		n += 0x0018;
1422c7e6a029SOndrej Zary 	}
1423c7e6a029SOndrej Zary 	atp_writew_base(atpdev, 0x34, 0);
1424c7e6a029SOndrej Zary 	atpdev->ultra_map[0] = 0;
1425c7e6a029SOndrej Zary 	atpdev->async[0] = 0;
1426c7e6a029SOndrej Zary 	for (k = 0; k < 16; k++) {
1427c7e6a029SOndrej Zary 		n = 1 << k;
1428c7e6a029SOndrej Zary 		if (atpdev->sp[0][k] > 1)
1429c7e6a029SOndrej Zary 			atpdev->ultra_map[0] |= n;
1430c7e6a029SOndrej Zary 		else
1431c7e6a029SOndrej Zary 			if (atpdev->sp[0][k] == 0)
1432c7e6a029SOndrej Zary 				atpdev->async[0] |= n;
1433c7e6a029SOndrej Zary 	}
1434c7e6a029SOndrej Zary 	atpdev->async[0] = ~(atpdev->async[0]);
1435c7e6a029SOndrej Zary 	atp_writeb_base(atpdev, 0x35, atpdev->global_map[0]);
1436c7e6a029SOndrej Zary 
1437c7e6a029SOndrej Zary 	k = atp_readb_base(atpdev, 0x38) & 0x80;
1438c7e6a029SOndrej Zary 	atp_writeb_base(atpdev, 0x38, k);
1439c7e6a029SOndrej Zary 	atp_writeb_base(atpdev, 0x3b, 0x20);
1440dcaa0c12SJia-Ju Bai 	msleep(32);
1441c7e6a029SOndrej Zary 	atp_writeb_base(atpdev, 0x3b, 0);
1442dcaa0c12SJia-Ju Bai 	msleep(32);
1443c7e6a029SOndrej Zary 	atp_readb_io(atpdev, 0, 0x1b);
1444c7e6a029SOndrej Zary 	atp_readb_io(atpdev, 0, 0x17);
1445c7e6a029SOndrej Zary 
1446c7e6a029SOndrej Zary 	atp_set_host_id(atpdev, 0, host_id);
1447c7e6a029SOndrej Zary 
1448c7e6a029SOndrej Zary 	tscam(shpnt, true, atp_readb_base(atpdev, 0x22));
1449c7e6a029SOndrej Zary 	atp_is(atpdev, 0, true, atp_readb_base(atpdev, 0x3f) & 0x40);
1450c7e6a029SOndrej Zary 	atp_writeb_base(atpdev, 0x38, 0xb0);
1451c7e6a029SOndrej Zary 	shpnt->max_id = 16;
1452c7e6a029SOndrej Zary 	shpnt->this_id = host_id;
1453c7e6a029SOndrej Zary }
1454c7e6a029SOndrej Zary 
1455ecc6ff95SOndrej Zary static void atp885_init(struct Scsi_Host *shpnt)
1456ecc6ff95SOndrej Zary {
1457ecc6ff95SOndrej Zary 	struct atp_unit *atpdev = shost_priv(shpnt);
1458ecc6ff95SOndrej Zary 	struct pci_dev *pdev = atpdev->pdev;
1459ecc6ff95SOndrej Zary 	unsigned char k, m, c;
1460ecc6ff95SOndrej Zary 	unsigned int n;
1461ecc6ff95SOndrej Zary 	unsigned char setupdata[2][16];
1462ecc6ff95SOndrej Zary 
1463bcd5c59fSHannes Reinecke 	dev_info(&pdev->dev, "ACARD AEC-67162 PCI Ultra3 LVD "
1464bcd5c59fSHannes Reinecke 		 "Host Adapter: IO:%lx, IRQ:%d.\n",
1465ecc6ff95SOndrej Zary 		 shpnt->io_port, shpnt->irq);
1466ecc6ff95SOndrej Zary 
1467ecc6ff95SOndrej Zary 	atpdev->ioport[0] = shpnt->io_port + 0x80;
1468ecc6ff95SOndrej Zary 	atpdev->ioport[1] = shpnt->io_port + 0xc0;
1469ecc6ff95SOndrej Zary 	atpdev->pciport[0] = shpnt->io_port + 0x40;
1470ecc6ff95SOndrej Zary 	atpdev->pciport[1] = shpnt->io_port + 0x50;
1471ecc6ff95SOndrej Zary 
1472ecc6ff95SOndrej Zary 	c = atp_readb_base(atpdev, 0x29);
1473ecc6ff95SOndrej Zary 	atp_writeb_base(atpdev, 0x29, c | 0x04);
1474ecc6ff95SOndrej Zary 
1475ecc6ff95SOndrej Zary 	n = 0x1f80;
1476ecc6ff95SOndrej Zary 	while (n < 0x2000) {
1477ecc6ff95SOndrej Zary 		atp_writew_base(atpdev, 0x3c, n);
1478ecc6ff95SOndrej Zary 		if (atp_readl_base(atpdev, 0x38) == 0xffffffff)
1479ecc6ff95SOndrej Zary 			break;
1480ecc6ff95SOndrej Zary 		for (m = 0; m < 2; m++) {
1481ecc6ff95SOndrej Zary 			atpdev->global_map[m] = 0;
1482ecc6ff95SOndrej Zary 			for (k = 0; k < 4; k++) {
1483ecc6ff95SOndrej Zary 				atp_writew_base(atpdev, 0x3c, n++);
1484bcd5c59fSHannes Reinecke 				((u32 *)&setupdata[m][0])[k] =
1485bcd5c59fSHannes Reinecke 					atp_readl_base(atpdev, 0x38);
1486ecc6ff95SOndrej Zary 			}
1487ecc6ff95SOndrej Zary 			for (k = 0; k < 4; k++) {
1488ecc6ff95SOndrej Zary 				atp_writew_base(atpdev, 0x3c, n++);
1489bcd5c59fSHannes Reinecke 				((u32 *)&atpdev->sp[m][0])[k] =
1490bcd5c59fSHannes Reinecke 					atp_readl_base(atpdev, 0x38);
1491ecc6ff95SOndrej Zary 			}
1492ecc6ff95SOndrej Zary 			n += 8;
1493ecc6ff95SOndrej Zary 		}
1494ecc6ff95SOndrej Zary 	}
1495ecc6ff95SOndrej Zary 	c = atp_readb_base(atpdev, 0x29);
1496ecc6ff95SOndrej Zary 	atp_writeb_base(atpdev, 0x29, c & 0xfb);
1497ecc6ff95SOndrej Zary 	for (c = 0; c < 2; c++) {
1498ecc6ff95SOndrej Zary 		atpdev->ultra_map[c] = 0;
1499ecc6ff95SOndrej Zary 		atpdev->async[c] = 0;
1500ecc6ff95SOndrej Zary 		for (k = 0; k < 16; k++) {
1501ecc6ff95SOndrej Zary 			n = 1 << k;
1502ecc6ff95SOndrej Zary 			if (atpdev->sp[c][k] > 1)
1503ecc6ff95SOndrej Zary 				atpdev->ultra_map[c] |= n;
1504ecc6ff95SOndrej Zary 			else
1505ecc6ff95SOndrej Zary 				if (atpdev->sp[c][k] == 0)
1506ecc6ff95SOndrej Zary 					atpdev->async[c] |= n;
1507ecc6ff95SOndrej Zary 		}
1508ecc6ff95SOndrej Zary 		atpdev->async[c] = ~(atpdev->async[c]);
1509ecc6ff95SOndrej Zary 
1510ecc6ff95SOndrej Zary 		if (atpdev->global_map[c] == 0) {
1511ecc6ff95SOndrej Zary 			k = setupdata[c][1];
1512ecc6ff95SOndrej Zary 			if ((k & 0x40) != 0)
1513ecc6ff95SOndrej Zary 				atpdev->global_map[c] |= 0x20;
1514ecc6ff95SOndrej Zary 			k &= 0x07;
1515ecc6ff95SOndrej Zary 			atpdev->global_map[c] |= k;
1516ecc6ff95SOndrej Zary 			if ((setupdata[c][2] & 0x04) != 0)
1517ecc6ff95SOndrej Zary 				atpdev->global_map[c] |= 0x08;
1518ecc6ff95SOndrej Zary 			atpdev->host_id[c] = setupdata[c][0] & 0x07;
1519ecc6ff95SOndrej Zary 		}
1520ecc6ff95SOndrej Zary 	}
1521ecc6ff95SOndrej Zary 
1522ecc6ff95SOndrej Zary 	k = atp_readb_base(atpdev, 0x28) & 0x8f;
1523ecc6ff95SOndrej Zary 	k |= 0x10;
1524ecc6ff95SOndrej Zary 	atp_writeb_base(atpdev, 0x28, k);
1525ecc6ff95SOndrej Zary 	atp_writeb_pci(atpdev, 0, 1, 0x80);
1526ecc6ff95SOndrej Zary 	atp_writeb_pci(atpdev, 1, 1, 0x80);
1527dcaa0c12SJia-Ju Bai 	msleep(100);
1528ecc6ff95SOndrej Zary 	atp_writeb_pci(atpdev, 0, 1, 0);
1529ecc6ff95SOndrej Zary 	atp_writeb_pci(atpdev, 1, 1, 0);
1530dcaa0c12SJia-Ju Bai 	msleep(1000);
1531ecc6ff95SOndrej Zary 	atp_readb_io(atpdev, 0, 0x1b);
1532ecc6ff95SOndrej Zary 	atp_readb_io(atpdev, 0, 0x17);
1533ecc6ff95SOndrej Zary 	atp_readb_io(atpdev, 1, 0x1b);
1534ecc6ff95SOndrej Zary 	atp_readb_io(atpdev, 1, 0x17);
1535ecc6ff95SOndrej Zary 
1536ecc6ff95SOndrej Zary 	k = atpdev->host_id[0];
1537ecc6ff95SOndrej Zary 	if (k > 7)
1538ecc6ff95SOndrej Zary 		k = (k & 0x07) | 0x40;
1539ecc6ff95SOndrej Zary 	atp_set_host_id(atpdev, 0, k);
1540ecc6ff95SOndrej Zary 
1541ecc6ff95SOndrej Zary 	k = atpdev->host_id[1];
1542ecc6ff95SOndrej Zary 	if (k > 7)
1543ecc6ff95SOndrej Zary 		k = (k & 0x07) | 0x40;
1544ecc6ff95SOndrej Zary 	atp_set_host_id(atpdev, 1, k);
1545ecc6ff95SOndrej Zary 
1546dcaa0c12SJia-Ju Bai 	msleep(600); /* this delay used to be called tscam_885() */
1547ecc6ff95SOndrej Zary 	dev_info(&pdev->dev, "Scanning Channel A SCSI Device ...\n");
1548ecc6ff95SOndrej Zary 	atp_is(atpdev, 0, true, atp_readb_io(atpdev, 0, 0x1b) >> 7);
1549ecc6ff95SOndrej Zary 	atp_writeb_io(atpdev, 0, 0x16, 0x80);
1550ecc6ff95SOndrej Zary 	dev_info(&pdev->dev, "Scanning Channel B SCSI Device ...\n");
1551ecc6ff95SOndrej Zary 	atp_is(atpdev, 1, true, atp_readb_io(atpdev, 1, 0x1b) >> 7);
1552ecc6ff95SOndrej Zary 	atp_writeb_io(atpdev, 1, 0x16, 0x80);
1553ecc6ff95SOndrej Zary 	k = atp_readb_base(atpdev, 0x28) & 0xcf;
1554ecc6ff95SOndrej Zary 	k |= 0xc0;
1555ecc6ff95SOndrej Zary 	atp_writeb_base(atpdev, 0x28, k);
1556ecc6ff95SOndrej Zary 	k = atp_readb_base(atpdev, 0x1f) | 0x80;
1557ecc6ff95SOndrej Zary 	atp_writeb_base(atpdev, 0x1f, k);
1558ecc6ff95SOndrej Zary 	k = atp_readb_base(atpdev, 0x29) | 0x01;
1559ecc6ff95SOndrej Zary 	atp_writeb_base(atpdev, 0x29, k);
1560ecc6ff95SOndrej Zary 	shpnt->max_id = 16;
1561ecc6ff95SOndrej Zary 	shpnt->max_lun = (atpdev->global_map[0] & 0x07) + 1;
1562ecc6ff95SOndrej Zary 	shpnt->max_channel = 1;
1563ecc6ff95SOndrej Zary 	shpnt->this_id = atpdev->host_id[0];
1564ecc6ff95SOndrej Zary }
1565ecc6ff95SOndrej Zary 
15661da177e4SLinus Torvalds /* return non-zero on detection */
15671da177e4SLinus Torvalds static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
15681da177e4SLinus Torvalds {
15691da177e4SLinus Torvalds 	struct Scsi_Host *shpnt = NULL;
1570bdd5ac40SOndrej Zary 	struct atp_unit *atpdev;
1571bdd5ac40SOndrej Zary 	int err;
15721da177e4SLinus Torvalds 
1573b1e85063SOndrej Zary 	if (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610 && pdev->revision < 2) {
1574b1e85063SOndrej Zary 		dev_err(&pdev->dev, "ATP850S chips (AEC6710L/F cards) are not supported.\n");
1575b1e85063SOndrej Zary 		return -ENODEV;
1576b1e85063SOndrej Zary 	}
1577b1e85063SOndrej Zary 
1578bdd5ac40SOndrej Zary 	err = pci_enable_device(pdev);
1579bdd5ac40SOndrej Zary 	if (err)
1580bdd5ac40SOndrej Zary 		goto fail;
15811da177e4SLinus Torvalds 
158248ecddb4SChristoph Hellwig 	if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) {
15831da177e4SLinus Torvalds 		printk(KERN_ERR "atp870u: DMA mask required but not available.\n");
1584bdd5ac40SOndrej Zary 		err = -EIO;
1585bdd5ac40SOndrej Zary 		goto disable_device;
15861da177e4SLinus Torvalds 	}
15871da177e4SLinus Torvalds 
158811ec1318SOndrej Zary 	err = pci_request_regions(pdev, "atp870u");
158911ec1318SOndrej Zary 	if (err)
159011ec1318SOndrej Zary 		goto disable_device;
159111ec1318SOndrej Zary 	pci_set_master(pdev);
159211ec1318SOndrej Zary 
1593bdd5ac40SOndrej Zary 	err = -ENOMEM;
1594bdd5ac40SOndrej Zary 	shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
1595bdd5ac40SOndrej Zary 	if (!shpnt)
159611ec1318SOndrej Zary 		goto release_region;
1597bdd5ac40SOndrej Zary 
1598bdd5ac40SOndrej Zary 	atpdev = shost_priv(shpnt);
1599bdd5ac40SOndrej Zary 
1600bdd5ac40SOndrej Zary 	atpdev->host = shpnt;
1601bdd5ac40SOndrej Zary 	atpdev->pdev = pdev;
1602bdd5ac40SOndrej Zary 	pci_set_drvdata(pdev, atpdev);
1603bdd5ac40SOndrej Zary 
16046c9b9c55SOndrej Zary 	shpnt->io_port = pci_resource_start(pdev, 0);
16056c9b9c55SOndrej Zary 	shpnt->io_port &= 0xfffffff8;
16066c9b9c55SOndrej Zary 	shpnt->n_io_port = pci_resource_len(pdev, 0);
16076c9b9c55SOndrej Zary 	atpdev->baseport = shpnt->io_port;
16086c9b9c55SOndrej Zary 	shpnt->unique_id = shpnt->io_port;
16096c9b9c55SOndrej Zary 	shpnt->irq = pdev->irq;
16101da177e4SLinus Torvalds 
1611f5f53a38SOndrej Zary 	err = atp870u_init_tables(shpnt);
1612f5f53a38SOndrej Zary 	if (err) {
1613f5f53a38SOndrej Zary 		dev_err(&pdev->dev, "Unable to allocate tables for Acard controller\n");
1614f5f53a38SOndrej Zary 		goto unregister;
1615f5f53a38SOndrej Zary 	}
1616f5f53a38SOndrej Zary 
1617c7e6a029SOndrej Zary 	if (is880(atpdev))
1618c7e6a029SOndrej Zary 		atp880_init(shpnt);
1619ecc6ff95SOndrej Zary 	else if (is885(atpdev))
1620ecc6ff95SOndrej Zary 		atp885_init(shpnt);
16214190230eSOndrej Zary 	else
16224190230eSOndrej Zary 		atp870_init(shpnt);
16231da177e4SLinus Torvalds 
16241729c0d2SOndrej Zary 	err = request_irq(shpnt->irq, atp870u_intr_handle, IRQF_SHARED, "atp870u", shpnt);
16251729c0d2SOndrej Zary 	if (err) {
16261729c0d2SOndrej Zary 		dev_err(&pdev->dev, "Unable to allocate IRQ %d.\n", shpnt->irq);
16271729c0d2SOndrej Zary 		goto free_tables;
16281729c0d2SOndrej Zary 	}
16291729c0d2SOndrej Zary 
1630bdd5ac40SOndrej Zary 	err = scsi_add_host(shpnt, &pdev->dev);
1631bdd5ac40SOndrej Zary 	if (err)
16321da177e4SLinus Torvalds 		goto scsi_add_fail;
16331da177e4SLinus Torvalds 	scsi_scan_host(shpnt);
16341729c0d2SOndrej Zary 
16351da177e4SLinus Torvalds 	return 0;
16361da177e4SLinus Torvalds 
16371da177e4SLinus Torvalds scsi_add_fail:
16386c9b9c55SOndrej Zary 	free_irq(shpnt->irq, shpnt);
16391da177e4SLinus Torvalds free_tables:
16401da177e4SLinus Torvalds 	atp870u_free_tables(shpnt);
16411da177e4SLinus Torvalds unregister:
16421da177e4SLinus Torvalds 	scsi_host_put(shpnt);
164311ec1318SOndrej Zary release_region:
164411ec1318SOndrej Zary 	pci_release_regions(pdev);
1645bdd5ac40SOndrej Zary disable_device:
1646bdd5ac40SOndrej Zary 	pci_disable_device(pdev);
1647bdd5ac40SOndrej Zary fail:
1648bdd5ac40SOndrej Zary 	return err;
16491da177e4SLinus Torvalds }
16501da177e4SLinus Torvalds 
16511da177e4SLinus Torvalds /* The abort command does not leave the device in a clean state where
16521da177e4SLinus Torvalds    it is available to be used again.  Until this gets worked out, we will
16531da177e4SLinus Torvalds    leave it commented out.  */
16541da177e4SLinus Torvalds 
16551da177e4SLinus Torvalds static int atp870u_abort(struct scsi_cmnd * SCpnt)
16561da177e4SLinus Torvalds {
16571da177e4SLinus Torvalds 	unsigned char  j, k, c;
16581da177e4SLinus Torvalds 	struct scsi_cmnd *workrequ;
16591da177e4SLinus Torvalds 	struct atp_unit *dev;
16601da177e4SLinus Torvalds 	struct Scsi_Host *host;
16611da177e4SLinus Torvalds 	host = SCpnt->device->host;
16621da177e4SLinus Torvalds 
16631da177e4SLinus Torvalds 	dev = (struct atp_unit *)&host->hostdata;
1664422c0d61SJeff Garzik 	c = scmd_channel(SCpnt);
16651da177e4SLinus Torvalds 	printk(" atp870u: abort Channel = %x \n", c);
16661da177e4SLinus Torvalds 	printk("working=%x last_cmd=%x ", dev->working[c], dev->last_cmd[c]);
16671da177e4SLinus Torvalds 	printk(" quhdu=%x quendu=%x ", dev->quhd[c], dev->quend[c]);
16681da177e4SLinus Torvalds 	for (j = 0; j < 0x18; j++) {
16696a3cebb6SOndrej Zary 		printk(" r%2x=%2x", j, atp_readb_io(dev, c, j));
16701da177e4SLinus Torvalds 	}
16716a3cebb6SOndrej Zary 	printk(" r1c=%2x", atp_readb_io(dev, c, 0x1c));
16726a3cebb6SOndrej Zary 	printk(" r1f=%2x in_snd=%2x ", atp_readb_io(dev, c, 0x1f), dev->in_snd[c]);
16736a3cebb6SOndrej Zary 	printk(" d00=%2x", atp_readb_pci(dev, c, 0x00));
16746a3cebb6SOndrej Zary 	printk(" d02=%2x", atp_readb_pci(dev, c, 0x02));
16751da177e4SLinus Torvalds 	for(j=0;j<16;j++) {
16761da177e4SLinus Torvalds 	   if (dev->id[c][j].curr_req != NULL) {
16771da177e4SLinus Torvalds 		workrequ = dev->id[c][j].curr_req;
16781da177e4SLinus Torvalds 		printk("\n que cdb= ");
16791da177e4SLinus Torvalds 		for (k=0; k < workrequ->cmd_len; k++) {
16801da177e4SLinus Torvalds 		    printk(" %2x ",workrequ->cmnd[k]);
16811da177e4SLinus Torvalds 		}
16821da177e4SLinus Torvalds 		printk(" last_lenu= %x ",(unsigned int)dev->id[c][j].last_len);
16831da177e4SLinus Torvalds 	   }
16841da177e4SLinus Torvalds 	}
16851da177e4SLinus Torvalds 	return SUCCESS;
16861da177e4SLinus Torvalds }
16871da177e4SLinus Torvalds 
16881da177e4SLinus Torvalds static const char *atp870u_info(struct Scsi_Host *notused)
16891da177e4SLinus Torvalds {
16901da177e4SLinus Torvalds 	static char buffer[128];
16911da177e4SLinus Torvalds 
16921da177e4SLinus Torvalds 	strcpy(buffer, "ACARD AEC-6710/6712/67160 PCI Ultra/W/LVD SCSI-3 Adapter Driver V2.6+ac ");
16931da177e4SLinus Torvalds 
16941da177e4SLinus Torvalds 	return buffer;
16951da177e4SLinus Torvalds }
16961da177e4SLinus Torvalds 
1697d773e422SAl Viro static int atp870u_show_info(struct seq_file *m, struct Scsi_Host *HBAptr)
16981da177e4SLinus Torvalds {
16993d30079cSRasmus Villemoes 	seq_puts(m, "ACARD AEC-671X Driver Version: 2.6+ac\n\n"
17003d30079cSRasmus Villemoes 		"Adapter Configuration:\n");
1701d773e422SAl Viro 	seq_printf(m, "               Base IO: %#.4lx\n", HBAptr->io_port);
1702d773e422SAl Viro 	seq_printf(m, "                   IRQ: %d\n", HBAptr->irq);
1703d773e422SAl Viro 	return 0;
17041da177e4SLinus Torvalds }
17051da177e4SLinus Torvalds 
17061da177e4SLinus Torvalds 
17071da177e4SLinus Torvalds static int atp870u_biosparam(struct scsi_device *disk, struct block_device *dev,
17081da177e4SLinus Torvalds 			sector_t capacity, int *ip)
17091da177e4SLinus Torvalds {
17101da177e4SLinus Torvalds 	int heads, sectors, cylinders;
17111da177e4SLinus Torvalds 
17121da177e4SLinus Torvalds 	heads = 64;
17131da177e4SLinus Torvalds 	sectors = 32;
17141da177e4SLinus Torvalds 	cylinders = (unsigned long)capacity / (heads * sectors);
17151da177e4SLinus Torvalds 	if (cylinders > 1024) {
17161da177e4SLinus Torvalds 		heads = 255;
17171da177e4SLinus Torvalds 		sectors = 63;
17181da177e4SLinus Torvalds 		cylinders = (unsigned long)capacity / (heads * sectors);
17191da177e4SLinus Torvalds 	}
17201da177e4SLinus Torvalds 	ip[0] = heads;
17211da177e4SLinus Torvalds 	ip[1] = sectors;
17221da177e4SLinus Torvalds 	ip[2] = cylinders;
17231da177e4SLinus Torvalds 
17241da177e4SLinus Torvalds 	return 0;
17251da177e4SLinus Torvalds }
17261da177e4SLinus Torvalds 
17271da177e4SLinus Torvalds static void atp870u_remove (struct pci_dev *pdev)
17281da177e4SLinus Torvalds {
17291da177e4SLinus Torvalds 	struct atp_unit *devext = pci_get_drvdata(pdev);
17301da177e4SLinus Torvalds 	struct Scsi_Host *pshost = devext->host;
17311da177e4SLinus Torvalds 
17321da177e4SLinus Torvalds 	scsi_remove_host(pshost);
17331da177e4SLinus Torvalds 	free_irq(pshost->irq, pshost);
173411ec1318SOndrej Zary 	pci_release_regions(pdev);
173511ec1318SOndrej Zary 	pci_disable_device(pdev);
17361da177e4SLinus Torvalds 	atp870u_free_tables(pshost);
17371da177e4SLinus Torvalds 	scsi_host_put(pshost);
17381da177e4SLinus Torvalds }
17391da177e4SLinus Torvalds MODULE_LICENSE("GPL");
17401da177e4SLinus Torvalds 
17411da177e4SLinus Torvalds static struct scsi_host_template atp870u_template = {
17421da177e4SLinus Torvalds      .module			= THIS_MODULE,
17431da177e4SLinus Torvalds      .name			= "atp870u"		/* name */,
17441da177e4SLinus Torvalds      .proc_name			= "atp870u",
1745d773e422SAl Viro      .show_info			= atp870u_show_info,
17461da177e4SLinus Torvalds      .info			= atp870u_info		/* info */,
17471da177e4SLinus Torvalds      .queuecommand		= atp870u_queuecommand	/* queuecommand */,
17481da177e4SLinus Torvalds      .eh_abort_handler		= atp870u_abort		/* abort */,
17491da177e4SLinus Torvalds      .bios_param		= atp870u_biosparam	/* biosparm */,
17501da177e4SLinus Torvalds      .can_queue			= qcnt			/* can_queue */,
17511da177e4SLinus Torvalds      .this_id			= 7			/* SCSI ID */,
175235c33633SFinn Thain      .sg_tablesize		= ATP870U_SCATTER	/*SG_ALL*/,
17531da177e4SLinus Torvalds      .max_sectors		= ATP870U_MAX_SECTORS,
17541da177e4SLinus Torvalds };
17551da177e4SLinus Torvalds 
17561da177e4SLinus Torvalds static struct pci_device_id atp870u_id_table[] = {
17571da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP885_DEVID)			  },
17581da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID1)		  },
17591da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID2)		  },
17601da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7610)    },
17611da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612UW)  },
17621da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612U)   },
17631da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612S)   },
17641da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612D)	  },
17651da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612SUW) },
17661da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_8060)	  },
17671da177e4SLinus Torvalds 	{ 0, },
17681da177e4SLinus Torvalds };
17691da177e4SLinus Torvalds 
17701da177e4SLinus Torvalds MODULE_DEVICE_TABLE(pci, atp870u_id_table);
17711da177e4SLinus Torvalds 
17721da177e4SLinus Torvalds static struct pci_driver atp870u_driver = {
17731da177e4SLinus Torvalds 	.id_table	= atp870u_id_table,
17741da177e4SLinus Torvalds 	.name		= "atp870u",
17751da177e4SLinus Torvalds 	.probe		= atp870u_probe,
17766f039790SGreg Kroah-Hartman 	.remove		= atp870u_remove,
17771da177e4SLinus Torvalds };
17781da177e4SLinus Torvalds 
17791ccd7d68SOndrej Zary module_pci_driver(atp870u_driver);
17801da177e4SLinus Torvalds 
1781bcd5c59fSHannes Reinecke static void atp_is(struct atp_unit *dev, unsigned char c, bool wide_chip,
1782bcd5c59fSHannes Reinecke 		   unsigned char lvdmode)
17831da177e4SLinus Torvalds {
1784fa50b308SOndrej Zary 	unsigned char i, j, k, rmb, n;
17851da177e4SLinus Torvalds 	unsigned short int m;
17861da177e4SLinus Torvalds 	static unsigned char mbuf[512];
17871da177e4SLinus Torvalds 	static unsigned char satn[9] = { 0, 0, 0, 0, 0, 0, 0, 6, 6 };
17881da177e4SLinus Torvalds 	static unsigned char inqd[9] = { 0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6 };
17891da177e4SLinus Torvalds 	static unsigned char synn[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
17901da177e4SLinus Torvalds 	unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
17911da177e4SLinus Torvalds 	static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
1792460da918SOndrej Zary 	static unsigned char synw_870[6] = { 0x80, 1, 3, 1, 0x0c, 0x07 };
17931da177e4SLinus Torvalds 	unsigned char synuw[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
17941da177e4SLinus Torvalds 	static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
17951da177e4SLinus Torvalds 	static unsigned char u3[9] = { 0x80, 1, 6, 4, 0x09, 00, 0x0e, 0x01, 0x02 };
17961da177e4SLinus Torvalds 
17971da177e4SLinus Torvalds 	for (i = 0; i < 16; i++) {
1798197fb8d8SOndrej Zary 		if (!wide_chip && (i > 7))
1799197fb8d8SOndrej Zary 			break;
18001da177e4SLinus Torvalds 		m = 1;
18011da177e4SLinus Torvalds 		m = m << i;
18021da177e4SLinus Torvalds 		if ((m & dev->active_id[c]) != 0) {
18031da177e4SLinus Torvalds 			continue;
18041da177e4SLinus Torvalds 		}
18051da177e4SLinus Torvalds 		if (i == dev->host_id[c]) {
18061da177e4SLinus Torvalds 			printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_id[c]);
18071da177e4SLinus Torvalds 			continue;
18081da177e4SLinus Torvalds 		}
1809197fb8d8SOndrej Zary 		atp_writeb_io(dev, c, 0x1b, wide_chip ? 0x01 : 0x00);
18105d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 1, 0x08);
18115d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 2, 0x7f);
18125d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 3, satn[0]);
18135d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 4, satn[1]);
18145d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 5, satn[2]);
18155d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 6, satn[3]);
18165d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 7, satn[4]);
18175d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 8, satn[5]);
18185d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x0f, 0);
18195d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
18205d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
18215d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, satn[6]);
18225d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, satn[7]);
18231da177e4SLinus Torvalds 		j = i;
18241da177e4SLinus Torvalds 		if ((j & 0x08) != 0) {
18251da177e4SLinus Torvalds 			j = (j & 0x07) | 0x40;
18261da177e4SLinus Torvalds 		}
18275d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x15, j);
18285d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, satn[8]);
18291da177e4SLinus Torvalds 
18305d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
18311da177e4SLinus Torvalds 			cpu_relax();
183280b52a7fSOndrej Zary 
183380b52a7fSOndrej Zary 		if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e)
18341da177e4SLinus Torvalds 			continue;
183580b52a7fSOndrej Zary 
18365d2a5a4fSOndrej Zary 		while (atp_readb_io(dev, c, 0x17) != 0x8e)
18371da177e4SLinus Torvalds 			cpu_relax();
183880b52a7fSOndrej Zary 
18391da177e4SLinus Torvalds 		dev->active_id[c] |= m;
18401da177e4SLinus Torvalds 
18415d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x10, 0x30);
1842b922a449SOndrej Zary 		if (is885(dev) || is880(dev))
18435d2a5a4fSOndrej Zary 			atp_writeb_io(dev, c, 0x14, 0x00);
1844460da918SOndrej Zary 		else /* result of is870() merge - is this a bug? */
1845460da918SOndrej Zary 			atp_writeb_io(dev, c, 0x04, 0x00);
18461da177e4SLinus Torvalds 
18471da177e4SLinus Torvalds phase_cmd:
18485d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
184980b52a7fSOndrej Zary 
18505d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
18511da177e4SLinus Torvalds 			cpu_relax();
185280b52a7fSOndrej Zary 
18535d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
18541da177e4SLinus Torvalds 		if (j != 0x16) {
18555d2a5a4fSOndrej Zary 			atp_writeb_io(dev, c, 0x10, 0x41);
18561da177e4SLinus Torvalds 			goto phase_cmd;
18571da177e4SLinus Torvalds 		}
18581da177e4SLinus Torvalds sel_ok:
18595d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 3, inqd[0]);
18605d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 4, inqd[1]);
18615d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 5, inqd[2]);
18625d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 6, inqd[3]);
18635d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 7, inqd[4]);
18645d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 8, inqd[5]);
18655d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x0f, 0);
18665d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
18675d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
18685d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, inqd[6]);
18695d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, inqd[7]);
18705d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, inqd[8]);
187180b52a7fSOndrej Zary 
18725d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
18731da177e4SLinus Torvalds 			cpu_relax();
187480b52a7fSOndrej Zary 
187580b52a7fSOndrej Zary 		if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e)
18761da177e4SLinus Torvalds 			continue;
187780b52a7fSOndrej Zary 
18785d2a5a4fSOndrej Zary 		while (atp_readb_io(dev, c, 0x17) != 0x8e)
18791da177e4SLinus Torvalds 			cpu_relax();
188080b52a7fSOndrej Zary 
1881197fb8d8SOndrej Zary 		if (wide_chip)
18825d2a5a4fSOndrej Zary 			atp_writeb_io(dev, c, 0x1b, 0x00);
1883197fb8d8SOndrej Zary 
18845d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
18851da177e4SLinus Torvalds 		j = 0;
18861da177e4SLinus Torvalds rd_inq_data:
18875d2a5a4fSOndrej Zary 		k = atp_readb_io(dev, c, 0x1f);
18881da177e4SLinus Torvalds 		if ((k & 0x01) != 0) {
18895d2a5a4fSOndrej Zary 			mbuf[j++] = atp_readb_io(dev, c, 0x19);
18901da177e4SLinus Torvalds 			goto rd_inq_data;
18911da177e4SLinus Torvalds 		}
18921da177e4SLinus Torvalds 		if ((k & 0x80) == 0) {
18931da177e4SLinus Torvalds 			goto rd_inq_data;
18941da177e4SLinus Torvalds 		}
18955d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
18961da177e4SLinus Torvalds 		if (j == 0x16) {
18971da177e4SLinus Torvalds 			goto inq_ok;
18981da177e4SLinus Torvalds 		}
18995d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x10, 0x46);
19005d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
19015d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, 0);
19025d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0);
19035d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
190480b52a7fSOndrej Zary 
19055d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
19061da177e4SLinus Torvalds 			cpu_relax();
190780b52a7fSOndrej Zary 
190880b52a7fSOndrej Zary 		if (atp_readb_io(dev, c, 0x17) != 0x16)
19091da177e4SLinus Torvalds 			goto sel_ok;
191080b52a7fSOndrej Zary 
19111da177e4SLinus Torvalds inq_ok:
19121da177e4SLinus Torvalds 		mbuf[36] = 0;
19131da177e4SLinus Torvalds 		printk(KERN_INFO "         ID: %2d  %s\n", i, &mbuf[8]);
19141da177e4SLinus Torvalds 		dev->id[c][i].devtype = mbuf[0];
19151da177e4SLinus Torvalds 		rmb = mbuf[1];
19161da177e4SLinus Torvalds 		n = mbuf[7];
1917197fb8d8SOndrej Zary 		if (!wide_chip)
1918197fb8d8SOndrej Zary 			goto not_wide;
19191da177e4SLinus Torvalds 		if ((mbuf[7] & 0x60) == 0) {
19201da177e4SLinus Torvalds 			goto not_wide;
19211da177e4SLinus Torvalds 		}
1922b922a449SOndrej Zary 		if (is885(dev) || is880(dev)) {
1923197fb8d8SOndrej Zary 			if ((i < 8) && ((dev->global_map[c] & 0x20) == 0))
1924197fb8d8SOndrej Zary 				goto not_wide;
1925197fb8d8SOndrej Zary 		} else { /* result of is870() merge - is this a bug? */
1926197fb8d8SOndrej Zary 			if ((dev->global_map[c] & 0x20) == 0)
19271da177e4SLinus Torvalds 				goto not_wide;
19281da177e4SLinus Torvalds 		}
19291da177e4SLinus Torvalds 		if (lvdmode == 0) {
19301da177e4SLinus Torvalds 			goto chg_wide;
19311da177e4SLinus Torvalds 		}
193280b52a7fSOndrej Zary 		if (dev->sp[c][i] != 0x04)	// force u2
193380b52a7fSOndrej Zary 		{
19341da177e4SLinus Torvalds 			goto chg_wide;
19351da177e4SLinus Torvalds 		}
19361da177e4SLinus Torvalds 
19375d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x1b, 0x01);
19385d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 3, satn[0]);
19395d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 4, satn[1]);
19405d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 5, satn[2]);
19415d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 6, satn[3]);
19425d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 7, satn[4]);
19435d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 8, satn[5]);
19445d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x0f, 0);
19455d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
19465d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
19475d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, satn[6]);
19485d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, satn[7]);
19495d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, satn[8]);
19501da177e4SLinus Torvalds 
19515d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
19521da177e4SLinus Torvalds 			cpu_relax();
195380b52a7fSOndrej Zary 
195480b52a7fSOndrej Zary 		if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e)
19551da177e4SLinus Torvalds 			continue;
195680b52a7fSOndrej Zary 
19575d2a5a4fSOndrej Zary 		while (atp_readb_io(dev, c, 0x17) != 0x8e)
19581da177e4SLinus Torvalds 			cpu_relax();
195980b52a7fSOndrej Zary 
19601da177e4SLinus Torvalds try_u3:
19611da177e4SLinus Torvalds 		j = 0;
19625d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x09);
19635d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
19641da177e4SLinus Torvalds 
19655d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) {
19665d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0)
19675d2a5a4fSOndrej Zary 				atp_writeb_io(dev, c, 0x19, u3[j++]);
19681da177e4SLinus Torvalds 			cpu_relax();
19691da177e4SLinus Torvalds 		}
197080b52a7fSOndrej Zary 
19715d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00)
19721da177e4SLinus Torvalds 			cpu_relax();
197380b52a7fSOndrej Zary 
19745d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
19751da177e4SLinus Torvalds 		if (j == 0x0f) {
19761da177e4SLinus Torvalds 			goto u3p_in;
19771da177e4SLinus Torvalds 		}
19781da177e4SLinus Torvalds 		if (j == 0x0a) {
19791da177e4SLinus Torvalds 			goto u3p_cmd;
19801da177e4SLinus Torvalds 		}
19811da177e4SLinus Torvalds 		if (j == 0x0e) {
19821da177e4SLinus Torvalds 			goto try_u3;
19831da177e4SLinus Torvalds 		}
19841da177e4SLinus Torvalds 		continue;
19851da177e4SLinus Torvalds u3p_out:
19865d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
19875d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) {
19885d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0)
19895d2a5a4fSOndrej Zary 				atp_writeb_io(dev, c, 0x19, 0);
19901da177e4SLinus Torvalds 			cpu_relax();
19911da177e4SLinus Torvalds 		}
19925d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
19931da177e4SLinus Torvalds 		if (j == 0x0f) {
19941da177e4SLinus Torvalds 			goto u3p_in;
19951da177e4SLinus Torvalds 		}
19961da177e4SLinus Torvalds 		if (j == 0x0a) {
19971da177e4SLinus Torvalds 			goto u3p_cmd;
19981da177e4SLinus Torvalds 		}
19991da177e4SLinus Torvalds 		if (j == 0x0e) {
20001da177e4SLinus Torvalds 			goto u3p_out;
20011da177e4SLinus Torvalds 		}
20021da177e4SLinus Torvalds 		continue;
20031da177e4SLinus Torvalds u3p_in:
20045d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x09);
20055d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
20061da177e4SLinus Torvalds 		k = 0;
20071da177e4SLinus Torvalds u3p_in1:
20085d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x1f);
20091da177e4SLinus Torvalds 		if ((j & 0x01) != 0) {
20105d2a5a4fSOndrej Zary 			mbuf[k++] = atp_readb_io(dev, c, 0x19);
20111da177e4SLinus Torvalds 			goto u3p_in1;
20121da177e4SLinus Torvalds 		}
20131da177e4SLinus Torvalds 		if ((j & 0x80) == 0x00) {
20141da177e4SLinus Torvalds 			goto u3p_in1;
20151da177e4SLinus Torvalds 		}
20165d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
20171da177e4SLinus Torvalds 		if (j == 0x0f) {
20181da177e4SLinus Torvalds 			goto u3p_in;
20191da177e4SLinus Torvalds 		}
20201da177e4SLinus Torvalds 		if (j == 0x0a) {
20211da177e4SLinus Torvalds 			goto u3p_cmd;
20221da177e4SLinus Torvalds 		}
20231da177e4SLinus Torvalds 		if (j == 0x0e) {
20241da177e4SLinus Torvalds 			goto u3p_out;
20251da177e4SLinus Torvalds 		}
20261da177e4SLinus Torvalds 		continue;
20271da177e4SLinus Torvalds u3p_cmd:
20285d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x10, 0x30);
20295d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x00);
20305d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
203180b52a7fSOndrej Zary 
20325d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00);
203380b52a7fSOndrej Zary 
20345d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
20351da177e4SLinus Torvalds 		if (j != 0x16) {
20361da177e4SLinus Torvalds 			if (j == 0x4e) {
20371da177e4SLinus Torvalds 				goto u3p_out;
20381da177e4SLinus Torvalds 			}
20391da177e4SLinus Torvalds 			continue;
20401da177e4SLinus Torvalds 		}
20411da177e4SLinus Torvalds 		if (mbuf[0] != 0x01) {
20421da177e4SLinus Torvalds 			goto chg_wide;
20431da177e4SLinus Torvalds 		}
20441da177e4SLinus Torvalds 		if (mbuf[1] != 0x06) {
20451da177e4SLinus Torvalds 			goto chg_wide;
20461da177e4SLinus Torvalds 		}
20471da177e4SLinus Torvalds 		if (mbuf[2] != 0x04) {
20481da177e4SLinus Torvalds 			goto chg_wide;
20491da177e4SLinus Torvalds 		}
20501da177e4SLinus Torvalds 		if (mbuf[3] == 0x09) {
20511da177e4SLinus Torvalds 			m = 1;
20521da177e4SLinus Torvalds 			m = m << i;
20531da177e4SLinus Torvalds 			dev->wide_id[c] |= m;
20541da177e4SLinus Torvalds 			dev->id[c][i].devsp = 0xce;
20551da177e4SLinus Torvalds #ifdef ED_DBGP
2056bcd5c59fSHannes Reinecke 			printk("dev->id[%2d][%2d].devsp = %2x\n",
2057bcd5c59fSHannes Reinecke 			       c, i, dev->id[c][i].devsp);
20581da177e4SLinus Torvalds #endif
20591da177e4SLinus Torvalds 			continue;
20601da177e4SLinus Torvalds 		}
20611da177e4SLinus Torvalds chg_wide:
20625d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x1b, 0x01);
20635d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 3, satn[0]);
20645d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 4, satn[1]);
20655d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 5, satn[2]);
20665d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 6, satn[3]);
20675d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 7, satn[4]);
20685d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 8, satn[5]);
20695d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x0f, 0);
20705d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
20715d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
20725d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, satn[6]);
20735d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, satn[7]);
20745d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, satn[8]);
20751da177e4SLinus Torvalds 
20765d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
20771da177e4SLinus Torvalds 			cpu_relax();
207880b52a7fSOndrej Zary 
2079bcd5c59fSHannes Reinecke 		if (atp_readb_io(dev, c, 0x17) != 0x11 &&
2080bcd5c59fSHannes Reinecke 		    atp_readb_io(dev, c, 0x17) != 0x8e)
20811da177e4SLinus Torvalds 			continue;
208280b52a7fSOndrej Zary 
20835d2a5a4fSOndrej Zary 		while (atp_readb_io(dev, c, 0x17) != 0x8e)
20841da177e4SLinus Torvalds 			cpu_relax();
208580b52a7fSOndrej Zary 
20861da177e4SLinus Torvalds try_wide:
20871da177e4SLinus Torvalds 		j = 0;
20885d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x05);
20895d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
20901da177e4SLinus Torvalds 
20915d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) {
20925d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0)
20935d2a5a4fSOndrej Zary 				atp_writeb_io(dev, c, 0x19, wide[j++]);
20941da177e4SLinus Torvalds 			cpu_relax();
20951da177e4SLinus Torvalds 		}
209680b52a7fSOndrej Zary 
20975d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00)
20981da177e4SLinus Torvalds 			cpu_relax();
209980b52a7fSOndrej Zary 
21005d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
21011da177e4SLinus Torvalds 		if (j == 0x0f) {
21021da177e4SLinus Torvalds 			goto widep_in;
21031da177e4SLinus Torvalds 		}
21041da177e4SLinus Torvalds 		if (j == 0x0a) {
21051da177e4SLinus Torvalds 			goto widep_cmd;
21061da177e4SLinus Torvalds 		}
21071da177e4SLinus Torvalds 		if (j == 0x0e) {
21081da177e4SLinus Torvalds 			goto try_wide;
21091da177e4SLinus Torvalds 		}
21101da177e4SLinus Torvalds 		continue;
21111da177e4SLinus Torvalds widep_out:
21125d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
21135d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) {
21145d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0)
21155d2a5a4fSOndrej Zary 				atp_writeb_io(dev, c, 0x19, 0);
21161da177e4SLinus Torvalds 			cpu_relax();
21171da177e4SLinus Torvalds 		}
21185d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
21191da177e4SLinus Torvalds 		if (j == 0x0f) {
21201da177e4SLinus Torvalds 			goto widep_in;
21211da177e4SLinus Torvalds 		}
21221da177e4SLinus Torvalds 		if (j == 0x0a) {
21231da177e4SLinus Torvalds 			goto widep_cmd;
21241da177e4SLinus Torvalds 		}
21251da177e4SLinus Torvalds 		if (j == 0x0e) {
21261da177e4SLinus Torvalds 			goto widep_out;
21271da177e4SLinus Torvalds 		}
21281da177e4SLinus Torvalds 		continue;
21291da177e4SLinus Torvalds widep_in:
21305d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0xff);
21315d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
21321da177e4SLinus Torvalds 		k = 0;
21331da177e4SLinus Torvalds widep_in1:
21345d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x1f);
21351da177e4SLinus Torvalds 		if ((j & 0x01) != 0) {
21365d2a5a4fSOndrej Zary 			mbuf[k++] = atp_readb_io(dev, c, 0x19);
21371da177e4SLinus Torvalds 			goto widep_in1;
21381da177e4SLinus Torvalds 		}
21391da177e4SLinus Torvalds 		if ((j & 0x80) == 0x00) {
21401da177e4SLinus Torvalds 			goto widep_in1;
21411da177e4SLinus Torvalds 		}
21425d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
21431da177e4SLinus Torvalds 		if (j == 0x0f) {
21441da177e4SLinus Torvalds 			goto widep_in;
21451da177e4SLinus Torvalds 		}
21461da177e4SLinus Torvalds 		if (j == 0x0a) {
21471da177e4SLinus Torvalds 			goto widep_cmd;
21481da177e4SLinus Torvalds 		}
21491da177e4SLinus Torvalds 		if (j == 0x0e) {
21501da177e4SLinus Torvalds 			goto widep_out;
21511da177e4SLinus Torvalds 		}
21521da177e4SLinus Torvalds 		continue;
21531da177e4SLinus Torvalds widep_cmd:
21545d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x10, 0x30);
21555d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x00);
21565d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
215780b52a7fSOndrej Zary 
21585d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
21591da177e4SLinus Torvalds 			cpu_relax();
216080b52a7fSOndrej Zary 
21615d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
21621da177e4SLinus Torvalds 		if (j != 0x16) {
21631da177e4SLinus Torvalds 			if (j == 0x4e) {
21641da177e4SLinus Torvalds 				goto widep_out;
21651da177e4SLinus Torvalds 			}
21661da177e4SLinus Torvalds 			continue;
21671da177e4SLinus Torvalds 		}
21681da177e4SLinus Torvalds 		if (mbuf[0] != 0x01) {
21691da177e4SLinus Torvalds 			goto not_wide;
21701da177e4SLinus Torvalds 		}
21711da177e4SLinus Torvalds 		if (mbuf[1] != 0x02) {
21721da177e4SLinus Torvalds 			goto not_wide;
21731da177e4SLinus Torvalds 		}
21741da177e4SLinus Torvalds 		if (mbuf[2] != 0x03) {
21751da177e4SLinus Torvalds 			goto not_wide;
21761da177e4SLinus Torvalds 		}
21771da177e4SLinus Torvalds 		if (mbuf[3] != 0x01) {
21781da177e4SLinus Torvalds 			goto not_wide;
21791da177e4SLinus Torvalds 		}
21801da177e4SLinus Torvalds 		m = 1;
21811da177e4SLinus Torvalds 		m = m << i;
21821da177e4SLinus Torvalds 		dev->wide_id[c] |= m;
21831da177e4SLinus Torvalds not_wide:
2184bcd5c59fSHannes Reinecke 		if ((dev->id[c][i].devtype == 0x00) ||
2185bcd5c59fSHannes Reinecke 		    (dev->id[c][i].devtype == 0x07) ||
2186bcd5c59fSHannes Reinecke 		    ((dev->id[c][i].devtype == 0x05) && ((n & 0x10) != 0))) {
21871da177e4SLinus Torvalds 			m = 1;
21881da177e4SLinus Torvalds 			m = m << i;
21891da177e4SLinus Torvalds 			if ((dev->async[c] & m) != 0) {
21901da177e4SLinus Torvalds 				goto set_sync;
21911da177e4SLinus Torvalds 			}
21921da177e4SLinus Torvalds 		}
21931da177e4SLinus Torvalds 		continue;
21941da177e4SLinus Torvalds set_sync:
2195b922a449SOndrej Zary 		if ((!is885(dev) && !is880(dev)) || (dev->sp[c][i] == 0x02)) {
21961da177e4SLinus Torvalds 			synu[4] = 0x0c;
21971da177e4SLinus Torvalds 			synuw[4] = 0x0c;
21981da177e4SLinus Torvalds 		} else {
21991da177e4SLinus Torvalds 			if (dev->sp[c][i] >= 0x03) {
22001da177e4SLinus Torvalds 				synu[4] = 0x0a;
22011da177e4SLinus Torvalds 				synuw[4] = 0x0a;
22021da177e4SLinus Torvalds 			}
22031da177e4SLinus Torvalds 		}
22041da177e4SLinus Torvalds 		j = 0;
22051da177e4SLinus Torvalds 		if ((m & dev->wide_id[c]) != 0) {
22061da177e4SLinus Torvalds 			j |= 0x01;
22071da177e4SLinus Torvalds 		}
22085d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x1b, j);
22095d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 3, satn[0]);
22105d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 4, satn[1]);
22115d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 5, satn[2]);
22125d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 6, satn[3]);
22135d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 7, satn[4]);
22145d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 8, satn[5]);
22155d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x0f, 0);
22165d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
22175d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
22185d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, satn[6]);
22195d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, satn[7]);
22205d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, satn[8]);
22211da177e4SLinus Torvalds 
22225d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
22231da177e4SLinus Torvalds 			cpu_relax();
222480b52a7fSOndrej Zary 
2225bcd5c59fSHannes Reinecke 		if (atp_readb_io(dev, c, 0x17) != 0x11 &&
2226bcd5c59fSHannes Reinecke 		    atp_readb_io(dev, c, 0x17) != 0x8e)
22271da177e4SLinus Torvalds 			continue;
222880b52a7fSOndrej Zary 
22295d2a5a4fSOndrej Zary 		while (atp_readb_io(dev, c, 0x17) != 0x8e)
22301da177e4SLinus Torvalds 			cpu_relax();
223180b52a7fSOndrej Zary 
22321da177e4SLinus Torvalds try_sync:
22331da177e4SLinus Torvalds 		j = 0;
22345d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x06);
22355d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
22361da177e4SLinus Torvalds 
22375d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) {
22385d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0) {
22391da177e4SLinus Torvalds 				if ((m & dev->wide_id[c]) != 0) {
2240b922a449SOndrej Zary 					if (is885(dev) || is880(dev)) {
22411da177e4SLinus Torvalds 						if ((m & dev->ultra_map[c]) != 0) {
22425d2a5a4fSOndrej Zary 							atp_writeb_io(dev, c, 0x19, synuw[j++]);
22431da177e4SLinus Torvalds 						} else {
22445d2a5a4fSOndrej Zary 							atp_writeb_io(dev, c, 0x19, synw[j++]);
22451da177e4SLinus Torvalds 						}
2246460da918SOndrej Zary 					} else
2247460da918SOndrej Zary 						atp_writeb_io(dev, c, 0x19, synw_870[j++]);
22481da177e4SLinus Torvalds 				} else {
22491da177e4SLinus Torvalds 					if ((m & dev->ultra_map[c]) != 0) {
22505d2a5a4fSOndrej Zary 						atp_writeb_io(dev, c, 0x19, synu[j++]);
22511da177e4SLinus Torvalds 					} else {
22525d2a5a4fSOndrej Zary 						atp_writeb_io(dev, c, 0x19, synn[j++]);
22531da177e4SLinus Torvalds 					}
22541da177e4SLinus Torvalds 				}
22551da177e4SLinus Torvalds 			}
22561da177e4SLinus Torvalds 		}
225780b52a7fSOndrej Zary 
22585d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00)
22591da177e4SLinus Torvalds 			cpu_relax();
226080b52a7fSOndrej Zary 
22615d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
22621da177e4SLinus Torvalds 		if (j == 0x0f) {
22631da177e4SLinus Torvalds 			goto phase_ins;
22641da177e4SLinus Torvalds 		}
22651da177e4SLinus Torvalds 		if (j == 0x0a) {
22661da177e4SLinus Torvalds 			goto phase_cmds;
22671da177e4SLinus Torvalds 		}
22681da177e4SLinus Torvalds 		if (j == 0x0e) {
22691da177e4SLinus Torvalds 			goto try_sync;
22701da177e4SLinus Torvalds 		}
22711da177e4SLinus Torvalds 		continue;
22721da177e4SLinus Torvalds phase_outs:
22735d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
22745d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) {
22755d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0x00)
22765d2a5a4fSOndrej Zary 				atp_writeb_io(dev, c, 0x19, 0x00);
22771da177e4SLinus Torvalds 			cpu_relax();
22781da177e4SLinus Torvalds 		}
22795d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
22801da177e4SLinus Torvalds 		if (j == 0x85) {
22811da177e4SLinus Torvalds 			goto tar_dcons;
22821da177e4SLinus Torvalds 		}
22831da177e4SLinus Torvalds 		j &= 0x0f;
22841da177e4SLinus Torvalds 		if (j == 0x0f) {
22851da177e4SLinus Torvalds 			goto phase_ins;
22861da177e4SLinus Torvalds 		}
22871da177e4SLinus Torvalds 		if (j == 0x0a) {
22881da177e4SLinus Torvalds 			goto phase_cmds;
22891da177e4SLinus Torvalds 		}
22901da177e4SLinus Torvalds 		if (j == 0x0e) {
22911da177e4SLinus Torvalds 			goto phase_outs;
22921da177e4SLinus Torvalds 		}
22931da177e4SLinus Torvalds 		continue;
22941da177e4SLinus Torvalds phase_ins:
2295b922a449SOndrej Zary 		if (is885(dev) || is880(dev))
22965d2a5a4fSOndrej Zary 			atp_writeb_io(dev, c, 0x14, 0x06);
2297460da918SOndrej Zary 		else
2298460da918SOndrej Zary 			atp_writeb_io(dev, c, 0x14, 0xff);
22995d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
23001da177e4SLinus Torvalds 		k = 0;
23011da177e4SLinus Torvalds phase_ins1:
23025d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x1f);
23031da177e4SLinus Torvalds 		if ((j & 0x01) != 0x00) {
23045d2a5a4fSOndrej Zary 			mbuf[k++] = atp_readb_io(dev, c, 0x19);
23051da177e4SLinus Torvalds 			goto phase_ins1;
23061da177e4SLinus Torvalds 		}
23071da177e4SLinus Torvalds 		if ((j & 0x80) == 0x00) {
23081da177e4SLinus Torvalds 			goto phase_ins1;
23091da177e4SLinus Torvalds 		}
231080b52a7fSOndrej Zary 
23115d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00);
231280b52a7fSOndrej Zary 
23135d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
23141da177e4SLinus Torvalds 		if (j == 0x85) {
23151da177e4SLinus Torvalds 			goto tar_dcons;
23161da177e4SLinus Torvalds 		}
23171da177e4SLinus Torvalds 		j &= 0x0f;
23181da177e4SLinus Torvalds 		if (j == 0x0f) {
23191da177e4SLinus Torvalds 			goto phase_ins;
23201da177e4SLinus Torvalds 		}
23211da177e4SLinus Torvalds 		if (j == 0x0a) {
23221da177e4SLinus Torvalds 			goto phase_cmds;
23231da177e4SLinus Torvalds 		}
23241da177e4SLinus Torvalds 		if (j == 0x0e) {
23251da177e4SLinus Torvalds 			goto phase_outs;
23261da177e4SLinus Torvalds 		}
23271da177e4SLinus Torvalds 		continue;
23281da177e4SLinus Torvalds phase_cmds:
23295d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x10, 0x30);
23301da177e4SLinus Torvalds tar_dcons:
23315d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x00);
23325d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
233380b52a7fSOndrej Zary 
23345d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
23351da177e4SLinus Torvalds 			cpu_relax();
233680b52a7fSOndrej Zary 
23375d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
23381da177e4SLinus Torvalds 		if (j != 0x16) {
23391da177e4SLinus Torvalds 			continue;
23401da177e4SLinus Torvalds 		}
23411da177e4SLinus Torvalds 		if (mbuf[0] != 0x01) {
23421da177e4SLinus Torvalds 			continue;
23431da177e4SLinus Torvalds 		}
23441da177e4SLinus Torvalds 		if (mbuf[1] != 0x03) {
23451da177e4SLinus Torvalds 			continue;
23461da177e4SLinus Torvalds 		}
23471da177e4SLinus Torvalds 		if (mbuf[4] == 0x00) {
23481da177e4SLinus Torvalds 			continue;
23491da177e4SLinus Torvalds 		}
23501da177e4SLinus Torvalds 		if (mbuf[3] > 0x64) {
23511da177e4SLinus Torvalds 			continue;
23521da177e4SLinus Torvalds 		}
2353b922a449SOndrej Zary 		if (is885(dev) || is880(dev)) {
23541da177e4SLinus Torvalds 			if (mbuf[4] > 0x0e) {
23551da177e4SLinus Torvalds 				mbuf[4] = 0x0e;
23561da177e4SLinus Torvalds 			}
2357460da918SOndrej Zary 		} else {
2358460da918SOndrej Zary 			if (mbuf[4] > 0x0c) {
2359460da918SOndrej Zary 				mbuf[4] = 0x0c;
2360460da918SOndrej Zary 			}
2361460da918SOndrej Zary 		}
23621da177e4SLinus Torvalds 		dev->id[c][i].devsp = mbuf[4];
2363b922a449SOndrej Zary 		if (is885(dev) || is880(dev))
23641da177e4SLinus Torvalds 			if (mbuf[3] < 0x0c) {
23651da177e4SLinus Torvalds 				j = 0xb0;
23661da177e4SLinus Torvalds 				goto set_syn_ok;
23671da177e4SLinus Torvalds 			}
23681da177e4SLinus Torvalds 		if ((mbuf[3] < 0x0d) && (rmb == 0)) {
23691da177e4SLinus Torvalds 			j = 0xa0;
23701da177e4SLinus Torvalds 			goto set_syn_ok;
23711da177e4SLinus Torvalds 		}
23721da177e4SLinus Torvalds 		if (mbuf[3] < 0x1a) {
23731da177e4SLinus Torvalds 			j = 0x20;
23741da177e4SLinus Torvalds 			goto set_syn_ok;
23751da177e4SLinus Torvalds 		}
23761da177e4SLinus Torvalds 		if (mbuf[3] < 0x33) {
23771da177e4SLinus Torvalds 			j = 0x40;
23781da177e4SLinus Torvalds 			goto set_syn_ok;
23791da177e4SLinus Torvalds 		}
23801da177e4SLinus Torvalds 		if (mbuf[3] < 0x4c) {
23811da177e4SLinus Torvalds 			j = 0x50;
23821da177e4SLinus Torvalds 			goto set_syn_ok;
23831da177e4SLinus Torvalds 		}
23841da177e4SLinus Torvalds 		j = 0x60;
23851da177e4SLinus Torvalds set_syn_ok:
23861da177e4SLinus Torvalds 		dev->id[c][i].devsp = (dev->id[c][i].devsp & 0x0f) | j;
23871da177e4SLinus Torvalds #ifdef ED_DBGP
2388bcd5c59fSHannes Reinecke 		printk("dev->id[%2d][%2d].devsp = %2x\n",
2389bcd5c59fSHannes Reinecke 		       c,i,dev->id[c][i].devsp);
23901da177e4SLinus Torvalds #endif
23911da177e4SLinus Torvalds 	}
23921da177e4SLinus Torvalds }
2393