xref: /openbmc/linux/drivers/scsi/atp870u.c (revision d804bb25)
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 static void tscam_885(void);
461da177e4SLinus Torvalds 
476a3cebb6SOndrej Zary static inline void atp_writeb_base(struct atp_unit *atp, u8 reg, u8 val)
486a3cebb6SOndrej Zary {
496a3cebb6SOndrej Zary 	outb(val, atp->baseport + reg);
506a3cebb6SOndrej Zary }
516a3cebb6SOndrej Zary 
52d804bb25SOndrej Zary static inline void atp_writew_base(struct atp_unit *atp, u8 reg, u16 val)
53d804bb25SOndrej Zary {
54d804bb25SOndrej Zary 	outw(val, atp->baseport + reg);
55d804bb25SOndrej Zary }
56d804bb25SOndrej Zary 
576a3cebb6SOndrej Zary static inline void atp_writeb_io(struct atp_unit *atp, u8 channel, u8 reg, u8 val)
586a3cebb6SOndrej Zary {
596a3cebb6SOndrej Zary 	outb(val, atp->ioport[channel] + reg);
606a3cebb6SOndrej Zary }
616a3cebb6SOndrej Zary 
626a3cebb6SOndrej Zary static inline void atp_writew_io(struct atp_unit *atp, u8 channel, u8 reg, u16 val)
636a3cebb6SOndrej Zary {
646a3cebb6SOndrej Zary 	outw(val, atp->ioport[channel] + reg);
656a3cebb6SOndrej Zary }
666a3cebb6SOndrej Zary 
676a3cebb6SOndrej Zary static inline void atp_writeb_pci(struct atp_unit *atp, u8 channel, u8 reg, u8 val)
686a3cebb6SOndrej Zary {
696a3cebb6SOndrej Zary 	outb(val, atp->pciport[channel] + reg);
706a3cebb6SOndrej Zary }
716a3cebb6SOndrej Zary 
726a3cebb6SOndrej Zary static inline void atp_writel_pci(struct atp_unit *atp, u8 channel, u8 reg, u32 val)
736a3cebb6SOndrej Zary {
746a3cebb6SOndrej Zary 	outl(val, atp->pciport[channel] + reg);
756a3cebb6SOndrej Zary }
766a3cebb6SOndrej Zary 
776a3cebb6SOndrej Zary static inline u8 atp_readb_base(struct atp_unit *atp, u8 reg)
786a3cebb6SOndrej Zary {
796a3cebb6SOndrej Zary 	return inb(atp->baseport + reg);
806a3cebb6SOndrej Zary }
816a3cebb6SOndrej Zary 
82d804bb25SOndrej Zary static inline u16 atp_readw_base(struct atp_unit *atp, u8 reg)
83d804bb25SOndrej Zary {
84d804bb25SOndrej Zary 	return inw(atp->baseport + reg);
85d804bb25SOndrej Zary }
86d804bb25SOndrej Zary 
87d804bb25SOndrej Zary static inline u32 atp_readl_base(struct atp_unit *atp, u8 reg)
88d804bb25SOndrej Zary {
89d804bb25SOndrej Zary 	return inl(atp->baseport + reg);
90d804bb25SOndrej Zary }
91d804bb25SOndrej Zary 
926a3cebb6SOndrej Zary static inline u8 atp_readb_io(struct atp_unit *atp, u8 channel, u8 reg)
936a3cebb6SOndrej Zary {
946a3cebb6SOndrej Zary 	return inb(atp->ioport[channel] + reg);
956a3cebb6SOndrej Zary }
966a3cebb6SOndrej Zary 
976a3cebb6SOndrej Zary static inline u16 atp_readw_io(struct atp_unit *atp, u8 channel, u8 reg)
986a3cebb6SOndrej Zary {
996a3cebb6SOndrej Zary 	return inw(atp->ioport[channel] + reg);
1006a3cebb6SOndrej Zary }
1016a3cebb6SOndrej Zary 
1026a3cebb6SOndrej Zary static inline u8 atp_readb_pci(struct atp_unit *atp, u8 channel, u8 reg)
1036a3cebb6SOndrej Zary {
1046a3cebb6SOndrej Zary 	return inb(atp->pciport[channel] + reg);
1056a3cebb6SOndrej Zary }
1066a3cebb6SOndrej Zary 
1077d12e780SDavid Howells static irqreturn_t atp870u_intr_handle(int irq, void *dev_id)
1081da177e4SLinus Torvalds {
1091da177e4SLinus Torvalds 	unsigned long flags;
110bc0fe4c9SOndrej Zary 	unsigned short int id;
1111da177e4SLinus Torvalds 	unsigned char i, j, c, target_id, lun,cmdp;
1121da177e4SLinus Torvalds 	unsigned char *prd;
1131da177e4SLinus Torvalds 	struct scsi_cmnd *workreq;
1141da177e4SLinus Torvalds 	unsigned long adrcnt, k;
1151da177e4SLinus Torvalds #ifdef ED_DBGP
1161da177e4SLinus Torvalds 	unsigned long l;
1171da177e4SLinus Torvalds #endif
1181da177e4SLinus Torvalds 	struct Scsi_Host *host = dev_id;
1191da177e4SLinus Torvalds 	struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
1201da177e4SLinus Torvalds 
1211da177e4SLinus Torvalds 	for (c = 0; c < 2; c++) {
1226a3cebb6SOndrej Zary 		j = atp_readb_io(dev, c, 0x1f);
1231da177e4SLinus Torvalds 		if ((j & 0x80) != 0)
12478614ecdSOndrej Zary 			break;
1251da177e4SLinus Torvalds 		dev->in_int[c] = 0;
1261da177e4SLinus Torvalds 	}
12778614ecdSOndrej Zary 	if ((j & 0x80) == 0)
1281da177e4SLinus Torvalds 		return IRQ_NONE;
1291da177e4SLinus Torvalds #ifdef ED_DBGP
1301da177e4SLinus Torvalds 	printk("atp870u_intr_handle enter\n");
1311da177e4SLinus Torvalds #endif
1321da177e4SLinus Torvalds 	dev->in_int[c] = 1;
1336a3cebb6SOndrej Zary 	cmdp = atp_readb_io(dev, c, 0x10);
1341da177e4SLinus Torvalds 	if (dev->working[c] != 0) {
1351da177e4SLinus Torvalds 		if (dev->dev_id == ATP885_DEVID) {
1366a3cebb6SOndrej Zary 			if ((atp_readb_io(dev, c, 0x16) & 0x80) == 0)
1376a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x16, (atp_readb_io(dev, c, 0x16) | 0x80));
1381da177e4SLinus Torvalds 		}
1396a3cebb6SOndrej Zary 		if ((atp_readb_pci(dev, c, 0x00) & 0x08) != 0)
1401da177e4SLinus Torvalds 		{
1411da177e4SLinus Torvalds 			for (k=0; k < 1000; k++) {
1426a3cebb6SOndrej Zary 				if ((atp_readb_pci(dev, c, 2) & 0x08) == 0)
14378614ecdSOndrej Zary 					break;
1446a3cebb6SOndrej Zary 				if ((atp_readb_pci(dev, c, 2) & 0x01) == 0)
14578614ecdSOndrej Zary 					break;
1461da177e4SLinus Torvalds 			}
1471da177e4SLinus Torvalds 		}
1486a3cebb6SOndrej Zary 		atp_writeb_pci(dev, c, 0, 0x00);
1491da177e4SLinus Torvalds 
1506a3cebb6SOndrej Zary 		i = atp_readb_io(dev, c, 0x17);
1511da177e4SLinus Torvalds 
152bc0fe4c9SOndrej Zary 		if (dev->dev_id == ATP885_DEVID)
1536a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 2, 0x06);
1541da177e4SLinus Torvalds 
1556a3cebb6SOndrej Zary 		target_id = atp_readb_io(dev, c, 0x15);
1561da177e4SLinus Torvalds 
1571da177e4SLinus Torvalds 		/*
1581da177e4SLinus Torvalds 		 *	Remap wide devices onto id numbers
1591da177e4SLinus Torvalds 		 */
1601da177e4SLinus Torvalds 
1611da177e4SLinus Torvalds 		if ((target_id & 0x40) != 0) {
1621da177e4SLinus Torvalds 			target_id = (target_id & 0x07) | 0x08;
1631da177e4SLinus Torvalds 		} else {
1641da177e4SLinus Torvalds 			target_id &= 0x07;
1651da177e4SLinus Torvalds 		}
1661da177e4SLinus Torvalds 
1671da177e4SLinus Torvalds 		if ((j & 0x40) != 0) {
1681da177e4SLinus Torvalds 		     if (dev->last_cmd[c] == 0xff) {
1691da177e4SLinus Torvalds 			dev->last_cmd[c] = target_id;
1701da177e4SLinus Torvalds 		     }
1711da177e4SLinus Torvalds 		     dev->last_cmd[c] |= 0x40;
1721da177e4SLinus Torvalds 		}
1731da177e4SLinus Torvalds 		if (dev->dev_id == ATP885_DEVID)
1741da177e4SLinus Torvalds 			dev->r1f[c][target_id] |= j;
1751da177e4SLinus Torvalds #ifdef ED_DBGP
1761da177e4SLinus Torvalds 		printk("atp870u_intr_handle status = %x\n",i);
1771da177e4SLinus Torvalds #endif
1781da177e4SLinus Torvalds 		if (i == 0x85) {
1791da177e4SLinus Torvalds 			if ((dev->last_cmd[c] & 0xf0) != 0x40) {
1801da177e4SLinus Torvalds 			   dev->last_cmd[c] = 0xff;
1811da177e4SLinus Torvalds 			}
1821da177e4SLinus Torvalds 			if (dev->dev_id == ATP885_DEVID) {
1831da177e4SLinus Torvalds 				adrcnt = 0;
1846a3cebb6SOndrej Zary 				((unsigned char *) &adrcnt)[2] = atp_readb_io(dev, c, 0x12);
1856a3cebb6SOndrej Zary 				((unsigned char *) &adrcnt)[1] = atp_readb_io(dev, c, 0x13);
1866a3cebb6SOndrej Zary 				((unsigned char *) &adrcnt)[0] = atp_readb_io(dev, c, 0x14);
1871da177e4SLinus Torvalds 				if (dev->id[c][target_id].last_len != adrcnt)
1881da177e4SLinus Torvalds 				{
1891da177e4SLinus Torvalds 			   		k = dev->id[c][target_id].last_len;
1901da177e4SLinus Torvalds 			   		k -= adrcnt;
1911da177e4SLinus Torvalds 			   		dev->id[c][target_id].tran_len = k;
1921da177e4SLinus Torvalds 			   	dev->id[c][target_id].last_len = adrcnt;
1931da177e4SLinus Torvalds 				}
1941da177e4SLinus Torvalds #ifdef ED_DBGP
1953a38e53eSOndrej 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);
1961da177e4SLinus Torvalds #endif
1971da177e4SLinus Torvalds 			}
1981da177e4SLinus Torvalds 
1991da177e4SLinus Torvalds 			/*
2001da177e4SLinus Torvalds 			 *      Flip wide
2011da177e4SLinus Torvalds 			 */
2021da177e4SLinus Torvalds 			if (dev->wide_id[c] != 0) {
2036a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x1b, 0x01);
2046a3cebb6SOndrej Zary 				while ((atp_readb_io(dev, c, 0x1b) & 0x01) != 0x01)
2056a3cebb6SOndrej Zary 					atp_writeb_io(dev, c, 0x1b, 0x01);
2061da177e4SLinus Torvalds 			}
2071da177e4SLinus Torvalds 			/*
2081da177e4SLinus Torvalds 			 *	Issue more commands
2091da177e4SLinus Torvalds 			 */
2101da177e4SLinus Torvalds 			spin_lock_irqsave(dev->host->host_lock, flags);
2111da177e4SLinus Torvalds 			if (((dev->quhd[c] != dev->quend[c]) || (dev->last_cmd[c] != 0xff)) &&
2121da177e4SLinus Torvalds 			    (dev->in_snd[c] == 0)) {
2131da177e4SLinus Torvalds #ifdef ED_DBGP
2141da177e4SLinus Torvalds 				printk("Call sent_s870\n");
2151da177e4SLinus Torvalds #endif
2161da177e4SLinus Torvalds 				send_s870(dev,c);
2171da177e4SLinus Torvalds 			}
2181da177e4SLinus Torvalds 			spin_unlock_irqrestore(dev->host->host_lock, flags);
2191da177e4SLinus Torvalds 			/*
2201da177e4SLinus Torvalds 			 *	Done
2211da177e4SLinus Torvalds 			 */
2221da177e4SLinus Torvalds 			dev->in_int[c] = 0;
2231da177e4SLinus Torvalds #ifdef ED_DBGP
2241da177e4SLinus Torvalds 				printk("Status 0x85 return\n");
2251da177e4SLinus Torvalds #endif
22678614ecdSOndrej Zary 			return IRQ_HANDLED;
2271da177e4SLinus Torvalds 		}
2281da177e4SLinus Torvalds 
2291da177e4SLinus Torvalds 		if (i == 0x40) {
2301da177e4SLinus Torvalds 		     dev->last_cmd[c] |= 0x40;
2311da177e4SLinus Torvalds 		     dev->in_int[c] = 0;
23278614ecdSOndrej Zary 		     return IRQ_HANDLED;
2331da177e4SLinus Torvalds 		}
2341da177e4SLinus Torvalds 
2351da177e4SLinus Torvalds 		if (i == 0x21) {
2361da177e4SLinus Torvalds 			if ((dev->last_cmd[c] & 0xf0) != 0x40) {
2371da177e4SLinus Torvalds 			   dev->last_cmd[c] = 0xff;
2381da177e4SLinus Torvalds 			}
2391da177e4SLinus Torvalds 			adrcnt = 0;
2406a3cebb6SOndrej Zary 			((unsigned char *) &adrcnt)[2] = atp_readb_io(dev, c, 0x12);
2416a3cebb6SOndrej Zary 			((unsigned char *) &adrcnt)[1] = atp_readb_io(dev, c, 0x13);
2426a3cebb6SOndrej Zary 			((unsigned char *) &adrcnt)[0] = atp_readb_io(dev, c, 0x14);
2431da177e4SLinus Torvalds 			k = dev->id[c][target_id].last_len;
2441da177e4SLinus Torvalds 			k -= adrcnt;
2451da177e4SLinus Torvalds 			dev->id[c][target_id].tran_len = k;
2461da177e4SLinus Torvalds 			dev->id[c][target_id].last_len = adrcnt;
2476a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x10, 0x41);
2486a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x18, 0x08);
2491da177e4SLinus Torvalds 			dev->in_int[c] = 0;
25078614ecdSOndrej Zary 			return IRQ_HANDLED;
2511da177e4SLinus Torvalds 		}
2521da177e4SLinus Torvalds 
2531da177e4SLinus Torvalds 		if (dev->dev_id == ATP885_DEVID) {
2541da177e4SLinus Torvalds 			if ((i == 0x4c) || (i == 0x4d) || (i == 0x8c) || (i == 0x8d)) {
2551da177e4SLinus Torvalds 		   		if ((i == 0x4c) || (i == 0x8c))
2561da177e4SLinus Torvalds 		      			i=0x48;
2571da177e4SLinus Torvalds 		   		else
2581da177e4SLinus Torvalds 		      			i=0x49;
2591da177e4SLinus Torvalds 		   	}
2601da177e4SLinus Torvalds 
2611da177e4SLinus Torvalds 		}
2621da177e4SLinus Torvalds 		if ((i == 0x80) || (i == 0x8f)) {
2631da177e4SLinus Torvalds #ifdef ED_DBGP
2641da177e4SLinus Torvalds 			printk(KERN_DEBUG "Device reselect\n");
2651da177e4SLinus Torvalds #endif
2661da177e4SLinus Torvalds 			lun = 0;
2676a3cebb6SOndrej Zary 			if (cmdp == 0x44 || i == 0x80)
2686a3cebb6SOndrej Zary 				lun = atp_readb_io(dev, c, 0x1d) & 0x07;
2696a3cebb6SOndrej Zary 			else {
2701da177e4SLinus Torvalds 				if ((dev->last_cmd[c] & 0xf0) != 0x40) {
2711da177e4SLinus Torvalds 				   dev->last_cmd[c] = 0xff;
2721da177e4SLinus Torvalds 				}
2731da177e4SLinus Torvalds 				if (cmdp == 0x41) {
2741da177e4SLinus Torvalds #ifdef ED_DBGP
2751da177e4SLinus Torvalds 					printk("cmdp = 0x41\n");
2761da177e4SLinus Torvalds #endif
2771da177e4SLinus Torvalds 					adrcnt = 0;
2786a3cebb6SOndrej Zary 					((unsigned char *) &adrcnt)[2] = atp_readb_io(dev, c, 0x12);
2796a3cebb6SOndrej Zary 					((unsigned char *) &adrcnt)[1] = atp_readb_io(dev, c, 0x13);
2806a3cebb6SOndrej Zary 					((unsigned char *) &adrcnt)[0] = atp_readb_io(dev, c, 0x14);
2811da177e4SLinus Torvalds 					k = dev->id[c][target_id].last_len;
2821da177e4SLinus Torvalds 					k -= adrcnt;
2831da177e4SLinus Torvalds 					dev->id[c][target_id].tran_len = k;
2841da177e4SLinus Torvalds 					dev->id[c][target_id].last_len = adrcnt;
2856a3cebb6SOndrej Zary 					atp_writeb_io(dev, c, 0x18, 0x08);
2861da177e4SLinus Torvalds 					dev->in_int[c] = 0;
28778614ecdSOndrej Zary 					return IRQ_HANDLED;
2881da177e4SLinus Torvalds 				} else {
2891da177e4SLinus Torvalds #ifdef ED_DBGP
2901da177e4SLinus Torvalds 					printk("cmdp != 0x41\n");
2911da177e4SLinus Torvalds #endif
2926a3cebb6SOndrej Zary 					atp_writeb_io(dev, c, 0x10, 0x46);
2931da177e4SLinus Torvalds 					dev->id[c][target_id].dirct = 0x00;
2946a3cebb6SOndrej Zary 					atp_writeb_io(dev, c, 0x12, 0x00);
2956a3cebb6SOndrej Zary 					atp_writeb_io(dev, c, 0x13, 0x00);
2966a3cebb6SOndrej Zary 					atp_writeb_io(dev, c, 0x14, 0x00);
2976a3cebb6SOndrej Zary 					atp_writeb_io(dev, c, 0x18, 0x08);
2981da177e4SLinus Torvalds 					dev->in_int[c] = 0;
29978614ecdSOndrej Zary 					return IRQ_HANDLED;
3001da177e4SLinus Torvalds 				}
3011da177e4SLinus Torvalds 			}
3021da177e4SLinus Torvalds 			if (dev->last_cmd[c] != 0xff) {
3031da177e4SLinus Torvalds 			   dev->last_cmd[c] |= 0x40;
3041da177e4SLinus Torvalds 			}
3051da177e4SLinus Torvalds 			if (dev->dev_id == ATP885_DEVID) {
3066a3cebb6SOndrej Zary 				j = atp_readb_base(dev, 0x29) & 0xfe;
3076a3cebb6SOndrej Zary 				atp_writeb_base(dev, 0x29, j);
3083a38e53eSOndrej Zary 			} else
3096a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x10, 0x45);
3101da177e4SLinus Torvalds 
3116a3cebb6SOndrej Zary 			target_id = atp_readb_io(dev, c, 0x16);
3121da177e4SLinus Torvalds 			/*
3131da177e4SLinus Torvalds 			 *	Remap wide identifiers
3141da177e4SLinus Torvalds 			 */
3151da177e4SLinus Torvalds 			if ((target_id & 0x10) != 0) {
3161da177e4SLinus Torvalds 				target_id = (target_id & 0x07) | 0x08;
3171da177e4SLinus Torvalds 			} else {
3181da177e4SLinus Torvalds 				target_id &= 0x07;
3191da177e4SLinus Torvalds 			}
3203a38e53eSOndrej Zary 			if (dev->dev_id == ATP885_DEVID)
3216a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x10, 0x45);
3221da177e4SLinus Torvalds 			workreq = dev->id[c][target_id].curr_req;
3231da177e4SLinus Torvalds #ifdef ED_DBGP
324017560fcSJeff Garzik 			scmd_printk(KERN_DEBUG, workreq, "CDB");
3251da177e4SLinus Torvalds 			for (l = 0; l < workreq->cmd_len; l++)
3261da177e4SLinus Torvalds 				printk(KERN_DEBUG " %x",workreq->cmnd[l]);
327017560fcSJeff Garzik 			printk("\n");
3281da177e4SLinus Torvalds #endif
3291da177e4SLinus Torvalds 
3306a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x0f, lun);
3316a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x11, dev->id[c][target_id].devsp);
3321da177e4SLinus Torvalds 			adrcnt = dev->id[c][target_id].tran_len;
3331da177e4SLinus Torvalds 			k = dev->id[c][target_id].last_len;
3341da177e4SLinus Torvalds 
3356a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x12, ((unsigned char *) &k)[2]);
3366a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x13, ((unsigned char *) &k)[1]);
3376a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x14, ((unsigned char *) &k)[0]);
3381da177e4SLinus Torvalds #ifdef ED_DBGP
3396a3cebb6SOndrej 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));
3401da177e4SLinus Torvalds #endif
3411da177e4SLinus Torvalds 			/* Remap wide */
3421da177e4SLinus Torvalds 			j = target_id;
3431da177e4SLinus Torvalds 			if (target_id > 7) {
3441da177e4SLinus Torvalds 				j = (j & 0x07) | 0x40;
3451da177e4SLinus Torvalds 			}
3461da177e4SLinus Torvalds 			/* Add direction */
3471da177e4SLinus Torvalds 			j |= dev->id[c][target_id].dirct;
3486a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x15, j);
3496a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x16, 0x80);
3501da177e4SLinus Torvalds 
3511da177e4SLinus Torvalds 			/* enable 32 bit fifo transfer */
3521da177e4SLinus Torvalds 			if (dev->dev_id == ATP885_DEVID) {
3536a3cebb6SOndrej Zary 				i = atp_readb_pci(dev, c, 1) & 0xf3;
3541da177e4SLinus Torvalds 				//j=workreq->cmnd[0];
3551da177e4SLinus Torvalds 				if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
3561da177e4SLinus Torvalds 				   i |= 0x0c;
3571da177e4SLinus Torvalds 				}
3586a3cebb6SOndrej Zary 				atp_writeb_pci(dev, c, 1, i);
3591da177e4SLinus Torvalds 			} else if ((dev->dev_id == ATP880_DEVID1) ||
3601da177e4SLinus Torvalds 	    		    	   (dev->dev_id == ATP880_DEVID2) ) {
3616a3cebb6SOndrej Zary 				if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a))
3626a3cebb6SOndrej Zary 					atp_writeb_base(dev, 0x3b, (atp_readb_base(dev, 0x3b) & 0x3f) | 0xc0);
3636a3cebb6SOndrej Zary 				else
3646a3cebb6SOndrej Zary 					atp_writeb_base(dev, 0x3b, atp_readb_base(dev, 0x3b) & 0x3f);
3651da177e4SLinus Torvalds 			} else {
3666a3cebb6SOndrej Zary 				if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a))
3676a3cebb6SOndrej Zary 					atp_writeb_io(dev, c, 0x3a, (atp_readb_io(dev, c, 0x3a) & 0xf3) | 0x08);
3686a3cebb6SOndrej Zary 				else
3696a3cebb6SOndrej Zary 					atp_writeb_io(dev, c, 0x3a, atp_readb_io(dev, c, 0x3a) & 0xf3);
3701da177e4SLinus Torvalds 			}
3711da177e4SLinus Torvalds 			j = 0;
3721da177e4SLinus Torvalds 			id = 1;
3731da177e4SLinus Torvalds 			id = id << target_id;
3741da177e4SLinus Torvalds 			/*
3751da177e4SLinus Torvalds 			 *	Is this a wide device
3761da177e4SLinus Torvalds 			 */
3771da177e4SLinus Torvalds 			if ((id & dev->wide_id[c]) != 0) {
3781da177e4SLinus Torvalds 				j |= 0x01;
3791da177e4SLinus Torvalds 			}
3806a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x1b, j);
3816a3cebb6SOndrej Zary 			while ((atp_readb_io(dev, c, 0x1b) & 0x01) != j)
3826a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x1b, j);
3831da177e4SLinus Torvalds 			if (dev->id[c][target_id].last_len == 0) {
3846a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x18, 0x08);
3851da177e4SLinus Torvalds 				dev->in_int[c] = 0;
3861da177e4SLinus Torvalds #ifdef ED_DBGP
3871da177e4SLinus Torvalds 				printk("dev->id[c][target_id].last_len = 0\n");
3881da177e4SLinus Torvalds #endif
38978614ecdSOndrej Zary 				return IRQ_HANDLED;
3901da177e4SLinus Torvalds 			}
3911da177e4SLinus Torvalds #ifdef ED_DBGP
3921da177e4SLinus Torvalds 			printk("target_id = %d adrcnt = %d\n",target_id,adrcnt);
3931da177e4SLinus Torvalds #endif
3941da177e4SLinus Torvalds 			prd = dev->id[c][target_id].prd_pos;
3951da177e4SLinus Torvalds 			while (adrcnt != 0) {
3961da177e4SLinus Torvalds 				id = ((unsigned short int *)prd)[2];
3971da177e4SLinus Torvalds 				if (id == 0) {
3981da177e4SLinus Torvalds 					k = 0x10000;
3991da177e4SLinus Torvalds 				} else {
4001da177e4SLinus Torvalds 					k = id;
4011da177e4SLinus Torvalds 				}
4021da177e4SLinus Torvalds 				if (k > adrcnt) {
4031da177e4SLinus Torvalds 					((unsigned short int *)prd)[2] = (unsigned short int)
4041da177e4SLinus Torvalds 					    (k - adrcnt);
4051da177e4SLinus Torvalds 					((unsigned long *)prd)[0] += adrcnt;
4061da177e4SLinus Torvalds 					adrcnt = 0;
4071da177e4SLinus Torvalds 					dev->id[c][target_id].prd_pos = prd;
4081da177e4SLinus Torvalds 				} else {
4091da177e4SLinus Torvalds 					adrcnt -= k;
4101da177e4SLinus Torvalds 					dev->id[c][target_id].prdaddr += 0x08;
4111da177e4SLinus Torvalds 					prd += 0x08;
4121da177e4SLinus Torvalds 					if (adrcnt == 0) {
4131da177e4SLinus Torvalds 						dev->id[c][target_id].prd_pos = prd;
4141da177e4SLinus Torvalds 					}
4151da177e4SLinus Torvalds 				}
4161da177e4SLinus Torvalds 			}
4176a3cebb6SOndrej Zary 			atp_writel_pci(dev, c, 0x04, dev->id[c][target_id].prdaddr);
4181da177e4SLinus Torvalds #ifdef ED_DBGP
4191da177e4SLinus Torvalds 			printk("dev->id[%d][%d].prdaddr 0x%8x\n", c, target_id, dev->id[c][target_id].prdaddr);
4201da177e4SLinus Torvalds #endif
421bc0fe4c9SOndrej Zary 			if (dev->dev_id != ATP885_DEVID) {
4226a3cebb6SOndrej Zary 				atp_writeb_pci(dev, c, 2, 0x06);
4236a3cebb6SOndrej Zary 				atp_writeb_pci(dev, c, 2, 0x00);
4241da177e4SLinus Torvalds 			}
4251da177e4SLinus Torvalds 			/*
4261da177e4SLinus Torvalds 			 *	Check transfer direction
4271da177e4SLinus Torvalds 			 */
4281da177e4SLinus Torvalds 			if (dev->id[c][target_id].dirct != 0) {
4296a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x18, 0x08);
4306a3cebb6SOndrej Zary 				atp_writeb_pci(dev, c, 0, 0x01);
4311da177e4SLinus Torvalds 				dev->in_int[c] = 0;
4321da177e4SLinus Torvalds #ifdef ED_DBGP
4331da177e4SLinus Torvalds 				printk("status 0x80 return dirct != 0\n");
4341da177e4SLinus Torvalds #endif
43578614ecdSOndrej Zary 				return IRQ_HANDLED;
4361da177e4SLinus Torvalds 			}
4376a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x18, 0x08);
4386a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 0, 0x09);
4391da177e4SLinus Torvalds 			dev->in_int[c] = 0;
4401da177e4SLinus Torvalds #ifdef ED_DBGP
4411da177e4SLinus Torvalds 			printk("status 0x80 return dirct = 0\n");
4421da177e4SLinus Torvalds #endif
44378614ecdSOndrej Zary 			return IRQ_HANDLED;
4441da177e4SLinus Torvalds 		}
4451da177e4SLinus Torvalds 
4461da177e4SLinus Torvalds 		/*
4471da177e4SLinus Torvalds 		 *	Current scsi request on this target
4481da177e4SLinus Torvalds 		 */
4491da177e4SLinus Torvalds 
4501da177e4SLinus Torvalds 		workreq = dev->id[c][target_id].curr_req;
4511da177e4SLinus Torvalds 
45278614ecdSOndrej Zary 		if (i == 0x42 || i == 0x16) {
4531da177e4SLinus Torvalds 			if ((dev->last_cmd[c] & 0xf0) != 0x40) {
4541da177e4SLinus Torvalds 			   dev->last_cmd[c] = 0xff;
4551da177e4SLinus Torvalds 			}
45678614ecdSOndrej Zary 			if (i == 0x16) {
4576a3cebb6SOndrej Zary 				workreq->result = atp_readb_io(dev, c, 0x0f);
4581da177e4SLinus Torvalds 				if (((dev->r1f[c][target_id] & 0x10) != 0)&&(dev->dev_id==ATP885_DEVID)) {
4591da177e4SLinus Torvalds 					printk(KERN_WARNING "AEC67162 CRC ERROR !\n");
46078614ecdSOndrej Zary 					workreq->result = 0x02;
4611da177e4SLinus Torvalds 				}
46278614ecdSOndrej Zary 			} else
46378614ecdSOndrej Zary 				workreq->result = 0x02;
46478614ecdSOndrej Zary 
4651da177e4SLinus Torvalds 			if (dev->dev_id == ATP885_DEVID) {
4666a3cebb6SOndrej Zary 				j = atp_readb_base(dev, 0x29) | 0x01;
4676a3cebb6SOndrej Zary 				atp_writeb_base(dev, 0x29, j);
4681da177e4SLinus Torvalds 			}
4691da177e4SLinus Torvalds 			/*
4701da177e4SLinus Torvalds 			 *	Complete the command
4711da177e4SLinus Torvalds 			 */
472fe7ed98fSBoaz Harrosh 			scsi_dma_unmap(workreq);
473fe7ed98fSBoaz Harrosh 
4741da177e4SLinus Torvalds 			spin_lock_irqsave(dev->host->host_lock, flags);
4751da177e4SLinus Torvalds 			(*workreq->scsi_done) (workreq);
4761da177e4SLinus Torvalds #ifdef ED_DBGP
4771da177e4SLinus Torvalds 			   printk("workreq->scsi_done\n");
4781da177e4SLinus Torvalds #endif
4791da177e4SLinus Torvalds 			/*
4801da177e4SLinus Torvalds 			 *	Clear it off the queue
4811da177e4SLinus Torvalds 			 */
4821da177e4SLinus Torvalds 			dev->id[c][target_id].curr_req = NULL;
4831da177e4SLinus Torvalds 			dev->working[c]--;
4841da177e4SLinus Torvalds 			spin_unlock_irqrestore(dev->host->host_lock, flags);
4851da177e4SLinus Torvalds 			/*
4861da177e4SLinus Torvalds 			 *      Take it back wide
4871da177e4SLinus Torvalds 			 */
4881da177e4SLinus Torvalds 			if (dev->wide_id[c] != 0) {
4896a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x1b, 0x01);
4906a3cebb6SOndrej Zary 				while ((atp_readb_io(dev, c, 0x1b) & 0x01) != 0x01)
4916a3cebb6SOndrej Zary 					atp_writeb_io(dev, c, 0x1b, 0x01);
4921da177e4SLinus Torvalds 			}
4931da177e4SLinus Torvalds 			/*
4941da177e4SLinus Torvalds 			 *	If there is stuff to send and nothing going then send it
4951da177e4SLinus Torvalds 			 */
4961da177e4SLinus Torvalds 			spin_lock_irqsave(dev->host->host_lock, flags);
4971da177e4SLinus Torvalds 			if (((dev->last_cmd[c] != 0xff) || (dev->quhd[c] != dev->quend[c])) &&
4981da177e4SLinus Torvalds 			    (dev->in_snd[c] == 0)) {
4991da177e4SLinus Torvalds #ifdef ED_DBGP
5001da177e4SLinus Torvalds 			   printk("Call sent_s870(scsi_done)\n");
5011da177e4SLinus Torvalds #endif
5021da177e4SLinus Torvalds 			   send_s870(dev,c);
5031da177e4SLinus Torvalds 			}
5041da177e4SLinus Torvalds 			spin_unlock_irqrestore(dev->host->host_lock, flags);
5051da177e4SLinus Torvalds 			dev->in_int[c] = 0;
50678614ecdSOndrej Zary 			return IRQ_HANDLED;
5071da177e4SLinus Torvalds 		}
5081da177e4SLinus Torvalds 		if ((dev->last_cmd[c] & 0xf0) != 0x40) {
5091da177e4SLinus Torvalds 		   dev->last_cmd[c] = 0xff;
5101da177e4SLinus Torvalds 		}
5111da177e4SLinus Torvalds 		if (i == 0x4f) {
5121da177e4SLinus Torvalds 			i = 0x89;
5131da177e4SLinus Torvalds 		}
5141da177e4SLinus Torvalds 		i &= 0x0f;
5151da177e4SLinus Torvalds 		if (i == 0x09) {
5166a3cebb6SOndrej Zary 			atp_writel_pci(dev, c, 4, dev->id[c][target_id].prdaddr);
5176a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 2, 0x06);
5186a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 2, 0x00);
5196a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x10, 0x41);
5201da177e4SLinus Torvalds 			if (dev->dev_id == ATP885_DEVID) {
5211da177e4SLinus Torvalds 				k = dev->id[c][target_id].last_len;
5226a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x12, ((unsigned char *) (&k))[2]);
5236a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x13, ((unsigned char *) (&k))[1]);
5246a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x14, ((unsigned char *) (&k))[0]);
5251da177e4SLinus Torvalds 				dev->id[c][target_id].dirct = 0x00;
5261da177e4SLinus Torvalds 			} else {
5271da177e4SLinus Torvalds 				dev->id[c][target_id].dirct = 0x00;
5281da177e4SLinus Torvalds 			}
5296a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x18, 0x08);
5306a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 0, 0x09);
5311da177e4SLinus Torvalds 			dev->in_int[c] = 0;
53278614ecdSOndrej Zary 			return IRQ_HANDLED;
5331da177e4SLinus Torvalds 		}
5341da177e4SLinus Torvalds 		if (i == 0x08) {
5356a3cebb6SOndrej Zary 			atp_writel_pci(dev, c, 4, dev->id[c][target_id].prdaddr);
5366a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 2, 0x06);
5376a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 2, 0x00);
5386a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x10, 0x41);
5391da177e4SLinus Torvalds 			if (dev->dev_id == ATP885_DEVID) {
5401da177e4SLinus Torvalds 				k = dev->id[c][target_id].last_len;
5416a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x12, ((unsigned char *) (&k))[2]);
5426a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x13, ((unsigned char *) (&k))[1]);
5436a3cebb6SOndrej Zary 				atp_writeb_io(dev, c, 0x14, ((unsigned char *) (&k))[0]);
5441da177e4SLinus Torvalds 			}
5456a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x15, atp_readb_io(dev, c, 0x15) | 0x20);
5461da177e4SLinus Torvalds 			dev->id[c][target_id].dirct = 0x20;
5476a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x18, 0x08);
5486a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 0, 0x01);
5491da177e4SLinus Torvalds 			dev->in_int[c] = 0;
55078614ecdSOndrej Zary 			return IRQ_HANDLED;
5511da177e4SLinus Torvalds 		}
5526a3cebb6SOndrej Zary 		if (i == 0x0a)
5536a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x10, 0x30);
5546a3cebb6SOndrej Zary 		else
5556a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x10, 0x46);
5561da177e4SLinus Torvalds 		dev->id[c][target_id].dirct = 0x00;
5576a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0x00);
5586a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x13, 0x00);
5596a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x00);
5606a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
5611da177e4SLinus Torvalds 	}
56278614ecdSOndrej Zary 	dev->in_int[c] = 0;
5631da177e4SLinus Torvalds 
5641da177e4SLinus Torvalds 	return IRQ_HANDLED;
5651da177e4SLinus Torvalds }
5661da177e4SLinus Torvalds /**
5671da177e4SLinus Torvalds  *	atp870u_queuecommand	-	Queue SCSI command
5681da177e4SLinus Torvalds  *	@req_p: request block
5691da177e4SLinus Torvalds  *	@done: completion function
5701da177e4SLinus Torvalds  *
5711da177e4SLinus Torvalds  *	Queue a command to the ATP queue. Called with the host lock held.
5721da177e4SLinus Torvalds  */
573f281233dSJeff Garzik static int atp870u_queuecommand_lck(struct scsi_cmnd *req_p,
5741da177e4SLinus Torvalds 			 void (*done) (struct scsi_cmnd *))
5751da177e4SLinus Torvalds {
5761da177e4SLinus Torvalds 	unsigned char c;
5773b836464SOndrej Zary 	unsigned int m;
5781da177e4SLinus Torvalds 	struct atp_unit *dev;
5791da177e4SLinus Torvalds 	struct Scsi_Host *host;
5801da177e4SLinus Torvalds 
581422c0d61SJeff Garzik 	c = scmd_channel(req_p);
5821da177e4SLinus Torvalds 	req_p->sense_buffer[0]=0;
583fe7ed98fSBoaz Harrosh 	scsi_set_resid(req_p, 0);
584422c0d61SJeff Garzik 	if (scmd_channel(req_p) > 1) {
5851da177e4SLinus Torvalds 		req_p->result = 0x00040000;
5861da177e4SLinus Torvalds 		done(req_p);
5871da177e4SLinus Torvalds #ifdef ED_DBGP
5881da177e4SLinus Torvalds 		printk("atp870u_queuecommand : req_p->device->channel > 1\n");
5891da177e4SLinus Torvalds #endif
5901da177e4SLinus Torvalds 		return 0;
5911da177e4SLinus Torvalds 	}
5921da177e4SLinus Torvalds 
5931da177e4SLinus Torvalds 	host = req_p->device->host;
5941da177e4SLinus Torvalds 	dev = (struct atp_unit *)&host->hostdata;
5951da177e4SLinus Torvalds 
5961da177e4SLinus Torvalds 
5971da177e4SLinus Torvalds 
5981da177e4SLinus Torvalds 	m = 1;
599422c0d61SJeff Garzik 	m = m << scmd_id(req_p);
6001da177e4SLinus Torvalds 
6011da177e4SLinus Torvalds 	/*
6021da177e4SLinus Torvalds 	 *      Fake a timeout for missing targets
6031da177e4SLinus Torvalds 	 */
6041da177e4SLinus Torvalds 
6051da177e4SLinus Torvalds 	if ((m & dev->active_id[c]) == 0) {
6061da177e4SLinus Torvalds 		req_p->result = 0x00040000;
6071da177e4SLinus Torvalds 		done(req_p);
6081da177e4SLinus Torvalds 		return 0;
6091da177e4SLinus Torvalds 	}
6101da177e4SLinus Torvalds 
6111da177e4SLinus Torvalds 	if (done) {
6121da177e4SLinus Torvalds 		req_p->scsi_done = done;
6131da177e4SLinus Torvalds 	} else {
6141da177e4SLinus Torvalds #ifdef ED_DBGP
6151da177e4SLinus Torvalds 		printk( "atp870u_queuecommand: done can't be NULL\n");
6161da177e4SLinus Torvalds #endif
6171da177e4SLinus Torvalds 		req_p->result = 0;
6181da177e4SLinus Torvalds 		done(req_p);
6191da177e4SLinus Torvalds 		return 0;
6201da177e4SLinus Torvalds 	}
6211da177e4SLinus Torvalds 
6221da177e4SLinus Torvalds 	/*
6231da177e4SLinus Torvalds 	 *	Count new command
6241da177e4SLinus Torvalds 	 */
6251da177e4SLinus Torvalds 	dev->quend[c]++;
6261da177e4SLinus Torvalds 	if (dev->quend[c] >= qcnt) {
6271da177e4SLinus Torvalds 		dev->quend[c] = 0;
6281da177e4SLinus Torvalds 	}
6291da177e4SLinus Torvalds 
6301da177e4SLinus Torvalds 	/*
6311da177e4SLinus Torvalds 	 *	Check queue state
6321da177e4SLinus Torvalds 	 */
6331da177e4SLinus Torvalds 	if (dev->quhd[c] == dev->quend[c]) {
6341da177e4SLinus Torvalds 		if (dev->quend[c] == 0) {
6351da177e4SLinus Torvalds 			dev->quend[c] = qcnt;
6361da177e4SLinus Torvalds 		}
6371da177e4SLinus Torvalds #ifdef ED_DBGP
6381da177e4SLinus Torvalds 		printk("atp870u_queuecommand : dev->quhd[c] == dev->quend[c]\n");
6391da177e4SLinus Torvalds #endif
6401da177e4SLinus Torvalds 		dev->quend[c]--;
6411da177e4SLinus Torvalds 		req_p->result = 0x00020000;
6421da177e4SLinus Torvalds 		done(req_p);
6431da177e4SLinus Torvalds 		return 0;
6441da177e4SLinus Torvalds 	}
6451da177e4SLinus Torvalds 	dev->quereq[c][dev->quend[c]] = req_p;
6461da177e4SLinus Torvalds #ifdef ED_DBGP
6476a3cebb6SOndrej 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]);
6481da177e4SLinus Torvalds #endif
6496a3cebb6SOndrej Zary 	if ((atp_readb_io(dev, c, 0x1c) == 0) && (dev->in_int[c] == 0) && (dev->in_snd[c] == 0)) {
6501da177e4SLinus Torvalds #ifdef ED_DBGP
6511da177e4SLinus Torvalds 		printk("Call sent_s870(atp870u_queuecommand)\n");
6521da177e4SLinus Torvalds #endif
6531da177e4SLinus Torvalds 		send_s870(dev,c);
6541da177e4SLinus Torvalds 	}
6551da177e4SLinus Torvalds #ifdef ED_DBGP
6561da177e4SLinus Torvalds 	printk("atp870u_queuecommand : exit\n");
6571da177e4SLinus Torvalds #endif
6581da177e4SLinus Torvalds 	return 0;
6591da177e4SLinus Torvalds }
6601da177e4SLinus Torvalds 
661f281233dSJeff Garzik static DEF_SCSI_QCMD(atp870u_queuecommand)
662f281233dSJeff Garzik 
6631da177e4SLinus Torvalds /**
6641da177e4SLinus Torvalds  *	send_s870	-	send a command to the controller
6651da177e4SLinus Torvalds  *	@host: host
6661da177e4SLinus Torvalds  *
6671da177e4SLinus Torvalds  *	On entry there is work queued to be done. We move some of that work to the
6681da177e4SLinus Torvalds  *	controller itself.
6691da177e4SLinus Torvalds  *
6701da177e4SLinus Torvalds  *	Caller holds the host lock.
6711da177e4SLinus Torvalds  */
6721da177e4SLinus Torvalds static void send_s870(struct atp_unit *dev,unsigned char c)
6731da177e4SLinus Torvalds {
674468b8968SOndrej Zary 	struct scsi_cmnd *workreq = NULL;
6751da177e4SLinus Torvalds 	unsigned int i;//,k;
6761da177e4SLinus Torvalds 	unsigned char  j, target_id;
6771da177e4SLinus Torvalds 	unsigned char *prd;
678c2bab403SOndrej Zary 	unsigned short int w;
6791da177e4SLinus Torvalds 	unsigned long l, bttl = 0;
6801da177e4SLinus Torvalds 	unsigned long  sg_count;
6811da177e4SLinus Torvalds 
6821da177e4SLinus Torvalds 	if (dev->in_snd[c] != 0) {
6831da177e4SLinus Torvalds #ifdef ED_DBGP
6841da177e4SLinus Torvalds 		printk("cmnd in_snd\n");
6851da177e4SLinus Torvalds #endif
6861da177e4SLinus Torvalds 		return;
6871da177e4SLinus Torvalds 	}
6881da177e4SLinus Torvalds #ifdef ED_DBGP
6891da177e4SLinus Torvalds 	printk("Sent_s870 enter\n");
6901da177e4SLinus Torvalds #endif
6911da177e4SLinus Torvalds 	dev->in_snd[c] = 1;
6921da177e4SLinus Torvalds 	if ((dev->last_cmd[c] != 0xff) && ((dev->last_cmd[c] & 0x40) != 0)) {
6931da177e4SLinus Torvalds 		dev->last_cmd[c] &= 0x0f;
6941da177e4SLinus Torvalds 		workreq = dev->id[c][dev->last_cmd[c]].curr_req;
695468b8968SOndrej Zary 		if (!workreq) {
6961da177e4SLinus Torvalds 			dev->last_cmd[c] = 0xff;
6971da177e4SLinus Torvalds 			if (dev->quhd[c] == dev->quend[c]) {
6981da177e4SLinus Torvalds 				dev->in_snd[c] = 0;
6991da177e4SLinus Torvalds 				return;
7001da177e4SLinus Torvalds 			}
7011da177e4SLinus Torvalds 		}
702468b8968SOndrej Zary 	}
703468b8968SOndrej Zary 	if (!workreq) {
7041da177e4SLinus Torvalds 		if ((dev->last_cmd[c] != 0xff) && (dev->working[c] != 0)) {
7051da177e4SLinus Torvalds 			dev->in_snd[c] = 0;
7061da177e4SLinus Torvalds 			return;
7071da177e4SLinus Torvalds 		}
7081da177e4SLinus Torvalds 		dev->working[c]++;
7091da177e4SLinus Torvalds 		j = dev->quhd[c];
7101da177e4SLinus Torvalds 		dev->quhd[c]++;
711468b8968SOndrej Zary 		if (dev->quhd[c] >= qcnt)
7121da177e4SLinus Torvalds 			dev->quhd[c] = 0;
7131da177e4SLinus Torvalds 		workreq = dev->quereq[c][dev->quhd[c]];
714468b8968SOndrej Zary 		if (dev->id[c][scmd_id(workreq)].curr_req != NULL) {
7151da177e4SLinus Torvalds 			dev->quhd[c] = j;
7161da177e4SLinus Torvalds 			dev->working[c]--;
7171da177e4SLinus Torvalds 			dev->in_snd[c] = 0;
7181da177e4SLinus Torvalds 			return;
7191da177e4SLinus Torvalds 		}
720468b8968SOndrej Zary 		dev->id[c][scmd_id(workreq)].curr_req = workreq;
721468b8968SOndrej Zary 		dev->last_cmd[c] = scmd_id(workreq);
7221da177e4SLinus Torvalds 	}
7236a3cebb6SOndrej Zary 	if ((atp_readb_io(dev, c, 0x1f) & 0xb0) != 0 || atp_readb_io(dev, c, 0x1c) != 0) {
7241da177e4SLinus Torvalds #ifdef ED_DBGP
7251da177e4SLinus Torvalds 		printk("Abort to Send\n");
7261da177e4SLinus Torvalds #endif
7271da177e4SLinus Torvalds 		dev->last_cmd[c] |= 0x40;
7281da177e4SLinus Torvalds 		dev->in_snd[c] = 0;
7291da177e4SLinus Torvalds 		return;
730468b8968SOndrej Zary 	}
7311da177e4SLinus Torvalds #ifdef ED_DBGP
7321da177e4SLinus Torvalds 	printk("OK to Send\n");
733422c0d61SJeff Garzik 	scmd_printk(KERN_DEBUG, workreq, "CDB");
7341da177e4SLinus Torvalds 	for(i=0;i<workreq->cmd_len;i++) {
7351da177e4SLinus Torvalds 		printk(" %x",workreq->cmnd[i]);
7361da177e4SLinus Torvalds 	}
737422c0d61SJeff Garzik 	printk("\n");
7381da177e4SLinus Torvalds #endif
739fe7ed98fSBoaz Harrosh 	l = scsi_bufflen(workreq);
740fe7ed98fSBoaz Harrosh 
7411da177e4SLinus Torvalds 	if (dev->dev_id == ATP885_DEVID) {
7426a3cebb6SOndrej Zary 		j = atp_readb_base(dev, 0x29) & 0xfe;
7436a3cebb6SOndrej Zary 		atp_writeb_base(dev, 0x29, j);
744422c0d61SJeff Garzik 		dev->r1f[c][scmd_id(workreq)] = 0;
7451da177e4SLinus Torvalds 	}
7461da177e4SLinus Torvalds 
7471da177e4SLinus Torvalds 	if (workreq->cmnd[0] == READ_CAPACITY) {
748fe7ed98fSBoaz Harrosh 		if (l > 8)
749fe7ed98fSBoaz Harrosh 			l = 8;
7501da177e4SLinus Torvalds 	}
7511da177e4SLinus Torvalds 	if (workreq->cmnd[0] == 0x00) {
752fe7ed98fSBoaz Harrosh 		l = 0;
7531da177e4SLinus Torvalds 	}
7541da177e4SLinus Torvalds 
7551da177e4SLinus Torvalds 	j = 0;
756422c0d61SJeff Garzik 	target_id = scmd_id(workreq);
7571da177e4SLinus Torvalds 
7581da177e4SLinus Torvalds 	/*
7591da177e4SLinus Torvalds 	 *	Wide ?
7601da177e4SLinus Torvalds 	 */
7611da177e4SLinus Torvalds 	w = 1;
7621da177e4SLinus Torvalds 	w = w << target_id;
7631da177e4SLinus Torvalds 	if ((w & dev->wide_id[c]) != 0) {
7641da177e4SLinus Torvalds 		j |= 0x01;
7651da177e4SLinus Torvalds 	}
7666a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x1b, j);
7676a3cebb6SOndrej Zary 	while ((atp_readb_io(dev, c, 0x1b) & 0x01) != j) {
7686a3cebb6SOndrej Zary 		atp_writeb_pci(dev, c, 0x1b, j);
7691da177e4SLinus Torvalds #ifdef ED_DBGP
7701da177e4SLinus Torvalds 		printk("send_s870 while loop 1\n");
7711da177e4SLinus Torvalds #endif
7721da177e4SLinus Torvalds 	}
7731da177e4SLinus Torvalds 	/*
7741da177e4SLinus Torvalds 	 *	Write the command
7751da177e4SLinus Torvalds 	 */
7761da177e4SLinus Torvalds 
7776a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x00, workreq->cmd_len);
7786a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x01, 0x2c);
7796a3cebb6SOndrej Zary 	if (dev->dev_id == ATP885_DEVID)
7806a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x02, 0x7f);
7816a3cebb6SOndrej Zary 	else
7826a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x02, 0xcf);
7836a3cebb6SOndrej Zary 	for (i = 0; i < workreq->cmd_len; i++)
7846a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x03 + i, workreq->cmnd[i]);
7856a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x0f, workreq->device->lun);
7861da177e4SLinus Torvalds 	/*
7871da177e4SLinus Torvalds 	 *	Write the target
7881da177e4SLinus Torvalds 	 */
7896a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x11, dev->id[c][target_id].devsp);
7901da177e4SLinus Torvalds #ifdef ED_DBGP
7911da177e4SLinus Torvalds 	printk("dev->id[%d][%d].devsp = %2x\n",c,target_id,dev->id[c][target_id].devsp);
7921da177e4SLinus Torvalds #endif
7931da177e4SLinus Torvalds 
794fe7ed98fSBoaz Harrosh 	sg_count = scsi_dma_map(workreq);
7951da177e4SLinus Torvalds 	/*
7961da177e4SLinus Torvalds 	 *	Write transfer size
7971da177e4SLinus Torvalds 	 */
7986a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x12, ((unsigned char *) (&l))[2]);
7996a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x13, ((unsigned char *) (&l))[1]);
8006a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x14, ((unsigned char *) (&l))[0]);
8011da177e4SLinus Torvalds 	j = target_id;
8021da177e4SLinus Torvalds 	dev->id[c][j].last_len = l;
8031da177e4SLinus Torvalds 	dev->id[c][j].tran_len = 0;
8041da177e4SLinus Torvalds #ifdef ED_DBGP
8051da177e4SLinus Torvalds 	printk("dev->id[%2d][%2d].last_len = %d\n",c,j,dev->id[c][j].last_len);
8061da177e4SLinus Torvalds #endif
8071da177e4SLinus Torvalds 	/*
8081da177e4SLinus Torvalds 	 *	Flip the wide bits
8091da177e4SLinus Torvalds 	 */
8101da177e4SLinus Torvalds 	if ((j & 0x08) != 0) {
8111da177e4SLinus Torvalds 		j = (j & 0x07) | 0x40;
8121da177e4SLinus Torvalds 	}
8131da177e4SLinus Torvalds 	/*
8141da177e4SLinus Torvalds 	 *	Check transfer direction
8151da177e4SLinus Torvalds 	 */
8166a3cebb6SOndrej Zary 	if (workreq->sc_data_direction == DMA_TO_DEVICE)
8176a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x15, j | 0x20);
8186a3cebb6SOndrej Zary 	else
8196a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x15, j);
8206a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x16, atp_readb_io(dev, c, 0x16) | 0x80);
8216a3cebb6SOndrej Zary 	atp_writeb_io(dev, c, 0x16, 0x80);
8221da177e4SLinus Torvalds 	dev->id[c][target_id].dirct = 0;
8231da177e4SLinus Torvalds 	if (l == 0) {
8246a3cebb6SOndrej Zary 		if (atp_readb_io(dev, c, 0x1c) == 0) {
8251da177e4SLinus Torvalds #ifdef ED_DBGP
8261da177e4SLinus Torvalds 			printk("change SCSI_CMD_REG 0x08\n");
8271da177e4SLinus Torvalds #endif
8286a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x18, 0x08);
8296a3cebb6SOndrej Zary 		} else
8301da177e4SLinus Torvalds 			dev->last_cmd[c] |= 0x40;
8311da177e4SLinus Torvalds 		dev->in_snd[c] = 0;
8321da177e4SLinus Torvalds 		return;
8331da177e4SLinus Torvalds 	}
8341da177e4SLinus Torvalds 	prd = dev->id[c][target_id].prd_table;
8351da177e4SLinus Torvalds 	dev->id[c][target_id].prd_pos = prd;
8361da177e4SLinus Torvalds 
8371da177e4SLinus Torvalds 	/*
8381da177e4SLinus Torvalds 	 *	Now write the request list. Either as scatter/gather or as
8391da177e4SLinus Torvalds 	 *	a linear chain.
8401da177e4SLinus Torvalds 	 */
8411da177e4SLinus Torvalds 
842fe7ed98fSBoaz Harrosh 	if (l) {
843fe7ed98fSBoaz Harrosh 		struct scatterlist *sgpnt;
8441da177e4SLinus Torvalds 		i = 0;
845fe7ed98fSBoaz Harrosh 		scsi_for_each_sg(workreq, sgpnt, sg_count, j) {
846fe7ed98fSBoaz Harrosh 			bttl = sg_dma_address(sgpnt);
847fe7ed98fSBoaz Harrosh 			l=sg_dma_len(sgpnt);
8481da177e4SLinus Torvalds #ifdef ED_DBGP
8491da177e4SLinus Torvalds 			printk("1. bttl %x, l %x\n",bttl, l);
8501da177e4SLinus Torvalds #endif
8511da177e4SLinus Torvalds 			while (l > 0x10000) {
8521da177e4SLinus Torvalds 				(((u16 *) (prd))[i + 3]) = 0x0000;
8531da177e4SLinus Torvalds 				(((u16 *) (prd))[i + 2]) = 0x0000;
8541da177e4SLinus Torvalds 				(((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
8551da177e4SLinus Torvalds 				l -= 0x10000;
8561da177e4SLinus Torvalds 				bttl += 0x10000;
8571da177e4SLinus Torvalds 				i += 0x04;
8581da177e4SLinus Torvalds 			}
8591da177e4SLinus Torvalds 			(((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
8601da177e4SLinus Torvalds 			(((u16 *) (prd))[i + 2]) = cpu_to_le16(l);
8611da177e4SLinus Torvalds 			(((u16 *) (prd))[i + 3]) = 0;
8621da177e4SLinus Torvalds 			i += 0x04;
8631da177e4SLinus Torvalds 		}
8641da177e4SLinus Torvalds 		(((u16 *) (prd))[i - 1]) = cpu_to_le16(0x8000);
8651da177e4SLinus Torvalds #ifdef ED_DBGP
8661da177e4SLinus 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]));
8671da177e4SLinus Torvalds 		printk("2. bttl %x, l %x\n",bttl, l);
8681da177e4SLinus Torvalds #endif
8691da177e4SLinus Torvalds 	}
8701da177e4SLinus Torvalds #ifdef ED_DBGP
871c2bab403SOndrej Zary 	printk("send_s870: prdaddr_2 0x%8x target_id %d\n", dev->id[c][target_id].prdaddr,target_id);
8721da177e4SLinus Torvalds #endif
873b5683557SJames Bottomley 	dev->id[c][target_id].prdaddr = dev->id[c][target_id].prd_bus;
8746a3cebb6SOndrej Zary 	atp_writel_pci(dev, c, 4, dev->id[c][target_id].prdaddr);
8756a3cebb6SOndrej Zary 	atp_writeb_pci(dev, c, 2, 0x06);
8766a3cebb6SOndrej Zary 	atp_writeb_pci(dev, c, 2, 0x00);
8771da177e4SLinus Torvalds 	if (dev->dev_id == ATP885_DEVID) {
8786a3cebb6SOndrej Zary 		j = atp_readb_pci(dev, c, 1) & 0xf3;
8791da177e4SLinus Torvalds 		if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) ||
8801da177e4SLinus Torvalds 	    	(workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
8811da177e4SLinus Torvalds 	   		j |= 0x0c;
8821da177e4SLinus Torvalds 		}
8836a3cebb6SOndrej Zary 		atp_writeb_pci(dev, c, 1, j);
8841da177e4SLinus Torvalds 	} else if ((dev->dev_id == ATP880_DEVID1) ||
8851da177e4SLinus Torvalds 	    	   (dev->dev_id == ATP880_DEVID2)) {
8866a3cebb6SOndrej Zary 		if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a))
8876a3cebb6SOndrej Zary 			atp_writeb_base(dev, 0x3b, (atp_readb_base(dev, 0x3b) & 0x3f) | 0xc0);
8886a3cebb6SOndrej Zary 		else
8896a3cebb6SOndrej Zary 			atp_writeb_base(dev, 0x3b, atp_readb_base(dev, 0x3b) & 0x3f);
8901da177e4SLinus Torvalds 	} else {
8916a3cebb6SOndrej Zary 		if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a))
8926a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x3a, (atp_readb_io(dev, c, 0x3a) & 0xf3) | 0x08);
8936a3cebb6SOndrej Zary 		else
8946a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x3a, atp_readb_io(dev, c, 0x3a) & 0xf3);
8951da177e4SLinus Torvalds 	}
8961da177e4SLinus Torvalds 
8971da177e4SLinus Torvalds 	if(workreq->sc_data_direction == DMA_TO_DEVICE) {
8981da177e4SLinus Torvalds 		dev->id[c][target_id].dirct = 0x20;
8996a3cebb6SOndrej Zary 		if (atp_readb_io(dev, c, 0x1c) == 0) {
9006a3cebb6SOndrej Zary 			atp_writeb_io(dev, c, 0x18, 0x08);
9016a3cebb6SOndrej Zary 			atp_writeb_pci(dev, c, 0, 0x01);
9021da177e4SLinus Torvalds #ifdef ED_DBGP
9031da177e4SLinus Torvalds 		printk( "start DMA(to target)\n");
9041da177e4SLinus Torvalds #endif
9051da177e4SLinus Torvalds 		} else {
9061da177e4SLinus Torvalds 			dev->last_cmd[c] |= 0x40;
9071da177e4SLinus Torvalds 		}
9081da177e4SLinus Torvalds 		dev->in_snd[c] = 0;
9091da177e4SLinus Torvalds 		return;
9101da177e4SLinus Torvalds 	}
9116a3cebb6SOndrej Zary 	if (atp_readb_io(dev, c, 0x1c) == 0) {
9126a3cebb6SOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
9136a3cebb6SOndrej Zary 		atp_writeb_pci(dev, c, 0, 0x09);
9141da177e4SLinus Torvalds #ifdef ED_DBGP
9151da177e4SLinus Torvalds 		printk( "start DMA(to host)\n");
9161da177e4SLinus Torvalds #endif
9171da177e4SLinus Torvalds 	} else {
9181da177e4SLinus Torvalds 		dev->last_cmd[c] |= 0x40;
9191da177e4SLinus Torvalds 	}
9201da177e4SLinus Torvalds 	dev->in_snd[c] = 0;
9211da177e4SLinus Torvalds 	return;
9221da177e4SLinus Torvalds 
9231da177e4SLinus Torvalds }
9241da177e4SLinus Torvalds 
9251da177e4SLinus Torvalds static unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val)
9261da177e4SLinus Torvalds {
9271da177e4SLinus Torvalds 	unsigned short int i, k;
9281da177e4SLinus Torvalds 	unsigned char j;
9291da177e4SLinus Torvalds 
9306a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, *val);
9311da177e4SLinus Torvalds 	for (i = 0; i < 10; i++) {	/* stable >= bus settle delay(400 ns)  */
9326a3cebb6SOndrej Zary 		k = atp_readw_io(dev, 0, 0x1c);
9331da177e4SLinus Torvalds 		j = (unsigned char) (k >> 8);
934832e9ac6SOndrej Zary 		if ((k & 0x8000) != 0)	/* DB7 all release?    */
935832e9ac6SOndrej Zary 			i = 0;
9361da177e4SLinus Torvalds 	}
9371da177e4SLinus Torvalds 	*val |= 0x4000;		/* assert DB6           */
9386a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, *val);
9391da177e4SLinus Torvalds 	*val &= 0xdfff;		/* assert DB5           */
9406a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, *val);
9411da177e4SLinus Torvalds 	for (i = 0; i < 10; i++) {	/* stable >= bus settle delay(400 ns) */
9426a3cebb6SOndrej Zary 		if ((atp_readw_io(dev, 0, 0x1c) & 0x2000) != 0)	/* DB5 all release?       */
943832e9ac6SOndrej Zary 			i = 0;
9441da177e4SLinus Torvalds 	}
9451da177e4SLinus Torvalds 	*val |= 0x8000;		/* no DB4-0, assert DB7    */
9461da177e4SLinus Torvalds 	*val &= 0xe0ff;
9476a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, *val);
9481da177e4SLinus Torvalds 	*val &= 0xbfff;		/* release DB6             */
9496a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, *val);
9501da177e4SLinus Torvalds 	for (i = 0; i < 10; i++) {	/* stable >= bus settle delay(400 ns)  */
9516a3cebb6SOndrej Zary 		if ((atp_readw_io(dev, 0, 0x1c) & 0x4000) != 0)	/* DB6 all release?  */
952832e9ac6SOndrej Zary 			i = 0;
9531da177e4SLinus Torvalds 	}
9541da177e4SLinus Torvalds 
9551da177e4SLinus Torvalds 	return j;
9561da177e4SLinus Torvalds }
9571da177e4SLinus Torvalds 
9581da177e4SLinus Torvalds static void tscam(struct Scsi_Host *host)
9591da177e4SLinus Torvalds {
9601da177e4SLinus Torvalds 
9611da177e4SLinus Torvalds 	unsigned char i, j, k;
9621da177e4SLinus Torvalds 	unsigned long n;
9631da177e4SLinus Torvalds 	unsigned short int m, assignid_map, val;
9641da177e4SLinus Torvalds 	unsigned char mbuf[33], quintet[2];
9651da177e4SLinus Torvalds 	struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
9661da177e4SLinus Torvalds 	static unsigned char g2q_tab[8] = {
9671da177e4SLinus Torvalds 		0x38, 0x31, 0x32, 0x2b, 0x34, 0x2d, 0x2e, 0x27
9681da177e4SLinus Torvalds 	};
9691da177e4SLinus Torvalds 
9701da177e4SLinus Torvalds /*  I can't believe we need this before we've even done anything.  Remove it
9711da177e4SLinus Torvalds  *  and see if anyone bitches.
9721da177e4SLinus Torvalds 	for (i = 0; i < 0x10; i++) {
9731da177e4SLinus Torvalds 		udelay(0xffff);
9741da177e4SLinus Torvalds 	}
9751da177e4SLinus Torvalds  */
9761da177e4SLinus Torvalds 
9776a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 1, 0x08);
9786a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 2, 0x7f);
9796a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x11, 0x20);
9801da177e4SLinus Torvalds 
9811da177e4SLinus Torvalds 	if ((dev->scam_on & 0x40) == 0) {
9821da177e4SLinus Torvalds 		return;
9831da177e4SLinus Torvalds 	}
9841da177e4SLinus Torvalds 	m = 1;
9851da177e4SLinus Torvalds 	m <<= dev->host_id[0];
9861da177e4SLinus Torvalds 	j = 16;
9871da177e4SLinus Torvalds 	if (dev->chip_ver < 4) {
9881da177e4SLinus Torvalds 		m |= 0xff00;
9891da177e4SLinus Torvalds 		j = 8;
9901da177e4SLinus Torvalds 	}
9911da177e4SLinus Torvalds 	assignid_map = m;
9926a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x02, 0x02);	/* 2*2=4ms,3EH 2/32*3E=3.9ms */
9936a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x03, 0);
9946a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x04, 0);
9956a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x05, 0);
9966a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x06, 0);
9976a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x07, 0);
9986a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x08, 0);
9991da177e4SLinus Torvalds 
10001da177e4SLinus Torvalds 	for (i = 0; i < j; i++) {
10011da177e4SLinus Torvalds 		m = 1;
10021da177e4SLinus Torvalds 		m = m << i;
10031da177e4SLinus Torvalds 		if ((m & assignid_map) != 0) {
10041da177e4SLinus Torvalds 			continue;
10051da177e4SLinus Torvalds 		}
10066a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x0f, 0);
10076a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x12, 0);
10086a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x13, 0);
10096a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x14, 0);
10101da177e4SLinus Torvalds 		if (i > 7) {
10111da177e4SLinus Torvalds 			k = (i & 0x07) | 0x40;
10121da177e4SLinus Torvalds 		} else {
10131da177e4SLinus Torvalds 			k = i;
10141da177e4SLinus Torvalds 		}
10156a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x15, k);
10166a3cebb6SOndrej Zary 		if (dev->chip_ver == 4)
10176a3cebb6SOndrej Zary 			atp_writeb_io(dev, 0, 0x1b, 0x01);
10186a3cebb6SOndrej Zary 		else
10196a3cebb6SOndrej Zary 			atp_writeb_io(dev, 0, 0x1b, 0x00);
102058c4d046SOndrej Zary 		do {
10216a3cebb6SOndrej Zary 			atp_writeb_io(dev, 0, 0x18, 0x09);
10221da177e4SLinus Torvalds 
10236a3cebb6SOndrej Zary 			while ((atp_readb_io(dev, 0, 0x1f) & 0x80) == 0x00)
10241da177e4SLinus Torvalds 				cpu_relax();
10256a3cebb6SOndrej Zary 			k = atp_readb_io(dev, 0, 0x17);
102658c4d046SOndrej Zary 			if ((k == 0x85) || (k == 0x42))
102758c4d046SOndrej Zary 				break;
102858c4d046SOndrej Zary 			if (k != 0x16)
10296a3cebb6SOndrej Zary 				atp_writeb_io(dev, 0, 0x10, 0x41);
103058c4d046SOndrej Zary 		} while (k != 0x16);
103158c4d046SOndrej Zary 		if ((k == 0x85) || (k == 0x42))
103258c4d046SOndrej Zary 			continue;
10331da177e4SLinus Torvalds 		assignid_map |= m;
10341da177e4SLinus Torvalds 
10351da177e4SLinus Torvalds 	}
10366a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x02, 0x7f);
10376a3cebb6SOndrej Zary 	atp_writeb_io(dev, 0, 0x1b, 0x02);
10381da177e4SLinus Torvalds 
10391da177e4SLinus Torvalds 	outb(0, 0x80);
10401da177e4SLinus Torvalds 
10411da177e4SLinus Torvalds 	val = 0x0080;		/* bsy  */
10426a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, val);
10431da177e4SLinus Torvalds 	val |= 0x0040;		/* sel  */
10446a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, val);
10451da177e4SLinus Torvalds 	val |= 0x0004;		/* msg  */
10466a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, val);
10471da177e4SLinus Torvalds 	inb(0x80);		/* 2 deskew delay(45ns*2=90ns) */
10481da177e4SLinus Torvalds 	val &= 0x007f;		/* no bsy  */
10496a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, val);
10501da177e4SLinus Torvalds 	mdelay(128);
10511da177e4SLinus Torvalds 	val &= 0x00fb;		/* after 1ms no msg */
10526a3cebb6SOndrej Zary 	atp_writew_io(dev, 0, 0x1c, val);
10536a3cebb6SOndrej Zary 	while ((atp_readb_io(dev, 0, 0x1c) & 0x04) != 0)
105458c4d046SOndrej Zary 		;
10551da177e4SLinus Torvalds 	outb(1, 0x80);
10561da177e4SLinus Torvalds 	udelay(100);
1057c7fcc089SOndrej Zary 	for (n = 0; n < 0x30000; n++)
10586a3cebb6SOndrej Zary 		if ((atp_readb_io(dev, 0, 0x1c) & 0x80) != 0)	/* bsy ? */
1059c7fcc089SOndrej Zary 			break;
1060c7fcc089SOndrej Zary 	if (n < 0x30000)
1061c7fcc089SOndrej Zary 		for (n = 0; n < 0x30000; n++)
10626a3cebb6SOndrej Zary 			if ((atp_readb_io(dev, 0, 0x1c) & 0x81) == 0x0081) {
10631da177e4SLinus Torvalds 				inb(0x80);
10641da177e4SLinus Torvalds 				val |= 0x8003;		/* io,cd,db7  */
10656a3cebb6SOndrej Zary 				atp_writew_io(dev, 0, 0x1c, val);
10661da177e4SLinus Torvalds 				inb(0x80);
10671da177e4SLinus Torvalds 				val &= 0x00bf;		/* no sel     */
10686a3cebb6SOndrej Zary 				atp_writew_io(dev, 0, 0x1c, val);
10691da177e4SLinus Torvalds 				outb(2, 0x80);
1070c7fcc089SOndrej Zary 				break;
1071c7fcc089SOndrej Zary 			}
1072c7fcc089SOndrej Zary 	while (1) {
10730f6d93aaSMartin Michlmayr 	/*
10740f6d93aaSMartin Michlmayr 	 * The funny division into multiple delays is to accomodate
10750f6d93aaSMartin Michlmayr 	 * arches like ARM where udelay() multiplies its argument by
10760f6d93aaSMartin Michlmayr 	 * a large number to initialize a loop counter.  To avoid
10770f6d93aaSMartin Michlmayr 	 * overflow, the maximum supported udelay is 2000 microseconds.
10780f6d93aaSMartin Michlmayr 	 *
10790f6d93aaSMartin Michlmayr 	 * XXX it would be more polite to find a way to use msleep()
10800f6d93aaSMartin Michlmayr 	 */
10810f6d93aaSMartin Michlmayr 	mdelay(2);
10820f6d93aaSMartin Michlmayr 	udelay(48);
10836a3cebb6SOndrej Zary 	if ((atp_readb_io(dev, 0, 0x1c) & 0x80) == 0x00) {	/* bsy ? */
10846a3cebb6SOndrej Zary 		atp_writew_io(dev, 0, 0x1c, 0);
10856a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x1b, 0);
10866a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x15, 0);
10876a3cebb6SOndrej Zary 		atp_writeb_io(dev, 0, 0x18, 0x09);
10886a3cebb6SOndrej Zary 		while ((atp_readb_io(dev, 0, 0x1f) & 0x80) == 0)
10891da177e4SLinus Torvalds 			cpu_relax();
10906a3cebb6SOndrej Zary 		atp_readb_io(dev, 0, 0x17);
10911da177e4SLinus Torvalds 		return;
10921da177e4SLinus Torvalds 	}
10931da177e4SLinus Torvalds 	val &= 0x00ff;		/* synchronization  */
10941da177e4SLinus Torvalds 	val |= 0x3f00;
10951da177e4SLinus Torvalds 	fun_scam(dev, &val);
10961da177e4SLinus Torvalds 	outb(3, 0x80);
10971da177e4SLinus Torvalds 	val &= 0x00ff;		/* isolation        */
10981da177e4SLinus Torvalds 	val |= 0x2000;
10991da177e4SLinus Torvalds 	fun_scam(dev, &val);
11001da177e4SLinus Torvalds 	outb(4, 0x80);
11011da177e4SLinus Torvalds 	i = 8;
11021da177e4SLinus Torvalds 	j = 0;
1103c7fcc089SOndrej Zary 
1104c7fcc089SOndrej Zary 	while (1) {
11056a3cebb6SOndrej Zary 		if ((atp_readw_io(dev, 0, 0x1c) & 0x2000) == 0)
1106c7fcc089SOndrej Zary 			continue;
11071da177e4SLinus Torvalds 		outb(5, 0x80);
11081da177e4SLinus Torvalds 		val &= 0x00ff;		/* get ID_STRING */
11091da177e4SLinus Torvalds 		val |= 0x2000;
11101da177e4SLinus Torvalds 		k = fun_scam(dev, &val);
1111c7fcc089SOndrej Zary 		if ((k & 0x03) == 0)
1112c7fcc089SOndrej Zary 			break;
11131da177e4SLinus Torvalds 		mbuf[j] <<= 0x01;
11141da177e4SLinus Torvalds 		mbuf[j] &= 0xfe;
1115c7fcc089SOndrej Zary 		if ((k & 0x02) != 0)
11161da177e4SLinus Torvalds 			mbuf[j] |= 0x01;
11171da177e4SLinus Torvalds 		i--;
1118c7fcc089SOndrej Zary 		if (i > 0)
1119c7fcc089SOndrej Zary 			continue;
11201da177e4SLinus Torvalds 		j++;
11211da177e4SLinus Torvalds 		i = 8;
1122c7fcc089SOndrej Zary 	}
11231da177e4SLinus Torvalds 
1124c7fcc089SOndrej Zary 	/* isolation complete..  */
11251da177e4SLinus Torvalds /*    mbuf[32]=0;
11261da177e4SLinus Torvalds 	printk(" \n%x %x %x %s\n ",assignid_map,mbuf[0],mbuf[1],&mbuf[2]); */
11271da177e4SLinus Torvalds 	i = 15;
11281da177e4SLinus Torvalds 	j = mbuf[0];
11291da177e4SLinus Torvalds 	if ((j & 0x20) != 0) {	/* bit5=1:ID up to 7      */
11301da177e4SLinus Torvalds 		i = 7;
11311da177e4SLinus Torvalds 	}
1132c7fcc089SOndrej Zary 	if ((j & 0x06) != 0) {	/* IDvalid?             */
11331da177e4SLinus Torvalds 		k = mbuf[1];
1134c7fcc089SOndrej Zary 		while (1) {
11351da177e4SLinus Torvalds 			m = 1;
11361da177e4SLinus Torvalds 			m <<= k;
1137c7fcc089SOndrej Zary 			if ((m & assignid_map) == 0)
1138c7fcc089SOndrej Zary 				break;
1139c7fcc089SOndrej Zary 			if (k > 0)
11401da177e4SLinus Torvalds 				k--;
1141c7fcc089SOndrej Zary 			else
1142c7fcc089SOndrej Zary 				break;
11431da177e4SLinus Torvalds 		}
1144c7fcc089SOndrej Zary 	}
1145c7fcc089SOndrej Zary 	if ((m & assignid_map) != 0) {	/* srch from max acceptable ID#  */
11461da177e4SLinus Torvalds 		k = i;			/* max acceptable ID#            */
1147c7fcc089SOndrej Zary 		while (1) {
11481da177e4SLinus Torvalds 			m = 1;
11491da177e4SLinus Torvalds 			m <<= k;
1150c7fcc089SOndrej Zary 			if ((m & assignid_map) == 0)
1151c7fcc089SOndrej Zary 				break;
1152c7fcc089SOndrej Zary 			if (k > 0)
11531da177e4SLinus Torvalds 				k--;
1154c7fcc089SOndrej Zary 			else
1155c7fcc089SOndrej Zary 				break;
11561da177e4SLinus Torvalds 		}
1157c7fcc089SOndrej Zary 	}
1158c7fcc089SOndrej Zary 	/* k=binID#,       */
11591da177e4SLinus Torvalds 	assignid_map |= m;
11601da177e4SLinus Torvalds 	if (k < 8) {
11611da177e4SLinus Torvalds 		quintet[0] = 0x38;	/* 1st dft ID<8    */
11621da177e4SLinus Torvalds 	} else {
11631da177e4SLinus Torvalds 		quintet[0] = 0x31;	/* 1st  ID>=8      */
11641da177e4SLinus Torvalds 	}
11651da177e4SLinus Torvalds 	k &= 0x07;
11661da177e4SLinus Torvalds 	quintet[1] = g2q_tab[k];
11671da177e4SLinus Torvalds 
11681da177e4SLinus Torvalds 	val &= 0x00ff;		/* AssignID 1stQuintet,AH=001xxxxx  */
11691da177e4SLinus Torvalds 	m = quintet[0] << 8;
11701da177e4SLinus Torvalds 	val |= m;
11711da177e4SLinus Torvalds 	fun_scam(dev, &val);
11721da177e4SLinus Torvalds 	val &= 0x00ff;		/* AssignID 2ndQuintet,AH=001xxxxx */
11731da177e4SLinus Torvalds 	m = quintet[1] << 8;
11741da177e4SLinus Torvalds 	val |= m;
11751da177e4SLinus Torvalds 	fun_scam(dev, &val);
11761da177e4SLinus Torvalds 
1177c7fcc089SOndrej Zary 	}
11781da177e4SLinus Torvalds }
11791da177e4SLinus Torvalds 
11801da177e4SLinus Torvalds static void atp870u_free_tables(struct Scsi_Host *host)
11811da177e4SLinus Torvalds {
11821da177e4SLinus Torvalds 	struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata;
11831da177e4SLinus Torvalds 	int j, k;
11841da177e4SLinus Torvalds 	for (j=0; j < 2; j++) {
11851da177e4SLinus Torvalds 		for (k = 0; k < 16; k++) {
11861da177e4SLinus Torvalds 			if (!atp_dev->id[j][k].prd_table)
11871da177e4SLinus Torvalds 				continue;
1188b5683557SJames Bottomley 			pci_free_consistent(atp_dev->pdev, 1024, atp_dev->id[j][k].prd_table, atp_dev->id[j][k].prd_bus);
11891da177e4SLinus Torvalds 			atp_dev->id[j][k].prd_table = NULL;
11901da177e4SLinus Torvalds 		}
11911da177e4SLinus Torvalds 	}
11921da177e4SLinus Torvalds }
11931da177e4SLinus Torvalds 
11941da177e4SLinus Torvalds static int atp870u_init_tables(struct Scsi_Host *host)
11951da177e4SLinus Torvalds {
11961da177e4SLinus Torvalds 	struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata;
11971da177e4SLinus Torvalds 	int c,k;
11981da177e4SLinus Torvalds 	for(c=0;c < 2;c++) {
11991da177e4SLinus Torvalds 	   	for(k=0;k<16;k++) {
1200b5683557SJames Bottomley 	   			atp_dev->id[c][k].prd_table = pci_alloc_consistent(atp_dev->pdev, 1024, &(atp_dev->id[c][k].prd_bus));
12011da177e4SLinus Torvalds 	   			if (!atp_dev->id[c][k].prd_table) {
12021da177e4SLinus Torvalds 	   				printk("atp870u_init_tables fail\n");
12031da177e4SLinus Torvalds 				atp870u_free_tables(host);
12041da177e4SLinus Torvalds 				return -ENOMEM;
12051da177e4SLinus Torvalds 			}
1206b5683557SJames Bottomley 			atp_dev->id[c][k].prdaddr = atp_dev->id[c][k].prd_bus;
12071da177e4SLinus Torvalds 			atp_dev->id[c][k].devsp=0x20;
12081da177e4SLinus Torvalds 			atp_dev->id[c][k].devtype = 0x7f;
12091da177e4SLinus Torvalds 			atp_dev->id[c][k].curr_req = NULL;
12101da177e4SLinus Torvalds 	   	}
12111da177e4SLinus Torvalds 
12121da177e4SLinus Torvalds 	   	atp_dev->active_id[c] = 0;
12131da177e4SLinus Torvalds 	   	atp_dev->wide_id[c] = 0;
12141da177e4SLinus Torvalds 	   	atp_dev->host_id[c] = 0x07;
12151da177e4SLinus Torvalds 	   	atp_dev->quhd[c] = 0;
12161da177e4SLinus Torvalds 	   	atp_dev->quend[c] = 0;
12171da177e4SLinus Torvalds 	   	atp_dev->last_cmd[c] = 0xff;
12181da177e4SLinus Torvalds 	   	atp_dev->in_snd[c] = 0;
12191da177e4SLinus Torvalds 	   	atp_dev->in_int[c] = 0;
12201da177e4SLinus Torvalds 
12211da177e4SLinus Torvalds 	   	for (k = 0; k < qcnt; k++) {
12221da177e4SLinus Torvalds 	   		  atp_dev->quereq[c][k] = NULL;
12231da177e4SLinus Torvalds 	   	}
12241da177e4SLinus Torvalds 	   	for (k = 0; k < 16; k++) {
12251da177e4SLinus Torvalds 			   atp_dev->id[c][k].curr_req = NULL;
12261da177e4SLinus Torvalds 			   atp_dev->sp[c][k] = 0x04;
12271da177e4SLinus Torvalds 	   	}
12281da177e4SLinus Torvalds 	}
12291da177e4SLinus Torvalds 	return 0;
12301da177e4SLinus Torvalds }
12311da177e4SLinus Torvalds 
12321da177e4SLinus Torvalds /* return non-zero on detection */
12331da177e4SLinus Torvalds static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
12341da177e4SLinus Torvalds {
12351da177e4SLinus Torvalds 	unsigned char k, m, c;
12361da177e4SLinus Torvalds 	unsigned long flags;
1237493c5201SOndrej Zary 	unsigned int base_io, error,n;
12381da177e4SLinus Torvalds 	unsigned char host_id;
12391da177e4SLinus Torvalds 	struct Scsi_Host *shpnt = NULL;
1240dc6a78f1SRandy Dunlap 	struct atp_unit *atpdev, *p;
12411da177e4SLinus Torvalds 	unsigned char setupdata[2][16];
12421da177e4SLinus Torvalds 	int count = 0;
12431da177e4SLinus Torvalds 
1244dc6a78f1SRandy Dunlap 	atpdev = kzalloc(sizeof(*atpdev), GFP_KERNEL);
1245dc6a78f1SRandy Dunlap 	if (!atpdev)
1246dc6a78f1SRandy Dunlap 		return -ENOMEM;
1247dc6a78f1SRandy Dunlap 
12481da177e4SLinus Torvalds 	if (pci_enable_device(pdev))
1249dc6a78f1SRandy Dunlap 		goto err_eio;
12501da177e4SLinus Torvalds 
1251284901a9SYang Hongyang         if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
12521da177e4SLinus Torvalds                 printk(KERN_INFO "atp870u: use 32bit DMA mask.\n");
12531da177e4SLinus Torvalds         } else {
12541da177e4SLinus Torvalds                 printk(KERN_ERR "atp870u: DMA mask required but not available.\n");
1255dc6a78f1SRandy Dunlap 		goto err_eio;
12561da177e4SLinus Torvalds         }
12571da177e4SLinus Torvalds 
12581da177e4SLinus Torvalds 	/*
12591da177e4SLinus Torvalds 	 * It's probably easier to weed out some revisions like
12601da177e4SLinus Torvalds 	 * this than via the PCI device table
12611da177e4SLinus Torvalds 	 */
12621da177e4SLinus Torvalds 	if (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610) {
12637d7311c4SSergei Shtylyov 		atpdev->chip_ver = pdev->revision;
1264dc6a78f1SRandy Dunlap 		if (atpdev->chip_ver < 2)
1265dc6a78f1SRandy Dunlap 			goto err_eio;
12661da177e4SLinus Torvalds 	}
12671da177e4SLinus Torvalds 
12681da177e4SLinus Torvalds 	switch (ent->device) {
12691da177e4SLinus Torvalds 	case PCI_DEVICE_ID_ARTOP_AEC7612UW:
12701da177e4SLinus Torvalds 	case PCI_DEVICE_ID_ARTOP_AEC7612SUW:
12711da177e4SLinus Torvalds 	case ATP880_DEVID1:
12721da177e4SLinus Torvalds 	case ATP880_DEVID2:
12731da177e4SLinus Torvalds 	case ATP885_DEVID:
1274dc6a78f1SRandy Dunlap 		atpdev->chip_ver = 0x04;
12751da177e4SLinus Torvalds 	default:
12761da177e4SLinus Torvalds 		break;
12771da177e4SLinus Torvalds 	}
12781da177e4SLinus Torvalds 	base_io = pci_resource_start(pdev, 0);
12791da177e4SLinus Torvalds 	base_io &= 0xfffffff8;
12806a3cebb6SOndrej Zary 	atpdev->baseport = base_io;
12811da177e4SLinus Torvalds 
12821da177e4SLinus Torvalds 	if ((ent->device == ATP880_DEVID1)||(ent->device == ATP880_DEVID2)) {
12837d7311c4SSergei Shtylyov 		atpdev->chip_ver = pdev->revision;
12841da177e4SLinus Torvalds 		pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80);//JCC082803
12851da177e4SLinus Torvalds 
1286d804bb25SOndrej Zary 		atpdev->ioport[0] = base_io + 0x40;
1287d804bb25SOndrej Zary 		atpdev->pciport[0] = base_io + 0x28;
1288d804bb25SOndrej Zary 
1289d804bb25SOndrej Zary 		host_id = atp_readb_base(atpdev, 0x39);
12901da177e4SLinus Torvalds 		host_id >>= 0x04;
12911da177e4SLinus Torvalds 
12921da177e4SLinus Torvalds 		printk(KERN_INFO "   ACARD AEC-67160 PCI Ultra3 LVD Host Adapter: %d"
12931da177e4SLinus Torvalds 			"    IO:%x, IRQ:%d.\n", count, base_io, pdev->irq);
1294dc6a78f1SRandy Dunlap 		atpdev->dev_id = ent->device;
1295dc6a78f1SRandy Dunlap 		atpdev->host_id[0] = host_id;
12961da177e4SLinus Torvalds 
1297d804bb25SOndrej Zary 		atpdev->scam_on = atp_readb_base(atpdev, 0x22);
1298d804bb25SOndrej Zary 		atpdev->global_map[0] = atp_readb_base(atpdev, 0x35);
1299d804bb25SOndrej Zary 		atpdev->ultra_map[0] = atp_readw_base(atpdev, 0x3c);
13001da177e4SLinus Torvalds 
13011da177e4SLinus Torvalds 		n = 0x3f09;
13021da177e4SLinus Torvalds next_fblk_880:
13031da177e4SLinus Torvalds 		if (n >= 0x4000)
13041da177e4SLinus Torvalds 			goto flash_ok_880;
13051da177e4SLinus Torvalds 
13061da177e4SLinus Torvalds 		m = 0;
1307d804bb25SOndrej Zary 		atp_writew_base(atpdev, 0x34, n);
13081da177e4SLinus Torvalds 		n += 0x0002;
1309d804bb25SOndrej Zary 		if (atp_readb_base(atpdev, 0x30) == 0xff)
13101da177e4SLinus Torvalds 			goto flash_ok_880;
13111da177e4SLinus Torvalds 
1312d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30);
1313d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31);
1314d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32);
1315d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33);
1316d804bb25SOndrej Zary 		atp_writew_base(atpdev, 0x34, n);
13171da177e4SLinus Torvalds 		n += 0x0002;
1318d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30);
1319d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31);
1320d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32);
1321d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33);
1322d804bb25SOndrej Zary 		atp_writew_base(atpdev, 0x34, n);
13231da177e4SLinus Torvalds 		n += 0x0002;
1324d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30);
1325d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31);
1326d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32);
1327d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33);
1328d804bb25SOndrej Zary 		atp_writew_base(atpdev, 0x34, n);
13291da177e4SLinus Torvalds 		n += 0x0002;
1330d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30);
1331d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31);
1332d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32);
1333d804bb25SOndrej Zary 		atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33);
13341da177e4SLinus Torvalds 		n += 0x0018;
13351da177e4SLinus Torvalds 		goto next_fblk_880;
13361da177e4SLinus Torvalds flash_ok_880:
1337d804bb25SOndrej Zary 		atp_writew_base(atpdev, 0x34, 0);
1338dc6a78f1SRandy Dunlap 		atpdev->ultra_map[0] = 0;
1339dc6a78f1SRandy Dunlap 		atpdev->async[0] = 0;
13401da177e4SLinus Torvalds 		for (k = 0; k < 16; k++) {
13411da177e4SLinus Torvalds 			n = 1;
13421da177e4SLinus Torvalds 			n = n << k;
1343dc6a78f1SRandy Dunlap 			if (atpdev->sp[0][k] > 1) {
1344dc6a78f1SRandy Dunlap 				atpdev->ultra_map[0] |= n;
13451da177e4SLinus Torvalds 			} else {
1346dc6a78f1SRandy Dunlap 				if (atpdev->sp[0][k] == 0)
1347dc6a78f1SRandy Dunlap 					atpdev->async[0] |= n;
13481da177e4SLinus Torvalds  			}
13491da177e4SLinus Torvalds 	 	}
1350dc6a78f1SRandy Dunlap 		atpdev->async[0] = ~(atpdev->async[0]);
1351d804bb25SOndrej Zary 		atp_writeb_base(atpdev, 0x35, atpdev->global_map[0]);
13521da177e4SLinus Torvalds 
13531da177e4SLinus Torvalds 		shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
13541da177e4SLinus Torvalds 		if (!shpnt)
1355dc6a78f1SRandy Dunlap 			goto err_nomem;
13561da177e4SLinus Torvalds 
13571da177e4SLinus Torvalds 		p = (struct atp_unit *)&shpnt->hostdata;
13581da177e4SLinus Torvalds 
1359dc6a78f1SRandy Dunlap 		atpdev->host = shpnt;
1360dc6a78f1SRandy Dunlap 		atpdev->pdev = pdev;
13611da177e4SLinus Torvalds 		pci_set_drvdata(pdev, p);
1362dc6a78f1SRandy Dunlap 		memcpy(p, atpdev, sizeof(*atpdev));
13631da177e4SLinus Torvalds 		if (atp870u_init_tables(shpnt) < 0) {
13641da177e4SLinus Torvalds 			printk(KERN_ERR "Unable to allocate tables for Acard controller\n");
13651da177e4SLinus Torvalds 			goto unregister;
13661da177e4SLinus Torvalds 		}
13671da177e4SLinus Torvalds 
13681d6f359aSThomas Gleixner 		if (request_irq(pdev->irq, atp870u_intr_handle, IRQF_SHARED, "atp880i", shpnt)) {
13691da177e4SLinus Torvalds  			printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", pdev->irq);
13701da177e4SLinus Torvalds 			goto free_tables;
13711da177e4SLinus Torvalds 		}
13721da177e4SLinus Torvalds 
13731da177e4SLinus Torvalds 		spin_lock_irqsave(shpnt->host_lock, flags);
1374d804bb25SOndrej Zary 		k = atp_readb_base(p, 0x38) & 0x80;
1375d804bb25SOndrej Zary 		atp_writeb_base(p, 0x38, k);
1376d804bb25SOndrej Zary 		atp_writeb_base(p, 0x3b, 0x20);
13771da177e4SLinus Torvalds 		mdelay(32);
1378d804bb25SOndrej Zary 		atp_writeb_base(p, 0x3b, 0);
13791da177e4SLinus Torvalds 		mdelay(32);
1380d804bb25SOndrej Zary 		atp_readb_io(p, 0, 0x1b);
1381d804bb25SOndrej Zary 		atp_readb_io(p, 0, 0x17);
1382d804bb25SOndrej Zary 		atp_writeb_io(p, 0, 0, host_id | 0x08);
1383d804bb25SOndrej Zary 		atp_writeb_io(p, 0, 0x18, 0);
1384d804bb25SOndrej Zary 		while ((atp_readb_io(p, 0, 0x1f) & 0x80) == 0)
13851da177e4SLinus Torvalds 			mdelay(1);
1386d804bb25SOndrej Zary 		atp_readb_io(p, 0, 0x17);
1387d804bb25SOndrej Zary 		atp_writeb_io(p, 0, 1, 8);
1388d804bb25SOndrej Zary 		atp_writeb_io(p, 0, 2, 0x7f);
1389d804bb25SOndrej Zary 		atp_writeb_io(p, 0, 0x11, 0x20);
13901da177e4SLinus Torvalds 
13911da177e4SLinus Torvalds 		tscam(shpnt);
13924192a40fSOndrej Zary 		atp_is(p, 0, true, atp_readb_base(p, 0x3f) & 0x40);
1393d804bb25SOndrej Zary 		atp_writeb_base(p, 0x38, 0xb0);
13941da177e4SLinus Torvalds 		shpnt->max_id = 16;
13951da177e4SLinus Torvalds 		shpnt->this_id = host_id;
13961da177e4SLinus Torvalds 		shpnt->unique_id = base_io;
13971da177e4SLinus Torvalds 		shpnt->io_port = base_io;
13981da177e4SLinus Torvalds 		shpnt->n_io_port = 0x60;	/* Number of bytes of I/O space used */
13991da177e4SLinus Torvalds 		shpnt->irq = pdev->irq;
14001da177e4SLinus Torvalds 	} else if (ent->device == ATP885_DEVID) {
14011da177e4SLinus Torvalds 			printk(KERN_INFO "   ACARD AEC-67162 PCI Ultra3 LVD Host Adapter:  IO:%x, IRQ:%d.\n"
14021da177e4SLinus Torvalds 			       , base_io, pdev->irq);
14031da177e4SLinus Torvalds 
1404dc6a78f1SRandy Dunlap 		atpdev->pdev = pdev;
1405dc6a78f1SRandy Dunlap 		atpdev->dev_id  = ent->device;
1406dc6a78f1SRandy Dunlap 		atpdev->ioport[0] = base_io + 0x80;
1407dc6a78f1SRandy Dunlap 		atpdev->ioport[1] = base_io + 0xc0;
1408dc6a78f1SRandy Dunlap 		atpdev->pciport[0] = base_io + 0x40;
1409dc6a78f1SRandy Dunlap 		atpdev->pciport[1] = base_io + 0x50;
14101da177e4SLinus Torvalds 
14111da177e4SLinus Torvalds 		shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
14121da177e4SLinus Torvalds 		if (!shpnt)
1413dc6a78f1SRandy Dunlap 			goto err_nomem;
14141da177e4SLinus Torvalds 
14151da177e4SLinus Torvalds 		p = (struct atp_unit *)&shpnt->hostdata;
14161da177e4SLinus Torvalds 
1417dc6a78f1SRandy Dunlap 		atpdev->host = shpnt;
1418dc6a78f1SRandy Dunlap 		atpdev->pdev = pdev;
14191da177e4SLinus Torvalds 		pci_set_drvdata(pdev, p);
1420dc6a78f1SRandy Dunlap 		memcpy(p, atpdev, sizeof(struct atp_unit));
14211da177e4SLinus Torvalds 		if (atp870u_init_tables(shpnt) < 0)
14221da177e4SLinus Torvalds 			goto unregister;
14231da177e4SLinus Torvalds 
14241da177e4SLinus Torvalds #ifdef ED_DBGP
14251da177e4SLinus Torvalds 	printk("request_irq() shpnt %p hostdata %p\n", shpnt, p);
14261da177e4SLinus Torvalds #endif
14271d6f359aSThomas Gleixner 		if (request_irq(pdev->irq, atp870u_intr_handle, IRQF_SHARED, "atp870u", shpnt)) {
14281da177e4SLinus Torvalds 				printk(KERN_ERR "Unable to allocate IRQ for Acard controller.\n");
14291da177e4SLinus Torvalds 			goto free_tables;
14301da177e4SLinus Torvalds 		}
14311da177e4SLinus Torvalds 
14321da177e4SLinus Torvalds 		spin_lock_irqsave(shpnt->host_lock, flags);
14331da177e4SLinus Torvalds 
1434d804bb25SOndrej Zary 		c = atp_readb_base(p, 0x29);
1435d804bb25SOndrej Zary 		atp_writeb_base(p, 0x29, c | 0x04);
14361da177e4SLinus Torvalds 
14371da177e4SLinus Torvalds 		n=0x1f80;
14381da177e4SLinus Torvalds next_fblk_885:
14391da177e4SLinus Torvalds 		if (n >= 0x2000) {
14401da177e4SLinus Torvalds 		   goto flash_ok_885;
14411da177e4SLinus Torvalds 		}
1442d804bb25SOndrej Zary 		atp_writew_base(p, 0x3c, n);
1443d804bb25SOndrej Zary 		if (atp_readl_base(p, 0x38) == 0xffffffff) {
14441da177e4SLinus Torvalds 		   goto flash_ok_885;
14451da177e4SLinus Torvalds 		}
14461da177e4SLinus Torvalds 		for (m=0; m < 2; m++) {
14471da177e4SLinus Torvalds 		    p->global_map[m]= 0;
14481da177e4SLinus Torvalds 		    for (k=0; k < 4; k++) {
1449d804bb25SOndrej Zary 			atp_writew_base(p, 0x3c, n++);
1450d804bb25SOndrej Zary 			((unsigned long *)&setupdata[m][0])[k] = atp_readl_base(p, 0x38);
14511da177e4SLinus Torvalds 		    }
14521da177e4SLinus Torvalds 		    for (k=0; k < 4; k++) {
1453d804bb25SOndrej Zary 			atp_writew_base(p, 0x3c, n++);
1454d804bb25SOndrej Zary 			((unsigned long *)&p->sp[m][0])[k] = atp_readl_base(p, 0x38);
14551da177e4SLinus Torvalds 		    }
14561da177e4SLinus Torvalds 		    n += 8;
14571da177e4SLinus Torvalds 		}
14581da177e4SLinus Torvalds 		goto next_fblk_885;
14591da177e4SLinus Torvalds flash_ok_885:
14601da177e4SLinus Torvalds #ifdef ED_DBGP
14611da177e4SLinus Torvalds 		printk( "Flash Read OK\n");
14621da177e4SLinus Torvalds #endif
1463d804bb25SOndrej Zary 		c = atp_readb_base(p, 0x29);
1464d804bb25SOndrej Zary 		atp_writeb_base(p, 0x29, c & 0xfb);
14651da177e4SLinus Torvalds 		for (c=0;c < 2;c++) {
14661da177e4SLinus Torvalds 		    p->ultra_map[c]=0;
14671da177e4SLinus Torvalds 		    p->async[c] = 0;
14681da177e4SLinus Torvalds 		    for (k=0; k < 16; k++) {
14691da177e4SLinus Torvalds 			n=1;
14701da177e4SLinus Torvalds 			n = n << k;
14711da177e4SLinus Torvalds 			if (p->sp[c][k] > 1) {
14721da177e4SLinus Torvalds 			   p->ultra_map[c] |= n;
14731da177e4SLinus Torvalds 			} else {
14741da177e4SLinus Torvalds 			   if (p->sp[c][k] == 0) {
14751da177e4SLinus Torvalds 			      p->async[c] |= n;
14761da177e4SLinus Torvalds 			   }
14771da177e4SLinus Torvalds 			}
14781da177e4SLinus Torvalds 		    }
14791da177e4SLinus Torvalds 		    p->async[c] = ~(p->async[c]);
14801da177e4SLinus Torvalds 
14811da177e4SLinus Torvalds 		    if (p->global_map[c] == 0) {
14821da177e4SLinus Torvalds 		       k=setupdata[c][1];
14831da177e4SLinus Torvalds 		       if ((k & 0x40) != 0)
14841da177e4SLinus Torvalds 			  p->global_map[c] |= 0x20;
14851da177e4SLinus Torvalds 		       k &= 0x07;
14861da177e4SLinus Torvalds 		       p->global_map[c] |= k;
14871da177e4SLinus Torvalds 		       if ((setupdata[c][2] & 0x04) != 0)
14881da177e4SLinus Torvalds 			  p->global_map[c] |= 0x08;
14891da177e4SLinus Torvalds 		       p->host_id[c] = setupdata[c][0] & 0x07;
14901da177e4SLinus Torvalds 		    }
14911da177e4SLinus Torvalds 		}
14921da177e4SLinus Torvalds 
1493d804bb25SOndrej Zary 		k = atp_readb_base(p, 0x28) & 0x8f;
14941da177e4SLinus Torvalds 		k |= 0x10;
1495d804bb25SOndrej Zary 		atp_writeb_base(p, 0x28, k);
1496d804bb25SOndrej Zary 		atp_writeb_pci(p, 0, 1, 0x80);
1497d804bb25SOndrej Zary 		atp_writeb_pci(p, 1, 1, 0x80);
14981da177e4SLinus Torvalds 		mdelay(100);
1499d804bb25SOndrej Zary 		atp_writeb_pci(p, 0, 1, 0);
1500d804bb25SOndrej Zary 		atp_writeb_pci(p, 1, 1, 0);
15011da177e4SLinus Torvalds 		mdelay(1000);
1502d804bb25SOndrej Zary 		atp_readb_io(p, 0, 0x1b);
1503d804bb25SOndrej Zary 		atp_readb_io(p, 0, 0x17);
1504d804bb25SOndrej Zary 		atp_readb_io(p, 1, 0x1b);
1505d804bb25SOndrej Zary 		atp_readb_io(p, 1, 0x17);
15061da177e4SLinus Torvalds 		k=p->host_id[0];
15071da177e4SLinus Torvalds 		if (k > 7)
15081da177e4SLinus Torvalds 		   k = (k & 0x07) | 0x40;
15091da177e4SLinus Torvalds 		k |= 0x08;
1510d804bb25SOndrej Zary 		atp_writeb_io(p, 0, 0, k);
1511d804bb25SOndrej Zary 		atp_writeb_io(p, 0, 0x18, 0);
15121da177e4SLinus Torvalds 
1513d804bb25SOndrej Zary 		while ((atp_readb_io(p, 0, 0x1f) & 0x80) == 0)
15141da177e4SLinus Torvalds 			cpu_relax();
15151da177e4SLinus Torvalds 
1516d804bb25SOndrej Zary 		atp_readb_io(p, 0, 0x17);
1517d804bb25SOndrej Zary 		atp_writeb_io(p, 0, 1, 8);
1518d804bb25SOndrej Zary 		atp_writeb_io(p, 0, 2, 0x7f);
1519d804bb25SOndrej Zary 		atp_writeb_io(p, 0, 0x11, 0x20);
15201da177e4SLinus Torvalds 
15211da177e4SLinus Torvalds 		k=p->host_id[1];
15221da177e4SLinus Torvalds 		if (k > 7)
15231da177e4SLinus Torvalds 		   k = (k & 0x07) | 0x40;
15241da177e4SLinus Torvalds 		k |= 0x08;
1525d804bb25SOndrej Zary 		atp_writeb_io(p, 1, 0, k);
1526d804bb25SOndrej Zary 		atp_writeb_io(p, 1, 0x18, 0);
15271da177e4SLinus Torvalds 
1528d804bb25SOndrej Zary 		while ((atp_readb_io(p, 1, 0x1f) & 0x80) == 0)
15291da177e4SLinus Torvalds 			cpu_relax();
15301da177e4SLinus Torvalds 
1531d804bb25SOndrej Zary 		atp_readb_io(p, 1, 0x17);
1532d804bb25SOndrej Zary 		atp_writeb_io(p, 1, 1, 8);
1533d804bb25SOndrej Zary 		atp_writeb_io(p, 1, 2, 0x7f);
1534d804bb25SOndrej Zary 		atp_writeb_io(p, 1, 0x11, 0x20);
15351da177e4SLinus Torvalds 
15361da177e4SLinus Torvalds 		tscam_885();
15371da177e4SLinus Torvalds 		printk(KERN_INFO "   Scanning Channel A SCSI Device ...\n");
15384192a40fSOndrej Zary 		atp_is(p, 0, true, atp_readb_io(p, 0, 0x1b) >> 7);
1539fa50b308SOndrej Zary 		atp_writeb_io(p, 0, 0x16, 0x80);
15401da177e4SLinus Torvalds 		printk(KERN_INFO "   Scanning Channel B SCSI Device ...\n");
15414192a40fSOndrej Zary 		atp_is(p, 1, true, atp_readb_io(p, 1, 0x1b) >> 7);
1542fa50b308SOndrej Zary 		atp_writeb_io(p, 1, 0x16, 0x80);
1543d804bb25SOndrej Zary 		k = atp_readb_base(p, 0x28) & 0xcf;
15441da177e4SLinus Torvalds 		k |= 0xc0;
1545d804bb25SOndrej Zary 		atp_writeb_base(p, 0x28, k);
1546d804bb25SOndrej Zary 		k = atp_readb_base(p, 0x1f) | 0x80;
1547d804bb25SOndrej Zary 		atp_writeb_base(p, 0x1f, k);
1548d804bb25SOndrej Zary 		k = atp_readb_base(p, 0x29) | 0x01;
1549d804bb25SOndrej Zary 		atp_writeb_base(p, 0x29, k);
15501da177e4SLinus Torvalds #ifdef ED_DBGP
15511da177e4SLinus Torvalds 		//printk("atp885: atp_host[0] 0x%p\n", atp_host[0]);
15521da177e4SLinus Torvalds #endif
15531da177e4SLinus Torvalds 		shpnt->max_id = 16;
15541da177e4SLinus Torvalds 		shpnt->max_lun = (p->global_map[0] & 0x07) + 1;
15551da177e4SLinus Torvalds 		shpnt->max_channel = 1;
15561da177e4SLinus Torvalds 		shpnt->this_id = p->host_id[0];
15571da177e4SLinus Torvalds 		shpnt->unique_id = base_io;
15581da177e4SLinus Torvalds 		shpnt->io_port = base_io;
15591da177e4SLinus Torvalds 		shpnt->n_io_port = 0xff;	/* Number of bytes of I/O space used */
15601da177e4SLinus Torvalds 		shpnt->irq = pdev->irq;
15611da177e4SLinus Torvalds 
15621da177e4SLinus Torvalds 	} else {
15631da177e4SLinus Torvalds 		error = pci_read_config_byte(pdev, 0x49, &host_id);
15641da177e4SLinus Torvalds 
15651da177e4SLinus Torvalds 		printk(KERN_INFO "   ACARD AEC-671X PCI Ultra/W SCSI-2/3 Host Adapter: %d "
15661da177e4SLinus Torvalds 			"IO:%x, IRQ:%d.\n", count, base_io, pdev->irq);
15671da177e4SLinus Torvalds 
1568dc6a78f1SRandy Dunlap 		atpdev->ioport[0] = base_io;
1569dc6a78f1SRandy Dunlap 		atpdev->pciport[0] = base_io + 0x20;
1570dc6a78f1SRandy Dunlap 		atpdev->dev_id = ent->device;
15711da177e4SLinus Torvalds 		host_id &= 0x07;
1572dc6a78f1SRandy Dunlap 		atpdev->host_id[0] = host_id;
1573d804bb25SOndrej Zary 		atpdev->scam_on = atp_readb_pci(atpdev, 0, 2);
1574d804bb25SOndrej Zary 		atpdev->global_map[0] = atp_readb_base(atpdev, 0x2d);
1575d804bb25SOndrej Zary 		atpdev->ultra_map[0] = atp_readw_base(atpdev, 0x2e);
15761da177e4SLinus Torvalds 
1577dc6a78f1SRandy Dunlap 		if (atpdev->ultra_map[0] == 0) {
1578dc6a78f1SRandy Dunlap 			atpdev->scam_on = 0x00;
1579dc6a78f1SRandy Dunlap 			atpdev->global_map[0] = 0x20;
1580dc6a78f1SRandy Dunlap 			atpdev->ultra_map[0] = 0xffff;
15811da177e4SLinus Torvalds 		}
15821da177e4SLinus Torvalds 
15831da177e4SLinus Torvalds 		shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
15841da177e4SLinus Torvalds 		if (!shpnt)
1585dc6a78f1SRandy Dunlap 			goto err_nomem;
15861da177e4SLinus Torvalds 
15871da177e4SLinus Torvalds 		p = (struct atp_unit *)&shpnt->hostdata;
15881da177e4SLinus Torvalds 
1589dc6a78f1SRandy Dunlap 		atpdev->host = shpnt;
1590dc6a78f1SRandy Dunlap 		atpdev->pdev = pdev;
15911da177e4SLinus Torvalds 		pci_set_drvdata(pdev, p);
1592dc6a78f1SRandy Dunlap 		memcpy(p, atpdev, sizeof(*atpdev));
15931da177e4SLinus Torvalds 		if (atp870u_init_tables(shpnt) < 0)
15941da177e4SLinus Torvalds 			goto unregister;
15951da177e4SLinus Torvalds 
15961d6f359aSThomas Gleixner 		if (request_irq(pdev->irq, atp870u_intr_handle, IRQF_SHARED, "atp870i", shpnt)) {
15971da177e4SLinus Torvalds 			printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", pdev->irq);
15981da177e4SLinus Torvalds 			goto free_tables;
15991da177e4SLinus Torvalds 		}
16001da177e4SLinus Torvalds 
16011da177e4SLinus Torvalds 		spin_lock_irqsave(shpnt->host_lock, flags);
1602d804bb25SOndrej Zary 		if (atpdev->chip_ver > 0x07)	/* check if atp876 chip then enable terminator */
1603d804bb25SOndrej Zary 			atp_writeb_base(p, 0x3e, 0x00);
16041da177e4SLinus Torvalds 
1605d804bb25SOndrej Zary 		k = (atp_readb_base(p, 0x3a) & 0xf3) | 0x10;
1606d804bb25SOndrej Zary 		atp_writeb_base(p, 0x3a, k);
1607d804bb25SOndrej Zary 		atp_writeb_base(p, 0x3a, k & 0xdf);
16081da177e4SLinus Torvalds 		mdelay(32);
1609d804bb25SOndrej Zary 		atp_writeb_base(p, 0x3a, k);
16101da177e4SLinus Torvalds 		mdelay(32);
1611d804bb25SOndrej Zary 		atp_writeb_io(p, 0, 0, host_id | 0x08);
1612d804bb25SOndrej Zary 		atp_writeb_io(p, 0, 0x18, 0);
1613d804bb25SOndrej Zary 		while ((atp_readb_io(p, 0, 0x1f) & 0x80) == 0)
16141da177e4SLinus Torvalds 			mdelay(1);
16151da177e4SLinus Torvalds 
1616d804bb25SOndrej Zary 		atp_readb_io(p, 0, 0x17);
1617d804bb25SOndrej Zary 		atp_writeb_io(p, 0, 1, 8);
1618d804bb25SOndrej Zary 		atp_writeb_io(p, 0, 2, 0x7f);
1619d804bb25SOndrej Zary 		atp_writeb_io(p, 0, 0x11, 0x20);
16201da177e4SLinus Torvalds 
16211da177e4SLinus Torvalds 		tscam(shpnt);
1622d804bb25SOndrej Zary 		atp_writeb_base(p, 0x3a, atp_readb_base(p, 0x3a) | 0x10);
16234192a40fSOndrej Zary 		atp_is(p, 0, p->chip_ver == 4, 0);
1624d804bb25SOndrej Zary 		atp_writeb_base(p, 0x3a, atp_readb_base(p, 0x3a) & 0xef);
1625d804bb25SOndrej Zary 		atp_writeb_base(p, 0x3b, atp_readb_base(p, 0x3b) | 0x20);
1626dc6a78f1SRandy Dunlap 		if (atpdev->chip_ver == 4)
16271da177e4SLinus Torvalds 			shpnt->max_id = 16;
16281da177e4SLinus Torvalds 		else
16292b89dad0SHannes Reinecke 			shpnt->max_id = 8;
16301da177e4SLinus Torvalds 		shpnt->this_id = host_id;
16311da177e4SLinus Torvalds 		shpnt->unique_id = base_io;
16321da177e4SLinus Torvalds 		shpnt->io_port = base_io;
16331da177e4SLinus Torvalds 		shpnt->n_io_port = 0x40;	/* Number of bytes of I/O space used */
16341da177e4SLinus Torvalds 		shpnt->irq = pdev->irq;
16351da177e4SLinus Torvalds 	}
16361da177e4SLinus Torvalds 		spin_unlock_irqrestore(shpnt->host_lock, flags);
16371da177e4SLinus Torvalds 		if(ent->device==ATP885_DEVID) {
16381da177e4SLinus Torvalds 			if(!request_region(base_io, 0xff, "atp870u")) /* Register the IO ports that we use */
16391da177e4SLinus Torvalds 				goto request_io_fail;
16401da177e4SLinus Torvalds 		} else if((ent->device==ATP880_DEVID1)||(ent->device==ATP880_DEVID2)) {
16411da177e4SLinus Torvalds 			if(!request_region(base_io, 0x60, "atp870u")) /* Register the IO ports that we use */
16421da177e4SLinus Torvalds 				goto request_io_fail;
16431da177e4SLinus Torvalds 		} else {
16441da177e4SLinus Torvalds 			if(!request_region(base_io, 0x40, "atp870u")) /* Register the IO ports that we use */
16451da177e4SLinus Torvalds 				goto request_io_fail;
16461da177e4SLinus Torvalds 		}
16471da177e4SLinus Torvalds 		count++;
16481da177e4SLinus Torvalds 		if (scsi_add_host(shpnt, &pdev->dev))
16491da177e4SLinus Torvalds 			goto scsi_add_fail;
16501da177e4SLinus Torvalds 		scsi_scan_host(shpnt);
16511da177e4SLinus Torvalds #ifdef ED_DBGP
16521da177e4SLinus Torvalds 		printk("atp870u_prob : exit\n");
16531da177e4SLinus Torvalds #endif
16541da177e4SLinus Torvalds 		return 0;
16551da177e4SLinus Torvalds 
16561da177e4SLinus Torvalds scsi_add_fail:
16571da177e4SLinus Torvalds 	printk("atp870u_prob:scsi_add_fail\n");
16581da177e4SLinus Torvalds 	if(ent->device==ATP885_DEVID) {
16591da177e4SLinus Torvalds 		release_region(base_io, 0xff);
16601da177e4SLinus Torvalds 	} else if((ent->device==ATP880_DEVID1)||(ent->device==ATP880_DEVID2)) {
16611da177e4SLinus Torvalds 		release_region(base_io, 0x60);
16621da177e4SLinus Torvalds 	} else {
16631da177e4SLinus Torvalds 		release_region(base_io, 0x40);
16641da177e4SLinus Torvalds 	}
16651da177e4SLinus Torvalds request_io_fail:
16661da177e4SLinus Torvalds 	printk("atp870u_prob:request_io_fail\n");
16671da177e4SLinus Torvalds 	free_irq(pdev->irq, shpnt);
16681da177e4SLinus Torvalds free_tables:
16691da177e4SLinus Torvalds 	printk("atp870u_prob:free_table\n");
16701da177e4SLinus Torvalds 	atp870u_free_tables(shpnt);
16711da177e4SLinus Torvalds unregister:
16721da177e4SLinus Torvalds 	printk("atp870u_prob:unregister\n");
16731da177e4SLinus Torvalds 	scsi_host_put(shpnt);
16741da177e4SLinus Torvalds 	return -1;
1675dc6a78f1SRandy Dunlap err_eio:
1676dc6a78f1SRandy Dunlap 	kfree(atpdev);
1677dc6a78f1SRandy Dunlap 	return -EIO;
1678dc6a78f1SRandy Dunlap err_nomem:
1679dc6a78f1SRandy Dunlap 	kfree(atpdev);
1680dc6a78f1SRandy Dunlap 	return -ENOMEM;
16811da177e4SLinus Torvalds }
16821da177e4SLinus Torvalds 
16831da177e4SLinus Torvalds /* The abort command does not leave the device in a clean state where
16841da177e4SLinus Torvalds    it is available to be used again.  Until this gets worked out, we will
16851da177e4SLinus Torvalds    leave it commented out.  */
16861da177e4SLinus Torvalds 
16871da177e4SLinus Torvalds static int atp870u_abort(struct scsi_cmnd * SCpnt)
16881da177e4SLinus Torvalds {
16891da177e4SLinus Torvalds 	unsigned char  j, k, c;
16901da177e4SLinus Torvalds 	struct scsi_cmnd *workrequ;
16911da177e4SLinus Torvalds 	struct atp_unit *dev;
16921da177e4SLinus Torvalds 	struct Scsi_Host *host;
16931da177e4SLinus Torvalds 	host = SCpnt->device->host;
16941da177e4SLinus Torvalds 
16951da177e4SLinus Torvalds 	dev = (struct atp_unit *)&host->hostdata;
1696422c0d61SJeff Garzik 	c = scmd_channel(SCpnt);
16971da177e4SLinus Torvalds 	printk(" atp870u: abort Channel = %x \n", c);
16981da177e4SLinus Torvalds 	printk("working=%x last_cmd=%x ", dev->working[c], dev->last_cmd[c]);
16991da177e4SLinus Torvalds 	printk(" quhdu=%x quendu=%x ", dev->quhd[c], dev->quend[c]);
17001da177e4SLinus Torvalds 	for (j = 0; j < 0x18; j++) {
17016a3cebb6SOndrej Zary 		printk(" r%2x=%2x", j, atp_readb_io(dev, c, j));
17021da177e4SLinus Torvalds 	}
17036a3cebb6SOndrej Zary 	printk(" r1c=%2x", atp_readb_io(dev, c, 0x1c));
17046a3cebb6SOndrej Zary 	printk(" r1f=%2x in_snd=%2x ", atp_readb_io(dev, c, 0x1f), dev->in_snd[c]);
17056a3cebb6SOndrej Zary 	printk(" d00=%2x", atp_readb_pci(dev, c, 0x00));
17066a3cebb6SOndrej Zary 	printk(" d02=%2x", atp_readb_pci(dev, c, 0x02));
17071da177e4SLinus Torvalds 	for(j=0;j<16;j++) {
17081da177e4SLinus Torvalds 	   if (dev->id[c][j].curr_req != NULL) {
17091da177e4SLinus Torvalds 		workrequ = dev->id[c][j].curr_req;
17101da177e4SLinus Torvalds 		printk("\n que cdb= ");
17111da177e4SLinus Torvalds 		for (k=0; k < workrequ->cmd_len; k++) {
17121da177e4SLinus Torvalds 		    printk(" %2x ",workrequ->cmnd[k]);
17131da177e4SLinus Torvalds 		}
17141da177e4SLinus Torvalds 		printk(" last_lenu= %x ",(unsigned int)dev->id[c][j].last_len);
17151da177e4SLinus Torvalds 	   }
17161da177e4SLinus Torvalds 	}
17171da177e4SLinus Torvalds 	return SUCCESS;
17181da177e4SLinus Torvalds }
17191da177e4SLinus Torvalds 
17201da177e4SLinus Torvalds static const char *atp870u_info(struct Scsi_Host *notused)
17211da177e4SLinus Torvalds {
17221da177e4SLinus Torvalds 	static char buffer[128];
17231da177e4SLinus Torvalds 
17241da177e4SLinus Torvalds 	strcpy(buffer, "ACARD AEC-6710/6712/67160 PCI Ultra/W/LVD SCSI-3 Adapter Driver V2.6+ac ");
17251da177e4SLinus Torvalds 
17261da177e4SLinus Torvalds 	return buffer;
17271da177e4SLinus Torvalds }
17281da177e4SLinus Torvalds 
1729d773e422SAl Viro static int atp870u_show_info(struct seq_file *m, struct Scsi_Host *HBAptr)
17301da177e4SLinus Torvalds {
17313d30079cSRasmus Villemoes 	seq_puts(m, "ACARD AEC-671X Driver Version: 2.6+ac\n\n"
17323d30079cSRasmus Villemoes 		"Adapter Configuration:\n");
1733d773e422SAl Viro 	seq_printf(m, "               Base IO: %#.4lx\n", HBAptr->io_port);
1734d773e422SAl Viro 	seq_printf(m, "                   IRQ: %d\n", HBAptr->irq);
1735d773e422SAl Viro 	return 0;
17361da177e4SLinus Torvalds }
17371da177e4SLinus Torvalds 
17381da177e4SLinus Torvalds 
17391da177e4SLinus Torvalds static int atp870u_biosparam(struct scsi_device *disk, struct block_device *dev,
17401da177e4SLinus Torvalds 			sector_t capacity, int *ip)
17411da177e4SLinus Torvalds {
17421da177e4SLinus Torvalds 	int heads, sectors, cylinders;
17431da177e4SLinus Torvalds 
17441da177e4SLinus Torvalds 	heads = 64;
17451da177e4SLinus Torvalds 	sectors = 32;
17461da177e4SLinus Torvalds 	cylinders = (unsigned long)capacity / (heads * sectors);
17471da177e4SLinus Torvalds 	if (cylinders > 1024) {
17481da177e4SLinus Torvalds 		heads = 255;
17491da177e4SLinus Torvalds 		sectors = 63;
17501da177e4SLinus Torvalds 		cylinders = (unsigned long)capacity / (heads * sectors);
17511da177e4SLinus Torvalds 	}
17521da177e4SLinus Torvalds 	ip[0] = heads;
17531da177e4SLinus Torvalds 	ip[1] = sectors;
17541da177e4SLinus Torvalds 	ip[2] = cylinders;
17551da177e4SLinus Torvalds 
17561da177e4SLinus Torvalds 	return 0;
17571da177e4SLinus Torvalds }
17581da177e4SLinus Torvalds 
17591da177e4SLinus Torvalds static void atp870u_remove (struct pci_dev *pdev)
17601da177e4SLinus Torvalds {
17611da177e4SLinus Torvalds 	struct atp_unit *devext = pci_get_drvdata(pdev);
17621da177e4SLinus Torvalds 	struct Scsi_Host *pshost = devext->host;
17631da177e4SLinus Torvalds 
17641da177e4SLinus Torvalds 
17651da177e4SLinus Torvalds 	scsi_remove_host(pshost);
17661da177e4SLinus Torvalds 	printk(KERN_INFO "free_irq : %d\n",pshost->irq);
17671da177e4SLinus Torvalds 	free_irq(pshost->irq, pshost);
17681da177e4SLinus Torvalds 	release_region(pshost->io_port, pshost->n_io_port);
17691da177e4SLinus Torvalds 	printk(KERN_INFO "atp870u_free_tables : %p\n",pshost);
17701da177e4SLinus Torvalds 	atp870u_free_tables(pshost);
17711da177e4SLinus Torvalds 	printk(KERN_INFO "scsi_host_put : %p\n",pshost);
17721da177e4SLinus Torvalds 	scsi_host_put(pshost);
17731da177e4SLinus Torvalds }
17741da177e4SLinus Torvalds MODULE_LICENSE("GPL");
17751da177e4SLinus Torvalds 
17761da177e4SLinus Torvalds static struct scsi_host_template atp870u_template = {
17771da177e4SLinus Torvalds      .module			= THIS_MODULE,
17781da177e4SLinus Torvalds      .name              	= "atp870u"		/* name */,
17791da177e4SLinus Torvalds      .proc_name			= "atp870u",
1780d773e422SAl Viro      .show_info			= atp870u_show_info,
17811da177e4SLinus Torvalds      .info              	= atp870u_info		/* info */,
17821da177e4SLinus Torvalds      .queuecommand      	= atp870u_queuecommand	/* queuecommand */,
17831da177e4SLinus Torvalds      .eh_abort_handler  	= atp870u_abort		/* abort */,
17841da177e4SLinus Torvalds      .bios_param        	= atp870u_biosparam	/* biosparm */,
17851da177e4SLinus Torvalds      .can_queue         	= qcnt			/* can_queue */,
17861da177e4SLinus Torvalds      .this_id           	= 7			/* SCSI ID */,
17871da177e4SLinus Torvalds      .sg_tablesize      	= ATP870U_SCATTER	/*SG_ALL*/ /*SG_NONE*/,
17881da177e4SLinus Torvalds      .use_clustering    	= ENABLE_CLUSTERING,
17891da177e4SLinus Torvalds      .max_sectors		= ATP870U_MAX_SECTORS,
17901da177e4SLinus Torvalds };
17911da177e4SLinus Torvalds 
17921da177e4SLinus Torvalds static struct pci_device_id atp870u_id_table[] = {
17931da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP885_DEVID)			  },
17941da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID1)			  },
17951da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID2)			  },
17961da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7610)    },
17971da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612UW)  },
17981da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612U)   },
17991da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612S)   },
18001da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612D)	  },
18011da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612SUW) },
18021da177e4SLinus Torvalds 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_8060)	  },
18031da177e4SLinus Torvalds 	{ 0, },
18041da177e4SLinus Torvalds };
18051da177e4SLinus Torvalds 
18061da177e4SLinus Torvalds MODULE_DEVICE_TABLE(pci, atp870u_id_table);
18071da177e4SLinus Torvalds 
18081da177e4SLinus Torvalds static struct pci_driver atp870u_driver = {
18091da177e4SLinus Torvalds 	.id_table	= atp870u_id_table,
18101da177e4SLinus Torvalds 	.name		= "atp870u",
18111da177e4SLinus Torvalds 	.probe		= atp870u_probe,
18126f039790SGreg Kroah-Hartman 	.remove		= atp870u_remove,
18131da177e4SLinus Torvalds };
18141da177e4SLinus Torvalds 
18151da177e4SLinus Torvalds static int __init atp870u_init(void)
18161da177e4SLinus Torvalds {
18171da177e4SLinus Torvalds #ifdef ED_DBGP
18181da177e4SLinus Torvalds 	printk("atp870u_init: Entry\n");
18191da177e4SLinus Torvalds #endif
18201da177e4SLinus Torvalds 	return pci_register_driver(&atp870u_driver);
18211da177e4SLinus Torvalds }
18221da177e4SLinus Torvalds 
18231da177e4SLinus Torvalds static void __exit atp870u_exit(void)
18241da177e4SLinus Torvalds {
18251da177e4SLinus Torvalds #ifdef ED_DBGP
18261da177e4SLinus Torvalds 	printk("atp870u_exit: Entry\n");
18271da177e4SLinus Torvalds #endif
18281da177e4SLinus Torvalds 	pci_unregister_driver(&atp870u_driver);
18291da177e4SLinus Torvalds }
18301da177e4SLinus Torvalds 
18311da177e4SLinus Torvalds static void tscam_885(void)
18321da177e4SLinus Torvalds {
18331da177e4SLinus Torvalds 	unsigned char i;
18341da177e4SLinus Torvalds 
18351da177e4SLinus Torvalds 	for (i = 0; i < 0x2; i++) {
18361da177e4SLinus Torvalds 		mdelay(300);
18371da177e4SLinus Torvalds 	}
18381da177e4SLinus Torvalds 	return;
18391da177e4SLinus Torvalds }
18401da177e4SLinus Torvalds 
18411da177e4SLinus Torvalds 
18421da177e4SLinus Torvalds 
18434192a40fSOndrej Zary static void atp_is(struct atp_unit *dev, unsigned char c, bool wide_chip, unsigned char lvdmode)
18441da177e4SLinus Torvalds {
1845fa50b308SOndrej Zary 	unsigned char i, j, k, rmb, n;
18461da177e4SLinus Torvalds 	unsigned short int m;
18471da177e4SLinus Torvalds 	static unsigned char mbuf[512];
18481da177e4SLinus Torvalds 	static unsigned char satn[9] = { 0, 0, 0, 0, 0, 0, 0, 6, 6 };
18491da177e4SLinus Torvalds 	static unsigned char inqd[9] = { 0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6 };
18501da177e4SLinus Torvalds 	static unsigned char synn[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
18511da177e4SLinus Torvalds 	unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
18521da177e4SLinus Torvalds 	static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
1853460da918SOndrej Zary 	static unsigned char synw_870[6] = { 0x80, 1, 3, 1, 0x0c, 0x07 };
18541da177e4SLinus Torvalds 	unsigned char synuw[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
18551da177e4SLinus Torvalds 	static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
18561da177e4SLinus Torvalds 	static unsigned char u3[9] = { 0x80, 1, 6, 4, 0x09, 00, 0x0e, 0x01, 0x02 };
18571da177e4SLinus Torvalds 
18581da177e4SLinus Torvalds 	for (i = 0; i < 16; i++) {
1859197fb8d8SOndrej Zary 		if (!wide_chip && (i > 7))
1860197fb8d8SOndrej Zary 			break;
18611da177e4SLinus Torvalds 		m = 1;
18621da177e4SLinus Torvalds 		m = m << i;
18631da177e4SLinus Torvalds 		if ((m & dev->active_id[c]) != 0) {
18641da177e4SLinus Torvalds 			continue;
18651da177e4SLinus Torvalds 		}
18661da177e4SLinus Torvalds 		if (i == dev->host_id[c]) {
18671da177e4SLinus Torvalds 			printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_id[c]);
18681da177e4SLinus Torvalds 			continue;
18691da177e4SLinus Torvalds 		}
1870197fb8d8SOndrej Zary 		atp_writeb_io(dev, c, 0x1b, wide_chip ? 0x01 : 0x00);
18715d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 1, 0x08);
18725d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 2, 0x7f);
18735d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 3, satn[0]);
18745d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 4, satn[1]);
18755d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 5, satn[2]);
18765d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 6, satn[3]);
18775d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 7, satn[4]);
18785d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 8, satn[5]);
18795d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x0f, 0);
18805d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
18815d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
18825d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, satn[6]);
18835d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, satn[7]);
18841da177e4SLinus Torvalds 		j = i;
18851da177e4SLinus Torvalds 		if ((j & 0x08) != 0) {
18861da177e4SLinus Torvalds 			j = (j & 0x07) | 0x40;
18871da177e4SLinus Torvalds 		}
18885d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x15, j);
18895d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, satn[8]);
18901da177e4SLinus Torvalds 
18915d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
18921da177e4SLinus Torvalds 			cpu_relax();
189380b52a7fSOndrej Zary 
189480b52a7fSOndrej Zary 		if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e)
18951da177e4SLinus Torvalds 			continue;
189680b52a7fSOndrej Zary 
18975d2a5a4fSOndrej Zary 		while (atp_readb_io(dev, c, 0x17) != 0x8e)
18981da177e4SLinus Torvalds 			cpu_relax();
189980b52a7fSOndrej Zary 
19001da177e4SLinus Torvalds 		dev->active_id[c] |= m;
19011da177e4SLinus Torvalds 
19025d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x10, 0x30);
1903460da918SOndrej Zary 		if (dev->dev_id == ATP885_DEVID || dev->dev_id == ATP880_DEVID1 || dev->dev_id == ATP880_DEVID2)
19045d2a5a4fSOndrej Zary 			atp_writeb_io(dev, c, 0x14, 0x00);
1905460da918SOndrej Zary 		else /* result of is870() merge - is this a bug? */
1906460da918SOndrej Zary 			atp_writeb_io(dev, c, 0x04, 0x00);
19071da177e4SLinus Torvalds 
19081da177e4SLinus Torvalds phase_cmd:
19095d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
191080b52a7fSOndrej Zary 
19115d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
19121da177e4SLinus Torvalds 			cpu_relax();
191380b52a7fSOndrej Zary 
19145d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
19151da177e4SLinus Torvalds 		if (j != 0x16) {
19165d2a5a4fSOndrej Zary 			atp_writeb_io(dev, c, 0x10, 0x41);
19171da177e4SLinus Torvalds 			goto phase_cmd;
19181da177e4SLinus Torvalds 		}
19191da177e4SLinus Torvalds sel_ok:
19205d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 3, inqd[0]);
19215d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 4, inqd[1]);
19225d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 5, inqd[2]);
19235d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 6, inqd[3]);
19245d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 7, inqd[4]);
19255d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 8, inqd[5]);
19265d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x0f, 0);
19275d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
19285d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
19295d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, inqd[6]);
19305d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, inqd[7]);
19315d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, inqd[8]);
193280b52a7fSOndrej Zary 
19335d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
19341da177e4SLinus Torvalds 			cpu_relax();
193580b52a7fSOndrej Zary 
193680b52a7fSOndrej Zary 		if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e)
19371da177e4SLinus Torvalds 			continue;
193880b52a7fSOndrej Zary 
19395d2a5a4fSOndrej Zary 		while (atp_readb_io(dev, c, 0x17) != 0x8e)
19401da177e4SLinus Torvalds 			cpu_relax();
194180b52a7fSOndrej Zary 
1942197fb8d8SOndrej Zary 		if (wide_chip)
19435d2a5a4fSOndrej Zary 			atp_writeb_io(dev, c, 0x1b, 0x00);
1944197fb8d8SOndrej Zary 
19455d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
19461da177e4SLinus Torvalds 		j = 0;
19471da177e4SLinus Torvalds rd_inq_data:
19485d2a5a4fSOndrej Zary 		k = atp_readb_io(dev, c, 0x1f);
19491da177e4SLinus Torvalds 		if ((k & 0x01) != 0) {
19505d2a5a4fSOndrej Zary 			mbuf[j++] = atp_readb_io(dev, c, 0x19);
19511da177e4SLinus Torvalds 			goto rd_inq_data;
19521da177e4SLinus Torvalds 		}
19531da177e4SLinus Torvalds 		if ((k & 0x80) == 0) {
19541da177e4SLinus Torvalds 			goto rd_inq_data;
19551da177e4SLinus Torvalds 		}
19565d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
19571da177e4SLinus Torvalds 		if (j == 0x16) {
19581da177e4SLinus Torvalds 			goto inq_ok;
19591da177e4SLinus Torvalds 		}
19605d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x10, 0x46);
19615d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
19625d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, 0);
19635d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0);
19645d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
196580b52a7fSOndrej Zary 
19665d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
19671da177e4SLinus Torvalds 			cpu_relax();
196880b52a7fSOndrej Zary 
196980b52a7fSOndrej Zary 		if (atp_readb_io(dev, c, 0x17) != 0x16)
19701da177e4SLinus Torvalds 			goto sel_ok;
197180b52a7fSOndrej Zary 
19721da177e4SLinus Torvalds inq_ok:
19731da177e4SLinus Torvalds 		mbuf[36] = 0;
19741da177e4SLinus Torvalds 		printk(KERN_INFO "         ID: %2d  %s\n", i, &mbuf[8]);
19751da177e4SLinus Torvalds 		dev->id[c][i].devtype = mbuf[0];
19761da177e4SLinus Torvalds 		rmb = mbuf[1];
19771da177e4SLinus Torvalds 		n = mbuf[7];
1978197fb8d8SOndrej Zary 		if (!wide_chip)
1979197fb8d8SOndrej Zary 			goto not_wide;
19801da177e4SLinus Torvalds 		if ((mbuf[7] & 0x60) == 0) {
19811da177e4SLinus Torvalds 			goto not_wide;
19821da177e4SLinus Torvalds 		}
1983197fb8d8SOndrej Zary 		if (dev->dev_id == ATP885_DEVID || dev->dev_id == ATP880_DEVID1 || dev->dev_id == ATP880_DEVID2) {
1984197fb8d8SOndrej Zary 			if ((i < 8) && ((dev->global_map[c] & 0x20) == 0))
1985197fb8d8SOndrej Zary 				goto not_wide;
1986197fb8d8SOndrej Zary 		} else { /* result of is870() merge - is this a bug? */
1987197fb8d8SOndrej Zary 			if ((dev->global_map[c] & 0x20) == 0)
19881da177e4SLinus Torvalds 				goto not_wide;
19891da177e4SLinus Torvalds 		}
19901da177e4SLinus Torvalds 		if (lvdmode == 0) {
19911da177e4SLinus Torvalds 			goto chg_wide;
19921da177e4SLinus Torvalds 		}
199380b52a7fSOndrej Zary 		if (dev->sp[c][i] != 0x04)	// force u2
199480b52a7fSOndrej Zary 		{
19951da177e4SLinus Torvalds 			goto chg_wide;
19961da177e4SLinus Torvalds 		}
19971da177e4SLinus Torvalds 
19985d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x1b, 0x01);
19995d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 3, satn[0]);
20005d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 4, satn[1]);
20015d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 5, satn[2]);
20025d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 6, satn[3]);
20035d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 7, satn[4]);
20045d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 8, satn[5]);
20055d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x0f, 0);
20065d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
20075d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
20085d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, satn[6]);
20095d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, satn[7]);
20105d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, satn[8]);
20111da177e4SLinus Torvalds 
20125d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
20131da177e4SLinus Torvalds 			cpu_relax();
201480b52a7fSOndrej Zary 
201580b52a7fSOndrej Zary 		if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e)
20161da177e4SLinus Torvalds 			continue;
201780b52a7fSOndrej Zary 
20185d2a5a4fSOndrej Zary 		while (atp_readb_io(dev, c, 0x17) != 0x8e)
20191da177e4SLinus Torvalds 			cpu_relax();
202080b52a7fSOndrej Zary 
20211da177e4SLinus Torvalds try_u3:
20221da177e4SLinus Torvalds 		j = 0;
20235d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x09);
20245d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
20251da177e4SLinus Torvalds 
20265d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) {
20275d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0)
20285d2a5a4fSOndrej Zary 				atp_writeb_io(dev, c, 0x19, u3[j++]);
20291da177e4SLinus Torvalds 			cpu_relax();
20301da177e4SLinus Torvalds 		}
203180b52a7fSOndrej Zary 
20325d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00)
20331da177e4SLinus Torvalds 			cpu_relax();
203480b52a7fSOndrej Zary 
20355d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
20361da177e4SLinus Torvalds 		if (j == 0x0f) {
20371da177e4SLinus Torvalds 			goto u3p_in;
20381da177e4SLinus Torvalds 		}
20391da177e4SLinus Torvalds 		if (j == 0x0a) {
20401da177e4SLinus Torvalds 			goto u3p_cmd;
20411da177e4SLinus Torvalds 		}
20421da177e4SLinus Torvalds 		if (j == 0x0e) {
20431da177e4SLinus Torvalds 			goto try_u3;
20441da177e4SLinus Torvalds 		}
20451da177e4SLinus Torvalds 		continue;
20461da177e4SLinus Torvalds u3p_out:
20475d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
20485d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) {
20495d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0)
20505d2a5a4fSOndrej Zary 				atp_writeb_io(dev, c, 0x19, 0);
20511da177e4SLinus Torvalds 			cpu_relax();
20521da177e4SLinus Torvalds 		}
20535d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
20541da177e4SLinus Torvalds 		if (j == 0x0f) {
20551da177e4SLinus Torvalds 			goto u3p_in;
20561da177e4SLinus Torvalds 		}
20571da177e4SLinus Torvalds 		if (j == 0x0a) {
20581da177e4SLinus Torvalds 			goto u3p_cmd;
20591da177e4SLinus Torvalds 		}
20601da177e4SLinus Torvalds 		if (j == 0x0e) {
20611da177e4SLinus Torvalds 			goto u3p_out;
20621da177e4SLinus Torvalds 		}
20631da177e4SLinus Torvalds 		continue;
20641da177e4SLinus Torvalds u3p_in:
20655d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x09);
20665d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
20671da177e4SLinus Torvalds 		k = 0;
20681da177e4SLinus Torvalds u3p_in1:
20695d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x1f);
20701da177e4SLinus Torvalds 		if ((j & 0x01) != 0) {
20715d2a5a4fSOndrej Zary 			mbuf[k++] = atp_readb_io(dev, c, 0x19);
20721da177e4SLinus Torvalds 			goto u3p_in1;
20731da177e4SLinus Torvalds 		}
20741da177e4SLinus Torvalds 		if ((j & 0x80) == 0x00) {
20751da177e4SLinus Torvalds 			goto u3p_in1;
20761da177e4SLinus Torvalds 		}
20775d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
20781da177e4SLinus Torvalds 		if (j == 0x0f) {
20791da177e4SLinus Torvalds 			goto u3p_in;
20801da177e4SLinus Torvalds 		}
20811da177e4SLinus Torvalds 		if (j == 0x0a) {
20821da177e4SLinus Torvalds 			goto u3p_cmd;
20831da177e4SLinus Torvalds 		}
20841da177e4SLinus Torvalds 		if (j == 0x0e) {
20851da177e4SLinus Torvalds 			goto u3p_out;
20861da177e4SLinus Torvalds 		}
20871da177e4SLinus Torvalds 		continue;
20881da177e4SLinus Torvalds u3p_cmd:
20895d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x10, 0x30);
20905d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x00);
20915d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
209280b52a7fSOndrej Zary 
20935d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00);
209480b52a7fSOndrej Zary 
20955d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
20961da177e4SLinus Torvalds 		if (j != 0x16) {
20971da177e4SLinus Torvalds 			if (j == 0x4e) {
20981da177e4SLinus Torvalds 				goto u3p_out;
20991da177e4SLinus Torvalds 			}
21001da177e4SLinus Torvalds 			continue;
21011da177e4SLinus Torvalds 		}
21021da177e4SLinus Torvalds 		if (mbuf[0] != 0x01) {
21031da177e4SLinus Torvalds 			goto chg_wide;
21041da177e4SLinus Torvalds 		}
21051da177e4SLinus Torvalds 		if (mbuf[1] != 0x06) {
21061da177e4SLinus Torvalds 			goto chg_wide;
21071da177e4SLinus Torvalds 		}
21081da177e4SLinus Torvalds 		if (mbuf[2] != 0x04) {
21091da177e4SLinus Torvalds 			goto chg_wide;
21101da177e4SLinus Torvalds 		}
21111da177e4SLinus Torvalds 		if (mbuf[3] == 0x09) {
21121da177e4SLinus Torvalds 			m = 1;
21131da177e4SLinus Torvalds 			m = m << i;
21141da177e4SLinus Torvalds 			dev->wide_id[c] |= m;
21151da177e4SLinus Torvalds 			dev->id[c][i].devsp = 0xce;
21161da177e4SLinus Torvalds #ifdef ED_DBGP
21171da177e4SLinus Torvalds 			printk("dev->id[%2d][%2d].devsp = %2x\n",c,i,dev->id[c][i].devsp);
21181da177e4SLinus Torvalds #endif
21191da177e4SLinus Torvalds 			continue;
21201da177e4SLinus Torvalds 		}
21211da177e4SLinus Torvalds chg_wide:
21225d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x1b, 0x01);
21235d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 3, satn[0]);
21245d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 4, satn[1]);
21255d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 5, satn[2]);
21265d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 6, satn[3]);
21275d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 7, satn[4]);
21285d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 8, satn[5]);
21295d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x0f, 0);
21305d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
21315d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
21325d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, satn[6]);
21335d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, satn[7]);
21345d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, satn[8]);
21351da177e4SLinus Torvalds 
21365d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
21371da177e4SLinus Torvalds 			cpu_relax();
213880b52a7fSOndrej Zary 
213980b52a7fSOndrej Zary 		if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e)
21401da177e4SLinus Torvalds 			continue;
214180b52a7fSOndrej Zary 
21425d2a5a4fSOndrej Zary 		while (atp_readb_io(dev, c, 0x17) != 0x8e)
21431da177e4SLinus Torvalds 			cpu_relax();
214480b52a7fSOndrej Zary 
21451da177e4SLinus Torvalds try_wide:
21461da177e4SLinus Torvalds 		j = 0;
21475d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x05);
21485d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
21491da177e4SLinus Torvalds 
21505d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) {
21515d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0)
21525d2a5a4fSOndrej Zary 				atp_writeb_io(dev, c, 0x19, wide[j++]);
21531da177e4SLinus Torvalds 			cpu_relax();
21541da177e4SLinus Torvalds 		}
215580b52a7fSOndrej Zary 
21565d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00)
21571da177e4SLinus Torvalds 			cpu_relax();
215880b52a7fSOndrej Zary 
21595d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
21601da177e4SLinus Torvalds 		if (j == 0x0f) {
21611da177e4SLinus Torvalds 			goto widep_in;
21621da177e4SLinus Torvalds 		}
21631da177e4SLinus Torvalds 		if (j == 0x0a) {
21641da177e4SLinus Torvalds 			goto widep_cmd;
21651da177e4SLinus Torvalds 		}
21661da177e4SLinus Torvalds 		if (j == 0x0e) {
21671da177e4SLinus Torvalds 			goto try_wide;
21681da177e4SLinus Torvalds 		}
21691da177e4SLinus Torvalds 		continue;
21701da177e4SLinus Torvalds widep_out:
21715d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
21725d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) {
21735d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0)
21745d2a5a4fSOndrej Zary 				atp_writeb_io(dev, c, 0x19, 0);
21751da177e4SLinus Torvalds 			cpu_relax();
21761da177e4SLinus Torvalds 		}
21775d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
21781da177e4SLinus Torvalds 		if (j == 0x0f) {
21791da177e4SLinus Torvalds 			goto widep_in;
21801da177e4SLinus Torvalds 		}
21811da177e4SLinus Torvalds 		if (j == 0x0a) {
21821da177e4SLinus Torvalds 			goto widep_cmd;
21831da177e4SLinus Torvalds 		}
21841da177e4SLinus Torvalds 		if (j == 0x0e) {
21851da177e4SLinus Torvalds 			goto widep_out;
21861da177e4SLinus Torvalds 		}
21871da177e4SLinus Torvalds 		continue;
21881da177e4SLinus Torvalds widep_in:
21895d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0xff);
21905d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
21911da177e4SLinus Torvalds 		k = 0;
21921da177e4SLinus Torvalds widep_in1:
21935d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x1f);
21941da177e4SLinus Torvalds 		if ((j & 0x01) != 0) {
21955d2a5a4fSOndrej Zary 			mbuf[k++] = atp_readb_io(dev, c, 0x19);
21961da177e4SLinus Torvalds 			goto widep_in1;
21971da177e4SLinus Torvalds 		}
21981da177e4SLinus Torvalds 		if ((j & 0x80) == 0x00) {
21991da177e4SLinus Torvalds 			goto widep_in1;
22001da177e4SLinus Torvalds 		}
22015d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
22021da177e4SLinus Torvalds 		if (j == 0x0f) {
22031da177e4SLinus Torvalds 			goto widep_in;
22041da177e4SLinus Torvalds 		}
22051da177e4SLinus Torvalds 		if (j == 0x0a) {
22061da177e4SLinus Torvalds 			goto widep_cmd;
22071da177e4SLinus Torvalds 		}
22081da177e4SLinus Torvalds 		if (j == 0x0e) {
22091da177e4SLinus Torvalds 			goto widep_out;
22101da177e4SLinus Torvalds 		}
22111da177e4SLinus Torvalds 		continue;
22121da177e4SLinus Torvalds widep_cmd:
22135d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x10, 0x30);
22145d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x00);
22155d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
221680b52a7fSOndrej Zary 
22175d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
22181da177e4SLinus Torvalds 			cpu_relax();
221980b52a7fSOndrej Zary 
22205d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
22211da177e4SLinus Torvalds 		if (j != 0x16) {
22221da177e4SLinus Torvalds 			if (j == 0x4e) {
22231da177e4SLinus Torvalds 				goto widep_out;
22241da177e4SLinus Torvalds 			}
22251da177e4SLinus Torvalds 			continue;
22261da177e4SLinus Torvalds 		}
22271da177e4SLinus Torvalds 		if (mbuf[0] != 0x01) {
22281da177e4SLinus Torvalds 			goto not_wide;
22291da177e4SLinus Torvalds 		}
22301da177e4SLinus Torvalds 		if (mbuf[1] != 0x02) {
22311da177e4SLinus Torvalds 			goto not_wide;
22321da177e4SLinus Torvalds 		}
22331da177e4SLinus Torvalds 		if (mbuf[2] != 0x03) {
22341da177e4SLinus Torvalds 			goto not_wide;
22351da177e4SLinus Torvalds 		}
22361da177e4SLinus Torvalds 		if (mbuf[3] != 0x01) {
22371da177e4SLinus Torvalds 			goto not_wide;
22381da177e4SLinus Torvalds 		}
22391da177e4SLinus Torvalds 		m = 1;
22401da177e4SLinus Torvalds 		m = m << i;
22411da177e4SLinus Torvalds 		dev->wide_id[c] |= m;
22421da177e4SLinus Torvalds not_wide:
224380b52a7fSOndrej Zary 		if ((dev->id[c][i].devtype == 0x00) || (dev->id[c][i].devtype == 0x07) || ((dev->id[c][i].devtype == 0x05) && ((n & 0x10) != 0))) {
22441da177e4SLinus Torvalds 			m = 1;
22451da177e4SLinus Torvalds 			m = m << i;
22461da177e4SLinus Torvalds 			if ((dev->async[c] & m) != 0) {
22471da177e4SLinus Torvalds 				goto set_sync;
22481da177e4SLinus Torvalds 			}
22491da177e4SLinus Torvalds 		}
22501da177e4SLinus Torvalds 		continue;
22511da177e4SLinus Torvalds set_sync:
2252460da918SOndrej Zary 		if ((dev->dev_id != ATP885_DEVID && dev->dev_id != ATP880_DEVID1 && dev->dev_id != ATP880_DEVID2) || (dev->sp[c][i] == 0x02)) {
22531da177e4SLinus Torvalds 			synu[4] = 0x0c;
22541da177e4SLinus Torvalds 			synuw[4] = 0x0c;
22551da177e4SLinus Torvalds 		} else {
22561da177e4SLinus Torvalds 			if (dev->sp[c][i] >= 0x03) {
22571da177e4SLinus Torvalds 				synu[4] = 0x0a;
22581da177e4SLinus Torvalds 				synuw[4] = 0x0a;
22591da177e4SLinus Torvalds 			}
22601da177e4SLinus Torvalds 		}
22611da177e4SLinus Torvalds 		j = 0;
22621da177e4SLinus Torvalds 		if ((m & dev->wide_id[c]) != 0) {
22631da177e4SLinus Torvalds 			j |= 0x01;
22641da177e4SLinus Torvalds 		}
22655d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x1b, j);
22665d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 3, satn[0]);
22675d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 4, satn[1]);
22685d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 5, satn[2]);
22695d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 6, satn[3]);
22705d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 7, satn[4]);
22715d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 8, satn[5]);
22725d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x0f, 0);
22735d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
22745d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x12, 0);
22755d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x13, satn[6]);
22765d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, satn[7]);
22775d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, satn[8]);
22781da177e4SLinus Torvalds 
22795d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
22801da177e4SLinus Torvalds 			cpu_relax();
228180b52a7fSOndrej Zary 
228280b52a7fSOndrej Zary 		if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e)
22831da177e4SLinus Torvalds 			continue;
228480b52a7fSOndrej Zary 
22855d2a5a4fSOndrej Zary 		while (atp_readb_io(dev, c, 0x17) != 0x8e)
22861da177e4SLinus Torvalds 			cpu_relax();
228780b52a7fSOndrej Zary 
22881da177e4SLinus Torvalds try_sync:
22891da177e4SLinus Torvalds 		j = 0;
22905d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x06);
22915d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
22921da177e4SLinus Torvalds 
22935d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) {
22945d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0) {
22951da177e4SLinus Torvalds 				if ((m & dev->wide_id[c]) != 0) {
2296460da918SOndrej Zary 					if (dev->dev_id == ATP885_DEVID || dev->dev_id == ATP880_DEVID1 || dev->dev_id == ATP880_DEVID2) {
22971da177e4SLinus Torvalds 						if ((m & dev->ultra_map[c]) != 0) {
22985d2a5a4fSOndrej Zary 							atp_writeb_io(dev, c, 0x19, synuw[j++]);
22991da177e4SLinus Torvalds 						} else {
23005d2a5a4fSOndrej Zary 							atp_writeb_io(dev, c, 0x19, synw[j++]);
23011da177e4SLinus Torvalds 						}
2302460da918SOndrej Zary 					} else
2303460da918SOndrej Zary 						atp_writeb_io(dev, c, 0x19, synw_870[j++]);
23041da177e4SLinus Torvalds 				} else {
23051da177e4SLinus Torvalds 					if ((m & dev->ultra_map[c]) != 0) {
23065d2a5a4fSOndrej Zary 						atp_writeb_io(dev, c, 0x19, synu[j++]);
23071da177e4SLinus Torvalds 					} else {
23085d2a5a4fSOndrej Zary 						atp_writeb_io(dev, c, 0x19, synn[j++]);
23091da177e4SLinus Torvalds 					}
23101da177e4SLinus Torvalds 				}
23111da177e4SLinus Torvalds 			}
23121da177e4SLinus Torvalds 		}
231380b52a7fSOndrej Zary 
23145d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00)
23151da177e4SLinus Torvalds 			cpu_relax();
231680b52a7fSOndrej Zary 
23175d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17) & 0x0f;
23181da177e4SLinus Torvalds 		if (j == 0x0f) {
23191da177e4SLinus Torvalds 			goto phase_ins;
23201da177e4SLinus Torvalds 		}
23211da177e4SLinus Torvalds 		if (j == 0x0a) {
23221da177e4SLinus Torvalds 			goto phase_cmds;
23231da177e4SLinus Torvalds 		}
23241da177e4SLinus Torvalds 		if (j == 0x0e) {
23251da177e4SLinus Torvalds 			goto try_sync;
23261da177e4SLinus Torvalds 		}
23271da177e4SLinus Torvalds 		continue;
23281da177e4SLinus Torvalds phase_outs:
23295d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
23305d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) {
23315d2a5a4fSOndrej Zary 			if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0x00)
23325d2a5a4fSOndrej Zary 				atp_writeb_io(dev, c, 0x19, 0x00);
23331da177e4SLinus Torvalds 			cpu_relax();
23341da177e4SLinus Torvalds 		}
23355d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
23361da177e4SLinus Torvalds 		if (j == 0x85) {
23371da177e4SLinus Torvalds 			goto tar_dcons;
23381da177e4SLinus Torvalds 		}
23391da177e4SLinus Torvalds 		j &= 0x0f;
23401da177e4SLinus Torvalds 		if (j == 0x0f) {
23411da177e4SLinus Torvalds 			goto phase_ins;
23421da177e4SLinus Torvalds 		}
23431da177e4SLinus Torvalds 		if (j == 0x0a) {
23441da177e4SLinus Torvalds 			goto phase_cmds;
23451da177e4SLinus Torvalds 		}
23461da177e4SLinus Torvalds 		if (j == 0x0e) {
23471da177e4SLinus Torvalds 			goto phase_outs;
23481da177e4SLinus Torvalds 		}
23491da177e4SLinus Torvalds 		continue;
23501da177e4SLinus Torvalds phase_ins:
2351460da918SOndrej Zary 		if (dev->dev_id == ATP885_DEVID || dev->dev_id == ATP880_DEVID1 || dev->dev_id == ATP880_DEVID2)
23525d2a5a4fSOndrej Zary 			atp_writeb_io(dev, c, 0x14, 0x06);
2353460da918SOndrej Zary 		else
2354460da918SOndrej Zary 			atp_writeb_io(dev, c, 0x14, 0xff);
23555d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x20);
23561da177e4SLinus Torvalds 		k = 0;
23571da177e4SLinus Torvalds phase_ins1:
23585d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x1f);
23591da177e4SLinus Torvalds 		if ((j & 0x01) != 0x00) {
23605d2a5a4fSOndrej Zary 			mbuf[k++] = atp_readb_io(dev, c, 0x19);
23611da177e4SLinus Torvalds 			goto phase_ins1;
23621da177e4SLinus Torvalds 		}
23631da177e4SLinus Torvalds 		if ((j & 0x80) == 0x00) {
23641da177e4SLinus Torvalds 			goto phase_ins1;
23651da177e4SLinus Torvalds 		}
236680b52a7fSOndrej Zary 
23675d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00);
236880b52a7fSOndrej Zary 
23695d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
23701da177e4SLinus Torvalds 		if (j == 0x85) {
23711da177e4SLinus Torvalds 			goto tar_dcons;
23721da177e4SLinus Torvalds 		}
23731da177e4SLinus Torvalds 		j &= 0x0f;
23741da177e4SLinus Torvalds 		if (j == 0x0f) {
23751da177e4SLinus Torvalds 			goto phase_ins;
23761da177e4SLinus Torvalds 		}
23771da177e4SLinus Torvalds 		if (j == 0x0a) {
23781da177e4SLinus Torvalds 			goto phase_cmds;
23791da177e4SLinus Torvalds 		}
23801da177e4SLinus Torvalds 		if (j == 0x0e) {
23811da177e4SLinus Torvalds 			goto phase_outs;
23821da177e4SLinus Torvalds 		}
23831da177e4SLinus Torvalds 		continue;
23841da177e4SLinus Torvalds phase_cmds:
23855d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x10, 0x30);
23861da177e4SLinus Torvalds tar_dcons:
23875d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x14, 0x00);
23885d2a5a4fSOndrej Zary 		atp_writeb_io(dev, c, 0x18, 0x08);
238980b52a7fSOndrej Zary 
23905d2a5a4fSOndrej Zary 		while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
23911da177e4SLinus Torvalds 			cpu_relax();
239280b52a7fSOndrej Zary 
23935d2a5a4fSOndrej Zary 		j = atp_readb_io(dev, c, 0x17);
23941da177e4SLinus Torvalds 		if (j != 0x16) {
23951da177e4SLinus Torvalds 			continue;
23961da177e4SLinus Torvalds 		}
23971da177e4SLinus Torvalds 		if (mbuf[0] != 0x01) {
23981da177e4SLinus Torvalds 			continue;
23991da177e4SLinus Torvalds 		}
24001da177e4SLinus Torvalds 		if (mbuf[1] != 0x03) {
24011da177e4SLinus Torvalds 			continue;
24021da177e4SLinus Torvalds 		}
24031da177e4SLinus Torvalds 		if (mbuf[4] == 0x00) {
24041da177e4SLinus Torvalds 			continue;
24051da177e4SLinus Torvalds 		}
24061da177e4SLinus Torvalds 		if (mbuf[3] > 0x64) {
24071da177e4SLinus Torvalds 			continue;
24081da177e4SLinus Torvalds 		}
2409460da918SOndrej Zary 		if (dev->dev_id == ATP885_DEVID || dev->dev_id == ATP880_DEVID1 || dev->dev_id == ATP880_DEVID2) {
24101da177e4SLinus Torvalds 			if (mbuf[4] > 0x0e) {
24111da177e4SLinus Torvalds 				mbuf[4] = 0x0e;
24121da177e4SLinus Torvalds 			}
2413460da918SOndrej Zary 		} else {
2414460da918SOndrej Zary 			if (mbuf[4] > 0x0c) {
2415460da918SOndrej Zary 				mbuf[4] = 0x0c;
2416460da918SOndrej Zary 			}
2417460da918SOndrej Zary 		}
24181da177e4SLinus Torvalds 		dev->id[c][i].devsp = mbuf[4];
2419460da918SOndrej Zary 		if (dev->dev_id == ATP885_DEVID || dev->dev_id == ATP880_DEVID1 || dev->dev_id == ATP880_DEVID2)
24201da177e4SLinus Torvalds 			if (mbuf[3] < 0x0c) {
24211da177e4SLinus Torvalds 				j = 0xb0;
24221da177e4SLinus Torvalds 				goto set_syn_ok;
24231da177e4SLinus Torvalds 			}
24241da177e4SLinus Torvalds 		if ((mbuf[3] < 0x0d) && (rmb == 0)) {
24251da177e4SLinus Torvalds 			j = 0xa0;
24261da177e4SLinus Torvalds 			goto set_syn_ok;
24271da177e4SLinus Torvalds 		}
24281da177e4SLinus Torvalds 		if (mbuf[3] < 0x1a) {
24291da177e4SLinus Torvalds 			j = 0x20;
24301da177e4SLinus Torvalds 			goto set_syn_ok;
24311da177e4SLinus Torvalds 		}
24321da177e4SLinus Torvalds 		if (mbuf[3] < 0x33) {
24331da177e4SLinus Torvalds 			j = 0x40;
24341da177e4SLinus Torvalds 			goto set_syn_ok;
24351da177e4SLinus Torvalds 		}
24361da177e4SLinus Torvalds 		if (mbuf[3] < 0x4c) {
24371da177e4SLinus Torvalds 			j = 0x50;
24381da177e4SLinus Torvalds 			goto set_syn_ok;
24391da177e4SLinus Torvalds 		}
24401da177e4SLinus Torvalds 		j = 0x60;
24411da177e4SLinus Torvalds set_syn_ok:
24421da177e4SLinus Torvalds 		dev->id[c][i].devsp = (dev->id[c][i].devsp & 0x0f) | j;
24431da177e4SLinus Torvalds #ifdef ED_DBGP
24441da177e4SLinus Torvalds 		printk("dev->id[%2d][%2d].devsp = %2x\n",c,i,dev->id[c][i].devsp);
24451da177e4SLinus Torvalds #endif
24461da177e4SLinus Torvalds 	}
24471da177e4SLinus Torvalds }
24481da177e4SLinus Torvalds 
24491da177e4SLinus Torvalds module_init(atp870u_init);
24501da177e4SLinus Torvalds module_exit(atp870u_exit);
24511da177e4SLinus Torvalds 
2452