11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Copyright (C) 1997 Wu Ching Chen 31da177e4SLinus Torvalds * 2.1.x update (C) 1998 Krzysztof G. Baranowski 4fa195afeSAlan Cox * 2.5.x update (C) 2002 Red Hat 5fa195afeSAlan Cox * 2.6.x update (C) 2004 Red Hat 61da177e4SLinus Torvalds * 71da177e4SLinus Torvalds * Marcelo Tosatti <marcelo@conectiva.com.br> : SMP fixes 81da177e4SLinus Torvalds * 91da177e4SLinus Torvalds * Wu Ching Chen : NULL pointer fixes 2000/06/02 101da177e4SLinus Torvalds * support atp876 chip 111da177e4SLinus Torvalds * enable 32 bit fifo transfer 121da177e4SLinus Torvalds * support cdrom & remove device run ultra speed 131da177e4SLinus Torvalds * fix disconnect bug 2000/12/21 141da177e4SLinus Torvalds * support atp880 chip lvd u160 2001/05/15 151da177e4SLinus Torvalds * fix prd table bug 2001/09/12 (7.1) 161da177e4SLinus Torvalds * 171da177e4SLinus Torvalds * atp885 support add by ACARD Hao Ping Lian 2005/01/05 181da177e4SLinus Torvalds */ 191da177e4SLinus Torvalds #include <linux/module.h> 201da177e4SLinus Torvalds #include <linux/init.h> 211da177e4SLinus Torvalds #include <linux/interrupt.h> 221da177e4SLinus Torvalds #include <linux/kernel.h> 231da177e4SLinus Torvalds #include <linux/types.h> 241da177e4SLinus Torvalds #include <linux/string.h> 251da177e4SLinus Torvalds #include <linux/ioport.h> 261da177e4SLinus Torvalds #include <linux/delay.h> 271da177e4SLinus Torvalds #include <linux/proc_fs.h> 281da177e4SLinus Torvalds #include <linux/spinlock.h> 291da177e4SLinus Torvalds #include <linux/pci.h> 301da177e4SLinus Torvalds #include <linux/blkdev.h> 31910638aeSMatthias Gehre #include <linux/dma-mapping.h> 325a0e3ad6STejun Heo #include <linux/slab.h> 331da177e4SLinus Torvalds #include <asm/io.h> 341da177e4SLinus Torvalds 351da177e4SLinus Torvalds #include <scsi/scsi.h> 361da177e4SLinus Torvalds #include <scsi/scsi_cmnd.h> 371da177e4SLinus Torvalds #include <scsi/scsi_device.h> 381da177e4SLinus Torvalds #include <scsi/scsi_host.h> 391da177e4SLinus Torvalds 401da177e4SLinus Torvalds #include "atp870u.h" 411da177e4SLinus Torvalds 421da177e4SLinus Torvalds static struct scsi_host_template atp870u_template; 431da177e4SLinus Torvalds static void send_s870(struct atp_unit *dev,unsigned char c); 444192a40fSOndrej Zary static void atp_is(struct atp_unit *dev, unsigned char c, bool wide_chip, unsigned char lvdmode); 451da177e4SLinus Torvalds 466a3cebb6SOndrej Zary static inline void atp_writeb_base(struct atp_unit *atp, u8 reg, u8 val) 476a3cebb6SOndrej Zary { 486a3cebb6SOndrej Zary outb(val, atp->baseport + reg); 496a3cebb6SOndrej Zary } 506a3cebb6SOndrej Zary 51d804bb25SOndrej Zary static inline void atp_writew_base(struct atp_unit *atp, u8 reg, u16 val) 52d804bb25SOndrej Zary { 53d804bb25SOndrej Zary outw(val, atp->baseport + reg); 54d804bb25SOndrej Zary } 55d804bb25SOndrej Zary 566a3cebb6SOndrej Zary static inline void atp_writeb_io(struct atp_unit *atp, u8 channel, u8 reg, u8 val) 576a3cebb6SOndrej Zary { 586a3cebb6SOndrej Zary outb(val, atp->ioport[channel] + reg); 596a3cebb6SOndrej Zary } 606a3cebb6SOndrej Zary 616a3cebb6SOndrej Zary static inline void atp_writew_io(struct atp_unit *atp, u8 channel, u8 reg, u16 val) 626a3cebb6SOndrej Zary { 636a3cebb6SOndrej Zary outw(val, atp->ioport[channel] + reg); 646a3cebb6SOndrej Zary } 656a3cebb6SOndrej Zary 666a3cebb6SOndrej Zary static inline void atp_writeb_pci(struct atp_unit *atp, u8 channel, u8 reg, u8 val) 676a3cebb6SOndrej Zary { 686a3cebb6SOndrej Zary outb(val, atp->pciport[channel] + reg); 696a3cebb6SOndrej Zary } 706a3cebb6SOndrej Zary 716a3cebb6SOndrej Zary static inline void atp_writel_pci(struct atp_unit *atp, u8 channel, u8 reg, u32 val) 726a3cebb6SOndrej Zary { 736a3cebb6SOndrej Zary outl(val, atp->pciport[channel] + reg); 746a3cebb6SOndrej Zary } 756a3cebb6SOndrej Zary 766a3cebb6SOndrej Zary static inline u8 atp_readb_base(struct atp_unit *atp, u8 reg) 776a3cebb6SOndrej Zary { 786a3cebb6SOndrej Zary return inb(atp->baseport + reg); 796a3cebb6SOndrej Zary } 806a3cebb6SOndrej Zary 81d804bb25SOndrej Zary static inline u16 atp_readw_base(struct atp_unit *atp, u8 reg) 82d804bb25SOndrej Zary { 83d804bb25SOndrej Zary return inw(atp->baseport + reg); 84d804bb25SOndrej Zary } 85d804bb25SOndrej Zary 86d804bb25SOndrej Zary static inline u32 atp_readl_base(struct atp_unit *atp, u8 reg) 87d804bb25SOndrej Zary { 88d804bb25SOndrej Zary return inl(atp->baseport + reg); 89d804bb25SOndrej Zary } 90d804bb25SOndrej Zary 916a3cebb6SOndrej Zary static inline u8 atp_readb_io(struct atp_unit *atp, u8 channel, u8 reg) 926a3cebb6SOndrej Zary { 936a3cebb6SOndrej Zary return inb(atp->ioport[channel] + reg); 946a3cebb6SOndrej Zary } 956a3cebb6SOndrej Zary 966a3cebb6SOndrej Zary static inline u16 atp_readw_io(struct atp_unit *atp, u8 channel, u8 reg) 976a3cebb6SOndrej Zary { 986a3cebb6SOndrej Zary return inw(atp->ioport[channel] + reg); 996a3cebb6SOndrej Zary } 1006a3cebb6SOndrej Zary 1016a3cebb6SOndrej Zary static inline u8 atp_readb_pci(struct atp_unit *atp, u8 channel, u8 reg) 1026a3cebb6SOndrej Zary { 1036a3cebb6SOndrej Zary return inb(atp->pciport[channel] + reg); 1046a3cebb6SOndrej Zary } 1056a3cebb6SOndrej Zary 1067d12e780SDavid Howells static irqreturn_t atp870u_intr_handle(int irq, void *dev_id) 1071da177e4SLinus Torvalds { 1081da177e4SLinus Torvalds unsigned long flags; 109bc0fe4c9SOndrej Zary unsigned short int id; 1101da177e4SLinus Torvalds unsigned char i, j, c, target_id, lun,cmdp; 1111da177e4SLinus Torvalds unsigned char *prd; 1121da177e4SLinus Torvalds struct scsi_cmnd *workreq; 1131da177e4SLinus Torvalds unsigned long adrcnt, k; 1141da177e4SLinus Torvalds #ifdef ED_DBGP 1151da177e4SLinus Torvalds unsigned long l; 1161da177e4SLinus Torvalds #endif 1171da177e4SLinus Torvalds struct Scsi_Host *host = dev_id; 1181da177e4SLinus Torvalds struct atp_unit *dev = (struct atp_unit *)&host->hostdata; 1191da177e4SLinus Torvalds 1201da177e4SLinus Torvalds for (c = 0; c < 2; c++) { 1216a3cebb6SOndrej Zary j = atp_readb_io(dev, c, 0x1f); 1221da177e4SLinus Torvalds if ((j & 0x80) != 0) 12378614ecdSOndrej Zary break; 1241da177e4SLinus Torvalds dev->in_int[c] = 0; 1251da177e4SLinus Torvalds } 12678614ecdSOndrej Zary if ((j & 0x80) == 0) 1271da177e4SLinus Torvalds return IRQ_NONE; 1281da177e4SLinus Torvalds #ifdef ED_DBGP 1291da177e4SLinus Torvalds printk("atp870u_intr_handle enter\n"); 1301da177e4SLinus Torvalds #endif 1311da177e4SLinus Torvalds dev->in_int[c] = 1; 1326a3cebb6SOndrej Zary cmdp = atp_readb_io(dev, c, 0x10); 1331da177e4SLinus Torvalds if (dev->working[c] != 0) { 1341da177e4SLinus Torvalds if (dev->dev_id == ATP885_DEVID) { 1356a3cebb6SOndrej Zary if ((atp_readb_io(dev, c, 0x16) & 0x80) == 0) 1366a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x16, (atp_readb_io(dev, c, 0x16) | 0x80)); 1371da177e4SLinus Torvalds } 1386a3cebb6SOndrej Zary if ((atp_readb_pci(dev, c, 0x00) & 0x08) != 0) 1391da177e4SLinus Torvalds { 1401da177e4SLinus Torvalds for (k=0; k < 1000; k++) { 1416a3cebb6SOndrej Zary if ((atp_readb_pci(dev, c, 2) & 0x08) == 0) 14278614ecdSOndrej Zary break; 1436a3cebb6SOndrej Zary if ((atp_readb_pci(dev, c, 2) & 0x01) == 0) 14478614ecdSOndrej Zary break; 1451da177e4SLinus Torvalds } 1461da177e4SLinus Torvalds } 1476a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 0, 0x00); 1481da177e4SLinus Torvalds 1496a3cebb6SOndrej Zary i = atp_readb_io(dev, c, 0x17); 1501da177e4SLinus Torvalds 151bc0fe4c9SOndrej Zary if (dev->dev_id == ATP885_DEVID) 1526a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 2, 0x06); 1531da177e4SLinus Torvalds 1546a3cebb6SOndrej Zary target_id = atp_readb_io(dev, c, 0x15); 1551da177e4SLinus Torvalds 1561da177e4SLinus Torvalds /* 1571da177e4SLinus Torvalds * Remap wide devices onto id numbers 1581da177e4SLinus Torvalds */ 1591da177e4SLinus Torvalds 1601da177e4SLinus Torvalds if ((target_id & 0x40) != 0) { 1611da177e4SLinus Torvalds target_id = (target_id & 0x07) | 0x08; 1621da177e4SLinus Torvalds } else { 1631da177e4SLinus Torvalds target_id &= 0x07; 1641da177e4SLinus Torvalds } 1651da177e4SLinus Torvalds 1661da177e4SLinus Torvalds if ((j & 0x40) != 0) { 1671da177e4SLinus Torvalds if (dev->last_cmd[c] == 0xff) { 1681da177e4SLinus Torvalds dev->last_cmd[c] = target_id; 1691da177e4SLinus Torvalds } 1701da177e4SLinus Torvalds dev->last_cmd[c] |= 0x40; 1711da177e4SLinus Torvalds } 1721da177e4SLinus Torvalds if (dev->dev_id == ATP885_DEVID) 1731da177e4SLinus Torvalds dev->r1f[c][target_id] |= j; 1741da177e4SLinus Torvalds #ifdef ED_DBGP 1751da177e4SLinus Torvalds printk("atp870u_intr_handle status = %x\n",i); 1761da177e4SLinus Torvalds #endif 1771da177e4SLinus Torvalds if (i == 0x85) { 1781da177e4SLinus Torvalds if ((dev->last_cmd[c] & 0xf0) != 0x40) { 1791da177e4SLinus Torvalds dev->last_cmd[c] = 0xff; 1801da177e4SLinus Torvalds } 1811da177e4SLinus Torvalds if (dev->dev_id == ATP885_DEVID) { 1821da177e4SLinus Torvalds adrcnt = 0; 1836a3cebb6SOndrej Zary ((unsigned char *) &adrcnt)[2] = atp_readb_io(dev, c, 0x12); 1846a3cebb6SOndrej Zary ((unsigned char *) &adrcnt)[1] = atp_readb_io(dev, c, 0x13); 1856a3cebb6SOndrej Zary ((unsigned char *) &adrcnt)[0] = atp_readb_io(dev, c, 0x14); 1861da177e4SLinus Torvalds if (dev->id[c][target_id].last_len != adrcnt) 1871da177e4SLinus Torvalds { 1881da177e4SLinus Torvalds k = dev->id[c][target_id].last_len; 1891da177e4SLinus Torvalds k -= adrcnt; 1901da177e4SLinus Torvalds dev->id[c][target_id].tran_len = k; 1911da177e4SLinus Torvalds dev->id[c][target_id].last_len = adrcnt; 1921da177e4SLinus Torvalds } 1931da177e4SLinus Torvalds #ifdef ED_DBGP 1943a38e53eSOndrej Zary printk("dev->id[c][target_id].last_len = %d dev->id[c][target_id].tran_len = %d\n",dev->id[c][target_id].last_len,dev->id[c][target_id].tran_len); 1951da177e4SLinus Torvalds #endif 1961da177e4SLinus Torvalds } 1971da177e4SLinus Torvalds 1981da177e4SLinus Torvalds /* 1991da177e4SLinus Torvalds * Flip wide 2001da177e4SLinus Torvalds */ 2011da177e4SLinus Torvalds if (dev->wide_id[c] != 0) { 2026a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x1b, 0x01); 2036a3cebb6SOndrej Zary while ((atp_readb_io(dev, c, 0x1b) & 0x01) != 0x01) 2046a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x1b, 0x01); 2051da177e4SLinus Torvalds } 2061da177e4SLinus Torvalds /* 2071da177e4SLinus Torvalds * Issue more commands 2081da177e4SLinus Torvalds */ 2091da177e4SLinus Torvalds spin_lock_irqsave(dev->host->host_lock, flags); 2101da177e4SLinus Torvalds if (((dev->quhd[c] != dev->quend[c]) || (dev->last_cmd[c] != 0xff)) && 2111da177e4SLinus Torvalds (dev->in_snd[c] == 0)) { 2121da177e4SLinus Torvalds #ifdef ED_DBGP 2131da177e4SLinus Torvalds printk("Call sent_s870\n"); 2141da177e4SLinus Torvalds #endif 2151da177e4SLinus Torvalds send_s870(dev,c); 2161da177e4SLinus Torvalds } 2171da177e4SLinus Torvalds spin_unlock_irqrestore(dev->host->host_lock, flags); 2181da177e4SLinus Torvalds /* 2191da177e4SLinus Torvalds * Done 2201da177e4SLinus Torvalds */ 2211da177e4SLinus Torvalds dev->in_int[c] = 0; 2221da177e4SLinus Torvalds #ifdef ED_DBGP 2231da177e4SLinus Torvalds printk("Status 0x85 return\n"); 2241da177e4SLinus Torvalds #endif 22578614ecdSOndrej Zary return IRQ_HANDLED; 2261da177e4SLinus Torvalds } 2271da177e4SLinus Torvalds 2281da177e4SLinus Torvalds if (i == 0x40) { 2291da177e4SLinus Torvalds dev->last_cmd[c] |= 0x40; 2301da177e4SLinus Torvalds dev->in_int[c] = 0; 23178614ecdSOndrej Zary return IRQ_HANDLED; 2321da177e4SLinus Torvalds } 2331da177e4SLinus Torvalds 2341da177e4SLinus Torvalds if (i == 0x21) { 2351da177e4SLinus Torvalds if ((dev->last_cmd[c] & 0xf0) != 0x40) { 2361da177e4SLinus Torvalds dev->last_cmd[c] = 0xff; 2371da177e4SLinus Torvalds } 2381da177e4SLinus Torvalds adrcnt = 0; 2396a3cebb6SOndrej Zary ((unsigned char *) &adrcnt)[2] = atp_readb_io(dev, c, 0x12); 2406a3cebb6SOndrej Zary ((unsigned char *) &adrcnt)[1] = atp_readb_io(dev, c, 0x13); 2416a3cebb6SOndrej Zary ((unsigned char *) &adrcnt)[0] = atp_readb_io(dev, c, 0x14); 2421da177e4SLinus Torvalds k = dev->id[c][target_id].last_len; 2431da177e4SLinus Torvalds k -= adrcnt; 2441da177e4SLinus Torvalds dev->id[c][target_id].tran_len = k; 2451da177e4SLinus Torvalds dev->id[c][target_id].last_len = adrcnt; 2466a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x10, 0x41); 2476a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 2481da177e4SLinus Torvalds dev->in_int[c] = 0; 24978614ecdSOndrej Zary return IRQ_HANDLED; 2501da177e4SLinus Torvalds } 2511da177e4SLinus Torvalds 2521da177e4SLinus Torvalds if (dev->dev_id == ATP885_DEVID) { 2531da177e4SLinus Torvalds if ((i == 0x4c) || (i == 0x4d) || (i == 0x8c) || (i == 0x8d)) { 2541da177e4SLinus Torvalds if ((i == 0x4c) || (i == 0x8c)) 2551da177e4SLinus Torvalds i=0x48; 2561da177e4SLinus Torvalds else 2571da177e4SLinus Torvalds i=0x49; 2581da177e4SLinus Torvalds } 2591da177e4SLinus Torvalds 2601da177e4SLinus Torvalds } 2611da177e4SLinus Torvalds if ((i == 0x80) || (i == 0x8f)) { 2621da177e4SLinus Torvalds #ifdef ED_DBGP 2631da177e4SLinus Torvalds printk(KERN_DEBUG "Device reselect\n"); 2641da177e4SLinus Torvalds #endif 2651da177e4SLinus Torvalds lun = 0; 2666a3cebb6SOndrej Zary if (cmdp == 0x44 || i == 0x80) 2676a3cebb6SOndrej Zary lun = atp_readb_io(dev, c, 0x1d) & 0x07; 2686a3cebb6SOndrej Zary else { 2691da177e4SLinus Torvalds if ((dev->last_cmd[c] & 0xf0) != 0x40) { 2701da177e4SLinus Torvalds dev->last_cmd[c] = 0xff; 2711da177e4SLinus Torvalds } 2721da177e4SLinus Torvalds if (cmdp == 0x41) { 2731da177e4SLinus Torvalds #ifdef ED_DBGP 2741da177e4SLinus Torvalds printk("cmdp = 0x41\n"); 2751da177e4SLinus Torvalds #endif 2761da177e4SLinus Torvalds adrcnt = 0; 2776a3cebb6SOndrej Zary ((unsigned char *) &adrcnt)[2] = atp_readb_io(dev, c, 0x12); 2786a3cebb6SOndrej Zary ((unsigned char *) &adrcnt)[1] = atp_readb_io(dev, c, 0x13); 2796a3cebb6SOndrej Zary ((unsigned char *) &adrcnt)[0] = atp_readb_io(dev, c, 0x14); 2801da177e4SLinus Torvalds k = dev->id[c][target_id].last_len; 2811da177e4SLinus Torvalds k -= adrcnt; 2821da177e4SLinus Torvalds dev->id[c][target_id].tran_len = k; 2831da177e4SLinus Torvalds dev->id[c][target_id].last_len = adrcnt; 2846a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 2851da177e4SLinus Torvalds dev->in_int[c] = 0; 28678614ecdSOndrej Zary return IRQ_HANDLED; 2871da177e4SLinus Torvalds } else { 2881da177e4SLinus Torvalds #ifdef ED_DBGP 2891da177e4SLinus Torvalds printk("cmdp != 0x41\n"); 2901da177e4SLinus Torvalds #endif 2916a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x10, 0x46); 2921da177e4SLinus Torvalds dev->id[c][target_id].dirct = 0x00; 2936a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x12, 0x00); 2946a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x13, 0x00); 2956a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x14, 0x00); 2966a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 2971da177e4SLinus Torvalds dev->in_int[c] = 0; 29878614ecdSOndrej Zary return IRQ_HANDLED; 2991da177e4SLinus Torvalds } 3001da177e4SLinus Torvalds } 3011da177e4SLinus Torvalds if (dev->last_cmd[c] != 0xff) { 3021da177e4SLinus Torvalds dev->last_cmd[c] |= 0x40; 3031da177e4SLinus Torvalds } 3041da177e4SLinus Torvalds if (dev->dev_id == ATP885_DEVID) { 3056a3cebb6SOndrej Zary j = atp_readb_base(dev, 0x29) & 0xfe; 3066a3cebb6SOndrej Zary atp_writeb_base(dev, 0x29, j); 3073a38e53eSOndrej Zary } else 3086a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x10, 0x45); 3091da177e4SLinus Torvalds 3106a3cebb6SOndrej Zary target_id = atp_readb_io(dev, c, 0x16); 3111da177e4SLinus Torvalds /* 3121da177e4SLinus Torvalds * Remap wide identifiers 3131da177e4SLinus Torvalds */ 3141da177e4SLinus Torvalds if ((target_id & 0x10) != 0) { 3151da177e4SLinus Torvalds target_id = (target_id & 0x07) | 0x08; 3161da177e4SLinus Torvalds } else { 3171da177e4SLinus Torvalds target_id &= 0x07; 3181da177e4SLinus Torvalds } 3193a38e53eSOndrej Zary if (dev->dev_id == ATP885_DEVID) 3206a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x10, 0x45); 3211da177e4SLinus Torvalds workreq = dev->id[c][target_id].curr_req; 3221da177e4SLinus Torvalds #ifdef ED_DBGP 323017560fcSJeff Garzik scmd_printk(KERN_DEBUG, workreq, "CDB"); 3241da177e4SLinus Torvalds for (l = 0; l < workreq->cmd_len; l++) 3251da177e4SLinus Torvalds printk(KERN_DEBUG " %x",workreq->cmnd[l]); 326017560fcSJeff Garzik printk("\n"); 3271da177e4SLinus Torvalds #endif 3281da177e4SLinus Torvalds 3296a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x0f, lun); 3306a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x11, dev->id[c][target_id].devsp); 3311da177e4SLinus Torvalds adrcnt = dev->id[c][target_id].tran_len; 3321da177e4SLinus Torvalds k = dev->id[c][target_id].last_len; 3331da177e4SLinus Torvalds 3346a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x12, ((unsigned char *) &k)[2]); 3356a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x13, ((unsigned char *) &k)[1]); 3366a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x14, ((unsigned char *) &k)[0]); 3371da177e4SLinus Torvalds #ifdef ED_DBGP 3386a3cebb6SOndrej Zary printk("k %x, k[0] 0x%x k[1] 0x%x k[2] 0x%x\n", k, atp_readb_io(dev, c, 0x14), atp_readb_io(dev, c, 0x13), atp_readb_io(dev, c, 0x12)); 3391da177e4SLinus Torvalds #endif 3401da177e4SLinus Torvalds /* Remap wide */ 3411da177e4SLinus Torvalds j = target_id; 3421da177e4SLinus Torvalds if (target_id > 7) { 3431da177e4SLinus Torvalds j = (j & 0x07) | 0x40; 3441da177e4SLinus Torvalds } 3451da177e4SLinus Torvalds /* Add direction */ 3461da177e4SLinus Torvalds j |= dev->id[c][target_id].dirct; 3476a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x15, j); 3486a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x16, 0x80); 3491da177e4SLinus Torvalds 3501da177e4SLinus Torvalds /* enable 32 bit fifo transfer */ 3511da177e4SLinus Torvalds if (dev->dev_id == ATP885_DEVID) { 3526a3cebb6SOndrej Zary i = atp_readb_pci(dev, c, 1) & 0xf3; 3531da177e4SLinus Torvalds //j=workreq->cmnd[0]; 3541da177e4SLinus Torvalds if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) { 3551da177e4SLinus Torvalds i |= 0x0c; 3561da177e4SLinus Torvalds } 3576a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 1, i); 3581da177e4SLinus Torvalds } else if ((dev->dev_id == ATP880_DEVID1) || 3591da177e4SLinus Torvalds (dev->dev_id == ATP880_DEVID2) ) { 3606a3cebb6SOndrej Zary if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) 3616a3cebb6SOndrej Zary atp_writeb_base(dev, 0x3b, (atp_readb_base(dev, 0x3b) & 0x3f) | 0xc0); 3626a3cebb6SOndrej Zary else 3636a3cebb6SOndrej Zary atp_writeb_base(dev, 0x3b, atp_readb_base(dev, 0x3b) & 0x3f); 3641da177e4SLinus Torvalds } else { 3656a3cebb6SOndrej Zary if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) 366c751d9f1SOndrej Zary atp_writeb_base(dev, 0x3a, (atp_readb_base(dev, 0x3a) & 0xf3) | 0x08); 3676a3cebb6SOndrej Zary else 368c751d9f1SOndrej Zary atp_writeb_base(dev, 0x3a, atp_readb_base(dev, 0x3a) & 0xf3); 3691da177e4SLinus Torvalds } 3701da177e4SLinus Torvalds j = 0; 3711da177e4SLinus Torvalds id = 1; 3721da177e4SLinus Torvalds id = id << target_id; 3731da177e4SLinus Torvalds /* 3741da177e4SLinus Torvalds * Is this a wide device 3751da177e4SLinus Torvalds */ 3761da177e4SLinus Torvalds if ((id & dev->wide_id[c]) != 0) { 3771da177e4SLinus Torvalds j |= 0x01; 3781da177e4SLinus Torvalds } 3796a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x1b, j); 3806a3cebb6SOndrej Zary while ((atp_readb_io(dev, c, 0x1b) & 0x01) != j) 3816a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x1b, j); 3821da177e4SLinus Torvalds if (dev->id[c][target_id].last_len == 0) { 3836a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 3841da177e4SLinus Torvalds dev->in_int[c] = 0; 3851da177e4SLinus Torvalds #ifdef ED_DBGP 3861da177e4SLinus Torvalds printk("dev->id[c][target_id].last_len = 0\n"); 3871da177e4SLinus Torvalds #endif 38878614ecdSOndrej Zary return IRQ_HANDLED; 3891da177e4SLinus Torvalds } 3901da177e4SLinus Torvalds #ifdef ED_DBGP 3911da177e4SLinus Torvalds printk("target_id = %d adrcnt = %d\n",target_id,adrcnt); 3921da177e4SLinus Torvalds #endif 3931da177e4SLinus Torvalds prd = dev->id[c][target_id].prd_pos; 3941da177e4SLinus Torvalds while (adrcnt != 0) { 3951da177e4SLinus Torvalds id = ((unsigned short int *)prd)[2]; 3961da177e4SLinus Torvalds if (id == 0) { 3971da177e4SLinus Torvalds k = 0x10000; 3981da177e4SLinus Torvalds } else { 3991da177e4SLinus Torvalds k = id; 4001da177e4SLinus Torvalds } 4011da177e4SLinus Torvalds if (k > adrcnt) { 4021da177e4SLinus Torvalds ((unsigned short int *)prd)[2] = (unsigned short int) 4031da177e4SLinus Torvalds (k - adrcnt); 4041da177e4SLinus Torvalds ((unsigned long *)prd)[0] += adrcnt; 4051da177e4SLinus Torvalds adrcnt = 0; 4061da177e4SLinus Torvalds dev->id[c][target_id].prd_pos = prd; 4071da177e4SLinus Torvalds } else { 4081da177e4SLinus Torvalds adrcnt -= k; 4091da177e4SLinus Torvalds dev->id[c][target_id].prdaddr += 0x08; 4101da177e4SLinus Torvalds prd += 0x08; 4111da177e4SLinus Torvalds if (adrcnt == 0) { 4121da177e4SLinus Torvalds dev->id[c][target_id].prd_pos = prd; 4131da177e4SLinus Torvalds } 4141da177e4SLinus Torvalds } 4151da177e4SLinus Torvalds } 4166a3cebb6SOndrej Zary atp_writel_pci(dev, c, 0x04, dev->id[c][target_id].prdaddr); 4171da177e4SLinus Torvalds #ifdef ED_DBGP 4181da177e4SLinus Torvalds printk("dev->id[%d][%d].prdaddr 0x%8x\n", c, target_id, dev->id[c][target_id].prdaddr); 4191da177e4SLinus Torvalds #endif 420bc0fe4c9SOndrej Zary if (dev->dev_id != ATP885_DEVID) { 4216a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 2, 0x06); 4226a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 2, 0x00); 4231da177e4SLinus Torvalds } 4241da177e4SLinus Torvalds /* 4251da177e4SLinus Torvalds * Check transfer direction 4261da177e4SLinus Torvalds */ 4271da177e4SLinus Torvalds if (dev->id[c][target_id].dirct != 0) { 4286a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 4296a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 0, 0x01); 4301da177e4SLinus Torvalds dev->in_int[c] = 0; 4311da177e4SLinus Torvalds #ifdef ED_DBGP 4321da177e4SLinus Torvalds printk("status 0x80 return dirct != 0\n"); 4331da177e4SLinus Torvalds #endif 43478614ecdSOndrej Zary return IRQ_HANDLED; 4351da177e4SLinus Torvalds } 4366a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 4376a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 0, 0x09); 4381da177e4SLinus Torvalds dev->in_int[c] = 0; 4391da177e4SLinus Torvalds #ifdef ED_DBGP 4401da177e4SLinus Torvalds printk("status 0x80 return dirct = 0\n"); 4411da177e4SLinus Torvalds #endif 44278614ecdSOndrej Zary return IRQ_HANDLED; 4431da177e4SLinus Torvalds } 4441da177e4SLinus Torvalds 4451da177e4SLinus Torvalds /* 4461da177e4SLinus Torvalds * Current scsi request on this target 4471da177e4SLinus Torvalds */ 4481da177e4SLinus Torvalds 4491da177e4SLinus Torvalds workreq = dev->id[c][target_id].curr_req; 4501da177e4SLinus Torvalds 45178614ecdSOndrej Zary if (i == 0x42 || i == 0x16) { 4521da177e4SLinus Torvalds if ((dev->last_cmd[c] & 0xf0) != 0x40) { 4531da177e4SLinus Torvalds dev->last_cmd[c] = 0xff; 4541da177e4SLinus Torvalds } 45578614ecdSOndrej Zary if (i == 0x16) { 4566a3cebb6SOndrej Zary workreq->result = atp_readb_io(dev, c, 0x0f); 4571da177e4SLinus Torvalds if (((dev->r1f[c][target_id] & 0x10) != 0)&&(dev->dev_id==ATP885_DEVID)) { 4581da177e4SLinus Torvalds printk(KERN_WARNING "AEC67162 CRC ERROR !\n"); 45978614ecdSOndrej Zary workreq->result = 0x02; 4601da177e4SLinus Torvalds } 46178614ecdSOndrej Zary } else 46278614ecdSOndrej Zary workreq->result = 0x02; 46378614ecdSOndrej Zary 4641da177e4SLinus Torvalds if (dev->dev_id == ATP885_DEVID) { 4656a3cebb6SOndrej Zary j = atp_readb_base(dev, 0x29) | 0x01; 4666a3cebb6SOndrej Zary atp_writeb_base(dev, 0x29, j); 4671da177e4SLinus Torvalds } 4681da177e4SLinus Torvalds /* 4691da177e4SLinus Torvalds * Complete the command 4701da177e4SLinus Torvalds */ 471fe7ed98fSBoaz Harrosh scsi_dma_unmap(workreq); 472fe7ed98fSBoaz Harrosh 4731da177e4SLinus Torvalds spin_lock_irqsave(dev->host->host_lock, flags); 4741da177e4SLinus Torvalds (*workreq->scsi_done) (workreq); 4751da177e4SLinus Torvalds #ifdef ED_DBGP 4761da177e4SLinus Torvalds printk("workreq->scsi_done\n"); 4771da177e4SLinus Torvalds #endif 4781da177e4SLinus Torvalds /* 4791da177e4SLinus Torvalds * Clear it off the queue 4801da177e4SLinus Torvalds */ 4811da177e4SLinus Torvalds dev->id[c][target_id].curr_req = NULL; 4821da177e4SLinus Torvalds dev->working[c]--; 4831da177e4SLinus Torvalds spin_unlock_irqrestore(dev->host->host_lock, flags); 4841da177e4SLinus Torvalds /* 4851da177e4SLinus Torvalds * Take it back wide 4861da177e4SLinus Torvalds */ 4871da177e4SLinus Torvalds if (dev->wide_id[c] != 0) { 4886a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x1b, 0x01); 4896a3cebb6SOndrej Zary while ((atp_readb_io(dev, c, 0x1b) & 0x01) != 0x01) 4906a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x1b, 0x01); 4911da177e4SLinus Torvalds } 4921da177e4SLinus Torvalds /* 4931da177e4SLinus Torvalds * If there is stuff to send and nothing going then send it 4941da177e4SLinus Torvalds */ 4951da177e4SLinus Torvalds spin_lock_irqsave(dev->host->host_lock, flags); 4961da177e4SLinus Torvalds if (((dev->last_cmd[c] != 0xff) || (dev->quhd[c] != dev->quend[c])) && 4971da177e4SLinus Torvalds (dev->in_snd[c] == 0)) { 4981da177e4SLinus Torvalds #ifdef ED_DBGP 4991da177e4SLinus Torvalds printk("Call sent_s870(scsi_done)\n"); 5001da177e4SLinus Torvalds #endif 5011da177e4SLinus Torvalds send_s870(dev,c); 5021da177e4SLinus Torvalds } 5031da177e4SLinus Torvalds spin_unlock_irqrestore(dev->host->host_lock, flags); 5041da177e4SLinus Torvalds dev->in_int[c] = 0; 50578614ecdSOndrej Zary return IRQ_HANDLED; 5061da177e4SLinus Torvalds } 5071da177e4SLinus Torvalds if ((dev->last_cmd[c] & 0xf0) != 0x40) { 5081da177e4SLinus Torvalds dev->last_cmd[c] = 0xff; 5091da177e4SLinus Torvalds } 5101da177e4SLinus Torvalds if (i == 0x4f) { 5111da177e4SLinus Torvalds i = 0x89; 5121da177e4SLinus Torvalds } 5131da177e4SLinus Torvalds i &= 0x0f; 5141da177e4SLinus Torvalds if (i == 0x09) { 5156a3cebb6SOndrej Zary atp_writel_pci(dev, c, 4, dev->id[c][target_id].prdaddr); 5166a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 2, 0x06); 5176a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 2, 0x00); 5186a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x10, 0x41); 5191da177e4SLinus Torvalds if (dev->dev_id == ATP885_DEVID) { 5201da177e4SLinus Torvalds k = dev->id[c][target_id].last_len; 5216a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x12, ((unsigned char *) (&k))[2]); 5226a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x13, ((unsigned char *) (&k))[1]); 5236a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x14, ((unsigned char *) (&k))[0]); 5241da177e4SLinus Torvalds dev->id[c][target_id].dirct = 0x00; 5251da177e4SLinus Torvalds } else { 5261da177e4SLinus Torvalds dev->id[c][target_id].dirct = 0x00; 5271da177e4SLinus Torvalds } 5286a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 5296a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 0, 0x09); 5301da177e4SLinus Torvalds dev->in_int[c] = 0; 53178614ecdSOndrej Zary return IRQ_HANDLED; 5321da177e4SLinus Torvalds } 5331da177e4SLinus Torvalds if (i == 0x08) { 5346a3cebb6SOndrej Zary atp_writel_pci(dev, c, 4, dev->id[c][target_id].prdaddr); 5356a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 2, 0x06); 5366a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 2, 0x00); 5376a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x10, 0x41); 5381da177e4SLinus Torvalds if (dev->dev_id == ATP885_DEVID) { 5391da177e4SLinus Torvalds k = dev->id[c][target_id].last_len; 5406a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x12, ((unsigned char *) (&k))[2]); 5416a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x13, ((unsigned char *) (&k))[1]); 5426a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x14, ((unsigned char *) (&k))[0]); 5431da177e4SLinus Torvalds } 5446a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x15, atp_readb_io(dev, c, 0x15) | 0x20); 5451da177e4SLinus Torvalds dev->id[c][target_id].dirct = 0x20; 5466a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 5476a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 0, 0x01); 5481da177e4SLinus Torvalds dev->in_int[c] = 0; 54978614ecdSOndrej Zary return IRQ_HANDLED; 5501da177e4SLinus Torvalds } 5516a3cebb6SOndrej Zary if (i == 0x0a) 5526a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x10, 0x30); 5536a3cebb6SOndrej Zary else 5546a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x10, 0x46); 5551da177e4SLinus Torvalds dev->id[c][target_id].dirct = 0x00; 5566a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x12, 0x00); 5576a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x13, 0x00); 5586a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x14, 0x00); 5596a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 5601da177e4SLinus Torvalds } 56178614ecdSOndrej Zary dev->in_int[c] = 0; 5621da177e4SLinus Torvalds 5631da177e4SLinus Torvalds return IRQ_HANDLED; 5641da177e4SLinus Torvalds } 5651da177e4SLinus Torvalds /** 5661da177e4SLinus Torvalds * atp870u_queuecommand - Queue SCSI command 5671da177e4SLinus Torvalds * @req_p: request block 5681da177e4SLinus Torvalds * @done: completion function 5691da177e4SLinus Torvalds * 5701da177e4SLinus Torvalds * Queue a command to the ATP queue. Called with the host lock held. 5711da177e4SLinus Torvalds */ 572f281233dSJeff Garzik static int atp870u_queuecommand_lck(struct scsi_cmnd *req_p, 5731da177e4SLinus Torvalds void (*done) (struct scsi_cmnd *)) 5741da177e4SLinus Torvalds { 5751da177e4SLinus Torvalds unsigned char c; 5763b836464SOndrej Zary unsigned int m; 5771da177e4SLinus Torvalds struct atp_unit *dev; 5781da177e4SLinus Torvalds struct Scsi_Host *host; 5791da177e4SLinus Torvalds 580422c0d61SJeff Garzik c = scmd_channel(req_p); 5811da177e4SLinus Torvalds req_p->sense_buffer[0]=0; 582fe7ed98fSBoaz Harrosh scsi_set_resid(req_p, 0); 583422c0d61SJeff Garzik if (scmd_channel(req_p) > 1) { 5841da177e4SLinus Torvalds req_p->result = 0x00040000; 5851da177e4SLinus Torvalds done(req_p); 5861da177e4SLinus Torvalds #ifdef ED_DBGP 5871da177e4SLinus Torvalds printk("atp870u_queuecommand : req_p->device->channel > 1\n"); 5881da177e4SLinus Torvalds #endif 5891da177e4SLinus Torvalds return 0; 5901da177e4SLinus Torvalds } 5911da177e4SLinus Torvalds 5921da177e4SLinus Torvalds host = req_p->device->host; 5931da177e4SLinus Torvalds dev = (struct atp_unit *)&host->hostdata; 5941da177e4SLinus Torvalds 5951da177e4SLinus Torvalds 5961da177e4SLinus Torvalds 5971da177e4SLinus Torvalds m = 1; 598422c0d61SJeff Garzik m = m << scmd_id(req_p); 5991da177e4SLinus Torvalds 6001da177e4SLinus Torvalds /* 6011da177e4SLinus Torvalds * Fake a timeout for missing targets 6021da177e4SLinus Torvalds */ 6031da177e4SLinus Torvalds 6041da177e4SLinus Torvalds if ((m & dev->active_id[c]) == 0) { 6051da177e4SLinus Torvalds req_p->result = 0x00040000; 6061da177e4SLinus Torvalds done(req_p); 6071da177e4SLinus Torvalds return 0; 6081da177e4SLinus Torvalds } 6091da177e4SLinus Torvalds 6101da177e4SLinus Torvalds if (done) { 6111da177e4SLinus Torvalds req_p->scsi_done = done; 6121da177e4SLinus Torvalds } else { 6131da177e4SLinus Torvalds #ifdef ED_DBGP 6141da177e4SLinus Torvalds printk( "atp870u_queuecommand: done can't be NULL\n"); 6151da177e4SLinus Torvalds #endif 6161da177e4SLinus Torvalds req_p->result = 0; 6171da177e4SLinus Torvalds done(req_p); 6181da177e4SLinus Torvalds return 0; 6191da177e4SLinus Torvalds } 6201da177e4SLinus Torvalds 6211da177e4SLinus Torvalds /* 6221da177e4SLinus Torvalds * Count new command 6231da177e4SLinus Torvalds */ 6241da177e4SLinus Torvalds dev->quend[c]++; 6251da177e4SLinus Torvalds if (dev->quend[c] >= qcnt) { 6261da177e4SLinus Torvalds dev->quend[c] = 0; 6271da177e4SLinus Torvalds } 6281da177e4SLinus Torvalds 6291da177e4SLinus Torvalds /* 6301da177e4SLinus Torvalds * Check queue state 6311da177e4SLinus Torvalds */ 6321da177e4SLinus Torvalds if (dev->quhd[c] == dev->quend[c]) { 6331da177e4SLinus Torvalds if (dev->quend[c] == 0) { 6341da177e4SLinus Torvalds dev->quend[c] = qcnt; 6351da177e4SLinus Torvalds } 6361da177e4SLinus Torvalds #ifdef ED_DBGP 6371da177e4SLinus Torvalds printk("atp870u_queuecommand : dev->quhd[c] == dev->quend[c]\n"); 6381da177e4SLinus Torvalds #endif 6391da177e4SLinus Torvalds dev->quend[c]--; 6401da177e4SLinus Torvalds req_p->result = 0x00020000; 6411da177e4SLinus Torvalds done(req_p); 6421da177e4SLinus Torvalds return 0; 6431da177e4SLinus Torvalds } 6441da177e4SLinus Torvalds dev->quereq[c][dev->quend[c]] = req_p; 6451da177e4SLinus Torvalds #ifdef ED_DBGP 6466a3cebb6SOndrej Zary printk("dev->ioport[c] = %x atp_readb_io(dev, c, 0x1c) = %x dev->in_int[%d] = %d dev->in_snd[%d] = %d\n",dev->ioport[c],atp_readb_io(dev, c, 0x1c),c,dev->in_int[c],c,dev->in_snd[c]); 6471da177e4SLinus Torvalds #endif 6486a3cebb6SOndrej Zary if ((atp_readb_io(dev, c, 0x1c) == 0) && (dev->in_int[c] == 0) && (dev->in_snd[c] == 0)) { 6491da177e4SLinus Torvalds #ifdef ED_DBGP 6501da177e4SLinus Torvalds printk("Call sent_s870(atp870u_queuecommand)\n"); 6511da177e4SLinus Torvalds #endif 6521da177e4SLinus Torvalds send_s870(dev,c); 6531da177e4SLinus Torvalds } 6541da177e4SLinus Torvalds #ifdef ED_DBGP 6551da177e4SLinus Torvalds printk("atp870u_queuecommand : exit\n"); 6561da177e4SLinus Torvalds #endif 6571da177e4SLinus Torvalds return 0; 6581da177e4SLinus Torvalds } 6591da177e4SLinus Torvalds 660f281233dSJeff Garzik static DEF_SCSI_QCMD(atp870u_queuecommand) 661f281233dSJeff Garzik 6621da177e4SLinus Torvalds /** 6631da177e4SLinus Torvalds * send_s870 - send a command to the controller 6641da177e4SLinus Torvalds * @host: host 6651da177e4SLinus Torvalds * 6661da177e4SLinus Torvalds * On entry there is work queued to be done. We move some of that work to the 6671da177e4SLinus Torvalds * controller itself. 6681da177e4SLinus Torvalds * 6691da177e4SLinus Torvalds * Caller holds the host lock. 6701da177e4SLinus Torvalds */ 6711da177e4SLinus Torvalds static void send_s870(struct atp_unit *dev,unsigned char c) 6721da177e4SLinus Torvalds { 673468b8968SOndrej Zary struct scsi_cmnd *workreq = NULL; 6741da177e4SLinus Torvalds unsigned int i;//,k; 6751da177e4SLinus Torvalds unsigned char j, target_id; 6761da177e4SLinus Torvalds unsigned char *prd; 677c2bab403SOndrej Zary unsigned short int w; 6781da177e4SLinus Torvalds unsigned long l, bttl = 0; 6791da177e4SLinus Torvalds unsigned long sg_count; 6801da177e4SLinus Torvalds 6811da177e4SLinus Torvalds if (dev->in_snd[c] != 0) { 6821da177e4SLinus Torvalds #ifdef ED_DBGP 6831da177e4SLinus Torvalds printk("cmnd in_snd\n"); 6841da177e4SLinus Torvalds #endif 6851da177e4SLinus Torvalds return; 6861da177e4SLinus Torvalds } 6871da177e4SLinus Torvalds #ifdef ED_DBGP 6881da177e4SLinus Torvalds printk("Sent_s870 enter\n"); 6891da177e4SLinus Torvalds #endif 6901da177e4SLinus Torvalds dev->in_snd[c] = 1; 6911da177e4SLinus Torvalds if ((dev->last_cmd[c] != 0xff) && ((dev->last_cmd[c] & 0x40) != 0)) { 6921da177e4SLinus Torvalds dev->last_cmd[c] &= 0x0f; 6931da177e4SLinus Torvalds workreq = dev->id[c][dev->last_cmd[c]].curr_req; 694468b8968SOndrej Zary if (!workreq) { 6951da177e4SLinus Torvalds dev->last_cmd[c] = 0xff; 6961da177e4SLinus Torvalds if (dev->quhd[c] == dev->quend[c]) { 6971da177e4SLinus Torvalds dev->in_snd[c] = 0; 6981da177e4SLinus Torvalds return; 6991da177e4SLinus Torvalds } 7001da177e4SLinus Torvalds } 701468b8968SOndrej Zary } 702468b8968SOndrej Zary if (!workreq) { 7031da177e4SLinus Torvalds if ((dev->last_cmd[c] != 0xff) && (dev->working[c] != 0)) { 7041da177e4SLinus Torvalds dev->in_snd[c] = 0; 7051da177e4SLinus Torvalds return; 7061da177e4SLinus Torvalds } 7071da177e4SLinus Torvalds dev->working[c]++; 7081da177e4SLinus Torvalds j = dev->quhd[c]; 7091da177e4SLinus Torvalds dev->quhd[c]++; 710468b8968SOndrej Zary if (dev->quhd[c] >= qcnt) 7111da177e4SLinus Torvalds dev->quhd[c] = 0; 7121da177e4SLinus Torvalds workreq = dev->quereq[c][dev->quhd[c]]; 713468b8968SOndrej Zary if (dev->id[c][scmd_id(workreq)].curr_req != NULL) { 7141da177e4SLinus Torvalds dev->quhd[c] = j; 7151da177e4SLinus Torvalds dev->working[c]--; 7161da177e4SLinus Torvalds dev->in_snd[c] = 0; 7171da177e4SLinus Torvalds return; 7181da177e4SLinus Torvalds } 719468b8968SOndrej Zary dev->id[c][scmd_id(workreq)].curr_req = workreq; 720468b8968SOndrej Zary dev->last_cmd[c] = scmd_id(workreq); 7211da177e4SLinus Torvalds } 7226a3cebb6SOndrej Zary if ((atp_readb_io(dev, c, 0x1f) & 0xb0) != 0 || atp_readb_io(dev, c, 0x1c) != 0) { 7231da177e4SLinus Torvalds #ifdef ED_DBGP 7241da177e4SLinus Torvalds printk("Abort to Send\n"); 7251da177e4SLinus Torvalds #endif 7261da177e4SLinus Torvalds dev->last_cmd[c] |= 0x40; 7271da177e4SLinus Torvalds dev->in_snd[c] = 0; 7281da177e4SLinus Torvalds return; 729468b8968SOndrej Zary } 7301da177e4SLinus Torvalds #ifdef ED_DBGP 7311da177e4SLinus Torvalds printk("OK to Send\n"); 732422c0d61SJeff Garzik scmd_printk(KERN_DEBUG, workreq, "CDB"); 7331da177e4SLinus Torvalds for(i=0;i<workreq->cmd_len;i++) { 7341da177e4SLinus Torvalds printk(" %x",workreq->cmnd[i]); 7351da177e4SLinus Torvalds } 736422c0d61SJeff Garzik printk("\n"); 7371da177e4SLinus Torvalds #endif 738fe7ed98fSBoaz Harrosh l = scsi_bufflen(workreq); 739fe7ed98fSBoaz Harrosh 7401da177e4SLinus Torvalds if (dev->dev_id == ATP885_DEVID) { 7416a3cebb6SOndrej Zary j = atp_readb_base(dev, 0x29) & 0xfe; 7426a3cebb6SOndrej Zary atp_writeb_base(dev, 0x29, j); 743422c0d61SJeff Garzik dev->r1f[c][scmd_id(workreq)] = 0; 7441da177e4SLinus Torvalds } 7451da177e4SLinus Torvalds 7461da177e4SLinus Torvalds if (workreq->cmnd[0] == READ_CAPACITY) { 747fe7ed98fSBoaz Harrosh if (l > 8) 748fe7ed98fSBoaz Harrosh l = 8; 7491da177e4SLinus Torvalds } 7501da177e4SLinus Torvalds if (workreq->cmnd[0] == 0x00) { 751fe7ed98fSBoaz Harrosh l = 0; 7521da177e4SLinus Torvalds } 7531da177e4SLinus Torvalds 7541da177e4SLinus Torvalds j = 0; 755422c0d61SJeff Garzik target_id = scmd_id(workreq); 7561da177e4SLinus Torvalds 7571da177e4SLinus Torvalds /* 7581da177e4SLinus Torvalds * Wide ? 7591da177e4SLinus Torvalds */ 7601da177e4SLinus Torvalds w = 1; 7611da177e4SLinus Torvalds w = w << target_id; 7621da177e4SLinus Torvalds if ((w & dev->wide_id[c]) != 0) { 7631da177e4SLinus Torvalds j |= 0x01; 7641da177e4SLinus Torvalds } 7656a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x1b, j); 7666a3cebb6SOndrej Zary while ((atp_readb_io(dev, c, 0x1b) & 0x01) != j) { 7676a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 0x1b, j); 7681da177e4SLinus Torvalds #ifdef ED_DBGP 7691da177e4SLinus Torvalds printk("send_s870 while loop 1\n"); 7701da177e4SLinus Torvalds #endif 7711da177e4SLinus Torvalds } 7721da177e4SLinus Torvalds /* 7731da177e4SLinus Torvalds * Write the command 7741da177e4SLinus Torvalds */ 7751da177e4SLinus Torvalds 7766a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x00, workreq->cmd_len); 7776a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x01, 0x2c); 7786a3cebb6SOndrej Zary if (dev->dev_id == ATP885_DEVID) 7796a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x02, 0x7f); 7806a3cebb6SOndrej Zary else 7816a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x02, 0xcf); 7826a3cebb6SOndrej Zary for (i = 0; i < workreq->cmd_len; i++) 7836a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x03 + i, workreq->cmnd[i]); 7846a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x0f, workreq->device->lun); 7851da177e4SLinus Torvalds /* 7861da177e4SLinus Torvalds * Write the target 7871da177e4SLinus Torvalds */ 7886a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x11, dev->id[c][target_id].devsp); 7891da177e4SLinus Torvalds #ifdef ED_DBGP 7901da177e4SLinus Torvalds printk("dev->id[%d][%d].devsp = %2x\n",c,target_id,dev->id[c][target_id].devsp); 7911da177e4SLinus Torvalds #endif 7921da177e4SLinus Torvalds 793fe7ed98fSBoaz Harrosh sg_count = scsi_dma_map(workreq); 7941da177e4SLinus Torvalds /* 7951da177e4SLinus Torvalds * Write transfer size 7961da177e4SLinus Torvalds */ 7976a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x12, ((unsigned char *) (&l))[2]); 7986a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x13, ((unsigned char *) (&l))[1]); 7996a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x14, ((unsigned char *) (&l))[0]); 8001da177e4SLinus Torvalds j = target_id; 8011da177e4SLinus Torvalds dev->id[c][j].last_len = l; 8021da177e4SLinus Torvalds dev->id[c][j].tran_len = 0; 8031da177e4SLinus Torvalds #ifdef ED_DBGP 8041da177e4SLinus Torvalds printk("dev->id[%2d][%2d].last_len = %d\n",c,j,dev->id[c][j].last_len); 8051da177e4SLinus Torvalds #endif 8061da177e4SLinus Torvalds /* 8071da177e4SLinus Torvalds * Flip the wide bits 8081da177e4SLinus Torvalds */ 8091da177e4SLinus Torvalds if ((j & 0x08) != 0) { 8101da177e4SLinus Torvalds j = (j & 0x07) | 0x40; 8111da177e4SLinus Torvalds } 8121da177e4SLinus Torvalds /* 8131da177e4SLinus Torvalds * Check transfer direction 8141da177e4SLinus Torvalds */ 8156a3cebb6SOndrej Zary if (workreq->sc_data_direction == DMA_TO_DEVICE) 8166a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x15, j | 0x20); 8176a3cebb6SOndrej Zary else 8186a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x15, j); 8196a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x16, atp_readb_io(dev, c, 0x16) | 0x80); 8206a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x16, 0x80); 8211da177e4SLinus Torvalds dev->id[c][target_id].dirct = 0; 8221da177e4SLinus Torvalds if (l == 0) { 8236a3cebb6SOndrej Zary if (atp_readb_io(dev, c, 0x1c) == 0) { 8241da177e4SLinus Torvalds #ifdef ED_DBGP 8251da177e4SLinus Torvalds printk("change SCSI_CMD_REG 0x08\n"); 8261da177e4SLinus Torvalds #endif 8276a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 8286a3cebb6SOndrej Zary } else 8291da177e4SLinus Torvalds dev->last_cmd[c] |= 0x40; 8301da177e4SLinus Torvalds dev->in_snd[c] = 0; 8311da177e4SLinus Torvalds return; 8321da177e4SLinus Torvalds } 8331da177e4SLinus Torvalds prd = dev->id[c][target_id].prd_table; 8341da177e4SLinus Torvalds dev->id[c][target_id].prd_pos = prd; 8351da177e4SLinus Torvalds 8361da177e4SLinus Torvalds /* 8371da177e4SLinus Torvalds * Now write the request list. Either as scatter/gather or as 8381da177e4SLinus Torvalds * a linear chain. 8391da177e4SLinus Torvalds */ 8401da177e4SLinus Torvalds 841fe7ed98fSBoaz Harrosh if (l) { 842fe7ed98fSBoaz Harrosh struct scatterlist *sgpnt; 8431da177e4SLinus Torvalds i = 0; 844fe7ed98fSBoaz Harrosh scsi_for_each_sg(workreq, sgpnt, sg_count, j) { 845fe7ed98fSBoaz Harrosh bttl = sg_dma_address(sgpnt); 846fe7ed98fSBoaz Harrosh l=sg_dma_len(sgpnt); 8471da177e4SLinus Torvalds #ifdef ED_DBGP 8481da177e4SLinus Torvalds printk("1. bttl %x, l %x\n",bttl, l); 8491da177e4SLinus Torvalds #endif 8501da177e4SLinus Torvalds while (l > 0x10000) { 8511da177e4SLinus Torvalds (((u16 *) (prd))[i + 3]) = 0x0000; 8521da177e4SLinus Torvalds (((u16 *) (prd))[i + 2]) = 0x0000; 8531da177e4SLinus Torvalds (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl); 8541da177e4SLinus Torvalds l -= 0x10000; 8551da177e4SLinus Torvalds bttl += 0x10000; 8561da177e4SLinus Torvalds i += 0x04; 8571da177e4SLinus Torvalds } 8581da177e4SLinus Torvalds (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl); 8591da177e4SLinus Torvalds (((u16 *) (prd))[i + 2]) = cpu_to_le16(l); 8601da177e4SLinus Torvalds (((u16 *) (prd))[i + 3]) = 0; 8611da177e4SLinus Torvalds i += 0x04; 8621da177e4SLinus Torvalds } 8631da177e4SLinus Torvalds (((u16 *) (prd))[i - 1]) = cpu_to_le16(0x8000); 8641da177e4SLinus Torvalds #ifdef ED_DBGP 8651da177e4SLinus Torvalds printk("prd %4x %4x %4x %4x\n",(((unsigned short int *)prd)[0]),(((unsigned short int *)prd)[1]),(((unsigned short int *)prd)[2]),(((unsigned short int *)prd)[3])); 8661da177e4SLinus Torvalds printk("2. bttl %x, l %x\n",bttl, l); 8671da177e4SLinus Torvalds #endif 8681da177e4SLinus Torvalds } 8691da177e4SLinus Torvalds #ifdef ED_DBGP 870c2bab403SOndrej Zary printk("send_s870: prdaddr_2 0x%8x target_id %d\n", dev->id[c][target_id].prdaddr,target_id); 8711da177e4SLinus Torvalds #endif 872b5683557SJames Bottomley dev->id[c][target_id].prdaddr = dev->id[c][target_id].prd_bus; 8736a3cebb6SOndrej Zary atp_writel_pci(dev, c, 4, dev->id[c][target_id].prdaddr); 8746a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 2, 0x06); 8756a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 2, 0x00); 8761da177e4SLinus Torvalds if (dev->dev_id == ATP885_DEVID) { 8776a3cebb6SOndrej Zary j = atp_readb_pci(dev, c, 1) & 0xf3; 8781da177e4SLinus Torvalds if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || 8791da177e4SLinus Torvalds (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) { 8801da177e4SLinus Torvalds j |= 0x0c; 8811da177e4SLinus Torvalds } 8826a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 1, j); 8831da177e4SLinus Torvalds } else if ((dev->dev_id == ATP880_DEVID1) || 8841da177e4SLinus Torvalds (dev->dev_id == ATP880_DEVID2)) { 8856a3cebb6SOndrej Zary if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) 8866a3cebb6SOndrej Zary atp_writeb_base(dev, 0x3b, (atp_readb_base(dev, 0x3b) & 0x3f) | 0xc0); 8876a3cebb6SOndrej Zary else 8886a3cebb6SOndrej Zary atp_writeb_base(dev, 0x3b, atp_readb_base(dev, 0x3b) & 0x3f); 8891da177e4SLinus Torvalds } else { 8906a3cebb6SOndrej Zary if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) 891c751d9f1SOndrej Zary atp_writeb_base(dev, 0x3a, (atp_readb_base(dev, 0x3a) & 0xf3) | 0x08); 8926a3cebb6SOndrej Zary else 893c751d9f1SOndrej Zary atp_writeb_base(dev, 0x3a, atp_readb_base(dev, 0x3a) & 0xf3); 8941da177e4SLinus Torvalds } 8951da177e4SLinus Torvalds 8961da177e4SLinus Torvalds if(workreq->sc_data_direction == DMA_TO_DEVICE) { 8971da177e4SLinus Torvalds dev->id[c][target_id].dirct = 0x20; 8986a3cebb6SOndrej Zary if (atp_readb_io(dev, c, 0x1c) == 0) { 8996a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 9006a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 0, 0x01); 9011da177e4SLinus Torvalds #ifdef ED_DBGP 9021da177e4SLinus Torvalds printk( "start DMA(to target)\n"); 9031da177e4SLinus Torvalds #endif 9041da177e4SLinus Torvalds } else { 9051da177e4SLinus Torvalds dev->last_cmd[c] |= 0x40; 9061da177e4SLinus Torvalds } 9071da177e4SLinus Torvalds dev->in_snd[c] = 0; 9081da177e4SLinus Torvalds return; 9091da177e4SLinus Torvalds } 9106a3cebb6SOndrej Zary if (atp_readb_io(dev, c, 0x1c) == 0) { 9116a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 9126a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 0, 0x09); 9131da177e4SLinus Torvalds #ifdef ED_DBGP 9141da177e4SLinus Torvalds printk( "start DMA(to host)\n"); 9151da177e4SLinus Torvalds #endif 9161da177e4SLinus Torvalds } else { 9171da177e4SLinus Torvalds dev->last_cmd[c] |= 0x40; 9181da177e4SLinus Torvalds } 9191da177e4SLinus Torvalds dev->in_snd[c] = 0; 9201da177e4SLinus Torvalds return; 9211da177e4SLinus Torvalds 9221da177e4SLinus Torvalds } 9231da177e4SLinus Torvalds 9241da177e4SLinus Torvalds static unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val) 9251da177e4SLinus Torvalds { 9261da177e4SLinus Torvalds unsigned short int i, k; 9271da177e4SLinus Torvalds unsigned char j; 9281da177e4SLinus Torvalds 9296a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, *val); 9301da177e4SLinus Torvalds for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */ 9316a3cebb6SOndrej Zary k = atp_readw_io(dev, 0, 0x1c); 9321da177e4SLinus Torvalds j = (unsigned char) (k >> 8); 933832e9ac6SOndrej Zary if ((k & 0x8000) != 0) /* DB7 all release? */ 934832e9ac6SOndrej Zary i = 0; 9351da177e4SLinus Torvalds } 9361da177e4SLinus Torvalds *val |= 0x4000; /* assert DB6 */ 9376a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, *val); 9381da177e4SLinus Torvalds *val &= 0xdfff; /* assert DB5 */ 9396a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, *val); 9401da177e4SLinus Torvalds for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */ 9416a3cebb6SOndrej Zary if ((atp_readw_io(dev, 0, 0x1c) & 0x2000) != 0) /* DB5 all release? */ 942832e9ac6SOndrej Zary i = 0; 9431da177e4SLinus Torvalds } 9441da177e4SLinus Torvalds *val |= 0x8000; /* no DB4-0, assert DB7 */ 9451da177e4SLinus Torvalds *val &= 0xe0ff; 9466a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, *val); 9471da177e4SLinus Torvalds *val &= 0xbfff; /* release DB6 */ 9486a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, *val); 9491da177e4SLinus Torvalds for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */ 9506a3cebb6SOndrej Zary if ((atp_readw_io(dev, 0, 0x1c) & 0x4000) != 0) /* DB6 all release? */ 951832e9ac6SOndrej Zary i = 0; 9521da177e4SLinus Torvalds } 9531da177e4SLinus Torvalds 9541da177e4SLinus Torvalds return j; 9551da177e4SLinus Torvalds } 9561da177e4SLinus Torvalds 957dd5a5f79SOndrej Zary static void tscam(struct Scsi_Host *host, bool wide_chip) 9581da177e4SLinus Torvalds { 9591da177e4SLinus Torvalds 9601da177e4SLinus Torvalds unsigned char i, j, k; 9611da177e4SLinus Torvalds unsigned long n; 9621da177e4SLinus Torvalds unsigned short int m, assignid_map, val; 9631da177e4SLinus Torvalds unsigned char mbuf[33], quintet[2]; 9641da177e4SLinus Torvalds struct atp_unit *dev = (struct atp_unit *)&host->hostdata; 9651da177e4SLinus Torvalds static unsigned char g2q_tab[8] = { 9661da177e4SLinus Torvalds 0x38, 0x31, 0x32, 0x2b, 0x34, 0x2d, 0x2e, 0x27 9671da177e4SLinus Torvalds }; 9681da177e4SLinus Torvalds 9691da177e4SLinus Torvalds /* I can't believe we need this before we've even done anything. Remove it 9701da177e4SLinus Torvalds * and see if anyone bitches. 9711da177e4SLinus Torvalds for (i = 0; i < 0x10; i++) { 9721da177e4SLinus Torvalds udelay(0xffff); 9731da177e4SLinus Torvalds } 9741da177e4SLinus Torvalds */ 9751da177e4SLinus Torvalds 9766a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 1, 0x08); 9776a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 2, 0x7f); 9786a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x11, 0x20); 9791da177e4SLinus Torvalds 9801da177e4SLinus Torvalds if ((dev->scam_on & 0x40) == 0) { 9811da177e4SLinus Torvalds return; 9821da177e4SLinus Torvalds } 9831da177e4SLinus Torvalds m = 1; 9841da177e4SLinus Torvalds m <<= dev->host_id[0]; 9851da177e4SLinus Torvalds j = 16; 986dd5a5f79SOndrej Zary if (!wide_chip) { 9871da177e4SLinus Torvalds m |= 0xff00; 9881da177e4SLinus Torvalds j = 8; 9891da177e4SLinus Torvalds } 9901da177e4SLinus Torvalds assignid_map = m; 9916a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x02, 0x02); /* 2*2=4ms,3EH 2/32*3E=3.9ms */ 9926a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x03, 0); 9936a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x04, 0); 9946a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x05, 0); 9956a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x06, 0); 9966a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x07, 0); 9976a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x08, 0); 9981da177e4SLinus Torvalds 9991da177e4SLinus Torvalds for (i = 0; i < j; i++) { 10001da177e4SLinus Torvalds m = 1; 10011da177e4SLinus Torvalds m = m << i; 10021da177e4SLinus Torvalds if ((m & assignid_map) != 0) { 10031da177e4SLinus Torvalds continue; 10041da177e4SLinus Torvalds } 10056a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x0f, 0); 10066a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x12, 0); 10076a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x13, 0); 10086a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x14, 0); 10091da177e4SLinus Torvalds if (i > 7) { 10101da177e4SLinus Torvalds k = (i & 0x07) | 0x40; 10111da177e4SLinus Torvalds } else { 10121da177e4SLinus Torvalds k = i; 10131da177e4SLinus Torvalds } 10146a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x15, k); 1015dd5a5f79SOndrej Zary if (wide_chip) 10166a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x1b, 0x01); 10176a3cebb6SOndrej Zary else 10186a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x1b, 0x00); 101958c4d046SOndrej Zary do { 10206a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x18, 0x09); 10211da177e4SLinus Torvalds 10226a3cebb6SOndrej Zary while ((atp_readb_io(dev, 0, 0x1f) & 0x80) == 0x00) 10231da177e4SLinus Torvalds cpu_relax(); 10246a3cebb6SOndrej Zary k = atp_readb_io(dev, 0, 0x17); 102558c4d046SOndrej Zary if ((k == 0x85) || (k == 0x42)) 102658c4d046SOndrej Zary break; 102758c4d046SOndrej Zary if (k != 0x16) 10286a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x10, 0x41); 102958c4d046SOndrej Zary } while (k != 0x16); 103058c4d046SOndrej Zary if ((k == 0x85) || (k == 0x42)) 103158c4d046SOndrej Zary continue; 10321da177e4SLinus Torvalds assignid_map |= m; 10331da177e4SLinus Torvalds 10341da177e4SLinus Torvalds } 10356a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x02, 0x7f); 10366a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x1b, 0x02); 10371da177e4SLinus Torvalds 10382bbbac45SOndrej Zary udelay(2); 10391da177e4SLinus Torvalds 10401da177e4SLinus Torvalds val = 0x0080; /* bsy */ 10416a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, val); 10421da177e4SLinus Torvalds val |= 0x0040; /* sel */ 10436a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, val); 10441da177e4SLinus Torvalds val |= 0x0004; /* msg */ 10456a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, val); 10462bbbac45SOndrej Zary udelay(2); /* 2 deskew delay(45ns*2=90ns) */ 10471da177e4SLinus Torvalds val &= 0x007f; /* no bsy */ 10486a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, val); 10491da177e4SLinus Torvalds mdelay(128); 10501da177e4SLinus Torvalds val &= 0x00fb; /* after 1ms no msg */ 10516a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, val); 10526a3cebb6SOndrej Zary while ((atp_readb_io(dev, 0, 0x1c) & 0x04) != 0) 105358c4d046SOndrej Zary ; 10542bbbac45SOndrej Zary udelay(2); 10551da177e4SLinus Torvalds udelay(100); 1056c7fcc089SOndrej Zary for (n = 0; n < 0x30000; n++) 10576a3cebb6SOndrej Zary if ((atp_readb_io(dev, 0, 0x1c) & 0x80) != 0) /* bsy ? */ 1058c7fcc089SOndrej Zary break; 1059c7fcc089SOndrej Zary if (n < 0x30000) 1060c7fcc089SOndrej Zary for (n = 0; n < 0x30000; n++) 10616a3cebb6SOndrej Zary if ((atp_readb_io(dev, 0, 0x1c) & 0x81) == 0x0081) { 10622bbbac45SOndrej Zary udelay(2); 10631da177e4SLinus Torvalds val |= 0x8003; /* io,cd,db7 */ 10646a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, val); 10652bbbac45SOndrej Zary udelay(2); 10661da177e4SLinus Torvalds val &= 0x00bf; /* no sel */ 10676a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, val); 10682bbbac45SOndrej Zary udelay(2); 1069c7fcc089SOndrej Zary break; 1070c7fcc089SOndrej Zary } 1071c7fcc089SOndrej Zary while (1) { 10720f6d93aaSMartin Michlmayr /* 10730f6d93aaSMartin Michlmayr * The funny division into multiple delays is to accomodate 10740f6d93aaSMartin Michlmayr * arches like ARM where udelay() multiplies its argument by 10750f6d93aaSMartin Michlmayr * a large number to initialize a loop counter. To avoid 10760f6d93aaSMartin Michlmayr * overflow, the maximum supported udelay is 2000 microseconds. 10770f6d93aaSMartin Michlmayr * 10780f6d93aaSMartin Michlmayr * XXX it would be more polite to find a way to use msleep() 10790f6d93aaSMartin Michlmayr */ 10800f6d93aaSMartin Michlmayr mdelay(2); 10810f6d93aaSMartin Michlmayr udelay(48); 10826a3cebb6SOndrej Zary if ((atp_readb_io(dev, 0, 0x1c) & 0x80) == 0x00) { /* bsy ? */ 10836a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, 0); 10846a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x1b, 0); 10856a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x15, 0); 10866a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x18, 0x09); 10876a3cebb6SOndrej Zary while ((atp_readb_io(dev, 0, 0x1f) & 0x80) == 0) 10881da177e4SLinus Torvalds cpu_relax(); 10896a3cebb6SOndrej Zary atp_readb_io(dev, 0, 0x17); 10901da177e4SLinus Torvalds return; 10911da177e4SLinus Torvalds } 10921da177e4SLinus Torvalds val &= 0x00ff; /* synchronization */ 10931da177e4SLinus Torvalds val |= 0x3f00; 10941da177e4SLinus Torvalds fun_scam(dev, &val); 10952bbbac45SOndrej Zary udelay(2); 10961da177e4SLinus Torvalds val &= 0x00ff; /* isolation */ 10971da177e4SLinus Torvalds val |= 0x2000; 10981da177e4SLinus Torvalds fun_scam(dev, &val); 10992bbbac45SOndrej Zary udelay(2); 11001da177e4SLinus Torvalds i = 8; 11011da177e4SLinus Torvalds j = 0; 1102c7fcc089SOndrej Zary 1103c7fcc089SOndrej Zary while (1) { 11046a3cebb6SOndrej Zary if ((atp_readw_io(dev, 0, 0x1c) & 0x2000) == 0) 1105c7fcc089SOndrej Zary continue; 11062bbbac45SOndrej Zary udelay(2); 11071da177e4SLinus Torvalds val &= 0x00ff; /* get ID_STRING */ 11081da177e4SLinus Torvalds val |= 0x2000; 11091da177e4SLinus Torvalds k = fun_scam(dev, &val); 1110c7fcc089SOndrej Zary if ((k & 0x03) == 0) 1111c7fcc089SOndrej Zary break; 11121da177e4SLinus Torvalds mbuf[j] <<= 0x01; 11131da177e4SLinus Torvalds mbuf[j] &= 0xfe; 1114c7fcc089SOndrej Zary if ((k & 0x02) != 0) 11151da177e4SLinus Torvalds mbuf[j] |= 0x01; 11161da177e4SLinus Torvalds i--; 1117c7fcc089SOndrej Zary if (i > 0) 1118c7fcc089SOndrej Zary continue; 11191da177e4SLinus Torvalds j++; 11201da177e4SLinus Torvalds i = 8; 1121c7fcc089SOndrej Zary } 11221da177e4SLinus Torvalds 1123c7fcc089SOndrej Zary /* isolation complete.. */ 11241da177e4SLinus Torvalds /* mbuf[32]=0; 11251da177e4SLinus Torvalds printk(" \n%x %x %x %s\n ",assignid_map,mbuf[0],mbuf[1],&mbuf[2]); */ 11261da177e4SLinus Torvalds i = 15; 11271da177e4SLinus Torvalds j = mbuf[0]; 11281da177e4SLinus Torvalds if ((j & 0x20) != 0) { /* bit5=1:ID up to 7 */ 11291da177e4SLinus Torvalds i = 7; 11301da177e4SLinus Torvalds } 1131c7fcc089SOndrej Zary if ((j & 0x06) != 0) { /* IDvalid? */ 11321da177e4SLinus Torvalds k = mbuf[1]; 1133c7fcc089SOndrej Zary while (1) { 11341da177e4SLinus Torvalds m = 1; 11351da177e4SLinus Torvalds m <<= k; 1136c7fcc089SOndrej Zary if ((m & assignid_map) == 0) 1137c7fcc089SOndrej Zary break; 1138c7fcc089SOndrej Zary if (k > 0) 11391da177e4SLinus Torvalds k--; 1140c7fcc089SOndrej Zary else 1141c7fcc089SOndrej Zary break; 11421da177e4SLinus Torvalds } 1143c7fcc089SOndrej Zary } 1144c7fcc089SOndrej Zary if ((m & assignid_map) != 0) { /* srch from max acceptable ID# */ 11451da177e4SLinus Torvalds k = i; /* max acceptable ID# */ 1146c7fcc089SOndrej Zary while (1) { 11471da177e4SLinus Torvalds m = 1; 11481da177e4SLinus Torvalds m <<= k; 1149c7fcc089SOndrej Zary if ((m & assignid_map) == 0) 1150c7fcc089SOndrej Zary break; 1151c7fcc089SOndrej Zary if (k > 0) 11521da177e4SLinus Torvalds k--; 1153c7fcc089SOndrej Zary else 1154c7fcc089SOndrej Zary break; 11551da177e4SLinus Torvalds } 1156c7fcc089SOndrej Zary } 1157c7fcc089SOndrej Zary /* k=binID#, */ 11581da177e4SLinus Torvalds assignid_map |= m; 11591da177e4SLinus Torvalds if (k < 8) { 11601da177e4SLinus Torvalds quintet[0] = 0x38; /* 1st dft ID<8 */ 11611da177e4SLinus Torvalds } else { 11621da177e4SLinus Torvalds quintet[0] = 0x31; /* 1st ID>=8 */ 11631da177e4SLinus Torvalds } 11641da177e4SLinus Torvalds k &= 0x07; 11651da177e4SLinus Torvalds quintet[1] = g2q_tab[k]; 11661da177e4SLinus Torvalds 11671da177e4SLinus Torvalds val &= 0x00ff; /* AssignID 1stQuintet,AH=001xxxxx */ 11681da177e4SLinus Torvalds m = quintet[0] << 8; 11691da177e4SLinus Torvalds val |= m; 11701da177e4SLinus Torvalds fun_scam(dev, &val); 11711da177e4SLinus Torvalds val &= 0x00ff; /* AssignID 2ndQuintet,AH=001xxxxx */ 11721da177e4SLinus Torvalds m = quintet[1] << 8; 11731da177e4SLinus Torvalds val |= m; 11741da177e4SLinus Torvalds fun_scam(dev, &val); 11751da177e4SLinus Torvalds 1176c7fcc089SOndrej Zary } 11771da177e4SLinus Torvalds } 11781da177e4SLinus Torvalds 11791da177e4SLinus Torvalds static void atp870u_free_tables(struct Scsi_Host *host) 11801da177e4SLinus Torvalds { 11811da177e4SLinus Torvalds struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata; 11821da177e4SLinus Torvalds int j, k; 11831da177e4SLinus Torvalds for (j=0; j < 2; j++) { 11841da177e4SLinus Torvalds for (k = 0; k < 16; k++) { 11851da177e4SLinus Torvalds if (!atp_dev->id[j][k].prd_table) 11861da177e4SLinus Torvalds continue; 1187b5683557SJames Bottomley pci_free_consistent(atp_dev->pdev, 1024, atp_dev->id[j][k].prd_table, atp_dev->id[j][k].prd_bus); 11881da177e4SLinus Torvalds atp_dev->id[j][k].prd_table = NULL; 11891da177e4SLinus Torvalds } 11901da177e4SLinus Torvalds } 11911da177e4SLinus Torvalds } 11921da177e4SLinus Torvalds 11931da177e4SLinus Torvalds static int atp870u_init_tables(struct Scsi_Host *host) 11941da177e4SLinus Torvalds { 11951da177e4SLinus Torvalds struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata; 11961da177e4SLinus Torvalds int c,k; 11971da177e4SLinus Torvalds for(c=0;c < 2;c++) { 11981da177e4SLinus Torvalds for(k=0;k<16;k++) { 1199b5683557SJames Bottomley atp_dev->id[c][k].prd_table = pci_alloc_consistent(atp_dev->pdev, 1024, &(atp_dev->id[c][k].prd_bus)); 12001da177e4SLinus Torvalds if (!atp_dev->id[c][k].prd_table) { 12011da177e4SLinus Torvalds printk("atp870u_init_tables fail\n"); 12021da177e4SLinus Torvalds atp870u_free_tables(host); 12031da177e4SLinus Torvalds return -ENOMEM; 12041da177e4SLinus Torvalds } 1205b5683557SJames Bottomley atp_dev->id[c][k].prdaddr = atp_dev->id[c][k].prd_bus; 12061da177e4SLinus Torvalds atp_dev->id[c][k].devsp=0x20; 12071da177e4SLinus Torvalds atp_dev->id[c][k].devtype = 0x7f; 12081da177e4SLinus Torvalds atp_dev->id[c][k].curr_req = NULL; 12091da177e4SLinus Torvalds } 12101da177e4SLinus Torvalds 12111da177e4SLinus Torvalds atp_dev->active_id[c] = 0; 12121da177e4SLinus Torvalds atp_dev->wide_id[c] = 0; 12131da177e4SLinus Torvalds atp_dev->host_id[c] = 0x07; 12141da177e4SLinus Torvalds atp_dev->quhd[c] = 0; 12151da177e4SLinus Torvalds atp_dev->quend[c] = 0; 12161da177e4SLinus Torvalds atp_dev->last_cmd[c] = 0xff; 12171da177e4SLinus Torvalds atp_dev->in_snd[c] = 0; 12181da177e4SLinus Torvalds atp_dev->in_int[c] = 0; 12191da177e4SLinus Torvalds 12201da177e4SLinus Torvalds for (k = 0; k < qcnt; k++) { 12211da177e4SLinus Torvalds atp_dev->quereq[c][k] = NULL; 12221da177e4SLinus Torvalds } 12231da177e4SLinus Torvalds for (k = 0; k < 16; k++) { 12241da177e4SLinus Torvalds atp_dev->id[c][k].curr_req = NULL; 12251da177e4SLinus Torvalds atp_dev->sp[c][k] = 0x04; 12261da177e4SLinus Torvalds } 12271da177e4SLinus Torvalds } 12281da177e4SLinus Torvalds return 0; 12291da177e4SLinus Torvalds } 12301da177e4SLinus Torvalds 12316a1961bcSOndrej Zary static void atp_set_host_id(struct atp_unit *atp, u8 c, u8 host_id) 12326a1961bcSOndrej Zary { 12336a1961bcSOndrej Zary atp_writeb_io(atp, c, 0, host_id | 0x08); 12346a1961bcSOndrej Zary atp_writeb_io(atp, c, 0x18, 0); 12356a1961bcSOndrej Zary while ((atp_readb_io(atp, c, 0x1f) & 0x80) == 0) 12366a1961bcSOndrej Zary mdelay(1); 12376a1961bcSOndrej Zary atp_readb_io(atp, c, 0x17); 12386a1961bcSOndrej Zary atp_writeb_io(atp, c, 1, 8); 12396a1961bcSOndrej Zary atp_writeb_io(atp, c, 2, 0x7f); 12406a1961bcSOndrej Zary atp_writeb_io(atp, c, 0x11, 0x20); 12416a1961bcSOndrej Zary } 12426a1961bcSOndrej Zary 12431da177e4SLinus Torvalds /* return non-zero on detection */ 12441da177e4SLinus Torvalds static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 12451da177e4SLinus Torvalds { 12461da177e4SLinus Torvalds unsigned char k, m, c; 12471da177e4SLinus Torvalds unsigned long flags; 12486c9b9c55SOndrej Zary unsigned int error,n; 12491da177e4SLinus Torvalds unsigned char host_id; 12501da177e4SLinus Torvalds struct Scsi_Host *shpnt = NULL; 1251bdd5ac40SOndrej Zary struct atp_unit *atpdev; 12521da177e4SLinus Torvalds unsigned char setupdata[2][16]; 1253bdd5ac40SOndrej Zary int err; 12541da177e4SLinus Torvalds 1255b1e85063SOndrej Zary if (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610 && pdev->revision < 2) { 1256b1e85063SOndrej Zary dev_err(&pdev->dev, "ATP850S chips (AEC6710L/F cards) are not supported.\n"); 1257b1e85063SOndrej Zary return -ENODEV; 1258b1e85063SOndrej Zary } 1259b1e85063SOndrej Zary 1260bdd5ac40SOndrej Zary err = pci_enable_device(pdev); 1261bdd5ac40SOndrej Zary if (err) 1262bdd5ac40SOndrej Zary goto fail; 12631da177e4SLinus Torvalds 126434a2c35dSOndrej Zary if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { 12651da177e4SLinus Torvalds printk(KERN_ERR "atp870u: DMA mask required but not available.\n"); 1266bdd5ac40SOndrej Zary err = -EIO; 1267bdd5ac40SOndrej Zary goto disable_device; 12681da177e4SLinus Torvalds } 12691da177e4SLinus Torvalds 1270bdd5ac40SOndrej Zary err = -ENOMEM; 1271bdd5ac40SOndrej Zary shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit)); 1272bdd5ac40SOndrej Zary if (!shpnt) 1273bdd5ac40SOndrej Zary goto disable_device; 1274bdd5ac40SOndrej Zary 1275bdd5ac40SOndrej Zary atpdev = shost_priv(shpnt); 1276bdd5ac40SOndrej Zary 1277bdd5ac40SOndrej Zary atpdev->host = shpnt; 1278bdd5ac40SOndrej Zary atpdev->pdev = pdev; 1279bdd5ac40SOndrej Zary pci_set_drvdata(pdev, atpdev); 1280bdd5ac40SOndrej Zary 12816c9b9c55SOndrej Zary shpnt->io_port = pci_resource_start(pdev, 0); 12826c9b9c55SOndrej Zary shpnt->io_port &= 0xfffffff8; 12836c9b9c55SOndrej Zary shpnt->n_io_port = pci_resource_len(pdev, 0); 12846c9b9c55SOndrej Zary atpdev->baseport = shpnt->io_port; 12856c9b9c55SOndrej Zary shpnt->unique_id = shpnt->io_port; 12866c9b9c55SOndrej Zary shpnt->irq = pdev->irq; 12871da177e4SLinus Torvalds 12881da177e4SLinus Torvalds if ((ent->device == ATP880_DEVID1)||(ent->device == ATP880_DEVID2)) { 12891da177e4SLinus Torvalds pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80);//JCC082803 12901da177e4SLinus Torvalds 12916c9b9c55SOndrej Zary atpdev->ioport[0] = shpnt->io_port + 0x40; 12926c9b9c55SOndrej Zary atpdev->pciport[0] = shpnt->io_port + 0x28; 1293d804bb25SOndrej Zary 1294d804bb25SOndrej Zary host_id = atp_readb_base(atpdev, 0x39); 12951da177e4SLinus Torvalds host_id >>= 0x04; 12961da177e4SLinus Torvalds 1297c48442d1SOndrej Zary printk(KERN_INFO " ACARD AEC-67160 PCI Ultra3 LVD Host Adapter:" 12986c9b9c55SOndrej Zary " IO:%lx, IRQ:%d.\n", shpnt->io_port, shpnt->irq); 1299dc6a78f1SRandy Dunlap atpdev->dev_id = ent->device; 1300dc6a78f1SRandy Dunlap atpdev->host_id[0] = host_id; 13011da177e4SLinus Torvalds 1302d804bb25SOndrej Zary atpdev->scam_on = atp_readb_base(atpdev, 0x22); 1303d804bb25SOndrej Zary atpdev->global_map[0] = atp_readb_base(atpdev, 0x35); 1304d804bb25SOndrej Zary atpdev->ultra_map[0] = atp_readw_base(atpdev, 0x3c); 13051da177e4SLinus Torvalds 13061da177e4SLinus Torvalds n = 0x3f09; 13071da177e4SLinus Torvalds next_fblk_880: 13081da177e4SLinus Torvalds if (n >= 0x4000) 13091da177e4SLinus Torvalds goto flash_ok_880; 13101da177e4SLinus Torvalds 13111da177e4SLinus Torvalds m = 0; 1312d804bb25SOndrej Zary atp_writew_base(atpdev, 0x34, n); 13131da177e4SLinus Torvalds n += 0x0002; 1314d804bb25SOndrej Zary if (atp_readb_base(atpdev, 0x30) == 0xff) 13151da177e4SLinus Torvalds goto flash_ok_880; 13161da177e4SLinus Torvalds 1317d804bb25SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30); 1318d804bb25SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31); 1319d804bb25SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32); 1320d804bb25SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33); 1321d804bb25SOndrej Zary atp_writew_base(atpdev, 0x34, n); 13221da177e4SLinus Torvalds n += 0x0002; 1323d804bb25SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30); 1324d804bb25SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31); 1325d804bb25SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32); 1326d804bb25SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33); 1327d804bb25SOndrej Zary atp_writew_base(atpdev, 0x34, n); 13281da177e4SLinus Torvalds n += 0x0002; 1329d804bb25SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30); 1330d804bb25SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31); 1331d804bb25SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32); 1332d804bb25SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33); 1333d804bb25SOndrej Zary atp_writew_base(atpdev, 0x34, n); 13341da177e4SLinus Torvalds n += 0x0002; 1335d804bb25SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30); 1336d804bb25SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31); 1337d804bb25SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32); 1338d804bb25SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33); 13391da177e4SLinus Torvalds n += 0x0018; 13401da177e4SLinus Torvalds goto next_fblk_880; 13411da177e4SLinus Torvalds flash_ok_880: 1342d804bb25SOndrej Zary atp_writew_base(atpdev, 0x34, 0); 1343dc6a78f1SRandy Dunlap atpdev->ultra_map[0] = 0; 1344dc6a78f1SRandy Dunlap atpdev->async[0] = 0; 13451da177e4SLinus Torvalds for (k = 0; k < 16; k++) { 13461da177e4SLinus Torvalds n = 1; 13471da177e4SLinus Torvalds n = n << k; 1348dc6a78f1SRandy Dunlap if (atpdev->sp[0][k] > 1) { 1349dc6a78f1SRandy Dunlap atpdev->ultra_map[0] |= n; 13501da177e4SLinus Torvalds } else { 1351dc6a78f1SRandy Dunlap if (atpdev->sp[0][k] == 0) 1352dc6a78f1SRandy Dunlap atpdev->async[0] |= n; 13531da177e4SLinus Torvalds } 13541da177e4SLinus Torvalds } 1355dc6a78f1SRandy Dunlap atpdev->async[0] = ~(atpdev->async[0]); 1356d804bb25SOndrej Zary atp_writeb_base(atpdev, 0x35, atpdev->global_map[0]); 13571da177e4SLinus Torvalds 13581da177e4SLinus Torvalds if (atp870u_init_tables(shpnt) < 0) { 13591da177e4SLinus Torvalds printk(KERN_ERR "Unable to allocate tables for Acard controller\n"); 1360bdd5ac40SOndrej Zary err = -ENOMEM; 13611da177e4SLinus Torvalds goto unregister; 13621da177e4SLinus Torvalds } 13631da177e4SLinus Torvalds 13646c9b9c55SOndrej Zary err = request_irq(shpnt->irq, atp870u_intr_handle, IRQF_SHARED, "atp880i", shpnt); 1365bdd5ac40SOndrej Zary if (err) { 13666c9b9c55SOndrej Zary printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", shpnt->irq); 13671da177e4SLinus Torvalds goto free_tables; 13681da177e4SLinus Torvalds } 13691da177e4SLinus Torvalds 13701da177e4SLinus Torvalds spin_lock_irqsave(shpnt->host_lock, flags); 1371bdd5ac40SOndrej Zary k = atp_readb_base(atpdev, 0x38) & 0x80; 1372bdd5ac40SOndrej Zary atp_writeb_base(atpdev, 0x38, k); 1373bdd5ac40SOndrej Zary atp_writeb_base(atpdev, 0x3b, 0x20); 13741da177e4SLinus Torvalds mdelay(32); 1375bdd5ac40SOndrej Zary atp_writeb_base(atpdev, 0x3b, 0); 13761da177e4SLinus Torvalds mdelay(32); 1377bdd5ac40SOndrej Zary atp_readb_io(atpdev, 0, 0x1b); 1378bdd5ac40SOndrej Zary atp_readb_io(atpdev, 0, 0x17); 13796a1961bcSOndrej Zary 1380bdd5ac40SOndrej Zary atp_set_host_id(atpdev, 0, host_id); 13811da177e4SLinus Torvalds 1382dd5a5f79SOndrej Zary tscam(shpnt, true); 1383bdd5ac40SOndrej Zary atp_is(atpdev, 0, true, atp_readb_base(atpdev, 0x3f) & 0x40); 1384bdd5ac40SOndrej Zary atp_writeb_base(atpdev, 0x38, 0xb0); 13851da177e4SLinus Torvalds shpnt->max_id = 16; 13861da177e4SLinus Torvalds shpnt->this_id = host_id; 13871da177e4SLinus Torvalds } else if (ent->device == ATP885_DEVID) { 13886c9b9c55SOndrej Zary printk(KERN_INFO " ACARD AEC-67162 PCI Ultra3 LVD Host Adapter: IO:%lx, IRQ:%d.\n" 13896c9b9c55SOndrej Zary , shpnt->io_port, shpnt->irq); 13901da177e4SLinus Torvalds 1391dc6a78f1SRandy Dunlap atpdev->pdev = pdev; 1392dc6a78f1SRandy Dunlap atpdev->dev_id = ent->device; 13936c9b9c55SOndrej Zary atpdev->ioport[0] = shpnt->io_port + 0x80; 13946c9b9c55SOndrej Zary atpdev->ioport[1] = shpnt->io_port + 0xc0; 13956c9b9c55SOndrej Zary atpdev->pciport[0] = shpnt->io_port + 0x40; 13966c9b9c55SOndrej Zary atpdev->pciport[1] = shpnt->io_port + 0x50; 13971da177e4SLinus Torvalds 1398bdd5ac40SOndrej Zary if (atp870u_init_tables(shpnt) < 0) { 1399bdd5ac40SOndrej Zary err = -ENOMEM; 14001da177e4SLinus Torvalds goto unregister; 1401bdd5ac40SOndrej Zary } 14021da177e4SLinus Torvalds 14031da177e4SLinus Torvalds #ifdef ED_DBGP 1404bdd5ac40SOndrej Zary printk("request_irq() shpnt %p hostdata %p\n", shpnt, atpdev); 14051da177e4SLinus Torvalds #endif 14066c9b9c55SOndrej Zary err = request_irq(shpnt->irq, atp870u_intr_handle, IRQF_SHARED, "atp870u", shpnt); 1407bdd5ac40SOndrej Zary if (err) { 14081da177e4SLinus Torvalds printk(KERN_ERR "Unable to allocate IRQ for Acard controller.\n"); 14091da177e4SLinus Torvalds goto free_tables; 14101da177e4SLinus Torvalds } 14111da177e4SLinus Torvalds 14121da177e4SLinus Torvalds spin_lock_irqsave(shpnt->host_lock, flags); 14131da177e4SLinus Torvalds 1414bdd5ac40SOndrej Zary c = atp_readb_base(atpdev, 0x29); 1415bdd5ac40SOndrej Zary atp_writeb_base(atpdev, 0x29, c | 0x04); 14161da177e4SLinus Torvalds 14171da177e4SLinus Torvalds n=0x1f80; 14181da177e4SLinus Torvalds next_fblk_885: 14191da177e4SLinus Torvalds if (n >= 0x2000) { 14201da177e4SLinus Torvalds goto flash_ok_885; 14211da177e4SLinus Torvalds } 1422bdd5ac40SOndrej Zary atp_writew_base(atpdev, 0x3c, n); 1423bdd5ac40SOndrej Zary if (atp_readl_base(atpdev, 0x38) == 0xffffffff) { 14241da177e4SLinus Torvalds goto flash_ok_885; 14251da177e4SLinus Torvalds } 14261da177e4SLinus Torvalds for (m=0; m < 2; m++) { 1427bdd5ac40SOndrej Zary atpdev->global_map[m]= 0; 14281da177e4SLinus Torvalds for (k=0; k < 4; k++) { 1429bdd5ac40SOndrej Zary atp_writew_base(atpdev, 0x3c, n++); 1430bdd5ac40SOndrej Zary ((unsigned long *)&setupdata[m][0])[k] = atp_readl_base(atpdev, 0x38); 14311da177e4SLinus Torvalds } 14321da177e4SLinus Torvalds for (k=0; k < 4; k++) { 1433bdd5ac40SOndrej Zary atp_writew_base(atpdev, 0x3c, n++); 1434bdd5ac40SOndrej Zary ((unsigned long *)&atpdev->sp[m][0])[k] = atp_readl_base(atpdev, 0x38); 14351da177e4SLinus Torvalds } 14361da177e4SLinus Torvalds n += 8; 14371da177e4SLinus Torvalds } 14381da177e4SLinus Torvalds goto next_fblk_885; 14391da177e4SLinus Torvalds flash_ok_885: 14401da177e4SLinus Torvalds #ifdef ED_DBGP 14411da177e4SLinus Torvalds printk( "Flash Read OK\n"); 14421da177e4SLinus Torvalds #endif 1443bdd5ac40SOndrej Zary c = atp_readb_base(atpdev, 0x29); 1444bdd5ac40SOndrej Zary atp_writeb_base(atpdev, 0x29, c & 0xfb); 14451da177e4SLinus Torvalds for (c=0;c < 2;c++) { 1446bdd5ac40SOndrej Zary atpdev->ultra_map[c]=0; 1447bdd5ac40SOndrej Zary atpdev->async[c] = 0; 14481da177e4SLinus Torvalds for (k=0; k < 16; k++) { 14491da177e4SLinus Torvalds n=1; 14501da177e4SLinus Torvalds n = n << k; 1451bdd5ac40SOndrej Zary if (atpdev->sp[c][k] > 1) { 1452bdd5ac40SOndrej Zary atpdev->ultra_map[c] |= n; 14531da177e4SLinus Torvalds } else { 1454bdd5ac40SOndrej Zary if (atpdev->sp[c][k] == 0) { 1455bdd5ac40SOndrej Zary atpdev->async[c] |= n; 14561da177e4SLinus Torvalds } 14571da177e4SLinus Torvalds } 14581da177e4SLinus Torvalds } 1459bdd5ac40SOndrej Zary atpdev->async[c] = ~(atpdev->async[c]); 14601da177e4SLinus Torvalds 1461bdd5ac40SOndrej Zary if (atpdev->global_map[c] == 0) { 14621da177e4SLinus Torvalds k=setupdata[c][1]; 14631da177e4SLinus Torvalds if ((k & 0x40) != 0) 1464bdd5ac40SOndrej Zary atpdev->global_map[c] |= 0x20; 14651da177e4SLinus Torvalds k &= 0x07; 1466bdd5ac40SOndrej Zary atpdev->global_map[c] |= k; 14671da177e4SLinus Torvalds if ((setupdata[c][2] & 0x04) != 0) 1468bdd5ac40SOndrej Zary atpdev->global_map[c] |= 0x08; 1469bdd5ac40SOndrej Zary atpdev->host_id[c] = setupdata[c][0] & 0x07; 14701da177e4SLinus Torvalds } 14711da177e4SLinus Torvalds } 14721da177e4SLinus Torvalds 1473bdd5ac40SOndrej Zary k = atp_readb_base(atpdev, 0x28) & 0x8f; 14741da177e4SLinus Torvalds k |= 0x10; 1475bdd5ac40SOndrej Zary atp_writeb_base(atpdev, 0x28, k); 1476bdd5ac40SOndrej Zary atp_writeb_pci(atpdev, 0, 1, 0x80); 1477bdd5ac40SOndrej Zary atp_writeb_pci(atpdev, 1, 1, 0x80); 14781da177e4SLinus Torvalds mdelay(100); 1479bdd5ac40SOndrej Zary atp_writeb_pci(atpdev, 0, 1, 0); 1480bdd5ac40SOndrej Zary atp_writeb_pci(atpdev, 1, 1, 0); 14811da177e4SLinus Torvalds mdelay(1000); 1482bdd5ac40SOndrej Zary atp_readb_io(atpdev, 0, 0x1b); 1483bdd5ac40SOndrej Zary atp_readb_io(atpdev, 0, 0x17); 1484bdd5ac40SOndrej Zary atp_readb_io(atpdev, 1, 0x1b); 1485bdd5ac40SOndrej Zary atp_readb_io(atpdev, 1, 0x17); 14866a1961bcSOndrej Zary 1487bdd5ac40SOndrej Zary k=atpdev->host_id[0]; 14881da177e4SLinus Torvalds if (k > 7) 14891da177e4SLinus Torvalds k = (k & 0x07) | 0x40; 1490bdd5ac40SOndrej Zary atp_set_host_id(atpdev, 0, k); 14911da177e4SLinus Torvalds 1492bdd5ac40SOndrej Zary k=atpdev->host_id[1]; 14931da177e4SLinus Torvalds if (k > 7) 14941da177e4SLinus Torvalds k = (k & 0x07) | 0x40; 1495bdd5ac40SOndrej Zary atp_set_host_id(atpdev, 1, k); 14961da177e4SLinus Torvalds 1497c4ad92bcSOndrej Zary mdelay(600); /* this delay used to be called tscam_885() */ 14981da177e4SLinus Torvalds printk(KERN_INFO " Scanning Channel A SCSI Device ...\n"); 1499bdd5ac40SOndrej Zary atp_is(atpdev, 0, true, atp_readb_io(atpdev, 0, 0x1b) >> 7); 1500bdd5ac40SOndrej Zary atp_writeb_io(atpdev, 0, 0x16, 0x80); 15011da177e4SLinus Torvalds printk(KERN_INFO " Scanning Channel B SCSI Device ...\n"); 1502bdd5ac40SOndrej Zary atp_is(atpdev, 1, true, atp_readb_io(atpdev, 1, 0x1b) >> 7); 1503bdd5ac40SOndrej Zary atp_writeb_io(atpdev, 1, 0x16, 0x80); 1504bdd5ac40SOndrej Zary k = atp_readb_base(atpdev, 0x28) & 0xcf; 15051da177e4SLinus Torvalds k |= 0xc0; 1506bdd5ac40SOndrej Zary atp_writeb_base(atpdev, 0x28, k); 1507bdd5ac40SOndrej Zary k = atp_readb_base(atpdev, 0x1f) | 0x80; 1508bdd5ac40SOndrej Zary atp_writeb_base(atpdev, 0x1f, k); 1509bdd5ac40SOndrej Zary k = atp_readb_base(atpdev, 0x29) | 0x01; 1510bdd5ac40SOndrej Zary atp_writeb_base(atpdev, 0x29, k); 15111da177e4SLinus Torvalds #ifdef ED_DBGP 15121da177e4SLinus Torvalds //printk("atp885: atp_host[0] 0x%p\n", atp_host[0]); 15131da177e4SLinus Torvalds #endif 15141da177e4SLinus Torvalds shpnt->max_id = 16; 1515bdd5ac40SOndrej Zary shpnt->max_lun = (atpdev->global_map[0] & 0x07) + 1; 15161da177e4SLinus Torvalds shpnt->max_channel = 1; 1517bdd5ac40SOndrej Zary shpnt->this_id = atpdev->host_id[0]; 15181da177e4SLinus Torvalds } else { 1519dd5a5f79SOndrej Zary bool wide_chip = 1520dd5a5f79SOndrej Zary (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610 && 1521dd5a5f79SOndrej Zary pdev->revision == 4) || 1522dd5a5f79SOndrej Zary (ent->device == PCI_DEVICE_ID_ARTOP_AEC7612UW) || 1523dd5a5f79SOndrej Zary (ent->device == PCI_DEVICE_ID_ARTOP_AEC7612SUW); 15241da177e4SLinus Torvalds error = pci_read_config_byte(pdev, 0x49, &host_id); 15251da177e4SLinus Torvalds 1526c48442d1SOndrej Zary printk(KERN_INFO " ACARD AEC-671X PCI Ultra/W SCSI-2/3 Host Adapter: " 15276c9b9c55SOndrej Zary "IO:%lx, IRQ:%d.\n", shpnt->io_port, shpnt->irq); 15281da177e4SLinus Torvalds 15296c9b9c55SOndrej Zary atpdev->ioport[0] = shpnt->io_port; 15306c9b9c55SOndrej Zary atpdev->pciport[0] = shpnt->io_port + 0x20; 1531dc6a78f1SRandy Dunlap atpdev->dev_id = ent->device; 15321da177e4SLinus Torvalds host_id &= 0x07; 1533dc6a78f1SRandy Dunlap atpdev->host_id[0] = host_id; 1534d804bb25SOndrej Zary atpdev->scam_on = atp_readb_pci(atpdev, 0, 2); 1535d804bb25SOndrej Zary atpdev->global_map[0] = atp_readb_base(atpdev, 0x2d); 1536d804bb25SOndrej Zary atpdev->ultra_map[0] = atp_readw_base(atpdev, 0x2e); 15371da177e4SLinus Torvalds 1538dc6a78f1SRandy Dunlap if (atpdev->ultra_map[0] == 0) { 1539dc6a78f1SRandy Dunlap atpdev->scam_on = 0x00; 1540dc6a78f1SRandy Dunlap atpdev->global_map[0] = 0x20; 1541dc6a78f1SRandy Dunlap atpdev->ultra_map[0] = 0xffff; 15421da177e4SLinus Torvalds } 15431da177e4SLinus Torvalds 15441da177e4SLinus Torvalds 1545bdd5ac40SOndrej Zary if (atp870u_init_tables(shpnt) < 0) { 1546bdd5ac40SOndrej Zary err = -ENOMEM; 15471da177e4SLinus Torvalds goto unregister; 1548bdd5ac40SOndrej Zary } 15491da177e4SLinus Torvalds 15506c9b9c55SOndrej Zary err = request_irq(shpnt->irq, atp870u_intr_handle, IRQF_SHARED, "atp870i", shpnt); 1551bdd5ac40SOndrej Zary if (err) { 15526c9b9c55SOndrej Zary printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", shpnt->irq); 15531da177e4SLinus Torvalds goto free_tables; 15541da177e4SLinus Torvalds } 15551da177e4SLinus Torvalds 15561da177e4SLinus Torvalds spin_lock_irqsave(shpnt->host_lock, flags); 1557dd5a5f79SOndrej Zary if (pdev->revision > 0x07) /* check if atp876 chip then enable terminator */ 1558bdd5ac40SOndrej Zary atp_writeb_base(atpdev, 0x3e, 0x00); 15591da177e4SLinus Torvalds 1560bdd5ac40SOndrej Zary k = (atp_readb_base(atpdev, 0x3a) & 0xf3) | 0x10; 1561bdd5ac40SOndrej Zary atp_writeb_base(atpdev, 0x3a, k); 1562bdd5ac40SOndrej Zary atp_writeb_base(atpdev, 0x3a, k & 0xdf); 15631da177e4SLinus Torvalds mdelay(32); 1564bdd5ac40SOndrej Zary atp_writeb_base(atpdev, 0x3a, k); 15651da177e4SLinus Torvalds mdelay(32); 1566bdd5ac40SOndrej Zary atp_set_host_id(atpdev, 0, host_id); 15671da177e4SLinus Torvalds 1568dd5a5f79SOndrej Zary 1569dd5a5f79SOndrej Zary tscam(shpnt, wide_chip); 1570bdd5ac40SOndrej Zary atp_writeb_base(atpdev, 0x3a, atp_readb_base(atpdev, 0x3a) | 0x10); 1571dd5a5f79SOndrej Zary atp_is(atpdev, 0, wide_chip, 0); 1572bdd5ac40SOndrej Zary atp_writeb_base(atpdev, 0x3a, atp_readb_base(atpdev, 0x3a) & 0xef); 1573bdd5ac40SOndrej Zary atp_writeb_base(atpdev, 0x3b, atp_readb_base(atpdev, 0x3b) | 0x20); 1574dd5a5f79SOndrej Zary shpnt->max_id = wide_chip ? 16 : 8; 15751da177e4SLinus Torvalds shpnt->this_id = host_id; 15766c9b9c55SOndrej Zary 15771da177e4SLinus Torvalds } 15781da177e4SLinus Torvalds spin_unlock_irqrestore(shpnt->host_lock, flags); 15796c9b9c55SOndrej Zary if (!request_region(shpnt->io_port, shpnt->n_io_port, "atp870u")) { 1580bdd5ac40SOndrej Zary err = -EBUSY; 15811da177e4SLinus Torvalds goto request_io_fail; 1582bdd5ac40SOndrej Zary } 1583bdd5ac40SOndrej Zary err = scsi_add_host(shpnt, &pdev->dev); 1584bdd5ac40SOndrej Zary if (err) 15851da177e4SLinus Torvalds goto scsi_add_fail; 15861da177e4SLinus Torvalds scsi_scan_host(shpnt); 15871da177e4SLinus Torvalds #ifdef ED_DBGP 15881da177e4SLinus Torvalds printk("atp870u_prob : exit\n"); 15891da177e4SLinus Torvalds #endif 15901da177e4SLinus Torvalds return 0; 15911da177e4SLinus Torvalds 15921da177e4SLinus Torvalds scsi_add_fail: 15931da177e4SLinus Torvalds printk("atp870u_prob:scsi_add_fail\n"); 15946c9b9c55SOndrej Zary release_region(shpnt->io_port, shpnt->n_io_port); 15951da177e4SLinus Torvalds request_io_fail: 15961da177e4SLinus Torvalds printk("atp870u_prob:request_io_fail\n"); 15976c9b9c55SOndrej Zary free_irq(shpnt->irq, shpnt); 15981da177e4SLinus Torvalds free_tables: 15991da177e4SLinus Torvalds printk("atp870u_prob:free_table\n"); 16001da177e4SLinus Torvalds atp870u_free_tables(shpnt); 16011da177e4SLinus Torvalds unregister: 16021da177e4SLinus Torvalds scsi_host_put(shpnt); 1603bdd5ac40SOndrej Zary disable_device: 1604bdd5ac40SOndrej Zary pci_disable_device(pdev); 1605bdd5ac40SOndrej Zary fail: 1606bdd5ac40SOndrej Zary return err; 16071da177e4SLinus Torvalds } 16081da177e4SLinus Torvalds 16091da177e4SLinus Torvalds /* The abort command does not leave the device in a clean state where 16101da177e4SLinus Torvalds it is available to be used again. Until this gets worked out, we will 16111da177e4SLinus Torvalds leave it commented out. */ 16121da177e4SLinus Torvalds 16131da177e4SLinus Torvalds static int atp870u_abort(struct scsi_cmnd * SCpnt) 16141da177e4SLinus Torvalds { 16151da177e4SLinus Torvalds unsigned char j, k, c; 16161da177e4SLinus Torvalds struct scsi_cmnd *workrequ; 16171da177e4SLinus Torvalds struct atp_unit *dev; 16181da177e4SLinus Torvalds struct Scsi_Host *host; 16191da177e4SLinus Torvalds host = SCpnt->device->host; 16201da177e4SLinus Torvalds 16211da177e4SLinus Torvalds dev = (struct atp_unit *)&host->hostdata; 1622422c0d61SJeff Garzik c = scmd_channel(SCpnt); 16231da177e4SLinus Torvalds printk(" atp870u: abort Channel = %x \n", c); 16241da177e4SLinus Torvalds printk("working=%x last_cmd=%x ", dev->working[c], dev->last_cmd[c]); 16251da177e4SLinus Torvalds printk(" quhdu=%x quendu=%x ", dev->quhd[c], dev->quend[c]); 16261da177e4SLinus Torvalds for (j = 0; j < 0x18; j++) { 16276a3cebb6SOndrej Zary printk(" r%2x=%2x", j, atp_readb_io(dev, c, j)); 16281da177e4SLinus Torvalds } 16296a3cebb6SOndrej Zary printk(" r1c=%2x", atp_readb_io(dev, c, 0x1c)); 16306a3cebb6SOndrej Zary printk(" r1f=%2x in_snd=%2x ", atp_readb_io(dev, c, 0x1f), dev->in_snd[c]); 16316a3cebb6SOndrej Zary printk(" d00=%2x", atp_readb_pci(dev, c, 0x00)); 16326a3cebb6SOndrej Zary printk(" d02=%2x", atp_readb_pci(dev, c, 0x02)); 16331da177e4SLinus Torvalds for(j=0;j<16;j++) { 16341da177e4SLinus Torvalds if (dev->id[c][j].curr_req != NULL) { 16351da177e4SLinus Torvalds workrequ = dev->id[c][j].curr_req; 16361da177e4SLinus Torvalds printk("\n que cdb= "); 16371da177e4SLinus Torvalds for (k=0; k < workrequ->cmd_len; k++) { 16381da177e4SLinus Torvalds printk(" %2x ",workrequ->cmnd[k]); 16391da177e4SLinus Torvalds } 16401da177e4SLinus Torvalds printk(" last_lenu= %x ",(unsigned int)dev->id[c][j].last_len); 16411da177e4SLinus Torvalds } 16421da177e4SLinus Torvalds } 16431da177e4SLinus Torvalds return SUCCESS; 16441da177e4SLinus Torvalds } 16451da177e4SLinus Torvalds 16461da177e4SLinus Torvalds static const char *atp870u_info(struct Scsi_Host *notused) 16471da177e4SLinus Torvalds { 16481da177e4SLinus Torvalds static char buffer[128]; 16491da177e4SLinus Torvalds 16501da177e4SLinus Torvalds strcpy(buffer, "ACARD AEC-6710/6712/67160 PCI Ultra/W/LVD SCSI-3 Adapter Driver V2.6+ac "); 16511da177e4SLinus Torvalds 16521da177e4SLinus Torvalds return buffer; 16531da177e4SLinus Torvalds } 16541da177e4SLinus Torvalds 1655d773e422SAl Viro static int atp870u_show_info(struct seq_file *m, struct Scsi_Host *HBAptr) 16561da177e4SLinus Torvalds { 16573d30079cSRasmus Villemoes seq_puts(m, "ACARD AEC-671X Driver Version: 2.6+ac\n\n" 16583d30079cSRasmus Villemoes "Adapter Configuration:\n"); 1659d773e422SAl Viro seq_printf(m, " Base IO: %#.4lx\n", HBAptr->io_port); 1660d773e422SAl Viro seq_printf(m, " IRQ: %d\n", HBAptr->irq); 1661d773e422SAl Viro return 0; 16621da177e4SLinus Torvalds } 16631da177e4SLinus Torvalds 16641da177e4SLinus Torvalds 16651da177e4SLinus Torvalds static int atp870u_biosparam(struct scsi_device *disk, struct block_device *dev, 16661da177e4SLinus Torvalds sector_t capacity, int *ip) 16671da177e4SLinus Torvalds { 16681da177e4SLinus Torvalds int heads, sectors, cylinders; 16691da177e4SLinus Torvalds 16701da177e4SLinus Torvalds heads = 64; 16711da177e4SLinus Torvalds sectors = 32; 16721da177e4SLinus Torvalds cylinders = (unsigned long)capacity / (heads * sectors); 16731da177e4SLinus Torvalds if (cylinders > 1024) { 16741da177e4SLinus Torvalds heads = 255; 16751da177e4SLinus Torvalds sectors = 63; 16761da177e4SLinus Torvalds cylinders = (unsigned long)capacity / (heads * sectors); 16771da177e4SLinus Torvalds } 16781da177e4SLinus Torvalds ip[0] = heads; 16791da177e4SLinus Torvalds ip[1] = sectors; 16801da177e4SLinus Torvalds ip[2] = cylinders; 16811da177e4SLinus Torvalds 16821da177e4SLinus Torvalds return 0; 16831da177e4SLinus Torvalds } 16841da177e4SLinus Torvalds 16851da177e4SLinus Torvalds static void atp870u_remove (struct pci_dev *pdev) 16861da177e4SLinus Torvalds { 16871da177e4SLinus Torvalds struct atp_unit *devext = pci_get_drvdata(pdev); 16881da177e4SLinus Torvalds struct Scsi_Host *pshost = devext->host; 16891da177e4SLinus Torvalds 16901da177e4SLinus Torvalds 16911da177e4SLinus Torvalds scsi_remove_host(pshost); 16921da177e4SLinus Torvalds free_irq(pshost->irq, pshost); 16931da177e4SLinus Torvalds release_region(pshost->io_port, pshost->n_io_port); 16941da177e4SLinus Torvalds atp870u_free_tables(pshost); 16951da177e4SLinus Torvalds scsi_host_put(pshost); 16961da177e4SLinus Torvalds } 16971da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 16981da177e4SLinus Torvalds 16991da177e4SLinus Torvalds static struct scsi_host_template atp870u_template = { 17001da177e4SLinus Torvalds .module = THIS_MODULE, 17011da177e4SLinus Torvalds .name = "atp870u" /* name */, 17021da177e4SLinus Torvalds .proc_name = "atp870u", 1703d773e422SAl Viro .show_info = atp870u_show_info, 17041da177e4SLinus Torvalds .info = atp870u_info /* info */, 17051da177e4SLinus Torvalds .queuecommand = atp870u_queuecommand /* queuecommand */, 17061da177e4SLinus Torvalds .eh_abort_handler = atp870u_abort /* abort */, 17071da177e4SLinus Torvalds .bios_param = atp870u_biosparam /* biosparm */, 17081da177e4SLinus Torvalds .can_queue = qcnt /* can_queue */, 17091da177e4SLinus Torvalds .this_id = 7 /* SCSI ID */, 17101da177e4SLinus Torvalds .sg_tablesize = ATP870U_SCATTER /*SG_ALL*/ /*SG_NONE*/, 17111da177e4SLinus Torvalds .use_clustering = ENABLE_CLUSTERING, 17121da177e4SLinus Torvalds .max_sectors = ATP870U_MAX_SECTORS, 17131da177e4SLinus Torvalds }; 17141da177e4SLinus Torvalds 17151da177e4SLinus Torvalds static struct pci_device_id atp870u_id_table[] = { 17161da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP885_DEVID) }, 17171da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID1) }, 17181da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID2) }, 17191da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7610) }, 17201da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612UW) }, 17211da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612U) }, 17221da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612S) }, 17231da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612D) }, 17241da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612SUW) }, 17251da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_8060) }, 17261da177e4SLinus Torvalds { 0, }, 17271da177e4SLinus Torvalds }; 17281da177e4SLinus Torvalds 17291da177e4SLinus Torvalds MODULE_DEVICE_TABLE(pci, atp870u_id_table); 17301da177e4SLinus Torvalds 17311da177e4SLinus Torvalds static struct pci_driver atp870u_driver = { 17321da177e4SLinus Torvalds .id_table = atp870u_id_table, 17331da177e4SLinus Torvalds .name = "atp870u", 17341da177e4SLinus Torvalds .probe = atp870u_probe, 17356f039790SGreg Kroah-Hartman .remove = atp870u_remove, 17361da177e4SLinus Torvalds }; 17371da177e4SLinus Torvalds 17381ccd7d68SOndrej Zary module_pci_driver(atp870u_driver); 17391da177e4SLinus Torvalds 17404192a40fSOndrej Zary static void atp_is(struct atp_unit *dev, unsigned char c, bool wide_chip, unsigned char lvdmode) 17411da177e4SLinus Torvalds { 1742fa50b308SOndrej Zary unsigned char i, j, k, rmb, n; 17431da177e4SLinus Torvalds unsigned short int m; 17441da177e4SLinus Torvalds static unsigned char mbuf[512]; 17451da177e4SLinus Torvalds static unsigned char satn[9] = { 0, 0, 0, 0, 0, 0, 0, 6, 6 }; 17461da177e4SLinus Torvalds static unsigned char inqd[9] = { 0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6 }; 17471da177e4SLinus Torvalds static unsigned char synn[6] = { 0x80, 1, 3, 1, 0x19, 0x0e }; 17481da177e4SLinus Torvalds unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e }; 17491da177e4SLinus Torvalds static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x19, 0x0e }; 1750460da918SOndrej Zary static unsigned char synw_870[6] = { 0x80, 1, 3, 1, 0x0c, 0x07 }; 17511da177e4SLinus Torvalds unsigned char synuw[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e }; 17521da177e4SLinus Torvalds static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 }; 17531da177e4SLinus Torvalds static unsigned char u3[9] = { 0x80, 1, 6, 4, 0x09, 00, 0x0e, 0x01, 0x02 }; 17541da177e4SLinus Torvalds 17551da177e4SLinus Torvalds for (i = 0; i < 16; i++) { 1756197fb8d8SOndrej Zary if (!wide_chip && (i > 7)) 1757197fb8d8SOndrej Zary break; 17581da177e4SLinus Torvalds m = 1; 17591da177e4SLinus Torvalds m = m << i; 17601da177e4SLinus Torvalds if ((m & dev->active_id[c]) != 0) { 17611da177e4SLinus Torvalds continue; 17621da177e4SLinus Torvalds } 17631da177e4SLinus Torvalds if (i == dev->host_id[c]) { 17641da177e4SLinus Torvalds printk(KERN_INFO " ID: %2d Host Adapter\n", dev->host_id[c]); 17651da177e4SLinus Torvalds continue; 17661da177e4SLinus Torvalds } 1767197fb8d8SOndrej Zary atp_writeb_io(dev, c, 0x1b, wide_chip ? 0x01 : 0x00); 17685d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 1, 0x08); 17695d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 2, 0x7f); 17705d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 3, satn[0]); 17715d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 4, satn[1]); 17725d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 5, satn[2]); 17735d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 6, satn[3]); 17745d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 7, satn[4]); 17755d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 8, satn[5]); 17765d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x0f, 0); 17775d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp); 17785d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x12, 0); 17795d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x13, satn[6]); 17805d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, satn[7]); 17811da177e4SLinus Torvalds j = i; 17821da177e4SLinus Torvalds if ((j & 0x08) != 0) { 17831da177e4SLinus Torvalds j = (j & 0x07) | 0x40; 17841da177e4SLinus Torvalds } 17855d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x15, j); 17865d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, satn[8]); 17871da177e4SLinus Torvalds 17885d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) 17891da177e4SLinus Torvalds cpu_relax(); 179080b52a7fSOndrej Zary 179180b52a7fSOndrej Zary if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e) 17921da177e4SLinus Torvalds continue; 179380b52a7fSOndrej Zary 17945d2a5a4fSOndrej Zary while (atp_readb_io(dev, c, 0x17) != 0x8e) 17951da177e4SLinus Torvalds cpu_relax(); 179680b52a7fSOndrej Zary 17971da177e4SLinus Torvalds dev->active_id[c] |= m; 17981da177e4SLinus Torvalds 17995d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x10, 0x30); 1800460da918SOndrej Zary if (dev->dev_id == ATP885_DEVID || dev->dev_id == ATP880_DEVID1 || dev->dev_id == ATP880_DEVID2) 18015d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, 0x00); 1802460da918SOndrej Zary else /* result of is870() merge - is this a bug? */ 1803460da918SOndrej Zary atp_writeb_io(dev, c, 0x04, 0x00); 18041da177e4SLinus Torvalds 18051da177e4SLinus Torvalds phase_cmd: 18065d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 180780b52a7fSOndrej Zary 18085d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) 18091da177e4SLinus Torvalds cpu_relax(); 181080b52a7fSOndrej Zary 18115d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17); 18121da177e4SLinus Torvalds if (j != 0x16) { 18135d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x10, 0x41); 18141da177e4SLinus Torvalds goto phase_cmd; 18151da177e4SLinus Torvalds } 18161da177e4SLinus Torvalds sel_ok: 18175d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 3, inqd[0]); 18185d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 4, inqd[1]); 18195d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 5, inqd[2]); 18205d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 6, inqd[3]); 18215d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 7, inqd[4]); 18225d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 8, inqd[5]); 18235d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x0f, 0); 18245d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp); 18255d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x12, 0); 18265d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x13, inqd[6]); 18275d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, inqd[7]); 18285d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, inqd[8]); 182980b52a7fSOndrej Zary 18305d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) 18311da177e4SLinus Torvalds cpu_relax(); 183280b52a7fSOndrej Zary 183380b52a7fSOndrej Zary if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e) 18341da177e4SLinus Torvalds continue; 183580b52a7fSOndrej Zary 18365d2a5a4fSOndrej Zary while (atp_readb_io(dev, c, 0x17) != 0x8e) 18371da177e4SLinus Torvalds cpu_relax(); 183880b52a7fSOndrej Zary 1839197fb8d8SOndrej Zary if (wide_chip) 18405d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x1b, 0x00); 1841197fb8d8SOndrej Zary 18425d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 18431da177e4SLinus Torvalds j = 0; 18441da177e4SLinus Torvalds rd_inq_data: 18455d2a5a4fSOndrej Zary k = atp_readb_io(dev, c, 0x1f); 18461da177e4SLinus Torvalds if ((k & 0x01) != 0) { 18475d2a5a4fSOndrej Zary mbuf[j++] = atp_readb_io(dev, c, 0x19); 18481da177e4SLinus Torvalds goto rd_inq_data; 18491da177e4SLinus Torvalds } 18501da177e4SLinus Torvalds if ((k & 0x80) == 0) { 18511da177e4SLinus Torvalds goto rd_inq_data; 18521da177e4SLinus Torvalds } 18535d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17); 18541da177e4SLinus Torvalds if (j == 0x16) { 18551da177e4SLinus Torvalds goto inq_ok; 18561da177e4SLinus Torvalds } 18575d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x10, 0x46); 18585d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x12, 0); 18595d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x13, 0); 18605d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, 0); 18615d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 186280b52a7fSOndrej Zary 18635d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) 18641da177e4SLinus Torvalds cpu_relax(); 186580b52a7fSOndrej Zary 186680b52a7fSOndrej Zary if (atp_readb_io(dev, c, 0x17) != 0x16) 18671da177e4SLinus Torvalds goto sel_ok; 186880b52a7fSOndrej Zary 18691da177e4SLinus Torvalds inq_ok: 18701da177e4SLinus Torvalds mbuf[36] = 0; 18711da177e4SLinus Torvalds printk(KERN_INFO " ID: %2d %s\n", i, &mbuf[8]); 18721da177e4SLinus Torvalds dev->id[c][i].devtype = mbuf[0]; 18731da177e4SLinus Torvalds rmb = mbuf[1]; 18741da177e4SLinus Torvalds n = mbuf[7]; 1875197fb8d8SOndrej Zary if (!wide_chip) 1876197fb8d8SOndrej Zary goto not_wide; 18771da177e4SLinus Torvalds if ((mbuf[7] & 0x60) == 0) { 18781da177e4SLinus Torvalds goto not_wide; 18791da177e4SLinus Torvalds } 1880197fb8d8SOndrej Zary if (dev->dev_id == ATP885_DEVID || dev->dev_id == ATP880_DEVID1 || dev->dev_id == ATP880_DEVID2) { 1881197fb8d8SOndrej Zary if ((i < 8) && ((dev->global_map[c] & 0x20) == 0)) 1882197fb8d8SOndrej Zary goto not_wide; 1883197fb8d8SOndrej Zary } else { /* result of is870() merge - is this a bug? */ 1884197fb8d8SOndrej Zary if ((dev->global_map[c] & 0x20) == 0) 18851da177e4SLinus Torvalds goto not_wide; 18861da177e4SLinus Torvalds } 18871da177e4SLinus Torvalds if (lvdmode == 0) { 18881da177e4SLinus Torvalds goto chg_wide; 18891da177e4SLinus Torvalds } 189080b52a7fSOndrej Zary if (dev->sp[c][i] != 0x04) // force u2 189180b52a7fSOndrej Zary { 18921da177e4SLinus Torvalds goto chg_wide; 18931da177e4SLinus Torvalds } 18941da177e4SLinus Torvalds 18955d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x1b, 0x01); 18965d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 3, satn[0]); 18975d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 4, satn[1]); 18985d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 5, satn[2]); 18995d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 6, satn[3]); 19005d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 7, satn[4]); 19015d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 8, satn[5]); 19025d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x0f, 0); 19035d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp); 19045d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x12, 0); 19055d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x13, satn[6]); 19065d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, satn[7]); 19075d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, satn[8]); 19081da177e4SLinus Torvalds 19095d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) 19101da177e4SLinus Torvalds cpu_relax(); 191180b52a7fSOndrej Zary 191280b52a7fSOndrej Zary if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e) 19131da177e4SLinus Torvalds continue; 191480b52a7fSOndrej Zary 19155d2a5a4fSOndrej Zary while (atp_readb_io(dev, c, 0x17) != 0x8e) 19161da177e4SLinus Torvalds cpu_relax(); 191780b52a7fSOndrej Zary 19181da177e4SLinus Torvalds try_u3: 19191da177e4SLinus Torvalds j = 0; 19205d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, 0x09); 19215d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x20); 19221da177e4SLinus Torvalds 19235d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) { 19245d2a5a4fSOndrej Zary if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0) 19255d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x19, u3[j++]); 19261da177e4SLinus Torvalds cpu_relax(); 19271da177e4SLinus Torvalds } 192880b52a7fSOndrej Zary 19295d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00) 19301da177e4SLinus Torvalds cpu_relax(); 193180b52a7fSOndrej Zary 19325d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17) & 0x0f; 19331da177e4SLinus Torvalds if (j == 0x0f) { 19341da177e4SLinus Torvalds goto u3p_in; 19351da177e4SLinus Torvalds } 19361da177e4SLinus Torvalds if (j == 0x0a) { 19371da177e4SLinus Torvalds goto u3p_cmd; 19381da177e4SLinus Torvalds } 19391da177e4SLinus Torvalds if (j == 0x0e) { 19401da177e4SLinus Torvalds goto try_u3; 19411da177e4SLinus Torvalds } 19421da177e4SLinus Torvalds continue; 19431da177e4SLinus Torvalds u3p_out: 19445d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x20); 19455d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) { 19465d2a5a4fSOndrej Zary if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0) 19475d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x19, 0); 19481da177e4SLinus Torvalds cpu_relax(); 19491da177e4SLinus Torvalds } 19505d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17) & 0x0f; 19511da177e4SLinus Torvalds if (j == 0x0f) { 19521da177e4SLinus Torvalds goto u3p_in; 19531da177e4SLinus Torvalds } 19541da177e4SLinus Torvalds if (j == 0x0a) { 19551da177e4SLinus Torvalds goto u3p_cmd; 19561da177e4SLinus Torvalds } 19571da177e4SLinus Torvalds if (j == 0x0e) { 19581da177e4SLinus Torvalds goto u3p_out; 19591da177e4SLinus Torvalds } 19601da177e4SLinus Torvalds continue; 19611da177e4SLinus Torvalds u3p_in: 19625d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, 0x09); 19635d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x20); 19641da177e4SLinus Torvalds k = 0; 19651da177e4SLinus Torvalds u3p_in1: 19665d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x1f); 19671da177e4SLinus Torvalds if ((j & 0x01) != 0) { 19685d2a5a4fSOndrej Zary mbuf[k++] = atp_readb_io(dev, c, 0x19); 19691da177e4SLinus Torvalds goto u3p_in1; 19701da177e4SLinus Torvalds } 19711da177e4SLinus Torvalds if ((j & 0x80) == 0x00) { 19721da177e4SLinus Torvalds goto u3p_in1; 19731da177e4SLinus Torvalds } 19745d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17) & 0x0f; 19751da177e4SLinus Torvalds if (j == 0x0f) { 19761da177e4SLinus Torvalds goto u3p_in; 19771da177e4SLinus Torvalds } 19781da177e4SLinus Torvalds if (j == 0x0a) { 19791da177e4SLinus Torvalds goto u3p_cmd; 19801da177e4SLinus Torvalds } 19811da177e4SLinus Torvalds if (j == 0x0e) { 19821da177e4SLinus Torvalds goto u3p_out; 19831da177e4SLinus Torvalds } 19841da177e4SLinus Torvalds continue; 19851da177e4SLinus Torvalds u3p_cmd: 19865d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x10, 0x30); 19875d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, 0x00); 19885d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 198980b52a7fSOndrej Zary 19905d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00); 199180b52a7fSOndrej Zary 19925d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17); 19931da177e4SLinus Torvalds if (j != 0x16) { 19941da177e4SLinus Torvalds if (j == 0x4e) { 19951da177e4SLinus Torvalds goto u3p_out; 19961da177e4SLinus Torvalds } 19971da177e4SLinus Torvalds continue; 19981da177e4SLinus Torvalds } 19991da177e4SLinus Torvalds if (mbuf[0] != 0x01) { 20001da177e4SLinus Torvalds goto chg_wide; 20011da177e4SLinus Torvalds } 20021da177e4SLinus Torvalds if (mbuf[1] != 0x06) { 20031da177e4SLinus Torvalds goto chg_wide; 20041da177e4SLinus Torvalds } 20051da177e4SLinus Torvalds if (mbuf[2] != 0x04) { 20061da177e4SLinus Torvalds goto chg_wide; 20071da177e4SLinus Torvalds } 20081da177e4SLinus Torvalds if (mbuf[3] == 0x09) { 20091da177e4SLinus Torvalds m = 1; 20101da177e4SLinus Torvalds m = m << i; 20111da177e4SLinus Torvalds dev->wide_id[c] |= m; 20121da177e4SLinus Torvalds dev->id[c][i].devsp = 0xce; 20131da177e4SLinus Torvalds #ifdef ED_DBGP 20141da177e4SLinus Torvalds printk("dev->id[%2d][%2d].devsp = %2x\n",c,i,dev->id[c][i].devsp); 20151da177e4SLinus Torvalds #endif 20161da177e4SLinus Torvalds continue; 20171da177e4SLinus Torvalds } 20181da177e4SLinus Torvalds chg_wide: 20195d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x1b, 0x01); 20205d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 3, satn[0]); 20215d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 4, satn[1]); 20225d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 5, satn[2]); 20235d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 6, satn[3]); 20245d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 7, satn[4]); 20255d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 8, satn[5]); 20265d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x0f, 0); 20275d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp); 20285d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x12, 0); 20295d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x13, satn[6]); 20305d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, satn[7]); 20315d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, satn[8]); 20321da177e4SLinus Torvalds 20335d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) 20341da177e4SLinus Torvalds cpu_relax(); 203580b52a7fSOndrej Zary 203680b52a7fSOndrej Zary if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e) 20371da177e4SLinus Torvalds continue; 203880b52a7fSOndrej Zary 20395d2a5a4fSOndrej Zary while (atp_readb_io(dev, c, 0x17) != 0x8e) 20401da177e4SLinus Torvalds cpu_relax(); 204180b52a7fSOndrej Zary 20421da177e4SLinus Torvalds try_wide: 20431da177e4SLinus Torvalds j = 0; 20445d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, 0x05); 20455d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x20); 20461da177e4SLinus Torvalds 20475d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) { 20485d2a5a4fSOndrej Zary if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0) 20495d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x19, wide[j++]); 20501da177e4SLinus Torvalds cpu_relax(); 20511da177e4SLinus Torvalds } 205280b52a7fSOndrej Zary 20535d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00) 20541da177e4SLinus Torvalds cpu_relax(); 205580b52a7fSOndrej Zary 20565d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17) & 0x0f; 20571da177e4SLinus Torvalds if (j == 0x0f) { 20581da177e4SLinus Torvalds goto widep_in; 20591da177e4SLinus Torvalds } 20601da177e4SLinus Torvalds if (j == 0x0a) { 20611da177e4SLinus Torvalds goto widep_cmd; 20621da177e4SLinus Torvalds } 20631da177e4SLinus Torvalds if (j == 0x0e) { 20641da177e4SLinus Torvalds goto try_wide; 20651da177e4SLinus Torvalds } 20661da177e4SLinus Torvalds continue; 20671da177e4SLinus Torvalds widep_out: 20685d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x20); 20695d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) { 20705d2a5a4fSOndrej Zary if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0) 20715d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x19, 0); 20721da177e4SLinus Torvalds cpu_relax(); 20731da177e4SLinus Torvalds } 20745d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17) & 0x0f; 20751da177e4SLinus Torvalds if (j == 0x0f) { 20761da177e4SLinus Torvalds goto widep_in; 20771da177e4SLinus Torvalds } 20781da177e4SLinus Torvalds if (j == 0x0a) { 20791da177e4SLinus Torvalds goto widep_cmd; 20801da177e4SLinus Torvalds } 20811da177e4SLinus Torvalds if (j == 0x0e) { 20821da177e4SLinus Torvalds goto widep_out; 20831da177e4SLinus Torvalds } 20841da177e4SLinus Torvalds continue; 20851da177e4SLinus Torvalds widep_in: 20865d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, 0xff); 20875d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x20); 20881da177e4SLinus Torvalds k = 0; 20891da177e4SLinus Torvalds widep_in1: 20905d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x1f); 20911da177e4SLinus Torvalds if ((j & 0x01) != 0) { 20925d2a5a4fSOndrej Zary mbuf[k++] = atp_readb_io(dev, c, 0x19); 20931da177e4SLinus Torvalds goto widep_in1; 20941da177e4SLinus Torvalds } 20951da177e4SLinus Torvalds if ((j & 0x80) == 0x00) { 20961da177e4SLinus Torvalds goto widep_in1; 20971da177e4SLinus Torvalds } 20985d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17) & 0x0f; 20991da177e4SLinus Torvalds if (j == 0x0f) { 21001da177e4SLinus Torvalds goto widep_in; 21011da177e4SLinus Torvalds } 21021da177e4SLinus Torvalds if (j == 0x0a) { 21031da177e4SLinus Torvalds goto widep_cmd; 21041da177e4SLinus Torvalds } 21051da177e4SLinus Torvalds if (j == 0x0e) { 21061da177e4SLinus Torvalds goto widep_out; 21071da177e4SLinus Torvalds } 21081da177e4SLinus Torvalds continue; 21091da177e4SLinus Torvalds widep_cmd: 21105d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x10, 0x30); 21115d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, 0x00); 21125d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 211380b52a7fSOndrej Zary 21145d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) 21151da177e4SLinus Torvalds cpu_relax(); 211680b52a7fSOndrej Zary 21175d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17); 21181da177e4SLinus Torvalds if (j != 0x16) { 21191da177e4SLinus Torvalds if (j == 0x4e) { 21201da177e4SLinus Torvalds goto widep_out; 21211da177e4SLinus Torvalds } 21221da177e4SLinus Torvalds continue; 21231da177e4SLinus Torvalds } 21241da177e4SLinus Torvalds if (mbuf[0] != 0x01) { 21251da177e4SLinus Torvalds goto not_wide; 21261da177e4SLinus Torvalds } 21271da177e4SLinus Torvalds if (mbuf[1] != 0x02) { 21281da177e4SLinus Torvalds goto not_wide; 21291da177e4SLinus Torvalds } 21301da177e4SLinus Torvalds if (mbuf[2] != 0x03) { 21311da177e4SLinus Torvalds goto not_wide; 21321da177e4SLinus Torvalds } 21331da177e4SLinus Torvalds if (mbuf[3] != 0x01) { 21341da177e4SLinus Torvalds goto not_wide; 21351da177e4SLinus Torvalds } 21361da177e4SLinus Torvalds m = 1; 21371da177e4SLinus Torvalds m = m << i; 21381da177e4SLinus Torvalds dev->wide_id[c] |= m; 21391da177e4SLinus Torvalds not_wide: 214080b52a7fSOndrej Zary if ((dev->id[c][i].devtype == 0x00) || (dev->id[c][i].devtype == 0x07) || ((dev->id[c][i].devtype == 0x05) && ((n & 0x10) != 0))) { 21411da177e4SLinus Torvalds m = 1; 21421da177e4SLinus Torvalds m = m << i; 21431da177e4SLinus Torvalds if ((dev->async[c] & m) != 0) { 21441da177e4SLinus Torvalds goto set_sync; 21451da177e4SLinus Torvalds } 21461da177e4SLinus Torvalds } 21471da177e4SLinus Torvalds continue; 21481da177e4SLinus Torvalds set_sync: 2149460da918SOndrej Zary if ((dev->dev_id != ATP885_DEVID && dev->dev_id != ATP880_DEVID1 && dev->dev_id != ATP880_DEVID2) || (dev->sp[c][i] == 0x02)) { 21501da177e4SLinus Torvalds synu[4] = 0x0c; 21511da177e4SLinus Torvalds synuw[4] = 0x0c; 21521da177e4SLinus Torvalds } else { 21531da177e4SLinus Torvalds if (dev->sp[c][i] >= 0x03) { 21541da177e4SLinus Torvalds synu[4] = 0x0a; 21551da177e4SLinus Torvalds synuw[4] = 0x0a; 21561da177e4SLinus Torvalds } 21571da177e4SLinus Torvalds } 21581da177e4SLinus Torvalds j = 0; 21591da177e4SLinus Torvalds if ((m & dev->wide_id[c]) != 0) { 21601da177e4SLinus Torvalds j |= 0x01; 21611da177e4SLinus Torvalds } 21625d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x1b, j); 21635d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 3, satn[0]); 21645d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 4, satn[1]); 21655d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 5, satn[2]); 21665d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 6, satn[3]); 21675d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 7, satn[4]); 21685d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 8, satn[5]); 21695d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x0f, 0); 21705d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp); 21715d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x12, 0); 21725d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x13, satn[6]); 21735d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, satn[7]); 21745d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, satn[8]); 21751da177e4SLinus Torvalds 21765d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) 21771da177e4SLinus Torvalds cpu_relax(); 217880b52a7fSOndrej Zary 217980b52a7fSOndrej Zary if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e) 21801da177e4SLinus Torvalds continue; 218180b52a7fSOndrej Zary 21825d2a5a4fSOndrej Zary while (atp_readb_io(dev, c, 0x17) != 0x8e) 21831da177e4SLinus Torvalds cpu_relax(); 218480b52a7fSOndrej Zary 21851da177e4SLinus Torvalds try_sync: 21861da177e4SLinus Torvalds j = 0; 21875d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, 0x06); 21885d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x20); 21891da177e4SLinus Torvalds 21905d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) { 21915d2a5a4fSOndrej Zary if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0) { 21921da177e4SLinus Torvalds if ((m & dev->wide_id[c]) != 0) { 2193460da918SOndrej Zary if (dev->dev_id == ATP885_DEVID || dev->dev_id == ATP880_DEVID1 || dev->dev_id == ATP880_DEVID2) { 21941da177e4SLinus Torvalds if ((m & dev->ultra_map[c]) != 0) { 21955d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x19, synuw[j++]); 21961da177e4SLinus Torvalds } else { 21975d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x19, synw[j++]); 21981da177e4SLinus Torvalds } 2199460da918SOndrej Zary } else 2200460da918SOndrej Zary atp_writeb_io(dev, c, 0x19, synw_870[j++]); 22011da177e4SLinus Torvalds } else { 22021da177e4SLinus Torvalds if ((m & dev->ultra_map[c]) != 0) { 22035d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x19, synu[j++]); 22041da177e4SLinus Torvalds } else { 22055d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x19, synn[j++]); 22061da177e4SLinus Torvalds } 22071da177e4SLinus Torvalds } 22081da177e4SLinus Torvalds } 22091da177e4SLinus Torvalds } 221080b52a7fSOndrej Zary 22115d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00) 22121da177e4SLinus Torvalds cpu_relax(); 221380b52a7fSOndrej Zary 22145d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17) & 0x0f; 22151da177e4SLinus Torvalds if (j == 0x0f) { 22161da177e4SLinus Torvalds goto phase_ins; 22171da177e4SLinus Torvalds } 22181da177e4SLinus Torvalds if (j == 0x0a) { 22191da177e4SLinus Torvalds goto phase_cmds; 22201da177e4SLinus Torvalds } 22211da177e4SLinus Torvalds if (j == 0x0e) { 22221da177e4SLinus Torvalds goto try_sync; 22231da177e4SLinus Torvalds } 22241da177e4SLinus Torvalds continue; 22251da177e4SLinus Torvalds phase_outs: 22265d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x20); 22275d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) { 22285d2a5a4fSOndrej Zary if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0x00) 22295d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x19, 0x00); 22301da177e4SLinus Torvalds cpu_relax(); 22311da177e4SLinus Torvalds } 22325d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17); 22331da177e4SLinus Torvalds if (j == 0x85) { 22341da177e4SLinus Torvalds goto tar_dcons; 22351da177e4SLinus Torvalds } 22361da177e4SLinus Torvalds j &= 0x0f; 22371da177e4SLinus Torvalds if (j == 0x0f) { 22381da177e4SLinus Torvalds goto phase_ins; 22391da177e4SLinus Torvalds } 22401da177e4SLinus Torvalds if (j == 0x0a) { 22411da177e4SLinus Torvalds goto phase_cmds; 22421da177e4SLinus Torvalds } 22431da177e4SLinus Torvalds if (j == 0x0e) { 22441da177e4SLinus Torvalds goto phase_outs; 22451da177e4SLinus Torvalds } 22461da177e4SLinus Torvalds continue; 22471da177e4SLinus Torvalds phase_ins: 2248460da918SOndrej Zary if (dev->dev_id == ATP885_DEVID || dev->dev_id == ATP880_DEVID1 || dev->dev_id == ATP880_DEVID2) 22495d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, 0x06); 2250460da918SOndrej Zary else 2251460da918SOndrej Zary atp_writeb_io(dev, c, 0x14, 0xff); 22525d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x20); 22531da177e4SLinus Torvalds k = 0; 22541da177e4SLinus Torvalds phase_ins1: 22555d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x1f); 22561da177e4SLinus Torvalds if ((j & 0x01) != 0x00) { 22575d2a5a4fSOndrej Zary mbuf[k++] = atp_readb_io(dev, c, 0x19); 22581da177e4SLinus Torvalds goto phase_ins1; 22591da177e4SLinus Torvalds } 22601da177e4SLinus Torvalds if ((j & 0x80) == 0x00) { 22611da177e4SLinus Torvalds goto phase_ins1; 22621da177e4SLinus Torvalds } 226380b52a7fSOndrej Zary 22645d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00); 226580b52a7fSOndrej Zary 22665d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17); 22671da177e4SLinus Torvalds if (j == 0x85) { 22681da177e4SLinus Torvalds goto tar_dcons; 22691da177e4SLinus Torvalds } 22701da177e4SLinus Torvalds j &= 0x0f; 22711da177e4SLinus Torvalds if (j == 0x0f) { 22721da177e4SLinus Torvalds goto phase_ins; 22731da177e4SLinus Torvalds } 22741da177e4SLinus Torvalds if (j == 0x0a) { 22751da177e4SLinus Torvalds goto phase_cmds; 22761da177e4SLinus Torvalds } 22771da177e4SLinus Torvalds if (j == 0x0e) { 22781da177e4SLinus Torvalds goto phase_outs; 22791da177e4SLinus Torvalds } 22801da177e4SLinus Torvalds continue; 22811da177e4SLinus Torvalds phase_cmds: 22825d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x10, 0x30); 22831da177e4SLinus Torvalds tar_dcons: 22845d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, 0x00); 22855d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 228680b52a7fSOndrej Zary 22875d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) 22881da177e4SLinus Torvalds cpu_relax(); 228980b52a7fSOndrej Zary 22905d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17); 22911da177e4SLinus Torvalds if (j != 0x16) { 22921da177e4SLinus Torvalds continue; 22931da177e4SLinus Torvalds } 22941da177e4SLinus Torvalds if (mbuf[0] != 0x01) { 22951da177e4SLinus Torvalds continue; 22961da177e4SLinus Torvalds } 22971da177e4SLinus Torvalds if (mbuf[1] != 0x03) { 22981da177e4SLinus Torvalds continue; 22991da177e4SLinus Torvalds } 23001da177e4SLinus Torvalds if (mbuf[4] == 0x00) { 23011da177e4SLinus Torvalds continue; 23021da177e4SLinus Torvalds } 23031da177e4SLinus Torvalds if (mbuf[3] > 0x64) { 23041da177e4SLinus Torvalds continue; 23051da177e4SLinus Torvalds } 2306460da918SOndrej Zary if (dev->dev_id == ATP885_DEVID || dev->dev_id == ATP880_DEVID1 || dev->dev_id == ATP880_DEVID2) { 23071da177e4SLinus Torvalds if (mbuf[4] > 0x0e) { 23081da177e4SLinus Torvalds mbuf[4] = 0x0e; 23091da177e4SLinus Torvalds } 2310460da918SOndrej Zary } else { 2311460da918SOndrej Zary if (mbuf[4] > 0x0c) { 2312460da918SOndrej Zary mbuf[4] = 0x0c; 2313460da918SOndrej Zary } 2314460da918SOndrej Zary } 23151da177e4SLinus Torvalds dev->id[c][i].devsp = mbuf[4]; 2316460da918SOndrej Zary if (dev->dev_id == ATP885_DEVID || dev->dev_id == ATP880_DEVID1 || dev->dev_id == ATP880_DEVID2) 23171da177e4SLinus Torvalds if (mbuf[3] < 0x0c) { 23181da177e4SLinus Torvalds j = 0xb0; 23191da177e4SLinus Torvalds goto set_syn_ok; 23201da177e4SLinus Torvalds } 23211da177e4SLinus Torvalds if ((mbuf[3] < 0x0d) && (rmb == 0)) { 23221da177e4SLinus Torvalds j = 0xa0; 23231da177e4SLinus Torvalds goto set_syn_ok; 23241da177e4SLinus Torvalds } 23251da177e4SLinus Torvalds if (mbuf[3] < 0x1a) { 23261da177e4SLinus Torvalds j = 0x20; 23271da177e4SLinus Torvalds goto set_syn_ok; 23281da177e4SLinus Torvalds } 23291da177e4SLinus Torvalds if (mbuf[3] < 0x33) { 23301da177e4SLinus Torvalds j = 0x40; 23311da177e4SLinus Torvalds goto set_syn_ok; 23321da177e4SLinus Torvalds } 23331da177e4SLinus Torvalds if (mbuf[3] < 0x4c) { 23341da177e4SLinus Torvalds j = 0x50; 23351da177e4SLinus Torvalds goto set_syn_ok; 23361da177e4SLinus Torvalds } 23371da177e4SLinus Torvalds j = 0x60; 23381da177e4SLinus Torvalds set_syn_ok: 23391da177e4SLinus Torvalds dev->id[c][i].devsp = (dev->id[c][i].devsp & 0x0f) | j; 23401da177e4SLinus Torvalds #ifdef ED_DBGP 23411da177e4SLinus Torvalds printk("dev->id[%2d][%2d].devsp = %2x\n",c,i,dev->id[c][i].devsp); 23421da177e4SLinus Torvalds #endif 23431da177e4SLinus Torvalds } 23441da177e4SLinus Torvalds } 2345