109c434b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 21da177e4SLinus Torvalds /* 31da177e4SLinus Torvalds * Copyright (C) 1997 Wu Ching Chen 41da177e4SLinus Torvalds * 2.1.x update (C) 1998 Krzysztof G. Baranowski 5fa195afeSAlan Cox * 2.5.x update (C) 2002 Red Hat 6fa195afeSAlan Cox * 2.6.x update (C) 2004 Red Hat 71da177e4SLinus Torvalds * 81da177e4SLinus Torvalds * Marcelo Tosatti <marcelo@conectiva.com.br> : SMP fixes 91da177e4SLinus Torvalds * 101da177e4SLinus Torvalds * Wu Ching Chen : NULL pointer fixes 2000/06/02 111da177e4SLinus Torvalds * support atp876 chip 121da177e4SLinus Torvalds * enable 32 bit fifo transfer 131da177e4SLinus Torvalds * support cdrom & remove device run ultra speed 141da177e4SLinus Torvalds * fix disconnect bug 2000/12/21 151da177e4SLinus Torvalds * support atp880 chip lvd u160 2001/05/15 161da177e4SLinus Torvalds * fix prd table bug 2001/09/12 (7.1) 171da177e4SLinus Torvalds * 181da177e4SLinus Torvalds * atp885 support add by ACARD Hao Ping Lian 2005/01/05 191da177e4SLinus Torvalds */ 201da177e4SLinus Torvalds #include <linux/module.h> 211da177e4SLinus Torvalds #include <linux/init.h> 221da177e4SLinus Torvalds #include <linux/interrupt.h> 231da177e4SLinus Torvalds #include <linux/kernel.h> 241da177e4SLinus Torvalds #include <linux/types.h> 251da177e4SLinus Torvalds #include <linux/string.h> 261da177e4SLinus Torvalds #include <linux/ioport.h> 271da177e4SLinus Torvalds #include <linux/delay.h> 281da177e4SLinus Torvalds #include <linux/proc_fs.h> 291da177e4SLinus Torvalds #include <linux/spinlock.h> 301da177e4SLinus Torvalds #include <linux/pci.h> 311da177e4SLinus Torvalds #include <linux/blkdev.h> 32910638aeSMatthias Gehre #include <linux/dma-mapping.h> 335a0e3ad6STejun Heo #include <linux/slab.h> 341da177e4SLinus Torvalds #include <asm/io.h> 351da177e4SLinus Torvalds 361da177e4SLinus Torvalds #include <scsi/scsi.h> 371da177e4SLinus Torvalds #include <scsi/scsi_cmnd.h> 381da177e4SLinus Torvalds #include <scsi/scsi_device.h> 391da177e4SLinus Torvalds #include <scsi/scsi_host.h> 401da177e4SLinus Torvalds 411da177e4SLinus Torvalds #include "atp870u.h" 421da177e4SLinus Torvalds 431da177e4SLinus Torvalds static struct scsi_host_template atp870u_template; 441da177e4SLinus Torvalds static void send_s870(struct atp_unit *dev,unsigned char c); 45bcd5c59fSHannes Reinecke static void atp_is(struct atp_unit *dev, unsigned char c, bool wide_chip, 46bcd5c59fSHannes Reinecke unsigned char lvdmode); 471da177e4SLinus Torvalds 486a3cebb6SOndrej Zary static inline void atp_writeb_base(struct atp_unit *atp, u8 reg, u8 val) 496a3cebb6SOndrej Zary { 506a3cebb6SOndrej Zary outb(val, atp->baseport + reg); 516a3cebb6SOndrej Zary } 526a3cebb6SOndrej Zary 53d804bb25SOndrej Zary static inline void atp_writew_base(struct atp_unit *atp, u8 reg, u16 val) 54d804bb25SOndrej Zary { 55d804bb25SOndrej Zary outw(val, atp->baseport + reg); 56d804bb25SOndrej Zary } 57d804bb25SOndrej Zary 586a3cebb6SOndrej Zary static inline void atp_writeb_io(struct atp_unit *atp, u8 channel, u8 reg, u8 val) 596a3cebb6SOndrej Zary { 606a3cebb6SOndrej Zary outb(val, atp->ioport[channel] + reg); 616a3cebb6SOndrej Zary } 626a3cebb6SOndrej Zary 636a3cebb6SOndrej Zary static inline void atp_writew_io(struct atp_unit *atp, u8 channel, u8 reg, u16 val) 646a3cebb6SOndrej Zary { 656a3cebb6SOndrej Zary outw(val, atp->ioport[channel] + reg); 666a3cebb6SOndrej Zary } 676a3cebb6SOndrej Zary 686a3cebb6SOndrej Zary static inline void atp_writeb_pci(struct atp_unit *atp, u8 channel, u8 reg, u8 val) 696a3cebb6SOndrej Zary { 706a3cebb6SOndrej Zary outb(val, atp->pciport[channel] + reg); 716a3cebb6SOndrej Zary } 726a3cebb6SOndrej Zary 736a3cebb6SOndrej Zary static inline void atp_writel_pci(struct atp_unit *atp, u8 channel, u8 reg, u32 val) 746a3cebb6SOndrej Zary { 756a3cebb6SOndrej Zary outl(val, atp->pciport[channel] + reg); 766a3cebb6SOndrej Zary } 776a3cebb6SOndrej Zary 786a3cebb6SOndrej Zary static inline u8 atp_readb_base(struct atp_unit *atp, u8 reg) 796a3cebb6SOndrej Zary { 806a3cebb6SOndrej Zary return inb(atp->baseport + reg); 816a3cebb6SOndrej Zary } 826a3cebb6SOndrej Zary 83d804bb25SOndrej Zary static inline u16 atp_readw_base(struct atp_unit *atp, u8 reg) 84d804bb25SOndrej Zary { 85d804bb25SOndrej Zary return inw(atp->baseport + reg); 86d804bb25SOndrej Zary } 87d804bb25SOndrej Zary 88d804bb25SOndrej Zary static inline u32 atp_readl_base(struct atp_unit *atp, u8 reg) 89d804bb25SOndrej Zary { 90d804bb25SOndrej Zary return inl(atp->baseport + reg); 91d804bb25SOndrej Zary } 92d804bb25SOndrej Zary 936a3cebb6SOndrej Zary static inline u8 atp_readb_io(struct atp_unit *atp, u8 channel, u8 reg) 946a3cebb6SOndrej Zary { 956a3cebb6SOndrej Zary return inb(atp->ioport[channel] + reg); 966a3cebb6SOndrej Zary } 976a3cebb6SOndrej Zary 986a3cebb6SOndrej Zary static inline u16 atp_readw_io(struct atp_unit *atp, u8 channel, u8 reg) 996a3cebb6SOndrej Zary { 1006a3cebb6SOndrej Zary return inw(atp->ioport[channel] + reg); 1016a3cebb6SOndrej Zary } 1026a3cebb6SOndrej Zary 1036a3cebb6SOndrej Zary static inline u8 atp_readb_pci(struct atp_unit *atp, u8 channel, u8 reg) 1046a3cebb6SOndrej Zary { 1056a3cebb6SOndrej Zary return inb(atp->pciport[channel] + reg); 1066a3cebb6SOndrej Zary } 1076a3cebb6SOndrej Zary 108b922a449SOndrej Zary static inline bool is880(struct atp_unit *atp) 109b922a449SOndrej Zary { 110b922a449SOndrej Zary return atp->pdev->device == ATP880_DEVID1 || 111b922a449SOndrej Zary atp->pdev->device == ATP880_DEVID2; 112b922a449SOndrej Zary } 113b922a449SOndrej Zary 114b922a449SOndrej Zary static inline bool is885(struct atp_unit *atp) 115b922a449SOndrej Zary { 116b922a449SOndrej Zary return atp->pdev->device == ATP885_DEVID; 117b922a449SOndrej Zary } 118b922a449SOndrej Zary 1197d12e780SDavid Howells static irqreturn_t atp870u_intr_handle(int irq, void *dev_id) 1201da177e4SLinus Torvalds { 1211da177e4SLinus Torvalds unsigned long flags; 122bc0fe4c9SOndrej Zary unsigned short int id; 1231da177e4SLinus Torvalds unsigned char i, j, c, target_id, lun,cmdp; 1241da177e4SLinus Torvalds unsigned char *prd; 1251da177e4SLinus Torvalds struct scsi_cmnd *workreq; 1261da177e4SLinus Torvalds unsigned long adrcnt, k; 1271da177e4SLinus Torvalds #ifdef ED_DBGP 1281da177e4SLinus Torvalds unsigned long l; 1291da177e4SLinus Torvalds #endif 1301da177e4SLinus Torvalds struct Scsi_Host *host = dev_id; 1311da177e4SLinus Torvalds struct atp_unit *dev = (struct atp_unit *)&host->hostdata; 1321da177e4SLinus Torvalds 1331da177e4SLinus Torvalds for (c = 0; c < 2; c++) { 1346a3cebb6SOndrej Zary j = atp_readb_io(dev, c, 0x1f); 1351da177e4SLinus Torvalds if ((j & 0x80) != 0) 13678614ecdSOndrej Zary break; 1371da177e4SLinus Torvalds dev->in_int[c] = 0; 1381da177e4SLinus Torvalds } 13978614ecdSOndrej Zary if ((j & 0x80) == 0) 1401da177e4SLinus Torvalds return IRQ_NONE; 1411da177e4SLinus Torvalds #ifdef ED_DBGP 1421da177e4SLinus Torvalds printk("atp870u_intr_handle enter\n"); 1431da177e4SLinus Torvalds #endif 1441da177e4SLinus Torvalds dev->in_int[c] = 1; 1456a3cebb6SOndrej Zary cmdp = atp_readb_io(dev, c, 0x10); 1461da177e4SLinus Torvalds if (dev->working[c] != 0) { 147b922a449SOndrej Zary if (is885(dev)) { 1486a3cebb6SOndrej Zary if ((atp_readb_io(dev, c, 0x16) & 0x80) == 0) 149bcd5c59fSHannes Reinecke atp_writeb_io(dev, c, 0x16, 150bcd5c59fSHannes Reinecke (atp_readb_io(dev, c, 0x16) | 0x80)); 1511da177e4SLinus Torvalds } 1526a3cebb6SOndrej Zary if ((atp_readb_pci(dev, c, 0x00) & 0x08) != 0) 1531da177e4SLinus Torvalds { 1541da177e4SLinus Torvalds for (k=0; k < 1000; k++) { 1556a3cebb6SOndrej Zary if ((atp_readb_pci(dev, c, 2) & 0x08) == 0) 15678614ecdSOndrej Zary break; 1576a3cebb6SOndrej Zary if ((atp_readb_pci(dev, c, 2) & 0x01) == 0) 15878614ecdSOndrej Zary break; 1591da177e4SLinus Torvalds } 1601da177e4SLinus Torvalds } 1616a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 0, 0x00); 1621da177e4SLinus Torvalds 1636a3cebb6SOndrej Zary i = atp_readb_io(dev, c, 0x17); 1641da177e4SLinus Torvalds 165b922a449SOndrej Zary if (is885(dev)) 1666a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 2, 0x06); 1671da177e4SLinus Torvalds 1686a3cebb6SOndrej Zary target_id = atp_readb_io(dev, c, 0x15); 1691da177e4SLinus Torvalds 1701da177e4SLinus Torvalds /* 1711da177e4SLinus Torvalds * Remap wide devices onto id numbers 1721da177e4SLinus Torvalds */ 1731da177e4SLinus Torvalds 1741da177e4SLinus Torvalds if ((target_id & 0x40) != 0) { 1751da177e4SLinus Torvalds target_id = (target_id & 0x07) | 0x08; 1761da177e4SLinus Torvalds } else { 1771da177e4SLinus Torvalds target_id &= 0x07; 1781da177e4SLinus Torvalds } 1791da177e4SLinus Torvalds 1801da177e4SLinus Torvalds if ((j & 0x40) != 0) { 1811da177e4SLinus Torvalds if (dev->last_cmd[c] == 0xff) { 1821da177e4SLinus Torvalds dev->last_cmd[c] = target_id; 1831da177e4SLinus Torvalds } 1841da177e4SLinus Torvalds dev->last_cmd[c] |= 0x40; 1851da177e4SLinus Torvalds } 186b922a449SOndrej Zary if (is885(dev)) 1871da177e4SLinus Torvalds dev->r1f[c][target_id] |= j; 1881da177e4SLinus Torvalds #ifdef ED_DBGP 1891da177e4SLinus Torvalds printk("atp870u_intr_handle status = %x\n",i); 1901da177e4SLinus Torvalds #endif 1911da177e4SLinus Torvalds if (i == 0x85) { 1921da177e4SLinus Torvalds if ((dev->last_cmd[c] & 0xf0) != 0x40) { 1931da177e4SLinus Torvalds dev->last_cmd[c] = 0xff; 1941da177e4SLinus Torvalds } 195b922a449SOndrej Zary if (is885(dev)) { 1961da177e4SLinus Torvalds adrcnt = 0; 197bcd5c59fSHannes Reinecke ((unsigned char *) &adrcnt)[2] = 198bcd5c59fSHannes Reinecke atp_readb_io(dev, c, 0x12); 199bcd5c59fSHannes Reinecke ((unsigned char *) &adrcnt)[1] = 200bcd5c59fSHannes Reinecke atp_readb_io(dev, c, 0x13); 201bcd5c59fSHannes Reinecke ((unsigned char *) &adrcnt)[0] = 202bcd5c59fSHannes Reinecke atp_readb_io(dev, c, 0x14); 20322c0738bSColin Ian King if (dev->id[c][target_id].last_len != adrcnt) { 2041da177e4SLinus Torvalds k = dev->id[c][target_id].last_len; 2051da177e4SLinus Torvalds k -= adrcnt; 2061da177e4SLinus Torvalds dev->id[c][target_id].tran_len = k; 2071da177e4SLinus Torvalds dev->id[c][target_id].last_len = adrcnt; 2081da177e4SLinus Torvalds } 2091da177e4SLinus Torvalds #ifdef ED_DBGP 210bcd5c59fSHannes Reinecke printk("dev->id[c][target_id].last_len = %d " 211bcd5c59fSHannes Reinecke "dev->id[c][target_id].tran_len = %d\n", 212bcd5c59fSHannes Reinecke dev->id[c][target_id].last_len, 213bcd5c59fSHannes Reinecke dev->id[c][target_id].tran_len); 2141da177e4SLinus Torvalds #endif 2151da177e4SLinus Torvalds } 2161da177e4SLinus Torvalds 2171da177e4SLinus Torvalds /* 2181da177e4SLinus Torvalds * Flip wide 2191da177e4SLinus Torvalds */ 2201da177e4SLinus Torvalds if (dev->wide_id[c] != 0) { 2216a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x1b, 0x01); 2226a3cebb6SOndrej Zary while ((atp_readb_io(dev, c, 0x1b) & 0x01) != 0x01) 2236a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x1b, 0x01); 2241da177e4SLinus Torvalds } 2251da177e4SLinus Torvalds /* 2261da177e4SLinus Torvalds * Issue more commands 2271da177e4SLinus Torvalds */ 2281da177e4SLinus Torvalds spin_lock_irqsave(dev->host->host_lock, flags); 229bcd5c59fSHannes Reinecke if (((dev->quhd[c] != dev->quend[c]) || 230bcd5c59fSHannes Reinecke (dev->last_cmd[c] != 0xff)) && 2311da177e4SLinus Torvalds (dev->in_snd[c] == 0)) { 2321da177e4SLinus Torvalds #ifdef ED_DBGP 2331da177e4SLinus Torvalds printk("Call sent_s870\n"); 2341da177e4SLinus Torvalds #endif 2351da177e4SLinus Torvalds send_s870(dev,c); 2361da177e4SLinus Torvalds } 2371da177e4SLinus Torvalds spin_unlock_irqrestore(dev->host->host_lock, flags); 2381da177e4SLinus Torvalds /* 2391da177e4SLinus Torvalds * Done 2401da177e4SLinus Torvalds */ 2411da177e4SLinus Torvalds dev->in_int[c] = 0; 2421da177e4SLinus Torvalds #ifdef ED_DBGP 2431da177e4SLinus Torvalds printk("Status 0x85 return\n"); 2441da177e4SLinus Torvalds #endif 24578614ecdSOndrej Zary return IRQ_HANDLED; 2461da177e4SLinus Torvalds } 2471da177e4SLinus Torvalds 2481da177e4SLinus Torvalds if (i == 0x40) { 2491da177e4SLinus Torvalds dev->last_cmd[c] |= 0x40; 2501da177e4SLinus Torvalds dev->in_int[c] = 0; 25178614ecdSOndrej Zary return IRQ_HANDLED; 2521da177e4SLinus Torvalds } 2531da177e4SLinus Torvalds 2541da177e4SLinus Torvalds if (i == 0x21) { 2551da177e4SLinus Torvalds if ((dev->last_cmd[c] & 0xf0) != 0x40) { 2561da177e4SLinus Torvalds dev->last_cmd[c] = 0xff; 2571da177e4SLinus Torvalds } 2581da177e4SLinus Torvalds adrcnt = 0; 259bcd5c59fSHannes Reinecke ((unsigned char *) &adrcnt)[2] = 260bcd5c59fSHannes Reinecke atp_readb_io(dev, c, 0x12); 261bcd5c59fSHannes Reinecke ((unsigned char *) &adrcnt)[1] = 262bcd5c59fSHannes Reinecke atp_readb_io(dev, c, 0x13); 263bcd5c59fSHannes Reinecke ((unsigned char *) &adrcnt)[0] = 264bcd5c59fSHannes Reinecke atp_readb_io(dev, c, 0x14); 2651da177e4SLinus Torvalds k = dev->id[c][target_id].last_len; 2661da177e4SLinus Torvalds k -= adrcnt; 2671da177e4SLinus Torvalds dev->id[c][target_id].tran_len = k; 2681da177e4SLinus Torvalds dev->id[c][target_id].last_len = adrcnt; 2696a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x10, 0x41); 2706a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 2711da177e4SLinus Torvalds dev->in_int[c] = 0; 27278614ecdSOndrej Zary return IRQ_HANDLED; 2731da177e4SLinus Torvalds } 2741da177e4SLinus Torvalds 275b922a449SOndrej Zary if (is885(dev)) { 2761da177e4SLinus Torvalds if ((i == 0x4c) || (i == 0x4d) || (i == 0x8c) || (i == 0x8d)) { 2771da177e4SLinus Torvalds if ((i == 0x4c) || (i == 0x8c)) 2781da177e4SLinus Torvalds i=0x48; 2791da177e4SLinus Torvalds else 2801da177e4SLinus Torvalds i=0x49; 2811da177e4SLinus Torvalds } 2821da177e4SLinus Torvalds } 2831da177e4SLinus Torvalds if ((i == 0x80) || (i == 0x8f)) { 2841da177e4SLinus Torvalds #ifdef ED_DBGP 2851da177e4SLinus Torvalds printk(KERN_DEBUG "Device reselect\n"); 2861da177e4SLinus Torvalds #endif 2871da177e4SLinus Torvalds lun = 0; 2886a3cebb6SOndrej Zary if (cmdp == 0x44 || i == 0x80) 2896a3cebb6SOndrej Zary lun = atp_readb_io(dev, c, 0x1d) & 0x07; 2906a3cebb6SOndrej Zary else { 2911da177e4SLinus Torvalds if ((dev->last_cmd[c] & 0xf0) != 0x40) { 2921da177e4SLinus Torvalds dev->last_cmd[c] = 0xff; 2931da177e4SLinus Torvalds } 2941da177e4SLinus Torvalds if (cmdp == 0x41) { 2951da177e4SLinus Torvalds #ifdef ED_DBGP 2961da177e4SLinus Torvalds printk("cmdp = 0x41\n"); 2971da177e4SLinus Torvalds #endif 2981da177e4SLinus Torvalds adrcnt = 0; 299bcd5c59fSHannes Reinecke ((unsigned char *) &adrcnt)[2] = 300bcd5c59fSHannes Reinecke atp_readb_io(dev, c, 0x12); 301bcd5c59fSHannes Reinecke ((unsigned char *) &adrcnt)[1] = 302bcd5c59fSHannes Reinecke atp_readb_io(dev, c, 0x13); 303bcd5c59fSHannes Reinecke ((unsigned char *) &adrcnt)[0] = 304bcd5c59fSHannes Reinecke atp_readb_io(dev, c, 0x14); 3051da177e4SLinus Torvalds k = dev->id[c][target_id].last_len; 3061da177e4SLinus Torvalds k -= adrcnt; 3071da177e4SLinus Torvalds dev->id[c][target_id].tran_len = k; 3081da177e4SLinus Torvalds dev->id[c][target_id].last_len = adrcnt; 3096a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 3101da177e4SLinus Torvalds dev->in_int[c] = 0; 31178614ecdSOndrej Zary return IRQ_HANDLED; 3121da177e4SLinus Torvalds } else { 3131da177e4SLinus Torvalds #ifdef ED_DBGP 3141da177e4SLinus Torvalds printk("cmdp != 0x41\n"); 3151da177e4SLinus Torvalds #endif 3166a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x10, 0x46); 3171da177e4SLinus Torvalds dev->id[c][target_id].dirct = 0x00; 3186a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x12, 0x00); 3196a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x13, 0x00); 3206a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x14, 0x00); 3216a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 3221da177e4SLinus Torvalds dev->in_int[c] = 0; 32378614ecdSOndrej Zary return IRQ_HANDLED; 3241da177e4SLinus Torvalds } 3251da177e4SLinus Torvalds } 3261da177e4SLinus Torvalds if (dev->last_cmd[c] != 0xff) { 3271da177e4SLinus Torvalds dev->last_cmd[c] |= 0x40; 3281da177e4SLinus Torvalds } 329b922a449SOndrej Zary if (is885(dev)) { 3306a3cebb6SOndrej Zary j = atp_readb_base(dev, 0x29) & 0xfe; 3316a3cebb6SOndrej Zary atp_writeb_base(dev, 0x29, j); 3323a38e53eSOndrej Zary } else 3336a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x10, 0x45); 3341da177e4SLinus Torvalds 3356a3cebb6SOndrej Zary target_id = atp_readb_io(dev, c, 0x16); 3361da177e4SLinus Torvalds /* 3371da177e4SLinus Torvalds * Remap wide identifiers 3381da177e4SLinus Torvalds */ 3391da177e4SLinus Torvalds if ((target_id & 0x10) != 0) { 3401da177e4SLinus Torvalds target_id = (target_id & 0x07) | 0x08; 3411da177e4SLinus Torvalds } else { 3421da177e4SLinus Torvalds target_id &= 0x07; 3431da177e4SLinus Torvalds } 344b922a449SOndrej Zary if (is885(dev)) 3456a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x10, 0x45); 3461da177e4SLinus Torvalds workreq = dev->id[c][target_id].curr_req; 3471da177e4SLinus Torvalds #ifdef ED_DBGP 348017560fcSJeff Garzik scmd_printk(KERN_DEBUG, workreq, "CDB"); 3491da177e4SLinus Torvalds for (l = 0; l < workreq->cmd_len; l++) 3501da177e4SLinus Torvalds printk(KERN_DEBUG " %x",workreq->cmnd[l]); 351017560fcSJeff Garzik printk("\n"); 3521da177e4SLinus Torvalds #endif 3531da177e4SLinus Torvalds 3546a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x0f, lun); 3556a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x11, dev->id[c][target_id].devsp); 3561da177e4SLinus Torvalds adrcnt = dev->id[c][target_id].tran_len; 3571da177e4SLinus Torvalds k = dev->id[c][target_id].last_len; 3581da177e4SLinus Torvalds 3596a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x12, ((unsigned char *) &k)[2]); 3606a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x13, ((unsigned char *) &k)[1]); 3616a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x14, ((unsigned char *) &k)[0]); 3621da177e4SLinus Torvalds #ifdef ED_DBGP 363bcd5c59fSHannes Reinecke printk("k %x, k[0] 0x%x k[1] 0x%x k[2] 0x%x\n", k, 364bcd5c59fSHannes Reinecke atp_readb_io(dev, c, 0x14), 365bcd5c59fSHannes Reinecke atp_readb_io(dev, c, 0x13), 366bcd5c59fSHannes Reinecke atp_readb_io(dev, c, 0x12)); 3671da177e4SLinus Torvalds #endif 3681da177e4SLinus Torvalds /* Remap wide */ 3691da177e4SLinus Torvalds j = target_id; 3701da177e4SLinus Torvalds if (target_id > 7) { 3711da177e4SLinus Torvalds j = (j & 0x07) | 0x40; 3721da177e4SLinus Torvalds } 3731da177e4SLinus Torvalds /* Add direction */ 3741da177e4SLinus Torvalds j |= dev->id[c][target_id].dirct; 3756a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x15, j); 3766a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x16, 0x80); 3771da177e4SLinus Torvalds 3781da177e4SLinus Torvalds /* enable 32 bit fifo transfer */ 379b922a449SOndrej Zary if (is885(dev)) { 3806a3cebb6SOndrej Zary i = atp_readb_pci(dev, c, 1) & 0xf3; 3811da177e4SLinus Torvalds //j=workreq->cmnd[0]; 382f3272258SHannes Reinecke if ((workreq->cmnd[0] == READ_6) || 383f3272258SHannes Reinecke (workreq->cmnd[0] == READ_10) || 384f3272258SHannes Reinecke (workreq->cmnd[0] == WRITE_6) || 385f3272258SHannes Reinecke (workreq->cmnd[0] == WRITE_10)) { 3861da177e4SLinus Torvalds i |= 0x0c; 3871da177e4SLinus Torvalds } 3886a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 1, i); 389b922a449SOndrej Zary } else if (is880(dev)) { 390f3272258SHannes Reinecke if ((workreq->cmnd[0] == READ_6) || 391f3272258SHannes Reinecke (workreq->cmnd[0] == READ_10) || 392f3272258SHannes Reinecke (workreq->cmnd[0] == WRITE_6) || 393f3272258SHannes Reinecke (workreq->cmnd[0] == WRITE_10)) 394bcd5c59fSHannes Reinecke atp_writeb_base(dev, 0x3b, 395bcd5c59fSHannes Reinecke (atp_readb_base(dev, 0x3b) & 0x3f) | 0xc0); 3966a3cebb6SOndrej Zary else 397bcd5c59fSHannes Reinecke atp_writeb_base(dev, 0x3b, 398bcd5c59fSHannes Reinecke atp_readb_base(dev, 0x3b) & 0x3f); 3991da177e4SLinus Torvalds } else { 400f3272258SHannes Reinecke if ((workreq->cmnd[0] == READ_6) || 401f3272258SHannes Reinecke (workreq->cmnd[0] == READ_10) || 402f3272258SHannes Reinecke (workreq->cmnd[0] == WRITE_6) || 403f3272258SHannes Reinecke (workreq->cmnd[0] == WRITE_10)) 404bcd5c59fSHannes Reinecke atp_writeb_base(dev, 0x3a, 405bcd5c59fSHannes Reinecke (atp_readb_base(dev, 0x3a) & 0xf3) | 0x08); 4066a3cebb6SOndrej Zary else 407bcd5c59fSHannes Reinecke atp_writeb_base(dev, 0x3a, 408bcd5c59fSHannes Reinecke atp_readb_base(dev, 0x3a) & 0xf3); 4091da177e4SLinus Torvalds } 4101da177e4SLinus Torvalds j = 0; 4111da177e4SLinus Torvalds id = 1; 4121da177e4SLinus Torvalds id = id << target_id; 4131da177e4SLinus Torvalds /* 4141da177e4SLinus Torvalds * Is this a wide device 4151da177e4SLinus Torvalds */ 4161da177e4SLinus Torvalds if ((id & dev->wide_id[c]) != 0) { 4171da177e4SLinus Torvalds j |= 0x01; 4181da177e4SLinus Torvalds } 4196a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x1b, j); 4206a3cebb6SOndrej Zary while ((atp_readb_io(dev, c, 0x1b) & 0x01) != j) 4216a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x1b, j); 4221da177e4SLinus Torvalds if (dev->id[c][target_id].last_len == 0) { 4236a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 4241da177e4SLinus Torvalds dev->in_int[c] = 0; 4251da177e4SLinus Torvalds #ifdef ED_DBGP 4261da177e4SLinus Torvalds printk("dev->id[c][target_id].last_len = 0\n"); 4271da177e4SLinus Torvalds #endif 42878614ecdSOndrej Zary return IRQ_HANDLED; 4291da177e4SLinus Torvalds } 4301da177e4SLinus Torvalds #ifdef ED_DBGP 4311da177e4SLinus Torvalds printk("target_id = %d adrcnt = %d\n",target_id,adrcnt); 4321da177e4SLinus Torvalds #endif 4331da177e4SLinus Torvalds prd = dev->id[c][target_id].prd_pos; 4341da177e4SLinus Torvalds while (adrcnt != 0) { 4351da177e4SLinus Torvalds id = ((unsigned short int *)prd)[2]; 4361da177e4SLinus Torvalds if (id == 0) { 4371da177e4SLinus Torvalds k = 0x10000; 4381da177e4SLinus Torvalds } else { 4391da177e4SLinus Torvalds k = id; 4401da177e4SLinus Torvalds } 4411da177e4SLinus Torvalds if (k > adrcnt) { 442bcd5c59fSHannes Reinecke ((unsigned short int *)prd)[2] = 443bcd5c59fSHannes Reinecke (unsigned short int)(k - adrcnt); 4441da177e4SLinus Torvalds ((unsigned long *)prd)[0] += adrcnt; 4451da177e4SLinus Torvalds adrcnt = 0; 4461da177e4SLinus Torvalds dev->id[c][target_id].prd_pos = prd; 4471da177e4SLinus Torvalds } else { 4481da177e4SLinus Torvalds adrcnt -= k; 4491da177e4SLinus Torvalds dev->id[c][target_id].prdaddr += 0x08; 4501da177e4SLinus Torvalds prd += 0x08; 4511da177e4SLinus Torvalds if (adrcnt == 0) { 4521da177e4SLinus Torvalds dev->id[c][target_id].prd_pos = prd; 4531da177e4SLinus Torvalds } 4541da177e4SLinus Torvalds } 4551da177e4SLinus Torvalds } 4566a3cebb6SOndrej Zary atp_writel_pci(dev, c, 0x04, dev->id[c][target_id].prdaddr); 4571da177e4SLinus Torvalds #ifdef ED_DBGP 458bcd5c59fSHannes Reinecke printk("dev->id[%d][%d].prdaddr 0x%8x\n", 459bcd5c59fSHannes Reinecke c, target_id, dev->id[c][target_id].prdaddr); 4601da177e4SLinus Torvalds #endif 461b922a449SOndrej Zary if (!is885(dev)) { 4626a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 2, 0x06); 4636a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 2, 0x00); 4641da177e4SLinus Torvalds } 4651da177e4SLinus Torvalds /* 4661da177e4SLinus Torvalds * Check transfer direction 4671da177e4SLinus Torvalds */ 4681da177e4SLinus Torvalds if (dev->id[c][target_id].dirct != 0) { 4696a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 4706a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 0, 0x01); 4711da177e4SLinus Torvalds dev->in_int[c] = 0; 4721da177e4SLinus Torvalds #ifdef ED_DBGP 4731da177e4SLinus Torvalds printk("status 0x80 return dirct != 0\n"); 4741da177e4SLinus Torvalds #endif 47578614ecdSOndrej Zary return IRQ_HANDLED; 4761da177e4SLinus Torvalds } 4776a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 4786a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 0, 0x09); 4791da177e4SLinus Torvalds dev->in_int[c] = 0; 4801da177e4SLinus Torvalds #ifdef ED_DBGP 4811da177e4SLinus Torvalds printk("status 0x80 return dirct = 0\n"); 4821da177e4SLinus Torvalds #endif 48378614ecdSOndrej Zary return IRQ_HANDLED; 4841da177e4SLinus Torvalds } 4851da177e4SLinus Torvalds 4861da177e4SLinus Torvalds /* 4871da177e4SLinus Torvalds * Current scsi request on this target 4881da177e4SLinus Torvalds */ 4891da177e4SLinus Torvalds 4901da177e4SLinus Torvalds workreq = dev->id[c][target_id].curr_req; 4911da177e4SLinus Torvalds 49278614ecdSOndrej Zary if (i == 0x42 || i == 0x16) { 4931da177e4SLinus Torvalds if ((dev->last_cmd[c] & 0xf0) != 0x40) { 4941da177e4SLinus Torvalds dev->last_cmd[c] = 0xff; 4951da177e4SLinus Torvalds } 49678614ecdSOndrej Zary if (i == 0x16) { 4976a3cebb6SOndrej Zary workreq->result = atp_readb_io(dev, c, 0x0f); 498b922a449SOndrej Zary if (((dev->r1f[c][target_id] & 0x10) != 0) && is885(dev)) { 4991da177e4SLinus Torvalds printk(KERN_WARNING "AEC67162 CRC ERROR !\n"); 500f3272258SHannes Reinecke workreq->result = SAM_STAT_CHECK_CONDITION; 5011da177e4SLinus Torvalds } 50278614ecdSOndrej Zary } else 503f3272258SHannes Reinecke workreq->result = SAM_STAT_CHECK_CONDITION; 50478614ecdSOndrej Zary 505b922a449SOndrej Zary if (is885(dev)) { 5066a3cebb6SOndrej Zary j = atp_readb_base(dev, 0x29) | 0x01; 5076a3cebb6SOndrej Zary atp_writeb_base(dev, 0x29, j); 5081da177e4SLinus Torvalds } 5091da177e4SLinus Torvalds /* 5101da177e4SLinus Torvalds * Complete the command 5111da177e4SLinus Torvalds */ 512fe7ed98fSBoaz Harrosh scsi_dma_unmap(workreq); 513fe7ed98fSBoaz Harrosh 5141da177e4SLinus Torvalds spin_lock_irqsave(dev->host->host_lock, flags); 515*681fa525SBart Van Assche scsi_done(workreq); 5161da177e4SLinus Torvalds #ifdef ED_DBGP 5171da177e4SLinus Torvalds printk("workreq->scsi_done\n"); 5181da177e4SLinus Torvalds #endif 5191da177e4SLinus Torvalds /* 5201da177e4SLinus Torvalds * Clear it off the queue 5211da177e4SLinus Torvalds */ 5221da177e4SLinus Torvalds dev->id[c][target_id].curr_req = NULL; 5231da177e4SLinus Torvalds dev->working[c]--; 5241da177e4SLinus Torvalds spin_unlock_irqrestore(dev->host->host_lock, flags); 5251da177e4SLinus Torvalds /* 5261da177e4SLinus Torvalds * Take it back wide 5271da177e4SLinus Torvalds */ 5281da177e4SLinus Torvalds if (dev->wide_id[c] != 0) { 5296a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x1b, 0x01); 5306a3cebb6SOndrej Zary while ((atp_readb_io(dev, c, 0x1b) & 0x01) != 0x01) 5316a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x1b, 0x01); 5321da177e4SLinus Torvalds } 5331da177e4SLinus Torvalds /* 5341da177e4SLinus Torvalds * If there is stuff to send and nothing going then send it 5351da177e4SLinus Torvalds */ 5361da177e4SLinus Torvalds spin_lock_irqsave(dev->host->host_lock, flags); 537bcd5c59fSHannes Reinecke if (((dev->last_cmd[c] != 0xff) || 538bcd5c59fSHannes Reinecke (dev->quhd[c] != dev->quend[c])) && 5391da177e4SLinus Torvalds (dev->in_snd[c] == 0)) { 5401da177e4SLinus Torvalds #ifdef ED_DBGP 5411da177e4SLinus Torvalds printk("Call sent_s870(scsi_done)\n"); 5421da177e4SLinus Torvalds #endif 5431da177e4SLinus Torvalds send_s870(dev,c); 5441da177e4SLinus Torvalds } 5451da177e4SLinus Torvalds spin_unlock_irqrestore(dev->host->host_lock, flags); 5461da177e4SLinus Torvalds dev->in_int[c] = 0; 54778614ecdSOndrej Zary return IRQ_HANDLED; 5481da177e4SLinus Torvalds } 5491da177e4SLinus Torvalds if ((dev->last_cmd[c] & 0xf0) != 0x40) { 5501da177e4SLinus Torvalds dev->last_cmd[c] = 0xff; 5511da177e4SLinus Torvalds } 5521da177e4SLinus Torvalds if (i == 0x4f) { 5531da177e4SLinus Torvalds i = 0x89; 5541da177e4SLinus Torvalds } 5551da177e4SLinus Torvalds i &= 0x0f; 5561da177e4SLinus Torvalds if (i == 0x09) { 5576a3cebb6SOndrej Zary atp_writel_pci(dev, c, 4, dev->id[c][target_id].prdaddr); 5586a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 2, 0x06); 5596a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 2, 0x00); 5606a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x10, 0x41); 561b922a449SOndrej Zary if (is885(dev)) { 5621da177e4SLinus Torvalds k = dev->id[c][target_id].last_len; 563bcd5c59fSHannes Reinecke atp_writeb_io(dev, c, 0x12, 564bcd5c59fSHannes Reinecke ((unsigned char *) (&k))[2]); 565bcd5c59fSHannes Reinecke atp_writeb_io(dev, c, 0x13, 566bcd5c59fSHannes Reinecke ((unsigned char *) (&k))[1]); 567bcd5c59fSHannes Reinecke atp_writeb_io(dev, c, 0x14, 568bcd5c59fSHannes Reinecke ((unsigned char *) (&k))[0]); 5691da177e4SLinus Torvalds dev->id[c][target_id].dirct = 0x00; 5701da177e4SLinus Torvalds } else { 5711da177e4SLinus Torvalds dev->id[c][target_id].dirct = 0x00; 5721da177e4SLinus Torvalds } 5736a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 5746a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 0, 0x09); 5751da177e4SLinus Torvalds dev->in_int[c] = 0; 57678614ecdSOndrej Zary return IRQ_HANDLED; 5771da177e4SLinus Torvalds } 5781da177e4SLinus Torvalds if (i == 0x08) { 5796a3cebb6SOndrej Zary atp_writel_pci(dev, c, 4, dev->id[c][target_id].prdaddr); 5806a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 2, 0x06); 5816a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 2, 0x00); 5826a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x10, 0x41); 583b922a449SOndrej Zary if (is885(dev)) { 5841da177e4SLinus Torvalds k = dev->id[c][target_id].last_len; 585bcd5c59fSHannes Reinecke atp_writeb_io(dev, c, 0x12, 586bcd5c59fSHannes Reinecke ((unsigned char *) (&k))[2]); 587bcd5c59fSHannes Reinecke atp_writeb_io(dev, c, 0x13, 588bcd5c59fSHannes Reinecke ((unsigned char *) (&k))[1]); 589bcd5c59fSHannes Reinecke atp_writeb_io(dev, c, 0x14, 590bcd5c59fSHannes Reinecke ((unsigned char *) (&k))[0]); 5911da177e4SLinus Torvalds } 592bcd5c59fSHannes Reinecke atp_writeb_io(dev, c, 0x15, 593bcd5c59fSHannes Reinecke atp_readb_io(dev, c, 0x15) | 0x20); 5941da177e4SLinus Torvalds dev->id[c][target_id].dirct = 0x20; 5956a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 5966a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 0, 0x01); 5971da177e4SLinus Torvalds dev->in_int[c] = 0; 59878614ecdSOndrej Zary return IRQ_HANDLED; 5991da177e4SLinus Torvalds } 6006a3cebb6SOndrej Zary if (i == 0x0a) 6016a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x10, 0x30); 6026a3cebb6SOndrej Zary else 6036a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x10, 0x46); 6041da177e4SLinus Torvalds dev->id[c][target_id].dirct = 0x00; 6056a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x12, 0x00); 6066a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x13, 0x00); 6076a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x14, 0x00); 6086a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 6091da177e4SLinus Torvalds } 61078614ecdSOndrej Zary dev->in_int[c] = 0; 6111da177e4SLinus Torvalds 6121da177e4SLinus Torvalds return IRQ_HANDLED; 6131da177e4SLinus Torvalds } 6141da177e4SLinus Torvalds /** 6156b71f60cSLee Jones * atp870u_queuecommand_lck - Queue SCSI command 6161da177e4SLinus Torvalds * @req_p: request block 6171da177e4SLinus Torvalds * @done: completion function 6181da177e4SLinus Torvalds * 6191da177e4SLinus Torvalds * Queue a command to the ATP queue. Called with the host lock held. 6201da177e4SLinus Torvalds */ 621f281233dSJeff Garzik static int atp870u_queuecommand_lck(struct scsi_cmnd *req_p, 6221da177e4SLinus Torvalds void (*done) (struct scsi_cmnd *)) 6231da177e4SLinus Torvalds { 6241da177e4SLinus Torvalds unsigned char c; 6253b836464SOndrej Zary unsigned int m; 6261da177e4SLinus Torvalds struct atp_unit *dev; 6271da177e4SLinus Torvalds struct Scsi_Host *host; 6281da177e4SLinus Torvalds 629422c0d61SJeff Garzik c = scmd_channel(req_p); 6301da177e4SLinus Torvalds req_p->sense_buffer[0]=0; 631fe7ed98fSBoaz Harrosh scsi_set_resid(req_p, 0); 632422c0d61SJeff Garzik if (scmd_channel(req_p) > 1) { 633f3272258SHannes Reinecke req_p->result = DID_BAD_TARGET << 16; 6341da177e4SLinus Torvalds done(req_p); 6351da177e4SLinus Torvalds #ifdef ED_DBGP 6361da177e4SLinus Torvalds printk("atp870u_queuecommand : req_p->device->channel > 1\n"); 6371da177e4SLinus Torvalds #endif 6381da177e4SLinus Torvalds return 0; 6391da177e4SLinus Torvalds } 6401da177e4SLinus Torvalds 6411da177e4SLinus Torvalds host = req_p->device->host; 6421da177e4SLinus Torvalds dev = (struct atp_unit *)&host->hostdata; 6431da177e4SLinus Torvalds 6441da177e4SLinus Torvalds m = 1; 645422c0d61SJeff Garzik m = m << scmd_id(req_p); 6461da177e4SLinus Torvalds 6471da177e4SLinus Torvalds /* 6481da177e4SLinus Torvalds * Fake a timeout for missing targets 6491da177e4SLinus Torvalds */ 6501da177e4SLinus Torvalds 6511da177e4SLinus Torvalds if ((m & dev->active_id[c]) == 0) { 652f3272258SHannes Reinecke req_p->result = DID_BAD_TARGET << 16; 6531da177e4SLinus Torvalds done(req_p); 6541da177e4SLinus Torvalds return 0; 6551da177e4SLinus Torvalds } 6561da177e4SLinus Torvalds 6571da177e4SLinus Torvalds /* 6581da177e4SLinus Torvalds * Count new command 6591da177e4SLinus Torvalds */ 6601da177e4SLinus Torvalds dev->quend[c]++; 6611da177e4SLinus Torvalds if (dev->quend[c] >= qcnt) { 6621da177e4SLinus Torvalds dev->quend[c] = 0; 6631da177e4SLinus Torvalds } 6641da177e4SLinus Torvalds 6651da177e4SLinus Torvalds /* 6661da177e4SLinus Torvalds * Check queue state 6671da177e4SLinus Torvalds */ 6681da177e4SLinus Torvalds if (dev->quhd[c] == dev->quend[c]) { 6691da177e4SLinus Torvalds if (dev->quend[c] == 0) { 6701da177e4SLinus Torvalds dev->quend[c] = qcnt; 6711da177e4SLinus Torvalds } 6721da177e4SLinus Torvalds #ifdef ED_DBGP 6731da177e4SLinus Torvalds printk("atp870u_queuecommand : dev->quhd[c] == dev->quend[c]\n"); 6741da177e4SLinus Torvalds #endif 6751da177e4SLinus Torvalds dev->quend[c]--; 676f3272258SHannes Reinecke req_p->result = DID_BUS_BUSY << 16; 6771da177e4SLinus Torvalds done(req_p); 6781da177e4SLinus Torvalds return 0; 6791da177e4SLinus Torvalds } 6801da177e4SLinus Torvalds dev->quereq[c][dev->quend[c]] = req_p; 6811da177e4SLinus Torvalds #ifdef ED_DBGP 682bcd5c59fSHannes Reinecke printk("dev->ioport[c] = %x atp_readb_io(dev, c, 0x1c) = %x " 683bcd5c59fSHannes Reinecke "dev->in_int[%d] = %d dev->in_snd[%d] = %d\n", 684bcd5c59fSHannes Reinecke dev->ioport[c], atp_readb_io(dev, c, 0x1c), c, 685bcd5c59fSHannes Reinecke dev->in_int[c],c,dev->in_snd[c]); 6861da177e4SLinus Torvalds #endif 687bcd5c59fSHannes Reinecke if ((atp_readb_io(dev, c, 0x1c) == 0) && 688bcd5c59fSHannes Reinecke (dev->in_int[c] == 0) && 689bcd5c59fSHannes Reinecke (dev->in_snd[c] == 0)) { 6901da177e4SLinus Torvalds #ifdef ED_DBGP 6911da177e4SLinus Torvalds printk("Call sent_s870(atp870u_queuecommand)\n"); 6921da177e4SLinus Torvalds #endif 6931da177e4SLinus Torvalds send_s870(dev,c); 6941da177e4SLinus Torvalds } 6951da177e4SLinus Torvalds #ifdef ED_DBGP 6961da177e4SLinus Torvalds printk("atp870u_queuecommand : exit\n"); 6971da177e4SLinus Torvalds #endif 6981da177e4SLinus Torvalds return 0; 6991da177e4SLinus Torvalds } 7001da177e4SLinus Torvalds 701f281233dSJeff Garzik static DEF_SCSI_QCMD(atp870u_queuecommand) 702f281233dSJeff Garzik 7036b71f60cSLee Jones /* 7041da177e4SLinus Torvalds * send_s870 - send a command to the controller 7051da177e4SLinus Torvalds * 7061da177e4SLinus Torvalds * On entry there is work queued to be done. We move some of that work to the 7071da177e4SLinus Torvalds * controller itself. 7081da177e4SLinus Torvalds * 7091da177e4SLinus Torvalds * Caller holds the host lock. 7101da177e4SLinus Torvalds */ 7111da177e4SLinus Torvalds static void send_s870(struct atp_unit *dev, unsigned char c) 7121da177e4SLinus Torvalds { 713468b8968SOndrej Zary struct scsi_cmnd *workreq = NULL; 7141da177e4SLinus Torvalds unsigned int i;//,k; 7151da177e4SLinus Torvalds unsigned char j, target_id; 7161da177e4SLinus Torvalds unsigned char *prd; 717c2bab403SOndrej Zary unsigned short int w; 7181da177e4SLinus Torvalds unsigned long l, bttl = 0; 7191da177e4SLinus Torvalds unsigned long sg_count; 7201da177e4SLinus Torvalds 7211da177e4SLinus Torvalds if (dev->in_snd[c] != 0) { 7221da177e4SLinus Torvalds #ifdef ED_DBGP 7231da177e4SLinus Torvalds printk("cmnd in_snd\n"); 7241da177e4SLinus Torvalds #endif 7251da177e4SLinus Torvalds return; 7261da177e4SLinus Torvalds } 7271da177e4SLinus Torvalds #ifdef ED_DBGP 7281da177e4SLinus Torvalds printk("Sent_s870 enter\n"); 7291da177e4SLinus Torvalds #endif 7301da177e4SLinus Torvalds dev->in_snd[c] = 1; 7311da177e4SLinus Torvalds if ((dev->last_cmd[c] != 0xff) && ((dev->last_cmd[c] & 0x40) != 0)) { 7321da177e4SLinus Torvalds dev->last_cmd[c] &= 0x0f; 7331da177e4SLinus Torvalds workreq = dev->id[c][dev->last_cmd[c]].curr_req; 734468b8968SOndrej Zary if (!workreq) { 7351da177e4SLinus Torvalds dev->last_cmd[c] = 0xff; 7361da177e4SLinus Torvalds if (dev->quhd[c] == dev->quend[c]) { 7371da177e4SLinus Torvalds dev->in_snd[c] = 0; 7381da177e4SLinus Torvalds return; 7391da177e4SLinus Torvalds } 7401da177e4SLinus Torvalds } 741468b8968SOndrej Zary } 742468b8968SOndrej Zary if (!workreq) { 7431da177e4SLinus Torvalds if ((dev->last_cmd[c] != 0xff) && (dev->working[c] != 0)) { 7441da177e4SLinus Torvalds dev->in_snd[c] = 0; 7451da177e4SLinus Torvalds return; 7461da177e4SLinus Torvalds } 7471da177e4SLinus Torvalds dev->working[c]++; 7481da177e4SLinus Torvalds j = dev->quhd[c]; 7491da177e4SLinus Torvalds dev->quhd[c]++; 750468b8968SOndrej Zary if (dev->quhd[c] >= qcnt) 7511da177e4SLinus Torvalds dev->quhd[c] = 0; 7521da177e4SLinus Torvalds workreq = dev->quereq[c][dev->quhd[c]]; 753468b8968SOndrej Zary if (dev->id[c][scmd_id(workreq)].curr_req != NULL) { 7541da177e4SLinus Torvalds dev->quhd[c] = j; 7551da177e4SLinus Torvalds dev->working[c]--; 7561da177e4SLinus Torvalds dev->in_snd[c] = 0; 7571da177e4SLinus Torvalds return; 7581da177e4SLinus Torvalds } 759468b8968SOndrej Zary dev->id[c][scmd_id(workreq)].curr_req = workreq; 760468b8968SOndrej Zary dev->last_cmd[c] = scmd_id(workreq); 7611da177e4SLinus Torvalds } 762bcd5c59fSHannes Reinecke if ((atp_readb_io(dev, c, 0x1f) & 0xb0) != 0 || 763bcd5c59fSHannes Reinecke atp_readb_io(dev, c, 0x1c) != 0) { 7641da177e4SLinus Torvalds #ifdef ED_DBGP 7651da177e4SLinus Torvalds printk("Abort to Send\n"); 7661da177e4SLinus Torvalds #endif 7671da177e4SLinus Torvalds dev->last_cmd[c] |= 0x40; 7681da177e4SLinus Torvalds dev->in_snd[c] = 0; 7691da177e4SLinus Torvalds return; 770468b8968SOndrej Zary } 7711da177e4SLinus Torvalds #ifdef ED_DBGP 7721da177e4SLinus Torvalds printk("OK to Send\n"); 773422c0d61SJeff Garzik scmd_printk(KERN_DEBUG, workreq, "CDB"); 7741da177e4SLinus Torvalds for(i=0;i<workreq->cmd_len;i++) { 7751da177e4SLinus Torvalds printk(" %x",workreq->cmnd[i]); 7761da177e4SLinus Torvalds } 777422c0d61SJeff Garzik printk("\n"); 7781da177e4SLinus Torvalds #endif 779fe7ed98fSBoaz Harrosh l = scsi_bufflen(workreq); 780fe7ed98fSBoaz Harrosh 781b922a449SOndrej Zary if (is885(dev)) { 7826a3cebb6SOndrej Zary j = atp_readb_base(dev, 0x29) & 0xfe; 7836a3cebb6SOndrej Zary atp_writeb_base(dev, 0x29, j); 784422c0d61SJeff Garzik dev->r1f[c][scmd_id(workreq)] = 0; 7851da177e4SLinus Torvalds } 7861da177e4SLinus Torvalds 7871da177e4SLinus Torvalds if (workreq->cmnd[0] == READ_CAPACITY) { 788fe7ed98fSBoaz Harrosh if (l > 8) 789fe7ed98fSBoaz Harrosh l = 8; 7901da177e4SLinus Torvalds } 791f3272258SHannes Reinecke if (workreq->cmnd[0] == TEST_UNIT_READY) { 792fe7ed98fSBoaz Harrosh l = 0; 7931da177e4SLinus Torvalds } 7941da177e4SLinus Torvalds 7951da177e4SLinus Torvalds j = 0; 796422c0d61SJeff Garzik target_id = scmd_id(workreq); 7971da177e4SLinus Torvalds 7981da177e4SLinus Torvalds /* 7991da177e4SLinus Torvalds * Wide ? 8001da177e4SLinus Torvalds */ 8011da177e4SLinus Torvalds w = 1; 8021da177e4SLinus Torvalds w = w << target_id; 8031da177e4SLinus Torvalds if ((w & dev->wide_id[c]) != 0) { 8041da177e4SLinus Torvalds j |= 0x01; 8051da177e4SLinus Torvalds } 8066a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x1b, j); 8076a3cebb6SOndrej Zary while ((atp_readb_io(dev, c, 0x1b) & 0x01) != j) { 8086a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 0x1b, j); 8091da177e4SLinus Torvalds #ifdef ED_DBGP 8101da177e4SLinus Torvalds printk("send_s870 while loop 1\n"); 8111da177e4SLinus Torvalds #endif 8121da177e4SLinus Torvalds } 8131da177e4SLinus Torvalds /* 8141da177e4SLinus Torvalds * Write the command 8151da177e4SLinus Torvalds */ 8161da177e4SLinus Torvalds 8176a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x00, workreq->cmd_len); 8186a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x01, 0x2c); 819b922a449SOndrej Zary if (is885(dev)) 8206a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x02, 0x7f); 8216a3cebb6SOndrej Zary else 8226a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x02, 0xcf); 8236a3cebb6SOndrej Zary for (i = 0; i < workreq->cmd_len; i++) 8246a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x03 + i, workreq->cmnd[i]); 8256a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x0f, workreq->device->lun); 8261da177e4SLinus Torvalds /* 8271da177e4SLinus Torvalds * Write the target 8281da177e4SLinus Torvalds */ 8296a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x11, dev->id[c][target_id].devsp); 8301da177e4SLinus Torvalds #ifdef ED_DBGP 831bcd5c59fSHannes Reinecke printk("dev->id[%d][%d].devsp = %2x\n",c,target_id, 832bcd5c59fSHannes Reinecke dev->id[c][target_id].devsp); 8331da177e4SLinus Torvalds #endif 8341da177e4SLinus Torvalds 835fe7ed98fSBoaz Harrosh sg_count = scsi_dma_map(workreq); 8361da177e4SLinus Torvalds /* 8371da177e4SLinus Torvalds * Write transfer size 8381da177e4SLinus Torvalds */ 8396a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x12, ((unsigned char *) (&l))[2]); 8406a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x13, ((unsigned char *) (&l))[1]); 8416a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x14, ((unsigned char *) (&l))[0]); 8421da177e4SLinus Torvalds j = target_id; 8431da177e4SLinus Torvalds dev->id[c][j].last_len = l; 8441da177e4SLinus Torvalds dev->id[c][j].tran_len = 0; 8451da177e4SLinus Torvalds #ifdef ED_DBGP 8461da177e4SLinus Torvalds printk("dev->id[%2d][%2d].last_len = %d\n",c,j,dev->id[c][j].last_len); 8471da177e4SLinus Torvalds #endif 8481da177e4SLinus Torvalds /* 8491da177e4SLinus Torvalds * Flip the wide bits 8501da177e4SLinus Torvalds */ 8511da177e4SLinus Torvalds if ((j & 0x08) != 0) { 8521da177e4SLinus Torvalds j = (j & 0x07) | 0x40; 8531da177e4SLinus Torvalds } 8541da177e4SLinus Torvalds /* 8551da177e4SLinus Torvalds * Check transfer direction 8561da177e4SLinus Torvalds */ 8576a3cebb6SOndrej Zary if (workreq->sc_data_direction == DMA_TO_DEVICE) 8586a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x15, j | 0x20); 8596a3cebb6SOndrej Zary else 8606a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x15, j); 8616a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x16, atp_readb_io(dev, c, 0x16) | 0x80); 8626a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x16, 0x80); 8631da177e4SLinus Torvalds dev->id[c][target_id].dirct = 0; 8641da177e4SLinus Torvalds if (l == 0) { 8656a3cebb6SOndrej Zary if (atp_readb_io(dev, c, 0x1c) == 0) { 8661da177e4SLinus Torvalds #ifdef ED_DBGP 8671da177e4SLinus Torvalds printk("change SCSI_CMD_REG 0x08\n"); 8681da177e4SLinus Torvalds #endif 8696a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 8706a3cebb6SOndrej Zary } else 8711da177e4SLinus Torvalds dev->last_cmd[c] |= 0x40; 8721da177e4SLinus Torvalds dev->in_snd[c] = 0; 8731da177e4SLinus Torvalds return; 8741da177e4SLinus Torvalds } 8751da177e4SLinus Torvalds prd = dev->id[c][target_id].prd_table; 8761da177e4SLinus Torvalds dev->id[c][target_id].prd_pos = prd; 8771da177e4SLinus Torvalds 8781da177e4SLinus Torvalds /* 8791da177e4SLinus Torvalds * Now write the request list. Either as scatter/gather or as 8801da177e4SLinus Torvalds * a linear chain. 8811da177e4SLinus Torvalds */ 8821da177e4SLinus Torvalds 883fe7ed98fSBoaz Harrosh if (l) { 884fe7ed98fSBoaz Harrosh struct scatterlist *sgpnt; 8851da177e4SLinus Torvalds i = 0; 886fe7ed98fSBoaz Harrosh scsi_for_each_sg(workreq, sgpnt, sg_count, j) { 887fe7ed98fSBoaz Harrosh bttl = sg_dma_address(sgpnt); 888fe7ed98fSBoaz Harrosh l=sg_dma_len(sgpnt); 8891da177e4SLinus Torvalds #ifdef ED_DBGP 8901da177e4SLinus Torvalds printk("1. bttl %x, l %x\n",bttl, l); 8911da177e4SLinus Torvalds #endif 8921da177e4SLinus Torvalds while (l > 0x10000) { 8931da177e4SLinus Torvalds (((u16 *) (prd))[i + 3]) = 0x0000; 8941da177e4SLinus Torvalds (((u16 *) (prd))[i + 2]) = 0x0000; 8951da177e4SLinus Torvalds (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl); 8961da177e4SLinus Torvalds l -= 0x10000; 8971da177e4SLinus Torvalds bttl += 0x10000; 8981da177e4SLinus Torvalds i += 0x04; 8991da177e4SLinus Torvalds } 9001da177e4SLinus Torvalds (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl); 9011da177e4SLinus Torvalds (((u16 *) (prd))[i + 2]) = cpu_to_le16(l); 9021da177e4SLinus Torvalds (((u16 *) (prd))[i + 3]) = 0; 9031da177e4SLinus Torvalds i += 0x04; 9041da177e4SLinus Torvalds } 9051da177e4SLinus Torvalds (((u16 *) (prd))[i - 1]) = cpu_to_le16(0x8000); 9061da177e4SLinus Torvalds #ifdef ED_DBGP 907bcd5c59fSHannes Reinecke printk("prd %4x %4x %4x %4x\n", 908bcd5c59fSHannes Reinecke (((unsigned short int *)prd)[0]), 909bcd5c59fSHannes Reinecke (((unsigned short int *)prd)[1]), 910bcd5c59fSHannes Reinecke (((unsigned short int *)prd)[2]), 911bcd5c59fSHannes Reinecke (((unsigned short int *)prd)[3])); 9121da177e4SLinus Torvalds printk("2. bttl %x, l %x\n",bttl, l); 9131da177e4SLinus Torvalds #endif 9141da177e4SLinus Torvalds } 9151da177e4SLinus Torvalds #ifdef ED_DBGP 916bcd5c59fSHannes Reinecke printk("send_s870: prdaddr_2 0x%8x target_id %d\n", 917bcd5c59fSHannes Reinecke dev->id[c][target_id].prdaddr,target_id); 9181da177e4SLinus Torvalds #endif 919b5683557SJames Bottomley dev->id[c][target_id].prdaddr = dev->id[c][target_id].prd_bus; 9206a3cebb6SOndrej Zary atp_writel_pci(dev, c, 4, dev->id[c][target_id].prdaddr); 9216a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 2, 0x06); 9226a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 2, 0x00); 923b922a449SOndrej Zary if (is885(dev)) { 9246a3cebb6SOndrej Zary j = atp_readb_pci(dev, c, 1) & 0xf3; 925f3272258SHannes Reinecke if ((workreq->cmnd[0] == READ_6) || 926f3272258SHannes Reinecke (workreq->cmnd[0] == READ_10) || 927f3272258SHannes Reinecke (workreq->cmnd[0] == WRITE_6) || 928f3272258SHannes Reinecke (workreq->cmnd[0] == WRITE_10)) { 9291da177e4SLinus Torvalds j |= 0x0c; 9301da177e4SLinus Torvalds } 9316a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 1, j); 932b922a449SOndrej Zary } else if (is880(dev)) { 933f3272258SHannes Reinecke if ((workreq->cmnd[0] == READ_6) || 934f3272258SHannes Reinecke (workreq->cmnd[0] == READ_10) || 935f3272258SHannes Reinecke (workreq->cmnd[0] == WRITE_6) || 936f3272258SHannes Reinecke (workreq->cmnd[0] == WRITE_10)) 937bcd5c59fSHannes Reinecke atp_writeb_base(dev, 0x3b, 938bcd5c59fSHannes Reinecke (atp_readb_base(dev, 0x3b) & 0x3f) | 0xc0); 9396a3cebb6SOndrej Zary else 940bcd5c59fSHannes Reinecke atp_writeb_base(dev, 0x3b, 941bcd5c59fSHannes Reinecke atp_readb_base(dev, 0x3b) & 0x3f); 9421da177e4SLinus Torvalds } else { 943f3272258SHannes Reinecke if ((workreq->cmnd[0] == READ_6) || 944f3272258SHannes Reinecke (workreq->cmnd[0] == READ_10) || 945f3272258SHannes Reinecke (workreq->cmnd[0] == WRITE_6) || 946f3272258SHannes Reinecke (workreq->cmnd[0] == WRITE_10)) 947bcd5c59fSHannes Reinecke atp_writeb_base(dev, 0x3a, 948bcd5c59fSHannes Reinecke (atp_readb_base(dev, 0x3a) & 0xf3) | 0x08); 9496a3cebb6SOndrej Zary else 950bcd5c59fSHannes Reinecke atp_writeb_base(dev, 0x3a, 951bcd5c59fSHannes Reinecke atp_readb_base(dev, 0x3a) & 0xf3); 9521da177e4SLinus Torvalds } 9531da177e4SLinus Torvalds 9541da177e4SLinus Torvalds if(workreq->sc_data_direction == DMA_TO_DEVICE) { 9551da177e4SLinus Torvalds dev->id[c][target_id].dirct = 0x20; 9566a3cebb6SOndrej Zary if (atp_readb_io(dev, c, 0x1c) == 0) { 9576a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 9586a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 0, 0x01); 9591da177e4SLinus Torvalds #ifdef ED_DBGP 9601da177e4SLinus Torvalds printk( "start DMA(to target)\n"); 9611da177e4SLinus Torvalds #endif 9621da177e4SLinus Torvalds } else { 9631da177e4SLinus Torvalds dev->last_cmd[c] |= 0x40; 9641da177e4SLinus Torvalds } 9651da177e4SLinus Torvalds dev->in_snd[c] = 0; 9661da177e4SLinus Torvalds return; 9671da177e4SLinus Torvalds } 9686a3cebb6SOndrej Zary if (atp_readb_io(dev, c, 0x1c) == 0) { 9696a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 9706a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 0, 0x09); 9711da177e4SLinus Torvalds #ifdef ED_DBGP 9721da177e4SLinus Torvalds printk( "start DMA(to host)\n"); 9731da177e4SLinus Torvalds #endif 9741da177e4SLinus Torvalds } else { 9751da177e4SLinus Torvalds dev->last_cmd[c] |= 0x40; 9761da177e4SLinus Torvalds } 9771da177e4SLinus Torvalds dev->in_snd[c] = 0; 9781da177e4SLinus Torvalds return; 9791da177e4SLinus Torvalds 9801da177e4SLinus Torvalds } 9811da177e4SLinus Torvalds 9821da177e4SLinus Torvalds static unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val) 9831da177e4SLinus Torvalds { 9841da177e4SLinus Torvalds unsigned short int i, k; 9851da177e4SLinus Torvalds unsigned char j; 9861da177e4SLinus Torvalds 9876a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, *val); 9881da177e4SLinus Torvalds for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */ 9896a3cebb6SOndrej Zary k = atp_readw_io(dev, 0, 0x1c); 9901da177e4SLinus Torvalds j = (unsigned char) (k >> 8); 991832e9ac6SOndrej Zary if ((k & 0x8000) != 0) /* DB7 all release? */ 992832e9ac6SOndrej Zary i = 0; 9931da177e4SLinus Torvalds } 9941da177e4SLinus Torvalds *val |= 0x4000; /* assert DB6 */ 9956a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, *val); 9961da177e4SLinus Torvalds *val &= 0xdfff; /* assert DB5 */ 9976a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, *val); 9981da177e4SLinus Torvalds for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */ 9996a3cebb6SOndrej Zary if ((atp_readw_io(dev, 0, 0x1c) & 0x2000) != 0) /* DB5 all release? */ 1000832e9ac6SOndrej Zary i = 0; 10011da177e4SLinus Torvalds } 10021da177e4SLinus Torvalds *val |= 0x8000; /* no DB4-0, assert DB7 */ 10031da177e4SLinus Torvalds *val &= 0xe0ff; 10046a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, *val); 10051da177e4SLinus Torvalds *val &= 0xbfff; /* release DB6 */ 10066a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, *val); 10071da177e4SLinus Torvalds for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */ 10086a3cebb6SOndrej Zary if ((atp_readw_io(dev, 0, 0x1c) & 0x4000) != 0) /* DB6 all release? */ 1009832e9ac6SOndrej Zary i = 0; 10101da177e4SLinus Torvalds } 10111da177e4SLinus Torvalds 10121da177e4SLinus Torvalds return j; 10131da177e4SLinus Torvalds } 10141da177e4SLinus Torvalds 10158177c507SOndrej Zary static void tscam(struct Scsi_Host *host, bool wide_chip, u8 scam_on) 10161da177e4SLinus Torvalds { 10171da177e4SLinus Torvalds 10181da177e4SLinus Torvalds unsigned char i, j, k; 10191da177e4SLinus Torvalds unsigned long n; 10201da177e4SLinus Torvalds unsigned short int m, assignid_map, val; 10211da177e4SLinus Torvalds unsigned char mbuf[33], quintet[2]; 10221da177e4SLinus Torvalds struct atp_unit *dev = (struct atp_unit *)&host->hostdata; 10231da177e4SLinus Torvalds static unsigned char g2q_tab[8] = { 10241da177e4SLinus Torvalds 0x38, 0x31, 0x32, 0x2b, 0x34, 0x2d, 0x2e, 0x27 10251da177e4SLinus Torvalds }; 10261da177e4SLinus Torvalds 10271da177e4SLinus Torvalds /* I can't believe we need this before we've even done anything. Remove it 10281da177e4SLinus Torvalds * and see if anyone bitches. 10291da177e4SLinus Torvalds for (i = 0; i < 0x10; i++) { 10301da177e4SLinus Torvalds udelay(0xffff); 10311da177e4SLinus Torvalds } 10321da177e4SLinus Torvalds */ 10331da177e4SLinus Torvalds 10346a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 1, 0x08); 10356a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 2, 0x7f); 10366a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x11, 0x20); 10371da177e4SLinus Torvalds 10388177c507SOndrej Zary if ((scam_on & 0x40) == 0) { 10391da177e4SLinus Torvalds return; 10401da177e4SLinus Torvalds } 10411da177e4SLinus Torvalds m = 1; 10421da177e4SLinus Torvalds m <<= dev->host_id[0]; 10431da177e4SLinus Torvalds j = 16; 1044dd5a5f79SOndrej Zary if (!wide_chip) { 10451da177e4SLinus Torvalds m |= 0xff00; 10461da177e4SLinus Torvalds j = 8; 10471da177e4SLinus Torvalds } 10481da177e4SLinus Torvalds assignid_map = m; 10496a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x02, 0x02); /* 2*2=4ms,3EH 2/32*3E=3.9ms */ 10506a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x03, 0); 10516a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x04, 0); 10526a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x05, 0); 10536a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x06, 0); 10546a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x07, 0); 10556a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x08, 0); 10561da177e4SLinus Torvalds 10571da177e4SLinus Torvalds for (i = 0; i < j; i++) { 10581da177e4SLinus Torvalds m = 1; 10591da177e4SLinus Torvalds m = m << i; 10601da177e4SLinus Torvalds if ((m & assignid_map) != 0) { 10611da177e4SLinus Torvalds continue; 10621da177e4SLinus Torvalds } 10636a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x0f, 0); 10646a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x12, 0); 10656a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x13, 0); 10666a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x14, 0); 10671da177e4SLinus Torvalds if (i > 7) { 10681da177e4SLinus Torvalds k = (i & 0x07) | 0x40; 10691da177e4SLinus Torvalds } else { 10701da177e4SLinus Torvalds k = i; 10711da177e4SLinus Torvalds } 10726a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x15, k); 1073dd5a5f79SOndrej Zary if (wide_chip) 10746a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x1b, 0x01); 10756a3cebb6SOndrej Zary else 10766a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x1b, 0x00); 107758c4d046SOndrej Zary do { 10786a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x18, 0x09); 10791da177e4SLinus Torvalds 10806a3cebb6SOndrej Zary while ((atp_readb_io(dev, 0, 0x1f) & 0x80) == 0x00) 10811da177e4SLinus Torvalds cpu_relax(); 10826a3cebb6SOndrej Zary k = atp_readb_io(dev, 0, 0x17); 108358c4d046SOndrej Zary if ((k == 0x85) || (k == 0x42)) 108458c4d046SOndrej Zary break; 108558c4d046SOndrej Zary if (k != 0x16) 10866a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x10, 0x41); 108758c4d046SOndrej Zary } while (k != 0x16); 108858c4d046SOndrej Zary if ((k == 0x85) || (k == 0x42)) 108958c4d046SOndrej Zary continue; 10901da177e4SLinus Torvalds assignid_map |= m; 10911da177e4SLinus Torvalds 10921da177e4SLinus Torvalds } 10936a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x02, 0x7f); 10946a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x1b, 0x02); 10951da177e4SLinus Torvalds 10962bbbac45SOndrej Zary udelay(2); 10971da177e4SLinus Torvalds 10981da177e4SLinus Torvalds val = 0x0080; /* bsy */ 10996a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, val); 11001da177e4SLinus Torvalds val |= 0x0040; /* sel */ 11016a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, val); 11021da177e4SLinus Torvalds val |= 0x0004; /* msg */ 11036a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, val); 11042bbbac45SOndrej Zary udelay(2); /* 2 deskew delay(45ns*2=90ns) */ 11051da177e4SLinus Torvalds val &= 0x007f; /* no bsy */ 11066a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, val); 1107dcaa0c12SJia-Ju Bai msleep(128); 11081da177e4SLinus Torvalds val &= 0x00fb; /* after 1ms no msg */ 11096a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, val); 11106a3cebb6SOndrej Zary while ((atp_readb_io(dev, 0, 0x1c) & 0x04) != 0) 111158c4d046SOndrej Zary ; 11122bbbac45SOndrej Zary udelay(2); 11131da177e4SLinus Torvalds udelay(100); 1114c7fcc089SOndrej Zary for (n = 0; n < 0x30000; n++) 11156a3cebb6SOndrej Zary if ((atp_readb_io(dev, 0, 0x1c) & 0x80) != 0) /* bsy ? */ 1116c7fcc089SOndrej Zary break; 1117c7fcc089SOndrej Zary if (n < 0x30000) 1118c7fcc089SOndrej Zary for (n = 0; n < 0x30000; n++) 11196a3cebb6SOndrej Zary if ((atp_readb_io(dev, 0, 0x1c) & 0x81) == 0x0081) { 11202bbbac45SOndrej Zary udelay(2); 11211da177e4SLinus Torvalds val |= 0x8003; /* io,cd,db7 */ 11226a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, val); 11232bbbac45SOndrej Zary udelay(2); 11241da177e4SLinus Torvalds val &= 0x00bf; /* no sel */ 11256a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, val); 11262bbbac45SOndrej Zary udelay(2); 1127c7fcc089SOndrej Zary break; 1128c7fcc089SOndrej Zary } 1129c7fcc089SOndrej Zary while (1) { 11300f6d93aaSMartin Michlmayr /* 11310f6d93aaSMartin Michlmayr * The funny division into multiple delays is to accomodate 11320f6d93aaSMartin Michlmayr * arches like ARM where udelay() multiplies its argument by 11330f6d93aaSMartin Michlmayr * a large number to initialize a loop counter. To avoid 11340f6d93aaSMartin Michlmayr * overflow, the maximum supported udelay is 2000 microseconds. 11350f6d93aaSMartin Michlmayr * 11360f6d93aaSMartin Michlmayr * XXX it would be more polite to find a way to use msleep() 11370f6d93aaSMartin Michlmayr */ 11380f6d93aaSMartin Michlmayr mdelay(2); 11390f6d93aaSMartin Michlmayr udelay(48); 11406a3cebb6SOndrej Zary if ((atp_readb_io(dev, 0, 0x1c) & 0x80) == 0x00) { /* bsy ? */ 11416a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, 0); 11426a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x1b, 0); 11436a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x15, 0); 11446a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x18, 0x09); 11456a3cebb6SOndrej Zary while ((atp_readb_io(dev, 0, 0x1f) & 0x80) == 0) 11461da177e4SLinus Torvalds cpu_relax(); 11476a3cebb6SOndrej Zary atp_readb_io(dev, 0, 0x17); 11481da177e4SLinus Torvalds return; 11491da177e4SLinus Torvalds } 11501da177e4SLinus Torvalds val &= 0x00ff; /* synchronization */ 11511da177e4SLinus Torvalds val |= 0x3f00; 11521da177e4SLinus Torvalds fun_scam(dev, &val); 11532bbbac45SOndrej Zary udelay(2); 11541da177e4SLinus Torvalds val &= 0x00ff; /* isolation */ 11551da177e4SLinus Torvalds val |= 0x2000; 11561da177e4SLinus Torvalds fun_scam(dev, &val); 11572bbbac45SOndrej Zary udelay(2); 11581da177e4SLinus Torvalds i = 8; 11591da177e4SLinus Torvalds j = 0; 1160c7fcc089SOndrej Zary 1161c7fcc089SOndrej Zary while (1) { 11626a3cebb6SOndrej Zary if ((atp_readw_io(dev, 0, 0x1c) & 0x2000) == 0) 1163c7fcc089SOndrej Zary continue; 11642bbbac45SOndrej Zary udelay(2); 11651da177e4SLinus Torvalds val &= 0x00ff; /* get ID_STRING */ 11661da177e4SLinus Torvalds val |= 0x2000; 11671da177e4SLinus Torvalds k = fun_scam(dev, &val); 1168c7fcc089SOndrej Zary if ((k & 0x03) == 0) 1169c7fcc089SOndrej Zary break; 11701da177e4SLinus Torvalds mbuf[j] <<= 0x01; 11711da177e4SLinus Torvalds mbuf[j] &= 0xfe; 1172c7fcc089SOndrej Zary if ((k & 0x02) != 0) 11731da177e4SLinus Torvalds mbuf[j] |= 0x01; 11741da177e4SLinus Torvalds i--; 1175c7fcc089SOndrej Zary if (i > 0) 1176c7fcc089SOndrej Zary continue; 11771da177e4SLinus Torvalds j++; 11781da177e4SLinus Torvalds i = 8; 1179c7fcc089SOndrej Zary } 11801da177e4SLinus Torvalds 1181c7fcc089SOndrej Zary /* isolation complete.. */ 11821da177e4SLinus Torvalds /* mbuf[32]=0; 11831da177e4SLinus Torvalds printk(" \n%x %x %x %s\n ",assignid_map,mbuf[0],mbuf[1],&mbuf[2]); */ 11841da177e4SLinus Torvalds i = 15; 11851da177e4SLinus Torvalds j = mbuf[0]; 11861da177e4SLinus Torvalds if ((j & 0x20) != 0) { /* bit5=1:ID up to 7 */ 11871da177e4SLinus Torvalds i = 7; 11881da177e4SLinus Torvalds } 1189c7fcc089SOndrej Zary if ((j & 0x06) != 0) { /* IDvalid? */ 11901da177e4SLinus Torvalds k = mbuf[1]; 1191c7fcc089SOndrej Zary while (1) { 11921da177e4SLinus Torvalds m = 1; 11931da177e4SLinus Torvalds m <<= k; 1194c7fcc089SOndrej Zary if ((m & assignid_map) == 0) 1195c7fcc089SOndrej Zary break; 1196c7fcc089SOndrej Zary if (k > 0) 11971da177e4SLinus Torvalds k--; 1198c7fcc089SOndrej Zary else 1199c7fcc089SOndrej Zary break; 12001da177e4SLinus Torvalds } 1201c7fcc089SOndrej Zary } 1202c7fcc089SOndrej Zary if ((m & assignid_map) != 0) { /* srch from max acceptable ID# */ 12031da177e4SLinus Torvalds k = i; /* max acceptable ID# */ 1204c7fcc089SOndrej Zary while (1) { 12051da177e4SLinus Torvalds m = 1; 12061da177e4SLinus Torvalds m <<= k; 1207c7fcc089SOndrej Zary if ((m & assignid_map) == 0) 1208c7fcc089SOndrej Zary break; 1209c7fcc089SOndrej Zary if (k > 0) 12101da177e4SLinus Torvalds k--; 1211c7fcc089SOndrej Zary else 1212c7fcc089SOndrej Zary break; 12131da177e4SLinus Torvalds } 1214c7fcc089SOndrej Zary } 1215c7fcc089SOndrej Zary /* k=binID#, */ 12161da177e4SLinus Torvalds assignid_map |= m; 12171da177e4SLinus Torvalds if (k < 8) { 12181da177e4SLinus Torvalds quintet[0] = 0x38; /* 1st dft ID<8 */ 12191da177e4SLinus Torvalds } else { 12201da177e4SLinus Torvalds quintet[0] = 0x31; /* 1st ID>=8 */ 12211da177e4SLinus Torvalds } 12221da177e4SLinus Torvalds k &= 0x07; 12231da177e4SLinus Torvalds quintet[1] = g2q_tab[k]; 12241da177e4SLinus Torvalds 12251da177e4SLinus Torvalds val &= 0x00ff; /* AssignID 1stQuintet,AH=001xxxxx */ 12261da177e4SLinus Torvalds m = quintet[0] << 8; 12271da177e4SLinus Torvalds val |= m; 12281da177e4SLinus Torvalds fun_scam(dev, &val); 12291da177e4SLinus Torvalds val &= 0x00ff; /* AssignID 2ndQuintet,AH=001xxxxx */ 12301da177e4SLinus Torvalds m = quintet[1] << 8; 12311da177e4SLinus Torvalds val |= m; 12321da177e4SLinus Torvalds fun_scam(dev, &val); 12331da177e4SLinus Torvalds 1234c7fcc089SOndrej Zary } 12351da177e4SLinus Torvalds } 12361da177e4SLinus Torvalds 12371da177e4SLinus Torvalds static void atp870u_free_tables(struct Scsi_Host *host) 12381da177e4SLinus Torvalds { 12391da177e4SLinus Torvalds struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata; 12401da177e4SLinus Torvalds int j, k; 12411da177e4SLinus Torvalds for (j=0; j < 2; j++) { 12421da177e4SLinus Torvalds for (k = 0; k < 16; k++) { 12431da177e4SLinus Torvalds if (!atp_dev->id[j][k].prd_table) 12441da177e4SLinus Torvalds continue; 1245bcd5c59fSHannes Reinecke dma_free_coherent(&atp_dev->pdev->dev, 1024, 1246bcd5c59fSHannes Reinecke atp_dev->id[j][k].prd_table, 1247bcd5c59fSHannes Reinecke atp_dev->id[j][k].prd_bus); 12481da177e4SLinus Torvalds atp_dev->id[j][k].prd_table = NULL; 12491da177e4SLinus Torvalds } 12501da177e4SLinus Torvalds } 12511da177e4SLinus Torvalds } 12521da177e4SLinus Torvalds 12531da177e4SLinus Torvalds static int atp870u_init_tables(struct Scsi_Host *host) 12541da177e4SLinus Torvalds { 12551da177e4SLinus Torvalds struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata; 12561da177e4SLinus Torvalds int c,k; 12571da177e4SLinus Torvalds for(c=0;c < 2;c++) { 12581da177e4SLinus Torvalds for(k=0;k<16;k++) { 1259bcd5c59fSHannes Reinecke atp_dev->id[c][k].prd_table = 1260bcd5c59fSHannes Reinecke dma_alloc_coherent(&atp_dev->pdev->dev, 1024, 1261bcd5c59fSHannes Reinecke &(atp_dev->id[c][k].prd_bus), 1262bcd5c59fSHannes Reinecke GFP_KERNEL); 12631da177e4SLinus Torvalds if (!atp_dev->id[c][k].prd_table) { 12641da177e4SLinus Torvalds printk("atp870u_init_tables fail\n"); 12651da177e4SLinus Torvalds atp870u_free_tables(host); 12661da177e4SLinus Torvalds return -ENOMEM; 12671da177e4SLinus Torvalds } 1268b5683557SJames Bottomley atp_dev->id[c][k].prdaddr = atp_dev->id[c][k].prd_bus; 12691da177e4SLinus Torvalds atp_dev->id[c][k].devsp=0x20; 12701da177e4SLinus Torvalds atp_dev->id[c][k].devtype = 0x7f; 12711da177e4SLinus Torvalds atp_dev->id[c][k].curr_req = NULL; 12721da177e4SLinus Torvalds } 12731da177e4SLinus Torvalds 12741da177e4SLinus Torvalds atp_dev->active_id[c] = 0; 12751da177e4SLinus Torvalds atp_dev->wide_id[c] = 0; 12761da177e4SLinus Torvalds atp_dev->host_id[c] = 0x07; 12771da177e4SLinus Torvalds atp_dev->quhd[c] = 0; 12781da177e4SLinus Torvalds atp_dev->quend[c] = 0; 12791da177e4SLinus Torvalds atp_dev->last_cmd[c] = 0xff; 12801da177e4SLinus Torvalds atp_dev->in_snd[c] = 0; 12811da177e4SLinus Torvalds atp_dev->in_int[c] = 0; 12821da177e4SLinus Torvalds 12831da177e4SLinus Torvalds for (k = 0; k < qcnt; k++) { 12841da177e4SLinus Torvalds atp_dev->quereq[c][k] = NULL; 12851da177e4SLinus Torvalds } 12861da177e4SLinus Torvalds for (k = 0; k < 16; k++) { 12871da177e4SLinus Torvalds atp_dev->id[c][k].curr_req = NULL; 12881da177e4SLinus Torvalds atp_dev->sp[c][k] = 0x04; 12891da177e4SLinus Torvalds } 12901da177e4SLinus Torvalds } 12911da177e4SLinus Torvalds return 0; 12921da177e4SLinus Torvalds } 12931da177e4SLinus Torvalds 12946a1961bcSOndrej Zary static void atp_set_host_id(struct atp_unit *atp, u8 c, u8 host_id) 12956a1961bcSOndrej Zary { 12966a1961bcSOndrej Zary atp_writeb_io(atp, c, 0, host_id | 0x08); 12976a1961bcSOndrej Zary atp_writeb_io(atp, c, 0x18, 0); 12986a1961bcSOndrej Zary while ((atp_readb_io(atp, c, 0x1f) & 0x80) == 0) 12996a1961bcSOndrej Zary mdelay(1); 13006a1961bcSOndrej Zary atp_readb_io(atp, c, 0x17); 13016a1961bcSOndrej Zary atp_writeb_io(atp, c, 1, 8); 13026a1961bcSOndrej Zary atp_writeb_io(atp, c, 2, 0x7f); 13036a1961bcSOndrej Zary atp_writeb_io(atp, c, 0x11, 0x20); 13046a1961bcSOndrej Zary } 13056a1961bcSOndrej Zary 13064190230eSOndrej Zary static void atp870_init(struct Scsi_Host *shpnt) 13074190230eSOndrej Zary { 13084190230eSOndrej Zary struct atp_unit *atpdev = shost_priv(shpnt); 13094190230eSOndrej Zary struct pci_dev *pdev = atpdev->pdev; 13104190230eSOndrej Zary unsigned char k, host_id; 13114190230eSOndrej Zary u8 scam_on; 13124190230eSOndrej Zary bool wide_chip = 13134190230eSOndrej Zary (pdev->device == PCI_DEVICE_ID_ARTOP_AEC7610 && 13144190230eSOndrej Zary pdev->revision == 4) || 13154190230eSOndrej Zary (pdev->device == PCI_DEVICE_ID_ARTOP_AEC7612UW) || 13164190230eSOndrej Zary (pdev->device == PCI_DEVICE_ID_ARTOP_AEC7612SUW); 13174190230eSOndrej Zary 13184190230eSOndrej Zary pci_read_config_byte(pdev, 0x49, &host_id); 13194190230eSOndrej Zary 1320bcd5c59fSHannes Reinecke dev_info(&pdev->dev, "ACARD AEC-671X PCI Ultra/W SCSI-2/3 " 1321bcd5c59fSHannes Reinecke "Host Adapter: IO:%lx, IRQ:%d.\n", 13224190230eSOndrej Zary shpnt->io_port, shpnt->irq); 13234190230eSOndrej Zary 13244190230eSOndrej Zary atpdev->ioport[0] = shpnt->io_port; 13254190230eSOndrej Zary atpdev->pciport[0] = shpnt->io_port + 0x20; 13264190230eSOndrej Zary host_id &= 0x07; 13274190230eSOndrej Zary atpdev->host_id[0] = host_id; 13284190230eSOndrej Zary scam_on = atp_readb_pci(atpdev, 0, 2); 13294190230eSOndrej Zary atpdev->global_map[0] = atp_readb_base(atpdev, 0x2d); 13304190230eSOndrej Zary atpdev->ultra_map[0] = atp_readw_base(atpdev, 0x2e); 13314190230eSOndrej Zary 13324190230eSOndrej Zary if (atpdev->ultra_map[0] == 0) { 13334190230eSOndrej Zary scam_on = 0x00; 13344190230eSOndrej Zary atpdev->global_map[0] = 0x20; 13354190230eSOndrej Zary atpdev->ultra_map[0] = 0xffff; 13364190230eSOndrej Zary } 13374190230eSOndrej Zary 13384190230eSOndrej Zary if (pdev->revision > 0x07) /* check if atp876 chip */ 13394190230eSOndrej Zary atp_writeb_base(atpdev, 0x3e, 0x00); /* enable terminator */ 13404190230eSOndrej Zary 13414190230eSOndrej Zary k = (atp_readb_base(atpdev, 0x3a) & 0xf3) | 0x10; 13424190230eSOndrej Zary atp_writeb_base(atpdev, 0x3a, k); 13434190230eSOndrej Zary atp_writeb_base(atpdev, 0x3a, k & 0xdf); 1344dcaa0c12SJia-Ju Bai msleep(32); 13454190230eSOndrej Zary atp_writeb_base(atpdev, 0x3a, k); 1346dcaa0c12SJia-Ju Bai msleep(32); 13474190230eSOndrej Zary atp_set_host_id(atpdev, 0, host_id); 13484190230eSOndrej Zary 13494190230eSOndrej Zary tscam(shpnt, wide_chip, scam_on); 13504190230eSOndrej Zary atp_writeb_base(atpdev, 0x3a, atp_readb_base(atpdev, 0x3a) | 0x10); 13514190230eSOndrej Zary atp_is(atpdev, 0, wide_chip, 0); 13524190230eSOndrej Zary atp_writeb_base(atpdev, 0x3a, atp_readb_base(atpdev, 0x3a) & 0xef); 13534190230eSOndrej Zary atp_writeb_base(atpdev, 0x3b, atp_readb_base(atpdev, 0x3b) | 0x20); 13544190230eSOndrej Zary shpnt->max_id = wide_chip ? 16 : 8; 13554190230eSOndrej Zary shpnt->this_id = host_id; 13564190230eSOndrej Zary } 13574190230eSOndrej Zary 1358c7e6a029SOndrej Zary static void atp880_init(struct Scsi_Host *shpnt) 1359c7e6a029SOndrej Zary { 1360c7e6a029SOndrej Zary struct atp_unit *atpdev = shost_priv(shpnt); 1361c7e6a029SOndrej Zary struct pci_dev *pdev = atpdev->pdev; 1362c7e6a029SOndrej Zary unsigned char k, m, host_id; 1363c7e6a029SOndrej Zary unsigned int n; 1364c7e6a029SOndrej Zary 1365c7e6a029SOndrej Zary pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80); 1366c7e6a029SOndrej Zary 1367c7e6a029SOndrej Zary atpdev->ioport[0] = shpnt->io_port + 0x40; 1368c7e6a029SOndrej Zary atpdev->pciport[0] = shpnt->io_port + 0x28; 1369c7e6a029SOndrej Zary 1370c7e6a029SOndrej Zary host_id = atp_readb_base(atpdev, 0x39) >> 4; 1371c7e6a029SOndrej Zary 1372bcd5c59fSHannes Reinecke dev_info(&pdev->dev, "ACARD AEC-67160 PCI Ultra3 LVD " 1373bcd5c59fSHannes Reinecke "Host Adapter: IO:%lx, IRQ:%d.\n", 1374c7e6a029SOndrej Zary shpnt->io_port, shpnt->irq); 1375c7e6a029SOndrej Zary atpdev->host_id[0] = host_id; 1376c7e6a029SOndrej Zary 1377c7e6a029SOndrej Zary atpdev->global_map[0] = atp_readb_base(atpdev, 0x35); 1378c7e6a029SOndrej Zary atpdev->ultra_map[0] = atp_readw_base(atpdev, 0x3c); 1379c7e6a029SOndrej Zary 1380c7e6a029SOndrej Zary n = 0x3f09; 1381c7e6a029SOndrej Zary while (n < 0x4000) { 1382c7e6a029SOndrej Zary m = 0; 1383c7e6a029SOndrej Zary atp_writew_base(atpdev, 0x34, n); 1384c7e6a029SOndrej Zary n += 0x0002; 1385c7e6a029SOndrej Zary if (atp_readb_base(atpdev, 0x30) == 0xff) 1386c7e6a029SOndrej Zary break; 1387c7e6a029SOndrej Zary 1388c7e6a029SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30); 1389c7e6a029SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31); 1390c7e6a029SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32); 1391c7e6a029SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33); 1392c7e6a029SOndrej Zary atp_writew_base(atpdev, 0x34, n); 1393c7e6a029SOndrej Zary n += 0x0002; 1394c7e6a029SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30); 1395c7e6a029SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31); 1396c7e6a029SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32); 1397c7e6a029SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33); 1398c7e6a029SOndrej Zary atp_writew_base(atpdev, 0x34, n); 1399c7e6a029SOndrej Zary n += 0x0002; 1400c7e6a029SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30); 1401c7e6a029SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31); 1402c7e6a029SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32); 1403c7e6a029SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33); 1404c7e6a029SOndrej Zary atp_writew_base(atpdev, 0x34, n); 1405c7e6a029SOndrej Zary n += 0x0002; 1406c7e6a029SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30); 1407c7e6a029SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31); 1408c7e6a029SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32); 1409c7e6a029SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33); 1410c7e6a029SOndrej Zary n += 0x0018; 1411c7e6a029SOndrej Zary } 1412c7e6a029SOndrej Zary atp_writew_base(atpdev, 0x34, 0); 1413c7e6a029SOndrej Zary atpdev->ultra_map[0] = 0; 1414c7e6a029SOndrej Zary atpdev->async[0] = 0; 1415c7e6a029SOndrej Zary for (k = 0; k < 16; k++) { 1416c7e6a029SOndrej Zary n = 1 << k; 1417c7e6a029SOndrej Zary if (atpdev->sp[0][k] > 1) 1418c7e6a029SOndrej Zary atpdev->ultra_map[0] |= n; 1419c7e6a029SOndrej Zary else 1420c7e6a029SOndrej Zary if (atpdev->sp[0][k] == 0) 1421c7e6a029SOndrej Zary atpdev->async[0] |= n; 1422c7e6a029SOndrej Zary } 1423c7e6a029SOndrej Zary atpdev->async[0] = ~(atpdev->async[0]); 1424c7e6a029SOndrej Zary atp_writeb_base(atpdev, 0x35, atpdev->global_map[0]); 1425c7e6a029SOndrej Zary 1426c7e6a029SOndrej Zary k = atp_readb_base(atpdev, 0x38) & 0x80; 1427c7e6a029SOndrej Zary atp_writeb_base(atpdev, 0x38, k); 1428c7e6a029SOndrej Zary atp_writeb_base(atpdev, 0x3b, 0x20); 1429dcaa0c12SJia-Ju Bai msleep(32); 1430c7e6a029SOndrej Zary atp_writeb_base(atpdev, 0x3b, 0); 1431dcaa0c12SJia-Ju Bai msleep(32); 1432c7e6a029SOndrej Zary atp_readb_io(atpdev, 0, 0x1b); 1433c7e6a029SOndrej Zary atp_readb_io(atpdev, 0, 0x17); 1434c7e6a029SOndrej Zary 1435c7e6a029SOndrej Zary atp_set_host_id(atpdev, 0, host_id); 1436c7e6a029SOndrej Zary 1437c7e6a029SOndrej Zary tscam(shpnt, true, atp_readb_base(atpdev, 0x22)); 1438c7e6a029SOndrej Zary atp_is(atpdev, 0, true, atp_readb_base(atpdev, 0x3f) & 0x40); 1439c7e6a029SOndrej Zary atp_writeb_base(atpdev, 0x38, 0xb0); 1440c7e6a029SOndrej Zary shpnt->max_id = 16; 1441c7e6a029SOndrej Zary shpnt->this_id = host_id; 1442c7e6a029SOndrej Zary } 1443c7e6a029SOndrej Zary 1444ecc6ff95SOndrej Zary static void atp885_init(struct Scsi_Host *shpnt) 1445ecc6ff95SOndrej Zary { 1446ecc6ff95SOndrej Zary struct atp_unit *atpdev = shost_priv(shpnt); 1447ecc6ff95SOndrej Zary struct pci_dev *pdev = atpdev->pdev; 1448ecc6ff95SOndrej Zary unsigned char k, m, c; 1449ecc6ff95SOndrej Zary unsigned int n; 1450ecc6ff95SOndrej Zary unsigned char setupdata[2][16]; 1451ecc6ff95SOndrej Zary 1452bcd5c59fSHannes Reinecke dev_info(&pdev->dev, "ACARD AEC-67162 PCI Ultra3 LVD " 1453bcd5c59fSHannes Reinecke "Host Adapter: IO:%lx, IRQ:%d.\n", 1454ecc6ff95SOndrej Zary shpnt->io_port, shpnt->irq); 1455ecc6ff95SOndrej Zary 1456ecc6ff95SOndrej Zary atpdev->ioport[0] = shpnt->io_port + 0x80; 1457ecc6ff95SOndrej Zary atpdev->ioport[1] = shpnt->io_port + 0xc0; 1458ecc6ff95SOndrej Zary atpdev->pciport[0] = shpnt->io_port + 0x40; 1459ecc6ff95SOndrej Zary atpdev->pciport[1] = shpnt->io_port + 0x50; 1460ecc6ff95SOndrej Zary 1461ecc6ff95SOndrej Zary c = atp_readb_base(atpdev, 0x29); 1462ecc6ff95SOndrej Zary atp_writeb_base(atpdev, 0x29, c | 0x04); 1463ecc6ff95SOndrej Zary 1464ecc6ff95SOndrej Zary n = 0x1f80; 1465ecc6ff95SOndrej Zary while (n < 0x2000) { 1466ecc6ff95SOndrej Zary atp_writew_base(atpdev, 0x3c, n); 1467ecc6ff95SOndrej Zary if (atp_readl_base(atpdev, 0x38) == 0xffffffff) 1468ecc6ff95SOndrej Zary break; 1469ecc6ff95SOndrej Zary for (m = 0; m < 2; m++) { 1470ecc6ff95SOndrej Zary atpdev->global_map[m] = 0; 1471ecc6ff95SOndrej Zary for (k = 0; k < 4; k++) { 1472ecc6ff95SOndrej Zary atp_writew_base(atpdev, 0x3c, n++); 1473bcd5c59fSHannes Reinecke ((u32 *)&setupdata[m][0])[k] = 1474bcd5c59fSHannes Reinecke atp_readl_base(atpdev, 0x38); 1475ecc6ff95SOndrej Zary } 1476ecc6ff95SOndrej Zary for (k = 0; k < 4; k++) { 1477ecc6ff95SOndrej Zary atp_writew_base(atpdev, 0x3c, n++); 1478bcd5c59fSHannes Reinecke ((u32 *)&atpdev->sp[m][0])[k] = 1479bcd5c59fSHannes Reinecke atp_readl_base(atpdev, 0x38); 1480ecc6ff95SOndrej Zary } 1481ecc6ff95SOndrej Zary n += 8; 1482ecc6ff95SOndrej Zary } 1483ecc6ff95SOndrej Zary } 1484ecc6ff95SOndrej Zary c = atp_readb_base(atpdev, 0x29); 1485ecc6ff95SOndrej Zary atp_writeb_base(atpdev, 0x29, c & 0xfb); 1486ecc6ff95SOndrej Zary for (c = 0; c < 2; c++) { 1487ecc6ff95SOndrej Zary atpdev->ultra_map[c] = 0; 1488ecc6ff95SOndrej Zary atpdev->async[c] = 0; 1489ecc6ff95SOndrej Zary for (k = 0; k < 16; k++) { 1490ecc6ff95SOndrej Zary n = 1 << k; 1491ecc6ff95SOndrej Zary if (atpdev->sp[c][k] > 1) 1492ecc6ff95SOndrej Zary atpdev->ultra_map[c] |= n; 1493ecc6ff95SOndrej Zary else 1494ecc6ff95SOndrej Zary if (atpdev->sp[c][k] == 0) 1495ecc6ff95SOndrej Zary atpdev->async[c] |= n; 1496ecc6ff95SOndrej Zary } 1497ecc6ff95SOndrej Zary atpdev->async[c] = ~(atpdev->async[c]); 1498ecc6ff95SOndrej Zary 1499ecc6ff95SOndrej Zary if (atpdev->global_map[c] == 0) { 1500ecc6ff95SOndrej Zary k = setupdata[c][1]; 1501ecc6ff95SOndrej Zary if ((k & 0x40) != 0) 1502ecc6ff95SOndrej Zary atpdev->global_map[c] |= 0x20; 1503ecc6ff95SOndrej Zary k &= 0x07; 1504ecc6ff95SOndrej Zary atpdev->global_map[c] |= k; 1505ecc6ff95SOndrej Zary if ((setupdata[c][2] & 0x04) != 0) 1506ecc6ff95SOndrej Zary atpdev->global_map[c] |= 0x08; 1507ecc6ff95SOndrej Zary atpdev->host_id[c] = setupdata[c][0] & 0x07; 1508ecc6ff95SOndrej Zary } 1509ecc6ff95SOndrej Zary } 1510ecc6ff95SOndrej Zary 1511ecc6ff95SOndrej Zary k = atp_readb_base(atpdev, 0x28) & 0x8f; 1512ecc6ff95SOndrej Zary k |= 0x10; 1513ecc6ff95SOndrej Zary atp_writeb_base(atpdev, 0x28, k); 1514ecc6ff95SOndrej Zary atp_writeb_pci(atpdev, 0, 1, 0x80); 1515ecc6ff95SOndrej Zary atp_writeb_pci(atpdev, 1, 1, 0x80); 1516dcaa0c12SJia-Ju Bai msleep(100); 1517ecc6ff95SOndrej Zary atp_writeb_pci(atpdev, 0, 1, 0); 1518ecc6ff95SOndrej Zary atp_writeb_pci(atpdev, 1, 1, 0); 1519dcaa0c12SJia-Ju Bai msleep(1000); 1520ecc6ff95SOndrej Zary atp_readb_io(atpdev, 0, 0x1b); 1521ecc6ff95SOndrej Zary atp_readb_io(atpdev, 0, 0x17); 1522ecc6ff95SOndrej Zary atp_readb_io(atpdev, 1, 0x1b); 1523ecc6ff95SOndrej Zary atp_readb_io(atpdev, 1, 0x17); 1524ecc6ff95SOndrej Zary 1525ecc6ff95SOndrej Zary k = atpdev->host_id[0]; 1526ecc6ff95SOndrej Zary if (k > 7) 1527ecc6ff95SOndrej Zary k = (k & 0x07) | 0x40; 1528ecc6ff95SOndrej Zary atp_set_host_id(atpdev, 0, k); 1529ecc6ff95SOndrej Zary 1530ecc6ff95SOndrej Zary k = atpdev->host_id[1]; 1531ecc6ff95SOndrej Zary if (k > 7) 1532ecc6ff95SOndrej Zary k = (k & 0x07) | 0x40; 1533ecc6ff95SOndrej Zary atp_set_host_id(atpdev, 1, k); 1534ecc6ff95SOndrej Zary 1535dcaa0c12SJia-Ju Bai msleep(600); /* this delay used to be called tscam_885() */ 1536ecc6ff95SOndrej Zary dev_info(&pdev->dev, "Scanning Channel A SCSI Device ...\n"); 1537ecc6ff95SOndrej Zary atp_is(atpdev, 0, true, atp_readb_io(atpdev, 0, 0x1b) >> 7); 1538ecc6ff95SOndrej Zary atp_writeb_io(atpdev, 0, 0x16, 0x80); 1539ecc6ff95SOndrej Zary dev_info(&pdev->dev, "Scanning Channel B SCSI Device ...\n"); 1540ecc6ff95SOndrej Zary atp_is(atpdev, 1, true, atp_readb_io(atpdev, 1, 0x1b) >> 7); 1541ecc6ff95SOndrej Zary atp_writeb_io(atpdev, 1, 0x16, 0x80); 1542ecc6ff95SOndrej Zary k = atp_readb_base(atpdev, 0x28) & 0xcf; 1543ecc6ff95SOndrej Zary k |= 0xc0; 1544ecc6ff95SOndrej Zary atp_writeb_base(atpdev, 0x28, k); 1545ecc6ff95SOndrej Zary k = atp_readb_base(atpdev, 0x1f) | 0x80; 1546ecc6ff95SOndrej Zary atp_writeb_base(atpdev, 0x1f, k); 1547ecc6ff95SOndrej Zary k = atp_readb_base(atpdev, 0x29) | 0x01; 1548ecc6ff95SOndrej Zary atp_writeb_base(atpdev, 0x29, k); 1549ecc6ff95SOndrej Zary shpnt->max_id = 16; 1550ecc6ff95SOndrej Zary shpnt->max_lun = (atpdev->global_map[0] & 0x07) + 1; 1551ecc6ff95SOndrej Zary shpnt->max_channel = 1; 1552ecc6ff95SOndrej Zary shpnt->this_id = atpdev->host_id[0]; 1553ecc6ff95SOndrej Zary } 1554ecc6ff95SOndrej Zary 15551da177e4SLinus Torvalds /* return non-zero on detection */ 15561da177e4SLinus Torvalds static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 15571da177e4SLinus Torvalds { 15581da177e4SLinus Torvalds struct Scsi_Host *shpnt = NULL; 1559bdd5ac40SOndrej Zary struct atp_unit *atpdev; 1560bdd5ac40SOndrej Zary int err; 15611da177e4SLinus Torvalds 1562b1e85063SOndrej Zary if (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610 && pdev->revision < 2) { 1563b1e85063SOndrej Zary dev_err(&pdev->dev, "ATP850S chips (AEC6710L/F cards) are not supported.\n"); 1564b1e85063SOndrej Zary return -ENODEV; 1565b1e85063SOndrej Zary } 1566b1e85063SOndrej Zary 1567bdd5ac40SOndrej Zary err = pci_enable_device(pdev); 1568bdd5ac40SOndrej Zary if (err) 1569bdd5ac40SOndrej Zary goto fail; 15701da177e4SLinus Torvalds 157148ecddb4SChristoph Hellwig if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) { 15721da177e4SLinus Torvalds printk(KERN_ERR "atp870u: DMA mask required but not available.\n"); 1573bdd5ac40SOndrej Zary err = -EIO; 1574bdd5ac40SOndrej Zary goto disable_device; 15751da177e4SLinus Torvalds } 15761da177e4SLinus Torvalds 157711ec1318SOndrej Zary err = pci_request_regions(pdev, "atp870u"); 157811ec1318SOndrej Zary if (err) 157911ec1318SOndrej Zary goto disable_device; 158011ec1318SOndrej Zary pci_set_master(pdev); 158111ec1318SOndrej Zary 1582bdd5ac40SOndrej Zary err = -ENOMEM; 1583bdd5ac40SOndrej Zary shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit)); 1584bdd5ac40SOndrej Zary if (!shpnt) 158511ec1318SOndrej Zary goto release_region; 1586bdd5ac40SOndrej Zary 1587bdd5ac40SOndrej Zary atpdev = shost_priv(shpnt); 1588bdd5ac40SOndrej Zary 1589bdd5ac40SOndrej Zary atpdev->host = shpnt; 1590bdd5ac40SOndrej Zary atpdev->pdev = pdev; 1591bdd5ac40SOndrej Zary pci_set_drvdata(pdev, atpdev); 1592bdd5ac40SOndrej Zary 15936c9b9c55SOndrej Zary shpnt->io_port = pci_resource_start(pdev, 0); 15946c9b9c55SOndrej Zary shpnt->io_port &= 0xfffffff8; 15956c9b9c55SOndrej Zary shpnt->n_io_port = pci_resource_len(pdev, 0); 15966c9b9c55SOndrej Zary atpdev->baseport = shpnt->io_port; 15976c9b9c55SOndrej Zary shpnt->unique_id = shpnt->io_port; 15986c9b9c55SOndrej Zary shpnt->irq = pdev->irq; 15991da177e4SLinus Torvalds 1600f5f53a38SOndrej Zary err = atp870u_init_tables(shpnt); 1601f5f53a38SOndrej Zary if (err) { 1602f5f53a38SOndrej Zary dev_err(&pdev->dev, "Unable to allocate tables for Acard controller\n"); 1603f5f53a38SOndrej Zary goto unregister; 1604f5f53a38SOndrej Zary } 1605f5f53a38SOndrej Zary 1606c7e6a029SOndrej Zary if (is880(atpdev)) 1607c7e6a029SOndrej Zary atp880_init(shpnt); 1608ecc6ff95SOndrej Zary else if (is885(atpdev)) 1609ecc6ff95SOndrej Zary atp885_init(shpnt); 16104190230eSOndrej Zary else 16114190230eSOndrej Zary atp870_init(shpnt); 16121da177e4SLinus Torvalds 16131729c0d2SOndrej Zary err = request_irq(shpnt->irq, atp870u_intr_handle, IRQF_SHARED, "atp870u", shpnt); 16141729c0d2SOndrej Zary if (err) { 16151729c0d2SOndrej Zary dev_err(&pdev->dev, "Unable to allocate IRQ %d.\n", shpnt->irq); 16161729c0d2SOndrej Zary goto free_tables; 16171729c0d2SOndrej Zary } 16181729c0d2SOndrej Zary 1619bdd5ac40SOndrej Zary err = scsi_add_host(shpnt, &pdev->dev); 1620bdd5ac40SOndrej Zary if (err) 16211da177e4SLinus Torvalds goto scsi_add_fail; 16221da177e4SLinus Torvalds scsi_scan_host(shpnt); 16231729c0d2SOndrej Zary 16241da177e4SLinus Torvalds return 0; 16251da177e4SLinus Torvalds 16261da177e4SLinus Torvalds scsi_add_fail: 16276c9b9c55SOndrej Zary free_irq(shpnt->irq, shpnt); 16281da177e4SLinus Torvalds free_tables: 16291da177e4SLinus Torvalds atp870u_free_tables(shpnt); 16301da177e4SLinus Torvalds unregister: 16311da177e4SLinus Torvalds scsi_host_put(shpnt); 163211ec1318SOndrej Zary release_region: 163311ec1318SOndrej Zary pci_release_regions(pdev); 1634bdd5ac40SOndrej Zary disable_device: 1635bdd5ac40SOndrej Zary pci_disable_device(pdev); 1636bdd5ac40SOndrej Zary fail: 1637bdd5ac40SOndrej Zary return err; 16381da177e4SLinus Torvalds } 16391da177e4SLinus Torvalds 16401da177e4SLinus Torvalds /* The abort command does not leave the device in a clean state where 16411da177e4SLinus Torvalds it is available to be used again. Until this gets worked out, we will 16421da177e4SLinus Torvalds leave it commented out. */ 16431da177e4SLinus Torvalds 16441da177e4SLinus Torvalds static int atp870u_abort(struct scsi_cmnd * SCpnt) 16451da177e4SLinus Torvalds { 16461da177e4SLinus Torvalds unsigned char j, k, c; 16471da177e4SLinus Torvalds struct scsi_cmnd *workrequ; 16481da177e4SLinus Torvalds struct atp_unit *dev; 16491da177e4SLinus Torvalds struct Scsi_Host *host; 16501da177e4SLinus Torvalds host = SCpnt->device->host; 16511da177e4SLinus Torvalds 16521da177e4SLinus Torvalds dev = (struct atp_unit *)&host->hostdata; 1653422c0d61SJeff Garzik c = scmd_channel(SCpnt); 16541da177e4SLinus Torvalds printk(" atp870u: abort Channel = %x \n", c); 16551da177e4SLinus Torvalds printk("working=%x last_cmd=%x ", dev->working[c], dev->last_cmd[c]); 16561da177e4SLinus Torvalds printk(" quhdu=%x quendu=%x ", dev->quhd[c], dev->quend[c]); 16571da177e4SLinus Torvalds for (j = 0; j < 0x18; j++) { 16586a3cebb6SOndrej Zary printk(" r%2x=%2x", j, atp_readb_io(dev, c, j)); 16591da177e4SLinus Torvalds } 16606a3cebb6SOndrej Zary printk(" r1c=%2x", atp_readb_io(dev, c, 0x1c)); 16616a3cebb6SOndrej Zary printk(" r1f=%2x in_snd=%2x ", atp_readb_io(dev, c, 0x1f), dev->in_snd[c]); 16626a3cebb6SOndrej Zary printk(" d00=%2x", atp_readb_pci(dev, c, 0x00)); 16636a3cebb6SOndrej Zary printk(" d02=%2x", atp_readb_pci(dev, c, 0x02)); 16641da177e4SLinus Torvalds for(j=0;j<16;j++) { 16651da177e4SLinus Torvalds if (dev->id[c][j].curr_req != NULL) { 16661da177e4SLinus Torvalds workrequ = dev->id[c][j].curr_req; 16671da177e4SLinus Torvalds printk("\n que cdb= "); 16681da177e4SLinus Torvalds for (k=0; k < workrequ->cmd_len; k++) { 16691da177e4SLinus Torvalds printk(" %2x ",workrequ->cmnd[k]); 16701da177e4SLinus Torvalds } 16711da177e4SLinus Torvalds printk(" last_lenu= %x ",(unsigned int)dev->id[c][j].last_len); 16721da177e4SLinus Torvalds } 16731da177e4SLinus Torvalds } 16741da177e4SLinus Torvalds return SUCCESS; 16751da177e4SLinus Torvalds } 16761da177e4SLinus Torvalds 16771da177e4SLinus Torvalds static const char *atp870u_info(struct Scsi_Host *notused) 16781da177e4SLinus Torvalds { 16791da177e4SLinus Torvalds static char buffer[128]; 16801da177e4SLinus Torvalds 16811da177e4SLinus Torvalds strcpy(buffer, "ACARD AEC-6710/6712/67160 PCI Ultra/W/LVD SCSI-3 Adapter Driver V2.6+ac "); 16821da177e4SLinus Torvalds 16831da177e4SLinus Torvalds return buffer; 16841da177e4SLinus Torvalds } 16851da177e4SLinus Torvalds 1686d773e422SAl Viro static int atp870u_show_info(struct seq_file *m, struct Scsi_Host *HBAptr) 16871da177e4SLinus Torvalds { 16883d30079cSRasmus Villemoes seq_puts(m, "ACARD AEC-671X Driver Version: 2.6+ac\n\n" 16893d30079cSRasmus Villemoes "Adapter Configuration:\n"); 1690d773e422SAl Viro seq_printf(m, " Base IO: %#.4lx\n", HBAptr->io_port); 1691d773e422SAl Viro seq_printf(m, " IRQ: %d\n", HBAptr->irq); 1692d773e422SAl Viro return 0; 16931da177e4SLinus Torvalds } 16941da177e4SLinus Torvalds 16951da177e4SLinus Torvalds 16961da177e4SLinus Torvalds static int atp870u_biosparam(struct scsi_device *disk, struct block_device *dev, 16971da177e4SLinus Torvalds sector_t capacity, int *ip) 16981da177e4SLinus Torvalds { 16991da177e4SLinus Torvalds int heads, sectors, cylinders; 17001da177e4SLinus Torvalds 17011da177e4SLinus Torvalds heads = 64; 17021da177e4SLinus Torvalds sectors = 32; 17031da177e4SLinus Torvalds cylinders = (unsigned long)capacity / (heads * sectors); 17041da177e4SLinus Torvalds if (cylinders > 1024) { 17051da177e4SLinus Torvalds heads = 255; 17061da177e4SLinus Torvalds sectors = 63; 17071da177e4SLinus Torvalds cylinders = (unsigned long)capacity / (heads * sectors); 17081da177e4SLinus Torvalds } 17091da177e4SLinus Torvalds ip[0] = heads; 17101da177e4SLinus Torvalds ip[1] = sectors; 17111da177e4SLinus Torvalds ip[2] = cylinders; 17121da177e4SLinus Torvalds 17131da177e4SLinus Torvalds return 0; 17141da177e4SLinus Torvalds } 17151da177e4SLinus Torvalds 17161da177e4SLinus Torvalds static void atp870u_remove (struct pci_dev *pdev) 17171da177e4SLinus Torvalds { 17181da177e4SLinus Torvalds struct atp_unit *devext = pci_get_drvdata(pdev); 17191da177e4SLinus Torvalds struct Scsi_Host *pshost = devext->host; 17201da177e4SLinus Torvalds 17211da177e4SLinus Torvalds scsi_remove_host(pshost); 17221da177e4SLinus Torvalds free_irq(pshost->irq, pshost); 172311ec1318SOndrej Zary pci_release_regions(pdev); 172411ec1318SOndrej Zary pci_disable_device(pdev); 17251da177e4SLinus Torvalds atp870u_free_tables(pshost); 17261da177e4SLinus Torvalds scsi_host_put(pshost); 17271da177e4SLinus Torvalds } 17281da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 17291da177e4SLinus Torvalds 17301da177e4SLinus Torvalds static struct scsi_host_template atp870u_template = { 17311da177e4SLinus Torvalds .module = THIS_MODULE, 17321da177e4SLinus Torvalds .name = "atp870u" /* name */, 17331da177e4SLinus Torvalds .proc_name = "atp870u", 1734d773e422SAl Viro .show_info = atp870u_show_info, 17351da177e4SLinus Torvalds .info = atp870u_info /* info */, 17361da177e4SLinus Torvalds .queuecommand = atp870u_queuecommand /* queuecommand */, 17371da177e4SLinus Torvalds .eh_abort_handler = atp870u_abort /* abort */, 17381da177e4SLinus Torvalds .bios_param = atp870u_biosparam /* biosparm */, 17391da177e4SLinus Torvalds .can_queue = qcnt /* can_queue */, 17401da177e4SLinus Torvalds .this_id = 7 /* SCSI ID */, 174135c33633SFinn Thain .sg_tablesize = ATP870U_SCATTER /*SG_ALL*/, 17421da177e4SLinus Torvalds .max_sectors = ATP870U_MAX_SECTORS, 17431da177e4SLinus Torvalds }; 17441da177e4SLinus Torvalds 17451da177e4SLinus Torvalds static struct pci_device_id atp870u_id_table[] = { 17461da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP885_DEVID) }, 17471da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID1) }, 17481da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID2) }, 17491da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7610) }, 17501da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612UW) }, 17511da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612U) }, 17521da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612S) }, 17531da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612D) }, 17541da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612SUW) }, 17551da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_8060) }, 17561da177e4SLinus Torvalds { 0, }, 17571da177e4SLinus Torvalds }; 17581da177e4SLinus Torvalds 17591da177e4SLinus Torvalds MODULE_DEVICE_TABLE(pci, atp870u_id_table); 17601da177e4SLinus Torvalds 17611da177e4SLinus Torvalds static struct pci_driver atp870u_driver = { 17621da177e4SLinus Torvalds .id_table = atp870u_id_table, 17631da177e4SLinus Torvalds .name = "atp870u", 17641da177e4SLinus Torvalds .probe = atp870u_probe, 17656f039790SGreg Kroah-Hartman .remove = atp870u_remove, 17661da177e4SLinus Torvalds }; 17671da177e4SLinus Torvalds 17681ccd7d68SOndrej Zary module_pci_driver(atp870u_driver); 17691da177e4SLinus Torvalds 1770bcd5c59fSHannes Reinecke static void atp_is(struct atp_unit *dev, unsigned char c, bool wide_chip, 1771bcd5c59fSHannes Reinecke unsigned char lvdmode) 17721da177e4SLinus Torvalds { 1773fa50b308SOndrej Zary unsigned char i, j, k, rmb, n; 17741da177e4SLinus Torvalds unsigned short int m; 17751da177e4SLinus Torvalds static unsigned char mbuf[512]; 17761da177e4SLinus Torvalds static unsigned char satn[9] = { 0, 0, 0, 0, 0, 0, 0, 6, 6 }; 17771da177e4SLinus Torvalds static unsigned char inqd[9] = { 0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6 }; 17781da177e4SLinus Torvalds static unsigned char synn[6] = { 0x80, 1, 3, 1, 0x19, 0x0e }; 17791da177e4SLinus Torvalds unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e }; 17801da177e4SLinus Torvalds static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x19, 0x0e }; 1781460da918SOndrej Zary static unsigned char synw_870[6] = { 0x80, 1, 3, 1, 0x0c, 0x07 }; 17821da177e4SLinus Torvalds unsigned char synuw[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e }; 17831da177e4SLinus Torvalds static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 }; 17841da177e4SLinus Torvalds static unsigned char u3[9] = { 0x80, 1, 6, 4, 0x09, 00, 0x0e, 0x01, 0x02 }; 17851da177e4SLinus Torvalds 17861da177e4SLinus Torvalds for (i = 0; i < 16; i++) { 1787197fb8d8SOndrej Zary if (!wide_chip && (i > 7)) 1788197fb8d8SOndrej Zary break; 17891da177e4SLinus Torvalds m = 1; 17901da177e4SLinus Torvalds m = m << i; 17911da177e4SLinus Torvalds if ((m & dev->active_id[c]) != 0) { 17921da177e4SLinus Torvalds continue; 17931da177e4SLinus Torvalds } 17941da177e4SLinus Torvalds if (i == dev->host_id[c]) { 17951da177e4SLinus Torvalds printk(KERN_INFO " ID: %2d Host Adapter\n", dev->host_id[c]); 17961da177e4SLinus Torvalds continue; 17971da177e4SLinus Torvalds } 1798197fb8d8SOndrej Zary atp_writeb_io(dev, c, 0x1b, wide_chip ? 0x01 : 0x00); 17995d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 1, 0x08); 18005d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 2, 0x7f); 18015d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 3, satn[0]); 18025d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 4, satn[1]); 18035d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 5, satn[2]); 18045d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 6, satn[3]); 18055d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 7, satn[4]); 18065d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 8, satn[5]); 18075d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x0f, 0); 18085d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp); 18095d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x12, 0); 18105d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x13, satn[6]); 18115d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, satn[7]); 18121da177e4SLinus Torvalds j = i; 18131da177e4SLinus Torvalds if ((j & 0x08) != 0) { 18141da177e4SLinus Torvalds j = (j & 0x07) | 0x40; 18151da177e4SLinus Torvalds } 18165d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x15, j); 18175d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, satn[8]); 18181da177e4SLinus Torvalds 18195d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) 18201da177e4SLinus Torvalds cpu_relax(); 182180b52a7fSOndrej Zary 182280b52a7fSOndrej Zary if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e) 18231da177e4SLinus Torvalds continue; 182480b52a7fSOndrej Zary 18255d2a5a4fSOndrej Zary while (atp_readb_io(dev, c, 0x17) != 0x8e) 18261da177e4SLinus Torvalds cpu_relax(); 182780b52a7fSOndrej Zary 18281da177e4SLinus Torvalds dev->active_id[c] |= m; 18291da177e4SLinus Torvalds 18305d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x10, 0x30); 1831b922a449SOndrej Zary if (is885(dev) || is880(dev)) 18325d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, 0x00); 1833460da918SOndrej Zary else /* result of is870() merge - is this a bug? */ 1834460da918SOndrej Zary atp_writeb_io(dev, c, 0x04, 0x00); 18351da177e4SLinus Torvalds 18361da177e4SLinus Torvalds phase_cmd: 18375d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 183880b52a7fSOndrej Zary 18395d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) 18401da177e4SLinus Torvalds cpu_relax(); 184180b52a7fSOndrej Zary 18425d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17); 18431da177e4SLinus Torvalds if (j != 0x16) { 18445d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x10, 0x41); 18451da177e4SLinus Torvalds goto phase_cmd; 18461da177e4SLinus Torvalds } 18471da177e4SLinus Torvalds sel_ok: 18485d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 3, inqd[0]); 18495d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 4, inqd[1]); 18505d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 5, inqd[2]); 18515d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 6, inqd[3]); 18525d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 7, inqd[4]); 18535d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 8, inqd[5]); 18545d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x0f, 0); 18555d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp); 18565d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x12, 0); 18575d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x13, inqd[6]); 18585d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, inqd[7]); 18595d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, inqd[8]); 186080b52a7fSOndrej Zary 18615d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) 18621da177e4SLinus Torvalds cpu_relax(); 186380b52a7fSOndrej Zary 186480b52a7fSOndrej Zary if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e) 18651da177e4SLinus Torvalds continue; 186680b52a7fSOndrej Zary 18675d2a5a4fSOndrej Zary while (atp_readb_io(dev, c, 0x17) != 0x8e) 18681da177e4SLinus Torvalds cpu_relax(); 186980b52a7fSOndrej Zary 1870197fb8d8SOndrej Zary if (wide_chip) 18715d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x1b, 0x00); 1872197fb8d8SOndrej Zary 18735d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 18741da177e4SLinus Torvalds j = 0; 18751da177e4SLinus Torvalds rd_inq_data: 18765d2a5a4fSOndrej Zary k = atp_readb_io(dev, c, 0x1f); 18771da177e4SLinus Torvalds if ((k & 0x01) != 0) { 18785d2a5a4fSOndrej Zary mbuf[j++] = atp_readb_io(dev, c, 0x19); 18791da177e4SLinus Torvalds goto rd_inq_data; 18801da177e4SLinus Torvalds } 18811da177e4SLinus Torvalds if ((k & 0x80) == 0) { 18821da177e4SLinus Torvalds goto rd_inq_data; 18831da177e4SLinus Torvalds } 18845d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17); 18851da177e4SLinus Torvalds if (j == 0x16) { 18861da177e4SLinus Torvalds goto inq_ok; 18871da177e4SLinus Torvalds } 18885d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x10, 0x46); 18895d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x12, 0); 18905d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x13, 0); 18915d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, 0); 18925d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 189380b52a7fSOndrej Zary 18945d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) 18951da177e4SLinus Torvalds cpu_relax(); 189680b52a7fSOndrej Zary 189780b52a7fSOndrej Zary if (atp_readb_io(dev, c, 0x17) != 0x16) 18981da177e4SLinus Torvalds goto sel_ok; 189980b52a7fSOndrej Zary 19001da177e4SLinus Torvalds inq_ok: 19011da177e4SLinus Torvalds mbuf[36] = 0; 19021da177e4SLinus Torvalds printk(KERN_INFO " ID: %2d %s\n", i, &mbuf[8]); 19031da177e4SLinus Torvalds dev->id[c][i].devtype = mbuf[0]; 19041da177e4SLinus Torvalds rmb = mbuf[1]; 19051da177e4SLinus Torvalds n = mbuf[7]; 1906197fb8d8SOndrej Zary if (!wide_chip) 1907197fb8d8SOndrej Zary goto not_wide; 19081da177e4SLinus Torvalds if ((mbuf[7] & 0x60) == 0) { 19091da177e4SLinus Torvalds goto not_wide; 19101da177e4SLinus Torvalds } 1911b922a449SOndrej Zary if (is885(dev) || is880(dev)) { 1912197fb8d8SOndrej Zary if ((i < 8) && ((dev->global_map[c] & 0x20) == 0)) 1913197fb8d8SOndrej Zary goto not_wide; 1914197fb8d8SOndrej Zary } else { /* result of is870() merge - is this a bug? */ 1915197fb8d8SOndrej Zary if ((dev->global_map[c] & 0x20) == 0) 19161da177e4SLinus Torvalds goto not_wide; 19171da177e4SLinus Torvalds } 19181da177e4SLinus Torvalds if (lvdmode == 0) { 19191da177e4SLinus Torvalds goto chg_wide; 19201da177e4SLinus Torvalds } 192180b52a7fSOndrej Zary if (dev->sp[c][i] != 0x04) // force u2 192280b52a7fSOndrej Zary { 19231da177e4SLinus Torvalds goto chg_wide; 19241da177e4SLinus Torvalds } 19251da177e4SLinus Torvalds 19265d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x1b, 0x01); 19275d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 3, satn[0]); 19285d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 4, satn[1]); 19295d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 5, satn[2]); 19305d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 6, satn[3]); 19315d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 7, satn[4]); 19325d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 8, satn[5]); 19335d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x0f, 0); 19345d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp); 19355d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x12, 0); 19365d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x13, satn[6]); 19375d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, satn[7]); 19385d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, satn[8]); 19391da177e4SLinus Torvalds 19405d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) 19411da177e4SLinus Torvalds cpu_relax(); 194280b52a7fSOndrej Zary 194380b52a7fSOndrej Zary if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e) 19441da177e4SLinus Torvalds continue; 194580b52a7fSOndrej Zary 19465d2a5a4fSOndrej Zary while (atp_readb_io(dev, c, 0x17) != 0x8e) 19471da177e4SLinus Torvalds cpu_relax(); 194880b52a7fSOndrej Zary 19491da177e4SLinus Torvalds try_u3: 19501da177e4SLinus Torvalds j = 0; 19515d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, 0x09); 19525d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x20); 19531da177e4SLinus Torvalds 19545d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) { 19555d2a5a4fSOndrej Zary if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0) 19565d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x19, u3[j++]); 19571da177e4SLinus Torvalds cpu_relax(); 19581da177e4SLinus Torvalds } 195980b52a7fSOndrej Zary 19605d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00) 19611da177e4SLinus Torvalds cpu_relax(); 196280b52a7fSOndrej Zary 19635d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17) & 0x0f; 19641da177e4SLinus Torvalds if (j == 0x0f) { 19651da177e4SLinus Torvalds goto u3p_in; 19661da177e4SLinus Torvalds } 19671da177e4SLinus Torvalds if (j == 0x0a) { 19681da177e4SLinus Torvalds goto u3p_cmd; 19691da177e4SLinus Torvalds } 19701da177e4SLinus Torvalds if (j == 0x0e) { 19711da177e4SLinus Torvalds goto try_u3; 19721da177e4SLinus Torvalds } 19731da177e4SLinus Torvalds continue; 19741da177e4SLinus Torvalds u3p_out: 19755d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x20); 19765d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) { 19775d2a5a4fSOndrej Zary if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0) 19785d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x19, 0); 19791da177e4SLinus Torvalds cpu_relax(); 19801da177e4SLinus Torvalds } 19815d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17) & 0x0f; 19821da177e4SLinus Torvalds if (j == 0x0f) { 19831da177e4SLinus Torvalds goto u3p_in; 19841da177e4SLinus Torvalds } 19851da177e4SLinus Torvalds if (j == 0x0a) { 19861da177e4SLinus Torvalds goto u3p_cmd; 19871da177e4SLinus Torvalds } 19881da177e4SLinus Torvalds if (j == 0x0e) { 19891da177e4SLinus Torvalds goto u3p_out; 19901da177e4SLinus Torvalds } 19911da177e4SLinus Torvalds continue; 19921da177e4SLinus Torvalds u3p_in: 19935d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, 0x09); 19945d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x20); 19951da177e4SLinus Torvalds k = 0; 19961da177e4SLinus Torvalds u3p_in1: 19975d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x1f); 19981da177e4SLinus Torvalds if ((j & 0x01) != 0) { 19995d2a5a4fSOndrej Zary mbuf[k++] = atp_readb_io(dev, c, 0x19); 20001da177e4SLinus Torvalds goto u3p_in1; 20011da177e4SLinus Torvalds } 20021da177e4SLinus Torvalds if ((j & 0x80) == 0x00) { 20031da177e4SLinus Torvalds goto u3p_in1; 20041da177e4SLinus Torvalds } 20055d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17) & 0x0f; 20061da177e4SLinus Torvalds if (j == 0x0f) { 20071da177e4SLinus Torvalds goto u3p_in; 20081da177e4SLinus Torvalds } 20091da177e4SLinus Torvalds if (j == 0x0a) { 20101da177e4SLinus Torvalds goto u3p_cmd; 20111da177e4SLinus Torvalds } 20121da177e4SLinus Torvalds if (j == 0x0e) { 20131da177e4SLinus Torvalds goto u3p_out; 20141da177e4SLinus Torvalds } 20151da177e4SLinus Torvalds continue; 20161da177e4SLinus Torvalds u3p_cmd: 20175d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x10, 0x30); 20185d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, 0x00); 20195d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 202080b52a7fSOndrej Zary 20215d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00); 202280b52a7fSOndrej Zary 20235d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17); 20241da177e4SLinus Torvalds if (j != 0x16) { 20251da177e4SLinus Torvalds if (j == 0x4e) { 20261da177e4SLinus Torvalds goto u3p_out; 20271da177e4SLinus Torvalds } 20281da177e4SLinus Torvalds continue; 20291da177e4SLinus Torvalds } 20301da177e4SLinus Torvalds if (mbuf[0] != 0x01) { 20311da177e4SLinus Torvalds goto chg_wide; 20321da177e4SLinus Torvalds } 20331da177e4SLinus Torvalds if (mbuf[1] != 0x06) { 20341da177e4SLinus Torvalds goto chg_wide; 20351da177e4SLinus Torvalds } 20361da177e4SLinus Torvalds if (mbuf[2] != 0x04) { 20371da177e4SLinus Torvalds goto chg_wide; 20381da177e4SLinus Torvalds } 20391da177e4SLinus Torvalds if (mbuf[3] == 0x09) { 20401da177e4SLinus Torvalds m = 1; 20411da177e4SLinus Torvalds m = m << i; 20421da177e4SLinus Torvalds dev->wide_id[c] |= m; 20431da177e4SLinus Torvalds dev->id[c][i].devsp = 0xce; 20441da177e4SLinus Torvalds #ifdef ED_DBGP 2045bcd5c59fSHannes Reinecke printk("dev->id[%2d][%2d].devsp = %2x\n", 2046bcd5c59fSHannes Reinecke c, i, dev->id[c][i].devsp); 20471da177e4SLinus Torvalds #endif 20481da177e4SLinus Torvalds continue; 20491da177e4SLinus Torvalds } 20501da177e4SLinus Torvalds chg_wide: 20515d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x1b, 0x01); 20525d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 3, satn[0]); 20535d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 4, satn[1]); 20545d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 5, satn[2]); 20555d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 6, satn[3]); 20565d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 7, satn[4]); 20575d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 8, satn[5]); 20585d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x0f, 0); 20595d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp); 20605d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x12, 0); 20615d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x13, satn[6]); 20625d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, satn[7]); 20635d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, satn[8]); 20641da177e4SLinus Torvalds 20655d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) 20661da177e4SLinus Torvalds cpu_relax(); 206780b52a7fSOndrej Zary 2068bcd5c59fSHannes Reinecke if (atp_readb_io(dev, c, 0x17) != 0x11 && 2069bcd5c59fSHannes Reinecke atp_readb_io(dev, c, 0x17) != 0x8e) 20701da177e4SLinus Torvalds continue; 207180b52a7fSOndrej Zary 20725d2a5a4fSOndrej Zary while (atp_readb_io(dev, c, 0x17) != 0x8e) 20731da177e4SLinus Torvalds cpu_relax(); 207480b52a7fSOndrej Zary 20751da177e4SLinus Torvalds try_wide: 20761da177e4SLinus Torvalds j = 0; 20775d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, 0x05); 20785d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x20); 20791da177e4SLinus Torvalds 20805d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) { 20815d2a5a4fSOndrej Zary if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0) 20825d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x19, wide[j++]); 20831da177e4SLinus Torvalds cpu_relax(); 20841da177e4SLinus Torvalds } 208580b52a7fSOndrej Zary 20865d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00) 20871da177e4SLinus Torvalds cpu_relax(); 208880b52a7fSOndrej Zary 20895d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17) & 0x0f; 20901da177e4SLinus Torvalds if (j == 0x0f) { 20911da177e4SLinus Torvalds goto widep_in; 20921da177e4SLinus Torvalds } 20931da177e4SLinus Torvalds if (j == 0x0a) { 20941da177e4SLinus Torvalds goto widep_cmd; 20951da177e4SLinus Torvalds } 20961da177e4SLinus Torvalds if (j == 0x0e) { 20971da177e4SLinus Torvalds goto try_wide; 20981da177e4SLinus Torvalds } 20991da177e4SLinus Torvalds continue; 21001da177e4SLinus Torvalds widep_out: 21015d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x20); 21025d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) { 21035d2a5a4fSOndrej Zary if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0) 21045d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x19, 0); 21051da177e4SLinus Torvalds cpu_relax(); 21061da177e4SLinus Torvalds } 21075d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17) & 0x0f; 21081da177e4SLinus Torvalds if (j == 0x0f) { 21091da177e4SLinus Torvalds goto widep_in; 21101da177e4SLinus Torvalds } 21111da177e4SLinus Torvalds if (j == 0x0a) { 21121da177e4SLinus Torvalds goto widep_cmd; 21131da177e4SLinus Torvalds } 21141da177e4SLinus Torvalds if (j == 0x0e) { 21151da177e4SLinus Torvalds goto widep_out; 21161da177e4SLinus Torvalds } 21171da177e4SLinus Torvalds continue; 21181da177e4SLinus Torvalds widep_in: 21195d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, 0xff); 21205d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x20); 21211da177e4SLinus Torvalds k = 0; 21221da177e4SLinus Torvalds widep_in1: 21235d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x1f); 21241da177e4SLinus Torvalds if ((j & 0x01) != 0) { 21255d2a5a4fSOndrej Zary mbuf[k++] = atp_readb_io(dev, c, 0x19); 21261da177e4SLinus Torvalds goto widep_in1; 21271da177e4SLinus Torvalds } 21281da177e4SLinus Torvalds if ((j & 0x80) == 0x00) { 21291da177e4SLinus Torvalds goto widep_in1; 21301da177e4SLinus Torvalds } 21315d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17) & 0x0f; 21321da177e4SLinus Torvalds if (j == 0x0f) { 21331da177e4SLinus Torvalds goto widep_in; 21341da177e4SLinus Torvalds } 21351da177e4SLinus Torvalds if (j == 0x0a) { 21361da177e4SLinus Torvalds goto widep_cmd; 21371da177e4SLinus Torvalds } 21381da177e4SLinus Torvalds if (j == 0x0e) { 21391da177e4SLinus Torvalds goto widep_out; 21401da177e4SLinus Torvalds } 21411da177e4SLinus Torvalds continue; 21421da177e4SLinus Torvalds widep_cmd: 21435d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x10, 0x30); 21445d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, 0x00); 21455d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 214680b52a7fSOndrej Zary 21475d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) 21481da177e4SLinus Torvalds cpu_relax(); 214980b52a7fSOndrej Zary 21505d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17); 21511da177e4SLinus Torvalds if (j != 0x16) { 21521da177e4SLinus Torvalds if (j == 0x4e) { 21531da177e4SLinus Torvalds goto widep_out; 21541da177e4SLinus Torvalds } 21551da177e4SLinus Torvalds continue; 21561da177e4SLinus Torvalds } 21571da177e4SLinus Torvalds if (mbuf[0] != 0x01) { 21581da177e4SLinus Torvalds goto not_wide; 21591da177e4SLinus Torvalds } 21601da177e4SLinus Torvalds if (mbuf[1] != 0x02) { 21611da177e4SLinus Torvalds goto not_wide; 21621da177e4SLinus Torvalds } 21631da177e4SLinus Torvalds if (mbuf[2] != 0x03) { 21641da177e4SLinus Torvalds goto not_wide; 21651da177e4SLinus Torvalds } 21661da177e4SLinus Torvalds if (mbuf[3] != 0x01) { 21671da177e4SLinus Torvalds goto not_wide; 21681da177e4SLinus Torvalds } 21691da177e4SLinus Torvalds m = 1; 21701da177e4SLinus Torvalds m = m << i; 21711da177e4SLinus Torvalds dev->wide_id[c] |= m; 21721da177e4SLinus Torvalds not_wide: 2173bcd5c59fSHannes Reinecke if ((dev->id[c][i].devtype == 0x00) || 2174bcd5c59fSHannes Reinecke (dev->id[c][i].devtype == 0x07) || 2175bcd5c59fSHannes Reinecke ((dev->id[c][i].devtype == 0x05) && ((n & 0x10) != 0))) { 21761da177e4SLinus Torvalds m = 1; 21771da177e4SLinus Torvalds m = m << i; 21781da177e4SLinus Torvalds if ((dev->async[c] & m) != 0) { 21791da177e4SLinus Torvalds goto set_sync; 21801da177e4SLinus Torvalds } 21811da177e4SLinus Torvalds } 21821da177e4SLinus Torvalds continue; 21831da177e4SLinus Torvalds set_sync: 2184b922a449SOndrej Zary if ((!is885(dev) && !is880(dev)) || (dev->sp[c][i] == 0x02)) { 21851da177e4SLinus Torvalds synu[4] = 0x0c; 21861da177e4SLinus Torvalds synuw[4] = 0x0c; 21871da177e4SLinus Torvalds } else { 21881da177e4SLinus Torvalds if (dev->sp[c][i] >= 0x03) { 21891da177e4SLinus Torvalds synu[4] = 0x0a; 21901da177e4SLinus Torvalds synuw[4] = 0x0a; 21911da177e4SLinus Torvalds } 21921da177e4SLinus Torvalds } 21931da177e4SLinus Torvalds j = 0; 21941da177e4SLinus Torvalds if ((m & dev->wide_id[c]) != 0) { 21951da177e4SLinus Torvalds j |= 0x01; 21961da177e4SLinus Torvalds } 21975d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x1b, j); 21985d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 3, satn[0]); 21995d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 4, satn[1]); 22005d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 5, satn[2]); 22015d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 6, satn[3]); 22025d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 7, satn[4]); 22035d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 8, satn[5]); 22045d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x0f, 0); 22055d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp); 22065d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x12, 0); 22075d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x13, satn[6]); 22085d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, satn[7]); 22095d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, satn[8]); 22101da177e4SLinus Torvalds 22115d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) 22121da177e4SLinus Torvalds cpu_relax(); 221380b52a7fSOndrej Zary 2214bcd5c59fSHannes Reinecke if (atp_readb_io(dev, c, 0x17) != 0x11 && 2215bcd5c59fSHannes Reinecke atp_readb_io(dev, c, 0x17) != 0x8e) 22161da177e4SLinus Torvalds continue; 221780b52a7fSOndrej Zary 22185d2a5a4fSOndrej Zary while (atp_readb_io(dev, c, 0x17) != 0x8e) 22191da177e4SLinus Torvalds cpu_relax(); 222080b52a7fSOndrej Zary 22211da177e4SLinus Torvalds try_sync: 22221da177e4SLinus Torvalds j = 0; 22235d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, 0x06); 22245d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x20); 22251da177e4SLinus Torvalds 22265d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) { 22275d2a5a4fSOndrej Zary if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0) { 22281da177e4SLinus Torvalds if ((m & dev->wide_id[c]) != 0) { 2229b922a449SOndrej Zary if (is885(dev) || is880(dev)) { 22301da177e4SLinus Torvalds if ((m & dev->ultra_map[c]) != 0) { 22315d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x19, synuw[j++]); 22321da177e4SLinus Torvalds } else { 22335d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x19, synw[j++]); 22341da177e4SLinus Torvalds } 2235460da918SOndrej Zary } else 2236460da918SOndrej Zary atp_writeb_io(dev, c, 0x19, synw_870[j++]); 22371da177e4SLinus Torvalds } else { 22381da177e4SLinus Torvalds if ((m & dev->ultra_map[c]) != 0) { 22395d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x19, synu[j++]); 22401da177e4SLinus Torvalds } else { 22415d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x19, synn[j++]); 22421da177e4SLinus Torvalds } 22431da177e4SLinus Torvalds } 22441da177e4SLinus Torvalds } 22451da177e4SLinus Torvalds } 224680b52a7fSOndrej Zary 22475d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00) 22481da177e4SLinus Torvalds cpu_relax(); 224980b52a7fSOndrej Zary 22505d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17) & 0x0f; 22511da177e4SLinus Torvalds if (j == 0x0f) { 22521da177e4SLinus Torvalds goto phase_ins; 22531da177e4SLinus Torvalds } 22541da177e4SLinus Torvalds if (j == 0x0a) { 22551da177e4SLinus Torvalds goto phase_cmds; 22561da177e4SLinus Torvalds } 22571da177e4SLinus Torvalds if (j == 0x0e) { 22581da177e4SLinus Torvalds goto try_sync; 22591da177e4SLinus Torvalds } 22601da177e4SLinus Torvalds continue; 22611da177e4SLinus Torvalds phase_outs: 22625d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x20); 22635d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) { 22645d2a5a4fSOndrej Zary if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0x00) 22655d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x19, 0x00); 22661da177e4SLinus Torvalds cpu_relax(); 22671da177e4SLinus Torvalds } 22685d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17); 22691da177e4SLinus Torvalds if (j == 0x85) { 22701da177e4SLinus Torvalds goto tar_dcons; 22711da177e4SLinus Torvalds } 22721da177e4SLinus Torvalds j &= 0x0f; 22731da177e4SLinus Torvalds if (j == 0x0f) { 22741da177e4SLinus Torvalds goto phase_ins; 22751da177e4SLinus Torvalds } 22761da177e4SLinus Torvalds if (j == 0x0a) { 22771da177e4SLinus Torvalds goto phase_cmds; 22781da177e4SLinus Torvalds } 22791da177e4SLinus Torvalds if (j == 0x0e) { 22801da177e4SLinus Torvalds goto phase_outs; 22811da177e4SLinus Torvalds } 22821da177e4SLinus Torvalds continue; 22831da177e4SLinus Torvalds phase_ins: 2284b922a449SOndrej Zary if (is885(dev) || is880(dev)) 22855d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, 0x06); 2286460da918SOndrej Zary else 2287460da918SOndrej Zary atp_writeb_io(dev, c, 0x14, 0xff); 22885d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x20); 22891da177e4SLinus Torvalds k = 0; 22901da177e4SLinus Torvalds phase_ins1: 22915d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x1f); 22921da177e4SLinus Torvalds if ((j & 0x01) != 0x00) { 22935d2a5a4fSOndrej Zary mbuf[k++] = atp_readb_io(dev, c, 0x19); 22941da177e4SLinus Torvalds goto phase_ins1; 22951da177e4SLinus Torvalds } 22961da177e4SLinus Torvalds if ((j & 0x80) == 0x00) { 22971da177e4SLinus Torvalds goto phase_ins1; 22981da177e4SLinus Torvalds } 229980b52a7fSOndrej Zary 23005d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00); 230180b52a7fSOndrej Zary 23025d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17); 23031da177e4SLinus Torvalds if (j == 0x85) { 23041da177e4SLinus Torvalds goto tar_dcons; 23051da177e4SLinus Torvalds } 23061da177e4SLinus Torvalds j &= 0x0f; 23071da177e4SLinus Torvalds if (j == 0x0f) { 23081da177e4SLinus Torvalds goto phase_ins; 23091da177e4SLinus Torvalds } 23101da177e4SLinus Torvalds if (j == 0x0a) { 23111da177e4SLinus Torvalds goto phase_cmds; 23121da177e4SLinus Torvalds } 23131da177e4SLinus Torvalds if (j == 0x0e) { 23141da177e4SLinus Torvalds goto phase_outs; 23151da177e4SLinus Torvalds } 23161da177e4SLinus Torvalds continue; 23171da177e4SLinus Torvalds phase_cmds: 23185d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x10, 0x30); 23191da177e4SLinus Torvalds tar_dcons: 23205d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, 0x00); 23215d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 232280b52a7fSOndrej Zary 23235d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) 23241da177e4SLinus Torvalds cpu_relax(); 232580b52a7fSOndrej Zary 23265d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17); 23271da177e4SLinus Torvalds if (j != 0x16) { 23281da177e4SLinus Torvalds continue; 23291da177e4SLinus Torvalds } 23301da177e4SLinus Torvalds if (mbuf[0] != 0x01) { 23311da177e4SLinus Torvalds continue; 23321da177e4SLinus Torvalds } 23331da177e4SLinus Torvalds if (mbuf[1] != 0x03) { 23341da177e4SLinus Torvalds continue; 23351da177e4SLinus Torvalds } 23361da177e4SLinus Torvalds if (mbuf[4] == 0x00) { 23371da177e4SLinus Torvalds continue; 23381da177e4SLinus Torvalds } 23391da177e4SLinus Torvalds if (mbuf[3] > 0x64) { 23401da177e4SLinus Torvalds continue; 23411da177e4SLinus Torvalds } 2342b922a449SOndrej Zary if (is885(dev) || is880(dev)) { 23431da177e4SLinus Torvalds if (mbuf[4] > 0x0e) { 23441da177e4SLinus Torvalds mbuf[4] = 0x0e; 23451da177e4SLinus Torvalds } 2346460da918SOndrej Zary } else { 2347460da918SOndrej Zary if (mbuf[4] > 0x0c) { 2348460da918SOndrej Zary mbuf[4] = 0x0c; 2349460da918SOndrej Zary } 2350460da918SOndrej Zary } 23511da177e4SLinus Torvalds dev->id[c][i].devsp = mbuf[4]; 2352b922a449SOndrej Zary if (is885(dev) || is880(dev)) 23531da177e4SLinus Torvalds if (mbuf[3] < 0x0c) { 23541da177e4SLinus Torvalds j = 0xb0; 23551da177e4SLinus Torvalds goto set_syn_ok; 23561da177e4SLinus Torvalds } 23571da177e4SLinus Torvalds if ((mbuf[3] < 0x0d) && (rmb == 0)) { 23581da177e4SLinus Torvalds j = 0xa0; 23591da177e4SLinus Torvalds goto set_syn_ok; 23601da177e4SLinus Torvalds } 23611da177e4SLinus Torvalds if (mbuf[3] < 0x1a) { 23621da177e4SLinus Torvalds j = 0x20; 23631da177e4SLinus Torvalds goto set_syn_ok; 23641da177e4SLinus Torvalds } 23651da177e4SLinus Torvalds if (mbuf[3] < 0x33) { 23661da177e4SLinus Torvalds j = 0x40; 23671da177e4SLinus Torvalds goto set_syn_ok; 23681da177e4SLinus Torvalds } 23691da177e4SLinus Torvalds if (mbuf[3] < 0x4c) { 23701da177e4SLinus Torvalds j = 0x50; 23711da177e4SLinus Torvalds goto set_syn_ok; 23721da177e4SLinus Torvalds } 23731da177e4SLinus Torvalds j = 0x60; 23741da177e4SLinus Torvalds set_syn_ok: 23751da177e4SLinus Torvalds dev->id[c][i].devsp = (dev->id[c][i].devsp & 0x0f) | j; 23761da177e4SLinus Torvalds #ifdef ED_DBGP 2377bcd5c59fSHannes Reinecke printk("dev->id[%2d][%2d].devsp = %2x\n", 2378bcd5c59fSHannes Reinecke c,i,dev->id[c][i].devsp); 23791da177e4SLinus Torvalds #endif 23801da177e4SLinus Torvalds } 23811da177e4SLinus Torvalds } 2382