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