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); 5151da177e4SLinus Torvalds (*workreq->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 /** 615*6b71f60cSLee 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 if (done) { 6581da177e4SLinus Torvalds req_p->scsi_done = done; 6591da177e4SLinus Torvalds } else { 6601da177e4SLinus Torvalds #ifdef ED_DBGP 6611da177e4SLinus Torvalds printk( "atp870u_queuecommand: done can't be NULL\n"); 6621da177e4SLinus Torvalds #endif 6631da177e4SLinus Torvalds req_p->result = 0; 6641da177e4SLinus Torvalds done(req_p); 6651da177e4SLinus Torvalds return 0; 6661da177e4SLinus Torvalds } 6671da177e4SLinus Torvalds 6681da177e4SLinus Torvalds /* 6691da177e4SLinus Torvalds * Count new command 6701da177e4SLinus Torvalds */ 6711da177e4SLinus Torvalds dev->quend[c]++; 6721da177e4SLinus Torvalds if (dev->quend[c] >= qcnt) { 6731da177e4SLinus Torvalds dev->quend[c] = 0; 6741da177e4SLinus Torvalds } 6751da177e4SLinus Torvalds 6761da177e4SLinus Torvalds /* 6771da177e4SLinus Torvalds * Check queue state 6781da177e4SLinus Torvalds */ 6791da177e4SLinus Torvalds if (dev->quhd[c] == dev->quend[c]) { 6801da177e4SLinus Torvalds if (dev->quend[c] == 0) { 6811da177e4SLinus Torvalds dev->quend[c] = qcnt; 6821da177e4SLinus Torvalds } 6831da177e4SLinus Torvalds #ifdef ED_DBGP 6841da177e4SLinus Torvalds printk("atp870u_queuecommand : dev->quhd[c] == dev->quend[c]\n"); 6851da177e4SLinus Torvalds #endif 6861da177e4SLinus Torvalds dev->quend[c]--; 687f3272258SHannes Reinecke req_p->result = DID_BUS_BUSY << 16; 6881da177e4SLinus Torvalds done(req_p); 6891da177e4SLinus Torvalds return 0; 6901da177e4SLinus Torvalds } 6911da177e4SLinus Torvalds dev->quereq[c][dev->quend[c]] = req_p; 6921da177e4SLinus Torvalds #ifdef ED_DBGP 693bcd5c59fSHannes Reinecke printk("dev->ioport[c] = %x atp_readb_io(dev, c, 0x1c) = %x " 694bcd5c59fSHannes Reinecke "dev->in_int[%d] = %d dev->in_snd[%d] = %d\n", 695bcd5c59fSHannes Reinecke dev->ioport[c], atp_readb_io(dev, c, 0x1c), c, 696bcd5c59fSHannes Reinecke dev->in_int[c],c,dev->in_snd[c]); 6971da177e4SLinus Torvalds #endif 698bcd5c59fSHannes Reinecke if ((atp_readb_io(dev, c, 0x1c) == 0) && 699bcd5c59fSHannes Reinecke (dev->in_int[c] == 0) && 700bcd5c59fSHannes Reinecke (dev->in_snd[c] == 0)) { 7011da177e4SLinus Torvalds #ifdef ED_DBGP 7021da177e4SLinus Torvalds printk("Call sent_s870(atp870u_queuecommand)\n"); 7031da177e4SLinus Torvalds #endif 7041da177e4SLinus Torvalds send_s870(dev,c); 7051da177e4SLinus Torvalds } 7061da177e4SLinus Torvalds #ifdef ED_DBGP 7071da177e4SLinus Torvalds printk("atp870u_queuecommand : exit\n"); 7081da177e4SLinus Torvalds #endif 7091da177e4SLinus Torvalds return 0; 7101da177e4SLinus Torvalds } 7111da177e4SLinus Torvalds 712f281233dSJeff Garzik static DEF_SCSI_QCMD(atp870u_queuecommand) 713f281233dSJeff Garzik 714*6b71f60cSLee Jones /* 7151da177e4SLinus Torvalds * send_s870 - send a command to the controller 7161da177e4SLinus Torvalds * 7171da177e4SLinus Torvalds * On entry there is work queued to be done. We move some of that work to the 7181da177e4SLinus Torvalds * controller itself. 7191da177e4SLinus Torvalds * 7201da177e4SLinus Torvalds * Caller holds the host lock. 7211da177e4SLinus Torvalds */ 7221da177e4SLinus Torvalds static void send_s870(struct atp_unit *dev, unsigned char c) 7231da177e4SLinus Torvalds { 724468b8968SOndrej Zary struct scsi_cmnd *workreq = NULL; 7251da177e4SLinus Torvalds unsigned int i;//,k; 7261da177e4SLinus Torvalds unsigned char j, target_id; 7271da177e4SLinus Torvalds unsigned char *prd; 728c2bab403SOndrej Zary unsigned short int w; 7291da177e4SLinus Torvalds unsigned long l, bttl = 0; 7301da177e4SLinus Torvalds unsigned long sg_count; 7311da177e4SLinus Torvalds 7321da177e4SLinus Torvalds if (dev->in_snd[c] != 0) { 7331da177e4SLinus Torvalds #ifdef ED_DBGP 7341da177e4SLinus Torvalds printk("cmnd in_snd\n"); 7351da177e4SLinus Torvalds #endif 7361da177e4SLinus Torvalds return; 7371da177e4SLinus Torvalds } 7381da177e4SLinus Torvalds #ifdef ED_DBGP 7391da177e4SLinus Torvalds printk("Sent_s870 enter\n"); 7401da177e4SLinus Torvalds #endif 7411da177e4SLinus Torvalds dev->in_snd[c] = 1; 7421da177e4SLinus Torvalds if ((dev->last_cmd[c] != 0xff) && ((dev->last_cmd[c] & 0x40) != 0)) { 7431da177e4SLinus Torvalds dev->last_cmd[c] &= 0x0f; 7441da177e4SLinus Torvalds workreq = dev->id[c][dev->last_cmd[c]].curr_req; 745468b8968SOndrej Zary if (!workreq) { 7461da177e4SLinus Torvalds dev->last_cmd[c] = 0xff; 7471da177e4SLinus Torvalds if (dev->quhd[c] == dev->quend[c]) { 7481da177e4SLinus Torvalds dev->in_snd[c] = 0; 7491da177e4SLinus Torvalds return; 7501da177e4SLinus Torvalds } 7511da177e4SLinus Torvalds } 752468b8968SOndrej Zary } 753468b8968SOndrej Zary if (!workreq) { 7541da177e4SLinus Torvalds if ((dev->last_cmd[c] != 0xff) && (dev->working[c] != 0)) { 7551da177e4SLinus Torvalds dev->in_snd[c] = 0; 7561da177e4SLinus Torvalds return; 7571da177e4SLinus Torvalds } 7581da177e4SLinus Torvalds dev->working[c]++; 7591da177e4SLinus Torvalds j = dev->quhd[c]; 7601da177e4SLinus Torvalds dev->quhd[c]++; 761468b8968SOndrej Zary if (dev->quhd[c] >= qcnt) 7621da177e4SLinus Torvalds dev->quhd[c] = 0; 7631da177e4SLinus Torvalds workreq = dev->quereq[c][dev->quhd[c]]; 764468b8968SOndrej Zary if (dev->id[c][scmd_id(workreq)].curr_req != NULL) { 7651da177e4SLinus Torvalds dev->quhd[c] = j; 7661da177e4SLinus Torvalds dev->working[c]--; 7671da177e4SLinus Torvalds dev->in_snd[c] = 0; 7681da177e4SLinus Torvalds return; 7691da177e4SLinus Torvalds } 770468b8968SOndrej Zary dev->id[c][scmd_id(workreq)].curr_req = workreq; 771468b8968SOndrej Zary dev->last_cmd[c] = scmd_id(workreq); 7721da177e4SLinus Torvalds } 773bcd5c59fSHannes Reinecke if ((atp_readb_io(dev, c, 0x1f) & 0xb0) != 0 || 774bcd5c59fSHannes Reinecke atp_readb_io(dev, c, 0x1c) != 0) { 7751da177e4SLinus Torvalds #ifdef ED_DBGP 7761da177e4SLinus Torvalds printk("Abort to Send\n"); 7771da177e4SLinus Torvalds #endif 7781da177e4SLinus Torvalds dev->last_cmd[c] |= 0x40; 7791da177e4SLinus Torvalds dev->in_snd[c] = 0; 7801da177e4SLinus Torvalds return; 781468b8968SOndrej Zary } 7821da177e4SLinus Torvalds #ifdef ED_DBGP 7831da177e4SLinus Torvalds printk("OK to Send\n"); 784422c0d61SJeff Garzik scmd_printk(KERN_DEBUG, workreq, "CDB"); 7851da177e4SLinus Torvalds for(i=0;i<workreq->cmd_len;i++) { 7861da177e4SLinus Torvalds printk(" %x",workreq->cmnd[i]); 7871da177e4SLinus Torvalds } 788422c0d61SJeff Garzik printk("\n"); 7891da177e4SLinus Torvalds #endif 790fe7ed98fSBoaz Harrosh l = scsi_bufflen(workreq); 791fe7ed98fSBoaz Harrosh 792b922a449SOndrej Zary if (is885(dev)) { 7936a3cebb6SOndrej Zary j = atp_readb_base(dev, 0x29) & 0xfe; 7946a3cebb6SOndrej Zary atp_writeb_base(dev, 0x29, j); 795422c0d61SJeff Garzik dev->r1f[c][scmd_id(workreq)] = 0; 7961da177e4SLinus Torvalds } 7971da177e4SLinus Torvalds 7981da177e4SLinus Torvalds if (workreq->cmnd[0] == READ_CAPACITY) { 799fe7ed98fSBoaz Harrosh if (l > 8) 800fe7ed98fSBoaz Harrosh l = 8; 8011da177e4SLinus Torvalds } 802f3272258SHannes Reinecke if (workreq->cmnd[0] == TEST_UNIT_READY) { 803fe7ed98fSBoaz Harrosh l = 0; 8041da177e4SLinus Torvalds } 8051da177e4SLinus Torvalds 8061da177e4SLinus Torvalds j = 0; 807422c0d61SJeff Garzik target_id = scmd_id(workreq); 8081da177e4SLinus Torvalds 8091da177e4SLinus Torvalds /* 8101da177e4SLinus Torvalds * Wide ? 8111da177e4SLinus Torvalds */ 8121da177e4SLinus Torvalds w = 1; 8131da177e4SLinus Torvalds w = w << target_id; 8141da177e4SLinus Torvalds if ((w & dev->wide_id[c]) != 0) { 8151da177e4SLinus Torvalds j |= 0x01; 8161da177e4SLinus Torvalds } 8176a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x1b, j); 8186a3cebb6SOndrej Zary while ((atp_readb_io(dev, c, 0x1b) & 0x01) != j) { 8196a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 0x1b, j); 8201da177e4SLinus Torvalds #ifdef ED_DBGP 8211da177e4SLinus Torvalds printk("send_s870 while loop 1\n"); 8221da177e4SLinus Torvalds #endif 8231da177e4SLinus Torvalds } 8241da177e4SLinus Torvalds /* 8251da177e4SLinus Torvalds * Write the command 8261da177e4SLinus Torvalds */ 8271da177e4SLinus Torvalds 8286a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x00, workreq->cmd_len); 8296a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x01, 0x2c); 830b922a449SOndrej Zary if (is885(dev)) 8316a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x02, 0x7f); 8326a3cebb6SOndrej Zary else 8336a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x02, 0xcf); 8346a3cebb6SOndrej Zary for (i = 0; i < workreq->cmd_len; i++) 8356a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x03 + i, workreq->cmnd[i]); 8366a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x0f, workreq->device->lun); 8371da177e4SLinus Torvalds /* 8381da177e4SLinus Torvalds * Write the target 8391da177e4SLinus Torvalds */ 8406a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x11, dev->id[c][target_id].devsp); 8411da177e4SLinus Torvalds #ifdef ED_DBGP 842bcd5c59fSHannes Reinecke printk("dev->id[%d][%d].devsp = %2x\n",c,target_id, 843bcd5c59fSHannes Reinecke dev->id[c][target_id].devsp); 8441da177e4SLinus Torvalds #endif 8451da177e4SLinus Torvalds 846fe7ed98fSBoaz Harrosh sg_count = scsi_dma_map(workreq); 8471da177e4SLinus Torvalds /* 8481da177e4SLinus Torvalds * Write transfer size 8491da177e4SLinus Torvalds */ 8506a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x12, ((unsigned char *) (&l))[2]); 8516a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x13, ((unsigned char *) (&l))[1]); 8526a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x14, ((unsigned char *) (&l))[0]); 8531da177e4SLinus Torvalds j = target_id; 8541da177e4SLinus Torvalds dev->id[c][j].last_len = l; 8551da177e4SLinus Torvalds dev->id[c][j].tran_len = 0; 8561da177e4SLinus Torvalds #ifdef ED_DBGP 8571da177e4SLinus Torvalds printk("dev->id[%2d][%2d].last_len = %d\n",c,j,dev->id[c][j].last_len); 8581da177e4SLinus Torvalds #endif 8591da177e4SLinus Torvalds /* 8601da177e4SLinus Torvalds * Flip the wide bits 8611da177e4SLinus Torvalds */ 8621da177e4SLinus Torvalds if ((j & 0x08) != 0) { 8631da177e4SLinus Torvalds j = (j & 0x07) | 0x40; 8641da177e4SLinus Torvalds } 8651da177e4SLinus Torvalds /* 8661da177e4SLinus Torvalds * Check transfer direction 8671da177e4SLinus Torvalds */ 8686a3cebb6SOndrej Zary if (workreq->sc_data_direction == DMA_TO_DEVICE) 8696a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x15, j | 0x20); 8706a3cebb6SOndrej Zary else 8716a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x15, j); 8726a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x16, atp_readb_io(dev, c, 0x16) | 0x80); 8736a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x16, 0x80); 8741da177e4SLinus Torvalds dev->id[c][target_id].dirct = 0; 8751da177e4SLinus Torvalds if (l == 0) { 8766a3cebb6SOndrej Zary if (atp_readb_io(dev, c, 0x1c) == 0) { 8771da177e4SLinus Torvalds #ifdef ED_DBGP 8781da177e4SLinus Torvalds printk("change SCSI_CMD_REG 0x08\n"); 8791da177e4SLinus Torvalds #endif 8806a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 8816a3cebb6SOndrej Zary } else 8821da177e4SLinus Torvalds dev->last_cmd[c] |= 0x40; 8831da177e4SLinus Torvalds dev->in_snd[c] = 0; 8841da177e4SLinus Torvalds return; 8851da177e4SLinus Torvalds } 8861da177e4SLinus Torvalds prd = dev->id[c][target_id].prd_table; 8871da177e4SLinus Torvalds dev->id[c][target_id].prd_pos = prd; 8881da177e4SLinus Torvalds 8891da177e4SLinus Torvalds /* 8901da177e4SLinus Torvalds * Now write the request list. Either as scatter/gather or as 8911da177e4SLinus Torvalds * a linear chain. 8921da177e4SLinus Torvalds */ 8931da177e4SLinus Torvalds 894fe7ed98fSBoaz Harrosh if (l) { 895fe7ed98fSBoaz Harrosh struct scatterlist *sgpnt; 8961da177e4SLinus Torvalds i = 0; 897fe7ed98fSBoaz Harrosh scsi_for_each_sg(workreq, sgpnt, sg_count, j) { 898fe7ed98fSBoaz Harrosh bttl = sg_dma_address(sgpnt); 899fe7ed98fSBoaz Harrosh l=sg_dma_len(sgpnt); 9001da177e4SLinus Torvalds #ifdef ED_DBGP 9011da177e4SLinus Torvalds printk("1. bttl %x, l %x\n",bttl, l); 9021da177e4SLinus Torvalds #endif 9031da177e4SLinus Torvalds while (l > 0x10000) { 9041da177e4SLinus Torvalds (((u16 *) (prd))[i + 3]) = 0x0000; 9051da177e4SLinus Torvalds (((u16 *) (prd))[i + 2]) = 0x0000; 9061da177e4SLinus Torvalds (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl); 9071da177e4SLinus Torvalds l -= 0x10000; 9081da177e4SLinus Torvalds bttl += 0x10000; 9091da177e4SLinus Torvalds i += 0x04; 9101da177e4SLinus Torvalds } 9111da177e4SLinus Torvalds (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl); 9121da177e4SLinus Torvalds (((u16 *) (prd))[i + 2]) = cpu_to_le16(l); 9131da177e4SLinus Torvalds (((u16 *) (prd))[i + 3]) = 0; 9141da177e4SLinus Torvalds i += 0x04; 9151da177e4SLinus Torvalds } 9161da177e4SLinus Torvalds (((u16 *) (prd))[i - 1]) = cpu_to_le16(0x8000); 9171da177e4SLinus Torvalds #ifdef ED_DBGP 918bcd5c59fSHannes Reinecke printk("prd %4x %4x %4x %4x\n", 919bcd5c59fSHannes Reinecke (((unsigned short int *)prd)[0]), 920bcd5c59fSHannes Reinecke (((unsigned short int *)prd)[1]), 921bcd5c59fSHannes Reinecke (((unsigned short int *)prd)[2]), 922bcd5c59fSHannes Reinecke (((unsigned short int *)prd)[3])); 9231da177e4SLinus Torvalds printk("2. bttl %x, l %x\n",bttl, l); 9241da177e4SLinus Torvalds #endif 9251da177e4SLinus Torvalds } 9261da177e4SLinus Torvalds #ifdef ED_DBGP 927bcd5c59fSHannes Reinecke printk("send_s870: prdaddr_2 0x%8x target_id %d\n", 928bcd5c59fSHannes Reinecke dev->id[c][target_id].prdaddr,target_id); 9291da177e4SLinus Torvalds #endif 930b5683557SJames Bottomley dev->id[c][target_id].prdaddr = dev->id[c][target_id].prd_bus; 9316a3cebb6SOndrej Zary atp_writel_pci(dev, c, 4, dev->id[c][target_id].prdaddr); 9326a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 2, 0x06); 9336a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 2, 0x00); 934b922a449SOndrej Zary if (is885(dev)) { 9356a3cebb6SOndrej Zary j = atp_readb_pci(dev, c, 1) & 0xf3; 936f3272258SHannes Reinecke if ((workreq->cmnd[0] == READ_6) || 937f3272258SHannes Reinecke (workreq->cmnd[0] == READ_10) || 938f3272258SHannes Reinecke (workreq->cmnd[0] == WRITE_6) || 939f3272258SHannes Reinecke (workreq->cmnd[0] == WRITE_10)) { 9401da177e4SLinus Torvalds j |= 0x0c; 9411da177e4SLinus Torvalds } 9426a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 1, j); 943b922a449SOndrej Zary } else if (is880(dev)) { 944f3272258SHannes Reinecke if ((workreq->cmnd[0] == READ_6) || 945f3272258SHannes Reinecke (workreq->cmnd[0] == READ_10) || 946f3272258SHannes Reinecke (workreq->cmnd[0] == WRITE_6) || 947f3272258SHannes Reinecke (workreq->cmnd[0] == WRITE_10)) 948bcd5c59fSHannes Reinecke atp_writeb_base(dev, 0x3b, 949bcd5c59fSHannes Reinecke (atp_readb_base(dev, 0x3b) & 0x3f) | 0xc0); 9506a3cebb6SOndrej Zary else 951bcd5c59fSHannes Reinecke atp_writeb_base(dev, 0x3b, 952bcd5c59fSHannes Reinecke atp_readb_base(dev, 0x3b) & 0x3f); 9531da177e4SLinus Torvalds } else { 954f3272258SHannes Reinecke if ((workreq->cmnd[0] == READ_6) || 955f3272258SHannes Reinecke (workreq->cmnd[0] == READ_10) || 956f3272258SHannes Reinecke (workreq->cmnd[0] == WRITE_6) || 957f3272258SHannes Reinecke (workreq->cmnd[0] == WRITE_10)) 958bcd5c59fSHannes Reinecke atp_writeb_base(dev, 0x3a, 959bcd5c59fSHannes Reinecke (atp_readb_base(dev, 0x3a) & 0xf3) | 0x08); 9606a3cebb6SOndrej Zary else 961bcd5c59fSHannes Reinecke atp_writeb_base(dev, 0x3a, 962bcd5c59fSHannes Reinecke atp_readb_base(dev, 0x3a) & 0xf3); 9631da177e4SLinus Torvalds } 9641da177e4SLinus Torvalds 9651da177e4SLinus Torvalds if(workreq->sc_data_direction == DMA_TO_DEVICE) { 9661da177e4SLinus Torvalds dev->id[c][target_id].dirct = 0x20; 9676a3cebb6SOndrej Zary if (atp_readb_io(dev, c, 0x1c) == 0) { 9686a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 9696a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 0, 0x01); 9701da177e4SLinus Torvalds #ifdef ED_DBGP 9711da177e4SLinus Torvalds printk( "start DMA(to target)\n"); 9721da177e4SLinus Torvalds #endif 9731da177e4SLinus Torvalds } else { 9741da177e4SLinus Torvalds dev->last_cmd[c] |= 0x40; 9751da177e4SLinus Torvalds } 9761da177e4SLinus Torvalds dev->in_snd[c] = 0; 9771da177e4SLinus Torvalds return; 9781da177e4SLinus Torvalds } 9796a3cebb6SOndrej Zary if (atp_readb_io(dev, c, 0x1c) == 0) { 9806a3cebb6SOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 9816a3cebb6SOndrej Zary atp_writeb_pci(dev, c, 0, 0x09); 9821da177e4SLinus Torvalds #ifdef ED_DBGP 9831da177e4SLinus Torvalds printk( "start DMA(to host)\n"); 9841da177e4SLinus Torvalds #endif 9851da177e4SLinus Torvalds } else { 9861da177e4SLinus Torvalds dev->last_cmd[c] |= 0x40; 9871da177e4SLinus Torvalds } 9881da177e4SLinus Torvalds dev->in_snd[c] = 0; 9891da177e4SLinus Torvalds return; 9901da177e4SLinus Torvalds 9911da177e4SLinus Torvalds } 9921da177e4SLinus Torvalds 9931da177e4SLinus Torvalds static unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val) 9941da177e4SLinus Torvalds { 9951da177e4SLinus Torvalds unsigned short int i, k; 9961da177e4SLinus Torvalds unsigned char j; 9971da177e4SLinus Torvalds 9986a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, *val); 9991da177e4SLinus Torvalds for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */ 10006a3cebb6SOndrej Zary k = atp_readw_io(dev, 0, 0x1c); 10011da177e4SLinus Torvalds j = (unsigned char) (k >> 8); 1002832e9ac6SOndrej Zary if ((k & 0x8000) != 0) /* DB7 all release? */ 1003832e9ac6SOndrej Zary i = 0; 10041da177e4SLinus Torvalds } 10051da177e4SLinus Torvalds *val |= 0x4000; /* assert DB6 */ 10066a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, *val); 10071da177e4SLinus Torvalds *val &= 0xdfff; /* assert DB5 */ 10086a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, *val); 10091da177e4SLinus Torvalds for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */ 10106a3cebb6SOndrej Zary if ((atp_readw_io(dev, 0, 0x1c) & 0x2000) != 0) /* DB5 all release? */ 1011832e9ac6SOndrej Zary i = 0; 10121da177e4SLinus Torvalds } 10131da177e4SLinus Torvalds *val |= 0x8000; /* no DB4-0, assert DB7 */ 10141da177e4SLinus Torvalds *val &= 0xe0ff; 10156a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, *val); 10161da177e4SLinus Torvalds *val &= 0xbfff; /* release DB6 */ 10176a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, *val); 10181da177e4SLinus Torvalds for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */ 10196a3cebb6SOndrej Zary if ((atp_readw_io(dev, 0, 0x1c) & 0x4000) != 0) /* DB6 all release? */ 1020832e9ac6SOndrej Zary i = 0; 10211da177e4SLinus Torvalds } 10221da177e4SLinus Torvalds 10231da177e4SLinus Torvalds return j; 10241da177e4SLinus Torvalds } 10251da177e4SLinus Torvalds 10268177c507SOndrej Zary static void tscam(struct Scsi_Host *host, bool wide_chip, u8 scam_on) 10271da177e4SLinus Torvalds { 10281da177e4SLinus Torvalds 10291da177e4SLinus Torvalds unsigned char i, j, k; 10301da177e4SLinus Torvalds unsigned long n; 10311da177e4SLinus Torvalds unsigned short int m, assignid_map, val; 10321da177e4SLinus Torvalds unsigned char mbuf[33], quintet[2]; 10331da177e4SLinus Torvalds struct atp_unit *dev = (struct atp_unit *)&host->hostdata; 10341da177e4SLinus Torvalds static unsigned char g2q_tab[8] = { 10351da177e4SLinus Torvalds 0x38, 0x31, 0x32, 0x2b, 0x34, 0x2d, 0x2e, 0x27 10361da177e4SLinus Torvalds }; 10371da177e4SLinus Torvalds 10381da177e4SLinus Torvalds /* I can't believe we need this before we've even done anything. Remove it 10391da177e4SLinus Torvalds * and see if anyone bitches. 10401da177e4SLinus Torvalds for (i = 0; i < 0x10; i++) { 10411da177e4SLinus Torvalds udelay(0xffff); 10421da177e4SLinus Torvalds } 10431da177e4SLinus Torvalds */ 10441da177e4SLinus Torvalds 10456a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 1, 0x08); 10466a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 2, 0x7f); 10476a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x11, 0x20); 10481da177e4SLinus Torvalds 10498177c507SOndrej Zary if ((scam_on & 0x40) == 0) { 10501da177e4SLinus Torvalds return; 10511da177e4SLinus Torvalds } 10521da177e4SLinus Torvalds m = 1; 10531da177e4SLinus Torvalds m <<= dev->host_id[0]; 10541da177e4SLinus Torvalds j = 16; 1055dd5a5f79SOndrej Zary if (!wide_chip) { 10561da177e4SLinus Torvalds m |= 0xff00; 10571da177e4SLinus Torvalds j = 8; 10581da177e4SLinus Torvalds } 10591da177e4SLinus Torvalds assignid_map = m; 10606a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x02, 0x02); /* 2*2=4ms,3EH 2/32*3E=3.9ms */ 10616a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x03, 0); 10626a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x04, 0); 10636a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x05, 0); 10646a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x06, 0); 10656a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x07, 0); 10666a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x08, 0); 10671da177e4SLinus Torvalds 10681da177e4SLinus Torvalds for (i = 0; i < j; i++) { 10691da177e4SLinus Torvalds m = 1; 10701da177e4SLinus Torvalds m = m << i; 10711da177e4SLinus Torvalds if ((m & assignid_map) != 0) { 10721da177e4SLinus Torvalds continue; 10731da177e4SLinus Torvalds } 10746a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x0f, 0); 10756a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x12, 0); 10766a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x13, 0); 10776a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x14, 0); 10781da177e4SLinus Torvalds if (i > 7) { 10791da177e4SLinus Torvalds k = (i & 0x07) | 0x40; 10801da177e4SLinus Torvalds } else { 10811da177e4SLinus Torvalds k = i; 10821da177e4SLinus Torvalds } 10836a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x15, k); 1084dd5a5f79SOndrej Zary if (wide_chip) 10856a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x1b, 0x01); 10866a3cebb6SOndrej Zary else 10876a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x1b, 0x00); 108858c4d046SOndrej Zary do { 10896a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x18, 0x09); 10901da177e4SLinus Torvalds 10916a3cebb6SOndrej Zary while ((atp_readb_io(dev, 0, 0x1f) & 0x80) == 0x00) 10921da177e4SLinus Torvalds cpu_relax(); 10936a3cebb6SOndrej Zary k = atp_readb_io(dev, 0, 0x17); 109458c4d046SOndrej Zary if ((k == 0x85) || (k == 0x42)) 109558c4d046SOndrej Zary break; 109658c4d046SOndrej Zary if (k != 0x16) 10976a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x10, 0x41); 109858c4d046SOndrej Zary } while (k != 0x16); 109958c4d046SOndrej Zary if ((k == 0x85) || (k == 0x42)) 110058c4d046SOndrej Zary continue; 11011da177e4SLinus Torvalds assignid_map |= m; 11021da177e4SLinus Torvalds 11031da177e4SLinus Torvalds } 11046a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x02, 0x7f); 11056a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x1b, 0x02); 11061da177e4SLinus Torvalds 11072bbbac45SOndrej Zary udelay(2); 11081da177e4SLinus Torvalds 11091da177e4SLinus Torvalds val = 0x0080; /* bsy */ 11106a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, val); 11111da177e4SLinus Torvalds val |= 0x0040; /* sel */ 11126a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, val); 11131da177e4SLinus Torvalds val |= 0x0004; /* msg */ 11146a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, val); 11152bbbac45SOndrej Zary udelay(2); /* 2 deskew delay(45ns*2=90ns) */ 11161da177e4SLinus Torvalds val &= 0x007f; /* no bsy */ 11176a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, val); 1118dcaa0c12SJia-Ju Bai msleep(128); 11191da177e4SLinus Torvalds val &= 0x00fb; /* after 1ms no msg */ 11206a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, val); 11216a3cebb6SOndrej Zary while ((atp_readb_io(dev, 0, 0x1c) & 0x04) != 0) 112258c4d046SOndrej Zary ; 11232bbbac45SOndrej Zary udelay(2); 11241da177e4SLinus Torvalds udelay(100); 1125c7fcc089SOndrej Zary for (n = 0; n < 0x30000; n++) 11266a3cebb6SOndrej Zary if ((atp_readb_io(dev, 0, 0x1c) & 0x80) != 0) /* bsy ? */ 1127c7fcc089SOndrej Zary break; 1128c7fcc089SOndrej Zary if (n < 0x30000) 1129c7fcc089SOndrej Zary for (n = 0; n < 0x30000; n++) 11306a3cebb6SOndrej Zary if ((atp_readb_io(dev, 0, 0x1c) & 0x81) == 0x0081) { 11312bbbac45SOndrej Zary udelay(2); 11321da177e4SLinus Torvalds val |= 0x8003; /* io,cd,db7 */ 11336a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, val); 11342bbbac45SOndrej Zary udelay(2); 11351da177e4SLinus Torvalds val &= 0x00bf; /* no sel */ 11366a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, val); 11372bbbac45SOndrej Zary udelay(2); 1138c7fcc089SOndrej Zary break; 1139c7fcc089SOndrej Zary } 1140c7fcc089SOndrej Zary while (1) { 11410f6d93aaSMartin Michlmayr /* 11420f6d93aaSMartin Michlmayr * The funny division into multiple delays is to accomodate 11430f6d93aaSMartin Michlmayr * arches like ARM where udelay() multiplies its argument by 11440f6d93aaSMartin Michlmayr * a large number to initialize a loop counter. To avoid 11450f6d93aaSMartin Michlmayr * overflow, the maximum supported udelay is 2000 microseconds. 11460f6d93aaSMartin Michlmayr * 11470f6d93aaSMartin Michlmayr * XXX it would be more polite to find a way to use msleep() 11480f6d93aaSMartin Michlmayr */ 11490f6d93aaSMartin Michlmayr mdelay(2); 11500f6d93aaSMartin Michlmayr udelay(48); 11516a3cebb6SOndrej Zary if ((atp_readb_io(dev, 0, 0x1c) & 0x80) == 0x00) { /* bsy ? */ 11526a3cebb6SOndrej Zary atp_writew_io(dev, 0, 0x1c, 0); 11536a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x1b, 0); 11546a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x15, 0); 11556a3cebb6SOndrej Zary atp_writeb_io(dev, 0, 0x18, 0x09); 11566a3cebb6SOndrej Zary while ((atp_readb_io(dev, 0, 0x1f) & 0x80) == 0) 11571da177e4SLinus Torvalds cpu_relax(); 11586a3cebb6SOndrej Zary atp_readb_io(dev, 0, 0x17); 11591da177e4SLinus Torvalds return; 11601da177e4SLinus Torvalds } 11611da177e4SLinus Torvalds val &= 0x00ff; /* synchronization */ 11621da177e4SLinus Torvalds val |= 0x3f00; 11631da177e4SLinus Torvalds fun_scam(dev, &val); 11642bbbac45SOndrej Zary udelay(2); 11651da177e4SLinus Torvalds val &= 0x00ff; /* isolation */ 11661da177e4SLinus Torvalds val |= 0x2000; 11671da177e4SLinus Torvalds fun_scam(dev, &val); 11682bbbac45SOndrej Zary udelay(2); 11691da177e4SLinus Torvalds i = 8; 11701da177e4SLinus Torvalds j = 0; 1171c7fcc089SOndrej Zary 1172c7fcc089SOndrej Zary while (1) { 11736a3cebb6SOndrej Zary if ((atp_readw_io(dev, 0, 0x1c) & 0x2000) == 0) 1174c7fcc089SOndrej Zary continue; 11752bbbac45SOndrej Zary udelay(2); 11761da177e4SLinus Torvalds val &= 0x00ff; /* get ID_STRING */ 11771da177e4SLinus Torvalds val |= 0x2000; 11781da177e4SLinus Torvalds k = fun_scam(dev, &val); 1179c7fcc089SOndrej Zary if ((k & 0x03) == 0) 1180c7fcc089SOndrej Zary break; 11811da177e4SLinus Torvalds mbuf[j] <<= 0x01; 11821da177e4SLinus Torvalds mbuf[j] &= 0xfe; 1183c7fcc089SOndrej Zary if ((k & 0x02) != 0) 11841da177e4SLinus Torvalds mbuf[j] |= 0x01; 11851da177e4SLinus Torvalds i--; 1186c7fcc089SOndrej Zary if (i > 0) 1187c7fcc089SOndrej Zary continue; 11881da177e4SLinus Torvalds j++; 11891da177e4SLinus Torvalds i = 8; 1190c7fcc089SOndrej Zary } 11911da177e4SLinus Torvalds 1192c7fcc089SOndrej Zary /* isolation complete.. */ 11931da177e4SLinus Torvalds /* mbuf[32]=0; 11941da177e4SLinus Torvalds printk(" \n%x %x %x %s\n ",assignid_map,mbuf[0],mbuf[1],&mbuf[2]); */ 11951da177e4SLinus Torvalds i = 15; 11961da177e4SLinus Torvalds j = mbuf[0]; 11971da177e4SLinus Torvalds if ((j & 0x20) != 0) { /* bit5=1:ID up to 7 */ 11981da177e4SLinus Torvalds i = 7; 11991da177e4SLinus Torvalds } 1200c7fcc089SOndrej Zary if ((j & 0x06) != 0) { /* IDvalid? */ 12011da177e4SLinus Torvalds k = mbuf[1]; 1202c7fcc089SOndrej Zary while (1) { 12031da177e4SLinus Torvalds m = 1; 12041da177e4SLinus Torvalds m <<= k; 1205c7fcc089SOndrej Zary if ((m & assignid_map) == 0) 1206c7fcc089SOndrej Zary break; 1207c7fcc089SOndrej Zary if (k > 0) 12081da177e4SLinus Torvalds k--; 1209c7fcc089SOndrej Zary else 1210c7fcc089SOndrej Zary break; 12111da177e4SLinus Torvalds } 1212c7fcc089SOndrej Zary } 1213c7fcc089SOndrej Zary if ((m & assignid_map) != 0) { /* srch from max acceptable ID# */ 12141da177e4SLinus Torvalds k = i; /* max acceptable ID# */ 1215c7fcc089SOndrej Zary while (1) { 12161da177e4SLinus Torvalds m = 1; 12171da177e4SLinus Torvalds m <<= k; 1218c7fcc089SOndrej Zary if ((m & assignid_map) == 0) 1219c7fcc089SOndrej Zary break; 1220c7fcc089SOndrej Zary if (k > 0) 12211da177e4SLinus Torvalds k--; 1222c7fcc089SOndrej Zary else 1223c7fcc089SOndrej Zary break; 12241da177e4SLinus Torvalds } 1225c7fcc089SOndrej Zary } 1226c7fcc089SOndrej Zary /* k=binID#, */ 12271da177e4SLinus Torvalds assignid_map |= m; 12281da177e4SLinus Torvalds if (k < 8) { 12291da177e4SLinus Torvalds quintet[0] = 0x38; /* 1st dft ID<8 */ 12301da177e4SLinus Torvalds } else { 12311da177e4SLinus Torvalds quintet[0] = 0x31; /* 1st ID>=8 */ 12321da177e4SLinus Torvalds } 12331da177e4SLinus Torvalds k &= 0x07; 12341da177e4SLinus Torvalds quintet[1] = g2q_tab[k]; 12351da177e4SLinus Torvalds 12361da177e4SLinus Torvalds val &= 0x00ff; /* AssignID 1stQuintet,AH=001xxxxx */ 12371da177e4SLinus Torvalds m = quintet[0] << 8; 12381da177e4SLinus Torvalds val |= m; 12391da177e4SLinus Torvalds fun_scam(dev, &val); 12401da177e4SLinus Torvalds val &= 0x00ff; /* AssignID 2ndQuintet,AH=001xxxxx */ 12411da177e4SLinus Torvalds m = quintet[1] << 8; 12421da177e4SLinus Torvalds val |= m; 12431da177e4SLinus Torvalds fun_scam(dev, &val); 12441da177e4SLinus Torvalds 1245c7fcc089SOndrej Zary } 12461da177e4SLinus Torvalds } 12471da177e4SLinus Torvalds 12481da177e4SLinus Torvalds static void atp870u_free_tables(struct Scsi_Host *host) 12491da177e4SLinus Torvalds { 12501da177e4SLinus Torvalds struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata; 12511da177e4SLinus Torvalds int j, k; 12521da177e4SLinus Torvalds for (j=0; j < 2; j++) { 12531da177e4SLinus Torvalds for (k = 0; k < 16; k++) { 12541da177e4SLinus Torvalds if (!atp_dev->id[j][k].prd_table) 12551da177e4SLinus Torvalds continue; 1256bcd5c59fSHannes Reinecke dma_free_coherent(&atp_dev->pdev->dev, 1024, 1257bcd5c59fSHannes Reinecke atp_dev->id[j][k].prd_table, 1258bcd5c59fSHannes Reinecke atp_dev->id[j][k].prd_bus); 12591da177e4SLinus Torvalds atp_dev->id[j][k].prd_table = NULL; 12601da177e4SLinus Torvalds } 12611da177e4SLinus Torvalds } 12621da177e4SLinus Torvalds } 12631da177e4SLinus Torvalds 12641da177e4SLinus Torvalds static int atp870u_init_tables(struct Scsi_Host *host) 12651da177e4SLinus Torvalds { 12661da177e4SLinus Torvalds struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata; 12671da177e4SLinus Torvalds int c,k; 12681da177e4SLinus Torvalds for(c=0;c < 2;c++) { 12691da177e4SLinus Torvalds for(k=0;k<16;k++) { 1270bcd5c59fSHannes Reinecke atp_dev->id[c][k].prd_table = 1271bcd5c59fSHannes Reinecke dma_alloc_coherent(&atp_dev->pdev->dev, 1024, 1272bcd5c59fSHannes Reinecke &(atp_dev->id[c][k].prd_bus), 1273bcd5c59fSHannes Reinecke GFP_KERNEL); 12741da177e4SLinus Torvalds if (!atp_dev->id[c][k].prd_table) { 12751da177e4SLinus Torvalds printk("atp870u_init_tables fail\n"); 12761da177e4SLinus Torvalds atp870u_free_tables(host); 12771da177e4SLinus Torvalds return -ENOMEM; 12781da177e4SLinus Torvalds } 1279b5683557SJames Bottomley atp_dev->id[c][k].prdaddr = atp_dev->id[c][k].prd_bus; 12801da177e4SLinus Torvalds atp_dev->id[c][k].devsp=0x20; 12811da177e4SLinus Torvalds atp_dev->id[c][k].devtype = 0x7f; 12821da177e4SLinus Torvalds atp_dev->id[c][k].curr_req = NULL; 12831da177e4SLinus Torvalds } 12841da177e4SLinus Torvalds 12851da177e4SLinus Torvalds atp_dev->active_id[c] = 0; 12861da177e4SLinus Torvalds atp_dev->wide_id[c] = 0; 12871da177e4SLinus Torvalds atp_dev->host_id[c] = 0x07; 12881da177e4SLinus Torvalds atp_dev->quhd[c] = 0; 12891da177e4SLinus Torvalds atp_dev->quend[c] = 0; 12901da177e4SLinus Torvalds atp_dev->last_cmd[c] = 0xff; 12911da177e4SLinus Torvalds atp_dev->in_snd[c] = 0; 12921da177e4SLinus Torvalds atp_dev->in_int[c] = 0; 12931da177e4SLinus Torvalds 12941da177e4SLinus Torvalds for (k = 0; k < qcnt; k++) { 12951da177e4SLinus Torvalds atp_dev->quereq[c][k] = NULL; 12961da177e4SLinus Torvalds } 12971da177e4SLinus Torvalds for (k = 0; k < 16; k++) { 12981da177e4SLinus Torvalds atp_dev->id[c][k].curr_req = NULL; 12991da177e4SLinus Torvalds atp_dev->sp[c][k] = 0x04; 13001da177e4SLinus Torvalds } 13011da177e4SLinus Torvalds } 13021da177e4SLinus Torvalds return 0; 13031da177e4SLinus Torvalds } 13041da177e4SLinus Torvalds 13056a1961bcSOndrej Zary static void atp_set_host_id(struct atp_unit *atp, u8 c, u8 host_id) 13066a1961bcSOndrej Zary { 13076a1961bcSOndrej Zary atp_writeb_io(atp, c, 0, host_id | 0x08); 13086a1961bcSOndrej Zary atp_writeb_io(atp, c, 0x18, 0); 13096a1961bcSOndrej Zary while ((atp_readb_io(atp, c, 0x1f) & 0x80) == 0) 13106a1961bcSOndrej Zary mdelay(1); 13116a1961bcSOndrej Zary atp_readb_io(atp, c, 0x17); 13126a1961bcSOndrej Zary atp_writeb_io(atp, c, 1, 8); 13136a1961bcSOndrej Zary atp_writeb_io(atp, c, 2, 0x7f); 13146a1961bcSOndrej Zary atp_writeb_io(atp, c, 0x11, 0x20); 13156a1961bcSOndrej Zary } 13166a1961bcSOndrej Zary 13174190230eSOndrej Zary static void atp870_init(struct Scsi_Host *shpnt) 13184190230eSOndrej Zary { 13194190230eSOndrej Zary struct atp_unit *atpdev = shost_priv(shpnt); 13204190230eSOndrej Zary struct pci_dev *pdev = atpdev->pdev; 13214190230eSOndrej Zary unsigned char k, host_id; 13224190230eSOndrej Zary u8 scam_on; 13234190230eSOndrej Zary bool wide_chip = 13244190230eSOndrej Zary (pdev->device == PCI_DEVICE_ID_ARTOP_AEC7610 && 13254190230eSOndrej Zary pdev->revision == 4) || 13264190230eSOndrej Zary (pdev->device == PCI_DEVICE_ID_ARTOP_AEC7612UW) || 13274190230eSOndrej Zary (pdev->device == PCI_DEVICE_ID_ARTOP_AEC7612SUW); 13284190230eSOndrej Zary 13294190230eSOndrej Zary pci_read_config_byte(pdev, 0x49, &host_id); 13304190230eSOndrej Zary 1331bcd5c59fSHannes Reinecke dev_info(&pdev->dev, "ACARD AEC-671X PCI Ultra/W SCSI-2/3 " 1332bcd5c59fSHannes Reinecke "Host Adapter: IO:%lx, IRQ:%d.\n", 13334190230eSOndrej Zary shpnt->io_port, shpnt->irq); 13344190230eSOndrej Zary 13354190230eSOndrej Zary atpdev->ioport[0] = shpnt->io_port; 13364190230eSOndrej Zary atpdev->pciport[0] = shpnt->io_port + 0x20; 13374190230eSOndrej Zary host_id &= 0x07; 13384190230eSOndrej Zary atpdev->host_id[0] = host_id; 13394190230eSOndrej Zary scam_on = atp_readb_pci(atpdev, 0, 2); 13404190230eSOndrej Zary atpdev->global_map[0] = atp_readb_base(atpdev, 0x2d); 13414190230eSOndrej Zary atpdev->ultra_map[0] = atp_readw_base(atpdev, 0x2e); 13424190230eSOndrej Zary 13434190230eSOndrej Zary if (atpdev->ultra_map[0] == 0) { 13444190230eSOndrej Zary scam_on = 0x00; 13454190230eSOndrej Zary atpdev->global_map[0] = 0x20; 13464190230eSOndrej Zary atpdev->ultra_map[0] = 0xffff; 13474190230eSOndrej Zary } 13484190230eSOndrej Zary 13494190230eSOndrej Zary if (pdev->revision > 0x07) /* check if atp876 chip */ 13504190230eSOndrej Zary atp_writeb_base(atpdev, 0x3e, 0x00); /* enable terminator */ 13514190230eSOndrej Zary 13524190230eSOndrej Zary k = (atp_readb_base(atpdev, 0x3a) & 0xf3) | 0x10; 13534190230eSOndrej Zary atp_writeb_base(atpdev, 0x3a, k); 13544190230eSOndrej Zary atp_writeb_base(atpdev, 0x3a, k & 0xdf); 1355dcaa0c12SJia-Ju Bai msleep(32); 13564190230eSOndrej Zary atp_writeb_base(atpdev, 0x3a, k); 1357dcaa0c12SJia-Ju Bai msleep(32); 13584190230eSOndrej Zary atp_set_host_id(atpdev, 0, host_id); 13594190230eSOndrej Zary 13604190230eSOndrej Zary tscam(shpnt, wide_chip, scam_on); 13614190230eSOndrej Zary atp_writeb_base(atpdev, 0x3a, atp_readb_base(atpdev, 0x3a) | 0x10); 13624190230eSOndrej Zary atp_is(atpdev, 0, wide_chip, 0); 13634190230eSOndrej Zary atp_writeb_base(atpdev, 0x3a, atp_readb_base(atpdev, 0x3a) & 0xef); 13644190230eSOndrej Zary atp_writeb_base(atpdev, 0x3b, atp_readb_base(atpdev, 0x3b) | 0x20); 13654190230eSOndrej Zary shpnt->max_id = wide_chip ? 16 : 8; 13664190230eSOndrej Zary shpnt->this_id = host_id; 13674190230eSOndrej Zary } 13684190230eSOndrej Zary 1369c7e6a029SOndrej Zary static void atp880_init(struct Scsi_Host *shpnt) 1370c7e6a029SOndrej Zary { 1371c7e6a029SOndrej Zary struct atp_unit *atpdev = shost_priv(shpnt); 1372c7e6a029SOndrej Zary struct pci_dev *pdev = atpdev->pdev; 1373c7e6a029SOndrej Zary unsigned char k, m, host_id; 1374c7e6a029SOndrej Zary unsigned int n; 1375c7e6a029SOndrej Zary 1376c7e6a029SOndrej Zary pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80); 1377c7e6a029SOndrej Zary 1378c7e6a029SOndrej Zary atpdev->ioport[0] = shpnt->io_port + 0x40; 1379c7e6a029SOndrej Zary atpdev->pciport[0] = shpnt->io_port + 0x28; 1380c7e6a029SOndrej Zary 1381c7e6a029SOndrej Zary host_id = atp_readb_base(atpdev, 0x39) >> 4; 1382c7e6a029SOndrej Zary 1383bcd5c59fSHannes Reinecke dev_info(&pdev->dev, "ACARD AEC-67160 PCI Ultra3 LVD " 1384bcd5c59fSHannes Reinecke "Host Adapter: IO:%lx, IRQ:%d.\n", 1385c7e6a029SOndrej Zary shpnt->io_port, shpnt->irq); 1386c7e6a029SOndrej Zary atpdev->host_id[0] = host_id; 1387c7e6a029SOndrej Zary 1388c7e6a029SOndrej Zary atpdev->global_map[0] = atp_readb_base(atpdev, 0x35); 1389c7e6a029SOndrej Zary atpdev->ultra_map[0] = atp_readw_base(atpdev, 0x3c); 1390c7e6a029SOndrej Zary 1391c7e6a029SOndrej Zary n = 0x3f09; 1392c7e6a029SOndrej Zary while (n < 0x4000) { 1393c7e6a029SOndrej Zary m = 0; 1394c7e6a029SOndrej Zary atp_writew_base(atpdev, 0x34, n); 1395c7e6a029SOndrej Zary n += 0x0002; 1396c7e6a029SOndrej Zary if (atp_readb_base(atpdev, 0x30) == 0xff) 1397c7e6a029SOndrej Zary break; 1398c7e6a029SOndrej Zary 1399c7e6a029SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30); 1400c7e6a029SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31); 1401c7e6a029SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32); 1402c7e6a029SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33); 1403c7e6a029SOndrej Zary atp_writew_base(atpdev, 0x34, n); 1404c7e6a029SOndrej Zary n += 0x0002; 1405c7e6a029SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30); 1406c7e6a029SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31); 1407c7e6a029SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32); 1408c7e6a029SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33); 1409c7e6a029SOndrej Zary atp_writew_base(atpdev, 0x34, n); 1410c7e6a029SOndrej Zary n += 0x0002; 1411c7e6a029SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30); 1412c7e6a029SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31); 1413c7e6a029SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32); 1414c7e6a029SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33); 1415c7e6a029SOndrej Zary atp_writew_base(atpdev, 0x34, n); 1416c7e6a029SOndrej Zary n += 0x0002; 1417c7e6a029SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30); 1418c7e6a029SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31); 1419c7e6a029SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32); 1420c7e6a029SOndrej Zary atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33); 1421c7e6a029SOndrej Zary n += 0x0018; 1422c7e6a029SOndrej Zary } 1423c7e6a029SOndrej Zary atp_writew_base(atpdev, 0x34, 0); 1424c7e6a029SOndrej Zary atpdev->ultra_map[0] = 0; 1425c7e6a029SOndrej Zary atpdev->async[0] = 0; 1426c7e6a029SOndrej Zary for (k = 0; k < 16; k++) { 1427c7e6a029SOndrej Zary n = 1 << k; 1428c7e6a029SOndrej Zary if (atpdev->sp[0][k] > 1) 1429c7e6a029SOndrej Zary atpdev->ultra_map[0] |= n; 1430c7e6a029SOndrej Zary else 1431c7e6a029SOndrej Zary if (atpdev->sp[0][k] == 0) 1432c7e6a029SOndrej Zary atpdev->async[0] |= n; 1433c7e6a029SOndrej Zary } 1434c7e6a029SOndrej Zary atpdev->async[0] = ~(atpdev->async[0]); 1435c7e6a029SOndrej Zary atp_writeb_base(atpdev, 0x35, atpdev->global_map[0]); 1436c7e6a029SOndrej Zary 1437c7e6a029SOndrej Zary k = atp_readb_base(atpdev, 0x38) & 0x80; 1438c7e6a029SOndrej Zary atp_writeb_base(atpdev, 0x38, k); 1439c7e6a029SOndrej Zary atp_writeb_base(atpdev, 0x3b, 0x20); 1440dcaa0c12SJia-Ju Bai msleep(32); 1441c7e6a029SOndrej Zary atp_writeb_base(atpdev, 0x3b, 0); 1442dcaa0c12SJia-Ju Bai msleep(32); 1443c7e6a029SOndrej Zary atp_readb_io(atpdev, 0, 0x1b); 1444c7e6a029SOndrej Zary atp_readb_io(atpdev, 0, 0x17); 1445c7e6a029SOndrej Zary 1446c7e6a029SOndrej Zary atp_set_host_id(atpdev, 0, host_id); 1447c7e6a029SOndrej Zary 1448c7e6a029SOndrej Zary tscam(shpnt, true, atp_readb_base(atpdev, 0x22)); 1449c7e6a029SOndrej Zary atp_is(atpdev, 0, true, atp_readb_base(atpdev, 0x3f) & 0x40); 1450c7e6a029SOndrej Zary atp_writeb_base(atpdev, 0x38, 0xb0); 1451c7e6a029SOndrej Zary shpnt->max_id = 16; 1452c7e6a029SOndrej Zary shpnt->this_id = host_id; 1453c7e6a029SOndrej Zary } 1454c7e6a029SOndrej Zary 1455ecc6ff95SOndrej Zary static void atp885_init(struct Scsi_Host *shpnt) 1456ecc6ff95SOndrej Zary { 1457ecc6ff95SOndrej Zary struct atp_unit *atpdev = shost_priv(shpnt); 1458ecc6ff95SOndrej Zary struct pci_dev *pdev = atpdev->pdev; 1459ecc6ff95SOndrej Zary unsigned char k, m, c; 1460ecc6ff95SOndrej Zary unsigned int n; 1461ecc6ff95SOndrej Zary unsigned char setupdata[2][16]; 1462ecc6ff95SOndrej Zary 1463bcd5c59fSHannes Reinecke dev_info(&pdev->dev, "ACARD AEC-67162 PCI Ultra3 LVD " 1464bcd5c59fSHannes Reinecke "Host Adapter: IO:%lx, IRQ:%d.\n", 1465ecc6ff95SOndrej Zary shpnt->io_port, shpnt->irq); 1466ecc6ff95SOndrej Zary 1467ecc6ff95SOndrej Zary atpdev->ioport[0] = shpnt->io_port + 0x80; 1468ecc6ff95SOndrej Zary atpdev->ioport[1] = shpnt->io_port + 0xc0; 1469ecc6ff95SOndrej Zary atpdev->pciport[0] = shpnt->io_port + 0x40; 1470ecc6ff95SOndrej Zary atpdev->pciport[1] = shpnt->io_port + 0x50; 1471ecc6ff95SOndrej Zary 1472ecc6ff95SOndrej Zary c = atp_readb_base(atpdev, 0x29); 1473ecc6ff95SOndrej Zary atp_writeb_base(atpdev, 0x29, c | 0x04); 1474ecc6ff95SOndrej Zary 1475ecc6ff95SOndrej Zary n = 0x1f80; 1476ecc6ff95SOndrej Zary while (n < 0x2000) { 1477ecc6ff95SOndrej Zary atp_writew_base(atpdev, 0x3c, n); 1478ecc6ff95SOndrej Zary if (atp_readl_base(atpdev, 0x38) == 0xffffffff) 1479ecc6ff95SOndrej Zary break; 1480ecc6ff95SOndrej Zary for (m = 0; m < 2; m++) { 1481ecc6ff95SOndrej Zary atpdev->global_map[m] = 0; 1482ecc6ff95SOndrej Zary for (k = 0; k < 4; k++) { 1483ecc6ff95SOndrej Zary atp_writew_base(atpdev, 0x3c, n++); 1484bcd5c59fSHannes Reinecke ((u32 *)&setupdata[m][0])[k] = 1485bcd5c59fSHannes Reinecke atp_readl_base(atpdev, 0x38); 1486ecc6ff95SOndrej Zary } 1487ecc6ff95SOndrej Zary for (k = 0; k < 4; k++) { 1488ecc6ff95SOndrej Zary atp_writew_base(atpdev, 0x3c, n++); 1489bcd5c59fSHannes Reinecke ((u32 *)&atpdev->sp[m][0])[k] = 1490bcd5c59fSHannes Reinecke atp_readl_base(atpdev, 0x38); 1491ecc6ff95SOndrej Zary } 1492ecc6ff95SOndrej Zary n += 8; 1493ecc6ff95SOndrej Zary } 1494ecc6ff95SOndrej Zary } 1495ecc6ff95SOndrej Zary c = atp_readb_base(atpdev, 0x29); 1496ecc6ff95SOndrej Zary atp_writeb_base(atpdev, 0x29, c & 0xfb); 1497ecc6ff95SOndrej Zary for (c = 0; c < 2; c++) { 1498ecc6ff95SOndrej Zary atpdev->ultra_map[c] = 0; 1499ecc6ff95SOndrej Zary atpdev->async[c] = 0; 1500ecc6ff95SOndrej Zary for (k = 0; k < 16; k++) { 1501ecc6ff95SOndrej Zary n = 1 << k; 1502ecc6ff95SOndrej Zary if (atpdev->sp[c][k] > 1) 1503ecc6ff95SOndrej Zary atpdev->ultra_map[c] |= n; 1504ecc6ff95SOndrej Zary else 1505ecc6ff95SOndrej Zary if (atpdev->sp[c][k] == 0) 1506ecc6ff95SOndrej Zary atpdev->async[c] |= n; 1507ecc6ff95SOndrej Zary } 1508ecc6ff95SOndrej Zary atpdev->async[c] = ~(atpdev->async[c]); 1509ecc6ff95SOndrej Zary 1510ecc6ff95SOndrej Zary if (atpdev->global_map[c] == 0) { 1511ecc6ff95SOndrej Zary k = setupdata[c][1]; 1512ecc6ff95SOndrej Zary if ((k & 0x40) != 0) 1513ecc6ff95SOndrej Zary atpdev->global_map[c] |= 0x20; 1514ecc6ff95SOndrej Zary k &= 0x07; 1515ecc6ff95SOndrej Zary atpdev->global_map[c] |= k; 1516ecc6ff95SOndrej Zary if ((setupdata[c][2] & 0x04) != 0) 1517ecc6ff95SOndrej Zary atpdev->global_map[c] |= 0x08; 1518ecc6ff95SOndrej Zary atpdev->host_id[c] = setupdata[c][0] & 0x07; 1519ecc6ff95SOndrej Zary } 1520ecc6ff95SOndrej Zary } 1521ecc6ff95SOndrej Zary 1522ecc6ff95SOndrej Zary k = atp_readb_base(atpdev, 0x28) & 0x8f; 1523ecc6ff95SOndrej Zary k |= 0x10; 1524ecc6ff95SOndrej Zary atp_writeb_base(atpdev, 0x28, k); 1525ecc6ff95SOndrej Zary atp_writeb_pci(atpdev, 0, 1, 0x80); 1526ecc6ff95SOndrej Zary atp_writeb_pci(atpdev, 1, 1, 0x80); 1527dcaa0c12SJia-Ju Bai msleep(100); 1528ecc6ff95SOndrej Zary atp_writeb_pci(atpdev, 0, 1, 0); 1529ecc6ff95SOndrej Zary atp_writeb_pci(atpdev, 1, 1, 0); 1530dcaa0c12SJia-Ju Bai msleep(1000); 1531ecc6ff95SOndrej Zary atp_readb_io(atpdev, 0, 0x1b); 1532ecc6ff95SOndrej Zary atp_readb_io(atpdev, 0, 0x17); 1533ecc6ff95SOndrej Zary atp_readb_io(atpdev, 1, 0x1b); 1534ecc6ff95SOndrej Zary atp_readb_io(atpdev, 1, 0x17); 1535ecc6ff95SOndrej Zary 1536ecc6ff95SOndrej Zary k = atpdev->host_id[0]; 1537ecc6ff95SOndrej Zary if (k > 7) 1538ecc6ff95SOndrej Zary k = (k & 0x07) | 0x40; 1539ecc6ff95SOndrej Zary atp_set_host_id(atpdev, 0, k); 1540ecc6ff95SOndrej Zary 1541ecc6ff95SOndrej Zary k = atpdev->host_id[1]; 1542ecc6ff95SOndrej Zary if (k > 7) 1543ecc6ff95SOndrej Zary k = (k & 0x07) | 0x40; 1544ecc6ff95SOndrej Zary atp_set_host_id(atpdev, 1, k); 1545ecc6ff95SOndrej Zary 1546dcaa0c12SJia-Ju Bai msleep(600); /* this delay used to be called tscam_885() */ 1547ecc6ff95SOndrej Zary dev_info(&pdev->dev, "Scanning Channel A SCSI Device ...\n"); 1548ecc6ff95SOndrej Zary atp_is(atpdev, 0, true, atp_readb_io(atpdev, 0, 0x1b) >> 7); 1549ecc6ff95SOndrej Zary atp_writeb_io(atpdev, 0, 0x16, 0x80); 1550ecc6ff95SOndrej Zary dev_info(&pdev->dev, "Scanning Channel B SCSI Device ...\n"); 1551ecc6ff95SOndrej Zary atp_is(atpdev, 1, true, atp_readb_io(atpdev, 1, 0x1b) >> 7); 1552ecc6ff95SOndrej Zary atp_writeb_io(atpdev, 1, 0x16, 0x80); 1553ecc6ff95SOndrej Zary k = atp_readb_base(atpdev, 0x28) & 0xcf; 1554ecc6ff95SOndrej Zary k |= 0xc0; 1555ecc6ff95SOndrej Zary atp_writeb_base(atpdev, 0x28, k); 1556ecc6ff95SOndrej Zary k = atp_readb_base(atpdev, 0x1f) | 0x80; 1557ecc6ff95SOndrej Zary atp_writeb_base(atpdev, 0x1f, k); 1558ecc6ff95SOndrej Zary k = atp_readb_base(atpdev, 0x29) | 0x01; 1559ecc6ff95SOndrej Zary atp_writeb_base(atpdev, 0x29, k); 1560ecc6ff95SOndrej Zary shpnt->max_id = 16; 1561ecc6ff95SOndrej Zary shpnt->max_lun = (atpdev->global_map[0] & 0x07) + 1; 1562ecc6ff95SOndrej Zary shpnt->max_channel = 1; 1563ecc6ff95SOndrej Zary shpnt->this_id = atpdev->host_id[0]; 1564ecc6ff95SOndrej Zary } 1565ecc6ff95SOndrej Zary 15661da177e4SLinus Torvalds /* return non-zero on detection */ 15671da177e4SLinus Torvalds static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 15681da177e4SLinus Torvalds { 15691da177e4SLinus Torvalds struct Scsi_Host *shpnt = NULL; 1570bdd5ac40SOndrej Zary struct atp_unit *atpdev; 1571bdd5ac40SOndrej Zary int err; 15721da177e4SLinus Torvalds 1573b1e85063SOndrej Zary if (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610 && pdev->revision < 2) { 1574b1e85063SOndrej Zary dev_err(&pdev->dev, "ATP850S chips (AEC6710L/F cards) are not supported.\n"); 1575b1e85063SOndrej Zary return -ENODEV; 1576b1e85063SOndrej Zary } 1577b1e85063SOndrej Zary 1578bdd5ac40SOndrej Zary err = pci_enable_device(pdev); 1579bdd5ac40SOndrej Zary if (err) 1580bdd5ac40SOndrej Zary goto fail; 15811da177e4SLinus Torvalds 158248ecddb4SChristoph Hellwig if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) { 15831da177e4SLinus Torvalds printk(KERN_ERR "atp870u: DMA mask required but not available.\n"); 1584bdd5ac40SOndrej Zary err = -EIO; 1585bdd5ac40SOndrej Zary goto disable_device; 15861da177e4SLinus Torvalds } 15871da177e4SLinus Torvalds 158811ec1318SOndrej Zary err = pci_request_regions(pdev, "atp870u"); 158911ec1318SOndrej Zary if (err) 159011ec1318SOndrej Zary goto disable_device; 159111ec1318SOndrej Zary pci_set_master(pdev); 159211ec1318SOndrej Zary 1593bdd5ac40SOndrej Zary err = -ENOMEM; 1594bdd5ac40SOndrej Zary shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit)); 1595bdd5ac40SOndrej Zary if (!shpnt) 159611ec1318SOndrej Zary goto release_region; 1597bdd5ac40SOndrej Zary 1598bdd5ac40SOndrej Zary atpdev = shost_priv(shpnt); 1599bdd5ac40SOndrej Zary 1600bdd5ac40SOndrej Zary atpdev->host = shpnt; 1601bdd5ac40SOndrej Zary atpdev->pdev = pdev; 1602bdd5ac40SOndrej Zary pci_set_drvdata(pdev, atpdev); 1603bdd5ac40SOndrej Zary 16046c9b9c55SOndrej Zary shpnt->io_port = pci_resource_start(pdev, 0); 16056c9b9c55SOndrej Zary shpnt->io_port &= 0xfffffff8; 16066c9b9c55SOndrej Zary shpnt->n_io_port = pci_resource_len(pdev, 0); 16076c9b9c55SOndrej Zary atpdev->baseport = shpnt->io_port; 16086c9b9c55SOndrej Zary shpnt->unique_id = shpnt->io_port; 16096c9b9c55SOndrej Zary shpnt->irq = pdev->irq; 16101da177e4SLinus Torvalds 1611f5f53a38SOndrej Zary err = atp870u_init_tables(shpnt); 1612f5f53a38SOndrej Zary if (err) { 1613f5f53a38SOndrej Zary dev_err(&pdev->dev, "Unable to allocate tables for Acard controller\n"); 1614f5f53a38SOndrej Zary goto unregister; 1615f5f53a38SOndrej Zary } 1616f5f53a38SOndrej Zary 1617c7e6a029SOndrej Zary if (is880(atpdev)) 1618c7e6a029SOndrej Zary atp880_init(shpnt); 1619ecc6ff95SOndrej Zary else if (is885(atpdev)) 1620ecc6ff95SOndrej Zary atp885_init(shpnt); 16214190230eSOndrej Zary else 16224190230eSOndrej Zary atp870_init(shpnt); 16231da177e4SLinus Torvalds 16241729c0d2SOndrej Zary err = request_irq(shpnt->irq, atp870u_intr_handle, IRQF_SHARED, "atp870u", shpnt); 16251729c0d2SOndrej Zary if (err) { 16261729c0d2SOndrej Zary dev_err(&pdev->dev, "Unable to allocate IRQ %d.\n", shpnt->irq); 16271729c0d2SOndrej Zary goto free_tables; 16281729c0d2SOndrej Zary } 16291729c0d2SOndrej Zary 1630bdd5ac40SOndrej Zary err = scsi_add_host(shpnt, &pdev->dev); 1631bdd5ac40SOndrej Zary if (err) 16321da177e4SLinus Torvalds goto scsi_add_fail; 16331da177e4SLinus Torvalds scsi_scan_host(shpnt); 16341729c0d2SOndrej Zary 16351da177e4SLinus Torvalds return 0; 16361da177e4SLinus Torvalds 16371da177e4SLinus Torvalds scsi_add_fail: 16386c9b9c55SOndrej Zary free_irq(shpnt->irq, shpnt); 16391da177e4SLinus Torvalds free_tables: 16401da177e4SLinus Torvalds atp870u_free_tables(shpnt); 16411da177e4SLinus Torvalds unregister: 16421da177e4SLinus Torvalds scsi_host_put(shpnt); 164311ec1318SOndrej Zary release_region: 164411ec1318SOndrej Zary pci_release_regions(pdev); 1645bdd5ac40SOndrej Zary disable_device: 1646bdd5ac40SOndrej Zary pci_disable_device(pdev); 1647bdd5ac40SOndrej Zary fail: 1648bdd5ac40SOndrej Zary return err; 16491da177e4SLinus Torvalds } 16501da177e4SLinus Torvalds 16511da177e4SLinus Torvalds /* The abort command does not leave the device in a clean state where 16521da177e4SLinus Torvalds it is available to be used again. Until this gets worked out, we will 16531da177e4SLinus Torvalds leave it commented out. */ 16541da177e4SLinus Torvalds 16551da177e4SLinus Torvalds static int atp870u_abort(struct scsi_cmnd * SCpnt) 16561da177e4SLinus Torvalds { 16571da177e4SLinus Torvalds unsigned char j, k, c; 16581da177e4SLinus Torvalds struct scsi_cmnd *workrequ; 16591da177e4SLinus Torvalds struct atp_unit *dev; 16601da177e4SLinus Torvalds struct Scsi_Host *host; 16611da177e4SLinus Torvalds host = SCpnt->device->host; 16621da177e4SLinus Torvalds 16631da177e4SLinus Torvalds dev = (struct atp_unit *)&host->hostdata; 1664422c0d61SJeff Garzik c = scmd_channel(SCpnt); 16651da177e4SLinus Torvalds printk(" atp870u: abort Channel = %x \n", c); 16661da177e4SLinus Torvalds printk("working=%x last_cmd=%x ", dev->working[c], dev->last_cmd[c]); 16671da177e4SLinus Torvalds printk(" quhdu=%x quendu=%x ", dev->quhd[c], dev->quend[c]); 16681da177e4SLinus Torvalds for (j = 0; j < 0x18; j++) { 16696a3cebb6SOndrej Zary printk(" r%2x=%2x", j, atp_readb_io(dev, c, j)); 16701da177e4SLinus Torvalds } 16716a3cebb6SOndrej Zary printk(" r1c=%2x", atp_readb_io(dev, c, 0x1c)); 16726a3cebb6SOndrej Zary printk(" r1f=%2x in_snd=%2x ", atp_readb_io(dev, c, 0x1f), dev->in_snd[c]); 16736a3cebb6SOndrej Zary printk(" d00=%2x", atp_readb_pci(dev, c, 0x00)); 16746a3cebb6SOndrej Zary printk(" d02=%2x", atp_readb_pci(dev, c, 0x02)); 16751da177e4SLinus Torvalds for(j=0;j<16;j++) { 16761da177e4SLinus Torvalds if (dev->id[c][j].curr_req != NULL) { 16771da177e4SLinus Torvalds workrequ = dev->id[c][j].curr_req; 16781da177e4SLinus Torvalds printk("\n que cdb= "); 16791da177e4SLinus Torvalds for (k=0; k < workrequ->cmd_len; k++) { 16801da177e4SLinus Torvalds printk(" %2x ",workrequ->cmnd[k]); 16811da177e4SLinus Torvalds } 16821da177e4SLinus Torvalds printk(" last_lenu= %x ",(unsigned int)dev->id[c][j].last_len); 16831da177e4SLinus Torvalds } 16841da177e4SLinus Torvalds } 16851da177e4SLinus Torvalds return SUCCESS; 16861da177e4SLinus Torvalds } 16871da177e4SLinus Torvalds 16881da177e4SLinus Torvalds static const char *atp870u_info(struct Scsi_Host *notused) 16891da177e4SLinus Torvalds { 16901da177e4SLinus Torvalds static char buffer[128]; 16911da177e4SLinus Torvalds 16921da177e4SLinus Torvalds strcpy(buffer, "ACARD AEC-6710/6712/67160 PCI Ultra/W/LVD SCSI-3 Adapter Driver V2.6+ac "); 16931da177e4SLinus Torvalds 16941da177e4SLinus Torvalds return buffer; 16951da177e4SLinus Torvalds } 16961da177e4SLinus Torvalds 1697d773e422SAl Viro static int atp870u_show_info(struct seq_file *m, struct Scsi_Host *HBAptr) 16981da177e4SLinus Torvalds { 16993d30079cSRasmus Villemoes seq_puts(m, "ACARD AEC-671X Driver Version: 2.6+ac\n\n" 17003d30079cSRasmus Villemoes "Adapter Configuration:\n"); 1701d773e422SAl Viro seq_printf(m, " Base IO: %#.4lx\n", HBAptr->io_port); 1702d773e422SAl Viro seq_printf(m, " IRQ: %d\n", HBAptr->irq); 1703d773e422SAl Viro return 0; 17041da177e4SLinus Torvalds } 17051da177e4SLinus Torvalds 17061da177e4SLinus Torvalds 17071da177e4SLinus Torvalds static int atp870u_biosparam(struct scsi_device *disk, struct block_device *dev, 17081da177e4SLinus Torvalds sector_t capacity, int *ip) 17091da177e4SLinus Torvalds { 17101da177e4SLinus Torvalds int heads, sectors, cylinders; 17111da177e4SLinus Torvalds 17121da177e4SLinus Torvalds heads = 64; 17131da177e4SLinus Torvalds sectors = 32; 17141da177e4SLinus Torvalds cylinders = (unsigned long)capacity / (heads * sectors); 17151da177e4SLinus Torvalds if (cylinders > 1024) { 17161da177e4SLinus Torvalds heads = 255; 17171da177e4SLinus Torvalds sectors = 63; 17181da177e4SLinus Torvalds cylinders = (unsigned long)capacity / (heads * sectors); 17191da177e4SLinus Torvalds } 17201da177e4SLinus Torvalds ip[0] = heads; 17211da177e4SLinus Torvalds ip[1] = sectors; 17221da177e4SLinus Torvalds ip[2] = cylinders; 17231da177e4SLinus Torvalds 17241da177e4SLinus Torvalds return 0; 17251da177e4SLinus Torvalds } 17261da177e4SLinus Torvalds 17271da177e4SLinus Torvalds static void atp870u_remove (struct pci_dev *pdev) 17281da177e4SLinus Torvalds { 17291da177e4SLinus Torvalds struct atp_unit *devext = pci_get_drvdata(pdev); 17301da177e4SLinus Torvalds struct Scsi_Host *pshost = devext->host; 17311da177e4SLinus Torvalds 17321da177e4SLinus Torvalds scsi_remove_host(pshost); 17331da177e4SLinus Torvalds free_irq(pshost->irq, pshost); 173411ec1318SOndrej Zary pci_release_regions(pdev); 173511ec1318SOndrej Zary pci_disable_device(pdev); 17361da177e4SLinus Torvalds atp870u_free_tables(pshost); 17371da177e4SLinus Torvalds scsi_host_put(pshost); 17381da177e4SLinus Torvalds } 17391da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 17401da177e4SLinus Torvalds 17411da177e4SLinus Torvalds static struct scsi_host_template atp870u_template = { 17421da177e4SLinus Torvalds .module = THIS_MODULE, 17431da177e4SLinus Torvalds .name = "atp870u" /* name */, 17441da177e4SLinus Torvalds .proc_name = "atp870u", 1745d773e422SAl Viro .show_info = atp870u_show_info, 17461da177e4SLinus Torvalds .info = atp870u_info /* info */, 17471da177e4SLinus Torvalds .queuecommand = atp870u_queuecommand /* queuecommand */, 17481da177e4SLinus Torvalds .eh_abort_handler = atp870u_abort /* abort */, 17491da177e4SLinus Torvalds .bios_param = atp870u_biosparam /* biosparm */, 17501da177e4SLinus Torvalds .can_queue = qcnt /* can_queue */, 17511da177e4SLinus Torvalds .this_id = 7 /* SCSI ID */, 175235c33633SFinn Thain .sg_tablesize = ATP870U_SCATTER /*SG_ALL*/, 17531da177e4SLinus Torvalds .max_sectors = ATP870U_MAX_SECTORS, 17541da177e4SLinus Torvalds }; 17551da177e4SLinus Torvalds 17561da177e4SLinus Torvalds static struct pci_device_id atp870u_id_table[] = { 17571da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP885_DEVID) }, 17581da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID1) }, 17591da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID2) }, 17601da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7610) }, 17611da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612UW) }, 17621da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612U) }, 17631da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612S) }, 17641da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612D) }, 17651da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612SUW) }, 17661da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_8060) }, 17671da177e4SLinus Torvalds { 0, }, 17681da177e4SLinus Torvalds }; 17691da177e4SLinus Torvalds 17701da177e4SLinus Torvalds MODULE_DEVICE_TABLE(pci, atp870u_id_table); 17711da177e4SLinus Torvalds 17721da177e4SLinus Torvalds static struct pci_driver atp870u_driver = { 17731da177e4SLinus Torvalds .id_table = atp870u_id_table, 17741da177e4SLinus Torvalds .name = "atp870u", 17751da177e4SLinus Torvalds .probe = atp870u_probe, 17766f039790SGreg Kroah-Hartman .remove = atp870u_remove, 17771da177e4SLinus Torvalds }; 17781da177e4SLinus Torvalds 17791ccd7d68SOndrej Zary module_pci_driver(atp870u_driver); 17801da177e4SLinus Torvalds 1781bcd5c59fSHannes Reinecke static void atp_is(struct atp_unit *dev, unsigned char c, bool wide_chip, 1782bcd5c59fSHannes Reinecke unsigned char lvdmode) 17831da177e4SLinus Torvalds { 1784fa50b308SOndrej Zary unsigned char i, j, k, rmb, n; 17851da177e4SLinus Torvalds unsigned short int m; 17861da177e4SLinus Torvalds static unsigned char mbuf[512]; 17871da177e4SLinus Torvalds static unsigned char satn[9] = { 0, 0, 0, 0, 0, 0, 0, 6, 6 }; 17881da177e4SLinus Torvalds static unsigned char inqd[9] = { 0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6 }; 17891da177e4SLinus Torvalds static unsigned char synn[6] = { 0x80, 1, 3, 1, 0x19, 0x0e }; 17901da177e4SLinus Torvalds unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e }; 17911da177e4SLinus Torvalds static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x19, 0x0e }; 1792460da918SOndrej Zary static unsigned char synw_870[6] = { 0x80, 1, 3, 1, 0x0c, 0x07 }; 17931da177e4SLinus Torvalds unsigned char synuw[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e }; 17941da177e4SLinus Torvalds static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 }; 17951da177e4SLinus Torvalds static unsigned char u3[9] = { 0x80, 1, 6, 4, 0x09, 00, 0x0e, 0x01, 0x02 }; 17961da177e4SLinus Torvalds 17971da177e4SLinus Torvalds for (i = 0; i < 16; i++) { 1798197fb8d8SOndrej Zary if (!wide_chip && (i > 7)) 1799197fb8d8SOndrej Zary break; 18001da177e4SLinus Torvalds m = 1; 18011da177e4SLinus Torvalds m = m << i; 18021da177e4SLinus Torvalds if ((m & dev->active_id[c]) != 0) { 18031da177e4SLinus Torvalds continue; 18041da177e4SLinus Torvalds } 18051da177e4SLinus Torvalds if (i == dev->host_id[c]) { 18061da177e4SLinus Torvalds printk(KERN_INFO " ID: %2d Host Adapter\n", dev->host_id[c]); 18071da177e4SLinus Torvalds continue; 18081da177e4SLinus Torvalds } 1809197fb8d8SOndrej Zary atp_writeb_io(dev, c, 0x1b, wide_chip ? 0x01 : 0x00); 18105d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 1, 0x08); 18115d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 2, 0x7f); 18125d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 3, satn[0]); 18135d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 4, satn[1]); 18145d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 5, satn[2]); 18155d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 6, satn[3]); 18165d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 7, satn[4]); 18175d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 8, satn[5]); 18185d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x0f, 0); 18195d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp); 18205d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x12, 0); 18215d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x13, satn[6]); 18225d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, satn[7]); 18231da177e4SLinus Torvalds j = i; 18241da177e4SLinus Torvalds if ((j & 0x08) != 0) { 18251da177e4SLinus Torvalds j = (j & 0x07) | 0x40; 18261da177e4SLinus Torvalds } 18275d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x15, j); 18285d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, satn[8]); 18291da177e4SLinus Torvalds 18305d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) 18311da177e4SLinus Torvalds cpu_relax(); 183280b52a7fSOndrej Zary 183380b52a7fSOndrej Zary if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e) 18341da177e4SLinus Torvalds continue; 183580b52a7fSOndrej Zary 18365d2a5a4fSOndrej Zary while (atp_readb_io(dev, c, 0x17) != 0x8e) 18371da177e4SLinus Torvalds cpu_relax(); 183880b52a7fSOndrej Zary 18391da177e4SLinus Torvalds dev->active_id[c] |= m; 18401da177e4SLinus Torvalds 18415d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x10, 0x30); 1842b922a449SOndrej Zary if (is885(dev) || is880(dev)) 18435d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, 0x00); 1844460da918SOndrej Zary else /* result of is870() merge - is this a bug? */ 1845460da918SOndrej Zary atp_writeb_io(dev, c, 0x04, 0x00); 18461da177e4SLinus Torvalds 18471da177e4SLinus Torvalds phase_cmd: 18485d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 184980b52a7fSOndrej Zary 18505d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) 18511da177e4SLinus Torvalds cpu_relax(); 185280b52a7fSOndrej Zary 18535d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17); 18541da177e4SLinus Torvalds if (j != 0x16) { 18555d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x10, 0x41); 18561da177e4SLinus Torvalds goto phase_cmd; 18571da177e4SLinus Torvalds } 18581da177e4SLinus Torvalds sel_ok: 18595d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 3, inqd[0]); 18605d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 4, inqd[1]); 18615d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 5, inqd[2]); 18625d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 6, inqd[3]); 18635d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 7, inqd[4]); 18645d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 8, inqd[5]); 18655d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x0f, 0); 18665d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp); 18675d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x12, 0); 18685d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x13, inqd[6]); 18695d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, inqd[7]); 18705d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, inqd[8]); 187180b52a7fSOndrej Zary 18725d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) 18731da177e4SLinus Torvalds cpu_relax(); 187480b52a7fSOndrej Zary 187580b52a7fSOndrej Zary if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e) 18761da177e4SLinus Torvalds continue; 187780b52a7fSOndrej Zary 18785d2a5a4fSOndrej Zary while (atp_readb_io(dev, c, 0x17) != 0x8e) 18791da177e4SLinus Torvalds cpu_relax(); 188080b52a7fSOndrej Zary 1881197fb8d8SOndrej Zary if (wide_chip) 18825d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x1b, 0x00); 1883197fb8d8SOndrej Zary 18845d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 18851da177e4SLinus Torvalds j = 0; 18861da177e4SLinus Torvalds rd_inq_data: 18875d2a5a4fSOndrej Zary k = atp_readb_io(dev, c, 0x1f); 18881da177e4SLinus Torvalds if ((k & 0x01) != 0) { 18895d2a5a4fSOndrej Zary mbuf[j++] = atp_readb_io(dev, c, 0x19); 18901da177e4SLinus Torvalds goto rd_inq_data; 18911da177e4SLinus Torvalds } 18921da177e4SLinus Torvalds if ((k & 0x80) == 0) { 18931da177e4SLinus Torvalds goto rd_inq_data; 18941da177e4SLinus Torvalds } 18955d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17); 18961da177e4SLinus Torvalds if (j == 0x16) { 18971da177e4SLinus Torvalds goto inq_ok; 18981da177e4SLinus Torvalds } 18995d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x10, 0x46); 19005d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x12, 0); 19015d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x13, 0); 19025d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, 0); 19035d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 190480b52a7fSOndrej Zary 19055d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) 19061da177e4SLinus Torvalds cpu_relax(); 190780b52a7fSOndrej Zary 190880b52a7fSOndrej Zary if (atp_readb_io(dev, c, 0x17) != 0x16) 19091da177e4SLinus Torvalds goto sel_ok; 191080b52a7fSOndrej Zary 19111da177e4SLinus Torvalds inq_ok: 19121da177e4SLinus Torvalds mbuf[36] = 0; 19131da177e4SLinus Torvalds printk(KERN_INFO " ID: %2d %s\n", i, &mbuf[8]); 19141da177e4SLinus Torvalds dev->id[c][i].devtype = mbuf[0]; 19151da177e4SLinus Torvalds rmb = mbuf[1]; 19161da177e4SLinus Torvalds n = mbuf[7]; 1917197fb8d8SOndrej Zary if (!wide_chip) 1918197fb8d8SOndrej Zary goto not_wide; 19191da177e4SLinus Torvalds if ((mbuf[7] & 0x60) == 0) { 19201da177e4SLinus Torvalds goto not_wide; 19211da177e4SLinus Torvalds } 1922b922a449SOndrej Zary if (is885(dev) || is880(dev)) { 1923197fb8d8SOndrej Zary if ((i < 8) && ((dev->global_map[c] & 0x20) == 0)) 1924197fb8d8SOndrej Zary goto not_wide; 1925197fb8d8SOndrej Zary } else { /* result of is870() merge - is this a bug? */ 1926197fb8d8SOndrej Zary if ((dev->global_map[c] & 0x20) == 0) 19271da177e4SLinus Torvalds goto not_wide; 19281da177e4SLinus Torvalds } 19291da177e4SLinus Torvalds if (lvdmode == 0) { 19301da177e4SLinus Torvalds goto chg_wide; 19311da177e4SLinus Torvalds } 193280b52a7fSOndrej Zary if (dev->sp[c][i] != 0x04) // force u2 193380b52a7fSOndrej Zary { 19341da177e4SLinus Torvalds goto chg_wide; 19351da177e4SLinus Torvalds } 19361da177e4SLinus Torvalds 19375d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x1b, 0x01); 19385d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 3, satn[0]); 19395d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 4, satn[1]); 19405d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 5, satn[2]); 19415d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 6, satn[3]); 19425d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 7, satn[4]); 19435d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 8, satn[5]); 19445d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x0f, 0); 19455d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp); 19465d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x12, 0); 19475d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x13, satn[6]); 19485d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, satn[7]); 19495d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, satn[8]); 19501da177e4SLinus Torvalds 19515d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) 19521da177e4SLinus Torvalds cpu_relax(); 195380b52a7fSOndrej Zary 195480b52a7fSOndrej Zary if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 0x17) != 0x8e) 19551da177e4SLinus Torvalds continue; 195680b52a7fSOndrej Zary 19575d2a5a4fSOndrej Zary while (atp_readb_io(dev, c, 0x17) != 0x8e) 19581da177e4SLinus Torvalds cpu_relax(); 195980b52a7fSOndrej Zary 19601da177e4SLinus Torvalds try_u3: 19611da177e4SLinus Torvalds j = 0; 19625d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, 0x09); 19635d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x20); 19641da177e4SLinus Torvalds 19655d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) { 19665d2a5a4fSOndrej Zary if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0) 19675d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x19, u3[j++]); 19681da177e4SLinus Torvalds cpu_relax(); 19691da177e4SLinus Torvalds } 197080b52a7fSOndrej Zary 19715d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00) 19721da177e4SLinus Torvalds cpu_relax(); 197380b52a7fSOndrej Zary 19745d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17) & 0x0f; 19751da177e4SLinus Torvalds if (j == 0x0f) { 19761da177e4SLinus Torvalds goto u3p_in; 19771da177e4SLinus Torvalds } 19781da177e4SLinus Torvalds if (j == 0x0a) { 19791da177e4SLinus Torvalds goto u3p_cmd; 19801da177e4SLinus Torvalds } 19811da177e4SLinus Torvalds if (j == 0x0e) { 19821da177e4SLinus Torvalds goto try_u3; 19831da177e4SLinus Torvalds } 19841da177e4SLinus Torvalds continue; 19851da177e4SLinus Torvalds u3p_out: 19865d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x20); 19875d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) { 19885d2a5a4fSOndrej Zary if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0) 19895d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x19, 0); 19901da177e4SLinus Torvalds cpu_relax(); 19911da177e4SLinus Torvalds } 19925d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17) & 0x0f; 19931da177e4SLinus Torvalds if (j == 0x0f) { 19941da177e4SLinus Torvalds goto u3p_in; 19951da177e4SLinus Torvalds } 19961da177e4SLinus Torvalds if (j == 0x0a) { 19971da177e4SLinus Torvalds goto u3p_cmd; 19981da177e4SLinus Torvalds } 19991da177e4SLinus Torvalds if (j == 0x0e) { 20001da177e4SLinus Torvalds goto u3p_out; 20011da177e4SLinus Torvalds } 20021da177e4SLinus Torvalds continue; 20031da177e4SLinus Torvalds u3p_in: 20045d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, 0x09); 20055d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x20); 20061da177e4SLinus Torvalds k = 0; 20071da177e4SLinus Torvalds u3p_in1: 20085d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x1f); 20091da177e4SLinus Torvalds if ((j & 0x01) != 0) { 20105d2a5a4fSOndrej Zary mbuf[k++] = atp_readb_io(dev, c, 0x19); 20111da177e4SLinus Torvalds goto u3p_in1; 20121da177e4SLinus Torvalds } 20131da177e4SLinus Torvalds if ((j & 0x80) == 0x00) { 20141da177e4SLinus Torvalds goto u3p_in1; 20151da177e4SLinus Torvalds } 20165d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17) & 0x0f; 20171da177e4SLinus Torvalds if (j == 0x0f) { 20181da177e4SLinus Torvalds goto u3p_in; 20191da177e4SLinus Torvalds } 20201da177e4SLinus Torvalds if (j == 0x0a) { 20211da177e4SLinus Torvalds goto u3p_cmd; 20221da177e4SLinus Torvalds } 20231da177e4SLinus Torvalds if (j == 0x0e) { 20241da177e4SLinus Torvalds goto u3p_out; 20251da177e4SLinus Torvalds } 20261da177e4SLinus Torvalds continue; 20271da177e4SLinus Torvalds u3p_cmd: 20285d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x10, 0x30); 20295d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, 0x00); 20305d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 203180b52a7fSOndrej Zary 20325d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00); 203380b52a7fSOndrej Zary 20345d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17); 20351da177e4SLinus Torvalds if (j != 0x16) { 20361da177e4SLinus Torvalds if (j == 0x4e) { 20371da177e4SLinus Torvalds goto u3p_out; 20381da177e4SLinus Torvalds } 20391da177e4SLinus Torvalds continue; 20401da177e4SLinus Torvalds } 20411da177e4SLinus Torvalds if (mbuf[0] != 0x01) { 20421da177e4SLinus Torvalds goto chg_wide; 20431da177e4SLinus Torvalds } 20441da177e4SLinus Torvalds if (mbuf[1] != 0x06) { 20451da177e4SLinus Torvalds goto chg_wide; 20461da177e4SLinus Torvalds } 20471da177e4SLinus Torvalds if (mbuf[2] != 0x04) { 20481da177e4SLinus Torvalds goto chg_wide; 20491da177e4SLinus Torvalds } 20501da177e4SLinus Torvalds if (mbuf[3] == 0x09) { 20511da177e4SLinus Torvalds m = 1; 20521da177e4SLinus Torvalds m = m << i; 20531da177e4SLinus Torvalds dev->wide_id[c] |= m; 20541da177e4SLinus Torvalds dev->id[c][i].devsp = 0xce; 20551da177e4SLinus Torvalds #ifdef ED_DBGP 2056bcd5c59fSHannes Reinecke printk("dev->id[%2d][%2d].devsp = %2x\n", 2057bcd5c59fSHannes Reinecke c, i, dev->id[c][i].devsp); 20581da177e4SLinus Torvalds #endif 20591da177e4SLinus Torvalds continue; 20601da177e4SLinus Torvalds } 20611da177e4SLinus Torvalds chg_wide: 20625d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x1b, 0x01); 20635d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 3, satn[0]); 20645d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 4, satn[1]); 20655d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 5, satn[2]); 20665d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 6, satn[3]); 20675d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 7, satn[4]); 20685d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 8, satn[5]); 20695d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x0f, 0); 20705d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp); 20715d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x12, 0); 20725d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x13, satn[6]); 20735d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, satn[7]); 20745d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, satn[8]); 20751da177e4SLinus Torvalds 20765d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) 20771da177e4SLinus Torvalds cpu_relax(); 207880b52a7fSOndrej Zary 2079bcd5c59fSHannes Reinecke if (atp_readb_io(dev, c, 0x17) != 0x11 && 2080bcd5c59fSHannes Reinecke atp_readb_io(dev, c, 0x17) != 0x8e) 20811da177e4SLinus Torvalds continue; 208280b52a7fSOndrej Zary 20835d2a5a4fSOndrej Zary while (atp_readb_io(dev, c, 0x17) != 0x8e) 20841da177e4SLinus Torvalds cpu_relax(); 208580b52a7fSOndrej Zary 20861da177e4SLinus Torvalds try_wide: 20871da177e4SLinus Torvalds j = 0; 20885d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, 0x05); 20895d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x20); 20901da177e4SLinus Torvalds 20915d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) { 20925d2a5a4fSOndrej Zary if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0) 20935d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x19, wide[j++]); 20941da177e4SLinus Torvalds cpu_relax(); 20951da177e4SLinus Torvalds } 209680b52a7fSOndrej Zary 20975d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00) 20981da177e4SLinus Torvalds cpu_relax(); 209980b52a7fSOndrej Zary 21005d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17) & 0x0f; 21011da177e4SLinus Torvalds if (j == 0x0f) { 21021da177e4SLinus Torvalds goto widep_in; 21031da177e4SLinus Torvalds } 21041da177e4SLinus Torvalds if (j == 0x0a) { 21051da177e4SLinus Torvalds goto widep_cmd; 21061da177e4SLinus Torvalds } 21071da177e4SLinus Torvalds if (j == 0x0e) { 21081da177e4SLinus Torvalds goto try_wide; 21091da177e4SLinus Torvalds } 21101da177e4SLinus Torvalds continue; 21111da177e4SLinus Torvalds widep_out: 21125d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x20); 21135d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) { 21145d2a5a4fSOndrej Zary if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0) 21155d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x19, 0); 21161da177e4SLinus Torvalds cpu_relax(); 21171da177e4SLinus Torvalds } 21185d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17) & 0x0f; 21191da177e4SLinus Torvalds if (j == 0x0f) { 21201da177e4SLinus Torvalds goto widep_in; 21211da177e4SLinus Torvalds } 21221da177e4SLinus Torvalds if (j == 0x0a) { 21231da177e4SLinus Torvalds goto widep_cmd; 21241da177e4SLinus Torvalds } 21251da177e4SLinus Torvalds if (j == 0x0e) { 21261da177e4SLinus Torvalds goto widep_out; 21271da177e4SLinus Torvalds } 21281da177e4SLinus Torvalds continue; 21291da177e4SLinus Torvalds widep_in: 21305d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, 0xff); 21315d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x20); 21321da177e4SLinus Torvalds k = 0; 21331da177e4SLinus Torvalds widep_in1: 21345d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x1f); 21351da177e4SLinus Torvalds if ((j & 0x01) != 0) { 21365d2a5a4fSOndrej Zary mbuf[k++] = atp_readb_io(dev, c, 0x19); 21371da177e4SLinus Torvalds goto widep_in1; 21381da177e4SLinus Torvalds } 21391da177e4SLinus Torvalds if ((j & 0x80) == 0x00) { 21401da177e4SLinus Torvalds goto widep_in1; 21411da177e4SLinus Torvalds } 21425d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17) & 0x0f; 21431da177e4SLinus Torvalds if (j == 0x0f) { 21441da177e4SLinus Torvalds goto widep_in; 21451da177e4SLinus Torvalds } 21461da177e4SLinus Torvalds if (j == 0x0a) { 21471da177e4SLinus Torvalds goto widep_cmd; 21481da177e4SLinus Torvalds } 21491da177e4SLinus Torvalds if (j == 0x0e) { 21501da177e4SLinus Torvalds goto widep_out; 21511da177e4SLinus Torvalds } 21521da177e4SLinus Torvalds continue; 21531da177e4SLinus Torvalds widep_cmd: 21545d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x10, 0x30); 21555d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, 0x00); 21565d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 215780b52a7fSOndrej Zary 21585d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) 21591da177e4SLinus Torvalds cpu_relax(); 216080b52a7fSOndrej Zary 21615d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17); 21621da177e4SLinus Torvalds if (j != 0x16) { 21631da177e4SLinus Torvalds if (j == 0x4e) { 21641da177e4SLinus Torvalds goto widep_out; 21651da177e4SLinus Torvalds } 21661da177e4SLinus Torvalds continue; 21671da177e4SLinus Torvalds } 21681da177e4SLinus Torvalds if (mbuf[0] != 0x01) { 21691da177e4SLinus Torvalds goto not_wide; 21701da177e4SLinus Torvalds } 21711da177e4SLinus Torvalds if (mbuf[1] != 0x02) { 21721da177e4SLinus Torvalds goto not_wide; 21731da177e4SLinus Torvalds } 21741da177e4SLinus Torvalds if (mbuf[2] != 0x03) { 21751da177e4SLinus Torvalds goto not_wide; 21761da177e4SLinus Torvalds } 21771da177e4SLinus Torvalds if (mbuf[3] != 0x01) { 21781da177e4SLinus Torvalds goto not_wide; 21791da177e4SLinus Torvalds } 21801da177e4SLinus Torvalds m = 1; 21811da177e4SLinus Torvalds m = m << i; 21821da177e4SLinus Torvalds dev->wide_id[c] |= m; 21831da177e4SLinus Torvalds not_wide: 2184bcd5c59fSHannes Reinecke if ((dev->id[c][i].devtype == 0x00) || 2185bcd5c59fSHannes Reinecke (dev->id[c][i].devtype == 0x07) || 2186bcd5c59fSHannes Reinecke ((dev->id[c][i].devtype == 0x05) && ((n & 0x10) != 0))) { 21871da177e4SLinus Torvalds m = 1; 21881da177e4SLinus Torvalds m = m << i; 21891da177e4SLinus Torvalds if ((dev->async[c] & m) != 0) { 21901da177e4SLinus Torvalds goto set_sync; 21911da177e4SLinus Torvalds } 21921da177e4SLinus Torvalds } 21931da177e4SLinus Torvalds continue; 21941da177e4SLinus Torvalds set_sync: 2195b922a449SOndrej Zary if ((!is885(dev) && !is880(dev)) || (dev->sp[c][i] == 0x02)) { 21961da177e4SLinus Torvalds synu[4] = 0x0c; 21971da177e4SLinus Torvalds synuw[4] = 0x0c; 21981da177e4SLinus Torvalds } else { 21991da177e4SLinus Torvalds if (dev->sp[c][i] >= 0x03) { 22001da177e4SLinus Torvalds synu[4] = 0x0a; 22011da177e4SLinus Torvalds synuw[4] = 0x0a; 22021da177e4SLinus Torvalds } 22031da177e4SLinus Torvalds } 22041da177e4SLinus Torvalds j = 0; 22051da177e4SLinus Torvalds if ((m & dev->wide_id[c]) != 0) { 22061da177e4SLinus Torvalds j |= 0x01; 22071da177e4SLinus Torvalds } 22085d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x1b, j); 22095d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 3, satn[0]); 22105d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 4, satn[1]); 22115d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 5, satn[2]); 22125d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 6, satn[3]); 22135d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 7, satn[4]); 22145d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 8, satn[5]); 22155d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x0f, 0); 22165d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp); 22175d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x12, 0); 22185d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x13, satn[6]); 22195d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, satn[7]); 22205d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, satn[8]); 22211da177e4SLinus Torvalds 22225d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) 22231da177e4SLinus Torvalds cpu_relax(); 222480b52a7fSOndrej Zary 2225bcd5c59fSHannes Reinecke if (atp_readb_io(dev, c, 0x17) != 0x11 && 2226bcd5c59fSHannes Reinecke atp_readb_io(dev, c, 0x17) != 0x8e) 22271da177e4SLinus Torvalds continue; 222880b52a7fSOndrej Zary 22295d2a5a4fSOndrej Zary while (atp_readb_io(dev, c, 0x17) != 0x8e) 22301da177e4SLinus Torvalds cpu_relax(); 223180b52a7fSOndrej Zary 22321da177e4SLinus Torvalds try_sync: 22331da177e4SLinus Torvalds j = 0; 22345d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, 0x06); 22355d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x20); 22361da177e4SLinus Torvalds 22375d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) { 22385d2a5a4fSOndrej Zary if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0) { 22391da177e4SLinus Torvalds if ((m & dev->wide_id[c]) != 0) { 2240b922a449SOndrej Zary if (is885(dev) || is880(dev)) { 22411da177e4SLinus Torvalds if ((m & dev->ultra_map[c]) != 0) { 22425d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x19, synuw[j++]); 22431da177e4SLinus Torvalds } else { 22445d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x19, synw[j++]); 22451da177e4SLinus Torvalds } 2246460da918SOndrej Zary } else 2247460da918SOndrej Zary atp_writeb_io(dev, c, 0x19, synw_870[j++]); 22481da177e4SLinus Torvalds } else { 22491da177e4SLinus Torvalds if ((m & dev->ultra_map[c]) != 0) { 22505d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x19, synu[j++]); 22511da177e4SLinus Torvalds } else { 22525d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x19, synn[j++]); 22531da177e4SLinus Torvalds } 22541da177e4SLinus Torvalds } 22551da177e4SLinus Torvalds } 22561da177e4SLinus Torvalds } 225780b52a7fSOndrej Zary 22585d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00) 22591da177e4SLinus Torvalds cpu_relax(); 226080b52a7fSOndrej Zary 22615d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17) & 0x0f; 22621da177e4SLinus Torvalds if (j == 0x0f) { 22631da177e4SLinus Torvalds goto phase_ins; 22641da177e4SLinus Torvalds } 22651da177e4SLinus Torvalds if (j == 0x0a) { 22661da177e4SLinus Torvalds goto phase_cmds; 22671da177e4SLinus Torvalds } 22681da177e4SLinus Torvalds if (j == 0x0e) { 22691da177e4SLinus Torvalds goto try_sync; 22701da177e4SLinus Torvalds } 22711da177e4SLinus Torvalds continue; 22721da177e4SLinus Torvalds phase_outs: 22735d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x20); 22745d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) { 22755d2a5a4fSOndrej Zary if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0x00) 22765d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x19, 0x00); 22771da177e4SLinus Torvalds cpu_relax(); 22781da177e4SLinus Torvalds } 22795d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17); 22801da177e4SLinus Torvalds if (j == 0x85) { 22811da177e4SLinus Torvalds goto tar_dcons; 22821da177e4SLinus Torvalds } 22831da177e4SLinus Torvalds j &= 0x0f; 22841da177e4SLinus Torvalds if (j == 0x0f) { 22851da177e4SLinus Torvalds goto phase_ins; 22861da177e4SLinus Torvalds } 22871da177e4SLinus Torvalds if (j == 0x0a) { 22881da177e4SLinus Torvalds goto phase_cmds; 22891da177e4SLinus Torvalds } 22901da177e4SLinus Torvalds if (j == 0x0e) { 22911da177e4SLinus Torvalds goto phase_outs; 22921da177e4SLinus Torvalds } 22931da177e4SLinus Torvalds continue; 22941da177e4SLinus Torvalds phase_ins: 2295b922a449SOndrej Zary if (is885(dev) || is880(dev)) 22965d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, 0x06); 2297460da918SOndrej Zary else 2298460da918SOndrej Zary atp_writeb_io(dev, c, 0x14, 0xff); 22995d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x20); 23001da177e4SLinus Torvalds k = 0; 23011da177e4SLinus Torvalds phase_ins1: 23025d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x1f); 23031da177e4SLinus Torvalds if ((j & 0x01) != 0x00) { 23045d2a5a4fSOndrej Zary mbuf[k++] = atp_readb_io(dev, c, 0x19); 23051da177e4SLinus Torvalds goto phase_ins1; 23061da177e4SLinus Torvalds } 23071da177e4SLinus Torvalds if ((j & 0x80) == 0x00) { 23081da177e4SLinus Torvalds goto phase_ins1; 23091da177e4SLinus Torvalds } 231080b52a7fSOndrej Zary 23115d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x17) & 0x80) == 0x00); 231280b52a7fSOndrej Zary 23135d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17); 23141da177e4SLinus Torvalds if (j == 0x85) { 23151da177e4SLinus Torvalds goto tar_dcons; 23161da177e4SLinus Torvalds } 23171da177e4SLinus Torvalds j &= 0x0f; 23181da177e4SLinus Torvalds if (j == 0x0f) { 23191da177e4SLinus Torvalds goto phase_ins; 23201da177e4SLinus Torvalds } 23211da177e4SLinus Torvalds if (j == 0x0a) { 23221da177e4SLinus Torvalds goto phase_cmds; 23231da177e4SLinus Torvalds } 23241da177e4SLinus Torvalds if (j == 0x0e) { 23251da177e4SLinus Torvalds goto phase_outs; 23261da177e4SLinus Torvalds } 23271da177e4SLinus Torvalds continue; 23281da177e4SLinus Torvalds phase_cmds: 23295d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x10, 0x30); 23301da177e4SLinus Torvalds tar_dcons: 23315d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x14, 0x00); 23325d2a5a4fSOndrej Zary atp_writeb_io(dev, c, 0x18, 0x08); 233380b52a7fSOndrej Zary 23345d2a5a4fSOndrej Zary while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00) 23351da177e4SLinus Torvalds cpu_relax(); 233680b52a7fSOndrej Zary 23375d2a5a4fSOndrej Zary j = atp_readb_io(dev, c, 0x17); 23381da177e4SLinus Torvalds if (j != 0x16) { 23391da177e4SLinus Torvalds continue; 23401da177e4SLinus Torvalds } 23411da177e4SLinus Torvalds if (mbuf[0] != 0x01) { 23421da177e4SLinus Torvalds continue; 23431da177e4SLinus Torvalds } 23441da177e4SLinus Torvalds if (mbuf[1] != 0x03) { 23451da177e4SLinus Torvalds continue; 23461da177e4SLinus Torvalds } 23471da177e4SLinus Torvalds if (mbuf[4] == 0x00) { 23481da177e4SLinus Torvalds continue; 23491da177e4SLinus Torvalds } 23501da177e4SLinus Torvalds if (mbuf[3] > 0x64) { 23511da177e4SLinus Torvalds continue; 23521da177e4SLinus Torvalds } 2353b922a449SOndrej Zary if (is885(dev) || is880(dev)) { 23541da177e4SLinus Torvalds if (mbuf[4] > 0x0e) { 23551da177e4SLinus Torvalds mbuf[4] = 0x0e; 23561da177e4SLinus Torvalds } 2357460da918SOndrej Zary } else { 2358460da918SOndrej Zary if (mbuf[4] > 0x0c) { 2359460da918SOndrej Zary mbuf[4] = 0x0c; 2360460da918SOndrej Zary } 2361460da918SOndrej Zary } 23621da177e4SLinus Torvalds dev->id[c][i].devsp = mbuf[4]; 2363b922a449SOndrej Zary if (is885(dev) || is880(dev)) 23641da177e4SLinus Torvalds if (mbuf[3] < 0x0c) { 23651da177e4SLinus Torvalds j = 0xb0; 23661da177e4SLinus Torvalds goto set_syn_ok; 23671da177e4SLinus Torvalds } 23681da177e4SLinus Torvalds if ((mbuf[3] < 0x0d) && (rmb == 0)) { 23691da177e4SLinus Torvalds j = 0xa0; 23701da177e4SLinus Torvalds goto set_syn_ok; 23711da177e4SLinus Torvalds } 23721da177e4SLinus Torvalds if (mbuf[3] < 0x1a) { 23731da177e4SLinus Torvalds j = 0x20; 23741da177e4SLinus Torvalds goto set_syn_ok; 23751da177e4SLinus Torvalds } 23761da177e4SLinus Torvalds if (mbuf[3] < 0x33) { 23771da177e4SLinus Torvalds j = 0x40; 23781da177e4SLinus Torvalds goto set_syn_ok; 23791da177e4SLinus Torvalds } 23801da177e4SLinus Torvalds if (mbuf[3] < 0x4c) { 23811da177e4SLinus Torvalds j = 0x50; 23821da177e4SLinus Torvalds goto set_syn_ok; 23831da177e4SLinus Torvalds } 23841da177e4SLinus Torvalds j = 0x60; 23851da177e4SLinus Torvalds set_syn_ok: 23861da177e4SLinus Torvalds dev->id[c][i].devsp = (dev->id[c][i].devsp & 0x0f) | j; 23871da177e4SLinus Torvalds #ifdef ED_DBGP 2388bcd5c59fSHannes Reinecke printk("dev->id[%2d][%2d].devsp = %2x\n", 2389bcd5c59fSHannes Reinecke c,i,dev->id[c][i].devsp); 23901da177e4SLinus Torvalds #endif 23911da177e4SLinus Torvalds } 23921da177e4SLinus Torvalds } 2393