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