xref: /openbmc/linux/drivers/scsi/atp870u.c (revision c4ad92bc)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  *  Copyright (C) 1997	Wu Ching Chen
31da177e4SLinus Torvalds  *  2.1.x update (C) 1998  Krzysztof G. Baranowski
4fa195afeSAlan Cox  *  2.5.x update (C) 2002  Red Hat
5fa195afeSAlan Cox  *  2.6.x update (C) 2004  Red Hat
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  * Marcelo Tosatti <marcelo@conectiva.com.br> : SMP fixes
81da177e4SLinus Torvalds  *
91da177e4SLinus Torvalds  * Wu Ching Chen : NULL pointer fixes  2000/06/02
101da177e4SLinus Torvalds  *		   support atp876 chip
111da177e4SLinus Torvalds  *		   enable 32 bit fifo transfer
121da177e4SLinus Torvalds  *		   support cdrom & remove device run ultra speed
131da177e4SLinus Torvalds  *		   fix disconnect bug  2000/12/21
141da177e4SLinus Torvalds  *		   support atp880 chip lvd u160 2001/05/15
151da177e4SLinus Torvalds  *		   fix prd table bug 2001/09/12 (7.1)
161da177e4SLinus Torvalds  *
171da177e4SLinus Torvalds  * atp885 support add by ACARD Hao Ping Lian 2005/01/05
181da177e4SLinus Torvalds  */
191da177e4SLinus Torvalds #include <linux/module.h>
201da177e4SLinus Torvalds #include <linux/init.h>
211da177e4SLinus Torvalds #include <linux/interrupt.h>
221da177e4SLinus Torvalds #include <linux/kernel.h>
231da177e4SLinus Torvalds #include <linux/types.h>
241da177e4SLinus Torvalds #include <linux/string.h>
251da177e4SLinus Torvalds #include <linux/ioport.h>
261da177e4SLinus Torvalds #include <linux/delay.h>
271da177e4SLinus Torvalds #include <linux/proc_fs.h>
281da177e4SLinus Torvalds #include <linux/spinlock.h>
291da177e4SLinus Torvalds #include <linux/pci.h>
301da177e4SLinus Torvalds #include <linux/blkdev.h>
31910638aeSMatthias Gehre #include <linux/dma-mapping.h>
325a0e3ad6STejun Heo #include <linux/slab.h>
331da177e4SLinus Torvalds #include <asm/io.h>
341da177e4SLinus Torvalds 
351da177e4SLinus Torvalds #include <scsi/scsi.h>
361da177e4SLinus Torvalds #include <scsi/scsi_cmnd.h>
371da177e4SLinus Torvalds #include <scsi/scsi_device.h>
381da177e4SLinus Torvalds #include <scsi/scsi_host.h>
391da177e4SLinus Torvalds 
401da177e4SLinus Torvalds #include "atp870u.h"
411da177e4SLinus Torvalds 
421da177e4SLinus Torvalds static struct scsi_host_template atp870u_template;
431da177e4SLinus Torvalds static void send_s870(struct atp_unit *dev,unsigned char c);
444192a40fSOndrej Zary static void atp_is(struct atp_unit *dev, unsigned char c, bool wide_chip, unsigned char lvdmode);
451da177e4SLinus Torvalds 
466a3cebb6SOndrej Zary static inline void atp_writeb_base(struct atp_unit *atp, u8 reg, u8 val)
476a3cebb6SOndrej Zary {
486a3cebb6SOndrej Zary 	outb(val, atp->baseport + reg);
496a3cebb6SOndrej Zary }
506a3cebb6SOndrej Zary 
51d804bb25SOndrej Zary static inline void atp_writew_base(struct atp_unit *atp, u8 reg, u16 val)
52d804bb25SOndrej Zary {
53d804bb25SOndrej Zary 	outw(val, atp->baseport + reg);
54d804bb25SOndrej Zary }
55d804bb25SOndrej Zary 
566a3cebb6SOndrej Zary static inline void atp_writeb_io(struct atp_unit *atp, u8 channel, u8 reg, u8 val)
576a3cebb6SOndrej Zary {
586a3cebb6SOndrej Zary 	outb(val, atp->ioport[channel] + reg);
596a3cebb6SOndrej Zary }
606a3cebb6SOndrej Zary 
616a3cebb6SOndrej Zary static inline void atp_writew_io(struct atp_unit *atp, u8 channel, u8 reg, u16 val)
626a3cebb6SOndrej Zary {
636a3cebb6SOndrej Zary 	outw(val, atp->ioport[channel] + reg);
646a3cebb6SOndrej Zary }
656a3cebb6SOndrej Zary 
666a3cebb6SOndrej Zary static inline void atp_writeb_pci(struct atp_unit *atp, u8 channel, u8 reg, u8 val)
676a3cebb6SOndrej Zary {
686a3cebb6SOndrej Zary 	outb(val, atp->pciport[channel] + reg);
696a3cebb6SOndrej Zary }
706a3cebb6SOndrej Zary 
716a3cebb6SOndrej Zary static inline void atp_writel_pci(struct atp_unit *atp, u8 channel, u8 reg, u32 val)
726a3cebb6SOndrej Zary {
736a3cebb6SOndrej Zary 	outl(val, atp->pciport[channel] + reg);
746a3cebb6SOndrej Zary }
756a3cebb6SOndrej Zary 
766a3cebb6SOndrej Zary static inline u8 atp_readb_base(struct atp_unit *atp, u8 reg)
776a3cebb6SOndrej Zary {
786a3cebb6SOndrej Zary 	return inb(atp->baseport + reg);
796a3cebb6SOndrej Zary }
806a3cebb6SOndrej Zary 
81d804bb25SOndrej Zary static inline u16 atp_readw_base(struct atp_unit *atp, u8 reg)
82d804bb25SOndrej Zary {
83d804bb25SOndrej Zary 	return inw(atp->baseport + reg);
84d804bb25SOndrej Zary }
85d804bb25SOndrej Zary 
86d804bb25SOndrej Zary static inline u32 atp_readl_base(struct atp_unit *atp, u8 reg)
87d804bb25SOndrej Zary {
88d804bb25SOndrej Zary 	return inl(atp->baseport + reg);
89d804bb25SOndrej Zary }
90d804bb25SOndrej Zary 
916a3cebb6SOndrej Zary static inline u8 atp_readb_io(struct atp_unit *atp, u8 channel, u8 reg)
926a3cebb6SOndrej Zary {
936a3cebb6SOndrej Zary 	return inb(atp->ioport[channel] + reg);
946a3cebb6SOndrej Zary }
956a3cebb6SOndrej Zary 
966a3cebb6SOndrej Zary static inline u16 atp_readw_io(struct atp_unit *atp, u8 channel, u8 reg)
976a3cebb6SOndrej Zary {
986a3cebb6SOndrej Zary 	return inw(atp->ioport[channel] + reg);
996a3cebb6SOndrej Zary }
1006a3cebb6SOndrej Zary 
1016a3cebb6SOndrej Zary static inline u8 atp_readb_pci(struct atp_unit *atp, u8 channel, u8 reg)
1026a3cebb6SOndrej Zary {
1036a3cebb6SOndrej Zary 	return inb(atp->pciport[channel] + reg);
1046a3cebb6SOndrej Zary }
1056a3cebb6SOndrej Zary 
1067d12e780SDavid Howells static irqreturn_t atp870u_intr_handle(int irq, void *dev_id)
1071da177e4SLinus Torvalds {
1081da177e4SLinus Torvalds 	unsigned long flags;
109bc0fe4c9SOndrej Zary 	unsigned short int id;
1101da177e4SLinus Torvalds 	unsigned char i, j, c, target_id, lun,cmdp;
1111da177e4SLinus Torvalds 	unsigned char *prd;
1121da177e4SLinus Torvalds 	struct scsi_cmnd *workreq;
1131da177e4SLinus Torvalds 	unsigned long adrcnt, k;
1141da177e4SLinus Torvalds #ifdef ED_DBGP
1151da177e4SLinus Torvalds 	unsigned long l;
1161da177e4SLinus Torvalds #endif
1171da177e4SLinus Torvalds 	struct Scsi_Host *host = dev_id;
1181da177e4SLinus Torvalds 	struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
1191da177e4SLinus Torvalds 
1201da177e4SLinus Torvalds 	for (c = 0; c < 2; c++) {
1216a3cebb6SOndrej Zary 		j = atp_readb_io(dev, c, 0x1f);
1221da177e4SLinus Torvalds 		if ((j & 0x80) != 0)
12378614ecdSOndrej Zary 			break;
1241da177e4SLinus Torvalds 		dev->in_int[c] = 0;
1251da177e4SLinus Torvalds 	}
12678614ecdSOndrej Zary 	if ((j & 0x80) == 0)
1271da177e4SLinus Torvalds 		return IRQ_NONE;
1281da177e4SLinus Torvalds #ifdef ED_DBGP
1291da177e4SLinus Torvalds 	printk("atp870u_intr_handle enter\n");
1301da177e4SLinus Torvalds #endif
1311da177e4SLinus Torvalds 	dev->in_int[c] = 1;
1326a3cebb6SOndrej Zary 	cmdp = atp_readb_io(dev, c, 0x10);
1331da177e4SLinus Torvalds 	if (dev->working[c] != 0) {
1341da177e4SLinus Torvalds 		if (dev->dev_id == ATP885_DEVID) {
1356a3cebb6SOndrej Zary 			if ((atp_readb_io(dev, c, 0x16) & 0x80) == 0)
1366a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x16, (atp_readb_io(dev, c, 0x16) | 0x80));
1371da177e4SLinus Torvalds 		}
1386a3cebb6SOndrej Zary 		if ((atp_readb_pci(dev, c, 0x00) & 0x08) != 0)
1391da177e4SLinus Torvalds 		{
1401da177e4SLinus Torvalds 			for (k=0; k < 1000; k++) {
1416a3cebb6SOndrej Zary 				if ((atp_readb_pci(dev, c, 2) & 0x08) == 0)
14278614ecdSOndrej Zary 					break;
1436a3cebb6SOndrej Zary 				if ((atp_readb_pci(dev, c, 2) & 0x01) == 0)
14478614ecdSOndrej Zary 					break;
1451da177e4SLinus Torvalds 			}
1461da177e4SLinus Torvalds 		}
1476a3cebb6SOndrej Zary 		atp_writeb_pci(dev, c, 0, 0x00);
1481da177e4SLinus Torvalds 
1496a3cebb6SOndrej Zary 		i = atp_readb_io(dev, c, 0x17);
1501da177e4SLinus Torvalds 
151bc0fe4c9SOndrej Zary 		if (dev->dev_id == ATP885_DEVID)
1526a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 2, 0x06);
1531da177e4SLinus Torvalds 
1546a3cebb6SOndrej Zary 		target_id = atp_readb_io(dev, c, 0x15);
1551da177e4SLinus Torvalds 
1561da177e4SLinus Torvalds 		/*
1571da177e4SLinus Torvalds 		 *	Remap wide devices onto id numbers
1581da177e4SLinus Torvalds 		 */
1591da177e4SLinus Torvalds 
1601da177e4SLinus Torvalds 		if ((target_id & 0x40) != 0) {
1611da177e4SLinus Torvalds 			target_id = (target_id & 0x07) | 0x08;
1621da177e4SLinus Torvalds 		} else {
1631da177e4SLinus Torvalds 			target_id &= 0x07;
1641da177e4SLinus Torvalds 		}
1651da177e4SLinus Torvalds 
1661da177e4SLinus Torvalds 		if ((j & 0x40) != 0) {
1671da177e4SLinus Torvalds 		     if (dev->last_cmd[c] == 0xff) {
1681da177e4SLinus Torvalds 			dev->last_cmd[c] = target_id;
1691da177e4SLinus Torvalds 		     }
1701da177e4SLinus Torvalds 		     dev->last_cmd[c] |= 0x40;
1711da177e4SLinus Torvalds 		}
1721da177e4SLinus Torvalds 		if (dev->dev_id == ATP885_DEVID)
1731da177e4SLinus Torvalds 			dev->r1f[c][target_id] |= j;
1741da177e4SLinus Torvalds #ifdef ED_DBGP
1751da177e4SLinus Torvalds 		printk("atp870u_intr_handle status = %x\n",i);
1761da177e4SLinus Torvalds #endif
1771da177e4SLinus Torvalds 		if (i == 0x85) {
1781da177e4SLinus Torvalds 			if ((dev->last_cmd[c] & 0xf0) != 0x40) {
1791da177e4SLinus Torvalds 			   dev->last_cmd[c] = 0xff;
1801da177e4SLinus Torvalds 			}
1811da177e4SLinus Torvalds 			if (dev->dev_id == ATP885_DEVID) {
1821da177e4SLinus Torvalds 				adrcnt = 0;
1836a3cebb6SOndrej Zary 				((unsigned char *) &adrcnt)[2] = atp_readb_io(dev, c, 0x12);
1846a3cebb6SOndrej Zary 				((unsigned char *) &adrcnt)[1] = atp_readb_io(dev, c, 0x13);
1856a3cebb6SOndrej Zary 				((unsigned char *) &adrcnt)[0] = atp_readb_io(dev, c, 0x14);
1861da177e4SLinus Torvalds 				if (dev->id[c][target_id].last_len != adrcnt)
1871da177e4SLinus Torvalds 				{
1881da177e4SLinus Torvalds 			   		k = dev->id[c][target_id].last_len;
1891da177e4SLinus Torvalds 			   		k -= adrcnt;
1901da177e4SLinus Torvalds 			   		dev->id[c][target_id].tran_len = k;
1911da177e4SLinus Torvalds 			   	dev->id[c][target_id].last_len = adrcnt;
1921da177e4SLinus Torvalds 				}
1931da177e4SLinus Torvalds #ifdef ED_DBGP
1943a38e53eSOndrej Zary 				printk("dev->id[c][target_id].last_len = %d dev->id[c][target_id].tran_len = %d\n",dev->id[c][target_id].last_len,dev->id[c][target_id].tran_len);
1951da177e4SLinus Torvalds #endif
1961da177e4SLinus Torvalds 			}
1971da177e4SLinus Torvalds 
1981da177e4SLinus Torvalds 			/*
1991da177e4SLinus Torvalds 			 *      Flip wide
2001da177e4SLinus Torvalds 			 */
2011da177e4SLinus Torvalds 			if (dev->wide_id[c] != 0) {
2026a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x1b, 0x01);
2036a3cebb6SOndrej Zary 				while ((atp_readb_io(dev, c, 0x1b) & 0x01) != 0x01)
2046a3cebb6SOndrej Zary 					atp_writeb_io(dev, c, 0x1b, 0x01);
2051da177e4SLinus Torvalds 			}
2061da177e4SLinus Torvalds 			/*
2071da177e4SLinus Torvalds 			 *	Issue more commands
2081da177e4SLinus Torvalds 			 */
2091da177e4SLinus Torvalds 			spin_lock_irqsave(dev->host->host_lock, flags);
2101da177e4SLinus Torvalds 			if (((dev->quhd[c] != dev->quend[c]) || (dev->last_cmd[c] != 0xff)) &&
2111da177e4SLinus Torvalds 			    (dev->in_snd[c] == 0)) {
2121da177e4SLinus Torvalds #ifdef ED_DBGP
2131da177e4SLinus Torvalds 				printk("Call sent_s870\n");
2141da177e4SLinus Torvalds #endif
2151da177e4SLinus Torvalds 				send_s870(dev,c);
2161da177e4SLinus Torvalds 			}
2171da177e4SLinus Torvalds 			spin_unlock_irqrestore(dev->host->host_lock, flags);
2181da177e4SLinus Torvalds 			/*
2191da177e4SLinus Torvalds 			 *	Done
2201da177e4SLinus Torvalds 			 */
2211da177e4SLinus Torvalds 			dev->in_int[c] = 0;
2221da177e4SLinus Torvalds #ifdef ED_DBGP
2231da177e4SLinus Torvalds 				printk("Status 0x85 return\n");
2241da177e4SLinus Torvalds #endif
22578614ecdSOndrej Zary 			return IRQ_HANDLED;
2261da177e4SLinus Torvalds 		}
2271da177e4SLinus Torvalds 
2281da177e4SLinus Torvalds 		if (i == 0x40) {
2291da177e4SLinus Torvalds 		     dev->last_cmd[c] |= 0x40;
2301da177e4SLinus Torvalds 		     dev->in_int[c] = 0;
23178614ecdSOndrej Zary 		     return IRQ_HANDLED;
2321da177e4SLinus Torvalds 		}
2331da177e4SLinus Torvalds 
2341da177e4SLinus Torvalds 		if (i == 0x21) {
2351da177e4SLinus Torvalds 			if ((dev->last_cmd[c] & 0xf0) != 0x40) {
2361da177e4SLinus Torvalds 			   dev->last_cmd[c] = 0xff;
2371da177e4SLinus Torvalds 			}
2381da177e4SLinus Torvalds 			adrcnt = 0;
2396a3cebb6SOndrej Zary 			((unsigned char *) &adrcnt)[2] = atp_readb_io(dev, c, 0x12);
2406a3cebb6SOndrej Zary 			((unsigned char *) &adrcnt)[1] = atp_readb_io(dev, c, 0x13);
2416a3cebb6SOndrej Zary 			((unsigned char *) &adrcnt)[0] = atp_readb_io(dev, c, 0x14);
2421da177e4SLinus Torvalds 			k = dev->id[c][target_id].last_len;
2431da177e4SLinus Torvalds 			k -= adrcnt;
2441da177e4SLinus Torvalds 			dev->id[c][target_id].tran_len = k;
2451da177e4SLinus Torvalds 			dev->id[c][target_id].last_len = adrcnt;
2466a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x10, 0x41);
2476a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x18, 0x08);
2481da177e4SLinus Torvalds 			dev->in_int[c] = 0;
24978614ecdSOndrej Zary 			return IRQ_HANDLED;
2501da177e4SLinus Torvalds 		}
2511da177e4SLinus Torvalds 
2521da177e4SLinus Torvalds 		if (dev->dev_id == ATP885_DEVID) {
2531da177e4SLinus Torvalds 			if ((i == 0x4c) || (i == 0x4d) || (i == 0x8c) || (i == 0x8d)) {
2541da177e4SLinus Torvalds 		   		if ((i == 0x4c) || (i == 0x8c))
2551da177e4SLinus Torvalds 		      			i=0x48;
2561da177e4SLinus Torvalds 		   		else
2571da177e4SLinus Torvalds 		      			i=0x49;
2581da177e4SLinus Torvalds 		   	}
2591da177e4SLinus Torvalds 
2601da177e4SLinus Torvalds 		}
2611da177e4SLinus Torvalds 		if ((i == 0x80) || (i == 0x8f)) {
2621da177e4SLinus Torvalds #ifdef ED_DBGP
2631da177e4SLinus Torvalds 			printk(KERN_DEBUG "Device reselect\n");
2641da177e4SLinus Torvalds #endif
2651da177e4SLinus Torvalds 			lun = 0;
2666a3cebb6SOndrej Zary 			if (cmdp == 0x44 || i == 0x80)
2676a3cebb6SOndrej Zary 				lun = atp_readb_io(dev, c, 0x1d) & 0x07;
2686a3cebb6SOndrej Zary 			else {
2691da177e4SLinus Torvalds 				if ((dev->last_cmd[c] & 0xf0) != 0x40) {
2701da177e4SLinus Torvalds 				   dev->last_cmd[c] = 0xff;
2711da177e4SLinus Torvalds 				}
2721da177e4SLinus Torvalds 				if (cmdp == 0x41) {
2731da177e4SLinus Torvalds #ifdef ED_DBGP
2741da177e4SLinus Torvalds 					printk("cmdp = 0x41\n");
2751da177e4SLinus Torvalds #endif
2761da177e4SLinus Torvalds 					adrcnt = 0;
2776a3cebb6SOndrej Zary 					((unsigned char *) &adrcnt)[2] = atp_readb_io(dev, c, 0x12);
2786a3cebb6SOndrej Zary 					((unsigned char *) &adrcnt)[1] = atp_readb_io(dev, c, 0x13);
2796a3cebb6SOndrej Zary 					((unsigned char *) &adrcnt)[0] = atp_readb_io(dev, c, 0x14);
2801da177e4SLinus Torvalds 					k = dev->id[c][target_id].last_len;
2811da177e4SLinus Torvalds 					k -= adrcnt;
2821da177e4SLinus Torvalds 					dev->id[c][target_id].tran_len = k;
2831da177e4SLinus Torvalds 					dev->id[c][target_id].last_len = adrcnt;
2846a3cebb6SOndrej Zary 					atp_writeb_io(dev, c, 0x18, 0x08);
2851da177e4SLinus Torvalds 					dev->in_int[c] = 0;
28678614ecdSOndrej Zary 					return IRQ_HANDLED;
2871da177e4SLinus Torvalds 				} else {
2881da177e4SLinus Torvalds #ifdef ED_DBGP
2891da177e4SLinus Torvalds 					printk("cmdp != 0x41\n");
2901da177e4SLinus Torvalds #endif
2916a3cebb6SOndrej Zary 					atp_writeb_io(dev, c, 0x10, 0x46);
2921da177e4SLinus Torvalds 					dev->id[c][target_id].dirct = 0x00;
2936a3cebb6SOndrej Zary 					atp_writeb_io(dev, c, 0x12, 0x00);
2946a3cebb6SOndrej Zary 					atp_writeb_io(dev, c, 0x13, 0x00);
2956a3cebb6SOndrej Zary 					atp_writeb_io(dev, c, 0x14, 0x00);
2966a3cebb6SOndrej Zary 					atp_writeb_io(dev, c, 0x18, 0x08);
2971da177e4SLinus Torvalds 					dev->in_int[c] = 0;
29878614ecdSOndrej Zary 					return IRQ_HANDLED;
2991da177e4SLinus Torvalds 				}
3001da177e4SLinus Torvalds 			}
3011da177e4SLinus Torvalds 			if (dev->last_cmd[c] != 0xff) {
3021da177e4SLinus Torvalds 			   dev->last_cmd[c] |= 0x40;
3031da177e4SLinus Torvalds 			}
3041da177e4SLinus Torvalds 			if (dev->dev_id == ATP885_DEVID) {
3056a3cebb6SOndrej Zary 				j = atp_readb_base(dev, 0x29) & 0xfe;
3066a3cebb6SOndrej Zary 				atp_writeb_base(dev, 0x29, j);
3073a38e53eSOndrej Zary 			} else
3086a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x10, 0x45);
3091da177e4SLinus Torvalds 
3106a3cebb6SOndrej Zary 			target_id = atp_readb_io(dev, c, 0x16);
3111da177e4SLinus Torvalds 			/*
3121da177e4SLinus Torvalds 			 *	Remap wide identifiers
3131da177e4SLinus Torvalds 			 */
3141da177e4SLinus Torvalds 			if ((target_id & 0x10) != 0) {
3151da177e4SLinus Torvalds 				target_id = (target_id & 0x07) | 0x08;
3161da177e4SLinus Torvalds 			} else {
3171da177e4SLinus Torvalds 				target_id &= 0x07;
3181da177e4SLinus Torvalds 			}
3193a38e53eSOndrej Zary 			if (dev->dev_id == ATP885_DEVID)
3206a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x10, 0x45);
3211da177e4SLinus Torvalds 			workreq = dev->id[c][target_id].curr_req;
3221da177e4SLinus Torvalds #ifdef ED_DBGP
323017560fcSJeff Garzik 			scmd_printk(KERN_DEBUG, workreq, "CDB");
3241da177e4SLinus Torvalds 			for (l = 0; l < workreq->cmd_len; l++)
3251da177e4SLinus Torvalds 				printk(KERN_DEBUG " %x",workreq->cmnd[l]);
326017560fcSJeff Garzik 			printk("\n");
3271da177e4SLinus Torvalds #endif
3281da177e4SLinus Torvalds 
3296a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x0f, lun);
3306a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x11, dev->id[c][target_id].devsp);
3311da177e4SLinus Torvalds 			adrcnt = dev->id[c][target_id].tran_len;
3321da177e4SLinus Torvalds 			k = dev->id[c][target_id].last_len;
3331da177e4SLinus Torvalds 
3346a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x12, ((unsigned char *) &k)[2]);
3356a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x13, ((unsigned char *) &k)[1]);
3366a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x14, ((unsigned char *) &k)[0]);
3371da177e4SLinus Torvalds #ifdef ED_DBGP
3386a3cebb6SOndrej Zary 			printk("k %x, k[0] 0x%x k[1] 0x%x k[2] 0x%x\n", k, atp_readb_io(dev, c, 0x14), atp_readb_io(dev, c, 0x13), atp_readb_io(dev, c, 0x12));
3391da177e4SLinus Torvalds #endif
3401da177e4SLinus Torvalds 			/* Remap wide */
3411da177e4SLinus Torvalds 			j = target_id;
3421da177e4SLinus Torvalds 			if (target_id > 7) {
3431da177e4SLinus Torvalds 				j = (j & 0x07) | 0x40;
3441da177e4SLinus Torvalds 			}
3451da177e4SLinus Torvalds 			/* Add direction */
3461da177e4SLinus Torvalds 			j |= dev->id[c][target_id].dirct;
3476a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x15, j);
3486a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x16, 0x80);
3491da177e4SLinus Torvalds 
3501da177e4SLinus Torvalds 			/* enable 32 bit fifo transfer */
3511da177e4SLinus Torvalds 			if (dev->dev_id == ATP885_DEVID) {
3526a3cebb6SOndrej Zary 				i = atp_readb_pci(dev, c, 1) & 0xf3;
3531da177e4SLinus Torvalds 				//j=workreq->cmnd[0];
3541da177e4SLinus Torvalds 				if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
3551da177e4SLinus Torvalds 				   i |= 0x0c;
3561da177e4SLinus Torvalds 				}
3576a3cebb6SOndrej Zary 				atp_writeb_pci(dev, c, 1, i);
3581da177e4SLinus Torvalds 			} else if ((dev->dev_id == ATP880_DEVID1) ||
3591da177e4SLinus Torvalds 	    		    	   (dev->dev_id == ATP880_DEVID2) ) {
3606a3cebb6SOndrej Zary 				if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a))
3616a3cebb6SOndrej Zary 					atp_writeb_base(dev, 0x3b, (atp_readb_base(dev, 0x3b) & 0x3f) | 0xc0);
3626a3cebb6SOndrej Zary 				else
3636a3cebb6SOndrej Zary 					atp_writeb_base(dev, 0x3b, atp_readb_base(dev, 0x3b) & 0x3f);
3641da177e4SLinus Torvalds 			} else {
3656a3cebb6SOndrej Zary 				if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a))
366c751d9f1SOndrej Zary 					atp_writeb_base(dev, 0x3a, (atp_readb_base(dev, 0x3a) & 0xf3) | 0x08);
3676a3cebb6SOndrej Zary 				else
368c751d9f1SOndrej Zary 					atp_writeb_base(dev, 0x3a, atp_readb_base(dev, 0x3a) & 0xf3);
3691da177e4SLinus Torvalds 			}
3701da177e4SLinus Torvalds 			j = 0;
3711da177e4SLinus Torvalds 			id = 1;
3721da177e4SLinus Torvalds 			id = id << target_id;
3731da177e4SLinus Torvalds 			/*
3741da177e4SLinus Torvalds 			 *	Is this a wide device
3751da177e4SLinus Torvalds 			 */
3761da177e4SLinus Torvalds 			if ((id & dev->wide_id[c]) != 0) {
3771da177e4SLinus Torvalds 				j |= 0x01;
3781da177e4SLinus Torvalds 			}
3796a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x1b, j);
3806a3cebb6SOndrej Zary 			while ((atp_readb_io(dev, c, 0x1b) & 0x01) != j)
3816a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x1b, j);
3821da177e4SLinus Torvalds 			if (dev->id[c][target_id].last_len == 0) {
3836a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x18, 0x08);
3841da177e4SLinus Torvalds 				dev->in_int[c] = 0;
3851da177e4SLinus Torvalds #ifdef ED_DBGP
3861da177e4SLinus Torvalds 				printk("dev->id[c][target_id].last_len = 0\n");
3871da177e4SLinus Torvalds #endif
38878614ecdSOndrej Zary 				return IRQ_HANDLED;
3891da177e4SLinus Torvalds 			}
3901da177e4SLinus Torvalds #ifdef ED_DBGP
3911da177e4SLinus Torvalds 			printk("target_id = %d adrcnt = %d\n",target_id,adrcnt);
3921da177e4SLinus Torvalds #endif
3931da177e4SLinus Torvalds 			prd = dev->id[c][target_id].prd_pos;
3941da177e4SLinus Torvalds 			while (adrcnt != 0) {
3951da177e4SLinus Torvalds 				id = ((unsigned short int *)prd)[2];
3961da177e4SLinus Torvalds 				if (id == 0) {
3971da177e4SLinus Torvalds 					k = 0x10000;
3981da177e4SLinus Torvalds 				} else {
3991da177e4SLinus Torvalds 					k = id;
4001da177e4SLinus Torvalds 				}
4011da177e4SLinus Torvalds 				if (k > adrcnt) {
4021da177e4SLinus Torvalds 					((unsigned short int *)prd)[2] = (unsigned short int)
4031da177e4SLinus Torvalds 					    (k - adrcnt);
4041da177e4SLinus Torvalds 					((unsigned long *)prd)[0] += adrcnt;
4051da177e4SLinus Torvalds 					adrcnt = 0;
4061da177e4SLinus Torvalds 					dev->id[c][target_id].prd_pos = prd;
4071da177e4SLinus Torvalds 				} else {
4081da177e4SLinus Torvalds 					adrcnt -= k;
4091da177e4SLinus Torvalds 					dev->id[c][target_id].prdaddr += 0x08;
4101da177e4SLinus Torvalds 					prd += 0x08;
4111da177e4SLinus Torvalds 					if (adrcnt == 0) {
4121da177e4SLinus Torvalds 						dev->id[c][target_id].prd_pos = prd;
4131da177e4SLinus Torvalds 					}
4141da177e4SLinus Torvalds 				}
4151da177e4SLinus Torvalds 			}
4166a3cebb6SOndrej Zary 			atp_writel_pci(dev, c, 0x04, dev->id[c][target_id].prdaddr);
4171da177e4SLinus Torvalds #ifdef ED_DBGP
4181da177e4SLinus Torvalds 			printk("dev->id[%d][%d].prdaddr 0x%8x\n", c, target_id, dev->id[c][target_id].prdaddr);
4191da177e4SLinus Torvalds #endif
420bc0fe4c9SOndrej Zary 			if (dev->dev_id != ATP885_DEVID) {
4216a3cebb6SOndrej Zary 				atp_writeb_pci(dev, c, 2, 0x06);
4226a3cebb6SOndrej Zary 				atp_writeb_pci(dev, c, 2, 0x00);
4231da177e4SLinus Torvalds 			}
4241da177e4SLinus Torvalds 			/*
4251da177e4SLinus Torvalds 			 *	Check transfer direction
4261da177e4SLinus Torvalds 			 */
4271da177e4SLinus Torvalds 			if (dev->id[c][target_id].dirct != 0) {
4286a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x18, 0x08);
4296a3cebb6SOndrej Zary 				atp_writeb_pci(dev, c, 0, 0x01);
4301da177e4SLinus Torvalds 				dev->in_int[c] = 0;
4311da177e4SLinus Torvalds #ifdef ED_DBGP
4321da177e4SLinus Torvalds 				printk("status 0x80 return dirct != 0\n");
4331da177e4SLinus Torvalds #endif
43478614ecdSOndrej Zary 				return IRQ_HANDLED;
4351da177e4SLinus Torvalds 			}
4366a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x18, 0x08);
4376a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 0, 0x09);
4381da177e4SLinus Torvalds 			dev->in_int[c] = 0;
4391da177e4SLinus Torvalds #ifdef ED_DBGP
4401da177e4SLinus Torvalds 			printk("status 0x80 return dirct = 0\n");
4411da177e4SLinus Torvalds #endif
44278614ecdSOndrej Zary 			return IRQ_HANDLED;
4431da177e4SLinus Torvalds 		}
4441da177e4SLinus Torvalds 
4451da177e4SLinus Torvalds 		/*
4461da177e4SLinus Torvalds 		 *	Current scsi request on this target
4471da177e4SLinus Torvalds 		 */
4481da177e4SLinus Torvalds 
4491da177e4SLinus Torvalds 		workreq = dev->id[c][target_id].curr_req;
4501da177e4SLinus Torvalds 
45178614ecdSOndrej Zary 		if (i == 0x42 || i == 0x16) {
4521da177e4SLinus Torvalds 			if ((dev->last_cmd[c] & 0xf0) != 0x40) {
4531da177e4SLinus Torvalds 			   dev->last_cmd[c] = 0xff;
4541da177e4SLinus Torvalds 			}
45578614ecdSOndrej Zary 			if (i == 0x16) {
4566a3cebb6SOndrej Zary 				workreq->result = atp_readb_io(dev, c, 0x0f);
4571da177e4SLinus Torvalds 				if (((dev->r1f[c][target_id] & 0x10) != 0)&&(dev->dev_id==ATP885_DEVID)) {
4581da177e4SLinus Torvalds 					printk(KERN_WARNING "AEC67162 CRC ERROR !\n");
45978614ecdSOndrej Zary 					workreq->result = 0x02;
4601da177e4SLinus Torvalds 				}
46178614ecdSOndrej Zary 			} else
46278614ecdSOndrej Zary 				workreq->result = 0x02;
46378614ecdSOndrej Zary 
4641da177e4SLinus Torvalds 			if (dev->dev_id == ATP885_DEVID) {
4656a3cebb6SOndrej Zary 				j = atp_readb_base(dev, 0x29) | 0x01;
4666a3cebb6SOndrej Zary 				atp_writeb_base(dev, 0x29, j);
4671da177e4SLinus Torvalds 			}
4681da177e4SLinus Torvalds 			/*
4691da177e4SLinus Torvalds 			 *	Complete the command
4701da177e4SLinus Torvalds 			 */
471fe7ed98fSBoaz Harrosh 			scsi_dma_unmap(workreq);
472fe7ed98fSBoaz Harrosh 
4731da177e4SLinus Torvalds 			spin_lock_irqsave(dev->host->host_lock, flags);
4741da177e4SLinus Torvalds 			(*workreq->scsi_done) (workreq);
4751da177e4SLinus Torvalds #ifdef ED_DBGP
4761da177e4SLinus Torvalds 			   printk("workreq->scsi_done\n");
4771da177e4SLinus Torvalds #endif
4781da177e4SLinus Torvalds 			/*
4791da177e4SLinus Torvalds 			 *	Clear it off the queue
4801da177e4SLinus Torvalds 			 */
4811da177e4SLinus Torvalds 			dev->id[c][target_id].curr_req = NULL;
4821da177e4SLinus Torvalds 			dev->working[c]--;
4831da177e4SLinus Torvalds 			spin_unlock_irqrestore(dev->host->host_lock, flags);
4841da177e4SLinus Torvalds 			/*
4851da177e4SLinus Torvalds 			 *      Take it back wide
4861da177e4SLinus Torvalds 			 */
4871da177e4SLinus Torvalds 			if (dev->wide_id[c] != 0) {
4886a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x1b, 0x01);
4896a3cebb6SOndrej Zary 				while ((atp_readb_io(dev, c, 0x1b) & 0x01) != 0x01)
4906a3cebb6SOndrej Zary 					atp_writeb_io(dev, c, 0x1b, 0x01);
4911da177e4SLinus Torvalds 			}
4921da177e4SLinus Torvalds 			/*
4931da177e4SLinus Torvalds 			 *	If there is stuff to send and nothing going then send it
4941da177e4SLinus Torvalds 			 */
4951da177e4SLinus Torvalds 			spin_lock_irqsave(dev->host->host_lock, flags);
4961da177e4SLinus Torvalds 			if (((dev->last_cmd[c] != 0xff) || (dev->quhd[c] != dev->quend[c])) &&
4971da177e4SLinus Torvalds 			    (dev->in_snd[c] == 0)) {
4981da177e4SLinus Torvalds #ifdef ED_DBGP
4991da177e4SLinus Torvalds 			   printk("Call sent_s870(scsi_done)\n");
5001da177e4SLinus Torvalds #endif
5011da177e4SLinus Torvalds 			   send_s870(dev,c);
5021da177e4SLinus Torvalds 			}
5031da177e4SLinus Torvalds 			spin_unlock_irqrestore(dev->host->host_lock, flags);
5041da177e4SLinus Torvalds 			dev->in_int[c] = 0;
50578614ecdSOndrej Zary 			return IRQ_HANDLED;
5061da177e4SLinus Torvalds 		}
5071da177e4SLinus Torvalds 		if ((dev->last_cmd[c] & 0xf0) != 0x40) {
5081da177e4SLinus Torvalds 		   dev->last_cmd[c] = 0xff;
5091da177e4SLinus Torvalds 		}
5101da177e4SLinus Torvalds 		if (i == 0x4f) {
5111da177e4SLinus Torvalds 			i = 0x89;
5121da177e4SLinus Torvalds 		}
5131da177e4SLinus Torvalds 		i &= 0x0f;
5141da177e4SLinus Torvalds 		if (i == 0x09) {
5156a3cebb6SOndrej Zary 			atp_writel_pci(dev, c, 4, dev->id[c][target_id].prdaddr);
5166a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 2, 0x06);
5176a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 2, 0x00);
5186a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x10, 0x41);
5191da177e4SLinus Torvalds 			if (dev->dev_id == ATP885_DEVID) {
5201da177e4SLinus Torvalds 				k = dev->id[c][target_id].last_len;
5216a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x12, ((unsigned char *) (&k))[2]);
5226a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x13, ((unsigned char *) (&k))[1]);
5236a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x14, ((unsigned char *) (&k))[0]);
5241da177e4SLinus Torvalds 				dev->id[c][target_id].dirct = 0x00;
5251da177e4SLinus Torvalds 			} else {
5261da177e4SLinus Torvalds 				dev->id[c][target_id].dirct = 0x00;
5271da177e4SLinus Torvalds 			}
5286a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x18, 0x08);
5296a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 0, 0x09);
5301da177e4SLinus Torvalds 			dev->in_int[c] = 0;
53178614ecdSOndrej Zary 			return IRQ_HANDLED;
5321da177e4SLinus Torvalds 		}
5331da177e4SLinus Torvalds 		if (i == 0x08) {
5346a3cebb6SOndrej Zary 			atp_writel_pci(dev, c, 4, dev->id[c][target_id].prdaddr);
5356a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 2, 0x06);
5366a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 2, 0x00);
5376a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x10, 0x41);
5381da177e4SLinus Torvalds 			if (dev->dev_id == ATP885_DEVID) {
5391da177e4SLinus Torvalds 				k = dev->id[c][target_id].last_len;
5406a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x12, ((unsigned char *) (&k))[2]);
5416a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x13, ((unsigned char *) (&k))[1]);
5426a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x14, ((unsigned char *) (&k))[0]);
5431da177e4SLinus Torvalds 			}
5446a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x15, atp_readb_io(dev, c, 0x15) | 0x20);
5451da177e4SLinus Torvalds 			dev->id[c][target_id].dirct = 0x20;
5466a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x18, 0x08);
5476a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 0, 0x01);
5481da177e4SLinus Torvalds 			dev->in_int[c] = 0;
54978614ecdSOndrej Zary 			return IRQ_HANDLED;
5501da177e4SLinus Torvalds 		}
5516a3cebb6SOndrej Zary 		if (i == 0x0a)
5526a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x10, 0x30);
5536a3cebb6SOndrej Zary 		else
5546a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x10, 0x46);
5551da177e4SLinus Torvalds 		dev->id[c][target_id].dirct = 0x00;
5566a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0x00);
5576a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x13, 0x00);
5586a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x00);
5596a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
5601da177e4SLinus Torvalds 	}
56178614ecdSOndrej Zary 	dev->in_int[c] = 0;
5621da177e4SLinus Torvalds 
5631da177e4SLinus Torvalds 	return IRQ_HANDLED;
5641da177e4SLinus Torvalds }
5651da177e4SLinus Torvalds /**
5661da177e4SLinus Torvalds  *	atp870u_queuecommand	-	Queue SCSI command
5671da177e4SLinus Torvalds  *	@req_p: request block
5681da177e4SLinus Torvalds  *	@done: completion function
5691da177e4SLinus Torvalds  *
5701da177e4SLinus Torvalds  *	Queue a command to the ATP queue. Called with the host lock held.
5711da177e4SLinus Torvalds  */
572f281233dSJeff Garzik static int atp870u_queuecommand_lck(struct scsi_cmnd *req_p,
5731da177e4SLinus Torvalds 			 void (*done) (struct scsi_cmnd *))
5741da177e4SLinus Torvalds {
5751da177e4SLinus Torvalds 	unsigned char c;
5763b836464SOndrej Zary 	unsigned int m;
5771da177e4SLinus Torvalds 	struct atp_unit *dev;
5781da177e4SLinus Torvalds 	struct Scsi_Host *host;
5791da177e4SLinus Torvalds 
580422c0d61SJeff Garzik 	c = scmd_channel(req_p);
5811da177e4SLinus Torvalds 	req_p->sense_buffer[0]=0;
582fe7ed98fSBoaz Harrosh 	scsi_set_resid(req_p, 0);
583422c0d61SJeff Garzik 	if (scmd_channel(req_p) > 1) {
5841da177e4SLinus Torvalds 		req_p->result = 0x00040000;
5851da177e4SLinus Torvalds 		done(req_p);
5861da177e4SLinus Torvalds #ifdef ED_DBGP
5871da177e4SLinus Torvalds 		printk("atp870u_queuecommand : req_p->device->channel > 1\n");
5881da177e4SLinus Torvalds #endif
5891da177e4SLinus Torvalds 		return 0;
5901da177e4SLinus Torvalds 	}
5911da177e4SLinus Torvalds 
5921da177e4SLinus Torvalds 	host = req_p->device->host;
5931da177e4SLinus Torvalds 	dev = (struct atp_unit *)&host->hostdata;
5941da177e4SLinus Torvalds 
5951da177e4SLinus Torvalds 
5961da177e4SLinus Torvalds 
5971da177e4SLinus Torvalds 	m = 1;
598422c0d61SJeff Garzik 	m = m << scmd_id(req_p);
5991da177e4SLinus Torvalds 
6001da177e4SLinus Torvalds 	/*
6011da177e4SLinus Torvalds 	 *      Fake a timeout for missing targets
6021da177e4SLinus Torvalds 	 */
6031da177e4SLinus Torvalds 
6041da177e4SLinus Torvalds 	if ((m & dev->active_id[c]) == 0) {
6051da177e4SLinus Torvalds 		req_p->result = 0x00040000;
6061da177e4SLinus Torvalds 		done(req_p);
6071da177e4SLinus Torvalds 		return 0;
6081da177e4SLinus Torvalds 	}
6091da177e4SLinus Torvalds 
6101da177e4SLinus Torvalds 	if (done) {
6111da177e4SLinus Torvalds 		req_p->scsi_done = done;
6121da177e4SLinus Torvalds 	} else {
6131da177e4SLinus Torvalds #ifdef ED_DBGP
6141da177e4SLinus Torvalds 		printk( "atp870u_queuecommand: done can't be NULL\n");
6151da177e4SLinus Torvalds #endif
6161da177e4SLinus Torvalds 		req_p->result = 0;
6171da177e4SLinus Torvalds 		done(req_p);
6181da177e4SLinus Torvalds 		return 0;
6191da177e4SLinus Torvalds 	}
6201da177e4SLinus Torvalds 
6211da177e4SLinus Torvalds 	/*
6221da177e4SLinus Torvalds 	 *	Count new command
6231da177e4SLinus Torvalds 	 */
6241da177e4SLinus Torvalds 	dev->quend[c]++;
6251da177e4SLinus Torvalds 	if (dev->quend[c] >= qcnt) {
6261da177e4SLinus Torvalds 		dev->quend[c] = 0;
6271da177e4SLinus Torvalds 	}
6281da177e4SLinus Torvalds 
6291da177e4SLinus Torvalds 	/*
6301da177e4SLinus Torvalds 	 *	Check queue state
6311da177e4SLinus Torvalds 	 */
6321da177e4SLinus Torvalds 	if (dev->quhd[c] == dev->quend[c]) {
6331da177e4SLinus Torvalds 		if (dev->quend[c] == 0) {
6341da177e4SLinus Torvalds 			dev->quend[c] = qcnt;
6351da177e4SLinus Torvalds 		}
6361da177e4SLinus Torvalds #ifdef ED_DBGP
6371da177e4SLinus Torvalds 		printk("atp870u_queuecommand : dev->quhd[c] == dev->quend[c]\n");
6381da177e4SLinus Torvalds #endif
6391da177e4SLinus Torvalds 		dev->quend[c]--;
6401da177e4SLinus Torvalds 		req_p->result = 0x00020000;
6411da177e4SLinus Torvalds 		done(req_p);
6421da177e4SLinus Torvalds 		return 0;
6431da177e4SLinus Torvalds 	}
6441da177e4SLinus Torvalds 	dev->quereq[c][dev->quend[c]] = req_p;
6451da177e4SLinus Torvalds #ifdef ED_DBGP
6466a3cebb6SOndrej Zary 	printk("dev->ioport[c] = %x atp_readb_io(dev, c, 0x1c) = %x dev->in_int[%d] = %d dev->in_snd[%d] = %d\n",dev->ioport[c],atp_readb_io(dev, c, 0x1c),c,dev->in_int[c],c,dev->in_snd[c]);
6471da177e4SLinus Torvalds #endif
6486a3cebb6SOndrej Zary 	if ((atp_readb_io(dev, c, 0x1c) == 0) && (dev->in_int[c] == 0) && (dev->in_snd[c] == 0)) {
6491da177e4SLinus Torvalds #ifdef ED_DBGP
6501da177e4SLinus Torvalds 		printk("Call sent_s870(atp870u_queuecommand)\n");
6511da177e4SLinus Torvalds #endif
6521da177e4SLinus Torvalds 		send_s870(dev,c);
6531da177e4SLinus Torvalds 	}
6541da177e4SLinus Torvalds #ifdef ED_DBGP
6551da177e4SLinus Torvalds 	printk("atp870u_queuecommand : exit\n");
6561da177e4SLinus Torvalds #endif
6571da177e4SLinus Torvalds 	return 0;
6581da177e4SLinus Torvalds }
6591da177e4SLinus Torvalds 
660f281233dSJeff Garzik static DEF_SCSI_QCMD(atp870u_queuecommand)
661f281233dSJeff Garzik 
6621da177e4SLinus Torvalds /**
6631da177e4SLinus Torvalds  *	send_s870	-	send a command to the controller
6641da177e4SLinus Torvalds  *	@host: host
6651da177e4SLinus Torvalds  *
6661da177e4SLinus Torvalds  *	On entry there is work queued to be done. We move some of that work to the
6671da177e4SLinus Torvalds  *	controller itself.
6681da177e4SLinus Torvalds  *
6691da177e4SLinus Torvalds  *	Caller holds the host lock.
6701da177e4SLinus Torvalds  */
6711da177e4SLinus Torvalds static void send_s870(struct atp_unit *dev,unsigned char c)
6721da177e4SLinus Torvalds {
673468b8968SOndrej Zary 	struct scsi_cmnd *workreq = NULL;
6741da177e4SLinus Torvalds 	unsigned int i;//,k;
6751da177e4SLinus Torvalds 	unsigned char  j, target_id;
6761da177e4SLinus Torvalds 	unsigned char *prd;
677c2bab403SOndrej Zary 	unsigned short int w;
6781da177e4SLinus Torvalds 	unsigned long l, bttl = 0;
6791da177e4SLinus Torvalds 	unsigned long  sg_count;
6801da177e4SLinus Torvalds 
6811da177e4SLinus Torvalds 	if (dev->in_snd[c] != 0) {
6821da177e4SLinus Torvalds #ifdef ED_DBGP
6831da177e4SLinus Torvalds 		printk("cmnd in_snd\n");
6841da177e4SLinus Torvalds #endif
6851da177e4SLinus Torvalds 		return;
6861da177e4SLinus Torvalds 	}
6871da177e4SLinus Torvalds #ifdef ED_DBGP
6881da177e4SLinus Torvalds 	printk("Sent_s870 enter\n");
6891da177e4SLinus Torvalds #endif
6901da177e4SLinus Torvalds 	dev->in_snd[c] = 1;
6911da177e4SLinus Torvalds 	if ((dev->last_cmd[c] != 0xff) && ((dev->last_cmd[c] & 0x40) != 0)) {
6921da177e4SLinus Torvalds 		dev->last_cmd[c] &= 0x0f;
6931da177e4SLinus Torvalds 		workreq = dev->id[c][dev->last_cmd[c]].curr_req;
694468b8968SOndrej Zary 		if (!workreq) {
6951da177e4SLinus Torvalds 			dev->last_cmd[c] = 0xff;
6961da177e4SLinus Torvalds 			if (dev->quhd[c] == dev->quend[c]) {
6971da177e4SLinus Torvalds 				dev->in_snd[c] = 0;
6981da177e4SLinus Torvalds 				return;
6991da177e4SLinus Torvalds 			}
7001da177e4SLinus Torvalds 		}
701468b8968SOndrej Zary 	}
702468b8968SOndrej Zary 	if (!workreq) {
7031da177e4SLinus Torvalds 		if ((dev->last_cmd[c] != 0xff) && (dev->working[c] != 0)) {
7041da177e4SLinus Torvalds 			dev->in_snd[c] = 0;
7051da177e4SLinus Torvalds 			return;
7061da177e4SLinus Torvalds 		}
7071da177e4SLinus Torvalds 		dev->working[c]++;
7081da177e4SLinus Torvalds 		j = dev->quhd[c];
7091da177e4SLinus Torvalds 		dev->quhd[c]++;
710468b8968SOndrej Zary 		if (dev->quhd[c] >= qcnt)
7111da177e4SLinus Torvalds 			dev->quhd[c] = 0;
7121da177e4SLinus Torvalds 		workreq = dev->quereq[c][dev->quhd[c]];
713468b8968SOndrej Zary 		if (dev->id[c][scmd_id(workreq)].curr_req != NULL) {
7141da177e4SLinus Torvalds 			dev->quhd[c] = j;
7151da177e4SLinus Torvalds 			dev->working[c]--;
7161da177e4SLinus Torvalds 			dev->in_snd[c] = 0;
7171da177e4SLinus Torvalds 			return;
7181da177e4SLinus Torvalds 		}
719468b8968SOndrej Zary 		dev->id[c][scmd_id(workreq)].curr_req = workreq;
720468b8968SOndrej Zary 		dev->last_cmd[c] = scmd_id(workreq);
7211da177e4SLinus Torvalds 	}
7226a3cebb6SOndrej Zary 	if ((atp_readb_io(dev, c, 0x1f) & 0xb0) != 0 || atp_readb_io(dev, c, 0x1c) != 0) {
7231da177e4SLinus Torvalds #ifdef ED_DBGP
7241da177e4SLinus Torvalds 		printk("Abort to Send\n");
7251da177e4SLinus Torvalds #endif
7261da177e4SLinus Torvalds 		dev->last_cmd[c] |= 0x40;
7271da177e4SLinus Torvalds 		dev->in_snd[c] = 0;
7281da177e4SLinus Torvalds 		return;
729468b8968SOndrej Zary 	}
7301da177e4SLinus Torvalds #ifdef ED_DBGP
7311da177e4SLinus Torvalds 	printk("OK to Send\n");
732422c0d61SJeff Garzik 	scmd_printk(KERN_DEBUG, workreq, "CDB");
7331da177e4SLinus Torvalds 	for(i=0;i<workreq->cmd_len;i++) {
7341da177e4SLinus Torvalds 		printk(" %x",workreq->cmnd[i]);
7351da177e4SLinus Torvalds 	}
736422c0d61SJeff Garzik 	printk("\n");
7371da177e4SLinus Torvalds #endif
738fe7ed98fSBoaz Harrosh 	l = scsi_bufflen(workreq);
739fe7ed98fSBoaz Harrosh 
7401da177e4SLinus Torvalds 	if (dev->dev_id == ATP885_DEVID) {
7416a3cebb6SOndrej Zary 		j = atp_readb_base(dev, 0x29) & 0xfe;
7426a3cebb6SOndrej Zary 		atp_writeb_base(dev, 0x29, j);
743422c0d61SJeff Garzik 		dev->r1f[c][scmd_id(workreq)] = 0;
7441da177e4SLinus Torvalds 	}
7451da177e4SLinus Torvalds 
7461da177e4SLinus Torvalds 	if (workreq->cmnd[0] == READ_CAPACITY) {
747fe7ed98fSBoaz Harrosh 		if (l > 8)
748fe7ed98fSBoaz Harrosh 			l = 8;
7491da177e4SLinus Torvalds 	}
7501da177e4SLinus Torvalds 	if (workreq->cmnd[0] == 0x00) {
751fe7ed98fSBoaz Harrosh 		l = 0;
7521da177e4SLinus Torvalds 	}
7531da177e4SLinus Torvalds 
7541da177e4SLinus Torvalds 	j = 0;
755422c0d61SJeff Garzik 	target_id = scmd_id(workreq);
7561da177e4SLinus Torvalds 
7571da177e4SLinus Torvalds 	/*
7581da177e4SLinus Torvalds 	 *	Wide ?
7591da177e4SLinus Torvalds 	 */
7601da177e4SLinus Torvalds 	w = 1;
7611da177e4SLinus Torvalds 	w = w << target_id;
7621da177e4SLinus Torvalds 	if ((w & dev->wide_id[c]) != 0) {
7631da177e4SLinus Torvalds 		j |= 0x01;
7641da177e4SLinus Torvalds 	}
7656a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x1b, j);
7666a3cebb6SOndrej Zary 	while ((atp_readb_io(dev, c, 0x1b) & 0x01) != j) {
7676a3cebb6SOndrej Zary 		atp_writeb_pci(dev, c, 0x1b, j);
7681da177e4SLinus Torvalds #ifdef ED_DBGP
7691da177e4SLinus Torvalds 		printk("send_s870 while loop 1\n");
7701da177e4SLinus Torvalds #endif
7711da177e4SLinus Torvalds 	}
7721da177e4SLinus Torvalds 	/*
7731da177e4SLinus Torvalds 	 *	Write the command
7741da177e4SLinus Torvalds 	 */
7751da177e4SLinus Torvalds 
7766a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x00, workreq->cmd_len);
7776a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x01, 0x2c);
7786a3cebb6SOndrej Zary 	if (dev->dev_id == ATP885_DEVID)
7796a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x02, 0x7f);
7806a3cebb6SOndrej Zary 	else
7816a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x02, 0xcf);
7826a3cebb6SOndrej Zary 	for (i = 0; i < workreq->cmd_len; i++)
7836a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x03 + i, workreq->cmnd[i]);
7846a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x0f, workreq->device->lun);
7851da177e4SLinus Torvalds 	/*
7861da177e4SLinus Torvalds 	 *	Write the target
7871da177e4SLinus Torvalds 	 */
7886a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x11, dev->id[c][target_id].devsp);
7891da177e4SLinus Torvalds #ifdef ED_DBGP
7901da177e4SLinus Torvalds 	printk("dev->id[%d][%d].devsp = %2x\n",c,target_id,dev->id[c][target_id].devsp);
7911da177e4SLinus Torvalds #endif
7921da177e4SLinus Torvalds 
793fe7ed98fSBoaz Harrosh 	sg_count = scsi_dma_map(workreq);
7941da177e4SLinus Torvalds 	/*
7951da177e4SLinus Torvalds 	 *	Write transfer size
7961da177e4SLinus Torvalds 	 */
7976a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x12, ((unsigned char *) (&l))[2]);
7986a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x13, ((unsigned char *) (&l))[1]);
7996a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x14, ((unsigned char *) (&l))[0]);
8001da177e4SLinus Torvalds 	j = target_id;
8011da177e4SLinus Torvalds 	dev->id[c][j].last_len = l;
8021da177e4SLinus Torvalds 	dev->id[c][j].tran_len = 0;
8031da177e4SLinus Torvalds #ifdef ED_DBGP
8041da177e4SLinus Torvalds 	printk("dev->id[%2d][%2d].last_len = %d\n",c,j,dev->id[c][j].last_len);
8051da177e4SLinus Torvalds #endif
8061da177e4SLinus Torvalds 	/*
8071da177e4SLinus Torvalds 	 *	Flip the wide bits
8081da177e4SLinus Torvalds 	 */
8091da177e4SLinus Torvalds 	if ((j & 0x08) != 0) {
8101da177e4SLinus Torvalds 		j = (j & 0x07) | 0x40;
8111da177e4SLinus Torvalds 	}
8121da177e4SLinus Torvalds 	/*
8131da177e4SLinus Torvalds 	 *	Check transfer direction
8141da177e4SLinus Torvalds 	 */
8156a3cebb6SOndrej Zary 	if (workreq->sc_data_direction == DMA_TO_DEVICE)
8166a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x15, j | 0x20);
8176a3cebb6SOndrej Zary 	else
8186a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x15, j);
8196a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x16, atp_readb_io(dev, c, 0x16) | 0x80);
8206a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x16, 0x80);
8211da177e4SLinus Torvalds 	dev->id[c][target_id].dirct = 0;
8221da177e4SLinus Torvalds 	if (l == 0) {
8236a3cebb6SOndrej Zary 		if (atp_readb_io(dev, c, 0x1c) == 0) {
8241da177e4SLinus Torvalds #ifdef ED_DBGP
8251da177e4SLinus Torvalds 			printk("change SCSI_CMD_REG 0x08\n");
8261da177e4SLinus Torvalds #endif
8276a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x18, 0x08);
8286a3cebb6SOndrej Zary 		} else
8291da177e4SLinus Torvalds 			dev->last_cmd[c] |= 0x40;
8301da177e4SLinus Torvalds 		dev->in_snd[c] = 0;
8311da177e4SLinus Torvalds 		return;
8321da177e4SLinus Torvalds 	}
8331da177e4SLinus Torvalds 	prd = dev->id[c][target_id].prd_table;
8341da177e4SLinus Torvalds 	dev->id[c][target_id].prd_pos = prd;
8351da177e4SLinus Torvalds 
8361da177e4SLinus Torvalds 	/*
8371da177e4SLinus Torvalds 	 *	Now write the request list. Either as scatter/gather or as
8381da177e4SLinus Torvalds 	 *	a linear chain.
8391da177e4SLinus Torvalds 	 */
8401da177e4SLinus Torvalds 
841fe7ed98fSBoaz Harrosh 	if (l) {
842fe7ed98fSBoaz Harrosh 		struct scatterlist *sgpnt;
8431da177e4SLinus Torvalds 		i = 0;
844fe7ed98fSBoaz Harrosh 		scsi_for_each_sg(workreq, sgpnt, sg_count, j) {
845fe7ed98fSBoaz Harrosh 			bttl = sg_dma_address(sgpnt);
846fe7ed98fSBoaz Harrosh 			l=sg_dma_len(sgpnt);
8471da177e4SLinus Torvalds #ifdef ED_DBGP
8481da177e4SLinus Torvalds 			printk("1. bttl %x, l %x\n",bttl, l);
8491da177e4SLinus Torvalds #endif
8501da177e4SLinus Torvalds 			while (l > 0x10000) {
8511da177e4SLinus Torvalds 				(((u16 *) (prd))[i + 3]) = 0x0000;
8521da177e4SLinus Torvalds 				(((u16 *) (prd))[i + 2]) = 0x0000;
8531da177e4SLinus Torvalds 				(((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
8541da177e4SLinus Torvalds 				l -= 0x10000;
8551da177e4SLinus Torvalds 				bttl += 0x10000;
8561da177e4SLinus Torvalds 				i += 0x04;
8571da177e4SLinus Torvalds 			}
8581da177e4SLinus Torvalds 			(((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
8591da177e4SLinus Torvalds 			(((u16 *) (prd))[i + 2]) = cpu_to_le16(l);
8601da177e4SLinus Torvalds 			(((u16 *) (prd))[i + 3]) = 0;
8611da177e4SLinus Torvalds 			i += 0x04;
8621da177e4SLinus Torvalds 		}
8631da177e4SLinus Torvalds 		(((u16 *) (prd))[i - 1]) = cpu_to_le16(0x8000);
8641da177e4SLinus Torvalds #ifdef ED_DBGP
8651da177e4SLinus Torvalds 		printk("prd %4x %4x %4x %4x\n",(((unsigned short int *)prd)[0]),(((unsigned short int *)prd)[1]),(((unsigned short int *)prd)[2]),(((unsigned short int *)prd)[3]));
8661da177e4SLinus Torvalds 		printk("2. bttl %x, l %x\n",bttl, l);
8671da177e4SLinus Torvalds #endif
8681da177e4SLinus Torvalds 	}
8691da177e4SLinus Torvalds #ifdef ED_DBGP
870c2bab403SOndrej Zary 	printk("send_s870: prdaddr_2 0x%8x target_id %d\n", dev->id[c][target_id].prdaddr,target_id);
8711da177e4SLinus Torvalds #endif
872b5683557SJames Bottomley 	dev->id[c][target_id].prdaddr = dev->id[c][target_id].prd_bus;
8736a3cebb6SOndrej Zary 	atp_writel_pci(dev, c, 4, dev->id[c][target_id].prdaddr);
8746a3cebb6SOndrej Zary 	atp_writeb_pci(dev, c, 2, 0x06);
8756a3cebb6SOndrej Zary 	atp_writeb_pci(dev, c, 2, 0x00);
8761da177e4SLinus Torvalds 	if (dev->dev_id == ATP885_DEVID) {
8776a3cebb6SOndrej Zary 		j = atp_readb_pci(dev, c, 1) & 0xf3;
8781da177e4SLinus Torvalds 		if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) ||
8791da177e4SLinus Torvalds 	    	(workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
8801da177e4SLinus Torvalds 	   		j |= 0x0c;
8811da177e4SLinus Torvalds 		}
8826a3cebb6SOndrej Zary 		atp_writeb_pci(dev, c, 1, j);
8831da177e4SLinus Torvalds 	} else if ((dev->dev_id == ATP880_DEVID1) ||
8841da177e4SLinus Torvalds 	    	   (dev->dev_id == ATP880_DEVID2)) {
8856a3cebb6SOndrej Zary 		if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a))
8866a3cebb6SOndrej Zary 			atp_writeb_base(dev, 0x3b, (atp_readb_base(dev, 0x3b) & 0x3f) | 0xc0);
8876a3cebb6SOndrej Zary 		else
8886a3cebb6SOndrej Zary 			atp_writeb_base(dev, 0x3b, atp_readb_base(dev, 0x3b) & 0x3f);
8891da177e4SLinus Torvalds 	} else {
8906a3cebb6SOndrej Zary 		if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a))
891c751d9f1SOndrej Zary 			atp_writeb_base(dev, 0x3a, (atp_readb_base(dev, 0x3a) & 0xf3) | 0x08);
8926a3cebb6SOndrej Zary 		else
893c751d9f1SOndrej Zary 			atp_writeb_base(dev, 0x3a, atp_readb_base(dev, 0x3a) & 0xf3);
8941da177e4SLinus Torvalds 	}
8951da177e4SLinus Torvalds 
8961da177e4SLinus Torvalds 	if(workreq->sc_data_direction == DMA_TO_DEVICE) {
8971da177e4SLinus Torvalds 		dev->id[c][target_id].dirct = 0x20;
8986a3cebb6SOndrej Zary 		if (atp_readb_io(dev, c, 0x1c) == 0) {
8996a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x18, 0x08);
9006a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 0, 0x01);
9011da177e4SLinus Torvalds #ifdef ED_DBGP
9021da177e4SLinus Torvalds 		printk( "start DMA(to target)\n");
9031da177e4SLinus Torvalds #endif
9041da177e4SLinus Torvalds 		} else {
9051da177e4SLinus Torvalds 			dev->last_cmd[c] |= 0x40;
9061da177e4SLinus Torvalds 		}
9071da177e4SLinus Torvalds 		dev->in_snd[c] = 0;
9081da177e4SLinus Torvalds 		return;
9091da177e4SLinus Torvalds 	}
9106a3cebb6SOndrej Zary 	if (atp_readb_io(dev, c, 0x1c) == 0) {
9116a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
9126a3cebb6SOndrej Zary 		atp_writeb_pci(dev, c, 0, 0x09);
9131da177e4SLinus Torvalds #ifdef ED_DBGP
9141da177e4SLinus Torvalds 		printk( "start DMA(to host)\n");
9151da177e4SLinus Torvalds #endif
9161da177e4SLinus Torvalds 	} else {
9171da177e4SLinus Torvalds 		dev->last_cmd[c] |= 0x40;
9181da177e4SLinus Torvalds 	}
9191da177e4SLinus Torvalds 	dev->in_snd[c] = 0;
9201da177e4SLinus Torvalds 	return;
9211da177e4SLinus Torvalds 
9221da177e4SLinus Torvalds }
9231da177e4SLinus Torvalds 
9241da177e4SLinus Torvalds static unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val)
9251da177e4SLinus Torvalds {
9261da177e4SLinus Torvalds 	unsigned short int i, k;
9271da177e4SLinus Torvalds 	unsigned char j;
9281da177e4SLinus Torvalds 
9296a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, *val);
9301da177e4SLinus Torvalds 	for (i = 0; i < 10; i++) {	/* stable >= bus settle delay(400 ns)  */
9316a3cebb6SOndrej Zary 		k = atp_readw_io(dev, 0, 0x1c);
9321da177e4SLinus Torvalds 		j = (unsigned char) (k >> 8);
933832e9ac6SOndrej Zary 		if ((k & 0x8000) != 0)	/* DB7 all release?    */
934832e9ac6SOndrej Zary 			i = 0;
9351da177e4SLinus Torvalds 	}
9361da177e4SLinus Torvalds 	*val |= 0x4000;		/* assert DB6           */
9376a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, *val);
9381da177e4SLinus Torvalds 	*val &= 0xdfff;		/* assert DB5           */
9396a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, *val);
9401da177e4SLinus Torvalds 	for (i = 0; i < 10; i++) {	/* stable >= bus settle delay(400 ns) */
9416a3cebb6SOndrej Zary 		if ((atp_readw_io(dev, 0, 0x1c) & 0x2000) != 0)	/* DB5 all release?       */
942832e9ac6SOndrej Zary 			i = 0;
9431da177e4SLinus Torvalds 	}
9441da177e4SLinus Torvalds 	*val |= 0x8000;		/* no DB4-0, assert DB7    */
9451da177e4SLinus Torvalds 	*val &= 0xe0ff;
9466a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, *val);
9471da177e4SLinus Torvalds 	*val &= 0xbfff;		/* release DB6             */
9486a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, *val);
9491da177e4SLinus Torvalds 	for (i = 0; i < 10; i++) {	/* stable >= bus settle delay(400 ns)  */
9506a3cebb6SOndrej Zary 		if ((atp_readw_io(dev, 0, 0x1c) & 0x4000) != 0)	/* DB6 all release?  */
951832e9ac6SOndrej Zary 			i = 0;
9521da177e4SLinus Torvalds 	}
9531da177e4SLinus Torvalds 
9541da177e4SLinus Torvalds 	return j;
9551da177e4SLinus Torvalds }
9561da177e4SLinus Torvalds 
9571da177e4SLinus Torvalds static void tscam(struct Scsi_Host *host)
9581da177e4SLinus Torvalds {
9591da177e4SLinus Torvalds 
9601da177e4SLinus Torvalds 	unsigned char i, j, k;
9611da177e4SLinus Torvalds 	unsigned long n;
9621da177e4SLinus Torvalds 	unsigned short int m, assignid_map, val;
9631da177e4SLinus Torvalds 	unsigned char mbuf[33], quintet[2];
9641da177e4SLinus Torvalds 	struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
9651da177e4SLinus Torvalds 	static unsigned char g2q_tab[8] = {
9661da177e4SLinus Torvalds 		0x38, 0x31, 0x32, 0x2b, 0x34, 0x2d, 0x2e, 0x27
9671da177e4SLinus Torvalds 	};
9681da177e4SLinus Torvalds 
9691da177e4SLinus Torvalds /*  I can't believe we need this before we've even done anything.  Remove it
9701da177e4SLinus Torvalds  *  and see if anyone bitches.
9711da177e4SLinus Torvalds 	for (i = 0; i < 0x10; i++) {
9721da177e4SLinus Torvalds 		udelay(0xffff);
9731da177e4SLinus Torvalds 	}
9741da177e4SLinus Torvalds  */
9751da177e4SLinus Torvalds 
9766a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 1, 0x08);
9776a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 2, 0x7f);
9786a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x11, 0x20);
9791da177e4SLinus Torvalds 
9801da177e4SLinus Torvalds 	if ((dev->scam_on & 0x40) == 0) {
9811da177e4SLinus Torvalds 		return;
9821da177e4SLinus Torvalds 	}
9831da177e4SLinus Torvalds 	m = 1;
9841da177e4SLinus Torvalds 	m <<= dev->host_id[0];
9851da177e4SLinus Torvalds 	j = 16;
9861da177e4SLinus Torvalds 	if (dev->chip_ver < 4) {
9871da177e4SLinus Torvalds 		m |= 0xff00;
9881da177e4SLinus Torvalds 		j = 8;
9891da177e4SLinus Torvalds 	}
9901da177e4SLinus Torvalds 	assignid_map = m;
9916a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x02, 0x02);	/* 2*2=4ms,3EH 2/32*3E=3.9ms */
9926a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x03, 0);
9936a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x04, 0);
9946a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x05, 0);
9956a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x06, 0);
9966a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x07, 0);
9976a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x08, 0);
9981da177e4SLinus Torvalds 
9991da177e4SLinus Torvalds 	for (i = 0; i < j; i++) {
10001da177e4SLinus Torvalds 		m = 1;
10011da177e4SLinus Torvalds 		m = m << i;
10021da177e4SLinus Torvalds 		if ((m & assignid_map) != 0) {
10031da177e4SLinus Torvalds 			continue;
10041da177e4SLinus Torvalds 		}
10056a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x0f, 0);
10066a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x12, 0);
10076a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x13, 0);
10086a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x14, 0);
10091da177e4SLinus Torvalds 		if (i > 7) {
10101da177e4SLinus Torvalds 			k = (i & 0x07) | 0x40;
10111da177e4SLinus Torvalds 		} else {
10121da177e4SLinus Torvalds 			k = i;
10131da177e4SLinus Torvalds 		}
10146a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x15, k);
10156a3cebb6SOndrej Zary 		if (dev->chip_ver == 4)
10166a3cebb6SOndrej Zary 			atp_writeb_io(dev, 0, 0x1b, 0x01);
10176a3cebb6SOndrej Zary 		else
10186a3cebb6SOndrej Zary 			atp_writeb_io(dev, 0, 0x1b, 0x00);
101958c4d046SOndrej Zary 		do {
10206a3cebb6SOndrej Zary 			atp_writeb_io(dev, 0, 0x18, 0x09);
10211da177e4SLinus Torvalds 
10226a3cebb6SOndrej Zary 			while ((atp_readb_io(dev, 0, 0x1f) & 0x80) == 0x00)
10231da177e4SLinus Torvalds 				cpu_relax();
10246a3cebb6SOndrej Zary 			k = atp_readb_io(dev, 0, 0x17);
102558c4d046SOndrej Zary 			if ((k == 0x85) || (k == 0x42))
102658c4d046SOndrej Zary 				break;
102758c4d046SOndrej Zary 			if (k != 0x16)
10286a3cebb6SOndrej Zary 				atp_writeb_io(dev, 0, 0x10, 0x41);
102958c4d046SOndrej Zary 		} while (k != 0x16);
103058c4d046SOndrej Zary 		if ((k == 0x85) || (k == 0x42))
103158c4d046SOndrej Zary 			continue;
10321da177e4SLinus Torvalds 		assignid_map |= m;
10331da177e4SLinus Torvalds 
10341da177e4SLinus Torvalds 	}
10356a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x02, 0x7f);
10366a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x1b, 0x02);
10371da177e4SLinus Torvalds 
10382bbbac45SOndrej Zary 	udelay(2);
10391da177e4SLinus Torvalds 
10401da177e4SLinus Torvalds 	val = 0x0080;		/* bsy  */
10416a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, val);
10421da177e4SLinus Torvalds 	val |= 0x0040;		/* sel  */
10436a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, val);
10441da177e4SLinus Torvalds 	val |= 0x0004;		/* msg  */
10456a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, val);
10462bbbac45SOndrej Zary 	udelay(2);		/* 2 deskew delay(45ns*2=90ns) */
10471da177e4SLinus Torvalds 	val &= 0x007f;		/* no bsy  */
10486a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, val);
10491da177e4SLinus Torvalds 	mdelay(128);
10501da177e4SLinus Torvalds 	val &= 0x00fb;		/* after 1ms no msg */
10516a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, val);
10526a3cebb6SOndrej Zary 	while ((atp_readb_io(dev, 0, 0x1c) & 0x04) != 0)
105358c4d046SOndrej Zary 		;
10542bbbac45SOndrej Zary 	udelay(2);
10551da177e4SLinus Torvalds 	udelay(100);
1056c7fcc089SOndrej Zary 	for (n = 0; n < 0x30000; n++)
10576a3cebb6SOndrej Zary 		if ((atp_readb_io(dev, 0, 0x1c) & 0x80) != 0)	/* bsy ? */
1058c7fcc089SOndrej Zary 			break;
1059c7fcc089SOndrej Zary 	if (n < 0x30000)
1060c7fcc089SOndrej Zary 		for (n = 0; n < 0x30000; n++)
10616a3cebb6SOndrej Zary 			if ((atp_readb_io(dev, 0, 0x1c) & 0x81) == 0x0081) {
10622bbbac45SOndrej Zary 				udelay(2);
10631da177e4SLinus Torvalds 				val |= 0x8003;		/* io,cd,db7  */
10646a3cebb6SOndrej Zary 				atp_writew_io(dev, 0, 0x1c, val);
10652bbbac45SOndrej Zary 				udelay(2);
10661da177e4SLinus Torvalds 				val &= 0x00bf;		/* no sel     */
10676a3cebb6SOndrej Zary 				atp_writew_io(dev, 0, 0x1c, val);
10682bbbac45SOndrej Zary 				udelay(2);
1069c7fcc089SOndrej Zary 				break;
1070c7fcc089SOndrej Zary 			}
1071c7fcc089SOndrej Zary 	while (1) {
10720f6d93aaSMartin Michlmayr 	/*
10730f6d93aaSMartin Michlmayr 	 * The funny division into multiple delays is to accomodate
10740f6d93aaSMartin Michlmayr 	 * arches like ARM where udelay() multiplies its argument by
10750f6d93aaSMartin Michlmayr 	 * a large number to initialize a loop counter.  To avoid
10760f6d93aaSMartin Michlmayr 	 * overflow, the maximum supported udelay is 2000 microseconds.
10770f6d93aaSMartin Michlmayr 	 *
10780f6d93aaSMartin Michlmayr 	 * XXX it would be more polite to find a way to use msleep()
10790f6d93aaSMartin Michlmayr 	 */
10800f6d93aaSMartin Michlmayr 	mdelay(2);
10810f6d93aaSMartin Michlmayr 	udelay(48);
10826a3cebb6SOndrej Zary 	if ((atp_readb_io(dev, 0, 0x1c) & 0x80) == 0x00) {	/* bsy ? */
10836a3cebb6SOndrej Zary 		atp_writew_io(dev, 0, 0x1c, 0);
10846a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x1b, 0);
10856a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x15, 0);
10866a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x18, 0x09);
10876a3cebb6SOndrej Zary 		while ((atp_readb_io(dev, 0, 0x1f) & 0x80) == 0)
10881da177e4SLinus Torvalds 			cpu_relax();
10896a3cebb6SOndrej Zary 		atp_readb_io(dev, 0, 0x17);
10901da177e4SLinus Torvalds 		return;
10911da177e4SLinus Torvalds 	}
10921da177e4SLinus Torvalds 	val &= 0x00ff;		/* synchronization  */
10931da177e4SLinus Torvalds 	val |= 0x3f00;
10941da177e4SLinus Torvalds 	fun_scam(dev, &val);
10952bbbac45SOndrej Zary 	udelay(2);
10961da177e4SLinus Torvalds 	val &= 0x00ff;		/* isolation        */
10971da177e4SLinus Torvalds 	val |= 0x2000;
10981da177e4SLinus Torvalds 	fun_scam(dev, &val);
10992bbbac45SOndrej Zary 	udelay(2);
11001da177e4SLinus Torvalds 	i = 8;
11011da177e4SLinus Torvalds 	j = 0;
1102c7fcc089SOndrej Zary 
1103c7fcc089SOndrej Zary 	while (1) {
11046a3cebb6SOndrej Zary 		if ((atp_readw_io(dev, 0, 0x1c) & 0x2000) == 0)
1105c7fcc089SOndrej Zary 			continue;
11062bbbac45SOndrej Zary 		udelay(2);
11071da177e4SLinus Torvalds 		val &= 0x00ff;		/* get ID_STRING */
11081da177e4SLinus Torvalds 		val |= 0x2000;
11091da177e4SLinus Torvalds 		k = fun_scam(dev, &val);
1110c7fcc089SOndrej Zary 		if ((k & 0x03) == 0)
1111c7fcc089SOndrej Zary 			break;
11121da177e4SLinus Torvalds 		mbuf[j] <<= 0x01;
11131da177e4SLinus Torvalds 		mbuf[j] &= 0xfe;
1114c7fcc089SOndrej Zary 		if ((k & 0x02) != 0)
11151da177e4SLinus Torvalds 			mbuf[j] |= 0x01;
11161da177e4SLinus Torvalds 		i--;
1117c7fcc089SOndrej Zary 		if (i > 0)
1118c7fcc089SOndrej Zary 			continue;
11191da177e4SLinus Torvalds 		j++;
11201da177e4SLinus Torvalds 		i = 8;
1121c7fcc089SOndrej Zary 	}
11221da177e4SLinus Torvalds 
1123c7fcc089SOndrej Zary 	/* isolation complete..  */
11241da177e4SLinus Torvalds /*    mbuf[32]=0;
11251da177e4SLinus Torvalds 	printk(" \n%x %x %x %s\n ",assignid_map,mbuf[0],mbuf[1],&mbuf[2]); */
11261da177e4SLinus Torvalds 	i = 15;
11271da177e4SLinus Torvalds 	j = mbuf[0];
11281da177e4SLinus Torvalds 	if ((j & 0x20) != 0) {	/* bit5=1:ID up to 7      */
11291da177e4SLinus Torvalds 		i = 7;
11301da177e4SLinus Torvalds 	}
1131c7fcc089SOndrej Zary 	if ((j & 0x06) != 0) {	/* IDvalid?             */
11321da177e4SLinus Torvalds 		k = mbuf[1];
1133c7fcc089SOndrej Zary 		while (1) {
11341da177e4SLinus Torvalds 			m = 1;
11351da177e4SLinus Torvalds 			m <<= k;
1136c7fcc089SOndrej Zary 			if ((m & assignid_map) == 0)
1137c7fcc089SOndrej Zary 				break;
1138c7fcc089SOndrej Zary 			if (k > 0)
11391da177e4SLinus Torvalds 				k--;
1140c7fcc089SOndrej Zary 			else
1141c7fcc089SOndrej Zary 				break;
11421da177e4SLinus Torvalds 		}
1143c7fcc089SOndrej Zary 	}
1144c7fcc089SOndrej Zary 	if ((m & assignid_map) != 0) {	/* srch from max acceptable ID#  */
11451da177e4SLinus Torvalds 		k = i;			/* max acceptable ID#            */
1146c7fcc089SOndrej Zary 		while (1) {
11471da177e4SLinus Torvalds 			m = 1;
11481da177e4SLinus Torvalds 			m <<= k;
1149c7fcc089SOndrej Zary 			if ((m & assignid_map) == 0)
1150c7fcc089SOndrej Zary 				break;
1151c7fcc089SOndrej Zary 			if (k > 0)
11521da177e4SLinus Torvalds 				k--;
1153c7fcc089SOndrej Zary 			else
1154c7fcc089SOndrej Zary 				break;
11551da177e4SLinus Torvalds 		}
1156c7fcc089SOndrej Zary 	}
1157c7fcc089SOndrej Zary 	/* k=binID#,       */
11581da177e4SLinus Torvalds 	assignid_map |= m;
11591da177e4SLinus Torvalds 	if (k < 8) {
11601da177e4SLinus Torvalds 		quintet[0] = 0x38;	/* 1st dft ID<8    */
11611da177e4SLinus Torvalds 	} else {
11621da177e4SLinus Torvalds 		quintet[0] = 0x31;	/* 1st  ID>=8      */
11631da177e4SLinus Torvalds 	}
11641da177e4SLinus Torvalds 	k &= 0x07;
11651da177e4SLinus Torvalds 	quintet[1] = g2q_tab[k];
11661da177e4SLinus Torvalds 
11671da177e4SLinus Torvalds 	val &= 0x00ff;		/* AssignID 1stQuintet,AH=001xxxxx  */
11681da177e4SLinus Torvalds 	m = quintet[0] << 8;
11691da177e4SLinus Torvalds 	val |= m;
11701da177e4SLinus Torvalds 	fun_scam(dev, &val);
11711da177e4SLinus Torvalds 	val &= 0x00ff;		/* AssignID 2ndQuintet,AH=001xxxxx */
11721da177e4SLinus Torvalds 	m = quintet[1] << 8;
11731da177e4SLinus Torvalds 	val |= m;
11741da177e4SLinus Torvalds 	fun_scam(dev, &val);
11751da177e4SLinus Torvalds 
1176c7fcc089SOndrej Zary 	}
11771da177e4SLinus Torvalds }
11781da177e4SLinus Torvalds 
11791da177e4SLinus Torvalds static void atp870u_free_tables(struct Scsi_Host *host)
11801da177e4SLinus Torvalds {
11811da177e4SLinus Torvalds 	struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata;
11821da177e4SLinus Torvalds 	int j, k;
11831da177e4SLinus Torvalds 	for (j=0; j < 2; j++) {
11841da177e4SLinus Torvalds 		for (k = 0; k < 16; k++) {
11851da177e4SLinus Torvalds 			if (!atp_dev->id[j][k].prd_table)
11861da177e4SLinus Torvalds 				continue;
1187b5683557SJames Bottomley 			pci_free_consistent(atp_dev->pdev, 1024, atp_dev->id[j][k].prd_table, atp_dev->id[j][k].prd_bus);
11881da177e4SLinus Torvalds 			atp_dev->id[j][k].prd_table = NULL;
11891da177e4SLinus Torvalds 		}
11901da177e4SLinus Torvalds 	}
11911da177e4SLinus Torvalds }
11921da177e4SLinus Torvalds 
11931da177e4SLinus Torvalds static int atp870u_init_tables(struct Scsi_Host *host)
11941da177e4SLinus Torvalds {
11951da177e4SLinus Torvalds 	struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata;
11961da177e4SLinus Torvalds 	int c,k;
11971da177e4SLinus Torvalds 	for(c=0;c < 2;c++) {
11981da177e4SLinus Torvalds 	   	for(k=0;k<16;k++) {
1199b5683557SJames Bottomley 	   			atp_dev->id[c][k].prd_table = pci_alloc_consistent(atp_dev->pdev, 1024, &(atp_dev->id[c][k].prd_bus));
12001da177e4SLinus Torvalds 	   			if (!atp_dev->id[c][k].prd_table) {
12011da177e4SLinus Torvalds 	   				printk("atp870u_init_tables fail\n");
12021da177e4SLinus Torvalds 				atp870u_free_tables(host);
12031da177e4SLinus Torvalds 				return -ENOMEM;
12041da177e4SLinus Torvalds 			}
1205b5683557SJames Bottomley 			atp_dev->id[c][k].prdaddr = atp_dev->id[c][k].prd_bus;
12061da177e4SLinus Torvalds 			atp_dev->id[c][k].devsp=0x20;
12071da177e4SLinus Torvalds 			atp_dev->id[c][k].devtype = 0x7f;
12081da177e4SLinus Torvalds 			atp_dev->id[c][k].curr_req = NULL;
12091da177e4SLinus Torvalds 	   	}
12101da177e4SLinus Torvalds 
12111da177e4SLinus Torvalds 	   	atp_dev->active_id[c] = 0;
12121da177e4SLinus Torvalds 	   	atp_dev->wide_id[c] = 0;
12131da177e4SLinus Torvalds 	   	atp_dev->host_id[c] = 0x07;
12141da177e4SLinus Torvalds 	   	atp_dev->quhd[c] = 0;
12151da177e4SLinus Torvalds 	   	atp_dev->quend[c] = 0;
12161da177e4SLinus Torvalds 	   	atp_dev->last_cmd[c] = 0xff;
12171da177e4SLinus Torvalds 	   	atp_dev->in_snd[c] = 0;
12181da177e4SLinus Torvalds 	   	atp_dev->in_int[c] = 0;
12191da177e4SLinus Torvalds 
12201da177e4SLinus Torvalds 	   	for (k = 0; k < qcnt; k++) {
12211da177e4SLinus Torvalds 	   		  atp_dev->quereq[c][k] = NULL;
12221da177e4SLinus Torvalds 	   	}
12231da177e4SLinus Torvalds 	   	for (k = 0; k < 16; k++) {
12241da177e4SLinus Torvalds 			   atp_dev->id[c][k].curr_req = NULL;
12251da177e4SLinus Torvalds 			   atp_dev->sp[c][k] = 0x04;
12261da177e4SLinus Torvalds 	   	}
12271da177e4SLinus Torvalds 	}
12281da177e4SLinus Torvalds 	return 0;
12291da177e4SLinus Torvalds }
12301da177e4SLinus Torvalds 
12316a1961bcSOndrej Zary static void atp_set_host_id(struct atp_unit *atp, u8 c, u8 host_id)
12326a1961bcSOndrej Zary {
12336a1961bcSOndrej Zary 	atp_writeb_io(atp, c, 0, host_id | 0x08);
12346a1961bcSOndrej Zary 	atp_writeb_io(atp, c, 0x18, 0);
12356a1961bcSOndrej Zary 	while ((atp_readb_io(atp, c, 0x1f) & 0x80) == 0)
12366a1961bcSOndrej Zary 		mdelay(1);
12376a1961bcSOndrej Zary 	atp_readb_io(atp, c, 0x17);
12386a1961bcSOndrej Zary 	atp_writeb_io(atp, c, 1, 8);
12396a1961bcSOndrej Zary 	atp_writeb_io(atp, c, 2, 0x7f);
12406a1961bcSOndrej Zary 	atp_writeb_io(atp, c, 0x11, 0x20);
12416a1961bcSOndrej Zary }
12426a1961bcSOndrej Zary 
12431da177e4SLinus Torvalds /* return non-zero on detection */
12441da177e4SLinus Torvalds static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
12451da177e4SLinus Torvalds {
12461da177e4SLinus Torvalds 	unsigned char k, m, c;
12471da177e4SLinus Torvalds 	unsigned long flags;
1248493c5201SOndrej Zary 	unsigned int base_io, error,n;
12491da177e4SLinus Torvalds 	unsigned char host_id;
12501da177e4SLinus Torvalds 	struct Scsi_Host *shpnt = NULL;
1251dc6a78f1SRandy Dunlap 	struct atp_unit *atpdev, *p;
12521da177e4SLinus Torvalds 	unsigned char setupdata[2][16];
12531da177e4SLinus Torvalds 	int count = 0;
12541da177e4SLinus Torvalds 
1255dc6a78f1SRandy Dunlap 	atpdev = kzalloc(sizeof(*atpdev), GFP_KERNEL);
1256dc6a78f1SRandy Dunlap 	if (!atpdev)
1257dc6a78f1SRandy Dunlap 		return -ENOMEM;
1258dc6a78f1SRandy Dunlap 
12591da177e4SLinus Torvalds 	if (pci_enable_device(pdev))
1260dc6a78f1SRandy Dunlap 		goto err_eio;
12611da177e4SLinus Torvalds 
126234a2c35dSOndrej Zary 	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
12631da177e4SLinus Torvalds                 printk(KERN_ERR "atp870u: DMA mask required but not available.\n");
1264dc6a78f1SRandy Dunlap 		goto err_eio;
12651da177e4SLinus Torvalds         }
12661da177e4SLinus Torvalds 
12671da177e4SLinus Torvalds 	/*
12681da177e4SLinus Torvalds 	 * It's probably easier to weed out some revisions like
12691da177e4SLinus Torvalds 	 * this than via the PCI device table
12701da177e4SLinus Torvalds 	 */
12711da177e4SLinus Torvalds 	if (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610) {
12727d7311c4SSergei Shtylyov 		atpdev->chip_ver = pdev->revision;
1273dc6a78f1SRandy Dunlap 		if (atpdev->chip_ver < 2)
1274dc6a78f1SRandy Dunlap 			goto err_eio;
12751da177e4SLinus Torvalds 	}
12761da177e4SLinus Torvalds 
12771da177e4SLinus Torvalds 	switch (ent->device) {
12781da177e4SLinus Torvalds 	case PCI_DEVICE_ID_ARTOP_AEC7612UW:
12791da177e4SLinus Torvalds 	case PCI_DEVICE_ID_ARTOP_AEC7612SUW:
12801da177e4SLinus Torvalds 	case ATP880_DEVID1:
12811da177e4SLinus Torvalds 	case ATP880_DEVID2:
12821da177e4SLinus Torvalds 	case ATP885_DEVID:
1283dc6a78f1SRandy Dunlap 		atpdev->chip_ver = 0x04;
12841da177e4SLinus Torvalds 	default:
12851da177e4SLinus Torvalds 		break;
12861da177e4SLinus Torvalds 	}
12871da177e4SLinus Torvalds 	base_io = pci_resource_start(pdev, 0);
12881da177e4SLinus Torvalds 	base_io &= 0xfffffff8;
12896a3cebb6SOndrej Zary 	atpdev->baseport = base_io;
12901da177e4SLinus Torvalds 
12911da177e4SLinus Torvalds 	if ((ent->device == ATP880_DEVID1)||(ent->device == ATP880_DEVID2)) {
12927d7311c4SSergei Shtylyov 		atpdev->chip_ver = pdev->revision;
12931da177e4SLinus Torvalds 		pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80);//JCC082803
12941da177e4SLinus Torvalds 
1295d804bb25SOndrej Zary 		atpdev->ioport[0] = base_io + 0x40;
1296d804bb25SOndrej Zary 		atpdev->pciport[0] = base_io + 0x28;
1297d804bb25SOndrej Zary 
1298d804bb25SOndrej Zary 		host_id = atp_readb_base(atpdev, 0x39);
12991da177e4SLinus Torvalds 		host_id >>= 0x04;
13001da177e4SLinus Torvalds 
13011da177e4SLinus Torvalds 		printk(KERN_INFO "   ACARD AEC-67160 PCI Ultra3 LVD Host Adapter: %d"
13021da177e4SLinus Torvalds 			"    IO:%x, IRQ:%d.\n", count, base_io, pdev->irq);
1303dc6a78f1SRandy Dunlap 		atpdev->dev_id = ent->device;
1304dc6a78f1SRandy Dunlap 		atpdev->host_id[0] = host_id;
13051da177e4SLinus Torvalds 
1306d804bb25SOndrej Zary 		atpdev->scam_on = atp_readb_base(atpdev, 0x22);
1307d804bb25SOndrej Zary 		atpdev->global_map[0] = atp_readb_base(atpdev, 0x35);
1308d804bb25SOndrej Zary 		atpdev->ultra_map[0] = atp_readw_base(atpdev, 0x3c);
13091da177e4SLinus Torvalds 
13101da177e4SLinus Torvalds 		n = 0x3f09;
13111da177e4SLinus Torvalds next_fblk_880:
13121da177e4SLinus Torvalds 		if (n >= 0x4000)
13131da177e4SLinus Torvalds 			goto flash_ok_880;
13141da177e4SLinus Torvalds 
13151da177e4SLinus Torvalds 		m = 0;
1316d804bb25SOndrej Zary 		atp_writew_base(atpdev, 0x34, n);
13171da177e4SLinus Torvalds 		n += 0x0002;
1318d804bb25SOndrej Zary 		if (atp_readb_base(atpdev, 0x30) == 0xff)
13191da177e4SLinus Torvalds 			goto flash_ok_880;
13201da177e4SLinus Torvalds 
1321d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30);
1322d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31);
1323d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32);
1324d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33);
1325d804bb25SOndrej Zary 		atp_writew_base(atpdev, 0x34, n);
13261da177e4SLinus Torvalds 		n += 0x0002;
1327d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30);
1328d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31);
1329d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32);
1330d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33);
1331d804bb25SOndrej Zary 		atp_writew_base(atpdev, 0x34, n);
13321da177e4SLinus Torvalds 		n += 0x0002;
1333d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30);
1334d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31);
1335d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32);
1336d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33);
1337d804bb25SOndrej Zary 		atp_writew_base(atpdev, 0x34, n);
13381da177e4SLinus Torvalds 		n += 0x0002;
1339d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30);
1340d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31);
1341d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32);
1342d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33);
13431da177e4SLinus Torvalds 		n += 0x0018;
13441da177e4SLinus Torvalds 		goto next_fblk_880;
13451da177e4SLinus Torvalds flash_ok_880:
1346d804bb25SOndrej Zary 		atp_writew_base(atpdev, 0x34, 0);
1347dc6a78f1SRandy Dunlap 		atpdev->ultra_map[0] = 0;
1348dc6a78f1SRandy Dunlap 		atpdev->async[0] = 0;
13491da177e4SLinus Torvalds 		for (k = 0; k < 16; k++) {
13501da177e4SLinus Torvalds 			n = 1;
13511da177e4SLinus Torvalds 			n = n << k;
1352dc6a78f1SRandy Dunlap 			if (atpdev->sp[0][k] > 1) {
1353dc6a78f1SRandy Dunlap 				atpdev->ultra_map[0] |= n;
13541da177e4SLinus Torvalds 			} else {
1355dc6a78f1SRandy Dunlap 				if (atpdev->sp[0][k] == 0)
1356dc6a78f1SRandy Dunlap 					atpdev->async[0] |= n;
13571da177e4SLinus Torvalds  			}
13581da177e4SLinus Torvalds 	 	}
1359dc6a78f1SRandy Dunlap 		atpdev->async[0] = ~(atpdev->async[0]);
1360d804bb25SOndrej Zary 		atp_writeb_base(atpdev, 0x35, atpdev->global_map[0]);
13611da177e4SLinus Torvalds 
13621da177e4SLinus Torvalds 		shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
13631da177e4SLinus Torvalds 		if (!shpnt)
1364dc6a78f1SRandy Dunlap 			goto err_nomem;
13651da177e4SLinus Torvalds 
13661da177e4SLinus Torvalds 		p = (struct atp_unit *)&shpnt->hostdata;
13671da177e4SLinus Torvalds 
1368dc6a78f1SRandy Dunlap 		atpdev->host = shpnt;
1369dc6a78f1SRandy Dunlap 		atpdev->pdev = pdev;
13701da177e4SLinus Torvalds 		pci_set_drvdata(pdev, p);
1371dc6a78f1SRandy Dunlap 		memcpy(p, atpdev, sizeof(*atpdev));
13721da177e4SLinus Torvalds 		if (atp870u_init_tables(shpnt) < 0) {
13731da177e4SLinus Torvalds 			printk(KERN_ERR "Unable to allocate tables for Acard controller\n");
13741da177e4SLinus Torvalds 			goto unregister;
13751da177e4SLinus Torvalds 		}
13761da177e4SLinus Torvalds 
13771d6f359aSThomas Gleixner 		if (request_irq(pdev->irq, atp870u_intr_handle, IRQF_SHARED, "atp880i", shpnt)) {
13781da177e4SLinus Torvalds  			printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", pdev->irq);
13791da177e4SLinus Torvalds 			goto free_tables;
13801da177e4SLinus Torvalds 		}
13811da177e4SLinus Torvalds 
13821da177e4SLinus Torvalds 		spin_lock_irqsave(shpnt->host_lock, flags);
1383d804bb25SOndrej Zary 		k = atp_readb_base(p, 0x38) & 0x80;
1384d804bb25SOndrej Zary 		atp_writeb_base(p, 0x38, k);
1385d804bb25SOndrej Zary 		atp_writeb_base(p, 0x3b, 0x20);
13861da177e4SLinus Torvalds 		mdelay(32);
1387d804bb25SOndrej Zary 		atp_writeb_base(p, 0x3b, 0);
13881da177e4SLinus Torvalds 		mdelay(32);
1389d804bb25SOndrej Zary 		atp_readb_io(p, 0, 0x1b);
1390d804bb25SOndrej Zary 		atp_readb_io(p, 0, 0x17);
13916a1961bcSOndrej Zary 
13926a1961bcSOndrej Zary 		atp_set_host_id(p, 0, host_id);
13931da177e4SLinus Torvalds 
13941da177e4SLinus Torvalds 		tscam(shpnt);
13954192a40fSOndrej Zary 		atp_is(p, 0, true, atp_readb_base(p, 0x3f) & 0x40);
1396d804bb25SOndrej Zary 		atp_writeb_base(p, 0x38, 0xb0);
13971da177e4SLinus Torvalds 		shpnt->max_id = 16;
13981da177e4SLinus Torvalds 		shpnt->this_id = host_id;
13991da177e4SLinus Torvalds 		shpnt->unique_id = base_io;
14001da177e4SLinus Torvalds 		shpnt->io_port = base_io;
14011da177e4SLinus Torvalds 		shpnt->n_io_port = 0x60;	/* Number of bytes of I/O space used */
14021da177e4SLinus Torvalds 		shpnt->irq = pdev->irq;
14031da177e4SLinus Torvalds 	} else if (ent->device == ATP885_DEVID) {
14041da177e4SLinus Torvalds 			printk(KERN_INFO "   ACARD AEC-67162 PCI Ultra3 LVD Host Adapter:  IO:%x, IRQ:%d.\n"
14051da177e4SLinus Torvalds 			       , base_io, pdev->irq);
14061da177e4SLinus Torvalds 
1407dc6a78f1SRandy Dunlap 		atpdev->pdev = pdev;
1408dc6a78f1SRandy Dunlap 		atpdev->dev_id  = ent->device;
1409dc6a78f1SRandy Dunlap 		atpdev->ioport[0] = base_io + 0x80;
1410dc6a78f1SRandy Dunlap 		atpdev->ioport[1] = base_io + 0xc0;
1411dc6a78f1SRandy Dunlap 		atpdev->pciport[0] = base_io + 0x40;
1412dc6a78f1SRandy Dunlap 		atpdev->pciport[1] = base_io + 0x50;
14131da177e4SLinus Torvalds 
14141da177e4SLinus Torvalds 		shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
14151da177e4SLinus Torvalds 		if (!shpnt)
1416dc6a78f1SRandy Dunlap 			goto err_nomem;
14171da177e4SLinus Torvalds 
14181da177e4SLinus Torvalds 		p = (struct atp_unit *)&shpnt->hostdata;
14191da177e4SLinus Torvalds 
1420dc6a78f1SRandy Dunlap 		atpdev->host = shpnt;
1421dc6a78f1SRandy Dunlap 		atpdev->pdev = pdev;
14221da177e4SLinus Torvalds 		pci_set_drvdata(pdev, p);
1423dc6a78f1SRandy Dunlap 		memcpy(p, atpdev, sizeof(struct atp_unit));
14241da177e4SLinus Torvalds 		if (atp870u_init_tables(shpnt) < 0)
14251da177e4SLinus Torvalds 			goto unregister;
14261da177e4SLinus Torvalds 
14271da177e4SLinus Torvalds #ifdef ED_DBGP
14281da177e4SLinus Torvalds 	printk("request_irq() shpnt %p hostdata %p\n", shpnt, p);
14291da177e4SLinus Torvalds #endif
14301d6f359aSThomas Gleixner 		if (request_irq(pdev->irq, atp870u_intr_handle, IRQF_SHARED, "atp870u", shpnt)) {
14311da177e4SLinus Torvalds 				printk(KERN_ERR "Unable to allocate IRQ for Acard controller.\n");
14321da177e4SLinus Torvalds 			goto free_tables;
14331da177e4SLinus Torvalds 		}
14341da177e4SLinus Torvalds 
14351da177e4SLinus Torvalds 		spin_lock_irqsave(shpnt->host_lock, flags);
14361da177e4SLinus Torvalds 
1437d804bb25SOndrej Zary 		c = atp_readb_base(p, 0x29);
1438d804bb25SOndrej Zary 		atp_writeb_base(p, 0x29, c | 0x04);
14391da177e4SLinus Torvalds 
14401da177e4SLinus Torvalds 		n=0x1f80;
14411da177e4SLinus Torvalds next_fblk_885:
14421da177e4SLinus Torvalds 		if (n >= 0x2000) {
14431da177e4SLinus Torvalds 		   goto flash_ok_885;
14441da177e4SLinus Torvalds 		}
1445d804bb25SOndrej Zary 		atp_writew_base(p, 0x3c, n);
1446d804bb25SOndrej Zary 		if (atp_readl_base(p, 0x38) == 0xffffffff) {
14471da177e4SLinus Torvalds 		   goto flash_ok_885;
14481da177e4SLinus Torvalds 		}
14491da177e4SLinus Torvalds 		for (m=0; m < 2; m++) {
14501da177e4SLinus Torvalds 		    p->global_map[m]= 0;
14511da177e4SLinus Torvalds 		    for (k=0; k < 4; k++) {
1452d804bb25SOndrej Zary 			atp_writew_base(p, 0x3c, n++);
1453d804bb25SOndrej Zary 			((unsigned long *)&setupdata[m][0])[k] = atp_readl_base(p, 0x38);
14541da177e4SLinus Torvalds 		    }
14551da177e4SLinus Torvalds 		    for (k=0; k < 4; k++) {
1456d804bb25SOndrej Zary 			atp_writew_base(p, 0x3c, n++);
1457d804bb25SOndrej Zary 			((unsigned long *)&p->sp[m][0])[k] = atp_readl_base(p, 0x38);
14581da177e4SLinus Torvalds 		    }
14591da177e4SLinus Torvalds 		    n += 8;
14601da177e4SLinus Torvalds 		}
14611da177e4SLinus Torvalds 		goto next_fblk_885;
14621da177e4SLinus Torvalds flash_ok_885:
14631da177e4SLinus Torvalds #ifdef ED_DBGP
14641da177e4SLinus Torvalds 		printk( "Flash Read OK\n");
14651da177e4SLinus Torvalds #endif
1466d804bb25SOndrej Zary 		c = atp_readb_base(p, 0x29);
1467d804bb25SOndrej Zary 		atp_writeb_base(p, 0x29, c & 0xfb);
14681da177e4SLinus Torvalds 		for (c=0;c < 2;c++) {
14691da177e4SLinus Torvalds 		    p->ultra_map[c]=0;
14701da177e4SLinus Torvalds 		    p->async[c] = 0;
14711da177e4SLinus Torvalds 		    for (k=0; k < 16; k++) {
14721da177e4SLinus Torvalds 			n=1;
14731da177e4SLinus Torvalds 			n = n << k;
14741da177e4SLinus Torvalds 			if (p->sp[c][k] > 1) {
14751da177e4SLinus Torvalds 			   p->ultra_map[c] |= n;
14761da177e4SLinus Torvalds 			} else {
14771da177e4SLinus Torvalds 			   if (p->sp[c][k] == 0) {
14781da177e4SLinus Torvalds 			      p->async[c] |= n;
14791da177e4SLinus Torvalds 			   }
14801da177e4SLinus Torvalds 			}
14811da177e4SLinus Torvalds 		    }
14821da177e4SLinus Torvalds 		    p->async[c] = ~(p->async[c]);
14831da177e4SLinus Torvalds 
14841da177e4SLinus Torvalds 		    if (p->global_map[c] == 0) {
14851da177e4SLinus Torvalds 		       k=setupdata[c][1];
14861da177e4SLinus Torvalds 		       if ((k & 0x40) != 0)
14871da177e4SLinus Torvalds 			  p->global_map[c] |= 0x20;
14881da177e4SLinus Torvalds 		       k &= 0x07;
14891da177e4SLinus Torvalds 		       p->global_map[c] |= k;
14901da177e4SLinus Torvalds 		       if ((setupdata[c][2] & 0x04) != 0)
14911da177e4SLinus Torvalds 			  p->global_map[c] |= 0x08;
14921da177e4SLinus Torvalds 		       p->host_id[c] = setupdata[c][0] & 0x07;
14931da177e4SLinus Torvalds 		    }
14941da177e4SLinus Torvalds 		}
14951da177e4SLinus Torvalds 
1496d804bb25SOndrej Zary 		k = atp_readb_base(p, 0x28) & 0x8f;
14971da177e4SLinus Torvalds 		k |= 0x10;
1498d804bb25SOndrej Zary 		atp_writeb_base(p, 0x28, k);
1499d804bb25SOndrej Zary 		atp_writeb_pci(p, 0, 1, 0x80);
1500d804bb25SOndrej Zary 		atp_writeb_pci(p, 1, 1, 0x80);
15011da177e4SLinus Torvalds 		mdelay(100);
1502d804bb25SOndrej Zary 		atp_writeb_pci(p, 0, 1, 0);
1503d804bb25SOndrej Zary 		atp_writeb_pci(p, 1, 1, 0);
15041da177e4SLinus Torvalds 		mdelay(1000);
1505d804bb25SOndrej Zary 		atp_readb_io(p, 0, 0x1b);
1506d804bb25SOndrej Zary 		atp_readb_io(p, 0, 0x17);
1507d804bb25SOndrej Zary 		atp_readb_io(p, 1, 0x1b);
1508d804bb25SOndrej Zary 		atp_readb_io(p, 1, 0x17);
15096a1961bcSOndrej Zary 
15101da177e4SLinus Torvalds 		k=p->host_id[0];
15111da177e4SLinus Torvalds 		if (k > 7)
15121da177e4SLinus Torvalds 		   k = (k & 0x07) | 0x40;
15136a1961bcSOndrej Zary 		atp_set_host_id(p, 0, k);
15141da177e4SLinus Torvalds 
15151da177e4SLinus Torvalds 		k=p->host_id[1];
15161da177e4SLinus Torvalds 		if (k > 7)
15171da177e4SLinus Torvalds 		   k = (k & 0x07) | 0x40;
15186a1961bcSOndrej Zary 		atp_set_host_id(p, 1, k);
15191da177e4SLinus Torvalds 
1520c4ad92bcSOndrej Zary 		mdelay(600); /* this delay used to be called tscam_885() */
15211da177e4SLinus Torvalds 		printk(KERN_INFO "   Scanning Channel A SCSI Device ...\n");
15224192a40fSOndrej Zary 		atp_is(p, 0, true, atp_readb_io(p, 0, 0x1b) >> 7);
1523fa50b308SOndrej Zary 		atp_writeb_io(p, 0, 0x16, 0x80);
15241da177e4SLinus Torvalds 		printk(KERN_INFO "   Scanning Channel B SCSI Device ...\n");
15254192a40fSOndrej Zary 		atp_is(p, 1, true, atp_readb_io(p, 1, 0x1b) >> 7);
1526fa50b308SOndrej Zary 		atp_writeb_io(p, 1, 0x16, 0x80);
1527d804bb25SOndrej Zary 		k = atp_readb_base(p, 0x28) & 0xcf;
15281da177e4SLinus Torvalds 		k |= 0xc0;
1529d804bb25SOndrej Zary 		atp_writeb_base(p, 0x28, k);
1530d804bb25SOndrej Zary 		k = atp_readb_base(p, 0x1f) | 0x80;
1531d804bb25SOndrej Zary 		atp_writeb_base(p, 0x1f, k);
1532d804bb25SOndrej Zary 		k = atp_readb_base(p, 0x29) | 0x01;
1533d804bb25SOndrej Zary 		atp_writeb_base(p, 0x29, k);
15341da177e4SLinus Torvalds #ifdef ED_DBGP
15351da177e4SLinus Torvalds 		//printk("atp885: atp_host[0] 0x%p\n", atp_host[0]);
15361da177e4SLinus Torvalds #endif
15371da177e4SLinus Torvalds 		shpnt->max_id = 16;
15381da177e4SLinus Torvalds 		shpnt->max_lun = (p->global_map[0] & 0x07) + 1;
15391da177e4SLinus Torvalds 		shpnt->max_channel = 1;
15401da177e4SLinus Torvalds 		shpnt->this_id = p->host_id[0];
15411da177e4SLinus Torvalds 		shpnt->unique_id = base_io;
15421da177e4SLinus Torvalds 		shpnt->io_port = base_io;
15431da177e4SLinus Torvalds 		shpnt->n_io_port = 0xff;	/* Number of bytes of I/O space used */
15441da177e4SLinus Torvalds 		shpnt->irq = pdev->irq;
15451da177e4SLinus Torvalds 
15461da177e4SLinus Torvalds 	} else {
15471da177e4SLinus Torvalds 		error = pci_read_config_byte(pdev, 0x49, &host_id);
15481da177e4SLinus Torvalds 
15491da177e4SLinus Torvalds 		printk(KERN_INFO "   ACARD AEC-671X PCI Ultra/W SCSI-2/3 Host Adapter: %d "
15501da177e4SLinus Torvalds 			"IO:%x, IRQ:%d.\n", count, base_io, pdev->irq);
15511da177e4SLinus Torvalds 
1552dc6a78f1SRandy Dunlap 		atpdev->ioport[0] = base_io;
1553dc6a78f1SRandy Dunlap 		atpdev->pciport[0] = base_io + 0x20;
1554dc6a78f1SRandy Dunlap 		atpdev->dev_id = ent->device;
15551da177e4SLinus Torvalds 		host_id &= 0x07;
1556dc6a78f1SRandy Dunlap 		atpdev->host_id[0] = host_id;
1557d804bb25SOndrej Zary 		atpdev->scam_on = atp_readb_pci(atpdev, 0, 2);
1558d804bb25SOndrej Zary 		atpdev->global_map[0] = atp_readb_base(atpdev, 0x2d);
1559d804bb25SOndrej Zary 		atpdev->ultra_map[0] = atp_readw_base(atpdev, 0x2e);
15601da177e4SLinus Torvalds 
1561dc6a78f1SRandy Dunlap 		if (atpdev->ultra_map[0] == 0) {
1562dc6a78f1SRandy Dunlap 			atpdev->scam_on = 0x00;
1563dc6a78f1SRandy Dunlap 			atpdev->global_map[0] = 0x20;
1564dc6a78f1SRandy Dunlap 			atpdev->ultra_map[0] = 0xffff;
15651da177e4SLinus Torvalds 		}
15661da177e4SLinus Torvalds 
15671da177e4SLinus Torvalds 		shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
15681da177e4SLinus Torvalds 		if (!shpnt)
1569dc6a78f1SRandy Dunlap 			goto err_nomem;
15701da177e4SLinus Torvalds 
15711da177e4SLinus Torvalds 		p = (struct atp_unit *)&shpnt->hostdata;
15721da177e4SLinus Torvalds 
1573dc6a78f1SRandy Dunlap 		atpdev->host = shpnt;
1574dc6a78f1SRandy Dunlap 		atpdev->pdev = pdev;
15751da177e4SLinus Torvalds 		pci_set_drvdata(pdev, p);
1576dc6a78f1SRandy Dunlap 		memcpy(p, atpdev, sizeof(*atpdev));
15771da177e4SLinus Torvalds 		if (atp870u_init_tables(shpnt) < 0)
15781da177e4SLinus Torvalds 			goto unregister;
15791da177e4SLinus Torvalds 
15801d6f359aSThomas Gleixner 		if (request_irq(pdev->irq, atp870u_intr_handle, IRQF_SHARED, "atp870i", shpnt)) {
15811da177e4SLinus Torvalds 			printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", pdev->irq);
15821da177e4SLinus Torvalds 			goto free_tables;
15831da177e4SLinus Torvalds 		}
15841da177e4SLinus Torvalds 
15851da177e4SLinus Torvalds 		spin_lock_irqsave(shpnt->host_lock, flags);
1586d804bb25SOndrej Zary 		if (atpdev->chip_ver > 0x07)	/* check if atp876 chip then enable terminator */
1587d804bb25SOndrej Zary 			atp_writeb_base(p, 0x3e, 0x00);
15881da177e4SLinus Torvalds 
1589d804bb25SOndrej Zary 		k = (atp_readb_base(p, 0x3a) & 0xf3) | 0x10;
1590d804bb25SOndrej Zary 		atp_writeb_base(p, 0x3a, k);
1591d804bb25SOndrej Zary 		atp_writeb_base(p, 0x3a, k & 0xdf);
15921da177e4SLinus Torvalds 		mdelay(32);
1593d804bb25SOndrej Zary 		atp_writeb_base(p, 0x3a, k);
15941da177e4SLinus Torvalds 		mdelay(32);
15956a1961bcSOndrej Zary 		atp_set_host_id(p, 0, host_id);
15961da177e4SLinus Torvalds 
15971da177e4SLinus Torvalds 		tscam(shpnt);
1598d804bb25SOndrej Zary 		atp_writeb_base(p, 0x3a, atp_readb_base(p, 0x3a) | 0x10);
15994192a40fSOndrej Zary 		atp_is(p, 0, p->chip_ver == 4, 0);
1600d804bb25SOndrej Zary 		atp_writeb_base(p, 0x3a, atp_readb_base(p, 0x3a) & 0xef);
1601d804bb25SOndrej Zary 		atp_writeb_base(p, 0x3b, atp_readb_base(p, 0x3b) | 0x20);
1602dc6a78f1SRandy Dunlap 		if (atpdev->chip_ver == 4)
16031da177e4SLinus Torvalds 			shpnt->max_id = 16;
16041da177e4SLinus Torvalds 		else
16052b89dad0SHannes Reinecke 			shpnt->max_id = 8;
16061da177e4SLinus Torvalds 		shpnt->this_id = host_id;
16071da177e4SLinus Torvalds 		shpnt->unique_id = base_io;
16081da177e4SLinus Torvalds 		shpnt->io_port = base_io;
16091da177e4SLinus Torvalds 		shpnt->n_io_port = 0x40;	/* Number of bytes of I/O space used */
16101da177e4SLinus Torvalds 		shpnt->irq = pdev->irq;
16111da177e4SLinus Torvalds 	}
16121da177e4SLinus Torvalds 		spin_unlock_irqrestore(shpnt->host_lock, flags);
16131da177e4SLinus Torvalds 		if(ent->device==ATP885_DEVID) {
16141da177e4SLinus Torvalds 			if(!request_region(base_io, 0xff, "atp870u")) /* Register the IO ports that we use */
16151da177e4SLinus Torvalds 				goto request_io_fail;
16161da177e4SLinus Torvalds 		} else if((ent->device==ATP880_DEVID1)||(ent->device==ATP880_DEVID2)) {
16171da177e4SLinus Torvalds 			if(!request_region(base_io, 0x60, "atp870u")) /* Register the IO ports that we use */
16181da177e4SLinus Torvalds 				goto request_io_fail;
16191da177e4SLinus Torvalds 		} else {
16201da177e4SLinus Torvalds 			if(!request_region(base_io, 0x40, "atp870u")) /* Register the IO ports that we use */
16211da177e4SLinus Torvalds 				goto request_io_fail;
16221da177e4SLinus Torvalds 		}
16231da177e4SLinus Torvalds 		count++;
16241da177e4SLinus Torvalds 		if (scsi_add_host(shpnt, &pdev->dev))
16251da177e4SLinus Torvalds 			goto scsi_add_fail;
16261da177e4SLinus Torvalds 		scsi_scan_host(shpnt);
16271da177e4SLinus Torvalds #ifdef ED_DBGP
16281da177e4SLinus Torvalds 		printk("atp870u_prob : exit\n");
16291da177e4SLinus Torvalds #endif
16301da177e4SLinus Torvalds 		return 0;
16311da177e4SLinus Torvalds 
16321da177e4SLinus Torvalds scsi_add_fail:
16331da177e4SLinus Torvalds 	printk("atp870u_prob:scsi_add_fail\n");
16341da177e4SLinus Torvalds 	if(ent->device==ATP885_DEVID) {
16351da177e4SLinus Torvalds 		release_region(base_io, 0xff);
16361da177e4SLinus Torvalds 	} else if((ent->device==ATP880_DEVID1)||(ent->device==ATP880_DEVID2)) {
16371da177e4SLinus Torvalds 		release_region(base_io, 0x60);
16381da177e4SLinus Torvalds 	} else {
16391da177e4SLinus Torvalds 		release_region(base_io, 0x40);
16401da177e4SLinus Torvalds 	}
16411da177e4SLinus Torvalds request_io_fail:
16421da177e4SLinus Torvalds 	printk("atp870u_prob:request_io_fail\n");
16431da177e4SLinus Torvalds 	free_irq(pdev->irq, shpnt);
16441da177e4SLinus Torvalds free_tables:
16451da177e4SLinus Torvalds 	printk("atp870u_prob:free_table\n");
16461da177e4SLinus Torvalds 	atp870u_free_tables(shpnt);
16471da177e4SLinus Torvalds unregister:
16481da177e4SLinus Torvalds 	printk("atp870u_prob:unregister\n");
16491da177e4SLinus Torvalds 	scsi_host_put(shpnt);
16501da177e4SLinus Torvalds 	return -1;
1651dc6a78f1SRandy Dunlap err_eio:
1652dc6a78f1SRandy Dunlap 	kfree(atpdev);
1653dc6a78f1SRandy Dunlap 	return -EIO;
1654dc6a78f1SRandy Dunlap err_nomem:
1655dc6a78f1SRandy Dunlap 	kfree(atpdev);
1656dc6a78f1SRandy Dunlap 	return -ENOMEM;
16571da177e4SLinus Torvalds }
16581da177e4SLinus Torvalds 
16591da177e4SLinus Torvalds /* The abort command does not leave the device in a clean state where
16601da177e4SLinus Torvalds    it is available to be used again.  Until this gets worked out, we will
16611da177e4SLinus Torvalds    leave it commented out.  */
16621da177e4SLinus Torvalds 
16631da177e4SLinus Torvalds static int atp870u_abort(struct scsi_cmnd * SCpnt)
16641da177e4SLinus Torvalds {
16651da177e4SLinus Torvalds 	unsigned char  j, k, c;
16661da177e4SLinus Torvalds 	struct scsi_cmnd *workrequ;
16671da177e4SLinus Torvalds 	struct atp_unit *dev;
16681da177e4SLinus Torvalds 	struct Scsi_Host *host;
16691da177e4SLinus Torvalds 	host = SCpnt->device->host;
16701da177e4SLinus Torvalds 
16711da177e4SLinus Torvalds 	dev = (struct atp_unit *)&host->hostdata;
1672422c0d61SJeff Garzik 	c = scmd_channel(SCpnt);
16731da177e4SLinus Torvalds 	printk(" atp870u: abort Channel = %x \n", c);
16741da177e4SLinus Torvalds 	printk("working=%x last_cmd=%x ", dev->working[c], dev->last_cmd[c]);
16751da177e4SLinus Torvalds 	printk(" quhdu=%x quendu=%x ", dev->quhd[c], dev->quend[c]);
16761da177e4SLinus Torvalds 	for (j = 0; j < 0x18; j++) {
16776a3cebb6SOndrej Zary 		printk(" r%2x=%2x", j, atp_readb_io(dev, c, j));
16781da177e4SLinus Torvalds 	}
16796a3cebb6SOndrej Zary 	printk(" r1c=%2x", atp_readb_io(dev, c, 0x1c));
16806a3cebb6SOndrej Zary 	printk(" r1f=%2x in_snd=%2x ", atp_readb_io(dev, c, 0x1f), dev->in_snd[c]);
16816a3cebb6SOndrej Zary 	printk(" d00=%2x", atp_readb_pci(dev, c, 0x00));
16826a3cebb6SOndrej Zary 	printk(" d02=%2x", atp_readb_pci(dev, c, 0x02));
16831da177e4SLinus Torvalds 	for(j=0;j<16;j++) {
16841da177e4SLinus Torvalds 	   if (dev->id[c][j].curr_req != NULL) {
16851da177e4SLinus Torvalds 		workrequ = dev->id[c][j].curr_req;
16861da177e4SLinus Torvalds 		printk("\n que cdb= ");
16871da177e4SLinus Torvalds 		for (k=0; k < workrequ->cmd_len; k++) {
16881da177e4SLinus Torvalds 		    printk(" %2x ",workrequ->cmnd[k]);
16891da177e4SLinus Torvalds 		}
16901da177e4SLinus Torvalds 		printk(" last_lenu= %x ",(unsigned int)dev->id[c][j].last_len);
16911da177e4SLinus Torvalds 	   }
16921da177e4SLinus Torvalds 	}
16931da177e4SLinus Torvalds 	return SUCCESS;
16941da177e4SLinus Torvalds }
16951da177e4SLinus Torvalds 
16961da177e4SLinus Torvalds static const char *atp870u_info(struct Scsi_Host *notused)
16971da177e4SLinus Torvalds {
16981da177e4SLinus Torvalds 	static char buffer[128];
16991da177e4SLinus Torvalds 
17001da177e4SLinus Torvalds 	strcpy(buffer, "ACARD AEC-6710/6712/67160 PCI Ultra/W/LVD SCSI-3 Adapter Driver V2.6+ac ");
17011da177e4SLinus Torvalds 
17021da177e4SLinus Torvalds 	return buffer;
17031da177e4SLinus Torvalds }
17041da177e4SLinus Torvalds 
1705d773e422SAl Viro static int atp870u_show_info(struct seq_file *m, struct Scsi_Host *HBAptr)
17061da177e4SLinus Torvalds {
17073d30079cSRasmus Villemoes 	seq_puts(m, "ACARD AEC-671X Driver Version: 2.6+ac\n\n"
17083d30079cSRasmus Villemoes 		"Adapter Configuration:\n");
1709d773e422SAl Viro 	seq_printf(m, "               Base IO: %#.4lx\n", HBAptr->io_port);
1710d773e422SAl Viro 	seq_printf(m, "                   IRQ: %d\n", HBAptr->irq);
1711d773e422SAl Viro 	return 0;
17121da177e4SLinus Torvalds }
17131da177e4SLinus Torvalds 
17141da177e4SLinus Torvalds 
17151da177e4SLinus Torvalds static int atp870u_biosparam(struct scsi_device *disk, struct block_device *dev,
17161da177e4SLinus Torvalds 			sector_t capacity, int *ip)
17171da177e4SLinus Torvalds {
17181da177e4SLinus Torvalds 	int heads, sectors, cylinders;
17191da177e4SLinus Torvalds 
17201da177e4SLinus Torvalds 	heads = 64;
17211da177e4SLinus Torvalds 	sectors = 32;
17221da177e4SLinus Torvalds 	cylinders = (unsigned long)capacity / (heads * sectors);
17231da177e4SLinus Torvalds 	if (cylinders > 1024) {
17241da177e4SLinus Torvalds 		heads = 255;
17251da177e4SLinus Torvalds 		sectors = 63;
17261da177e4SLinus Torvalds 		cylinders = (unsigned long)capacity / (heads * sectors);
17271da177e4SLinus Torvalds 	}
17281da177e4SLinus Torvalds 	ip[0] = heads;
17291da177e4SLinus Torvalds 	ip[1] = sectors;
17301da177e4SLinus Torvalds 	ip[2] = cylinders;
17311da177e4SLinus Torvalds 
17321da177e4SLinus Torvalds 	return 0;
17331da177e4SLinus Torvalds }
17341da177e4SLinus Torvalds 
17351da177e4SLinus Torvalds static void atp870u_remove (struct pci_dev *pdev)
17361da177e4SLinus Torvalds {
17371da177e4SLinus Torvalds 	struct atp_unit *devext = pci_get_drvdata(pdev);
17381da177e4SLinus Torvalds 	struct Scsi_Host *pshost = devext->host;
17391da177e4SLinus Torvalds 
17401da177e4SLinus Torvalds 
17411da177e4SLinus Torvalds 	scsi_remove_host(pshost);
17421da177e4SLinus Torvalds 	free_irq(pshost->irq, pshost);
17431da177e4SLinus Torvalds 	release_region(pshost->io_port, pshost->n_io_port);
17441da177e4SLinus Torvalds 	atp870u_free_tables(pshost);
17451da177e4SLinus Torvalds 	scsi_host_put(pshost);
17461da177e4SLinus Torvalds }
17471da177e4SLinus Torvalds MODULE_LICENSE("GPL");
17481da177e4SLinus Torvalds 
17491da177e4SLinus Torvalds static struct scsi_host_template atp870u_template = {
17501da177e4SLinus Torvalds      .module			= THIS_MODULE,
17511da177e4SLinus Torvalds      .name              	= "atp870u"		/* name */,
17521da177e4SLinus Torvalds      .proc_name			= "atp870u",
1753d773e422SAl Viro      .show_info			= atp870u_show_info,
17541da177e4SLinus Torvalds      .info              	= atp870u_info		/* info */,
17551da177e4SLinus Torvalds      .queuecommand      	= atp870u_queuecommand	/* queuecommand */,
17561da177e4SLinus Torvalds      .eh_abort_handler  	= atp870u_abort		/* abort */,
17571da177e4SLinus Torvalds      .bios_param        	= atp870u_biosparam	/* biosparm */,
17581da177e4SLinus Torvalds      .can_queue         	= qcnt			/* can_queue */,
17591da177e4SLinus Torvalds      .this_id           	= 7			/* SCSI ID */,
17601da177e4SLinus Torvalds      .sg_tablesize      	= ATP870U_SCATTER	/*SG_ALL*/ /*SG_NONE*/,
17611da177e4SLinus Torvalds      .use_clustering    	= ENABLE_CLUSTERING,
17621da177e4SLinus Torvalds      .max_sectors		= ATP870U_MAX_SECTORS,
17631da177e4SLinus Torvalds };
17641da177e4SLinus Torvalds 
17651da177e4SLinus Torvalds static struct pci_device_id atp870u_id_table[] = {
17661da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP885_DEVID)			  },
17671da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID1)			  },
17681da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID2)			  },
17691da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7610)    },
17701da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612UW)  },
17711da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612U)   },
17721da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612S)   },
17731da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612D)	  },
17741da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612SUW) },
17751da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_8060)	  },
17761da177e4SLinus Torvalds 	{ 0, },
17771da177e4SLinus Torvalds };
17781da177e4SLinus Torvalds 
17791da177e4SLinus Torvalds MODULE_DEVICE_TABLE(pci, atp870u_id_table);
17801da177e4SLinus Torvalds 
17811da177e4SLinus Torvalds static struct pci_driver atp870u_driver = {
17821da177e4SLinus Torvalds 	.id_table	= atp870u_id_table,
17831da177e4SLinus Torvalds 	.name		= "atp870u",
17841da177e4SLinus Torvalds 	.probe		= atp870u_probe,
17856f039790SGreg Kroah-Hartman 	.remove		= atp870u_remove,
17861da177e4SLinus Torvalds };
17871da177e4SLinus Torvalds 
17881da177e4SLinus Torvalds static int __init atp870u_init(void)
17891da177e4SLinus Torvalds {
17901da177e4SLinus Torvalds #ifdef ED_DBGP
17911da177e4SLinus Torvalds 	printk("atp870u_init: Entry\n");
17921da177e4SLinus Torvalds #endif
17931da177e4SLinus Torvalds 	return pci_register_driver(&atp870u_driver);
17941da177e4SLinus Torvalds }
17951da177e4SLinus Torvalds 
17961da177e4SLinus Torvalds static void __exit atp870u_exit(void)
17971da177e4SLinus Torvalds {
17981da177e4SLinus Torvalds #ifdef ED_DBGP
17991da177e4SLinus Torvalds 	printk("atp870u_exit: Entry\n");
18001da177e4SLinus Torvalds #endif
18011da177e4SLinus Torvalds 	pci_unregister_driver(&atp870u_driver);
18021da177e4SLinus Torvalds }
18031da177e4SLinus Torvalds 
18044192a40fSOndrej Zary static void atp_is(struct atp_unit *dev, unsigned char c, bool wide_chip, unsigned char lvdmode)
18051da177e4SLinus Torvalds {
1806fa50b308SOndrej Zary 	unsigned char i, j, k, rmb, n;
18071da177e4SLinus Torvalds 	unsigned short int m;
18081da177e4SLinus Torvalds 	static unsigned char mbuf[512];
18091da177e4SLinus Torvalds 	static unsigned char satn[9] = { 0, 0, 0, 0, 0, 0, 0, 6, 6 };
18101da177e4SLinus Torvalds 	static unsigned char inqd[9] = { 0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6 };
18111da177e4SLinus Torvalds 	static unsigned char synn[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
18121da177e4SLinus Torvalds 	unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
18131da177e4SLinus Torvalds 	static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
1814460da918SOndrej Zary 	static unsigned char synw_870[6] = { 0x80, 1, 3, 1, 0x0c, 0x07 };
18151da177e4SLinus Torvalds 	unsigned char synuw[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
18161da177e4SLinus Torvalds 	static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
18171da177e4SLinus Torvalds 	static unsigned char u3[9] = { 0x80, 1, 6, 4, 0x09, 00, 0x0e, 0x01, 0x02 };
18181da177e4SLinus Torvalds 
18191da177e4SLinus Torvalds 	for (i = 0; i < 16; i++) {
1820197fb8d8SOndrej Zary 		if (!wide_chip && (i > 7))
1821197fb8d8SOndrej Zary 			break;
18221da177e4SLinus Torvalds 		m = 1;
18231da177e4SLinus Torvalds 		m = m << i;
18241da177e4SLinus Torvalds 		if ((m & dev->active_id[c]) != 0) {
18251da177e4SLinus Torvalds 			continue;
18261da177e4SLinus Torvalds 		}
18271da177e4SLinus Torvalds 		if (i == dev->host_id[c]) {
18281da177e4SLinus Torvalds 			printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_id[c]);
18291da177e4SLinus Torvalds 			continue;
18301da177e4SLinus Torvalds 		}
1831197fb8d8SOndrej Zary 		atp_writeb_io(dev, c, 0x1b, wide_chip ? 0x01 : 0x00);
18325d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 1, 0x08);
18335d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 2, 0x7f);
18345d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 3, satn[0]);
18355d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 4, satn[1]);
18365d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 5, satn[2]);
18375d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 6, satn[3]);
18385d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 7, satn[4]);
18395d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 8, satn[5]);
18405d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x0f, 0);
18415d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
18425d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
18435d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, satn[6]);
18445d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, satn[7]);
18451da177e4SLinus Torvalds 		j = i;
18461da177e4SLinus Torvalds 		if ((j & 0x08) != 0) {
18471da177e4SLinus Torvalds 			j = (j & 0x07) | 0x40;
18481da177e4SLinus Torvalds 		}
18495d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x15, j);
18505d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, satn[8]);
18511da177e4SLinus Torvalds 
18525d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
18531da177e4SLinus Torvalds 			cpu_relax();
185480b52a7fSOndrej Zary 
185580b52a7fSOndrej Zary 		if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e)
18561da177e4SLinus Torvalds 			continue;
185780b52a7fSOndrej Zary 
18585d2a5a4fSOndrej Zary 		while (atp_readb_io(dev, c, 0x17) != 0x8e)
18591da177e4SLinus Torvalds 			cpu_relax();
186080b52a7fSOndrej Zary 
18611da177e4SLinus Torvalds 		dev->active_id[c] |= m;
18621da177e4SLinus Torvalds 
18635d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x10, 0x30);
1864460da918SOndrej Zary 		if (dev->dev_id == ATP885_DEVID || dev->dev_id == ATP880_DEVID1 || dev->dev_id == ATP880_DEVID2)
18655d2a5a4fSOndrej Zary 			atp_writeb_io(dev, c, 0x14, 0x00);
1866460da918SOndrej Zary 		else /* result of is870() merge - is this a bug? */
1867460da918SOndrej Zary 			atp_writeb_io(dev, c, 0x04, 0x00);
18681da177e4SLinus Torvalds 
18691da177e4SLinus Torvalds phase_cmd:
18705d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
187180b52a7fSOndrej Zary 
18725d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
18731da177e4SLinus Torvalds 			cpu_relax();
187480b52a7fSOndrej Zary 
18755d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
18761da177e4SLinus Torvalds 		if (j != 0x16) {
18775d2a5a4fSOndrej Zary 			atp_writeb_io(dev, c, 0x10, 0x41);
18781da177e4SLinus Torvalds 			goto phase_cmd;
18791da177e4SLinus Torvalds 		}
18801da177e4SLinus Torvalds sel_ok:
18815d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 3, inqd[0]);
18825d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 4, inqd[1]);
18835d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 5, inqd[2]);
18845d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 6, inqd[3]);
18855d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 7, inqd[4]);
18865d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 8, inqd[5]);
18875d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x0f, 0);
18885d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
18895d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
18905d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, inqd[6]);
18915d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, inqd[7]);
18925d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, inqd[8]);
189380b52a7fSOndrej Zary 
18945d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
18951da177e4SLinus Torvalds 			cpu_relax();
189680b52a7fSOndrej Zary 
189780b52a7fSOndrej Zary 		if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e)
18981da177e4SLinus Torvalds 			continue;
189980b52a7fSOndrej Zary 
19005d2a5a4fSOndrej Zary 		while (atp_readb_io(dev, c, 0x17) != 0x8e)
19011da177e4SLinus Torvalds 			cpu_relax();
190280b52a7fSOndrej Zary 
1903197fb8d8SOndrej Zary 		if (wide_chip)
19045d2a5a4fSOndrej Zary 			atp_writeb_io(dev, c, 0x1b, 0x00);
1905197fb8d8SOndrej Zary 
19065d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
19071da177e4SLinus Torvalds 		j = 0;
19081da177e4SLinus Torvalds rd_inq_data:
19095d2a5a4fSOndrej Zary 		k = atp_readb_io(dev, c, 0x1f);
19101da177e4SLinus Torvalds 		if ((k & 0x01) != 0) {
19115d2a5a4fSOndrej Zary 			mbuf[j++] = atp_readb_io(dev, c, 0x19);
19121da177e4SLinus Torvalds 			goto rd_inq_data;
19131da177e4SLinus Torvalds 		}
19141da177e4SLinus Torvalds 		if ((k & 0x80) == 0) {
19151da177e4SLinus Torvalds 			goto rd_inq_data;
19161da177e4SLinus Torvalds 		}
19175d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
19181da177e4SLinus Torvalds 		if (j == 0x16) {
19191da177e4SLinus Torvalds 			goto inq_ok;
19201da177e4SLinus Torvalds 		}
19215d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x10, 0x46);
19225d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
19235d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, 0);
19245d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0);
19255d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
192680b52a7fSOndrej Zary 
19275d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
19281da177e4SLinus Torvalds 			cpu_relax();
192980b52a7fSOndrej Zary 
193080b52a7fSOndrej Zary 		if (atp_readb_io(dev, c, 0x17) != 0x16)
19311da177e4SLinus Torvalds 			goto sel_ok;
193280b52a7fSOndrej Zary 
19331da177e4SLinus Torvalds inq_ok:
19341da177e4SLinus Torvalds 		mbuf[36] = 0;
19351da177e4SLinus Torvalds 		printk(KERN_INFO "         ID: %2d  %s\n", i, &mbuf[8]);
19361da177e4SLinus Torvalds 		dev->id[c][i].devtype = mbuf[0];
19371da177e4SLinus Torvalds 		rmb = mbuf[1];
19381da177e4SLinus Torvalds 		n = mbuf[7];
1939197fb8d8SOndrej Zary 		if (!wide_chip)
1940197fb8d8SOndrej Zary 			goto not_wide;
19411da177e4SLinus Torvalds 		if ((mbuf[7] & 0x60) == 0) {
19421da177e4SLinus Torvalds 			goto not_wide;
19431da177e4SLinus Torvalds 		}
1944197fb8d8SOndrej Zary 		if (dev->dev_id == ATP885_DEVID || dev->dev_id == ATP880_DEVID1 || dev->dev_id == ATP880_DEVID2) {
1945197fb8d8SOndrej Zary 			if ((i < 8) && ((dev->global_map[c] & 0x20) == 0))
1946197fb8d8SOndrej Zary 				goto not_wide;
1947197fb8d8SOndrej Zary 		} else { /* result of is870() merge - is this a bug? */
1948197fb8d8SOndrej Zary 			if ((dev->global_map[c] & 0x20) == 0)
19491da177e4SLinus Torvalds 				goto not_wide;
19501da177e4SLinus Torvalds 		}
19511da177e4SLinus Torvalds 		if (lvdmode == 0) {
19521da177e4SLinus Torvalds 			goto chg_wide;
19531da177e4SLinus Torvalds 		}
195480b52a7fSOndrej Zary 		if (dev->sp[c][i] != 0x04)	// force u2
195580b52a7fSOndrej Zary 		{
19561da177e4SLinus Torvalds 			goto chg_wide;
19571da177e4SLinus Torvalds 		}
19581da177e4SLinus Torvalds 
19595d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x1b, 0x01);
19605d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 3, satn[0]);
19615d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 4, satn[1]);
19625d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 5, satn[2]);
19635d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 6, satn[3]);
19645d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 7, satn[4]);
19655d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 8, satn[5]);
19665d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x0f, 0);
19675d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
19685d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
19695d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, satn[6]);
19705d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, satn[7]);
19715d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, satn[8]);
19721da177e4SLinus Torvalds 
19735d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
19741da177e4SLinus Torvalds 			cpu_relax();
197580b52a7fSOndrej Zary 
197680b52a7fSOndrej Zary 		if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e)
19771da177e4SLinus Torvalds 			continue;
197880b52a7fSOndrej Zary 
19795d2a5a4fSOndrej Zary 		while (atp_readb_io(dev, c, 0x17) != 0x8e)
19801da177e4SLinus Torvalds 			cpu_relax();
198180b52a7fSOndrej Zary 
19821da177e4SLinus Torvalds try_u3:
19831da177e4SLinus Torvalds 		j = 0;
19845d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x09);
19855d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
19861da177e4SLinus Torvalds 
19875d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) {
19885d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0)
19895d2a5a4fSOndrej Zary 				atp_writeb_io(dev, c, 0x19, u3[j++]);
19901da177e4SLinus Torvalds 			cpu_relax();
19911da177e4SLinus Torvalds 		}
199280b52a7fSOndrej Zary 
19935d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00)
19941da177e4SLinus Torvalds 			cpu_relax();
199580b52a7fSOndrej Zary 
19965d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
19971da177e4SLinus Torvalds 		if (j == 0x0f) {
19981da177e4SLinus Torvalds 			goto u3p_in;
19991da177e4SLinus Torvalds 		}
20001da177e4SLinus Torvalds 		if (j == 0x0a) {
20011da177e4SLinus Torvalds 			goto u3p_cmd;
20021da177e4SLinus Torvalds 		}
20031da177e4SLinus Torvalds 		if (j == 0x0e) {
20041da177e4SLinus Torvalds 			goto try_u3;
20051da177e4SLinus Torvalds 		}
20061da177e4SLinus Torvalds 		continue;
20071da177e4SLinus Torvalds u3p_out:
20085d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
20095d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) {
20105d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0)
20115d2a5a4fSOndrej Zary 				atp_writeb_io(dev, c, 0x19, 0);
20121da177e4SLinus Torvalds 			cpu_relax();
20131da177e4SLinus Torvalds 		}
20145d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
20151da177e4SLinus Torvalds 		if (j == 0x0f) {
20161da177e4SLinus Torvalds 			goto u3p_in;
20171da177e4SLinus Torvalds 		}
20181da177e4SLinus Torvalds 		if (j == 0x0a) {
20191da177e4SLinus Torvalds 			goto u3p_cmd;
20201da177e4SLinus Torvalds 		}
20211da177e4SLinus Torvalds 		if (j == 0x0e) {
20221da177e4SLinus Torvalds 			goto u3p_out;
20231da177e4SLinus Torvalds 		}
20241da177e4SLinus Torvalds 		continue;
20251da177e4SLinus Torvalds u3p_in:
20265d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x09);
20275d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
20281da177e4SLinus Torvalds 		k = 0;
20291da177e4SLinus Torvalds u3p_in1:
20305d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x1f);
20311da177e4SLinus Torvalds 		if ((j & 0x01) != 0) {
20325d2a5a4fSOndrej Zary 			mbuf[k++] = atp_readb_io(dev, c, 0x19);
20331da177e4SLinus Torvalds 			goto u3p_in1;
20341da177e4SLinus Torvalds 		}
20351da177e4SLinus Torvalds 		if ((j & 0x80) == 0x00) {
20361da177e4SLinus Torvalds 			goto u3p_in1;
20371da177e4SLinus Torvalds 		}
20385d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
20391da177e4SLinus Torvalds 		if (j == 0x0f) {
20401da177e4SLinus Torvalds 			goto u3p_in;
20411da177e4SLinus Torvalds 		}
20421da177e4SLinus Torvalds 		if (j == 0x0a) {
20431da177e4SLinus Torvalds 			goto u3p_cmd;
20441da177e4SLinus Torvalds 		}
20451da177e4SLinus Torvalds 		if (j == 0x0e) {
20461da177e4SLinus Torvalds 			goto u3p_out;
20471da177e4SLinus Torvalds 		}
20481da177e4SLinus Torvalds 		continue;
20491da177e4SLinus Torvalds u3p_cmd:
20505d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x10, 0x30);
20515d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x00);
20525d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
205380b52a7fSOndrej Zary 
20545d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00);
205580b52a7fSOndrej Zary 
20565d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
20571da177e4SLinus Torvalds 		if (j != 0x16) {
20581da177e4SLinus Torvalds 			if (j == 0x4e) {
20591da177e4SLinus Torvalds 				goto u3p_out;
20601da177e4SLinus Torvalds 			}
20611da177e4SLinus Torvalds 			continue;
20621da177e4SLinus Torvalds 		}
20631da177e4SLinus Torvalds 		if (mbuf[0] != 0x01) {
20641da177e4SLinus Torvalds 			goto chg_wide;
20651da177e4SLinus Torvalds 		}
20661da177e4SLinus Torvalds 		if (mbuf[1] != 0x06) {
20671da177e4SLinus Torvalds 			goto chg_wide;
20681da177e4SLinus Torvalds 		}
20691da177e4SLinus Torvalds 		if (mbuf[2] != 0x04) {
20701da177e4SLinus Torvalds 			goto chg_wide;
20711da177e4SLinus Torvalds 		}
20721da177e4SLinus Torvalds 		if (mbuf[3] == 0x09) {
20731da177e4SLinus Torvalds 			m = 1;
20741da177e4SLinus Torvalds 			m = m << i;
20751da177e4SLinus Torvalds 			dev->wide_id[c] |= m;
20761da177e4SLinus Torvalds 			dev->id[c][i].devsp = 0xce;
20771da177e4SLinus Torvalds #ifdef ED_DBGP
20781da177e4SLinus Torvalds 			printk("dev->id[%2d][%2d].devsp = %2x\n",c,i,dev->id[c][i].devsp);
20791da177e4SLinus Torvalds #endif
20801da177e4SLinus Torvalds 			continue;
20811da177e4SLinus Torvalds 		}
20821da177e4SLinus Torvalds chg_wide:
20835d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x1b, 0x01);
20845d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 3, satn[0]);
20855d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 4, satn[1]);
20865d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 5, satn[2]);
20875d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 6, satn[3]);
20885d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 7, satn[4]);
20895d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 8, satn[5]);
20905d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x0f, 0);
20915d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
20925d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
20935d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, satn[6]);
20945d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, satn[7]);
20955d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, satn[8]);
20961da177e4SLinus Torvalds 
20975d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
20981da177e4SLinus Torvalds 			cpu_relax();
209980b52a7fSOndrej Zary 
210080b52a7fSOndrej Zary 		if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e)
21011da177e4SLinus Torvalds 			continue;
210280b52a7fSOndrej Zary 
21035d2a5a4fSOndrej Zary 		while (atp_readb_io(dev, c, 0x17) != 0x8e)
21041da177e4SLinus Torvalds 			cpu_relax();
210580b52a7fSOndrej Zary 
21061da177e4SLinus Torvalds try_wide:
21071da177e4SLinus Torvalds 		j = 0;
21085d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x05);
21095d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
21101da177e4SLinus Torvalds 
21115d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) {
21125d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0)
21135d2a5a4fSOndrej Zary 				atp_writeb_io(dev, c, 0x19, wide[j++]);
21141da177e4SLinus Torvalds 			cpu_relax();
21151da177e4SLinus Torvalds 		}
211680b52a7fSOndrej Zary 
21175d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00)
21181da177e4SLinus Torvalds 			cpu_relax();
211980b52a7fSOndrej Zary 
21205d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
21211da177e4SLinus Torvalds 		if (j == 0x0f) {
21221da177e4SLinus Torvalds 			goto widep_in;
21231da177e4SLinus Torvalds 		}
21241da177e4SLinus Torvalds 		if (j == 0x0a) {
21251da177e4SLinus Torvalds 			goto widep_cmd;
21261da177e4SLinus Torvalds 		}
21271da177e4SLinus Torvalds 		if (j == 0x0e) {
21281da177e4SLinus Torvalds 			goto try_wide;
21291da177e4SLinus Torvalds 		}
21301da177e4SLinus Torvalds 		continue;
21311da177e4SLinus Torvalds widep_out:
21325d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
21335d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) {
21345d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0)
21355d2a5a4fSOndrej Zary 				atp_writeb_io(dev, c, 0x19, 0);
21361da177e4SLinus Torvalds 			cpu_relax();
21371da177e4SLinus Torvalds 		}
21385d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
21391da177e4SLinus Torvalds 		if (j == 0x0f) {
21401da177e4SLinus Torvalds 			goto widep_in;
21411da177e4SLinus Torvalds 		}
21421da177e4SLinus Torvalds 		if (j == 0x0a) {
21431da177e4SLinus Torvalds 			goto widep_cmd;
21441da177e4SLinus Torvalds 		}
21451da177e4SLinus Torvalds 		if (j == 0x0e) {
21461da177e4SLinus Torvalds 			goto widep_out;
21471da177e4SLinus Torvalds 		}
21481da177e4SLinus Torvalds 		continue;
21491da177e4SLinus Torvalds widep_in:
21505d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0xff);
21515d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
21521da177e4SLinus Torvalds 		k = 0;
21531da177e4SLinus Torvalds widep_in1:
21545d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x1f);
21551da177e4SLinus Torvalds 		if ((j & 0x01) != 0) {
21565d2a5a4fSOndrej Zary 			mbuf[k++] = atp_readb_io(dev, c, 0x19);
21571da177e4SLinus Torvalds 			goto widep_in1;
21581da177e4SLinus Torvalds 		}
21591da177e4SLinus Torvalds 		if ((j & 0x80) == 0x00) {
21601da177e4SLinus Torvalds 			goto widep_in1;
21611da177e4SLinus Torvalds 		}
21625d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
21631da177e4SLinus Torvalds 		if (j == 0x0f) {
21641da177e4SLinus Torvalds 			goto widep_in;
21651da177e4SLinus Torvalds 		}
21661da177e4SLinus Torvalds 		if (j == 0x0a) {
21671da177e4SLinus Torvalds 			goto widep_cmd;
21681da177e4SLinus Torvalds 		}
21691da177e4SLinus Torvalds 		if (j == 0x0e) {
21701da177e4SLinus Torvalds 			goto widep_out;
21711da177e4SLinus Torvalds 		}
21721da177e4SLinus Torvalds 		continue;
21731da177e4SLinus Torvalds widep_cmd:
21745d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x10, 0x30);
21755d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x00);
21765d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
217780b52a7fSOndrej Zary 
21785d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
21791da177e4SLinus Torvalds 			cpu_relax();
218080b52a7fSOndrej Zary 
21815d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
21821da177e4SLinus Torvalds 		if (j != 0x16) {
21831da177e4SLinus Torvalds 			if (j == 0x4e) {
21841da177e4SLinus Torvalds 				goto widep_out;
21851da177e4SLinus Torvalds 			}
21861da177e4SLinus Torvalds 			continue;
21871da177e4SLinus Torvalds 		}
21881da177e4SLinus Torvalds 		if (mbuf[0] != 0x01) {
21891da177e4SLinus Torvalds 			goto not_wide;
21901da177e4SLinus Torvalds 		}
21911da177e4SLinus Torvalds 		if (mbuf[1] != 0x02) {
21921da177e4SLinus Torvalds 			goto not_wide;
21931da177e4SLinus Torvalds 		}
21941da177e4SLinus Torvalds 		if (mbuf[2] != 0x03) {
21951da177e4SLinus Torvalds 			goto not_wide;
21961da177e4SLinus Torvalds 		}
21971da177e4SLinus Torvalds 		if (mbuf[3] != 0x01) {
21981da177e4SLinus Torvalds 			goto not_wide;
21991da177e4SLinus Torvalds 		}
22001da177e4SLinus Torvalds 		m = 1;
22011da177e4SLinus Torvalds 		m = m << i;
22021da177e4SLinus Torvalds 		dev->wide_id[c] |= m;
22031da177e4SLinus Torvalds not_wide:
220480b52a7fSOndrej Zary 		if ((dev->id[c][i].devtype == 0x00) || (dev->id[c][i].devtype == 0x07) || ((dev->id[c][i].devtype == 0x05) && ((n & 0x10) != 0))) {
22051da177e4SLinus Torvalds 			m = 1;
22061da177e4SLinus Torvalds 			m = m << i;
22071da177e4SLinus Torvalds 			if ((dev->async[c] & m) != 0) {
22081da177e4SLinus Torvalds 				goto set_sync;
22091da177e4SLinus Torvalds 			}
22101da177e4SLinus Torvalds 		}
22111da177e4SLinus Torvalds 		continue;
22121da177e4SLinus Torvalds set_sync:
2213460da918SOndrej Zary 		if ((dev->dev_id != ATP885_DEVID && dev->dev_id != ATP880_DEVID1 && dev->dev_id != ATP880_DEVID2) || (dev->sp[c][i] == 0x02)) {
22141da177e4SLinus Torvalds 			synu[4] = 0x0c;
22151da177e4SLinus Torvalds 			synuw[4] = 0x0c;
22161da177e4SLinus Torvalds 		} else {
22171da177e4SLinus Torvalds 			if (dev->sp[c][i] >= 0x03) {
22181da177e4SLinus Torvalds 				synu[4] = 0x0a;
22191da177e4SLinus Torvalds 				synuw[4] = 0x0a;
22201da177e4SLinus Torvalds 			}
22211da177e4SLinus Torvalds 		}
22221da177e4SLinus Torvalds 		j = 0;
22231da177e4SLinus Torvalds 		if ((m & dev->wide_id[c]) != 0) {
22241da177e4SLinus Torvalds 			j |= 0x01;
22251da177e4SLinus Torvalds 		}
22265d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x1b, j);
22275d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 3, satn[0]);
22285d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 4, satn[1]);
22295d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 5, satn[2]);
22305d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 6, satn[3]);
22315d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 7, satn[4]);
22325d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 8, satn[5]);
22335d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x0f, 0);
22345d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
22355d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
22365d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, satn[6]);
22375d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, satn[7]);
22385d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, satn[8]);
22391da177e4SLinus Torvalds 
22405d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
22411da177e4SLinus Torvalds 			cpu_relax();
224280b52a7fSOndrej Zary 
224380b52a7fSOndrej Zary 		if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e)
22441da177e4SLinus Torvalds 			continue;
224580b52a7fSOndrej Zary 
22465d2a5a4fSOndrej Zary 		while (atp_readb_io(dev, c, 0x17) != 0x8e)
22471da177e4SLinus Torvalds 			cpu_relax();
224880b52a7fSOndrej Zary 
22491da177e4SLinus Torvalds try_sync:
22501da177e4SLinus Torvalds 		j = 0;
22515d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x06);
22525d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
22531da177e4SLinus Torvalds 
22545d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) {
22555d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0) {
22561da177e4SLinus Torvalds 				if ((m & dev->wide_id[c]) != 0) {
2257460da918SOndrej Zary 					if (dev->dev_id == ATP885_DEVID || dev->dev_id == ATP880_DEVID1 || dev->dev_id == ATP880_DEVID2) {
22581da177e4SLinus Torvalds 						if ((m & dev->ultra_map[c]) != 0) {
22595d2a5a4fSOndrej Zary 							atp_writeb_io(dev, c, 0x19, synuw[j++]);
22601da177e4SLinus Torvalds 						} else {
22615d2a5a4fSOndrej Zary 							atp_writeb_io(dev, c, 0x19, synw[j++]);
22621da177e4SLinus Torvalds 						}
2263460da918SOndrej Zary 					} else
2264460da918SOndrej Zary 						atp_writeb_io(dev, c, 0x19, synw_870[j++]);
22651da177e4SLinus Torvalds 				} else {
22661da177e4SLinus Torvalds 					if ((m & dev->ultra_map[c]) != 0) {
22675d2a5a4fSOndrej Zary 						atp_writeb_io(dev, c, 0x19, synu[j++]);
22681da177e4SLinus Torvalds 					} else {
22695d2a5a4fSOndrej Zary 						atp_writeb_io(dev, c, 0x19, synn[j++]);
22701da177e4SLinus Torvalds 					}
22711da177e4SLinus Torvalds 				}
22721da177e4SLinus Torvalds 			}
22731da177e4SLinus Torvalds 		}
227480b52a7fSOndrej Zary 
22755d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00)
22761da177e4SLinus Torvalds 			cpu_relax();
227780b52a7fSOndrej Zary 
22785d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
22791da177e4SLinus Torvalds 		if (j == 0x0f) {
22801da177e4SLinus Torvalds 			goto phase_ins;
22811da177e4SLinus Torvalds 		}
22821da177e4SLinus Torvalds 		if (j == 0x0a) {
22831da177e4SLinus Torvalds 			goto phase_cmds;
22841da177e4SLinus Torvalds 		}
22851da177e4SLinus Torvalds 		if (j == 0x0e) {
22861da177e4SLinus Torvalds 			goto try_sync;
22871da177e4SLinus Torvalds 		}
22881da177e4SLinus Torvalds 		continue;
22891da177e4SLinus Torvalds phase_outs:
22905d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
22915d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) {
22925d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0x00)
22935d2a5a4fSOndrej Zary 				atp_writeb_io(dev, c, 0x19, 0x00);
22941da177e4SLinus Torvalds 			cpu_relax();
22951da177e4SLinus Torvalds 		}
22965d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
22971da177e4SLinus Torvalds 		if (j == 0x85) {
22981da177e4SLinus Torvalds 			goto tar_dcons;
22991da177e4SLinus Torvalds 		}
23001da177e4SLinus Torvalds 		j &= 0x0f;
23011da177e4SLinus Torvalds 		if (j == 0x0f) {
23021da177e4SLinus Torvalds 			goto phase_ins;
23031da177e4SLinus Torvalds 		}
23041da177e4SLinus Torvalds 		if (j == 0x0a) {
23051da177e4SLinus Torvalds 			goto phase_cmds;
23061da177e4SLinus Torvalds 		}
23071da177e4SLinus Torvalds 		if (j == 0x0e) {
23081da177e4SLinus Torvalds 			goto phase_outs;
23091da177e4SLinus Torvalds 		}
23101da177e4SLinus Torvalds 		continue;
23111da177e4SLinus Torvalds phase_ins:
2312460da918SOndrej Zary 		if (dev->dev_id == ATP885_DEVID || dev->dev_id == ATP880_DEVID1 || dev->dev_id == ATP880_DEVID2)
23135d2a5a4fSOndrej Zary 			atp_writeb_io(dev, c, 0x14, 0x06);
2314460da918SOndrej Zary 		else
2315460da918SOndrej Zary 			atp_writeb_io(dev, c, 0x14, 0xff);
23165d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
23171da177e4SLinus Torvalds 		k = 0;
23181da177e4SLinus Torvalds phase_ins1:
23195d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x1f);
23201da177e4SLinus Torvalds 		if ((j & 0x01) != 0x00) {
23215d2a5a4fSOndrej Zary 			mbuf[k++] = atp_readb_io(dev, c, 0x19);
23221da177e4SLinus Torvalds 			goto phase_ins1;
23231da177e4SLinus Torvalds 		}
23241da177e4SLinus Torvalds 		if ((j & 0x80) == 0x00) {
23251da177e4SLinus Torvalds 			goto phase_ins1;
23261da177e4SLinus Torvalds 		}
232780b52a7fSOndrej Zary 
23285d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00);
232980b52a7fSOndrej Zary 
23305d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
23311da177e4SLinus Torvalds 		if (j == 0x85) {
23321da177e4SLinus Torvalds 			goto tar_dcons;
23331da177e4SLinus Torvalds 		}
23341da177e4SLinus Torvalds 		j &= 0x0f;
23351da177e4SLinus Torvalds 		if (j == 0x0f) {
23361da177e4SLinus Torvalds 			goto phase_ins;
23371da177e4SLinus Torvalds 		}
23381da177e4SLinus Torvalds 		if (j == 0x0a) {
23391da177e4SLinus Torvalds 			goto phase_cmds;
23401da177e4SLinus Torvalds 		}
23411da177e4SLinus Torvalds 		if (j == 0x0e) {
23421da177e4SLinus Torvalds 			goto phase_outs;
23431da177e4SLinus Torvalds 		}
23441da177e4SLinus Torvalds 		continue;
23451da177e4SLinus Torvalds phase_cmds:
23465d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x10, 0x30);
23471da177e4SLinus Torvalds tar_dcons:
23485d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x00);
23495d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
235080b52a7fSOndrej Zary 
23515d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
23521da177e4SLinus Torvalds 			cpu_relax();
235380b52a7fSOndrej Zary 
23545d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
23551da177e4SLinus Torvalds 		if (j != 0x16) {
23561da177e4SLinus Torvalds 			continue;
23571da177e4SLinus Torvalds 		}
23581da177e4SLinus Torvalds 		if (mbuf[0] != 0x01) {
23591da177e4SLinus Torvalds 			continue;
23601da177e4SLinus Torvalds 		}
23611da177e4SLinus Torvalds 		if (mbuf[1] != 0x03) {
23621da177e4SLinus Torvalds 			continue;
23631da177e4SLinus Torvalds 		}
23641da177e4SLinus Torvalds 		if (mbuf[4] == 0x00) {
23651da177e4SLinus Torvalds 			continue;
23661da177e4SLinus Torvalds 		}
23671da177e4SLinus Torvalds 		if (mbuf[3] > 0x64) {
23681da177e4SLinus Torvalds 			continue;
23691da177e4SLinus Torvalds 		}
2370460da918SOndrej Zary 		if (dev->dev_id == ATP885_DEVID || dev->dev_id == ATP880_DEVID1 || dev->dev_id == ATP880_DEVID2) {
23711da177e4SLinus Torvalds 			if (mbuf[4] > 0x0e) {
23721da177e4SLinus Torvalds 				mbuf[4] = 0x0e;
23731da177e4SLinus Torvalds 			}
2374460da918SOndrej Zary 		} else {
2375460da918SOndrej Zary 			if (mbuf[4] > 0x0c) {
2376460da918SOndrej Zary 				mbuf[4] = 0x0c;
2377460da918SOndrej Zary 			}
2378460da918SOndrej Zary 		}
23791da177e4SLinus Torvalds 		dev->id[c][i].devsp = mbuf[4];
2380460da918SOndrej Zary 		if (dev->dev_id == ATP885_DEVID || dev->dev_id == ATP880_DEVID1 || dev->dev_id == ATP880_DEVID2)
23811da177e4SLinus Torvalds 			if (mbuf[3] < 0x0c) {
23821da177e4SLinus Torvalds 				j = 0xb0;
23831da177e4SLinus Torvalds 				goto set_syn_ok;
23841da177e4SLinus Torvalds 			}
23851da177e4SLinus Torvalds 		if ((mbuf[3] < 0x0d) && (rmb == 0)) {
23861da177e4SLinus Torvalds 			j = 0xa0;
23871da177e4SLinus Torvalds 			goto set_syn_ok;
23881da177e4SLinus Torvalds 		}
23891da177e4SLinus Torvalds 		if (mbuf[3] < 0x1a) {
23901da177e4SLinus Torvalds 			j = 0x20;
23911da177e4SLinus Torvalds 			goto set_syn_ok;
23921da177e4SLinus Torvalds 		}
23931da177e4SLinus Torvalds 		if (mbuf[3] < 0x33) {
23941da177e4SLinus Torvalds 			j = 0x40;
23951da177e4SLinus Torvalds 			goto set_syn_ok;
23961da177e4SLinus Torvalds 		}
23971da177e4SLinus Torvalds 		if (mbuf[3] < 0x4c) {
23981da177e4SLinus Torvalds 			j = 0x50;
23991da177e4SLinus Torvalds 			goto set_syn_ok;
24001da177e4SLinus Torvalds 		}
24011da177e4SLinus Torvalds 		j = 0x60;
24021da177e4SLinus Torvalds set_syn_ok:
24031da177e4SLinus Torvalds 		dev->id[c][i].devsp = (dev->id[c][i].devsp & 0x0f) | j;
24041da177e4SLinus Torvalds #ifdef ED_DBGP
24051da177e4SLinus Torvalds 		printk("dev->id[%2d][%2d].devsp = %2x\n",c,i,dev->id[c][i].devsp);
24061da177e4SLinus Torvalds #endif
24071da177e4SLinus Torvalds 	}
24081da177e4SLinus Torvalds }
24091da177e4SLinus Torvalds 
24101da177e4SLinus Torvalds module_init(atp870u_init);
24111da177e4SLinus Torvalds module_exit(atp870u_exit);
24121da177e4SLinus Torvalds 
2413