xref: /linux/drivers/scsi/atp870u.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
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 
43f44e1c63SBart Van Assche static const 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 
atp_writeb_base(struct atp_unit * atp,u8 reg,u8 val)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 
atp_writew_base(struct atp_unit * atp,u8 reg,u16 val)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 
atp_writeb_io(struct atp_unit * atp,u8 channel,u8 reg,u8 val)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 
atp_writew_io(struct atp_unit * atp,u8 channel,u8 reg,u16 val)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 
atp_writeb_pci(struct atp_unit * atp,u8 channel,u8 reg,u8 val)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 
atp_writel_pci(struct atp_unit * atp,u8 channel,u8 reg,u32 val)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 
atp_readb_base(struct atp_unit * atp,u8 reg)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 
atp_readw_base(struct atp_unit * atp,u8 reg)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 
atp_readl_base(struct atp_unit * atp,u8 reg)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 
atp_readb_io(struct atp_unit * atp,u8 channel,u8 reg)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 
atp_readw_io(struct atp_unit * atp,u8 channel,u8 reg)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 
atp_readb_pci(struct atp_unit * atp,u8 channel,u8 reg)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 
is880(struct atp_unit * atp)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 
is885(struct atp_unit * atp)114b922a449SOndrej Zary static inline bool is885(struct atp_unit *atp)
115b922a449SOndrej Zary {
116b922a449SOndrej Zary 	return atp->pdev->device == ATP885_DEVID;
117b922a449SOndrej Zary }
118b922a449SOndrej Zary 
atp870u_intr_handle(int irq,void * dev_id)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);
515681fa525SBart Van Assche 			scsi_done(workreq);
5161da177e4SLinus Torvalds #ifdef ED_DBGP
5171da177e4SLinus Torvalds 			   printk("workreq->scsi_done\n");
5181da177e4SLinus Torvalds #endif
5191da177e4SLinus Torvalds 			/*
5201da177e4SLinus Torvalds 			 *	Clear it off the queue
5211da177e4SLinus Torvalds 			 */
5221da177e4SLinus Torvalds 			dev->id[c][target_id].curr_req = NULL;
5231da177e4SLinus Torvalds 			dev->working[c]--;
5241da177e4SLinus Torvalds 			spin_unlock_irqrestore(dev->host->host_lock, flags);
5251da177e4SLinus Torvalds 			/*
5261da177e4SLinus Torvalds 			 *      Take it back wide
5271da177e4SLinus Torvalds 			 */
5281da177e4SLinus Torvalds 			if (dev->wide_id[c] != 0) {
5296a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x1b, 0x01);
5306a3cebb6SOndrej Zary 				while ((atp_readb_io(dev, c, 0x1b) & 0x01) != 0x01)
5316a3cebb6SOndrej Zary 					atp_writeb_io(dev, c, 0x1b, 0x01);
5321da177e4SLinus Torvalds 			}
5331da177e4SLinus Torvalds 			/*
5341da177e4SLinus Torvalds 			 *	If there is stuff to send and nothing going then send it
5351da177e4SLinus Torvalds 			 */
5361da177e4SLinus Torvalds 			spin_lock_irqsave(dev->host->host_lock, flags);
537bcd5c59fSHannes Reinecke 			if (((dev->last_cmd[c] != 0xff) ||
538bcd5c59fSHannes Reinecke 			     (dev->quhd[c] != dev->quend[c])) &&
5391da177e4SLinus Torvalds 			    (dev->in_snd[c] == 0)) {
5401da177e4SLinus Torvalds #ifdef ED_DBGP
5411da177e4SLinus Torvalds 			   printk("Call sent_s870(scsi_done)\n");
5421da177e4SLinus Torvalds #endif
5431da177e4SLinus Torvalds 			   send_s870(dev,c);
5441da177e4SLinus Torvalds 			}
5451da177e4SLinus Torvalds 			spin_unlock_irqrestore(dev->host->host_lock, flags);
5461da177e4SLinus Torvalds 			dev->in_int[c] = 0;
54778614ecdSOndrej Zary 			return IRQ_HANDLED;
5481da177e4SLinus Torvalds 		}
5491da177e4SLinus Torvalds 		if ((dev->last_cmd[c] & 0xf0) != 0x40) {
5501da177e4SLinus Torvalds 		   dev->last_cmd[c] = 0xff;
5511da177e4SLinus Torvalds 		}
5521da177e4SLinus Torvalds 		if (i == 0x4f) {
5531da177e4SLinus Torvalds 			i = 0x89;
5541da177e4SLinus Torvalds 		}
5551da177e4SLinus Torvalds 		i &= 0x0f;
5561da177e4SLinus Torvalds 		if (i == 0x09) {
5576a3cebb6SOndrej Zary 			atp_writel_pci(dev, c, 4, dev->id[c][target_id].prdaddr);
5586a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 2, 0x06);
5596a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 2, 0x00);
5606a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x10, 0x41);
561b922a449SOndrej Zary 			if (is885(dev)) {
5621da177e4SLinus Torvalds 				k = dev->id[c][target_id].last_len;
563bcd5c59fSHannes Reinecke 				atp_writeb_io(dev, c, 0x12,
564bcd5c59fSHannes Reinecke 					      ((unsigned char *) (&k))[2]);
565bcd5c59fSHannes Reinecke 				atp_writeb_io(dev, c, 0x13,
566bcd5c59fSHannes Reinecke 					      ((unsigned char *) (&k))[1]);
567bcd5c59fSHannes Reinecke 				atp_writeb_io(dev, c, 0x14,
568bcd5c59fSHannes Reinecke 					      ((unsigned char *) (&k))[0]);
5691da177e4SLinus Torvalds 				dev->id[c][target_id].dirct = 0x00;
5701da177e4SLinus Torvalds 			} else {
5711da177e4SLinus Torvalds 				dev->id[c][target_id].dirct = 0x00;
5721da177e4SLinus Torvalds 			}
5736a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x18, 0x08);
5746a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 0, 0x09);
5751da177e4SLinus Torvalds 			dev->in_int[c] = 0;
57678614ecdSOndrej Zary 			return IRQ_HANDLED;
5771da177e4SLinus Torvalds 		}
5781da177e4SLinus Torvalds 		if (i == 0x08) {
5796a3cebb6SOndrej Zary 			atp_writel_pci(dev, c, 4, dev->id[c][target_id].prdaddr);
5806a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 2, 0x06);
5816a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 2, 0x00);
5826a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x10, 0x41);
583b922a449SOndrej Zary 			if (is885(dev)) {
5841da177e4SLinus Torvalds 				k = dev->id[c][target_id].last_len;
585bcd5c59fSHannes Reinecke 				atp_writeb_io(dev, c, 0x12,
586bcd5c59fSHannes Reinecke 					      ((unsigned char *) (&k))[2]);
587bcd5c59fSHannes Reinecke 				atp_writeb_io(dev, c, 0x13,
588bcd5c59fSHannes Reinecke 					      ((unsigned char *) (&k))[1]);
589bcd5c59fSHannes Reinecke 				atp_writeb_io(dev, c, 0x14,
590bcd5c59fSHannes Reinecke 					      ((unsigned char *) (&k))[0]);
5911da177e4SLinus Torvalds 			}
592bcd5c59fSHannes Reinecke 			atp_writeb_io(dev, c, 0x15,
593bcd5c59fSHannes Reinecke 				      atp_readb_io(dev, c, 0x15) | 0x20);
5941da177e4SLinus Torvalds 			dev->id[c][target_id].dirct = 0x20;
5956a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x18, 0x08);
5966a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 0, 0x01);
5971da177e4SLinus Torvalds 			dev->in_int[c] = 0;
59878614ecdSOndrej Zary 			return IRQ_HANDLED;
5991da177e4SLinus Torvalds 		}
6006a3cebb6SOndrej Zary 		if (i == 0x0a)
6016a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x10, 0x30);
6026a3cebb6SOndrej Zary 		else
6036a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x10, 0x46);
6041da177e4SLinus Torvalds 		dev->id[c][target_id].dirct = 0x00;
6056a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0x00);
6066a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x13, 0x00);
6076a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x00);
6086a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
6091da177e4SLinus Torvalds 	}
61078614ecdSOndrej Zary 	dev->in_int[c] = 0;
6111da177e4SLinus Torvalds 
6121da177e4SLinus Torvalds 	return IRQ_HANDLED;
6131da177e4SLinus Torvalds }
6141da177e4SLinus Torvalds /**
6156b71f60cSLee Jones  *	atp870u_queuecommand_lck -	Queue SCSI command
6161da177e4SLinus Torvalds  *	@req_p: request block
6171da177e4SLinus Torvalds  *
6181da177e4SLinus Torvalds  *	Queue a command to the ATP queue. Called with the host lock held.
6191da177e4SLinus Torvalds  */
atp870u_queuecommand_lck(struct scsi_cmnd * req_p)620af049dfdSBart Van Assche static int atp870u_queuecommand_lck(struct scsi_cmnd *req_p)
6211da177e4SLinus Torvalds {
622af049dfdSBart Van Assche 	void (*done)(struct scsi_cmnd *) = scsi_done;
6231da177e4SLinus Torvalds 	unsigned char c;
6243b836464SOndrej Zary 	unsigned int m;
6251da177e4SLinus Torvalds 	struct atp_unit *dev;
6261da177e4SLinus Torvalds 	struct Scsi_Host *host;
6271da177e4SLinus Torvalds 
628422c0d61SJeff Garzik 	c = scmd_channel(req_p);
6291da177e4SLinus Torvalds 	req_p->sense_buffer[0]=0;
630fe7ed98fSBoaz Harrosh 	scsi_set_resid(req_p, 0);
631422c0d61SJeff Garzik 	if (scmd_channel(req_p) > 1) {
632f3272258SHannes Reinecke 		req_p->result = DID_BAD_TARGET << 16;
6331da177e4SLinus Torvalds 		done(req_p);
6341da177e4SLinus Torvalds #ifdef ED_DBGP
6351da177e4SLinus Torvalds 		printk("atp870u_queuecommand : req_p->device->channel > 1\n");
6361da177e4SLinus Torvalds #endif
6371da177e4SLinus Torvalds 		return 0;
6381da177e4SLinus Torvalds 	}
6391da177e4SLinus Torvalds 
6401da177e4SLinus Torvalds 	host = req_p->device->host;
6411da177e4SLinus Torvalds 	dev = (struct atp_unit *)&host->hostdata;
6421da177e4SLinus Torvalds 
6431da177e4SLinus Torvalds 	m = 1;
644422c0d61SJeff Garzik 	m = m << scmd_id(req_p);
6451da177e4SLinus Torvalds 
6461da177e4SLinus Torvalds 	/*
6471da177e4SLinus Torvalds 	 *      Fake a timeout for missing targets
6481da177e4SLinus Torvalds 	 */
6491da177e4SLinus Torvalds 
6501da177e4SLinus Torvalds 	if ((m & dev->active_id[c]) == 0) {
651f3272258SHannes Reinecke 		req_p->result = DID_BAD_TARGET << 16;
6521da177e4SLinus Torvalds 		done(req_p);
6531da177e4SLinus Torvalds 		return 0;
6541da177e4SLinus Torvalds 	}
6551da177e4SLinus Torvalds 
6561da177e4SLinus Torvalds 	/*
6571da177e4SLinus Torvalds 	 *	Count new command
6581da177e4SLinus Torvalds 	 */
6591da177e4SLinus Torvalds 	dev->quend[c]++;
6601da177e4SLinus Torvalds 	if (dev->quend[c] >= qcnt) {
6611da177e4SLinus Torvalds 		dev->quend[c] = 0;
6621da177e4SLinus Torvalds 	}
6631da177e4SLinus Torvalds 
6641da177e4SLinus Torvalds 	/*
6651da177e4SLinus Torvalds 	 *	Check queue state
6661da177e4SLinus Torvalds 	 */
6671da177e4SLinus Torvalds 	if (dev->quhd[c] == dev->quend[c]) {
6681da177e4SLinus Torvalds 		if (dev->quend[c] == 0) {
6691da177e4SLinus Torvalds 			dev->quend[c] = qcnt;
6701da177e4SLinus Torvalds 		}
6711da177e4SLinus Torvalds #ifdef ED_DBGP
6721da177e4SLinus Torvalds 		printk("atp870u_queuecommand : dev->quhd[c] == dev->quend[c]\n");
6731da177e4SLinus Torvalds #endif
6741da177e4SLinus Torvalds 		dev->quend[c]--;
675f3272258SHannes Reinecke 		req_p->result = DID_BUS_BUSY << 16;
6761da177e4SLinus Torvalds 		done(req_p);
6771da177e4SLinus Torvalds 		return 0;
6781da177e4SLinus Torvalds 	}
6791da177e4SLinus Torvalds 	dev->quereq[c][dev->quend[c]] = req_p;
6801da177e4SLinus Torvalds #ifdef ED_DBGP
681bcd5c59fSHannes Reinecke 	printk("dev->ioport[c] = %x atp_readb_io(dev, c, 0x1c) = %x "
682bcd5c59fSHannes Reinecke 	       "dev->in_int[%d] = %d dev->in_snd[%d] = %d\n",
683bcd5c59fSHannes Reinecke 	       dev->ioport[c], atp_readb_io(dev, c, 0x1c), c,
684bcd5c59fSHannes Reinecke 	       dev->in_int[c],c,dev->in_snd[c]);
6851da177e4SLinus Torvalds #endif
686bcd5c59fSHannes Reinecke 	if ((atp_readb_io(dev, c, 0x1c) == 0) &&
687bcd5c59fSHannes Reinecke 	    (dev->in_int[c] == 0) &&
688bcd5c59fSHannes Reinecke 	    (dev->in_snd[c] == 0)) {
6891da177e4SLinus Torvalds #ifdef ED_DBGP
6901da177e4SLinus Torvalds 		printk("Call sent_s870(atp870u_queuecommand)\n");
6911da177e4SLinus Torvalds #endif
6921da177e4SLinus Torvalds 		send_s870(dev,c);
6931da177e4SLinus Torvalds 	}
6941da177e4SLinus Torvalds #ifdef ED_DBGP
6951da177e4SLinus Torvalds 	printk("atp870u_queuecommand : exit\n");
6961da177e4SLinus Torvalds #endif
6971da177e4SLinus Torvalds 	return 0;
6981da177e4SLinus Torvalds }
6991da177e4SLinus Torvalds 
DEF_SCSI_QCMD(atp870u_queuecommand)700f281233dSJeff Garzik static DEF_SCSI_QCMD(atp870u_queuecommand)
701f281233dSJeff Garzik 
7026b71f60cSLee Jones /*
7031da177e4SLinus Torvalds  *	send_s870	-	send a command to the controller
7041da177e4SLinus Torvalds  *
7051da177e4SLinus Torvalds  *	On entry there is work queued to be done. We move some of that work to the
7061da177e4SLinus Torvalds  *	controller itself.
7071da177e4SLinus Torvalds  *
7081da177e4SLinus Torvalds  *	Caller holds the host lock.
7091da177e4SLinus Torvalds  */
7101da177e4SLinus Torvalds static void send_s870(struct atp_unit *dev, unsigned char c)
7111da177e4SLinus Torvalds {
712468b8968SOndrej Zary 	struct scsi_cmnd *workreq = NULL;
7131da177e4SLinus Torvalds 	unsigned int i;//,k;
7141da177e4SLinus Torvalds 	unsigned char  j, target_id;
7151da177e4SLinus Torvalds 	unsigned char *prd;
716c2bab403SOndrej Zary 	unsigned short int w;
7171da177e4SLinus Torvalds 	unsigned long l, bttl = 0;
7181da177e4SLinus Torvalds 	unsigned long  sg_count;
7191da177e4SLinus Torvalds 
7201da177e4SLinus Torvalds 	if (dev->in_snd[c] != 0) {
7211da177e4SLinus Torvalds #ifdef ED_DBGP
7221da177e4SLinus Torvalds 		printk("cmnd in_snd\n");
7231da177e4SLinus Torvalds #endif
7241da177e4SLinus Torvalds 		return;
7251da177e4SLinus Torvalds 	}
7261da177e4SLinus Torvalds #ifdef ED_DBGP
7271da177e4SLinus Torvalds 	printk("Sent_s870 enter\n");
7281da177e4SLinus Torvalds #endif
7291da177e4SLinus Torvalds 	dev->in_snd[c] = 1;
7301da177e4SLinus Torvalds 	if ((dev->last_cmd[c] != 0xff) && ((dev->last_cmd[c] & 0x40) != 0)) {
7311da177e4SLinus Torvalds 		dev->last_cmd[c] &= 0x0f;
7321da177e4SLinus Torvalds 		workreq = dev->id[c][dev->last_cmd[c]].curr_req;
733468b8968SOndrej Zary 		if (!workreq) {
7341da177e4SLinus Torvalds 			dev->last_cmd[c] = 0xff;
7351da177e4SLinus Torvalds 			if (dev->quhd[c] == dev->quend[c]) {
7361da177e4SLinus Torvalds 				dev->in_snd[c] = 0;
7371da177e4SLinus Torvalds 				return;
7381da177e4SLinus Torvalds 			}
7391da177e4SLinus Torvalds 		}
740468b8968SOndrej Zary 	}
741468b8968SOndrej Zary 	if (!workreq) {
7421da177e4SLinus Torvalds 		if ((dev->last_cmd[c] != 0xff) && (dev->working[c] != 0)) {
7431da177e4SLinus Torvalds 			dev->in_snd[c] = 0;
7441da177e4SLinus Torvalds 			return;
7451da177e4SLinus Torvalds 		}
7461da177e4SLinus Torvalds 		dev->working[c]++;
7471da177e4SLinus Torvalds 		j = dev->quhd[c];
7481da177e4SLinus Torvalds 		dev->quhd[c]++;
749468b8968SOndrej Zary 		if (dev->quhd[c] >= qcnt)
7501da177e4SLinus Torvalds 			dev->quhd[c] = 0;
7511da177e4SLinus Torvalds 		workreq = dev->quereq[c][dev->quhd[c]];
752468b8968SOndrej Zary 		if (dev->id[c][scmd_id(workreq)].curr_req != NULL) {
7531da177e4SLinus Torvalds 			dev->quhd[c] = j;
7541da177e4SLinus Torvalds 			dev->working[c]--;
7551da177e4SLinus Torvalds 			dev->in_snd[c] = 0;
7561da177e4SLinus Torvalds 			return;
7571da177e4SLinus Torvalds 		}
758468b8968SOndrej Zary 		dev->id[c][scmd_id(workreq)].curr_req = workreq;
759468b8968SOndrej Zary 		dev->last_cmd[c] = scmd_id(workreq);
7601da177e4SLinus Torvalds 	}
761bcd5c59fSHannes Reinecke 	if ((atp_readb_io(dev, c, 0x1f) & 0xb0) != 0 ||
762bcd5c59fSHannes Reinecke 	    atp_readb_io(dev, c, 0x1c) != 0) {
7631da177e4SLinus Torvalds #ifdef ED_DBGP
7641da177e4SLinus Torvalds 		printk("Abort to Send\n");
7651da177e4SLinus Torvalds #endif
7661da177e4SLinus Torvalds 		dev->last_cmd[c] |= 0x40;
7671da177e4SLinus Torvalds 		dev->in_snd[c] = 0;
7681da177e4SLinus Torvalds 		return;
769468b8968SOndrej Zary 	}
7701da177e4SLinus Torvalds #ifdef ED_DBGP
7711da177e4SLinus Torvalds 	printk("OK to Send\n");
772422c0d61SJeff Garzik 	scmd_printk(KERN_DEBUG, workreq, "CDB");
7731da177e4SLinus Torvalds 	for(i=0;i<workreq->cmd_len;i++) {
7741da177e4SLinus Torvalds 		printk(" %x",workreq->cmnd[i]);
7751da177e4SLinus Torvalds 	}
776422c0d61SJeff Garzik 	printk("\n");
7771da177e4SLinus Torvalds #endif
778fe7ed98fSBoaz Harrosh 	l = scsi_bufflen(workreq);
779fe7ed98fSBoaz Harrosh 
780b922a449SOndrej Zary 	if (is885(dev)) {
7816a3cebb6SOndrej Zary 		j = atp_readb_base(dev, 0x29) & 0xfe;
7826a3cebb6SOndrej Zary 		atp_writeb_base(dev, 0x29, j);
783422c0d61SJeff Garzik 		dev->r1f[c][scmd_id(workreq)] = 0;
7841da177e4SLinus Torvalds 	}
7851da177e4SLinus Torvalds 
7861da177e4SLinus Torvalds 	if (workreq->cmnd[0] == READ_CAPACITY) {
787fe7ed98fSBoaz Harrosh 		if (l > 8)
788fe7ed98fSBoaz Harrosh 			l = 8;
7891da177e4SLinus Torvalds 	}
790f3272258SHannes Reinecke 	if (workreq->cmnd[0] == TEST_UNIT_READY) {
791fe7ed98fSBoaz Harrosh 		l = 0;
7921da177e4SLinus Torvalds 	}
7931da177e4SLinus Torvalds 
7941da177e4SLinus Torvalds 	j = 0;
795422c0d61SJeff Garzik 	target_id = scmd_id(workreq);
7961da177e4SLinus Torvalds 
7971da177e4SLinus Torvalds 	/*
7981da177e4SLinus Torvalds 	 *	Wide ?
7991da177e4SLinus Torvalds 	 */
8001da177e4SLinus Torvalds 	w = 1;
8011da177e4SLinus Torvalds 	w = w << target_id;
8021da177e4SLinus Torvalds 	if ((w & dev->wide_id[c]) != 0) {
8031da177e4SLinus Torvalds 		j |= 0x01;
8041da177e4SLinus Torvalds 	}
8056a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x1b, j);
8066a3cebb6SOndrej Zary 	while ((atp_readb_io(dev, c, 0x1b) & 0x01) != j) {
8076a3cebb6SOndrej Zary 		atp_writeb_pci(dev, c, 0x1b, j);
8081da177e4SLinus Torvalds #ifdef ED_DBGP
8091da177e4SLinus Torvalds 		printk("send_s870 while loop 1\n");
8101da177e4SLinus Torvalds #endif
8111da177e4SLinus Torvalds 	}
8121da177e4SLinus Torvalds 	/*
8131da177e4SLinus Torvalds 	 *	Write the command
8141da177e4SLinus Torvalds 	 */
8151da177e4SLinus Torvalds 
8166a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x00, workreq->cmd_len);
8176a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x01, 0x2c);
818b922a449SOndrej Zary 	if (is885(dev))
8196a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x02, 0x7f);
8206a3cebb6SOndrej Zary 	else
8216a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x02, 0xcf);
8226a3cebb6SOndrej Zary 	for (i = 0; i < workreq->cmd_len; i++)
8236a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x03 + i, workreq->cmnd[i]);
8246a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x0f, workreq->device->lun);
8251da177e4SLinus Torvalds 	/*
8261da177e4SLinus Torvalds 	 *	Write the target
8271da177e4SLinus Torvalds 	 */
8286a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x11, dev->id[c][target_id].devsp);
8291da177e4SLinus Torvalds #ifdef ED_DBGP
830bcd5c59fSHannes Reinecke 	printk("dev->id[%d][%d].devsp = %2x\n",c,target_id,
831bcd5c59fSHannes Reinecke 	       dev->id[c][target_id].devsp);
8321da177e4SLinus Torvalds #endif
8331da177e4SLinus Torvalds 
834fe7ed98fSBoaz Harrosh 	sg_count = scsi_dma_map(workreq);
8351da177e4SLinus Torvalds 	/*
8361da177e4SLinus Torvalds 	 *	Write transfer size
8371da177e4SLinus Torvalds 	 */
8386a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x12, ((unsigned char *) (&l))[2]);
8396a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x13, ((unsigned char *) (&l))[1]);
8406a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x14, ((unsigned char *) (&l))[0]);
8411da177e4SLinus Torvalds 	j = target_id;
8421da177e4SLinus Torvalds 	dev->id[c][j].last_len = l;
8431da177e4SLinus Torvalds 	dev->id[c][j].tran_len = 0;
8441da177e4SLinus Torvalds #ifdef ED_DBGP
8451da177e4SLinus Torvalds 	printk("dev->id[%2d][%2d].last_len = %d\n",c,j,dev->id[c][j].last_len);
8461da177e4SLinus Torvalds #endif
8471da177e4SLinus Torvalds 	/*
8481da177e4SLinus Torvalds 	 *	Flip the wide bits
8491da177e4SLinus Torvalds 	 */
8501da177e4SLinus Torvalds 	if ((j & 0x08) != 0) {
8511da177e4SLinus Torvalds 		j = (j & 0x07) | 0x40;
8521da177e4SLinus Torvalds 	}
8531da177e4SLinus Torvalds 	/*
8541da177e4SLinus Torvalds 	 *	Check transfer direction
8551da177e4SLinus Torvalds 	 */
8566a3cebb6SOndrej Zary 	if (workreq->sc_data_direction == DMA_TO_DEVICE)
8576a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x15, j | 0x20);
8586a3cebb6SOndrej Zary 	else
8596a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x15, j);
8606a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x16, atp_readb_io(dev, c, 0x16) | 0x80);
8616a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x16, 0x80);
8621da177e4SLinus Torvalds 	dev->id[c][target_id].dirct = 0;
8631da177e4SLinus Torvalds 	if (l == 0) {
8646a3cebb6SOndrej Zary 		if (atp_readb_io(dev, c, 0x1c) == 0) {
8651da177e4SLinus Torvalds #ifdef ED_DBGP
8661da177e4SLinus Torvalds 			printk("change SCSI_CMD_REG 0x08\n");
8671da177e4SLinus Torvalds #endif
8686a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x18, 0x08);
8696a3cebb6SOndrej Zary 		} else
8701da177e4SLinus Torvalds 			dev->last_cmd[c] |= 0x40;
8711da177e4SLinus Torvalds 		dev->in_snd[c] = 0;
8721da177e4SLinus Torvalds 		return;
8731da177e4SLinus Torvalds 	}
8741da177e4SLinus Torvalds 	prd = dev->id[c][target_id].prd_table;
8751da177e4SLinus Torvalds 	dev->id[c][target_id].prd_pos = prd;
8761da177e4SLinus Torvalds 
8771da177e4SLinus Torvalds 	/*
8781da177e4SLinus Torvalds 	 *	Now write the request list. Either as scatter/gather or as
8791da177e4SLinus Torvalds 	 *	a linear chain.
8801da177e4SLinus Torvalds 	 */
8811da177e4SLinus Torvalds 
882fe7ed98fSBoaz Harrosh 	if (l) {
883fe7ed98fSBoaz Harrosh 		struct scatterlist *sgpnt;
8841da177e4SLinus Torvalds 		i = 0;
885fe7ed98fSBoaz Harrosh 		scsi_for_each_sg(workreq, sgpnt, sg_count, j) {
886fe7ed98fSBoaz Harrosh 			bttl = sg_dma_address(sgpnt);
887fe7ed98fSBoaz Harrosh 			l=sg_dma_len(sgpnt);
8881da177e4SLinus Torvalds #ifdef ED_DBGP
8891da177e4SLinus Torvalds 			printk("1. bttl %x, l %x\n",bttl, l);
8901da177e4SLinus Torvalds #endif
8911da177e4SLinus Torvalds 			while (l > 0x10000) {
8921da177e4SLinus Torvalds 				(((u16 *) (prd))[i + 3]) = 0x0000;
8931da177e4SLinus Torvalds 				(((u16 *) (prd))[i + 2]) = 0x0000;
8941da177e4SLinus Torvalds 				(((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
8951da177e4SLinus Torvalds 				l -= 0x10000;
8961da177e4SLinus Torvalds 				bttl += 0x10000;
8971da177e4SLinus Torvalds 				i += 0x04;
8981da177e4SLinus Torvalds 			}
8991da177e4SLinus Torvalds 			(((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
9001da177e4SLinus Torvalds 			(((u16 *) (prd))[i + 2]) = cpu_to_le16(l);
9011da177e4SLinus Torvalds 			(((u16 *) (prd))[i + 3]) = 0;
9021da177e4SLinus Torvalds 			i += 0x04;
9031da177e4SLinus Torvalds 		}
9041da177e4SLinus Torvalds 		(((u16 *) (prd))[i - 1]) = cpu_to_le16(0x8000);
9051da177e4SLinus Torvalds #ifdef ED_DBGP
906bcd5c59fSHannes Reinecke 		printk("prd %4x %4x %4x %4x\n",
907bcd5c59fSHannes Reinecke 		       (((unsigned short int *)prd)[0]),
908bcd5c59fSHannes Reinecke 		       (((unsigned short int *)prd)[1]),
909bcd5c59fSHannes Reinecke 		       (((unsigned short int *)prd)[2]),
910bcd5c59fSHannes Reinecke 		       (((unsigned short int *)prd)[3]));
9111da177e4SLinus Torvalds 		printk("2. bttl %x, l %x\n",bttl, l);
9121da177e4SLinus Torvalds #endif
9131da177e4SLinus Torvalds 	}
9141da177e4SLinus Torvalds #ifdef ED_DBGP
915bcd5c59fSHannes Reinecke 	printk("send_s870: prdaddr_2 0x%8x target_id %d\n",
916bcd5c59fSHannes Reinecke 	       dev->id[c][target_id].prdaddr,target_id);
9171da177e4SLinus Torvalds #endif
918b5683557SJames Bottomley 	dev->id[c][target_id].prdaddr = dev->id[c][target_id].prd_bus;
9196a3cebb6SOndrej Zary 	atp_writel_pci(dev, c, 4, dev->id[c][target_id].prdaddr);
9206a3cebb6SOndrej Zary 	atp_writeb_pci(dev, c, 2, 0x06);
9216a3cebb6SOndrej Zary 	atp_writeb_pci(dev, c, 2, 0x00);
922b922a449SOndrej Zary 	if (is885(dev)) {
9236a3cebb6SOndrej Zary 		j = atp_readb_pci(dev, c, 1) & 0xf3;
924f3272258SHannes Reinecke 		if ((workreq->cmnd[0] == READ_6) ||
925f3272258SHannes Reinecke 		    (workreq->cmnd[0] == READ_10) ||
926f3272258SHannes Reinecke 		    (workreq->cmnd[0] == WRITE_6) ||
927f3272258SHannes Reinecke 		    (workreq->cmnd[0] == WRITE_10)) {
9281da177e4SLinus Torvalds 			j |= 0x0c;
9291da177e4SLinus Torvalds 		}
9306a3cebb6SOndrej Zary 		atp_writeb_pci(dev, c, 1, j);
931b922a449SOndrej Zary 	} else if (is880(dev)) {
932f3272258SHannes Reinecke 		if ((workreq->cmnd[0] == READ_6) ||
933f3272258SHannes Reinecke 		    (workreq->cmnd[0] == READ_10) ||
934f3272258SHannes Reinecke 		    (workreq->cmnd[0] == WRITE_6) ||
935f3272258SHannes Reinecke 		    (workreq->cmnd[0] == WRITE_10))
936bcd5c59fSHannes Reinecke 			atp_writeb_base(dev, 0x3b,
937bcd5c59fSHannes Reinecke 					(atp_readb_base(dev, 0x3b) & 0x3f) | 0xc0);
9386a3cebb6SOndrej Zary 		else
939bcd5c59fSHannes Reinecke 			atp_writeb_base(dev, 0x3b,
940bcd5c59fSHannes Reinecke 					atp_readb_base(dev, 0x3b) & 0x3f);
9411da177e4SLinus Torvalds 	} else {
942f3272258SHannes Reinecke 		if ((workreq->cmnd[0] == READ_6) ||
943f3272258SHannes Reinecke 		    (workreq->cmnd[0] == READ_10) ||
944f3272258SHannes Reinecke 		    (workreq->cmnd[0] == WRITE_6) ||
945f3272258SHannes Reinecke 		    (workreq->cmnd[0] == WRITE_10))
946bcd5c59fSHannes Reinecke 			atp_writeb_base(dev, 0x3a,
947bcd5c59fSHannes Reinecke 					(atp_readb_base(dev, 0x3a) & 0xf3) | 0x08);
9486a3cebb6SOndrej Zary 		else
949bcd5c59fSHannes Reinecke 			atp_writeb_base(dev, 0x3a,
950bcd5c59fSHannes Reinecke 					atp_readb_base(dev, 0x3a) & 0xf3);
9511da177e4SLinus Torvalds 	}
9521da177e4SLinus Torvalds 
9531da177e4SLinus Torvalds 	if(workreq->sc_data_direction == DMA_TO_DEVICE) {
9541da177e4SLinus Torvalds 		dev->id[c][target_id].dirct = 0x20;
9556a3cebb6SOndrej Zary 		if (atp_readb_io(dev, c, 0x1c) == 0) {
9566a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x18, 0x08);
9576a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 0, 0x01);
9581da177e4SLinus Torvalds #ifdef ED_DBGP
9591da177e4SLinus Torvalds 		printk( "start DMA(to target)\n");
9601da177e4SLinus Torvalds #endif
9611da177e4SLinus Torvalds 		} else {
9621da177e4SLinus Torvalds 			dev->last_cmd[c] |= 0x40;
9631da177e4SLinus Torvalds 		}
9641da177e4SLinus Torvalds 		dev->in_snd[c] = 0;
9651da177e4SLinus Torvalds 		return;
9661da177e4SLinus Torvalds 	}
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, 0x09);
9701da177e4SLinus Torvalds #ifdef ED_DBGP
9711da177e4SLinus Torvalds 		printk( "start DMA(to host)\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 
9791da177e4SLinus Torvalds }
9801da177e4SLinus Torvalds 
fun_scam(struct atp_unit * dev,unsigned short int * val)9811da177e4SLinus Torvalds static unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val)
9821da177e4SLinus Torvalds {
9831da177e4SLinus Torvalds 	unsigned short int i, k;
9841da177e4SLinus Torvalds 	unsigned char j;
9851da177e4SLinus Torvalds 
9866a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, *val);
9871da177e4SLinus Torvalds 	for (i = 0; i < 10; i++) {	/* stable >= bus settle delay(400 ns)  */
9886a3cebb6SOndrej Zary 		k = atp_readw_io(dev, 0, 0x1c);
9891da177e4SLinus Torvalds 		j = (unsigned char) (k >> 8);
990832e9ac6SOndrej Zary 		if ((k & 0x8000) != 0)	/* DB7 all release?    */
991832e9ac6SOndrej Zary 			i = 0;
9921da177e4SLinus Torvalds 	}
9931da177e4SLinus Torvalds 	*val |= 0x4000;		/* assert DB6           */
9946a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, *val);
9951da177e4SLinus Torvalds 	*val &= 0xdfff;		/* assert DB5           */
9966a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, *val);
9971da177e4SLinus Torvalds 	for (i = 0; i < 10; i++) {	/* stable >= bus settle delay(400 ns) */
9986a3cebb6SOndrej Zary 		if ((atp_readw_io(dev, 0, 0x1c) & 0x2000) != 0)	/* DB5 all release?       */
999832e9ac6SOndrej Zary 			i = 0;
10001da177e4SLinus Torvalds 	}
10011da177e4SLinus Torvalds 	*val |= 0x8000;		/* no DB4-0, assert DB7    */
10021da177e4SLinus Torvalds 	*val &= 0xe0ff;
10036a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, *val);
10041da177e4SLinus Torvalds 	*val &= 0xbfff;		/* release DB6             */
10056a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, *val);
10061da177e4SLinus Torvalds 	for (i = 0; i < 10; i++) {	/* stable >= bus settle delay(400 ns)  */
10076a3cebb6SOndrej Zary 		if ((atp_readw_io(dev, 0, 0x1c) & 0x4000) != 0)	/* DB6 all release?  */
1008832e9ac6SOndrej Zary 			i = 0;
10091da177e4SLinus Torvalds 	}
10101da177e4SLinus Torvalds 
10111da177e4SLinus Torvalds 	return j;
10121da177e4SLinus Torvalds }
10131da177e4SLinus Torvalds 
tscam(struct Scsi_Host * host,bool wide_chip,u8 scam_on)10148177c507SOndrej Zary static void tscam(struct Scsi_Host *host, bool wide_chip, u8 scam_on)
10151da177e4SLinus Torvalds {
10161da177e4SLinus Torvalds 
10171da177e4SLinus Torvalds 	unsigned char i, j, k;
10181da177e4SLinus Torvalds 	unsigned long n;
10191da177e4SLinus Torvalds 	unsigned short int m, assignid_map, val;
10201da177e4SLinus Torvalds 	unsigned char mbuf[33], quintet[2];
10211da177e4SLinus Torvalds 	struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
10221da177e4SLinus Torvalds 	static unsigned char g2q_tab[8] = {
10231da177e4SLinus Torvalds 		0x38, 0x31, 0x32, 0x2b, 0x34, 0x2d, 0x2e, 0x27
10241da177e4SLinus Torvalds 	};
10251da177e4SLinus Torvalds 
10261da177e4SLinus Torvalds /*  I can't believe we need this before we've even done anything.  Remove it
10271da177e4SLinus Torvalds  *  and see if anyone bitches.
10281da177e4SLinus Torvalds 	for (i = 0; i < 0x10; i++) {
10291da177e4SLinus Torvalds 		udelay(0xffff);
10301da177e4SLinus Torvalds 	}
10311da177e4SLinus Torvalds  */
10321da177e4SLinus Torvalds 
10336a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 1, 0x08);
10346a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 2, 0x7f);
10356a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x11, 0x20);
10361da177e4SLinus Torvalds 
10378177c507SOndrej Zary 	if ((scam_on & 0x40) == 0) {
10381da177e4SLinus Torvalds 		return;
10391da177e4SLinus Torvalds 	}
10401da177e4SLinus Torvalds 	m = 1;
10411da177e4SLinus Torvalds 	m <<= dev->host_id[0];
10421da177e4SLinus Torvalds 	j = 16;
1043dd5a5f79SOndrej Zary 	if (!wide_chip) {
10441da177e4SLinus Torvalds 		m |= 0xff00;
10451da177e4SLinus Torvalds 		j = 8;
10461da177e4SLinus Torvalds 	}
10471da177e4SLinus Torvalds 	assignid_map = m;
10486a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x02, 0x02);	/* 2*2=4ms,3EH 2/32*3E=3.9ms */
10496a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x03, 0);
10506a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x04, 0);
10516a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x05, 0);
10526a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x06, 0);
10536a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x07, 0);
10546a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x08, 0);
10551da177e4SLinus Torvalds 
10561da177e4SLinus Torvalds 	for (i = 0; i < j; i++) {
10571da177e4SLinus Torvalds 		m = 1;
10581da177e4SLinus Torvalds 		m = m << i;
10591da177e4SLinus Torvalds 		if ((m & assignid_map) != 0) {
10601da177e4SLinus Torvalds 			continue;
10611da177e4SLinus Torvalds 		}
10626a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x0f, 0);
10636a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x12, 0);
10646a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x13, 0);
10656a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x14, 0);
10661da177e4SLinus Torvalds 		if (i > 7) {
10671da177e4SLinus Torvalds 			k = (i & 0x07) | 0x40;
10681da177e4SLinus Torvalds 		} else {
10691da177e4SLinus Torvalds 			k = i;
10701da177e4SLinus Torvalds 		}
10716a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x15, k);
1072dd5a5f79SOndrej Zary 		if (wide_chip)
10736a3cebb6SOndrej Zary 			atp_writeb_io(dev, 0, 0x1b, 0x01);
10746a3cebb6SOndrej Zary 		else
10756a3cebb6SOndrej Zary 			atp_writeb_io(dev, 0, 0x1b, 0x00);
107658c4d046SOndrej Zary 		do {
10776a3cebb6SOndrej Zary 			atp_writeb_io(dev, 0, 0x18, 0x09);
10781da177e4SLinus Torvalds 
10796a3cebb6SOndrej Zary 			while ((atp_readb_io(dev, 0, 0x1f) & 0x80) == 0x00)
10801da177e4SLinus Torvalds 				cpu_relax();
10816a3cebb6SOndrej Zary 			k = atp_readb_io(dev, 0, 0x17);
108258c4d046SOndrej Zary 			if ((k == 0x85) || (k == 0x42))
108358c4d046SOndrej Zary 				break;
108458c4d046SOndrej Zary 			if (k != 0x16)
10856a3cebb6SOndrej Zary 				atp_writeb_io(dev, 0, 0x10, 0x41);
108658c4d046SOndrej Zary 		} while (k != 0x16);
108758c4d046SOndrej Zary 		if ((k == 0x85) || (k == 0x42))
108858c4d046SOndrej Zary 			continue;
10891da177e4SLinus Torvalds 		assignid_map |= m;
10901da177e4SLinus Torvalds 
10911da177e4SLinus Torvalds 	}
10926a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x02, 0x7f);
10936a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x1b, 0x02);
10941da177e4SLinus Torvalds 
10952bbbac45SOndrej Zary 	udelay(2);
10961da177e4SLinus Torvalds 
10971da177e4SLinus Torvalds 	val = 0x0080;		/* bsy  */
10986a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, val);
10991da177e4SLinus Torvalds 	val |= 0x0040;		/* sel  */
11006a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, val);
11011da177e4SLinus Torvalds 	val |= 0x0004;		/* msg  */
11026a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, val);
11032bbbac45SOndrej Zary 	udelay(2);		/* 2 deskew delay(45ns*2=90ns) */
11041da177e4SLinus Torvalds 	val &= 0x007f;		/* no bsy  */
11056a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, val);
1106dcaa0c12SJia-Ju Bai 	msleep(128);
11071da177e4SLinus Torvalds 	val &= 0x00fb;		/* after 1ms no msg */
11086a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, val);
11096a3cebb6SOndrej Zary 	while ((atp_readb_io(dev, 0, 0x1c) & 0x04) != 0)
111058c4d046SOndrej Zary 		;
11112bbbac45SOndrej Zary 	udelay(2);
11121da177e4SLinus Torvalds 	udelay(100);
1113c7fcc089SOndrej Zary 	for (n = 0; n < 0x30000; n++)
11146a3cebb6SOndrej Zary 		if ((atp_readb_io(dev, 0, 0x1c) & 0x80) != 0)	/* bsy ? */
1115c7fcc089SOndrej Zary 			break;
1116c7fcc089SOndrej Zary 	if (n < 0x30000)
1117c7fcc089SOndrej Zary 		for (n = 0; n < 0x30000; n++)
11186a3cebb6SOndrej Zary 			if ((atp_readb_io(dev, 0, 0x1c) & 0x81) == 0x0081) {
11192bbbac45SOndrej Zary 				udelay(2);
11201da177e4SLinus Torvalds 				val |= 0x8003;		/* io,cd,db7  */
11216a3cebb6SOndrej Zary 				atp_writew_io(dev, 0, 0x1c, val);
11222bbbac45SOndrej Zary 				udelay(2);
11231da177e4SLinus Torvalds 				val &= 0x00bf;		/* no sel     */
11246a3cebb6SOndrej Zary 				atp_writew_io(dev, 0, 0x1c, val);
11252bbbac45SOndrej Zary 				udelay(2);
1126c7fcc089SOndrej Zary 				break;
1127c7fcc089SOndrej Zary 			}
1128c7fcc089SOndrej Zary 	while (1) {
11290f6d93aaSMartin Michlmayr 	/*
11300f6d93aaSMartin Michlmayr 	 * The funny division into multiple delays is to accomodate
11310f6d93aaSMartin Michlmayr 	 * arches like ARM where udelay() multiplies its argument by
11320f6d93aaSMartin Michlmayr 	 * a large number to initialize a loop counter.  To avoid
11330f6d93aaSMartin Michlmayr 	 * overflow, the maximum supported udelay is 2000 microseconds.
11340f6d93aaSMartin Michlmayr 	 *
11350f6d93aaSMartin Michlmayr 	 * XXX it would be more polite to find a way to use msleep()
11360f6d93aaSMartin Michlmayr 	 */
11370f6d93aaSMartin Michlmayr 	mdelay(2);
11380f6d93aaSMartin Michlmayr 	udelay(48);
11396a3cebb6SOndrej Zary 	if ((atp_readb_io(dev, 0, 0x1c) & 0x80) == 0x00) {	/* bsy ? */
11406a3cebb6SOndrej Zary 		atp_writew_io(dev, 0, 0x1c, 0);
11416a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x1b, 0);
11426a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x15, 0);
11436a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x18, 0x09);
11446a3cebb6SOndrej Zary 		while ((atp_readb_io(dev, 0, 0x1f) & 0x80) == 0)
11451da177e4SLinus Torvalds 			cpu_relax();
11466a3cebb6SOndrej Zary 		atp_readb_io(dev, 0, 0x17);
11471da177e4SLinus Torvalds 		return;
11481da177e4SLinus Torvalds 	}
11491da177e4SLinus Torvalds 	val &= 0x00ff;		/* synchronization  */
11501da177e4SLinus Torvalds 	val |= 0x3f00;
11511da177e4SLinus Torvalds 	fun_scam(dev, &val);
11522bbbac45SOndrej Zary 	udelay(2);
11531da177e4SLinus Torvalds 	val &= 0x00ff;		/* isolation        */
11541da177e4SLinus Torvalds 	val |= 0x2000;
11551da177e4SLinus Torvalds 	fun_scam(dev, &val);
11562bbbac45SOndrej Zary 	udelay(2);
11571da177e4SLinus Torvalds 	i = 8;
11581da177e4SLinus Torvalds 	j = 0;
1159c7fcc089SOndrej Zary 
1160c7fcc089SOndrej Zary 	while (1) {
11616a3cebb6SOndrej Zary 		if ((atp_readw_io(dev, 0, 0x1c) & 0x2000) == 0)
1162c7fcc089SOndrej Zary 			continue;
11632bbbac45SOndrej Zary 		udelay(2);
11641da177e4SLinus Torvalds 		val &= 0x00ff;		/* get ID_STRING */
11651da177e4SLinus Torvalds 		val |= 0x2000;
11661da177e4SLinus Torvalds 		k = fun_scam(dev, &val);
1167c7fcc089SOndrej Zary 		if ((k & 0x03) == 0)
1168c7fcc089SOndrej Zary 			break;
11691da177e4SLinus Torvalds 		mbuf[j] <<= 0x01;
11701da177e4SLinus Torvalds 		mbuf[j] &= 0xfe;
1171c7fcc089SOndrej Zary 		if ((k & 0x02) != 0)
11721da177e4SLinus Torvalds 			mbuf[j] |= 0x01;
11731da177e4SLinus Torvalds 		i--;
1174c7fcc089SOndrej Zary 		if (i > 0)
1175c7fcc089SOndrej Zary 			continue;
11761da177e4SLinus Torvalds 		j++;
11771da177e4SLinus Torvalds 		i = 8;
1178c7fcc089SOndrej Zary 	}
11791da177e4SLinus Torvalds 
1180c7fcc089SOndrej Zary 	/* isolation complete..  */
11811da177e4SLinus Torvalds /*    mbuf[32]=0;
11821da177e4SLinus Torvalds 	printk(" \n%x %x %x %s\n ",assignid_map,mbuf[0],mbuf[1],&mbuf[2]); */
11831da177e4SLinus Torvalds 	i = 15;
11841da177e4SLinus Torvalds 	j = mbuf[0];
11851da177e4SLinus Torvalds 	if ((j & 0x20) != 0) {	/* bit5=1:ID up to 7      */
11861da177e4SLinus Torvalds 		i = 7;
11871da177e4SLinus Torvalds 	}
1188c7fcc089SOndrej Zary 	if ((j & 0x06) != 0) {	/* IDvalid?             */
11891da177e4SLinus Torvalds 		k = mbuf[1];
1190c7fcc089SOndrej Zary 		while (1) {
11911da177e4SLinus Torvalds 			m = 1;
11921da177e4SLinus Torvalds 			m <<= k;
1193c7fcc089SOndrej Zary 			if ((m & assignid_map) == 0)
1194c7fcc089SOndrej Zary 				break;
1195c7fcc089SOndrej Zary 			if (k > 0)
11961da177e4SLinus Torvalds 				k--;
1197c7fcc089SOndrej Zary 			else
1198c7fcc089SOndrej Zary 				break;
11991da177e4SLinus Torvalds 		}
1200c7fcc089SOndrej Zary 	}
1201c7fcc089SOndrej Zary 	if ((m & assignid_map) != 0) {	/* srch from max acceptable ID#  */
12021da177e4SLinus Torvalds 		k = i;			/* max acceptable ID#            */
1203c7fcc089SOndrej Zary 		while (1) {
12041da177e4SLinus Torvalds 			m = 1;
12051da177e4SLinus Torvalds 			m <<= k;
1206c7fcc089SOndrej Zary 			if ((m & assignid_map) == 0)
1207c7fcc089SOndrej Zary 				break;
1208c7fcc089SOndrej Zary 			if (k > 0)
12091da177e4SLinus Torvalds 				k--;
1210c7fcc089SOndrej Zary 			else
1211c7fcc089SOndrej Zary 				break;
12121da177e4SLinus Torvalds 		}
1213c7fcc089SOndrej Zary 	}
1214c7fcc089SOndrej Zary 	/* k=binID#,       */
12151da177e4SLinus Torvalds 	assignid_map |= m;
12161da177e4SLinus Torvalds 	if (k < 8) {
12171da177e4SLinus Torvalds 		quintet[0] = 0x38;	/* 1st dft ID<8    */
12181da177e4SLinus Torvalds 	} else {
12191da177e4SLinus Torvalds 		quintet[0] = 0x31;	/* 1st  ID>=8      */
12201da177e4SLinus Torvalds 	}
12211da177e4SLinus Torvalds 	k &= 0x07;
12221da177e4SLinus Torvalds 	quintet[1] = g2q_tab[k];
12231da177e4SLinus Torvalds 
12241da177e4SLinus Torvalds 	val &= 0x00ff;		/* AssignID 1stQuintet,AH=001xxxxx  */
12251da177e4SLinus Torvalds 	m = quintet[0] << 8;
12261da177e4SLinus Torvalds 	val |= m;
12271da177e4SLinus Torvalds 	fun_scam(dev, &val);
12281da177e4SLinus Torvalds 	val &= 0x00ff;		/* AssignID 2ndQuintet,AH=001xxxxx */
12291da177e4SLinus Torvalds 	m = quintet[1] << 8;
12301da177e4SLinus Torvalds 	val |= m;
12311da177e4SLinus Torvalds 	fun_scam(dev, &val);
12321da177e4SLinus Torvalds 
1233c7fcc089SOndrej Zary 	}
12341da177e4SLinus Torvalds }
12351da177e4SLinus Torvalds 
atp870u_free_tables(struct Scsi_Host * host)12361da177e4SLinus Torvalds static void atp870u_free_tables(struct Scsi_Host *host)
12371da177e4SLinus Torvalds {
12381da177e4SLinus Torvalds 	struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata;
12391da177e4SLinus Torvalds 	int j, k;
12401da177e4SLinus Torvalds 	for (j=0; j < 2; j++) {
12411da177e4SLinus Torvalds 		for (k = 0; k < 16; k++) {
12421da177e4SLinus Torvalds 			if (!atp_dev->id[j][k].prd_table)
12431da177e4SLinus Torvalds 				continue;
1244bcd5c59fSHannes Reinecke 			dma_free_coherent(&atp_dev->pdev->dev, 1024,
1245bcd5c59fSHannes Reinecke 					  atp_dev->id[j][k].prd_table,
1246bcd5c59fSHannes Reinecke 					  atp_dev->id[j][k].prd_bus);
12471da177e4SLinus Torvalds 			atp_dev->id[j][k].prd_table = NULL;
12481da177e4SLinus Torvalds 		}
12491da177e4SLinus Torvalds 	}
12501da177e4SLinus Torvalds }
12511da177e4SLinus Torvalds 
atp870u_init_tables(struct Scsi_Host * host)12521da177e4SLinus Torvalds static int atp870u_init_tables(struct Scsi_Host *host)
12531da177e4SLinus Torvalds {
12541da177e4SLinus Torvalds 	struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata;
12551da177e4SLinus Torvalds 	int c,k;
12561da177e4SLinus Torvalds 	for(c=0;c < 2;c++) {
12571da177e4SLinus Torvalds 		for(k=0;k<16;k++) {
1258bcd5c59fSHannes Reinecke 			atp_dev->id[c][k].prd_table =
1259bcd5c59fSHannes Reinecke 				dma_alloc_coherent(&atp_dev->pdev->dev, 1024,
1260bcd5c59fSHannes Reinecke 						   &(atp_dev->id[c][k].prd_bus),
1261bcd5c59fSHannes Reinecke 						   GFP_KERNEL);
12621da177e4SLinus Torvalds 			if (!atp_dev->id[c][k].prd_table) {
12631da177e4SLinus Torvalds 				printk("atp870u_init_tables fail\n");
12641da177e4SLinus Torvalds 				atp870u_free_tables(host);
12651da177e4SLinus Torvalds 				return -ENOMEM;
12661da177e4SLinus Torvalds 			}
1267b5683557SJames Bottomley 			atp_dev->id[c][k].prdaddr = atp_dev->id[c][k].prd_bus;
12681da177e4SLinus Torvalds 			atp_dev->id[c][k].devsp=0x20;
12691da177e4SLinus Torvalds 			atp_dev->id[c][k].devtype = 0x7f;
12701da177e4SLinus Torvalds 			atp_dev->id[c][k].curr_req = NULL;
12711da177e4SLinus Torvalds 		}
12721da177e4SLinus Torvalds 
12731da177e4SLinus Torvalds 		atp_dev->active_id[c] = 0;
12741da177e4SLinus Torvalds 		atp_dev->wide_id[c] = 0;
12751da177e4SLinus Torvalds 		atp_dev->host_id[c] = 0x07;
12761da177e4SLinus Torvalds 		atp_dev->quhd[c] = 0;
12771da177e4SLinus Torvalds 		atp_dev->quend[c] = 0;
12781da177e4SLinus Torvalds 		atp_dev->last_cmd[c] = 0xff;
12791da177e4SLinus Torvalds 		atp_dev->in_snd[c] = 0;
12801da177e4SLinus Torvalds 		atp_dev->in_int[c] = 0;
12811da177e4SLinus Torvalds 
12821da177e4SLinus Torvalds 		for (k = 0; k < qcnt; k++) {
12831da177e4SLinus Torvalds 			atp_dev->quereq[c][k] = NULL;
12841da177e4SLinus Torvalds 		}
12851da177e4SLinus Torvalds 		for (k = 0; k < 16; k++) {
12861da177e4SLinus Torvalds 			   atp_dev->id[c][k].curr_req = NULL;
12871da177e4SLinus Torvalds 			   atp_dev->sp[c][k] = 0x04;
12881da177e4SLinus Torvalds 		}
12891da177e4SLinus Torvalds 	}
12901da177e4SLinus Torvalds 	return 0;
12911da177e4SLinus Torvalds }
12921da177e4SLinus Torvalds 
atp_set_host_id(struct atp_unit * atp,u8 c,u8 host_id)12936a1961bcSOndrej Zary static void atp_set_host_id(struct atp_unit *atp, u8 c, u8 host_id)
12946a1961bcSOndrej Zary {
12956a1961bcSOndrej Zary 	atp_writeb_io(atp, c, 0, host_id | 0x08);
12966a1961bcSOndrej Zary 	atp_writeb_io(atp, c, 0x18, 0);
12976a1961bcSOndrej Zary 	while ((atp_readb_io(atp, c, 0x1f) & 0x80) == 0)
12986a1961bcSOndrej Zary 		mdelay(1);
12996a1961bcSOndrej Zary 	atp_readb_io(atp, c, 0x17);
13006a1961bcSOndrej Zary 	atp_writeb_io(atp, c, 1, 8);
13016a1961bcSOndrej Zary 	atp_writeb_io(atp, c, 2, 0x7f);
13026a1961bcSOndrej Zary 	atp_writeb_io(atp, c, 0x11, 0x20);
13036a1961bcSOndrej Zary }
13046a1961bcSOndrej Zary 
atp870_init(struct Scsi_Host * shpnt)13054190230eSOndrej Zary static void atp870_init(struct Scsi_Host *shpnt)
13064190230eSOndrej Zary {
13074190230eSOndrej Zary 	struct atp_unit *atpdev = shost_priv(shpnt);
13084190230eSOndrej Zary 	struct pci_dev *pdev = atpdev->pdev;
13094190230eSOndrej Zary 	unsigned char k, host_id;
13104190230eSOndrej Zary 	u8 scam_on;
13114190230eSOndrej Zary 	bool wide_chip =
13124190230eSOndrej Zary 		(pdev->device == PCI_DEVICE_ID_ARTOP_AEC7610 &&
13134190230eSOndrej Zary 		 pdev->revision == 4) ||
13144190230eSOndrej Zary 		(pdev->device == PCI_DEVICE_ID_ARTOP_AEC7612UW) ||
13154190230eSOndrej Zary 		(pdev->device == PCI_DEVICE_ID_ARTOP_AEC7612SUW);
13164190230eSOndrej Zary 
13174190230eSOndrej Zary 	pci_read_config_byte(pdev, 0x49, &host_id);
13184190230eSOndrej Zary 
1319bcd5c59fSHannes Reinecke 	dev_info(&pdev->dev, "ACARD AEC-671X PCI Ultra/W SCSI-2/3 "
1320bcd5c59fSHannes Reinecke 		 "Host Adapter: IO:%lx, IRQ:%d.\n",
13214190230eSOndrej Zary 		 shpnt->io_port, shpnt->irq);
13224190230eSOndrej Zary 
13234190230eSOndrej Zary 	atpdev->ioport[0] = shpnt->io_port;
13244190230eSOndrej Zary 	atpdev->pciport[0] = shpnt->io_port + 0x20;
13254190230eSOndrej Zary 	host_id &= 0x07;
13264190230eSOndrej Zary 	atpdev->host_id[0] = host_id;
13274190230eSOndrej Zary 	scam_on = atp_readb_pci(atpdev, 0, 2);
13284190230eSOndrej Zary 	atpdev->global_map[0] = atp_readb_base(atpdev, 0x2d);
13294190230eSOndrej Zary 	atpdev->ultra_map[0] = atp_readw_base(atpdev, 0x2e);
13304190230eSOndrej Zary 
13314190230eSOndrej Zary 	if (atpdev->ultra_map[0] == 0) {
13324190230eSOndrej Zary 		scam_on = 0x00;
13334190230eSOndrej Zary 		atpdev->global_map[0] = 0x20;
13344190230eSOndrej Zary 		atpdev->ultra_map[0] = 0xffff;
13354190230eSOndrej Zary 	}
13364190230eSOndrej Zary 
13374190230eSOndrej Zary 	if (pdev->revision > 0x07)	/* check if atp876 chip */
13384190230eSOndrej Zary 		atp_writeb_base(atpdev, 0x3e, 0x00); /* enable terminator */
13394190230eSOndrej Zary 
13404190230eSOndrej Zary 	k = (atp_readb_base(atpdev, 0x3a) & 0xf3) | 0x10;
13414190230eSOndrej Zary 	atp_writeb_base(atpdev, 0x3a, k);
13424190230eSOndrej Zary 	atp_writeb_base(atpdev, 0x3a, k & 0xdf);
1343dcaa0c12SJia-Ju Bai 	msleep(32);
13444190230eSOndrej Zary 	atp_writeb_base(atpdev, 0x3a, k);
1345dcaa0c12SJia-Ju Bai 	msleep(32);
13464190230eSOndrej Zary 	atp_set_host_id(atpdev, 0, host_id);
13474190230eSOndrej Zary 
13484190230eSOndrej Zary 	tscam(shpnt, wide_chip, scam_on);
13494190230eSOndrej Zary 	atp_writeb_base(atpdev, 0x3a, atp_readb_base(atpdev, 0x3a) | 0x10);
13504190230eSOndrej Zary 	atp_is(atpdev, 0, wide_chip, 0);
13514190230eSOndrej Zary 	atp_writeb_base(atpdev, 0x3a, atp_readb_base(atpdev, 0x3a) & 0xef);
13524190230eSOndrej Zary 	atp_writeb_base(atpdev, 0x3b, atp_readb_base(atpdev, 0x3b) | 0x20);
13534190230eSOndrej Zary 	shpnt->max_id = wide_chip ? 16 : 8;
13544190230eSOndrej Zary 	shpnt->this_id = host_id;
13554190230eSOndrej Zary }
13564190230eSOndrej Zary 
atp880_init(struct Scsi_Host * shpnt)1357c7e6a029SOndrej Zary static void atp880_init(struct Scsi_Host *shpnt)
1358c7e6a029SOndrej Zary {
1359c7e6a029SOndrej Zary 	struct atp_unit *atpdev = shost_priv(shpnt);
1360c7e6a029SOndrej Zary 	struct pci_dev *pdev = atpdev->pdev;
1361c7e6a029SOndrej Zary 	unsigned char k, m, host_id;
1362c7e6a029SOndrej Zary 	unsigned int n;
1363c7e6a029SOndrej Zary 
1364c7e6a029SOndrej Zary 	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80);
1365c7e6a029SOndrej Zary 
1366c7e6a029SOndrej Zary 	atpdev->ioport[0] = shpnt->io_port + 0x40;
1367c7e6a029SOndrej Zary 	atpdev->pciport[0] = shpnt->io_port + 0x28;
1368c7e6a029SOndrej Zary 
1369c7e6a029SOndrej Zary 	host_id = atp_readb_base(atpdev, 0x39) >> 4;
1370c7e6a029SOndrej Zary 
1371bcd5c59fSHannes Reinecke 	dev_info(&pdev->dev, "ACARD AEC-67160 PCI Ultra3 LVD "
1372bcd5c59fSHannes Reinecke 		 "Host Adapter: IO:%lx, IRQ:%d.\n",
1373c7e6a029SOndrej Zary 		 shpnt->io_port, shpnt->irq);
1374c7e6a029SOndrej Zary 	atpdev->host_id[0] = host_id;
1375c7e6a029SOndrej Zary 
1376c7e6a029SOndrej Zary 	atpdev->global_map[0] = atp_readb_base(atpdev, 0x35);
1377c7e6a029SOndrej Zary 	atpdev->ultra_map[0] = atp_readw_base(atpdev, 0x3c);
1378c7e6a029SOndrej Zary 
1379c7e6a029SOndrej Zary 	n = 0x3f09;
1380c7e6a029SOndrej Zary 	while (n < 0x4000) {
1381c7e6a029SOndrej Zary 		m = 0;
1382c7e6a029SOndrej Zary 		atp_writew_base(atpdev, 0x34, n);
1383c7e6a029SOndrej Zary 		n += 0x0002;
1384c7e6a029SOndrej Zary 		if (atp_readb_base(atpdev, 0x30) == 0xff)
1385c7e6a029SOndrej Zary 			break;
1386c7e6a029SOndrej Zary 
1387c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30);
1388c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31);
1389c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32);
1390c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33);
1391c7e6a029SOndrej Zary 		atp_writew_base(atpdev, 0x34, n);
1392c7e6a029SOndrej Zary 		n += 0x0002;
1393c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30);
1394c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31);
1395c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32);
1396c7e6a029SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33);
1397c7e6a029SOndrej Zary 		atp_writew_base(atpdev, 0x34, n);
1398c7e6a029SOndrej Zary 		n += 0x0002;
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 		n += 0x0018;
1410c7e6a029SOndrej Zary 	}
1411c7e6a029SOndrej Zary 	atp_writew_base(atpdev, 0x34, 0);
1412c7e6a029SOndrej Zary 	atpdev->ultra_map[0] = 0;
1413c7e6a029SOndrej Zary 	atpdev->async[0] = 0;
1414c7e6a029SOndrej Zary 	for (k = 0; k < 16; k++) {
1415c7e6a029SOndrej Zary 		n = 1 << k;
1416c7e6a029SOndrej Zary 		if (atpdev->sp[0][k] > 1)
1417c7e6a029SOndrej Zary 			atpdev->ultra_map[0] |= n;
1418c7e6a029SOndrej Zary 		else
1419c7e6a029SOndrej Zary 			if (atpdev->sp[0][k] == 0)
1420c7e6a029SOndrej Zary 				atpdev->async[0] |= n;
1421c7e6a029SOndrej Zary 	}
1422c7e6a029SOndrej Zary 	atpdev->async[0] = ~(atpdev->async[0]);
1423c7e6a029SOndrej Zary 	atp_writeb_base(atpdev, 0x35, atpdev->global_map[0]);
1424c7e6a029SOndrej Zary 
1425c7e6a029SOndrej Zary 	k = atp_readb_base(atpdev, 0x38) & 0x80;
1426c7e6a029SOndrej Zary 	atp_writeb_base(atpdev, 0x38, k);
1427c7e6a029SOndrej Zary 	atp_writeb_base(atpdev, 0x3b, 0x20);
1428dcaa0c12SJia-Ju Bai 	msleep(32);
1429c7e6a029SOndrej Zary 	atp_writeb_base(atpdev, 0x3b, 0);
1430dcaa0c12SJia-Ju Bai 	msleep(32);
1431c7e6a029SOndrej Zary 	atp_readb_io(atpdev, 0, 0x1b);
1432c7e6a029SOndrej Zary 	atp_readb_io(atpdev, 0, 0x17);
1433c7e6a029SOndrej Zary 
1434c7e6a029SOndrej Zary 	atp_set_host_id(atpdev, 0, host_id);
1435c7e6a029SOndrej Zary 
1436c7e6a029SOndrej Zary 	tscam(shpnt, true, atp_readb_base(atpdev, 0x22));
1437c7e6a029SOndrej Zary 	atp_is(atpdev, 0, true, atp_readb_base(atpdev, 0x3f) & 0x40);
1438c7e6a029SOndrej Zary 	atp_writeb_base(atpdev, 0x38, 0xb0);
1439c7e6a029SOndrej Zary 	shpnt->max_id = 16;
1440c7e6a029SOndrej Zary 	shpnt->this_id = host_id;
1441c7e6a029SOndrej Zary }
1442c7e6a029SOndrej Zary 
atp885_init(struct Scsi_Host * shpnt)1443ecc6ff95SOndrej Zary static void atp885_init(struct Scsi_Host *shpnt)
1444ecc6ff95SOndrej Zary {
1445ecc6ff95SOndrej Zary 	struct atp_unit *atpdev = shost_priv(shpnt);
1446ecc6ff95SOndrej Zary 	struct pci_dev *pdev = atpdev->pdev;
1447ecc6ff95SOndrej Zary 	unsigned char k, m, c;
1448ecc6ff95SOndrej Zary 	unsigned int n;
1449ecc6ff95SOndrej Zary 	unsigned char setupdata[2][16];
1450ecc6ff95SOndrej Zary 
1451bcd5c59fSHannes Reinecke 	dev_info(&pdev->dev, "ACARD AEC-67162 PCI Ultra3 LVD "
1452bcd5c59fSHannes Reinecke 		 "Host Adapter: IO:%lx, IRQ:%d.\n",
1453ecc6ff95SOndrej Zary 		 shpnt->io_port, shpnt->irq);
1454ecc6ff95SOndrej Zary 
1455ecc6ff95SOndrej Zary 	atpdev->ioport[0] = shpnt->io_port + 0x80;
1456ecc6ff95SOndrej Zary 	atpdev->ioport[1] = shpnt->io_port + 0xc0;
1457ecc6ff95SOndrej Zary 	atpdev->pciport[0] = shpnt->io_port + 0x40;
1458ecc6ff95SOndrej Zary 	atpdev->pciport[1] = shpnt->io_port + 0x50;
1459ecc6ff95SOndrej Zary 
1460ecc6ff95SOndrej Zary 	c = atp_readb_base(atpdev, 0x29);
1461ecc6ff95SOndrej Zary 	atp_writeb_base(atpdev, 0x29, c | 0x04);
1462ecc6ff95SOndrej Zary 
1463ecc6ff95SOndrej Zary 	n = 0x1f80;
1464ecc6ff95SOndrej Zary 	while (n < 0x2000) {
1465ecc6ff95SOndrej Zary 		atp_writew_base(atpdev, 0x3c, n);
1466ecc6ff95SOndrej Zary 		if (atp_readl_base(atpdev, 0x38) == 0xffffffff)
1467ecc6ff95SOndrej Zary 			break;
1468ecc6ff95SOndrej Zary 		for (m = 0; m < 2; m++) {
1469ecc6ff95SOndrej Zary 			atpdev->global_map[m] = 0;
1470ecc6ff95SOndrej Zary 			for (k = 0; k < 4; k++) {
1471ecc6ff95SOndrej Zary 				atp_writew_base(atpdev, 0x3c, n++);
1472bcd5c59fSHannes Reinecke 				((u32 *)&setupdata[m][0])[k] =
1473bcd5c59fSHannes Reinecke 					atp_readl_base(atpdev, 0x38);
1474ecc6ff95SOndrej Zary 			}
1475ecc6ff95SOndrej Zary 			for (k = 0; k < 4; k++) {
1476ecc6ff95SOndrej Zary 				atp_writew_base(atpdev, 0x3c, n++);
1477bcd5c59fSHannes Reinecke 				((u32 *)&atpdev->sp[m][0])[k] =
1478bcd5c59fSHannes Reinecke 					atp_readl_base(atpdev, 0x38);
1479ecc6ff95SOndrej Zary 			}
1480ecc6ff95SOndrej Zary 			n += 8;
1481ecc6ff95SOndrej Zary 		}
1482ecc6ff95SOndrej Zary 	}
1483ecc6ff95SOndrej Zary 	c = atp_readb_base(atpdev, 0x29);
1484ecc6ff95SOndrej Zary 	atp_writeb_base(atpdev, 0x29, c & 0xfb);
1485ecc6ff95SOndrej Zary 	for (c = 0; c < 2; c++) {
1486ecc6ff95SOndrej Zary 		atpdev->ultra_map[c] = 0;
1487ecc6ff95SOndrej Zary 		atpdev->async[c] = 0;
1488ecc6ff95SOndrej Zary 		for (k = 0; k < 16; k++) {
1489ecc6ff95SOndrej Zary 			n = 1 << k;
1490ecc6ff95SOndrej Zary 			if (atpdev->sp[c][k] > 1)
1491ecc6ff95SOndrej Zary 				atpdev->ultra_map[c] |= n;
1492ecc6ff95SOndrej Zary 			else
1493ecc6ff95SOndrej Zary 				if (atpdev->sp[c][k] == 0)
1494ecc6ff95SOndrej Zary 					atpdev->async[c] |= n;
1495ecc6ff95SOndrej Zary 		}
1496ecc6ff95SOndrej Zary 		atpdev->async[c] = ~(atpdev->async[c]);
1497ecc6ff95SOndrej Zary 
1498ecc6ff95SOndrej Zary 		if (atpdev->global_map[c] == 0) {
1499ecc6ff95SOndrej Zary 			k = setupdata[c][1];
1500ecc6ff95SOndrej Zary 			if ((k & 0x40) != 0)
1501ecc6ff95SOndrej Zary 				atpdev->global_map[c] |= 0x20;
1502ecc6ff95SOndrej Zary 			k &= 0x07;
1503ecc6ff95SOndrej Zary 			atpdev->global_map[c] |= k;
1504ecc6ff95SOndrej Zary 			if ((setupdata[c][2] & 0x04) != 0)
1505ecc6ff95SOndrej Zary 				atpdev->global_map[c] |= 0x08;
1506ecc6ff95SOndrej Zary 			atpdev->host_id[c] = setupdata[c][0] & 0x07;
1507ecc6ff95SOndrej Zary 		}
1508ecc6ff95SOndrej Zary 	}
1509ecc6ff95SOndrej Zary 
1510ecc6ff95SOndrej Zary 	k = atp_readb_base(atpdev, 0x28) & 0x8f;
1511ecc6ff95SOndrej Zary 	k |= 0x10;
1512ecc6ff95SOndrej Zary 	atp_writeb_base(atpdev, 0x28, k);
1513ecc6ff95SOndrej Zary 	atp_writeb_pci(atpdev, 0, 1, 0x80);
1514ecc6ff95SOndrej Zary 	atp_writeb_pci(atpdev, 1, 1, 0x80);
1515dcaa0c12SJia-Ju Bai 	msleep(100);
1516ecc6ff95SOndrej Zary 	atp_writeb_pci(atpdev, 0, 1, 0);
1517ecc6ff95SOndrej Zary 	atp_writeb_pci(atpdev, 1, 1, 0);
1518dcaa0c12SJia-Ju Bai 	msleep(1000);
1519ecc6ff95SOndrej Zary 	atp_readb_io(atpdev, 0, 0x1b);
1520ecc6ff95SOndrej Zary 	atp_readb_io(atpdev, 0, 0x17);
1521ecc6ff95SOndrej Zary 	atp_readb_io(atpdev, 1, 0x1b);
1522ecc6ff95SOndrej Zary 	atp_readb_io(atpdev, 1, 0x17);
1523ecc6ff95SOndrej Zary 
1524ecc6ff95SOndrej Zary 	k = atpdev->host_id[0];
1525ecc6ff95SOndrej Zary 	if (k > 7)
1526ecc6ff95SOndrej Zary 		k = (k & 0x07) | 0x40;
1527ecc6ff95SOndrej Zary 	atp_set_host_id(atpdev, 0, k);
1528ecc6ff95SOndrej Zary 
1529ecc6ff95SOndrej Zary 	k = atpdev->host_id[1];
1530ecc6ff95SOndrej Zary 	if (k > 7)
1531ecc6ff95SOndrej Zary 		k = (k & 0x07) | 0x40;
1532ecc6ff95SOndrej Zary 	atp_set_host_id(atpdev, 1, k);
1533ecc6ff95SOndrej Zary 
1534dcaa0c12SJia-Ju Bai 	msleep(600); /* this delay used to be called tscam_885() */
1535ecc6ff95SOndrej Zary 	dev_info(&pdev->dev, "Scanning Channel A SCSI Device ...\n");
1536ecc6ff95SOndrej Zary 	atp_is(atpdev, 0, true, atp_readb_io(atpdev, 0, 0x1b) >> 7);
1537ecc6ff95SOndrej Zary 	atp_writeb_io(atpdev, 0, 0x16, 0x80);
1538ecc6ff95SOndrej Zary 	dev_info(&pdev->dev, "Scanning Channel B SCSI Device ...\n");
1539ecc6ff95SOndrej Zary 	atp_is(atpdev, 1, true, atp_readb_io(atpdev, 1, 0x1b) >> 7);
1540ecc6ff95SOndrej Zary 	atp_writeb_io(atpdev, 1, 0x16, 0x80);
1541ecc6ff95SOndrej Zary 	k = atp_readb_base(atpdev, 0x28) & 0xcf;
1542ecc6ff95SOndrej Zary 	k |= 0xc0;
1543ecc6ff95SOndrej Zary 	atp_writeb_base(atpdev, 0x28, k);
1544ecc6ff95SOndrej Zary 	k = atp_readb_base(atpdev, 0x1f) | 0x80;
1545ecc6ff95SOndrej Zary 	atp_writeb_base(atpdev, 0x1f, k);
1546ecc6ff95SOndrej Zary 	k = atp_readb_base(atpdev, 0x29) | 0x01;
1547ecc6ff95SOndrej Zary 	atp_writeb_base(atpdev, 0x29, k);
1548ecc6ff95SOndrej Zary 	shpnt->max_id = 16;
1549ecc6ff95SOndrej Zary 	shpnt->max_lun = (atpdev->global_map[0] & 0x07) + 1;
1550ecc6ff95SOndrej Zary 	shpnt->max_channel = 1;
1551ecc6ff95SOndrej Zary 	shpnt->this_id = atpdev->host_id[0];
1552ecc6ff95SOndrej Zary }
1553ecc6ff95SOndrej Zary 
15541da177e4SLinus Torvalds /* return non-zero on detection */
atp870u_probe(struct pci_dev * pdev,const struct pci_device_id * ent)15551da177e4SLinus Torvalds static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
15561da177e4SLinus Torvalds {
15571da177e4SLinus Torvalds 	struct Scsi_Host *shpnt = NULL;
1558bdd5ac40SOndrej Zary 	struct atp_unit *atpdev;
1559bdd5ac40SOndrej Zary 	int err;
15601da177e4SLinus Torvalds 
1561b1e85063SOndrej Zary 	if (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610 && pdev->revision < 2) {
1562b1e85063SOndrej Zary 		dev_err(&pdev->dev, "ATP850S chips (AEC6710L/F cards) are not supported.\n");
1563b1e85063SOndrej Zary 		return -ENODEV;
1564b1e85063SOndrej Zary 	}
1565b1e85063SOndrej Zary 
1566bdd5ac40SOndrej Zary 	err = pci_enable_device(pdev);
1567bdd5ac40SOndrej Zary 	if (err)
1568bdd5ac40SOndrej Zary 		goto fail;
15691da177e4SLinus Torvalds 
157048ecddb4SChristoph Hellwig 	if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) {
15711da177e4SLinus Torvalds 		printk(KERN_ERR "atp870u: DMA mask required but not available.\n");
1572bdd5ac40SOndrej Zary 		err = -EIO;
1573bdd5ac40SOndrej Zary 		goto disable_device;
15741da177e4SLinus Torvalds 	}
15751da177e4SLinus Torvalds 
157611ec1318SOndrej Zary 	err = pci_request_regions(pdev, "atp870u");
157711ec1318SOndrej Zary 	if (err)
157811ec1318SOndrej Zary 		goto disable_device;
157911ec1318SOndrej Zary 	pci_set_master(pdev);
158011ec1318SOndrej Zary 
1581bdd5ac40SOndrej Zary 	err = -ENOMEM;
1582bdd5ac40SOndrej Zary 	shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
1583bdd5ac40SOndrej Zary 	if (!shpnt)
158411ec1318SOndrej Zary 		goto release_region;
1585bdd5ac40SOndrej Zary 
1586bdd5ac40SOndrej Zary 	atpdev = shost_priv(shpnt);
1587bdd5ac40SOndrej Zary 
1588bdd5ac40SOndrej Zary 	atpdev->host = shpnt;
1589bdd5ac40SOndrej Zary 	atpdev->pdev = pdev;
1590bdd5ac40SOndrej Zary 	pci_set_drvdata(pdev, atpdev);
1591bdd5ac40SOndrej Zary 
15926c9b9c55SOndrej Zary 	shpnt->io_port = pci_resource_start(pdev, 0);
15936c9b9c55SOndrej Zary 	shpnt->io_port &= 0xfffffff8;
15946c9b9c55SOndrej Zary 	shpnt->n_io_port = pci_resource_len(pdev, 0);
15956c9b9c55SOndrej Zary 	atpdev->baseport = shpnt->io_port;
15966c9b9c55SOndrej Zary 	shpnt->unique_id = shpnt->io_port;
15976c9b9c55SOndrej Zary 	shpnt->irq = pdev->irq;
15981da177e4SLinus Torvalds 
1599f5f53a38SOndrej Zary 	err = atp870u_init_tables(shpnt);
1600f5f53a38SOndrej Zary 	if (err) {
1601f5f53a38SOndrej Zary 		dev_err(&pdev->dev, "Unable to allocate tables for Acard controller\n");
1602f5f53a38SOndrej Zary 		goto unregister;
1603f5f53a38SOndrej Zary 	}
1604f5f53a38SOndrej Zary 
1605c7e6a029SOndrej Zary 	if (is880(atpdev))
1606c7e6a029SOndrej Zary 		atp880_init(shpnt);
1607ecc6ff95SOndrej Zary 	else if (is885(atpdev))
1608ecc6ff95SOndrej Zary 		atp885_init(shpnt);
16094190230eSOndrej Zary 	else
16104190230eSOndrej Zary 		atp870_init(shpnt);
16111da177e4SLinus Torvalds 
16121729c0d2SOndrej Zary 	err = request_irq(shpnt->irq, atp870u_intr_handle, IRQF_SHARED, "atp870u", shpnt);
16131729c0d2SOndrej Zary 	if (err) {
16141729c0d2SOndrej Zary 		dev_err(&pdev->dev, "Unable to allocate IRQ %d.\n", shpnt->irq);
16151729c0d2SOndrej Zary 		goto free_tables;
16161729c0d2SOndrej Zary 	}
16171729c0d2SOndrej Zary 
1618bdd5ac40SOndrej Zary 	err = scsi_add_host(shpnt, &pdev->dev);
1619bdd5ac40SOndrej Zary 	if (err)
16201da177e4SLinus Torvalds 		goto scsi_add_fail;
16211da177e4SLinus Torvalds 	scsi_scan_host(shpnt);
16221729c0d2SOndrej Zary 
16231da177e4SLinus Torvalds 	return 0;
16241da177e4SLinus Torvalds 
16251da177e4SLinus Torvalds scsi_add_fail:
16266c9b9c55SOndrej Zary 	free_irq(shpnt->irq, shpnt);
16271da177e4SLinus Torvalds free_tables:
16281da177e4SLinus Torvalds 	atp870u_free_tables(shpnt);
16291da177e4SLinus Torvalds unregister:
16301da177e4SLinus Torvalds 	scsi_host_put(shpnt);
163111ec1318SOndrej Zary release_region:
163211ec1318SOndrej Zary 	pci_release_regions(pdev);
1633bdd5ac40SOndrej Zary disable_device:
1634bdd5ac40SOndrej Zary 	pci_disable_device(pdev);
1635bdd5ac40SOndrej Zary fail:
1636bdd5ac40SOndrej Zary 	return err;
16371da177e4SLinus Torvalds }
16381da177e4SLinus Torvalds 
16391da177e4SLinus Torvalds /* The abort command does not leave the device in a clean state where
16401da177e4SLinus Torvalds    it is available to be used again.  Until this gets worked out, we will
16411da177e4SLinus Torvalds    leave it commented out.  */
16421da177e4SLinus Torvalds 
atp870u_abort(struct scsi_cmnd * SCpnt)16431da177e4SLinus Torvalds static int atp870u_abort(struct scsi_cmnd * SCpnt)
16441da177e4SLinus Torvalds {
16451da177e4SLinus Torvalds 	unsigned char  j, k, c;
16461da177e4SLinus Torvalds 	struct scsi_cmnd *workrequ;
16471da177e4SLinus Torvalds 	struct atp_unit *dev;
16481da177e4SLinus Torvalds 	struct Scsi_Host *host;
16491da177e4SLinus Torvalds 	host = SCpnt->device->host;
16501da177e4SLinus Torvalds 
16511da177e4SLinus Torvalds 	dev = (struct atp_unit *)&host->hostdata;
1652422c0d61SJeff Garzik 	c = scmd_channel(SCpnt);
16531da177e4SLinus Torvalds 	printk(" atp870u: abort Channel = %x \n", c);
16541da177e4SLinus Torvalds 	printk("working=%x last_cmd=%x ", dev->working[c], dev->last_cmd[c]);
16551da177e4SLinus Torvalds 	printk(" quhdu=%x quendu=%x ", dev->quhd[c], dev->quend[c]);
16561da177e4SLinus Torvalds 	for (j = 0; j < 0x18; j++) {
16576a3cebb6SOndrej Zary 		printk(" r%2x=%2x", j, atp_readb_io(dev, c, j));
16581da177e4SLinus Torvalds 	}
16596a3cebb6SOndrej Zary 	printk(" r1c=%2x", atp_readb_io(dev, c, 0x1c));
16606a3cebb6SOndrej Zary 	printk(" r1f=%2x in_snd=%2x ", atp_readb_io(dev, c, 0x1f), dev->in_snd[c]);
16616a3cebb6SOndrej Zary 	printk(" d00=%2x", atp_readb_pci(dev, c, 0x00));
16626a3cebb6SOndrej Zary 	printk(" d02=%2x", atp_readb_pci(dev, c, 0x02));
16631da177e4SLinus Torvalds 	for(j=0;j<16;j++) {
16641da177e4SLinus Torvalds 	   if (dev->id[c][j].curr_req != NULL) {
16651da177e4SLinus Torvalds 		workrequ = dev->id[c][j].curr_req;
16661da177e4SLinus Torvalds 		printk("\n que cdb= ");
16671da177e4SLinus Torvalds 		for (k=0; k < workrequ->cmd_len; k++) {
16681da177e4SLinus Torvalds 		    printk(" %2x ",workrequ->cmnd[k]);
16691da177e4SLinus Torvalds 		}
16701da177e4SLinus Torvalds 		printk(" last_lenu= %x ",(unsigned int)dev->id[c][j].last_len);
16711da177e4SLinus Torvalds 	   }
16721da177e4SLinus Torvalds 	}
16731da177e4SLinus Torvalds 	return SUCCESS;
16741da177e4SLinus Torvalds }
16751da177e4SLinus Torvalds 
atp870u_info(struct Scsi_Host * notused)16761da177e4SLinus Torvalds static const char *atp870u_info(struct Scsi_Host *notused)
16771da177e4SLinus Torvalds {
16781da177e4SLinus Torvalds 	static char buffer[128];
16791da177e4SLinus Torvalds 
16801da177e4SLinus Torvalds 	strcpy(buffer, "ACARD AEC-6710/6712/67160 PCI Ultra/W/LVD SCSI-3 Adapter Driver V2.6+ac ");
16811da177e4SLinus Torvalds 
16821da177e4SLinus Torvalds 	return buffer;
16831da177e4SLinus Torvalds }
16841da177e4SLinus Torvalds 
atp870u_show_info(struct seq_file * m,struct Scsi_Host * HBAptr)1685d773e422SAl Viro static int atp870u_show_info(struct seq_file *m, struct Scsi_Host *HBAptr)
16861da177e4SLinus Torvalds {
16873d30079cSRasmus Villemoes 	seq_puts(m, "ACARD AEC-671X Driver Version: 2.6+ac\n\n"
16883d30079cSRasmus Villemoes 		"Adapter Configuration:\n");
1689d773e422SAl Viro 	seq_printf(m, "               Base IO: %#.4lx\n", HBAptr->io_port);
1690d773e422SAl Viro 	seq_printf(m, "                   IRQ: %d\n", HBAptr->irq);
1691d773e422SAl Viro 	return 0;
16921da177e4SLinus Torvalds }
16931da177e4SLinus Torvalds 
16941da177e4SLinus Torvalds 
atp870u_biosparam(struct scsi_device * disk,struct block_device * dev,sector_t capacity,int * ip)16951da177e4SLinus Torvalds static int atp870u_biosparam(struct scsi_device *disk, struct block_device *dev,
16961da177e4SLinus Torvalds 			sector_t capacity, int *ip)
16971da177e4SLinus Torvalds {
16981da177e4SLinus Torvalds 	int heads, sectors, cylinders;
16991da177e4SLinus Torvalds 
17001da177e4SLinus Torvalds 	heads = 64;
17011da177e4SLinus Torvalds 	sectors = 32;
17021da177e4SLinus Torvalds 	cylinders = (unsigned long)capacity / (heads * sectors);
17031da177e4SLinus Torvalds 	if (cylinders > 1024) {
17041da177e4SLinus Torvalds 		heads = 255;
17051da177e4SLinus Torvalds 		sectors = 63;
17061da177e4SLinus Torvalds 		cylinders = (unsigned long)capacity / (heads * sectors);
17071da177e4SLinus Torvalds 	}
17081da177e4SLinus Torvalds 	ip[0] = heads;
17091da177e4SLinus Torvalds 	ip[1] = sectors;
17101da177e4SLinus Torvalds 	ip[2] = cylinders;
17111da177e4SLinus Torvalds 
17121da177e4SLinus Torvalds 	return 0;
17131da177e4SLinus Torvalds }
17141da177e4SLinus Torvalds 
atp870u_remove(struct pci_dev * pdev)17151da177e4SLinus Torvalds static void atp870u_remove (struct pci_dev *pdev)
17161da177e4SLinus Torvalds {
17171da177e4SLinus Torvalds 	struct atp_unit *devext = pci_get_drvdata(pdev);
17181da177e4SLinus Torvalds 	struct Scsi_Host *pshost = devext->host;
17191da177e4SLinus Torvalds 
17201da177e4SLinus Torvalds 	scsi_remove_host(pshost);
17211da177e4SLinus Torvalds 	free_irq(pshost->irq, pshost);
172211ec1318SOndrej Zary 	pci_release_regions(pdev);
172311ec1318SOndrej Zary 	pci_disable_device(pdev);
17241da177e4SLinus Torvalds 	atp870u_free_tables(pshost);
17251da177e4SLinus Torvalds 	scsi_host_put(pshost);
17261da177e4SLinus Torvalds }
1727*95f8bf93SJeff Johnson 
1728*95f8bf93SJeff Johnson MODULE_DESCRIPTION("ACARD SCSI host adapter driver");
17291da177e4SLinus Torvalds MODULE_LICENSE("GPL");
17301da177e4SLinus Torvalds 
1731f44e1c63SBart Van Assche static const struct scsi_host_template atp870u_template = {
17321da177e4SLinus Torvalds      .module			= THIS_MODULE,
17331da177e4SLinus Torvalds      .name			= "atp870u"		/* name */,
17341da177e4SLinus Torvalds      .proc_name			= "atp870u",
1735d773e422SAl Viro      .show_info			= atp870u_show_info,
17361da177e4SLinus Torvalds      .info			= atp870u_info		/* info */,
17371da177e4SLinus Torvalds      .queuecommand		= atp870u_queuecommand	/* queuecommand */,
17381da177e4SLinus Torvalds      .eh_abort_handler		= atp870u_abort		/* abort */,
17391da177e4SLinus Torvalds      .bios_param		= atp870u_biosparam	/* biosparm */,
17401da177e4SLinus Torvalds      .can_queue			= qcnt			/* can_queue */,
17411da177e4SLinus Torvalds      .this_id			= 7			/* SCSI ID */,
174235c33633SFinn Thain      .sg_tablesize		= ATP870U_SCATTER	/*SG_ALL*/,
17431da177e4SLinus Torvalds      .max_sectors		= ATP870U_MAX_SECTORS,
17441da177e4SLinus Torvalds };
17451da177e4SLinus Torvalds 
17461da177e4SLinus Torvalds static struct pci_device_id atp870u_id_table[] = {
17471da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP885_DEVID)			  },
17481da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID1)		  },
17491da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID2)		  },
17501da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7610)    },
17511da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612UW)  },
17521da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612U)   },
17531da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612S)   },
17541da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612D)	  },
17551da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612SUW) },
17561da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_8060)	  },
17571da177e4SLinus Torvalds 	{ 0, },
17581da177e4SLinus Torvalds };
17591da177e4SLinus Torvalds 
17601da177e4SLinus Torvalds MODULE_DEVICE_TABLE(pci, atp870u_id_table);
17611da177e4SLinus Torvalds 
17621da177e4SLinus Torvalds static struct pci_driver atp870u_driver = {
17631da177e4SLinus Torvalds 	.id_table	= atp870u_id_table,
17641da177e4SLinus Torvalds 	.name		= "atp870u",
17651da177e4SLinus Torvalds 	.probe		= atp870u_probe,
17666f039790SGreg Kroah-Hartman 	.remove		= atp870u_remove,
17671da177e4SLinus Torvalds };
17681da177e4SLinus Torvalds 
17691ccd7d68SOndrej Zary module_pci_driver(atp870u_driver);
17701da177e4SLinus Torvalds 
atp_is(struct atp_unit * dev,unsigned char c,bool wide_chip,unsigned char lvdmode)1771bcd5c59fSHannes Reinecke static void atp_is(struct atp_unit *dev, unsigned char c, bool wide_chip,
1772bcd5c59fSHannes Reinecke 		   unsigned char lvdmode)
17731da177e4SLinus Torvalds {
1774fa50b308SOndrej Zary 	unsigned char i, j, k, rmb, n;
17751da177e4SLinus Torvalds 	unsigned short int m;
17761da177e4SLinus Torvalds 	static unsigned char mbuf[512];
17771da177e4SLinus Torvalds 	static unsigned char satn[9] = { 0, 0, 0, 0, 0, 0, 0, 6, 6 };
17781da177e4SLinus Torvalds 	static unsigned char inqd[9] = { 0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6 };
17791da177e4SLinus Torvalds 	static unsigned char synn[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
17801da177e4SLinus Torvalds 	unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
17811da177e4SLinus Torvalds 	static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
1782460da918SOndrej Zary 	static unsigned char synw_870[6] = { 0x80, 1, 3, 1, 0x0c, 0x07 };
17831da177e4SLinus Torvalds 	unsigned char synuw[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
17841da177e4SLinus Torvalds 	static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
17851da177e4SLinus Torvalds 	static unsigned char u3[9] = { 0x80, 1, 6, 4, 0x09, 00, 0x0e, 0x01, 0x02 };
17861da177e4SLinus Torvalds 
17871da177e4SLinus Torvalds 	for (i = 0; i < 16; i++) {
1788197fb8d8SOndrej Zary 		if (!wide_chip && (i > 7))
1789197fb8d8SOndrej Zary 			break;
17901da177e4SLinus Torvalds 		m = 1;
17911da177e4SLinus Torvalds 		m = m << i;
17921da177e4SLinus Torvalds 		if ((m & dev->active_id[c]) != 0) {
17931da177e4SLinus Torvalds 			continue;
17941da177e4SLinus Torvalds 		}
17951da177e4SLinus Torvalds 		if (i == dev->host_id[c]) {
17961da177e4SLinus Torvalds 			printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_id[c]);
17971da177e4SLinus Torvalds 			continue;
17981da177e4SLinus Torvalds 		}
1799197fb8d8SOndrej Zary 		atp_writeb_io(dev, c, 0x1b, wide_chip ? 0x01 : 0x00);
18005d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 1, 0x08);
18015d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 2, 0x7f);
18025d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 3, satn[0]);
18035d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 4, satn[1]);
18045d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 5, satn[2]);
18055d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 6, satn[3]);
18065d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 7, satn[4]);
18075d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 8, satn[5]);
18085d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x0f, 0);
18095d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
18105d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
18115d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, satn[6]);
18125d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, satn[7]);
18131da177e4SLinus Torvalds 		j = i;
18141da177e4SLinus Torvalds 		if ((j & 0x08) != 0) {
18151da177e4SLinus Torvalds 			j = (j & 0x07) | 0x40;
18161da177e4SLinus Torvalds 		}
18175d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x15, j);
18185d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, satn[8]);
18191da177e4SLinus Torvalds 
18205d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
18211da177e4SLinus Torvalds 			cpu_relax();
182280b52a7fSOndrej Zary 
182380b52a7fSOndrej Zary 		if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e)
18241da177e4SLinus Torvalds 			continue;
182580b52a7fSOndrej Zary 
18265d2a5a4fSOndrej Zary 		while (atp_readb_io(dev, c, 0x17) != 0x8e)
18271da177e4SLinus Torvalds 			cpu_relax();
182880b52a7fSOndrej Zary 
18291da177e4SLinus Torvalds 		dev->active_id[c] |= m;
18301da177e4SLinus Torvalds 
18315d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x10, 0x30);
1832b922a449SOndrej Zary 		if (is885(dev) || is880(dev))
18335d2a5a4fSOndrej Zary 			atp_writeb_io(dev, c, 0x14, 0x00);
1834460da918SOndrej Zary 		else /* result of is870() merge - is this a bug? */
1835460da918SOndrej Zary 			atp_writeb_io(dev, c, 0x04, 0x00);
18361da177e4SLinus Torvalds 
18371da177e4SLinus Torvalds phase_cmd:
18385d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
183980b52a7fSOndrej Zary 
18405d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
18411da177e4SLinus Torvalds 			cpu_relax();
184280b52a7fSOndrej Zary 
18435d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
18441da177e4SLinus Torvalds 		if (j != 0x16) {
18455d2a5a4fSOndrej Zary 			atp_writeb_io(dev, c, 0x10, 0x41);
18461da177e4SLinus Torvalds 			goto phase_cmd;
18471da177e4SLinus Torvalds 		}
18481da177e4SLinus Torvalds sel_ok:
18495d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 3, inqd[0]);
18505d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 4, inqd[1]);
18515d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 5, inqd[2]);
18525d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 6, inqd[3]);
18535d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 7, inqd[4]);
18545d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 8, inqd[5]);
18555d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x0f, 0);
18565d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
18575d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
18585d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, inqd[6]);
18595d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, inqd[7]);
18605d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, inqd[8]);
186180b52a7fSOndrej Zary 
18625d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
18631da177e4SLinus Torvalds 			cpu_relax();
186480b52a7fSOndrej Zary 
186580b52a7fSOndrej Zary 		if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e)
18661da177e4SLinus Torvalds 			continue;
186780b52a7fSOndrej Zary 
18685d2a5a4fSOndrej Zary 		while (atp_readb_io(dev, c, 0x17) != 0x8e)
18691da177e4SLinus Torvalds 			cpu_relax();
187080b52a7fSOndrej Zary 
1871197fb8d8SOndrej Zary 		if (wide_chip)
18725d2a5a4fSOndrej Zary 			atp_writeb_io(dev, c, 0x1b, 0x00);
1873197fb8d8SOndrej Zary 
18745d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
18751da177e4SLinus Torvalds 		j = 0;
18761da177e4SLinus Torvalds rd_inq_data:
18775d2a5a4fSOndrej Zary 		k = atp_readb_io(dev, c, 0x1f);
18781da177e4SLinus Torvalds 		if ((k & 0x01) != 0) {
18795d2a5a4fSOndrej Zary 			mbuf[j++] = atp_readb_io(dev, c, 0x19);
18801da177e4SLinus Torvalds 			goto rd_inq_data;
18811da177e4SLinus Torvalds 		}
18821da177e4SLinus Torvalds 		if ((k & 0x80) == 0) {
18831da177e4SLinus Torvalds 			goto rd_inq_data;
18841da177e4SLinus Torvalds 		}
18855d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
18861da177e4SLinus Torvalds 		if (j == 0x16) {
18871da177e4SLinus Torvalds 			goto inq_ok;
18881da177e4SLinus Torvalds 		}
18895d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x10, 0x46);
18905d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
18915d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, 0);
18925d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0);
18935d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
189480b52a7fSOndrej Zary 
18955d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
18961da177e4SLinus Torvalds 			cpu_relax();
189780b52a7fSOndrej Zary 
189880b52a7fSOndrej Zary 		if (atp_readb_io(dev, c, 0x17) != 0x16)
18991da177e4SLinus Torvalds 			goto sel_ok;
190080b52a7fSOndrej Zary 
19011da177e4SLinus Torvalds inq_ok:
19021da177e4SLinus Torvalds 		mbuf[36] = 0;
19031da177e4SLinus Torvalds 		printk(KERN_INFO "         ID: %2d  %s\n", i, &mbuf[8]);
19041da177e4SLinus Torvalds 		dev->id[c][i].devtype = mbuf[0];
19051da177e4SLinus Torvalds 		rmb = mbuf[1];
19061da177e4SLinus Torvalds 		n = mbuf[7];
1907197fb8d8SOndrej Zary 		if (!wide_chip)
1908197fb8d8SOndrej Zary 			goto not_wide;
19091da177e4SLinus Torvalds 		if ((mbuf[7] & 0x60) == 0) {
19101da177e4SLinus Torvalds 			goto not_wide;
19111da177e4SLinus Torvalds 		}
1912b922a449SOndrej Zary 		if (is885(dev) || is880(dev)) {
1913197fb8d8SOndrej Zary 			if ((i < 8) && ((dev->global_map[c] & 0x20) == 0))
1914197fb8d8SOndrej Zary 				goto not_wide;
1915197fb8d8SOndrej Zary 		} else { /* result of is870() merge - is this a bug? */
1916197fb8d8SOndrej Zary 			if ((dev->global_map[c] & 0x20) == 0)
19171da177e4SLinus Torvalds 				goto not_wide;
19181da177e4SLinus Torvalds 		}
19191da177e4SLinus Torvalds 		if (lvdmode == 0) {
19201da177e4SLinus Torvalds 			goto chg_wide;
19211da177e4SLinus Torvalds 		}
192280b52a7fSOndrej Zary 		if (dev->sp[c][i] != 0x04)	// force u2
192380b52a7fSOndrej Zary 		{
19241da177e4SLinus Torvalds 			goto chg_wide;
19251da177e4SLinus Torvalds 		}
19261da177e4SLinus Torvalds 
19275d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x1b, 0x01);
19285d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 3, satn[0]);
19295d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 4, satn[1]);
19305d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 5, satn[2]);
19315d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 6, satn[3]);
19325d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 7, satn[4]);
19335d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 8, satn[5]);
19345d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x0f, 0);
19355d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
19365d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
19375d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, satn[6]);
19385d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, satn[7]);
19395d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, satn[8]);
19401da177e4SLinus Torvalds 
19415d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
19421da177e4SLinus Torvalds 			cpu_relax();
194380b52a7fSOndrej Zary 
194480b52a7fSOndrej Zary 		if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e)
19451da177e4SLinus Torvalds 			continue;
194680b52a7fSOndrej Zary 
19475d2a5a4fSOndrej Zary 		while (atp_readb_io(dev, c, 0x17) != 0x8e)
19481da177e4SLinus Torvalds 			cpu_relax();
194980b52a7fSOndrej Zary 
19501da177e4SLinus Torvalds try_u3:
19511da177e4SLinus Torvalds 		j = 0;
19525d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x09);
19535d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
19541da177e4SLinus Torvalds 
19555d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) {
19565d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0)
19575d2a5a4fSOndrej Zary 				atp_writeb_io(dev, c, 0x19, u3[j++]);
19581da177e4SLinus Torvalds 			cpu_relax();
19591da177e4SLinus Torvalds 		}
196080b52a7fSOndrej Zary 
19615d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00)
19621da177e4SLinus Torvalds 			cpu_relax();
196380b52a7fSOndrej Zary 
19645d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
19651da177e4SLinus Torvalds 		if (j == 0x0f) {
19661da177e4SLinus Torvalds 			goto u3p_in;
19671da177e4SLinus Torvalds 		}
19681da177e4SLinus Torvalds 		if (j == 0x0a) {
19691da177e4SLinus Torvalds 			goto u3p_cmd;
19701da177e4SLinus Torvalds 		}
19711da177e4SLinus Torvalds 		if (j == 0x0e) {
19721da177e4SLinus Torvalds 			goto try_u3;
19731da177e4SLinus Torvalds 		}
19741da177e4SLinus Torvalds 		continue;
19751da177e4SLinus Torvalds u3p_out:
19765d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
19775d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) {
19785d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0)
19795d2a5a4fSOndrej Zary 				atp_writeb_io(dev, c, 0x19, 0);
19801da177e4SLinus Torvalds 			cpu_relax();
19811da177e4SLinus Torvalds 		}
19825d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
19831da177e4SLinus Torvalds 		if (j == 0x0f) {
19841da177e4SLinus Torvalds 			goto u3p_in;
19851da177e4SLinus Torvalds 		}
19861da177e4SLinus Torvalds 		if (j == 0x0a) {
19871da177e4SLinus Torvalds 			goto u3p_cmd;
19881da177e4SLinus Torvalds 		}
19891da177e4SLinus Torvalds 		if (j == 0x0e) {
19901da177e4SLinus Torvalds 			goto u3p_out;
19911da177e4SLinus Torvalds 		}
19921da177e4SLinus Torvalds 		continue;
19931da177e4SLinus Torvalds u3p_in:
19945d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x09);
19955d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
19961da177e4SLinus Torvalds 		k = 0;
19971da177e4SLinus Torvalds u3p_in1:
19985d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x1f);
19991da177e4SLinus Torvalds 		if ((j & 0x01) != 0) {
20005d2a5a4fSOndrej Zary 			mbuf[k++] = atp_readb_io(dev, c, 0x19);
20011da177e4SLinus Torvalds 			goto u3p_in1;
20021da177e4SLinus Torvalds 		}
20031da177e4SLinus Torvalds 		if ((j & 0x80) == 0x00) {
20041da177e4SLinus Torvalds 			goto u3p_in1;
20051da177e4SLinus Torvalds 		}
20065d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
20071da177e4SLinus Torvalds 		if (j == 0x0f) {
20081da177e4SLinus Torvalds 			goto u3p_in;
20091da177e4SLinus Torvalds 		}
20101da177e4SLinus Torvalds 		if (j == 0x0a) {
20111da177e4SLinus Torvalds 			goto u3p_cmd;
20121da177e4SLinus Torvalds 		}
20131da177e4SLinus Torvalds 		if (j == 0x0e) {
20141da177e4SLinus Torvalds 			goto u3p_out;
20151da177e4SLinus Torvalds 		}
20161da177e4SLinus Torvalds 		continue;
20171da177e4SLinus Torvalds u3p_cmd:
20185d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x10, 0x30);
20195d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x00);
20205d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
202180b52a7fSOndrej Zary 
20225d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00);
202380b52a7fSOndrej Zary 
20245d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
20251da177e4SLinus Torvalds 		if (j != 0x16) {
20261da177e4SLinus Torvalds 			if (j == 0x4e) {
20271da177e4SLinus Torvalds 				goto u3p_out;
20281da177e4SLinus Torvalds 			}
20291da177e4SLinus Torvalds 			continue;
20301da177e4SLinus Torvalds 		}
20311da177e4SLinus Torvalds 		if (mbuf[0] != 0x01) {
20321da177e4SLinus Torvalds 			goto chg_wide;
20331da177e4SLinus Torvalds 		}
20341da177e4SLinus Torvalds 		if (mbuf[1] != 0x06) {
20351da177e4SLinus Torvalds 			goto chg_wide;
20361da177e4SLinus Torvalds 		}
20371da177e4SLinus Torvalds 		if (mbuf[2] != 0x04) {
20381da177e4SLinus Torvalds 			goto chg_wide;
20391da177e4SLinus Torvalds 		}
20401da177e4SLinus Torvalds 		if (mbuf[3] == 0x09) {
20411da177e4SLinus Torvalds 			m = 1;
20421da177e4SLinus Torvalds 			m = m << i;
20431da177e4SLinus Torvalds 			dev->wide_id[c] |= m;
20441da177e4SLinus Torvalds 			dev->id[c][i].devsp = 0xce;
20451da177e4SLinus Torvalds #ifdef ED_DBGP
2046bcd5c59fSHannes Reinecke 			printk("dev->id[%2d][%2d].devsp = %2x\n",
2047bcd5c59fSHannes Reinecke 			       c, i, dev->id[c][i].devsp);
20481da177e4SLinus Torvalds #endif
20491da177e4SLinus Torvalds 			continue;
20501da177e4SLinus Torvalds 		}
20511da177e4SLinus Torvalds chg_wide:
20525d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x1b, 0x01);
20535d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 3, satn[0]);
20545d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 4, satn[1]);
20555d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 5, satn[2]);
20565d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 6, satn[3]);
20575d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 7, satn[4]);
20585d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 8, satn[5]);
20595d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x0f, 0);
20605d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
20615d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
20625d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, satn[6]);
20635d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, satn[7]);
20645d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, satn[8]);
20651da177e4SLinus Torvalds 
20665d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
20671da177e4SLinus Torvalds 			cpu_relax();
206880b52a7fSOndrej Zary 
2069bcd5c59fSHannes Reinecke 		if (atp_readb_io(dev, c, 0x17) != 0x11 &&
2070bcd5c59fSHannes Reinecke 		    atp_readb_io(dev, c, 0x17) != 0x8e)
20711da177e4SLinus Torvalds 			continue;
207280b52a7fSOndrej Zary 
20735d2a5a4fSOndrej Zary 		while (atp_readb_io(dev, c, 0x17) != 0x8e)
20741da177e4SLinus Torvalds 			cpu_relax();
207580b52a7fSOndrej Zary 
20761da177e4SLinus Torvalds try_wide:
20771da177e4SLinus Torvalds 		j = 0;
20785d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x05);
20795d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
20801da177e4SLinus Torvalds 
20815d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) {
20825d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0)
20835d2a5a4fSOndrej Zary 				atp_writeb_io(dev, c, 0x19, wide[j++]);
20841da177e4SLinus Torvalds 			cpu_relax();
20851da177e4SLinus Torvalds 		}
208680b52a7fSOndrej Zary 
20875d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00)
20881da177e4SLinus Torvalds 			cpu_relax();
208980b52a7fSOndrej Zary 
20905d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
20911da177e4SLinus Torvalds 		if (j == 0x0f) {
20921da177e4SLinus Torvalds 			goto widep_in;
20931da177e4SLinus Torvalds 		}
20941da177e4SLinus Torvalds 		if (j == 0x0a) {
20951da177e4SLinus Torvalds 			goto widep_cmd;
20961da177e4SLinus Torvalds 		}
20971da177e4SLinus Torvalds 		if (j == 0x0e) {
20981da177e4SLinus Torvalds 			goto try_wide;
20991da177e4SLinus Torvalds 		}
21001da177e4SLinus Torvalds 		continue;
21011da177e4SLinus Torvalds widep_out:
21025d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
21035d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) {
21045d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0)
21055d2a5a4fSOndrej Zary 				atp_writeb_io(dev, c, 0x19, 0);
21061da177e4SLinus Torvalds 			cpu_relax();
21071da177e4SLinus Torvalds 		}
21085d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
21091da177e4SLinus Torvalds 		if (j == 0x0f) {
21101da177e4SLinus Torvalds 			goto widep_in;
21111da177e4SLinus Torvalds 		}
21121da177e4SLinus Torvalds 		if (j == 0x0a) {
21131da177e4SLinus Torvalds 			goto widep_cmd;
21141da177e4SLinus Torvalds 		}
21151da177e4SLinus Torvalds 		if (j == 0x0e) {
21161da177e4SLinus Torvalds 			goto widep_out;
21171da177e4SLinus Torvalds 		}
21181da177e4SLinus Torvalds 		continue;
21191da177e4SLinus Torvalds widep_in:
21205d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0xff);
21215d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
21221da177e4SLinus Torvalds 		k = 0;
21231da177e4SLinus Torvalds widep_in1:
21245d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x1f);
21251da177e4SLinus Torvalds 		if ((j & 0x01) != 0) {
21265d2a5a4fSOndrej Zary 			mbuf[k++] = atp_readb_io(dev, c, 0x19);
21271da177e4SLinus Torvalds 			goto widep_in1;
21281da177e4SLinus Torvalds 		}
21291da177e4SLinus Torvalds 		if ((j & 0x80) == 0x00) {
21301da177e4SLinus Torvalds 			goto widep_in1;
21311da177e4SLinus Torvalds 		}
21325d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
21331da177e4SLinus Torvalds 		if (j == 0x0f) {
21341da177e4SLinus Torvalds 			goto widep_in;
21351da177e4SLinus Torvalds 		}
21361da177e4SLinus Torvalds 		if (j == 0x0a) {
21371da177e4SLinus Torvalds 			goto widep_cmd;
21381da177e4SLinus Torvalds 		}
21391da177e4SLinus Torvalds 		if (j == 0x0e) {
21401da177e4SLinus Torvalds 			goto widep_out;
21411da177e4SLinus Torvalds 		}
21421da177e4SLinus Torvalds 		continue;
21431da177e4SLinus Torvalds widep_cmd:
21445d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x10, 0x30);
21455d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x00);
21465d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
214780b52a7fSOndrej Zary 
21485d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
21491da177e4SLinus Torvalds 			cpu_relax();
215080b52a7fSOndrej Zary 
21515d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
21521da177e4SLinus Torvalds 		if (j != 0x16) {
21531da177e4SLinus Torvalds 			if (j == 0x4e) {
21541da177e4SLinus Torvalds 				goto widep_out;
21551da177e4SLinus Torvalds 			}
21561da177e4SLinus Torvalds 			continue;
21571da177e4SLinus Torvalds 		}
21581da177e4SLinus Torvalds 		if (mbuf[0] != 0x01) {
21591da177e4SLinus Torvalds 			goto not_wide;
21601da177e4SLinus Torvalds 		}
21611da177e4SLinus Torvalds 		if (mbuf[1] != 0x02) {
21621da177e4SLinus Torvalds 			goto not_wide;
21631da177e4SLinus Torvalds 		}
21641da177e4SLinus Torvalds 		if (mbuf[2] != 0x03) {
21651da177e4SLinus Torvalds 			goto not_wide;
21661da177e4SLinus Torvalds 		}
21671da177e4SLinus Torvalds 		if (mbuf[3] != 0x01) {
21681da177e4SLinus Torvalds 			goto not_wide;
21691da177e4SLinus Torvalds 		}
21701da177e4SLinus Torvalds 		m = 1;
21711da177e4SLinus Torvalds 		m = m << i;
21721da177e4SLinus Torvalds 		dev->wide_id[c] |= m;
21731da177e4SLinus Torvalds not_wide:
2174bcd5c59fSHannes Reinecke 		if ((dev->id[c][i].devtype == 0x00) ||
2175bcd5c59fSHannes Reinecke 		    (dev->id[c][i].devtype == 0x07) ||
2176bcd5c59fSHannes Reinecke 		    ((dev->id[c][i].devtype == 0x05) && ((n & 0x10) != 0))) {
21771da177e4SLinus Torvalds 			m = 1;
21781da177e4SLinus Torvalds 			m = m << i;
21791da177e4SLinus Torvalds 			if ((dev->async[c] & m) != 0) {
21801da177e4SLinus Torvalds 				goto set_sync;
21811da177e4SLinus Torvalds 			}
21821da177e4SLinus Torvalds 		}
21831da177e4SLinus Torvalds 		continue;
21841da177e4SLinus Torvalds set_sync:
2185b922a449SOndrej Zary 		if ((!is885(dev) && !is880(dev)) || (dev->sp[c][i] == 0x02)) {
21861da177e4SLinus Torvalds 			synu[4] = 0x0c;
21871da177e4SLinus Torvalds 			synuw[4] = 0x0c;
21881da177e4SLinus Torvalds 		} else {
21891da177e4SLinus Torvalds 			if (dev->sp[c][i] >= 0x03) {
21901da177e4SLinus Torvalds 				synu[4] = 0x0a;
21911da177e4SLinus Torvalds 				synuw[4] = 0x0a;
21921da177e4SLinus Torvalds 			}
21931da177e4SLinus Torvalds 		}
21941da177e4SLinus Torvalds 		j = 0;
21951da177e4SLinus Torvalds 		if ((m & dev->wide_id[c]) != 0) {
21961da177e4SLinus Torvalds 			j |= 0x01;
21971da177e4SLinus Torvalds 		}
21985d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x1b, j);
21995d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 3, satn[0]);
22005d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 4, satn[1]);
22015d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 5, satn[2]);
22025d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 6, satn[3]);
22035d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 7, satn[4]);
22045d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 8, satn[5]);
22055d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x0f, 0);
22065d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
22075d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
22085d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, satn[6]);
22095d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, satn[7]);
22105d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, satn[8]);
22111da177e4SLinus Torvalds 
22125d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
22131da177e4SLinus Torvalds 			cpu_relax();
221480b52a7fSOndrej Zary 
2215bcd5c59fSHannes Reinecke 		if (atp_readb_io(dev, c, 0x17) != 0x11 &&
2216bcd5c59fSHannes Reinecke 		    atp_readb_io(dev, c, 0x17) != 0x8e)
22171da177e4SLinus Torvalds 			continue;
221880b52a7fSOndrej Zary 
22195d2a5a4fSOndrej Zary 		while (atp_readb_io(dev, c, 0x17) != 0x8e)
22201da177e4SLinus Torvalds 			cpu_relax();
222180b52a7fSOndrej Zary 
22221da177e4SLinus Torvalds try_sync:
22231da177e4SLinus Torvalds 		j = 0;
22245d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x06);
22255d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
22261da177e4SLinus Torvalds 
22275d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) {
22285d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0) {
22291da177e4SLinus Torvalds 				if ((m & dev->wide_id[c]) != 0) {
2230b922a449SOndrej Zary 					if (is885(dev) || is880(dev)) {
22311da177e4SLinus Torvalds 						if ((m & dev->ultra_map[c]) != 0) {
22325d2a5a4fSOndrej Zary 							atp_writeb_io(dev, c, 0x19, synuw[j++]);
22331da177e4SLinus Torvalds 						} else {
22345d2a5a4fSOndrej Zary 							atp_writeb_io(dev, c, 0x19, synw[j++]);
22351da177e4SLinus Torvalds 						}
2236460da918SOndrej Zary 					} else
2237460da918SOndrej Zary 						atp_writeb_io(dev, c, 0x19, synw_870[j++]);
22381da177e4SLinus Torvalds 				} else {
22391da177e4SLinus Torvalds 					if ((m & dev->ultra_map[c]) != 0) {
22405d2a5a4fSOndrej Zary 						atp_writeb_io(dev, c, 0x19, synu[j++]);
22411da177e4SLinus Torvalds 					} else {
22425d2a5a4fSOndrej Zary 						atp_writeb_io(dev, c, 0x19, synn[j++]);
22431da177e4SLinus Torvalds 					}
22441da177e4SLinus Torvalds 				}
22451da177e4SLinus Torvalds 			}
22461da177e4SLinus Torvalds 		}
224780b52a7fSOndrej Zary 
22485d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00)
22491da177e4SLinus Torvalds 			cpu_relax();
225080b52a7fSOndrej Zary 
22515d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
22521da177e4SLinus Torvalds 		if (j == 0x0f) {
22531da177e4SLinus Torvalds 			goto phase_ins;
22541da177e4SLinus Torvalds 		}
22551da177e4SLinus Torvalds 		if (j == 0x0a) {
22561da177e4SLinus Torvalds 			goto phase_cmds;
22571da177e4SLinus Torvalds 		}
22581da177e4SLinus Torvalds 		if (j == 0x0e) {
22591da177e4SLinus Torvalds 			goto try_sync;
22601da177e4SLinus Torvalds 		}
22611da177e4SLinus Torvalds 		continue;
22621da177e4SLinus Torvalds phase_outs:
22635d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
22645d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) {
22655d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0x00)
22665d2a5a4fSOndrej Zary 				atp_writeb_io(dev, c, 0x19, 0x00);
22671da177e4SLinus Torvalds 			cpu_relax();
22681da177e4SLinus Torvalds 		}
22695d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
22701da177e4SLinus Torvalds 		if (j == 0x85) {
22711da177e4SLinus Torvalds 			goto tar_dcons;
22721da177e4SLinus Torvalds 		}
22731da177e4SLinus Torvalds 		j &= 0x0f;
22741da177e4SLinus Torvalds 		if (j == 0x0f) {
22751da177e4SLinus Torvalds 			goto phase_ins;
22761da177e4SLinus Torvalds 		}
22771da177e4SLinus Torvalds 		if (j == 0x0a) {
22781da177e4SLinus Torvalds 			goto phase_cmds;
22791da177e4SLinus Torvalds 		}
22801da177e4SLinus Torvalds 		if (j == 0x0e) {
22811da177e4SLinus Torvalds 			goto phase_outs;
22821da177e4SLinus Torvalds 		}
22831da177e4SLinus Torvalds 		continue;
22841da177e4SLinus Torvalds phase_ins:
2285b922a449SOndrej Zary 		if (is885(dev) || is880(dev))
22865d2a5a4fSOndrej Zary 			atp_writeb_io(dev, c, 0x14, 0x06);
2287460da918SOndrej Zary 		else
2288460da918SOndrej Zary 			atp_writeb_io(dev, c, 0x14, 0xff);
22895d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
22901da177e4SLinus Torvalds 		k = 0;
22911da177e4SLinus Torvalds phase_ins1:
22925d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x1f);
22931da177e4SLinus Torvalds 		if ((j & 0x01) != 0x00) {
22945d2a5a4fSOndrej Zary 			mbuf[k++] = atp_readb_io(dev, c, 0x19);
22951da177e4SLinus Torvalds 			goto phase_ins1;
22961da177e4SLinus Torvalds 		}
22971da177e4SLinus Torvalds 		if ((j & 0x80) == 0x00) {
22981da177e4SLinus Torvalds 			goto phase_ins1;
22991da177e4SLinus Torvalds 		}
230080b52a7fSOndrej Zary 
23015d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00);
230280b52a7fSOndrej Zary 
23035d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
23041da177e4SLinus Torvalds 		if (j == 0x85) {
23051da177e4SLinus Torvalds 			goto tar_dcons;
23061da177e4SLinus Torvalds 		}
23071da177e4SLinus Torvalds 		j &= 0x0f;
23081da177e4SLinus Torvalds 		if (j == 0x0f) {
23091da177e4SLinus Torvalds 			goto phase_ins;
23101da177e4SLinus Torvalds 		}
23111da177e4SLinus Torvalds 		if (j == 0x0a) {
23121da177e4SLinus Torvalds 			goto phase_cmds;
23131da177e4SLinus Torvalds 		}
23141da177e4SLinus Torvalds 		if (j == 0x0e) {
23151da177e4SLinus Torvalds 			goto phase_outs;
23161da177e4SLinus Torvalds 		}
23171da177e4SLinus Torvalds 		continue;
23181da177e4SLinus Torvalds phase_cmds:
23195d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x10, 0x30);
23201da177e4SLinus Torvalds tar_dcons:
23215d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x00);
23225d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
232380b52a7fSOndrej Zary 
23245d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
23251da177e4SLinus Torvalds 			cpu_relax();
232680b52a7fSOndrej Zary 
23275d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
23281da177e4SLinus Torvalds 		if (j != 0x16) {
23291da177e4SLinus Torvalds 			continue;
23301da177e4SLinus Torvalds 		}
23311da177e4SLinus Torvalds 		if (mbuf[0] != 0x01) {
23321da177e4SLinus Torvalds 			continue;
23331da177e4SLinus Torvalds 		}
23341da177e4SLinus Torvalds 		if (mbuf[1] != 0x03) {
23351da177e4SLinus Torvalds 			continue;
23361da177e4SLinus Torvalds 		}
23371da177e4SLinus Torvalds 		if (mbuf[4] == 0x00) {
23381da177e4SLinus Torvalds 			continue;
23391da177e4SLinus Torvalds 		}
23401da177e4SLinus Torvalds 		if (mbuf[3] > 0x64) {
23411da177e4SLinus Torvalds 			continue;
23421da177e4SLinus Torvalds 		}
2343b922a449SOndrej Zary 		if (is885(dev) || is880(dev)) {
23441da177e4SLinus Torvalds 			if (mbuf[4] > 0x0e) {
23451da177e4SLinus Torvalds 				mbuf[4] = 0x0e;
23461da177e4SLinus Torvalds 			}
2347460da918SOndrej Zary 		} else {
2348460da918SOndrej Zary 			if (mbuf[4] > 0x0c) {
2349460da918SOndrej Zary 				mbuf[4] = 0x0c;
2350460da918SOndrej Zary 			}
2351460da918SOndrej Zary 		}
23521da177e4SLinus Torvalds 		dev->id[c][i].devsp = mbuf[4];
2353b922a449SOndrej Zary 		if (is885(dev) || is880(dev))
23541da177e4SLinus Torvalds 			if (mbuf[3] < 0x0c) {
23551da177e4SLinus Torvalds 				j = 0xb0;
23561da177e4SLinus Torvalds 				goto set_syn_ok;
23571da177e4SLinus Torvalds 			}
23581da177e4SLinus Torvalds 		if ((mbuf[3] < 0x0d) && (rmb == 0)) {
23591da177e4SLinus Torvalds 			j = 0xa0;
23601da177e4SLinus Torvalds 			goto set_syn_ok;
23611da177e4SLinus Torvalds 		}
23621da177e4SLinus Torvalds 		if (mbuf[3] < 0x1a) {
23631da177e4SLinus Torvalds 			j = 0x20;
23641da177e4SLinus Torvalds 			goto set_syn_ok;
23651da177e4SLinus Torvalds 		}
23661da177e4SLinus Torvalds 		if (mbuf[3] < 0x33) {
23671da177e4SLinus Torvalds 			j = 0x40;
23681da177e4SLinus Torvalds 			goto set_syn_ok;
23691da177e4SLinus Torvalds 		}
23701da177e4SLinus Torvalds 		if (mbuf[3] < 0x4c) {
23711da177e4SLinus Torvalds 			j = 0x50;
23721da177e4SLinus Torvalds 			goto set_syn_ok;
23731da177e4SLinus Torvalds 		}
23741da177e4SLinus Torvalds 		j = 0x60;
23751da177e4SLinus Torvalds set_syn_ok:
23761da177e4SLinus Torvalds 		dev->id[c][i].devsp = (dev->id[c][i].devsp & 0x0f) | j;
23771da177e4SLinus Torvalds #ifdef ED_DBGP
2378bcd5c59fSHannes Reinecke 		printk("dev->id[%2d][%2d].devsp = %2x\n",
2379bcd5c59fSHannes Reinecke 		       c,i,dev->id[c][i].devsp);
23801da177e4SLinus Torvalds #endif
23811da177e4SLinus Torvalds 	}
23821da177e4SLinus Torvalds }
2383