xref: /openbmc/linux/drivers/scsi/atp870u.c (revision 6c9b9c55)
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 
957dd5a5f79SOndrej Zary static void tscam(struct Scsi_Host *host, bool wide_chip)
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;
986dd5a5f79SOndrej Zary 	if (!wide_chip) {
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);
1015dd5a5f79SOndrej Zary 		if (wide_chip)
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;
12486c9b9c55SOndrej Zary 	unsigned int error,n;
12491da177e4SLinus Torvalds 	unsigned char host_id;
12501da177e4SLinus Torvalds 	struct Scsi_Host *shpnt = NULL;
1251bdd5ac40SOndrej Zary 	struct atp_unit *atpdev;
12521da177e4SLinus Torvalds 	unsigned char setupdata[2][16];
1253bdd5ac40SOndrej Zary 	int err;
12541da177e4SLinus Torvalds 
1255b1e85063SOndrej Zary 	if (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610 && pdev->revision < 2) {
1256b1e85063SOndrej Zary 		dev_err(&pdev->dev, "ATP850S chips (AEC6710L/F cards) are not supported.\n");
1257b1e85063SOndrej Zary 		return -ENODEV;
1258b1e85063SOndrej Zary 	}
1259b1e85063SOndrej Zary 
1260bdd5ac40SOndrej Zary 	err = pci_enable_device(pdev);
1261bdd5ac40SOndrej Zary 	if (err)
1262bdd5ac40SOndrej Zary 		goto fail;
12631da177e4SLinus Torvalds 
126434a2c35dSOndrej Zary 	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
12651da177e4SLinus Torvalds                 printk(KERN_ERR "atp870u: DMA mask required but not available.\n");
1266bdd5ac40SOndrej Zary                 err = -EIO;
1267bdd5ac40SOndrej Zary                 goto disable_device;
12681da177e4SLinus Torvalds         }
12691da177e4SLinus Torvalds 
1270bdd5ac40SOndrej Zary         err = -ENOMEM;
1271bdd5ac40SOndrej Zary 	shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
1272bdd5ac40SOndrej Zary 	if (!shpnt)
1273bdd5ac40SOndrej Zary 		goto disable_device;
1274bdd5ac40SOndrej Zary 
1275bdd5ac40SOndrej Zary 	atpdev = shost_priv(shpnt);
1276bdd5ac40SOndrej Zary 
1277bdd5ac40SOndrej Zary 	atpdev->host = shpnt;
1278bdd5ac40SOndrej Zary 	atpdev->pdev = pdev;
1279bdd5ac40SOndrej Zary 	pci_set_drvdata(pdev, atpdev);
1280bdd5ac40SOndrej Zary 
12816c9b9c55SOndrej Zary 	shpnt->io_port = pci_resource_start(pdev, 0);
12826c9b9c55SOndrej Zary 	shpnt->io_port &= 0xfffffff8;
12836c9b9c55SOndrej Zary 	shpnt->n_io_port = pci_resource_len(pdev, 0);
12846c9b9c55SOndrej Zary 	atpdev->baseport = shpnt->io_port;
12856c9b9c55SOndrej Zary 	shpnt->unique_id = shpnt->io_port;
12866c9b9c55SOndrej Zary 	shpnt->irq = pdev->irq;
12871da177e4SLinus Torvalds 
12881da177e4SLinus Torvalds 	if ((ent->device == ATP880_DEVID1)||(ent->device == ATP880_DEVID2)) {
12891da177e4SLinus Torvalds 		pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80);//JCC082803
12901da177e4SLinus Torvalds 
12916c9b9c55SOndrej Zary 		atpdev->ioport[0] = shpnt->io_port + 0x40;
12926c9b9c55SOndrej Zary 		atpdev->pciport[0] = shpnt->io_port + 0x28;
1293d804bb25SOndrej Zary 
1294d804bb25SOndrej Zary 		host_id = atp_readb_base(atpdev, 0x39);
12951da177e4SLinus Torvalds 		host_id >>= 0x04;
12961da177e4SLinus Torvalds 
1297c48442d1SOndrej Zary 		printk(KERN_INFO "   ACARD AEC-67160 PCI Ultra3 LVD Host Adapter:"
12986c9b9c55SOndrej Zary 			"    IO:%lx, IRQ:%d.\n", shpnt->io_port, shpnt->irq);
1299dc6a78f1SRandy Dunlap 		atpdev->dev_id = ent->device;
1300dc6a78f1SRandy Dunlap 		atpdev->host_id[0] = host_id;
13011da177e4SLinus Torvalds 
1302d804bb25SOndrej Zary 		atpdev->scam_on = atp_readb_base(atpdev, 0x22);
1303d804bb25SOndrej Zary 		atpdev->global_map[0] = atp_readb_base(atpdev, 0x35);
1304d804bb25SOndrej Zary 		atpdev->ultra_map[0] = atp_readw_base(atpdev, 0x3c);
13051da177e4SLinus Torvalds 
13061da177e4SLinus Torvalds 		n = 0x3f09;
13071da177e4SLinus Torvalds next_fblk_880:
13081da177e4SLinus Torvalds 		if (n >= 0x4000)
13091da177e4SLinus Torvalds 			goto flash_ok_880;
13101da177e4SLinus Torvalds 
13111da177e4SLinus Torvalds 		m = 0;
1312d804bb25SOndrej Zary 		atp_writew_base(atpdev, 0x34, n);
13131da177e4SLinus Torvalds 		n += 0x0002;
1314d804bb25SOndrej Zary 		if (atp_readb_base(atpdev, 0x30) == 0xff)
13151da177e4SLinus Torvalds 			goto flash_ok_880;
13161da177e4SLinus Torvalds 
1317d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30);
1318d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31);
1319d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32);
1320d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33);
1321d804bb25SOndrej Zary 		atp_writew_base(atpdev, 0x34, n);
13221da177e4SLinus Torvalds 		n += 0x0002;
1323d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30);
1324d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31);
1325d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32);
1326d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33);
1327d804bb25SOndrej Zary 		atp_writew_base(atpdev, 0x34, n);
13281da177e4SLinus Torvalds 		n += 0x0002;
1329d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30);
1330d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31);
1331d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32);
1332d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33);
1333d804bb25SOndrej Zary 		atp_writew_base(atpdev, 0x34, n);
13341da177e4SLinus Torvalds 		n += 0x0002;
1335d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30);
1336d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31);
1337d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32);
1338d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33);
13391da177e4SLinus Torvalds 		n += 0x0018;
13401da177e4SLinus Torvalds 		goto next_fblk_880;
13411da177e4SLinus Torvalds flash_ok_880:
1342d804bb25SOndrej Zary 		atp_writew_base(atpdev, 0x34, 0);
1343dc6a78f1SRandy Dunlap 		atpdev->ultra_map[0] = 0;
1344dc6a78f1SRandy Dunlap 		atpdev->async[0] = 0;
13451da177e4SLinus Torvalds 		for (k = 0; k < 16; k++) {
13461da177e4SLinus Torvalds 			n = 1;
13471da177e4SLinus Torvalds 			n = n << k;
1348dc6a78f1SRandy Dunlap 			if (atpdev->sp[0][k] > 1) {
1349dc6a78f1SRandy Dunlap 				atpdev->ultra_map[0] |= n;
13501da177e4SLinus Torvalds 			} else {
1351dc6a78f1SRandy Dunlap 				if (atpdev->sp[0][k] == 0)
1352dc6a78f1SRandy Dunlap 					atpdev->async[0] |= n;
13531da177e4SLinus Torvalds  			}
13541da177e4SLinus Torvalds 	 	}
1355dc6a78f1SRandy Dunlap 		atpdev->async[0] = ~(atpdev->async[0]);
1356d804bb25SOndrej Zary 		atp_writeb_base(atpdev, 0x35, atpdev->global_map[0]);
13571da177e4SLinus Torvalds 
13581da177e4SLinus Torvalds 		if (atp870u_init_tables(shpnt) < 0) {
13591da177e4SLinus Torvalds 			printk(KERN_ERR "Unable to allocate tables for Acard controller\n");
1360bdd5ac40SOndrej Zary 			err = -ENOMEM;
13611da177e4SLinus Torvalds 			goto unregister;
13621da177e4SLinus Torvalds 		}
13631da177e4SLinus Torvalds 
13646c9b9c55SOndrej Zary 		err = request_irq(shpnt->irq, atp870u_intr_handle, IRQF_SHARED, "atp880i", shpnt);
1365bdd5ac40SOndrej Zary 		if (err) {
13666c9b9c55SOndrej Zary 			printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", shpnt->irq);
13671da177e4SLinus Torvalds 			goto free_tables;
13681da177e4SLinus Torvalds 		}
13691da177e4SLinus Torvalds 
13701da177e4SLinus Torvalds 		spin_lock_irqsave(shpnt->host_lock, flags);
1371bdd5ac40SOndrej Zary 		k = atp_readb_base(atpdev, 0x38) & 0x80;
1372bdd5ac40SOndrej Zary 		atp_writeb_base(atpdev, 0x38, k);
1373bdd5ac40SOndrej Zary 		atp_writeb_base(atpdev, 0x3b, 0x20);
13741da177e4SLinus Torvalds 		mdelay(32);
1375bdd5ac40SOndrej Zary 		atp_writeb_base(atpdev, 0x3b, 0);
13761da177e4SLinus Torvalds 		mdelay(32);
1377bdd5ac40SOndrej Zary 		atp_readb_io(atpdev, 0, 0x1b);
1378bdd5ac40SOndrej Zary 		atp_readb_io(atpdev, 0, 0x17);
13796a1961bcSOndrej Zary 
1380bdd5ac40SOndrej Zary 		atp_set_host_id(atpdev, 0, host_id);
13811da177e4SLinus Torvalds 
1382dd5a5f79SOndrej Zary 		tscam(shpnt, true);
1383bdd5ac40SOndrej Zary 		atp_is(atpdev, 0, true, atp_readb_base(atpdev, 0x3f) & 0x40);
1384bdd5ac40SOndrej Zary 		atp_writeb_base(atpdev, 0x38, 0xb0);
13851da177e4SLinus Torvalds 		shpnt->max_id = 16;
13861da177e4SLinus Torvalds 		shpnt->this_id = host_id;
13871da177e4SLinus Torvalds 	} else if (ent->device == ATP885_DEVID) {
13886c9b9c55SOndrej Zary 			printk(KERN_INFO "   ACARD AEC-67162 PCI Ultra3 LVD Host Adapter:  IO:%lx, IRQ:%d.\n"
13896c9b9c55SOndrej Zary 			       , shpnt->io_port, shpnt->irq);
13901da177e4SLinus Torvalds 
1391dc6a78f1SRandy Dunlap 		atpdev->pdev = pdev;
1392dc6a78f1SRandy Dunlap 		atpdev->dev_id  = ent->device;
13936c9b9c55SOndrej Zary 		atpdev->ioport[0] = shpnt->io_port + 0x80;
13946c9b9c55SOndrej Zary 		atpdev->ioport[1] = shpnt->io_port + 0xc0;
13956c9b9c55SOndrej Zary 		atpdev->pciport[0] = shpnt->io_port + 0x40;
13966c9b9c55SOndrej Zary 		atpdev->pciport[1] = shpnt->io_port + 0x50;
13971da177e4SLinus Torvalds 
1398bdd5ac40SOndrej Zary 		if (atp870u_init_tables(shpnt) < 0) {
1399bdd5ac40SOndrej Zary 			err = -ENOMEM;
14001da177e4SLinus Torvalds 			goto unregister;
1401bdd5ac40SOndrej Zary 		}
14021da177e4SLinus Torvalds 
14031da177e4SLinus Torvalds #ifdef ED_DBGP
1404bdd5ac40SOndrej Zary 	printk("request_irq() shpnt %p hostdata %p\n", shpnt, atpdev);
14051da177e4SLinus Torvalds #endif
14066c9b9c55SOndrej Zary 		err = request_irq(shpnt->irq, atp870u_intr_handle, IRQF_SHARED, "atp870u", shpnt);
1407bdd5ac40SOndrej Zary 		if (err) {
14081da177e4SLinus Torvalds 				printk(KERN_ERR "Unable to allocate IRQ for Acard controller.\n");
14091da177e4SLinus Torvalds 			goto free_tables;
14101da177e4SLinus Torvalds 		}
14111da177e4SLinus Torvalds 
14121da177e4SLinus Torvalds 		spin_lock_irqsave(shpnt->host_lock, flags);
14131da177e4SLinus Torvalds 
1414bdd5ac40SOndrej Zary 		c = atp_readb_base(atpdev, 0x29);
1415bdd5ac40SOndrej Zary 		atp_writeb_base(atpdev, 0x29, c | 0x04);
14161da177e4SLinus Torvalds 
14171da177e4SLinus Torvalds 		n=0x1f80;
14181da177e4SLinus Torvalds next_fblk_885:
14191da177e4SLinus Torvalds 		if (n >= 0x2000) {
14201da177e4SLinus Torvalds 		   goto flash_ok_885;
14211da177e4SLinus Torvalds 		}
1422bdd5ac40SOndrej Zary 		atp_writew_base(atpdev, 0x3c, n);
1423bdd5ac40SOndrej Zary 		if (atp_readl_base(atpdev, 0x38) == 0xffffffff) {
14241da177e4SLinus Torvalds 		   goto flash_ok_885;
14251da177e4SLinus Torvalds 		}
14261da177e4SLinus Torvalds 		for (m=0; m < 2; m++) {
1427bdd5ac40SOndrej Zary 		    atpdev->global_map[m]= 0;
14281da177e4SLinus Torvalds 		    for (k=0; k < 4; k++) {
1429bdd5ac40SOndrej Zary 			atp_writew_base(atpdev, 0x3c, n++);
1430bdd5ac40SOndrej Zary 			((unsigned long *)&setupdata[m][0])[k] = atp_readl_base(atpdev, 0x38);
14311da177e4SLinus Torvalds 		    }
14321da177e4SLinus Torvalds 		    for (k=0; k < 4; k++) {
1433bdd5ac40SOndrej Zary 			atp_writew_base(atpdev, 0x3c, n++);
1434bdd5ac40SOndrej Zary 			((unsigned long *)&atpdev->sp[m][0])[k] = atp_readl_base(atpdev, 0x38);
14351da177e4SLinus Torvalds 		    }
14361da177e4SLinus Torvalds 		    n += 8;
14371da177e4SLinus Torvalds 		}
14381da177e4SLinus Torvalds 		goto next_fblk_885;
14391da177e4SLinus Torvalds flash_ok_885:
14401da177e4SLinus Torvalds #ifdef ED_DBGP
14411da177e4SLinus Torvalds 		printk( "Flash Read OK\n");
14421da177e4SLinus Torvalds #endif
1443bdd5ac40SOndrej Zary 		c = atp_readb_base(atpdev, 0x29);
1444bdd5ac40SOndrej Zary 		atp_writeb_base(atpdev, 0x29, c & 0xfb);
14451da177e4SLinus Torvalds 		for (c=0;c < 2;c++) {
1446bdd5ac40SOndrej Zary 		    atpdev->ultra_map[c]=0;
1447bdd5ac40SOndrej Zary 		    atpdev->async[c] = 0;
14481da177e4SLinus Torvalds 		    for (k=0; k < 16; k++) {
14491da177e4SLinus Torvalds 			n=1;
14501da177e4SLinus Torvalds 			n = n << k;
1451bdd5ac40SOndrej Zary 			if (atpdev->sp[c][k] > 1) {
1452bdd5ac40SOndrej Zary 			   atpdev->ultra_map[c] |= n;
14531da177e4SLinus Torvalds 			} else {
1454bdd5ac40SOndrej Zary 			   if (atpdev->sp[c][k] == 0) {
1455bdd5ac40SOndrej Zary 			      atpdev->async[c] |= n;
14561da177e4SLinus Torvalds 			   }
14571da177e4SLinus Torvalds 			}
14581da177e4SLinus Torvalds 		    }
1459bdd5ac40SOndrej Zary 		    atpdev->async[c] = ~(atpdev->async[c]);
14601da177e4SLinus Torvalds 
1461bdd5ac40SOndrej Zary 		    if (atpdev->global_map[c] == 0) {
14621da177e4SLinus Torvalds 		       k=setupdata[c][1];
14631da177e4SLinus Torvalds 		       if ((k & 0x40) != 0)
1464bdd5ac40SOndrej Zary 			  atpdev->global_map[c] |= 0x20;
14651da177e4SLinus Torvalds 		       k &= 0x07;
1466bdd5ac40SOndrej Zary 		       atpdev->global_map[c] |= k;
14671da177e4SLinus Torvalds 		       if ((setupdata[c][2] & 0x04) != 0)
1468bdd5ac40SOndrej Zary 			  atpdev->global_map[c] |= 0x08;
1469bdd5ac40SOndrej Zary 		       atpdev->host_id[c] = setupdata[c][0] & 0x07;
14701da177e4SLinus Torvalds 		    }
14711da177e4SLinus Torvalds 		}
14721da177e4SLinus Torvalds 
1473bdd5ac40SOndrej Zary 		k = atp_readb_base(atpdev, 0x28) & 0x8f;
14741da177e4SLinus Torvalds 		k |= 0x10;
1475bdd5ac40SOndrej Zary 		atp_writeb_base(atpdev, 0x28, k);
1476bdd5ac40SOndrej Zary 		atp_writeb_pci(atpdev, 0, 1, 0x80);
1477bdd5ac40SOndrej Zary 		atp_writeb_pci(atpdev, 1, 1, 0x80);
14781da177e4SLinus Torvalds 		mdelay(100);
1479bdd5ac40SOndrej Zary 		atp_writeb_pci(atpdev, 0, 1, 0);
1480bdd5ac40SOndrej Zary 		atp_writeb_pci(atpdev, 1, 1, 0);
14811da177e4SLinus Torvalds 		mdelay(1000);
1482bdd5ac40SOndrej Zary 		atp_readb_io(atpdev, 0, 0x1b);
1483bdd5ac40SOndrej Zary 		atp_readb_io(atpdev, 0, 0x17);
1484bdd5ac40SOndrej Zary 		atp_readb_io(atpdev, 1, 0x1b);
1485bdd5ac40SOndrej Zary 		atp_readb_io(atpdev, 1, 0x17);
14866a1961bcSOndrej Zary 
1487bdd5ac40SOndrej Zary 		k=atpdev->host_id[0];
14881da177e4SLinus Torvalds 		if (k > 7)
14891da177e4SLinus Torvalds 		   k = (k & 0x07) | 0x40;
1490bdd5ac40SOndrej Zary 		atp_set_host_id(atpdev, 0, k);
14911da177e4SLinus Torvalds 
1492bdd5ac40SOndrej Zary 		k=atpdev->host_id[1];
14931da177e4SLinus Torvalds 		if (k > 7)
14941da177e4SLinus Torvalds 		   k = (k & 0x07) | 0x40;
1495bdd5ac40SOndrej Zary 		atp_set_host_id(atpdev, 1, k);
14961da177e4SLinus Torvalds 
1497c4ad92bcSOndrej Zary 		mdelay(600); /* this delay used to be called tscam_885() */
14981da177e4SLinus Torvalds 		printk(KERN_INFO "   Scanning Channel A SCSI Device ...\n");
1499bdd5ac40SOndrej Zary 		atp_is(atpdev, 0, true, atp_readb_io(atpdev, 0, 0x1b) >> 7);
1500bdd5ac40SOndrej Zary 		atp_writeb_io(atpdev, 0, 0x16, 0x80);
15011da177e4SLinus Torvalds 		printk(KERN_INFO "   Scanning Channel B SCSI Device ...\n");
1502bdd5ac40SOndrej Zary 		atp_is(atpdev, 1, true, atp_readb_io(atpdev, 1, 0x1b) >> 7);
1503bdd5ac40SOndrej Zary 		atp_writeb_io(atpdev, 1, 0x16, 0x80);
1504bdd5ac40SOndrej Zary 		k = atp_readb_base(atpdev, 0x28) & 0xcf;
15051da177e4SLinus Torvalds 		k |= 0xc0;
1506bdd5ac40SOndrej Zary 		atp_writeb_base(atpdev, 0x28, k);
1507bdd5ac40SOndrej Zary 		k = atp_readb_base(atpdev, 0x1f) | 0x80;
1508bdd5ac40SOndrej Zary 		atp_writeb_base(atpdev, 0x1f, k);
1509bdd5ac40SOndrej Zary 		k = atp_readb_base(atpdev, 0x29) | 0x01;
1510bdd5ac40SOndrej Zary 		atp_writeb_base(atpdev, 0x29, k);
15111da177e4SLinus Torvalds #ifdef ED_DBGP
15121da177e4SLinus Torvalds 		//printk("atp885: atp_host[0] 0x%p\n", atp_host[0]);
15131da177e4SLinus Torvalds #endif
15141da177e4SLinus Torvalds 		shpnt->max_id = 16;
1515bdd5ac40SOndrej Zary 		shpnt->max_lun = (atpdev->global_map[0] & 0x07) + 1;
15161da177e4SLinus Torvalds 		shpnt->max_channel = 1;
1517bdd5ac40SOndrej Zary 		shpnt->this_id = atpdev->host_id[0];
15181da177e4SLinus Torvalds 	} else {
1519dd5a5f79SOndrej Zary 		bool wide_chip =
1520dd5a5f79SOndrej Zary 			(ent->device == PCI_DEVICE_ID_ARTOP_AEC7610 &&
1521dd5a5f79SOndrej Zary 			 pdev->revision == 4) ||
1522dd5a5f79SOndrej Zary 			(ent->device == PCI_DEVICE_ID_ARTOP_AEC7612UW) ||
1523dd5a5f79SOndrej Zary 			(ent->device == PCI_DEVICE_ID_ARTOP_AEC7612SUW);
15241da177e4SLinus Torvalds 		error = pci_read_config_byte(pdev, 0x49, &host_id);
15251da177e4SLinus Torvalds 
1526c48442d1SOndrej Zary 		printk(KERN_INFO "   ACARD AEC-671X PCI Ultra/W SCSI-2/3 Host Adapter: "
15276c9b9c55SOndrej Zary 			"IO:%lx, IRQ:%d.\n", shpnt->io_port, shpnt->irq);
15281da177e4SLinus Torvalds 
15296c9b9c55SOndrej Zary 		atpdev->ioport[0] = shpnt->io_port;
15306c9b9c55SOndrej Zary 		atpdev->pciport[0] = shpnt->io_port + 0x20;
1531dc6a78f1SRandy Dunlap 		atpdev->dev_id = ent->device;
15321da177e4SLinus Torvalds 		host_id &= 0x07;
1533dc6a78f1SRandy Dunlap 		atpdev->host_id[0] = host_id;
1534d804bb25SOndrej Zary 		atpdev->scam_on = atp_readb_pci(atpdev, 0, 2);
1535d804bb25SOndrej Zary 		atpdev->global_map[0] = atp_readb_base(atpdev, 0x2d);
1536d804bb25SOndrej Zary 		atpdev->ultra_map[0] = atp_readw_base(atpdev, 0x2e);
15371da177e4SLinus Torvalds 
1538dc6a78f1SRandy Dunlap 		if (atpdev->ultra_map[0] == 0) {
1539dc6a78f1SRandy Dunlap 			atpdev->scam_on = 0x00;
1540dc6a78f1SRandy Dunlap 			atpdev->global_map[0] = 0x20;
1541dc6a78f1SRandy Dunlap 			atpdev->ultra_map[0] = 0xffff;
15421da177e4SLinus Torvalds 		}
15431da177e4SLinus Torvalds 
15441da177e4SLinus Torvalds 
1545bdd5ac40SOndrej Zary 		if (atp870u_init_tables(shpnt) < 0) {
1546bdd5ac40SOndrej Zary 			err = -ENOMEM;
15471da177e4SLinus Torvalds 			goto unregister;
1548bdd5ac40SOndrej Zary 		}
15491da177e4SLinus Torvalds 
15506c9b9c55SOndrej Zary 		err = request_irq(shpnt->irq, atp870u_intr_handle, IRQF_SHARED, "atp870i", shpnt);
1551bdd5ac40SOndrej Zary 		if (err) {
15526c9b9c55SOndrej Zary 			printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", shpnt->irq);
15531da177e4SLinus Torvalds 			goto free_tables;
15541da177e4SLinus Torvalds 		}
15551da177e4SLinus Torvalds 
15561da177e4SLinus Torvalds 		spin_lock_irqsave(shpnt->host_lock, flags);
1557dd5a5f79SOndrej Zary 		if (pdev->revision > 0x07)	/* check if atp876 chip then enable terminator */
1558bdd5ac40SOndrej Zary 			atp_writeb_base(atpdev, 0x3e, 0x00);
15591da177e4SLinus Torvalds 
1560bdd5ac40SOndrej Zary 		k = (atp_readb_base(atpdev, 0x3a) & 0xf3) | 0x10;
1561bdd5ac40SOndrej Zary 		atp_writeb_base(atpdev, 0x3a, k);
1562bdd5ac40SOndrej Zary 		atp_writeb_base(atpdev, 0x3a, k & 0xdf);
15631da177e4SLinus Torvalds 		mdelay(32);
1564bdd5ac40SOndrej Zary 		atp_writeb_base(atpdev, 0x3a, k);
15651da177e4SLinus Torvalds 		mdelay(32);
1566bdd5ac40SOndrej Zary 		atp_set_host_id(atpdev, 0, host_id);
15671da177e4SLinus Torvalds 
1568dd5a5f79SOndrej Zary 
1569dd5a5f79SOndrej Zary 		tscam(shpnt, wide_chip);
1570bdd5ac40SOndrej Zary 		atp_writeb_base(atpdev, 0x3a, atp_readb_base(atpdev, 0x3a) | 0x10);
1571dd5a5f79SOndrej Zary 		atp_is(atpdev, 0, wide_chip, 0);
1572bdd5ac40SOndrej Zary 		atp_writeb_base(atpdev, 0x3a, atp_readb_base(atpdev, 0x3a) & 0xef);
1573bdd5ac40SOndrej Zary 		atp_writeb_base(atpdev, 0x3b, atp_readb_base(atpdev, 0x3b) | 0x20);
1574dd5a5f79SOndrej Zary 		shpnt->max_id = wide_chip ? 16 : 8;
15751da177e4SLinus Torvalds 		shpnt->this_id = host_id;
15766c9b9c55SOndrej Zary 
15771da177e4SLinus Torvalds 	}
15781da177e4SLinus Torvalds 		spin_unlock_irqrestore(shpnt->host_lock, flags);
15796c9b9c55SOndrej Zary 		if (!request_region(shpnt->io_port, shpnt->n_io_port, "atp870u")) {
1580bdd5ac40SOndrej Zary 			err = -EBUSY;
15811da177e4SLinus Torvalds 			goto request_io_fail;
1582bdd5ac40SOndrej Zary 		}
1583bdd5ac40SOndrej Zary 		err = scsi_add_host(shpnt, &pdev->dev);
1584bdd5ac40SOndrej Zary 		if (err)
15851da177e4SLinus Torvalds 			goto scsi_add_fail;
15861da177e4SLinus Torvalds 		scsi_scan_host(shpnt);
15871da177e4SLinus Torvalds #ifdef ED_DBGP
15881da177e4SLinus Torvalds 		printk("atp870u_prob : exit\n");
15891da177e4SLinus Torvalds #endif
15901da177e4SLinus Torvalds 		return 0;
15911da177e4SLinus Torvalds 
15921da177e4SLinus Torvalds scsi_add_fail:
15931da177e4SLinus Torvalds 	printk("atp870u_prob:scsi_add_fail\n");
15946c9b9c55SOndrej Zary 	release_region(shpnt->io_port, shpnt->n_io_port);
15951da177e4SLinus Torvalds request_io_fail:
15961da177e4SLinus Torvalds 	printk("atp870u_prob:request_io_fail\n");
15976c9b9c55SOndrej Zary 	free_irq(shpnt->irq, shpnt);
15981da177e4SLinus Torvalds free_tables:
15991da177e4SLinus Torvalds 	printk("atp870u_prob:free_table\n");
16001da177e4SLinus Torvalds 	atp870u_free_tables(shpnt);
16011da177e4SLinus Torvalds unregister:
16021da177e4SLinus Torvalds 	scsi_host_put(shpnt);
1603bdd5ac40SOndrej Zary disable_device:
1604bdd5ac40SOndrej Zary 	pci_disable_device(pdev);
1605bdd5ac40SOndrej Zary fail:
1606bdd5ac40SOndrej Zary 	return err;
16071da177e4SLinus Torvalds }
16081da177e4SLinus Torvalds 
16091da177e4SLinus Torvalds /* The abort command does not leave the device in a clean state where
16101da177e4SLinus Torvalds    it is available to be used again.  Until this gets worked out, we will
16111da177e4SLinus Torvalds    leave it commented out.  */
16121da177e4SLinus Torvalds 
16131da177e4SLinus Torvalds static int atp870u_abort(struct scsi_cmnd * SCpnt)
16141da177e4SLinus Torvalds {
16151da177e4SLinus Torvalds 	unsigned char  j, k, c;
16161da177e4SLinus Torvalds 	struct scsi_cmnd *workrequ;
16171da177e4SLinus Torvalds 	struct atp_unit *dev;
16181da177e4SLinus Torvalds 	struct Scsi_Host *host;
16191da177e4SLinus Torvalds 	host = SCpnt->device->host;
16201da177e4SLinus Torvalds 
16211da177e4SLinus Torvalds 	dev = (struct atp_unit *)&host->hostdata;
1622422c0d61SJeff Garzik 	c = scmd_channel(SCpnt);
16231da177e4SLinus Torvalds 	printk(" atp870u: abort Channel = %x \n", c);
16241da177e4SLinus Torvalds 	printk("working=%x last_cmd=%x ", dev->working[c], dev->last_cmd[c]);
16251da177e4SLinus Torvalds 	printk(" quhdu=%x quendu=%x ", dev->quhd[c], dev->quend[c]);
16261da177e4SLinus Torvalds 	for (j = 0; j < 0x18; j++) {
16276a3cebb6SOndrej Zary 		printk(" r%2x=%2x", j, atp_readb_io(dev, c, j));
16281da177e4SLinus Torvalds 	}
16296a3cebb6SOndrej Zary 	printk(" r1c=%2x", atp_readb_io(dev, c, 0x1c));
16306a3cebb6SOndrej Zary 	printk(" r1f=%2x in_snd=%2x ", atp_readb_io(dev, c, 0x1f), dev->in_snd[c]);
16316a3cebb6SOndrej Zary 	printk(" d00=%2x", atp_readb_pci(dev, c, 0x00));
16326a3cebb6SOndrej Zary 	printk(" d02=%2x", atp_readb_pci(dev, c, 0x02));
16331da177e4SLinus Torvalds 	for(j=0;j<16;j++) {
16341da177e4SLinus Torvalds 	   if (dev->id[c][j].curr_req != NULL) {
16351da177e4SLinus Torvalds 		workrequ = dev->id[c][j].curr_req;
16361da177e4SLinus Torvalds 		printk("\n que cdb= ");
16371da177e4SLinus Torvalds 		for (k=0; k < workrequ->cmd_len; k++) {
16381da177e4SLinus Torvalds 		    printk(" %2x ",workrequ->cmnd[k]);
16391da177e4SLinus Torvalds 		}
16401da177e4SLinus Torvalds 		printk(" last_lenu= %x ",(unsigned int)dev->id[c][j].last_len);
16411da177e4SLinus Torvalds 	   }
16421da177e4SLinus Torvalds 	}
16431da177e4SLinus Torvalds 	return SUCCESS;
16441da177e4SLinus Torvalds }
16451da177e4SLinus Torvalds 
16461da177e4SLinus Torvalds static const char *atp870u_info(struct Scsi_Host *notused)
16471da177e4SLinus Torvalds {
16481da177e4SLinus Torvalds 	static char buffer[128];
16491da177e4SLinus Torvalds 
16501da177e4SLinus Torvalds 	strcpy(buffer, "ACARD AEC-6710/6712/67160 PCI Ultra/W/LVD SCSI-3 Adapter Driver V2.6+ac ");
16511da177e4SLinus Torvalds 
16521da177e4SLinus Torvalds 	return buffer;
16531da177e4SLinus Torvalds }
16541da177e4SLinus Torvalds 
1655d773e422SAl Viro static int atp870u_show_info(struct seq_file *m, struct Scsi_Host *HBAptr)
16561da177e4SLinus Torvalds {
16573d30079cSRasmus Villemoes 	seq_puts(m, "ACARD AEC-671X Driver Version: 2.6+ac\n\n"
16583d30079cSRasmus Villemoes 		"Adapter Configuration:\n");
1659d773e422SAl Viro 	seq_printf(m, "               Base IO: %#.4lx\n", HBAptr->io_port);
1660d773e422SAl Viro 	seq_printf(m, "                   IRQ: %d\n", HBAptr->irq);
1661d773e422SAl Viro 	return 0;
16621da177e4SLinus Torvalds }
16631da177e4SLinus Torvalds 
16641da177e4SLinus Torvalds 
16651da177e4SLinus Torvalds static int atp870u_biosparam(struct scsi_device *disk, struct block_device *dev,
16661da177e4SLinus Torvalds 			sector_t capacity, int *ip)
16671da177e4SLinus Torvalds {
16681da177e4SLinus Torvalds 	int heads, sectors, cylinders;
16691da177e4SLinus Torvalds 
16701da177e4SLinus Torvalds 	heads = 64;
16711da177e4SLinus Torvalds 	sectors = 32;
16721da177e4SLinus Torvalds 	cylinders = (unsigned long)capacity / (heads * sectors);
16731da177e4SLinus Torvalds 	if (cylinders > 1024) {
16741da177e4SLinus Torvalds 		heads = 255;
16751da177e4SLinus Torvalds 		sectors = 63;
16761da177e4SLinus Torvalds 		cylinders = (unsigned long)capacity / (heads * sectors);
16771da177e4SLinus Torvalds 	}
16781da177e4SLinus Torvalds 	ip[0] = heads;
16791da177e4SLinus Torvalds 	ip[1] = sectors;
16801da177e4SLinus Torvalds 	ip[2] = cylinders;
16811da177e4SLinus Torvalds 
16821da177e4SLinus Torvalds 	return 0;
16831da177e4SLinus Torvalds }
16841da177e4SLinus Torvalds 
16851da177e4SLinus Torvalds static void atp870u_remove (struct pci_dev *pdev)
16861da177e4SLinus Torvalds {
16871da177e4SLinus Torvalds 	struct atp_unit *devext = pci_get_drvdata(pdev);
16881da177e4SLinus Torvalds 	struct Scsi_Host *pshost = devext->host;
16891da177e4SLinus Torvalds 
16901da177e4SLinus Torvalds 
16911da177e4SLinus Torvalds 	scsi_remove_host(pshost);
16921da177e4SLinus Torvalds 	free_irq(pshost->irq, pshost);
16931da177e4SLinus Torvalds 	release_region(pshost->io_port, pshost->n_io_port);
16941da177e4SLinus Torvalds 	atp870u_free_tables(pshost);
16951da177e4SLinus Torvalds 	scsi_host_put(pshost);
16961da177e4SLinus Torvalds }
16971da177e4SLinus Torvalds MODULE_LICENSE("GPL");
16981da177e4SLinus Torvalds 
16991da177e4SLinus Torvalds static struct scsi_host_template atp870u_template = {
17001da177e4SLinus Torvalds      .module			= THIS_MODULE,
17011da177e4SLinus Torvalds      .name              	= "atp870u"		/* name */,
17021da177e4SLinus Torvalds      .proc_name			= "atp870u",
1703d773e422SAl Viro      .show_info			= atp870u_show_info,
17041da177e4SLinus Torvalds      .info              	= atp870u_info		/* info */,
17051da177e4SLinus Torvalds      .queuecommand      	= atp870u_queuecommand	/* queuecommand */,
17061da177e4SLinus Torvalds      .eh_abort_handler  	= atp870u_abort		/* abort */,
17071da177e4SLinus Torvalds      .bios_param        	= atp870u_biosparam	/* biosparm */,
17081da177e4SLinus Torvalds      .can_queue         	= qcnt			/* can_queue */,
17091da177e4SLinus Torvalds      .this_id           	= 7			/* SCSI ID */,
17101da177e4SLinus Torvalds      .sg_tablesize      	= ATP870U_SCATTER	/*SG_ALL*/ /*SG_NONE*/,
17111da177e4SLinus Torvalds      .use_clustering    	= ENABLE_CLUSTERING,
17121da177e4SLinus Torvalds      .max_sectors		= ATP870U_MAX_SECTORS,
17131da177e4SLinus Torvalds };
17141da177e4SLinus Torvalds 
17151da177e4SLinus Torvalds static struct pci_device_id atp870u_id_table[] = {
17161da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP885_DEVID)			  },
17171da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID1)			  },
17181da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID2)			  },
17191da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7610)    },
17201da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612UW)  },
17211da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612U)   },
17221da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612S)   },
17231da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612D)	  },
17241da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612SUW) },
17251da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_8060)	  },
17261da177e4SLinus Torvalds 	{ 0, },
17271da177e4SLinus Torvalds };
17281da177e4SLinus Torvalds 
17291da177e4SLinus Torvalds MODULE_DEVICE_TABLE(pci, atp870u_id_table);
17301da177e4SLinus Torvalds 
17311da177e4SLinus Torvalds static struct pci_driver atp870u_driver = {
17321da177e4SLinus Torvalds 	.id_table	= atp870u_id_table,
17331da177e4SLinus Torvalds 	.name		= "atp870u",
17341da177e4SLinus Torvalds 	.probe		= atp870u_probe,
17356f039790SGreg Kroah-Hartman 	.remove		= atp870u_remove,
17361da177e4SLinus Torvalds };
17371da177e4SLinus Torvalds 
17381ccd7d68SOndrej Zary module_pci_driver(atp870u_driver);
17391da177e4SLinus Torvalds 
17404192a40fSOndrej Zary static void atp_is(struct atp_unit *dev, unsigned char c, bool wide_chip, unsigned char lvdmode)
17411da177e4SLinus Torvalds {
1742fa50b308SOndrej Zary 	unsigned char i, j, k, rmb, n;
17431da177e4SLinus Torvalds 	unsigned short int m;
17441da177e4SLinus Torvalds 	static unsigned char mbuf[512];
17451da177e4SLinus Torvalds 	static unsigned char satn[9] = { 0, 0, 0, 0, 0, 0, 0, 6, 6 };
17461da177e4SLinus Torvalds 	static unsigned char inqd[9] = { 0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6 };
17471da177e4SLinus Torvalds 	static unsigned char synn[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
17481da177e4SLinus Torvalds 	unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
17491da177e4SLinus Torvalds 	static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
1750460da918SOndrej Zary 	static unsigned char synw_870[6] = { 0x80, 1, 3, 1, 0x0c, 0x07 };
17511da177e4SLinus Torvalds 	unsigned char synuw[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
17521da177e4SLinus Torvalds 	static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
17531da177e4SLinus Torvalds 	static unsigned char u3[9] = { 0x80, 1, 6, 4, 0x09, 00, 0x0e, 0x01, 0x02 };
17541da177e4SLinus Torvalds 
17551da177e4SLinus Torvalds 	for (i = 0; i < 16; i++) {
1756197fb8d8SOndrej Zary 		if (!wide_chip && (i > 7))
1757197fb8d8SOndrej Zary 			break;
17581da177e4SLinus Torvalds 		m = 1;
17591da177e4SLinus Torvalds 		m = m << i;
17601da177e4SLinus Torvalds 		if ((m & dev->active_id[c]) != 0) {
17611da177e4SLinus Torvalds 			continue;
17621da177e4SLinus Torvalds 		}
17631da177e4SLinus Torvalds 		if (i == dev->host_id[c]) {
17641da177e4SLinus Torvalds 			printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_id[c]);
17651da177e4SLinus Torvalds 			continue;
17661da177e4SLinus Torvalds 		}
1767197fb8d8SOndrej Zary 		atp_writeb_io(dev, c, 0x1b, wide_chip ? 0x01 : 0x00);
17685d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 1, 0x08);
17695d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 2, 0x7f);
17705d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 3, satn[0]);
17715d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 4, satn[1]);
17725d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 5, satn[2]);
17735d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 6, satn[3]);
17745d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 7, satn[4]);
17755d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 8, satn[5]);
17765d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x0f, 0);
17775d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
17785d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
17795d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, satn[6]);
17805d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, satn[7]);
17811da177e4SLinus Torvalds 		j = i;
17821da177e4SLinus Torvalds 		if ((j & 0x08) != 0) {
17831da177e4SLinus Torvalds 			j = (j & 0x07) | 0x40;
17841da177e4SLinus Torvalds 		}
17855d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x15, j);
17865d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, satn[8]);
17871da177e4SLinus Torvalds 
17885d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
17891da177e4SLinus Torvalds 			cpu_relax();
179080b52a7fSOndrej Zary 
179180b52a7fSOndrej Zary 		if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e)
17921da177e4SLinus Torvalds 			continue;
179380b52a7fSOndrej Zary 
17945d2a5a4fSOndrej Zary 		while (atp_readb_io(dev, c, 0x17) != 0x8e)
17951da177e4SLinus Torvalds 			cpu_relax();
179680b52a7fSOndrej Zary 
17971da177e4SLinus Torvalds 		dev->active_id[c] |= m;
17981da177e4SLinus Torvalds 
17995d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x10, 0x30);
1800460da918SOndrej Zary 		if (dev->dev_id == ATP885_DEVID || dev->dev_id == ATP880_DEVID1 || dev->dev_id == ATP880_DEVID2)
18015d2a5a4fSOndrej Zary 			atp_writeb_io(dev, c, 0x14, 0x00);
1802460da918SOndrej Zary 		else /* result of is870() merge - is this a bug? */
1803460da918SOndrej Zary 			atp_writeb_io(dev, c, 0x04, 0x00);
18041da177e4SLinus Torvalds 
18051da177e4SLinus Torvalds phase_cmd:
18065d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
180780b52a7fSOndrej Zary 
18085d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
18091da177e4SLinus Torvalds 			cpu_relax();
181080b52a7fSOndrej Zary 
18115d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
18121da177e4SLinus Torvalds 		if (j != 0x16) {
18135d2a5a4fSOndrej Zary 			atp_writeb_io(dev, c, 0x10, 0x41);
18141da177e4SLinus Torvalds 			goto phase_cmd;
18151da177e4SLinus Torvalds 		}
18161da177e4SLinus Torvalds sel_ok:
18175d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 3, inqd[0]);
18185d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 4, inqd[1]);
18195d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 5, inqd[2]);
18205d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 6, inqd[3]);
18215d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 7, inqd[4]);
18225d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 8, inqd[5]);
18235d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x0f, 0);
18245d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
18255d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
18265d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, inqd[6]);
18275d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, inqd[7]);
18285d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, inqd[8]);
182980b52a7fSOndrej Zary 
18305d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
18311da177e4SLinus Torvalds 			cpu_relax();
183280b52a7fSOndrej Zary 
183380b52a7fSOndrej Zary 		if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e)
18341da177e4SLinus Torvalds 			continue;
183580b52a7fSOndrej Zary 
18365d2a5a4fSOndrej Zary 		while (atp_readb_io(dev, c, 0x17) != 0x8e)
18371da177e4SLinus Torvalds 			cpu_relax();
183880b52a7fSOndrej Zary 
1839197fb8d8SOndrej Zary 		if (wide_chip)
18405d2a5a4fSOndrej Zary 			atp_writeb_io(dev, c, 0x1b, 0x00);
1841197fb8d8SOndrej Zary 
18425d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
18431da177e4SLinus Torvalds 		j = 0;
18441da177e4SLinus Torvalds rd_inq_data:
18455d2a5a4fSOndrej Zary 		k = atp_readb_io(dev, c, 0x1f);
18461da177e4SLinus Torvalds 		if ((k & 0x01) != 0) {
18475d2a5a4fSOndrej Zary 			mbuf[j++] = atp_readb_io(dev, c, 0x19);
18481da177e4SLinus Torvalds 			goto rd_inq_data;
18491da177e4SLinus Torvalds 		}
18501da177e4SLinus Torvalds 		if ((k & 0x80) == 0) {
18511da177e4SLinus Torvalds 			goto rd_inq_data;
18521da177e4SLinus Torvalds 		}
18535d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
18541da177e4SLinus Torvalds 		if (j == 0x16) {
18551da177e4SLinus Torvalds 			goto inq_ok;
18561da177e4SLinus Torvalds 		}
18575d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x10, 0x46);
18585d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
18595d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, 0);
18605d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0);
18615d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
186280b52a7fSOndrej Zary 
18635d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
18641da177e4SLinus Torvalds 			cpu_relax();
186580b52a7fSOndrej Zary 
186680b52a7fSOndrej Zary 		if (atp_readb_io(dev, c, 0x17) != 0x16)
18671da177e4SLinus Torvalds 			goto sel_ok;
186880b52a7fSOndrej Zary 
18691da177e4SLinus Torvalds inq_ok:
18701da177e4SLinus Torvalds 		mbuf[36] = 0;
18711da177e4SLinus Torvalds 		printk(KERN_INFO "         ID: %2d  %s\n", i, &mbuf[8]);
18721da177e4SLinus Torvalds 		dev->id[c][i].devtype = mbuf[0];
18731da177e4SLinus Torvalds 		rmb = mbuf[1];
18741da177e4SLinus Torvalds 		n = mbuf[7];
1875197fb8d8SOndrej Zary 		if (!wide_chip)
1876197fb8d8SOndrej Zary 			goto not_wide;
18771da177e4SLinus Torvalds 		if ((mbuf[7] & 0x60) == 0) {
18781da177e4SLinus Torvalds 			goto not_wide;
18791da177e4SLinus Torvalds 		}
1880197fb8d8SOndrej Zary 		if (dev->dev_id == ATP885_DEVID || dev->dev_id == ATP880_DEVID1 || dev->dev_id == ATP880_DEVID2) {
1881197fb8d8SOndrej Zary 			if ((i < 8) && ((dev->global_map[c] & 0x20) == 0))
1882197fb8d8SOndrej Zary 				goto not_wide;
1883197fb8d8SOndrej Zary 		} else { /* result of is870() merge - is this a bug? */
1884197fb8d8SOndrej Zary 			if ((dev->global_map[c] & 0x20) == 0)
18851da177e4SLinus Torvalds 				goto not_wide;
18861da177e4SLinus Torvalds 		}
18871da177e4SLinus Torvalds 		if (lvdmode == 0) {
18881da177e4SLinus Torvalds 			goto chg_wide;
18891da177e4SLinus Torvalds 		}
189080b52a7fSOndrej Zary 		if (dev->sp[c][i] != 0x04)	// force u2
189180b52a7fSOndrej Zary 		{
18921da177e4SLinus Torvalds 			goto chg_wide;
18931da177e4SLinus Torvalds 		}
18941da177e4SLinus Torvalds 
18955d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x1b, 0x01);
18965d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 3, satn[0]);
18975d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 4, satn[1]);
18985d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 5, satn[2]);
18995d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 6, satn[3]);
19005d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 7, satn[4]);
19015d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 8, satn[5]);
19025d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x0f, 0);
19035d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
19045d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
19055d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, satn[6]);
19065d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, satn[7]);
19075d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, satn[8]);
19081da177e4SLinus Torvalds 
19095d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
19101da177e4SLinus Torvalds 			cpu_relax();
191180b52a7fSOndrej Zary 
191280b52a7fSOndrej Zary 		if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e)
19131da177e4SLinus Torvalds 			continue;
191480b52a7fSOndrej Zary 
19155d2a5a4fSOndrej Zary 		while (atp_readb_io(dev, c, 0x17) != 0x8e)
19161da177e4SLinus Torvalds 			cpu_relax();
191780b52a7fSOndrej Zary 
19181da177e4SLinus Torvalds try_u3:
19191da177e4SLinus Torvalds 		j = 0;
19205d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x09);
19215d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
19221da177e4SLinus Torvalds 
19235d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) {
19245d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0)
19255d2a5a4fSOndrej Zary 				atp_writeb_io(dev, c, 0x19, u3[j++]);
19261da177e4SLinus Torvalds 			cpu_relax();
19271da177e4SLinus Torvalds 		}
192880b52a7fSOndrej Zary 
19295d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00)
19301da177e4SLinus Torvalds 			cpu_relax();
193180b52a7fSOndrej Zary 
19325d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
19331da177e4SLinus Torvalds 		if (j == 0x0f) {
19341da177e4SLinus Torvalds 			goto u3p_in;
19351da177e4SLinus Torvalds 		}
19361da177e4SLinus Torvalds 		if (j == 0x0a) {
19371da177e4SLinus Torvalds 			goto u3p_cmd;
19381da177e4SLinus Torvalds 		}
19391da177e4SLinus Torvalds 		if (j == 0x0e) {
19401da177e4SLinus Torvalds 			goto try_u3;
19411da177e4SLinus Torvalds 		}
19421da177e4SLinus Torvalds 		continue;
19431da177e4SLinus Torvalds u3p_out:
19445d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
19455d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) {
19465d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0)
19475d2a5a4fSOndrej Zary 				atp_writeb_io(dev, c, 0x19, 0);
19481da177e4SLinus Torvalds 			cpu_relax();
19491da177e4SLinus Torvalds 		}
19505d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
19511da177e4SLinus Torvalds 		if (j == 0x0f) {
19521da177e4SLinus Torvalds 			goto u3p_in;
19531da177e4SLinus Torvalds 		}
19541da177e4SLinus Torvalds 		if (j == 0x0a) {
19551da177e4SLinus Torvalds 			goto u3p_cmd;
19561da177e4SLinus Torvalds 		}
19571da177e4SLinus Torvalds 		if (j == 0x0e) {
19581da177e4SLinus Torvalds 			goto u3p_out;
19591da177e4SLinus Torvalds 		}
19601da177e4SLinus Torvalds 		continue;
19611da177e4SLinus Torvalds u3p_in:
19625d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x09);
19635d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
19641da177e4SLinus Torvalds 		k = 0;
19651da177e4SLinus Torvalds u3p_in1:
19665d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x1f);
19671da177e4SLinus Torvalds 		if ((j & 0x01) != 0) {
19685d2a5a4fSOndrej Zary 			mbuf[k++] = atp_readb_io(dev, c, 0x19);
19691da177e4SLinus Torvalds 			goto u3p_in1;
19701da177e4SLinus Torvalds 		}
19711da177e4SLinus Torvalds 		if ((j & 0x80) == 0x00) {
19721da177e4SLinus Torvalds 			goto u3p_in1;
19731da177e4SLinus Torvalds 		}
19745d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
19751da177e4SLinus Torvalds 		if (j == 0x0f) {
19761da177e4SLinus Torvalds 			goto u3p_in;
19771da177e4SLinus Torvalds 		}
19781da177e4SLinus Torvalds 		if (j == 0x0a) {
19791da177e4SLinus Torvalds 			goto u3p_cmd;
19801da177e4SLinus Torvalds 		}
19811da177e4SLinus Torvalds 		if (j == 0x0e) {
19821da177e4SLinus Torvalds 			goto u3p_out;
19831da177e4SLinus Torvalds 		}
19841da177e4SLinus Torvalds 		continue;
19851da177e4SLinus Torvalds u3p_cmd:
19865d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x10, 0x30);
19875d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x00);
19885d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
198980b52a7fSOndrej Zary 
19905d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00);
199180b52a7fSOndrej Zary 
19925d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
19931da177e4SLinus Torvalds 		if (j != 0x16) {
19941da177e4SLinus Torvalds 			if (j == 0x4e) {
19951da177e4SLinus Torvalds 				goto u3p_out;
19961da177e4SLinus Torvalds 			}
19971da177e4SLinus Torvalds 			continue;
19981da177e4SLinus Torvalds 		}
19991da177e4SLinus Torvalds 		if (mbuf[0] != 0x01) {
20001da177e4SLinus Torvalds 			goto chg_wide;
20011da177e4SLinus Torvalds 		}
20021da177e4SLinus Torvalds 		if (mbuf[1] != 0x06) {
20031da177e4SLinus Torvalds 			goto chg_wide;
20041da177e4SLinus Torvalds 		}
20051da177e4SLinus Torvalds 		if (mbuf[2] != 0x04) {
20061da177e4SLinus Torvalds 			goto chg_wide;
20071da177e4SLinus Torvalds 		}
20081da177e4SLinus Torvalds 		if (mbuf[3] == 0x09) {
20091da177e4SLinus Torvalds 			m = 1;
20101da177e4SLinus Torvalds 			m = m << i;
20111da177e4SLinus Torvalds 			dev->wide_id[c] |= m;
20121da177e4SLinus Torvalds 			dev->id[c][i].devsp = 0xce;
20131da177e4SLinus Torvalds #ifdef ED_DBGP
20141da177e4SLinus Torvalds 			printk("dev->id[%2d][%2d].devsp = %2x\n",c,i,dev->id[c][i].devsp);
20151da177e4SLinus Torvalds #endif
20161da177e4SLinus Torvalds 			continue;
20171da177e4SLinus Torvalds 		}
20181da177e4SLinus Torvalds chg_wide:
20195d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x1b, 0x01);
20205d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 3, satn[0]);
20215d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 4, satn[1]);
20225d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 5, satn[2]);
20235d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 6, satn[3]);
20245d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 7, satn[4]);
20255d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 8, satn[5]);
20265d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x0f, 0);
20275d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
20285d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
20295d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, satn[6]);
20305d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, satn[7]);
20315d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, satn[8]);
20321da177e4SLinus Torvalds 
20335d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
20341da177e4SLinus Torvalds 			cpu_relax();
203580b52a7fSOndrej Zary 
203680b52a7fSOndrej Zary 		if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e)
20371da177e4SLinus Torvalds 			continue;
203880b52a7fSOndrej Zary 
20395d2a5a4fSOndrej Zary 		while (atp_readb_io(dev, c, 0x17) != 0x8e)
20401da177e4SLinus Torvalds 			cpu_relax();
204180b52a7fSOndrej Zary 
20421da177e4SLinus Torvalds try_wide:
20431da177e4SLinus Torvalds 		j = 0;
20445d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x05);
20455d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
20461da177e4SLinus Torvalds 
20475d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) {
20485d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0)
20495d2a5a4fSOndrej Zary 				atp_writeb_io(dev, c, 0x19, wide[j++]);
20501da177e4SLinus Torvalds 			cpu_relax();
20511da177e4SLinus Torvalds 		}
205280b52a7fSOndrej Zary 
20535d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00)
20541da177e4SLinus Torvalds 			cpu_relax();
205580b52a7fSOndrej Zary 
20565d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
20571da177e4SLinus Torvalds 		if (j == 0x0f) {
20581da177e4SLinus Torvalds 			goto widep_in;
20591da177e4SLinus Torvalds 		}
20601da177e4SLinus Torvalds 		if (j == 0x0a) {
20611da177e4SLinus Torvalds 			goto widep_cmd;
20621da177e4SLinus Torvalds 		}
20631da177e4SLinus Torvalds 		if (j == 0x0e) {
20641da177e4SLinus Torvalds 			goto try_wide;
20651da177e4SLinus Torvalds 		}
20661da177e4SLinus Torvalds 		continue;
20671da177e4SLinus Torvalds widep_out:
20685d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
20695d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) {
20705d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0)
20715d2a5a4fSOndrej Zary 				atp_writeb_io(dev, c, 0x19, 0);
20721da177e4SLinus Torvalds 			cpu_relax();
20731da177e4SLinus Torvalds 		}
20745d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
20751da177e4SLinus Torvalds 		if (j == 0x0f) {
20761da177e4SLinus Torvalds 			goto widep_in;
20771da177e4SLinus Torvalds 		}
20781da177e4SLinus Torvalds 		if (j == 0x0a) {
20791da177e4SLinus Torvalds 			goto widep_cmd;
20801da177e4SLinus Torvalds 		}
20811da177e4SLinus Torvalds 		if (j == 0x0e) {
20821da177e4SLinus Torvalds 			goto widep_out;
20831da177e4SLinus Torvalds 		}
20841da177e4SLinus Torvalds 		continue;
20851da177e4SLinus Torvalds widep_in:
20865d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0xff);
20875d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
20881da177e4SLinus Torvalds 		k = 0;
20891da177e4SLinus Torvalds widep_in1:
20905d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x1f);
20911da177e4SLinus Torvalds 		if ((j & 0x01) != 0) {
20925d2a5a4fSOndrej Zary 			mbuf[k++] = atp_readb_io(dev, c, 0x19);
20931da177e4SLinus Torvalds 			goto widep_in1;
20941da177e4SLinus Torvalds 		}
20951da177e4SLinus Torvalds 		if ((j & 0x80) == 0x00) {
20961da177e4SLinus Torvalds 			goto widep_in1;
20971da177e4SLinus Torvalds 		}
20985d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
20991da177e4SLinus Torvalds 		if (j == 0x0f) {
21001da177e4SLinus Torvalds 			goto widep_in;
21011da177e4SLinus Torvalds 		}
21021da177e4SLinus Torvalds 		if (j == 0x0a) {
21031da177e4SLinus Torvalds 			goto widep_cmd;
21041da177e4SLinus Torvalds 		}
21051da177e4SLinus Torvalds 		if (j == 0x0e) {
21061da177e4SLinus Torvalds 			goto widep_out;
21071da177e4SLinus Torvalds 		}
21081da177e4SLinus Torvalds 		continue;
21091da177e4SLinus Torvalds widep_cmd:
21105d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x10, 0x30);
21115d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x00);
21125d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
211380b52a7fSOndrej Zary 
21145d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
21151da177e4SLinus Torvalds 			cpu_relax();
211680b52a7fSOndrej Zary 
21175d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
21181da177e4SLinus Torvalds 		if (j != 0x16) {
21191da177e4SLinus Torvalds 			if (j == 0x4e) {
21201da177e4SLinus Torvalds 				goto widep_out;
21211da177e4SLinus Torvalds 			}
21221da177e4SLinus Torvalds 			continue;
21231da177e4SLinus Torvalds 		}
21241da177e4SLinus Torvalds 		if (mbuf[0] != 0x01) {
21251da177e4SLinus Torvalds 			goto not_wide;
21261da177e4SLinus Torvalds 		}
21271da177e4SLinus Torvalds 		if (mbuf[1] != 0x02) {
21281da177e4SLinus Torvalds 			goto not_wide;
21291da177e4SLinus Torvalds 		}
21301da177e4SLinus Torvalds 		if (mbuf[2] != 0x03) {
21311da177e4SLinus Torvalds 			goto not_wide;
21321da177e4SLinus Torvalds 		}
21331da177e4SLinus Torvalds 		if (mbuf[3] != 0x01) {
21341da177e4SLinus Torvalds 			goto not_wide;
21351da177e4SLinus Torvalds 		}
21361da177e4SLinus Torvalds 		m = 1;
21371da177e4SLinus Torvalds 		m = m << i;
21381da177e4SLinus Torvalds 		dev->wide_id[c] |= m;
21391da177e4SLinus Torvalds not_wide:
214080b52a7fSOndrej Zary 		if ((dev->id[c][i].devtype == 0x00) || (dev->id[c][i].devtype == 0x07) || ((dev->id[c][i].devtype == 0x05) && ((n & 0x10) != 0))) {
21411da177e4SLinus Torvalds 			m = 1;
21421da177e4SLinus Torvalds 			m = m << i;
21431da177e4SLinus Torvalds 			if ((dev->async[c] & m) != 0) {
21441da177e4SLinus Torvalds 				goto set_sync;
21451da177e4SLinus Torvalds 			}
21461da177e4SLinus Torvalds 		}
21471da177e4SLinus Torvalds 		continue;
21481da177e4SLinus Torvalds set_sync:
2149460da918SOndrej Zary 		if ((dev->dev_id != ATP885_DEVID && dev->dev_id != ATP880_DEVID1 && dev->dev_id != ATP880_DEVID2) || (dev->sp[c][i] == 0x02)) {
21501da177e4SLinus Torvalds 			synu[4] = 0x0c;
21511da177e4SLinus Torvalds 			synuw[4] = 0x0c;
21521da177e4SLinus Torvalds 		} else {
21531da177e4SLinus Torvalds 			if (dev->sp[c][i] >= 0x03) {
21541da177e4SLinus Torvalds 				synu[4] = 0x0a;
21551da177e4SLinus Torvalds 				synuw[4] = 0x0a;
21561da177e4SLinus Torvalds 			}
21571da177e4SLinus Torvalds 		}
21581da177e4SLinus Torvalds 		j = 0;
21591da177e4SLinus Torvalds 		if ((m & dev->wide_id[c]) != 0) {
21601da177e4SLinus Torvalds 			j |= 0x01;
21611da177e4SLinus Torvalds 		}
21625d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x1b, j);
21635d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 3, satn[0]);
21645d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 4, satn[1]);
21655d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 5, satn[2]);
21665d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 6, satn[3]);
21675d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 7, satn[4]);
21685d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 8, satn[5]);
21695d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x0f, 0);
21705d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
21715d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
21725d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, satn[6]);
21735d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, satn[7]);
21745d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, satn[8]);
21751da177e4SLinus Torvalds 
21765d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
21771da177e4SLinus Torvalds 			cpu_relax();
217880b52a7fSOndrej Zary 
217980b52a7fSOndrej Zary 		if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e)
21801da177e4SLinus Torvalds 			continue;
218180b52a7fSOndrej Zary 
21825d2a5a4fSOndrej Zary 		while (atp_readb_io(dev, c, 0x17) != 0x8e)
21831da177e4SLinus Torvalds 			cpu_relax();
218480b52a7fSOndrej Zary 
21851da177e4SLinus Torvalds try_sync:
21861da177e4SLinus Torvalds 		j = 0;
21875d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x06);
21885d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
21891da177e4SLinus Torvalds 
21905d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) {
21915d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0) {
21921da177e4SLinus Torvalds 				if ((m & dev->wide_id[c]) != 0) {
2193460da918SOndrej Zary 					if (dev->dev_id == ATP885_DEVID || dev->dev_id == ATP880_DEVID1 || dev->dev_id == ATP880_DEVID2) {
21941da177e4SLinus Torvalds 						if ((m & dev->ultra_map[c]) != 0) {
21955d2a5a4fSOndrej Zary 							atp_writeb_io(dev, c, 0x19, synuw[j++]);
21961da177e4SLinus Torvalds 						} else {
21975d2a5a4fSOndrej Zary 							atp_writeb_io(dev, c, 0x19, synw[j++]);
21981da177e4SLinus Torvalds 						}
2199460da918SOndrej Zary 					} else
2200460da918SOndrej Zary 						atp_writeb_io(dev, c, 0x19, synw_870[j++]);
22011da177e4SLinus Torvalds 				} else {
22021da177e4SLinus Torvalds 					if ((m & dev->ultra_map[c]) != 0) {
22035d2a5a4fSOndrej Zary 						atp_writeb_io(dev, c, 0x19, synu[j++]);
22041da177e4SLinus Torvalds 					} else {
22055d2a5a4fSOndrej Zary 						atp_writeb_io(dev, c, 0x19, synn[j++]);
22061da177e4SLinus Torvalds 					}
22071da177e4SLinus Torvalds 				}
22081da177e4SLinus Torvalds 			}
22091da177e4SLinus Torvalds 		}
221080b52a7fSOndrej Zary 
22115d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00)
22121da177e4SLinus Torvalds 			cpu_relax();
221380b52a7fSOndrej Zary 
22145d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
22151da177e4SLinus Torvalds 		if (j == 0x0f) {
22161da177e4SLinus Torvalds 			goto phase_ins;
22171da177e4SLinus Torvalds 		}
22181da177e4SLinus Torvalds 		if (j == 0x0a) {
22191da177e4SLinus Torvalds 			goto phase_cmds;
22201da177e4SLinus Torvalds 		}
22211da177e4SLinus Torvalds 		if (j == 0x0e) {
22221da177e4SLinus Torvalds 			goto try_sync;
22231da177e4SLinus Torvalds 		}
22241da177e4SLinus Torvalds 		continue;
22251da177e4SLinus Torvalds phase_outs:
22265d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
22275d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) {
22285d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0x00)
22295d2a5a4fSOndrej Zary 				atp_writeb_io(dev, c, 0x19, 0x00);
22301da177e4SLinus Torvalds 			cpu_relax();
22311da177e4SLinus Torvalds 		}
22325d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
22331da177e4SLinus Torvalds 		if (j == 0x85) {
22341da177e4SLinus Torvalds 			goto tar_dcons;
22351da177e4SLinus Torvalds 		}
22361da177e4SLinus Torvalds 		j &= 0x0f;
22371da177e4SLinus Torvalds 		if (j == 0x0f) {
22381da177e4SLinus Torvalds 			goto phase_ins;
22391da177e4SLinus Torvalds 		}
22401da177e4SLinus Torvalds 		if (j == 0x0a) {
22411da177e4SLinus Torvalds 			goto phase_cmds;
22421da177e4SLinus Torvalds 		}
22431da177e4SLinus Torvalds 		if (j == 0x0e) {
22441da177e4SLinus Torvalds 			goto phase_outs;
22451da177e4SLinus Torvalds 		}
22461da177e4SLinus Torvalds 		continue;
22471da177e4SLinus Torvalds phase_ins:
2248460da918SOndrej Zary 		if (dev->dev_id == ATP885_DEVID || dev->dev_id == ATP880_DEVID1 || dev->dev_id == ATP880_DEVID2)
22495d2a5a4fSOndrej Zary 			atp_writeb_io(dev, c, 0x14, 0x06);
2250460da918SOndrej Zary 		else
2251460da918SOndrej Zary 			atp_writeb_io(dev, c, 0x14, 0xff);
22525d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
22531da177e4SLinus Torvalds 		k = 0;
22541da177e4SLinus Torvalds phase_ins1:
22555d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x1f);
22561da177e4SLinus Torvalds 		if ((j & 0x01) != 0x00) {
22575d2a5a4fSOndrej Zary 			mbuf[k++] = atp_readb_io(dev, c, 0x19);
22581da177e4SLinus Torvalds 			goto phase_ins1;
22591da177e4SLinus Torvalds 		}
22601da177e4SLinus Torvalds 		if ((j & 0x80) == 0x00) {
22611da177e4SLinus Torvalds 			goto phase_ins1;
22621da177e4SLinus Torvalds 		}
226380b52a7fSOndrej Zary 
22645d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00);
226580b52a7fSOndrej Zary 
22665d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
22671da177e4SLinus Torvalds 		if (j == 0x85) {
22681da177e4SLinus Torvalds 			goto tar_dcons;
22691da177e4SLinus Torvalds 		}
22701da177e4SLinus Torvalds 		j &= 0x0f;
22711da177e4SLinus Torvalds 		if (j == 0x0f) {
22721da177e4SLinus Torvalds 			goto phase_ins;
22731da177e4SLinus Torvalds 		}
22741da177e4SLinus Torvalds 		if (j == 0x0a) {
22751da177e4SLinus Torvalds 			goto phase_cmds;
22761da177e4SLinus Torvalds 		}
22771da177e4SLinus Torvalds 		if (j == 0x0e) {
22781da177e4SLinus Torvalds 			goto phase_outs;
22791da177e4SLinus Torvalds 		}
22801da177e4SLinus Torvalds 		continue;
22811da177e4SLinus Torvalds phase_cmds:
22825d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x10, 0x30);
22831da177e4SLinus Torvalds tar_dcons:
22845d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x00);
22855d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
228680b52a7fSOndrej Zary 
22875d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
22881da177e4SLinus Torvalds 			cpu_relax();
228980b52a7fSOndrej Zary 
22905d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
22911da177e4SLinus Torvalds 		if (j != 0x16) {
22921da177e4SLinus Torvalds 			continue;
22931da177e4SLinus Torvalds 		}
22941da177e4SLinus Torvalds 		if (mbuf[0] != 0x01) {
22951da177e4SLinus Torvalds 			continue;
22961da177e4SLinus Torvalds 		}
22971da177e4SLinus Torvalds 		if (mbuf[1] != 0x03) {
22981da177e4SLinus Torvalds 			continue;
22991da177e4SLinus Torvalds 		}
23001da177e4SLinus Torvalds 		if (mbuf[4] == 0x00) {
23011da177e4SLinus Torvalds 			continue;
23021da177e4SLinus Torvalds 		}
23031da177e4SLinus Torvalds 		if (mbuf[3] > 0x64) {
23041da177e4SLinus Torvalds 			continue;
23051da177e4SLinus Torvalds 		}
2306460da918SOndrej Zary 		if (dev->dev_id == ATP885_DEVID || dev->dev_id == ATP880_DEVID1 || dev->dev_id == ATP880_DEVID2) {
23071da177e4SLinus Torvalds 			if (mbuf[4] > 0x0e) {
23081da177e4SLinus Torvalds 				mbuf[4] = 0x0e;
23091da177e4SLinus Torvalds 			}
2310460da918SOndrej Zary 		} else {
2311460da918SOndrej Zary 			if (mbuf[4] > 0x0c) {
2312460da918SOndrej Zary 				mbuf[4] = 0x0c;
2313460da918SOndrej Zary 			}
2314460da918SOndrej Zary 		}
23151da177e4SLinus Torvalds 		dev->id[c][i].devsp = mbuf[4];
2316460da918SOndrej Zary 		if (dev->dev_id == ATP885_DEVID || dev->dev_id == ATP880_DEVID1 || dev->dev_id == ATP880_DEVID2)
23171da177e4SLinus Torvalds 			if (mbuf[3] < 0x0c) {
23181da177e4SLinus Torvalds 				j = 0xb0;
23191da177e4SLinus Torvalds 				goto set_syn_ok;
23201da177e4SLinus Torvalds 			}
23211da177e4SLinus Torvalds 		if ((mbuf[3] < 0x0d) && (rmb == 0)) {
23221da177e4SLinus Torvalds 			j = 0xa0;
23231da177e4SLinus Torvalds 			goto set_syn_ok;
23241da177e4SLinus Torvalds 		}
23251da177e4SLinus Torvalds 		if (mbuf[3] < 0x1a) {
23261da177e4SLinus Torvalds 			j = 0x20;
23271da177e4SLinus Torvalds 			goto set_syn_ok;
23281da177e4SLinus Torvalds 		}
23291da177e4SLinus Torvalds 		if (mbuf[3] < 0x33) {
23301da177e4SLinus Torvalds 			j = 0x40;
23311da177e4SLinus Torvalds 			goto set_syn_ok;
23321da177e4SLinus Torvalds 		}
23331da177e4SLinus Torvalds 		if (mbuf[3] < 0x4c) {
23341da177e4SLinus Torvalds 			j = 0x50;
23351da177e4SLinus Torvalds 			goto set_syn_ok;
23361da177e4SLinus Torvalds 		}
23371da177e4SLinus Torvalds 		j = 0x60;
23381da177e4SLinus Torvalds set_syn_ok:
23391da177e4SLinus Torvalds 		dev->id[c][i].devsp = (dev->id[c][i].devsp & 0x0f) | j;
23401da177e4SLinus Torvalds #ifdef ED_DBGP
23411da177e4SLinus Torvalds 		printk("dev->id[%2d][%2d].devsp = %2x\n",c,i,dev->id[c][i].devsp);
23421da177e4SLinus Torvalds #endif
23431da177e4SLinus Torvalds 	}
23441da177e4SLinus Torvalds }
2345