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