11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Copyright (C) 1997 Wu Ching Chen 31da177e4SLinus Torvalds * 2.1.x update (C) 1998 Krzysztof G. Baranowski 41da177e4SLinus Torvalds * 2.5.x update (C) 2002 Red Hat <alan@redhat.com> 51da177e4SLinus Torvalds * 2.6.x update (C) 2004 Red Hat <alan@redhat.com> 61da177e4SLinus Torvalds * 71da177e4SLinus Torvalds * Marcelo Tosatti <marcelo@conectiva.com.br> : SMP fixes 81da177e4SLinus Torvalds * 91da177e4SLinus Torvalds * Wu Ching Chen : NULL pointer fixes 2000/06/02 101da177e4SLinus Torvalds * support atp876 chip 111da177e4SLinus Torvalds * enable 32 bit fifo transfer 121da177e4SLinus Torvalds * support cdrom & remove device run ultra speed 131da177e4SLinus Torvalds * fix disconnect bug 2000/12/21 141da177e4SLinus Torvalds * support atp880 chip lvd u160 2001/05/15 151da177e4SLinus Torvalds * fix prd table bug 2001/09/12 (7.1) 161da177e4SLinus Torvalds * 171da177e4SLinus Torvalds * atp885 support add by ACARD Hao Ping Lian 2005/01/05 181da177e4SLinus Torvalds */ 191da177e4SLinus Torvalds #include <linux/module.h> 201da177e4SLinus Torvalds #include <linux/init.h> 211da177e4SLinus Torvalds #include <linux/interrupt.h> 221da177e4SLinus Torvalds #include <linux/kernel.h> 231da177e4SLinus Torvalds #include <linux/types.h> 241da177e4SLinus Torvalds #include <linux/string.h> 251da177e4SLinus Torvalds #include <linux/ioport.h> 261da177e4SLinus Torvalds #include <linux/delay.h> 271da177e4SLinus Torvalds #include <linux/proc_fs.h> 281da177e4SLinus Torvalds #include <linux/spinlock.h> 291da177e4SLinus Torvalds #include <linux/pci.h> 301da177e4SLinus Torvalds #include <linux/blkdev.h> 31910638aeSMatthias Gehre #include <linux/dma-mapping.h> 321da177e4SLinus Torvalds #include <asm/system.h> 331da177e4SLinus Torvalds #include <asm/io.h> 341da177e4SLinus Torvalds 351da177e4SLinus Torvalds #include <scsi/scsi.h> 361da177e4SLinus Torvalds #include <scsi/scsi_cmnd.h> 371da177e4SLinus Torvalds #include <scsi/scsi_device.h> 381da177e4SLinus Torvalds #include <scsi/scsi_host.h> 391da177e4SLinus Torvalds 401da177e4SLinus Torvalds #include "atp870u.h" 411da177e4SLinus Torvalds 421da177e4SLinus Torvalds static struct scsi_host_template atp870u_template; 431da177e4SLinus Torvalds static void send_s870(struct atp_unit *dev,unsigned char c); 441da177e4SLinus Torvalds static void is885(struct atp_unit *dev, unsigned int wkport,unsigned char c); 451da177e4SLinus Torvalds static void tscam_885(void); 461da177e4SLinus Torvalds 471da177e4SLinus Torvalds static irqreturn_t atp870u_intr_handle(int irq, void *dev_id, struct pt_regs *regs) 481da177e4SLinus Torvalds { 491da177e4SLinus Torvalds unsigned long flags; 501da177e4SLinus Torvalds unsigned short int tmpcip, id; 511da177e4SLinus Torvalds unsigned char i, j, c, target_id, lun,cmdp; 521da177e4SLinus Torvalds unsigned char *prd; 531da177e4SLinus Torvalds struct scsi_cmnd *workreq; 541da177e4SLinus Torvalds unsigned int workport, tmport, tmport1; 551da177e4SLinus Torvalds unsigned long adrcnt, k; 561da177e4SLinus Torvalds #ifdef ED_DBGP 571da177e4SLinus Torvalds unsigned long l; 581da177e4SLinus Torvalds #endif 591da177e4SLinus Torvalds int errstus; 601da177e4SLinus Torvalds struct Scsi_Host *host = dev_id; 611da177e4SLinus Torvalds struct atp_unit *dev = (struct atp_unit *)&host->hostdata; 621da177e4SLinus Torvalds 631da177e4SLinus Torvalds for (c = 0; c < 2; c++) { 641da177e4SLinus Torvalds tmport = dev->ioport[c] + 0x1f; 651da177e4SLinus Torvalds j = inb(tmport); 661da177e4SLinus Torvalds if ((j & 0x80) != 0) 671da177e4SLinus Torvalds { 681da177e4SLinus Torvalds goto ch_sel; 691da177e4SLinus Torvalds } 701da177e4SLinus Torvalds dev->in_int[c] = 0; 711da177e4SLinus Torvalds } 721da177e4SLinus Torvalds return IRQ_NONE; 731da177e4SLinus Torvalds ch_sel: 741da177e4SLinus Torvalds #ifdef ED_DBGP 751da177e4SLinus Torvalds printk("atp870u_intr_handle enter\n"); 761da177e4SLinus Torvalds #endif 771da177e4SLinus Torvalds dev->in_int[c] = 1; 781da177e4SLinus Torvalds cmdp = inb(dev->ioport[c] + 0x10); 791da177e4SLinus Torvalds workport = dev->ioport[c]; 801da177e4SLinus Torvalds if (dev->working[c] != 0) { 811da177e4SLinus Torvalds if (dev->dev_id == ATP885_DEVID) { 821da177e4SLinus Torvalds tmport1 = workport + 0x16; 831da177e4SLinus Torvalds if ((inb(tmport1) & 0x80) == 0) 841da177e4SLinus Torvalds outb((inb(tmport1) | 0x80), tmport1); 851da177e4SLinus Torvalds } 861da177e4SLinus Torvalds tmpcip = dev->pciport[c]; 871da177e4SLinus Torvalds if ((inb(tmpcip) & 0x08) != 0) 881da177e4SLinus Torvalds { 891da177e4SLinus Torvalds tmpcip += 0x2; 901da177e4SLinus Torvalds for (k=0; k < 1000; k++) { 911da177e4SLinus Torvalds if ((inb(tmpcip) & 0x08) == 0) { 921da177e4SLinus Torvalds goto stop_dma; 931da177e4SLinus Torvalds } 941da177e4SLinus Torvalds if ((inb(tmpcip) & 0x01) == 0) { 951da177e4SLinus Torvalds goto stop_dma; 961da177e4SLinus Torvalds } 971da177e4SLinus Torvalds } 981da177e4SLinus Torvalds } 991da177e4SLinus Torvalds stop_dma: 1001da177e4SLinus Torvalds tmpcip = dev->pciport[c]; 1011da177e4SLinus Torvalds outb(0x00, tmpcip); 1021da177e4SLinus Torvalds tmport -= 0x08; 1031da177e4SLinus Torvalds 1041da177e4SLinus Torvalds i = inb(tmport); 1051da177e4SLinus Torvalds 1061da177e4SLinus Torvalds if (dev->dev_id == ATP885_DEVID) { 1071da177e4SLinus Torvalds tmpcip += 2; 1081da177e4SLinus Torvalds outb(0x06, tmpcip); 1091da177e4SLinus Torvalds tmpcip -= 2; 1101da177e4SLinus Torvalds } 1111da177e4SLinus Torvalds 1121da177e4SLinus Torvalds tmport -= 0x02; 1131da177e4SLinus Torvalds target_id = inb(tmport); 1141da177e4SLinus Torvalds tmport += 0x02; 1151da177e4SLinus Torvalds 1161da177e4SLinus Torvalds /* 1171da177e4SLinus Torvalds * Remap wide devices onto id numbers 1181da177e4SLinus Torvalds */ 1191da177e4SLinus Torvalds 1201da177e4SLinus Torvalds if ((target_id & 0x40) != 0) { 1211da177e4SLinus Torvalds target_id = (target_id & 0x07) | 0x08; 1221da177e4SLinus Torvalds } else { 1231da177e4SLinus Torvalds target_id &= 0x07; 1241da177e4SLinus Torvalds } 1251da177e4SLinus Torvalds 1261da177e4SLinus Torvalds if ((j & 0x40) != 0) { 1271da177e4SLinus Torvalds if (dev->last_cmd[c] == 0xff) { 1281da177e4SLinus Torvalds dev->last_cmd[c] = target_id; 1291da177e4SLinus Torvalds } 1301da177e4SLinus Torvalds dev->last_cmd[c] |= 0x40; 1311da177e4SLinus Torvalds } 1321da177e4SLinus Torvalds if (dev->dev_id == ATP885_DEVID) 1331da177e4SLinus Torvalds dev->r1f[c][target_id] |= j; 1341da177e4SLinus Torvalds #ifdef ED_DBGP 1351da177e4SLinus Torvalds printk("atp870u_intr_handle status = %x\n",i); 1361da177e4SLinus Torvalds #endif 1371da177e4SLinus Torvalds if (i == 0x85) { 1381da177e4SLinus Torvalds if ((dev->last_cmd[c] & 0xf0) != 0x40) { 1391da177e4SLinus Torvalds dev->last_cmd[c] = 0xff; 1401da177e4SLinus Torvalds } 1411da177e4SLinus Torvalds if (dev->dev_id == ATP885_DEVID) { 1421da177e4SLinus Torvalds tmport -= 0x05; 1431da177e4SLinus Torvalds adrcnt = 0; 1441da177e4SLinus Torvalds ((unsigned char *) &adrcnt)[2] = inb(tmport++); 1451da177e4SLinus Torvalds ((unsigned char *) &adrcnt)[1] = inb(tmport++); 1461da177e4SLinus Torvalds ((unsigned char *) &adrcnt)[0] = inb(tmport); 1471da177e4SLinus Torvalds if (dev->id[c][target_id].last_len != adrcnt) 1481da177e4SLinus Torvalds { 1491da177e4SLinus Torvalds k = dev->id[c][target_id].last_len; 1501da177e4SLinus Torvalds k -= adrcnt; 1511da177e4SLinus Torvalds dev->id[c][target_id].tran_len = k; 1521da177e4SLinus Torvalds dev->id[c][target_id].last_len = adrcnt; 1531da177e4SLinus Torvalds } 1541da177e4SLinus Torvalds #ifdef ED_DBGP 1551da177e4SLinus Torvalds printk("tmport = %x dev->id[c][target_id].last_len = %d dev->id[c][target_id].tran_len = %d\n",tmport,dev->id[c][target_id].last_len,dev->id[c][target_id].tran_len); 1561da177e4SLinus Torvalds #endif 1571da177e4SLinus Torvalds } 1581da177e4SLinus Torvalds 1591da177e4SLinus Torvalds /* 1601da177e4SLinus Torvalds * Flip wide 1611da177e4SLinus Torvalds */ 1621da177e4SLinus Torvalds if (dev->wide_id[c] != 0) { 1631da177e4SLinus Torvalds tmport = workport + 0x1b; 1641da177e4SLinus Torvalds outb(0x01, tmport); 1651da177e4SLinus Torvalds while ((inb(tmport) & 0x01) != 0x01) { 1661da177e4SLinus Torvalds outb(0x01, tmport); 1671da177e4SLinus Torvalds } 1681da177e4SLinus Torvalds } 1691da177e4SLinus Torvalds /* 1701da177e4SLinus Torvalds * Issue more commands 1711da177e4SLinus Torvalds */ 1721da177e4SLinus Torvalds spin_lock_irqsave(dev->host->host_lock, flags); 1731da177e4SLinus Torvalds if (((dev->quhd[c] != dev->quend[c]) || (dev->last_cmd[c] != 0xff)) && 1741da177e4SLinus Torvalds (dev->in_snd[c] == 0)) { 1751da177e4SLinus Torvalds #ifdef ED_DBGP 1761da177e4SLinus Torvalds printk("Call sent_s870\n"); 1771da177e4SLinus Torvalds #endif 1781da177e4SLinus Torvalds send_s870(dev,c); 1791da177e4SLinus Torvalds } 1801da177e4SLinus Torvalds spin_unlock_irqrestore(dev->host->host_lock, flags); 1811da177e4SLinus Torvalds /* 1821da177e4SLinus Torvalds * Done 1831da177e4SLinus Torvalds */ 1841da177e4SLinus Torvalds dev->in_int[c] = 0; 1851da177e4SLinus Torvalds #ifdef ED_DBGP 1861da177e4SLinus Torvalds printk("Status 0x85 return\n"); 1871da177e4SLinus Torvalds #endif 1881da177e4SLinus Torvalds goto handled; 1891da177e4SLinus Torvalds } 1901da177e4SLinus Torvalds 1911da177e4SLinus Torvalds if (i == 0x40) { 1921da177e4SLinus Torvalds dev->last_cmd[c] |= 0x40; 1931da177e4SLinus Torvalds dev->in_int[c] = 0; 1941da177e4SLinus Torvalds goto handled; 1951da177e4SLinus Torvalds } 1961da177e4SLinus Torvalds 1971da177e4SLinus Torvalds if (i == 0x21) { 1981da177e4SLinus Torvalds if ((dev->last_cmd[c] & 0xf0) != 0x40) { 1991da177e4SLinus Torvalds dev->last_cmd[c] = 0xff; 2001da177e4SLinus Torvalds } 2011da177e4SLinus Torvalds tmport -= 0x05; 2021da177e4SLinus Torvalds adrcnt = 0; 2031da177e4SLinus Torvalds ((unsigned char *) &adrcnt)[2] = inb(tmport++); 2041da177e4SLinus Torvalds ((unsigned char *) &adrcnt)[1] = inb(tmport++); 2051da177e4SLinus Torvalds ((unsigned char *) &adrcnt)[0] = inb(tmport); 2061da177e4SLinus Torvalds k = dev->id[c][target_id].last_len; 2071da177e4SLinus Torvalds k -= adrcnt; 2081da177e4SLinus Torvalds dev->id[c][target_id].tran_len = k; 2091da177e4SLinus Torvalds dev->id[c][target_id].last_len = adrcnt; 2101da177e4SLinus Torvalds tmport -= 0x04; 2111da177e4SLinus Torvalds outb(0x41, tmport); 2121da177e4SLinus Torvalds tmport += 0x08; 2131da177e4SLinus Torvalds outb(0x08, tmport); 2141da177e4SLinus Torvalds dev->in_int[c] = 0; 2151da177e4SLinus Torvalds goto handled; 2161da177e4SLinus Torvalds } 2171da177e4SLinus Torvalds 2181da177e4SLinus Torvalds if (dev->dev_id == ATP885_DEVID) { 2191da177e4SLinus Torvalds if ((i == 0x4c) || (i == 0x4d) || (i == 0x8c) || (i == 0x8d)) { 2201da177e4SLinus Torvalds if ((i == 0x4c) || (i == 0x8c)) 2211da177e4SLinus Torvalds i=0x48; 2221da177e4SLinus Torvalds else 2231da177e4SLinus Torvalds i=0x49; 2241da177e4SLinus Torvalds } 2251da177e4SLinus Torvalds 2261da177e4SLinus Torvalds } 2271da177e4SLinus Torvalds if ((i == 0x80) || (i == 0x8f)) { 2281da177e4SLinus Torvalds #ifdef ED_DBGP 2291da177e4SLinus Torvalds printk(KERN_DEBUG "Device reselect\n"); 2301da177e4SLinus Torvalds #endif 2311da177e4SLinus Torvalds lun = 0; 2321da177e4SLinus Torvalds tmport -= 0x07; 2331da177e4SLinus Torvalds if (cmdp == 0x44 || i==0x80) { 2341da177e4SLinus Torvalds tmport += 0x0d; 2351da177e4SLinus Torvalds lun = inb(tmport) & 0x07; 2361da177e4SLinus Torvalds } else { 2371da177e4SLinus Torvalds if ((dev->last_cmd[c] & 0xf0) != 0x40) { 2381da177e4SLinus Torvalds dev->last_cmd[c] = 0xff; 2391da177e4SLinus Torvalds } 2401da177e4SLinus Torvalds if (cmdp == 0x41) { 2411da177e4SLinus Torvalds #ifdef ED_DBGP 2421da177e4SLinus Torvalds printk("cmdp = 0x41\n"); 2431da177e4SLinus Torvalds #endif 2441da177e4SLinus Torvalds tmport += 0x02; 2451da177e4SLinus Torvalds adrcnt = 0; 2461da177e4SLinus Torvalds ((unsigned char *) &adrcnt)[2] = inb(tmport++); 2471da177e4SLinus Torvalds ((unsigned char *) &adrcnt)[1] = inb(tmport++); 2481da177e4SLinus Torvalds ((unsigned char *) &adrcnt)[0] = inb(tmport); 2491da177e4SLinus Torvalds k = dev->id[c][target_id].last_len; 2501da177e4SLinus Torvalds k -= adrcnt; 2511da177e4SLinus Torvalds dev->id[c][target_id].tran_len = k; 2521da177e4SLinus Torvalds dev->id[c][target_id].last_len = adrcnt; 2531da177e4SLinus Torvalds tmport += 0x04; 2541da177e4SLinus Torvalds outb(0x08, tmport); 2551da177e4SLinus Torvalds dev->in_int[c] = 0; 2561da177e4SLinus Torvalds goto handled; 2571da177e4SLinus Torvalds } else { 2581da177e4SLinus Torvalds #ifdef ED_DBGP 2591da177e4SLinus Torvalds printk("cmdp != 0x41\n"); 2601da177e4SLinus Torvalds #endif 2611da177e4SLinus Torvalds outb(0x46, tmport); 2621da177e4SLinus Torvalds dev->id[c][target_id].dirct = 0x00; 2631da177e4SLinus Torvalds tmport += 0x02; 2641da177e4SLinus Torvalds outb(0x00, tmport++); 2651da177e4SLinus Torvalds outb(0x00, tmport++); 2661da177e4SLinus Torvalds outb(0x00, tmport++); 2671da177e4SLinus Torvalds tmport += 0x03; 2681da177e4SLinus Torvalds outb(0x08, tmport); 2691da177e4SLinus Torvalds dev->in_int[c] = 0; 2701da177e4SLinus Torvalds goto handled; 2711da177e4SLinus Torvalds } 2721da177e4SLinus Torvalds } 2731da177e4SLinus Torvalds if (dev->last_cmd[c] != 0xff) { 2741da177e4SLinus Torvalds dev->last_cmd[c] |= 0x40; 2751da177e4SLinus Torvalds } 2761da177e4SLinus Torvalds if (dev->dev_id == ATP885_DEVID) { 2771da177e4SLinus Torvalds j = inb(dev->baseport + 0x29) & 0xfe; 2781da177e4SLinus Torvalds outb(j, dev->baseport + 0x29); 2791da177e4SLinus Torvalds tmport = workport + 0x16; 2801da177e4SLinus Torvalds } else { 2811da177e4SLinus Torvalds tmport = workport + 0x10; 2821da177e4SLinus Torvalds outb(0x45, tmport); 2831da177e4SLinus Torvalds tmport += 0x06; 2841da177e4SLinus Torvalds } 2851da177e4SLinus Torvalds 2861da177e4SLinus Torvalds target_id = inb(tmport); 2871da177e4SLinus Torvalds /* 2881da177e4SLinus Torvalds * Remap wide identifiers 2891da177e4SLinus Torvalds */ 2901da177e4SLinus Torvalds if ((target_id & 0x10) != 0) { 2911da177e4SLinus Torvalds target_id = (target_id & 0x07) | 0x08; 2921da177e4SLinus Torvalds } else { 2931da177e4SLinus Torvalds target_id &= 0x07; 2941da177e4SLinus Torvalds } 2951da177e4SLinus Torvalds if (dev->dev_id == ATP885_DEVID) { 2961da177e4SLinus Torvalds tmport = workport + 0x10; 2971da177e4SLinus Torvalds outb(0x45, tmport); 2981da177e4SLinus Torvalds } 2991da177e4SLinus Torvalds workreq = dev->id[c][target_id].curr_req; 3001da177e4SLinus Torvalds #ifdef ED_DBGP 301017560fcSJeff Garzik scmd_printk(KERN_DEBUG, workreq, "CDB"); 3021da177e4SLinus Torvalds for (l = 0; l < workreq->cmd_len; l++) 3031da177e4SLinus Torvalds printk(KERN_DEBUG " %x",workreq->cmnd[l]); 304017560fcSJeff Garzik printk("\n"); 3051da177e4SLinus Torvalds #endif 3061da177e4SLinus Torvalds 3071da177e4SLinus Torvalds tmport = workport + 0x0f; 3081da177e4SLinus Torvalds outb(lun, tmport); 3091da177e4SLinus Torvalds tmport += 0x02; 3101da177e4SLinus Torvalds outb(dev->id[c][target_id].devsp, tmport++); 3111da177e4SLinus Torvalds adrcnt = dev->id[c][target_id].tran_len; 3121da177e4SLinus Torvalds k = dev->id[c][target_id].last_len; 3131da177e4SLinus Torvalds 3141da177e4SLinus Torvalds outb(((unsigned char *) &k)[2], tmport++); 3151da177e4SLinus Torvalds outb(((unsigned char *) &k)[1], tmport++); 3161da177e4SLinus Torvalds outb(((unsigned char *) &k)[0], tmport++); 3171da177e4SLinus Torvalds #ifdef ED_DBGP 3181da177e4SLinus Torvalds printk("k %x, k[0] 0x%x k[1] 0x%x k[2] 0x%x\n", k, inb(tmport-1), inb(tmport-2), inb(tmport-3)); 3191da177e4SLinus Torvalds #endif 3201da177e4SLinus Torvalds /* Remap wide */ 3211da177e4SLinus Torvalds j = target_id; 3221da177e4SLinus Torvalds if (target_id > 7) { 3231da177e4SLinus Torvalds j = (j & 0x07) | 0x40; 3241da177e4SLinus Torvalds } 3251da177e4SLinus Torvalds /* Add direction */ 3261da177e4SLinus Torvalds j |= dev->id[c][target_id].dirct; 3271da177e4SLinus Torvalds outb(j, tmport++); 3281da177e4SLinus Torvalds outb(0x80,tmport); 3291da177e4SLinus Torvalds 3301da177e4SLinus Torvalds /* enable 32 bit fifo transfer */ 3311da177e4SLinus Torvalds if (dev->dev_id == ATP885_DEVID) { 3321da177e4SLinus Torvalds tmpcip = dev->pciport[c] + 1; 3331da177e4SLinus Torvalds i=inb(tmpcip) & 0xf3; 3341da177e4SLinus Torvalds //j=workreq->cmnd[0]; 3351da177e4SLinus Torvalds if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) { 3361da177e4SLinus Torvalds i |= 0x0c; 3371da177e4SLinus Torvalds } 3381da177e4SLinus Torvalds outb(i,tmpcip); 3391da177e4SLinus Torvalds } else if ((dev->dev_id == ATP880_DEVID1) || 3401da177e4SLinus Torvalds (dev->dev_id == ATP880_DEVID2) ) { 3411da177e4SLinus Torvalds tmport = workport - 0x05; 3421da177e4SLinus Torvalds if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) { 3431da177e4SLinus Torvalds outb((unsigned char) ((inb(tmport) & 0x3f) | 0xc0), tmport); 3441da177e4SLinus Torvalds } else { 3451da177e4SLinus Torvalds outb((unsigned char) (inb(tmport) & 0x3f), tmport); 3461da177e4SLinus Torvalds } 3471da177e4SLinus Torvalds } else { 3481da177e4SLinus Torvalds tmport = workport + 0x3a; 3491da177e4SLinus Torvalds if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) { 3501da177e4SLinus Torvalds outb((unsigned char) ((inb(tmport) & 0xf3) | 0x08), tmport); 3511da177e4SLinus Torvalds } else { 3521da177e4SLinus Torvalds outb((unsigned char) (inb(tmport) & 0xf3), tmport); 3531da177e4SLinus Torvalds } 3541da177e4SLinus Torvalds } 3551da177e4SLinus Torvalds tmport = workport + 0x1b; 3561da177e4SLinus Torvalds j = 0; 3571da177e4SLinus Torvalds id = 1; 3581da177e4SLinus Torvalds id = id << target_id; 3591da177e4SLinus Torvalds /* 3601da177e4SLinus Torvalds * Is this a wide device 3611da177e4SLinus Torvalds */ 3621da177e4SLinus Torvalds if ((id & dev->wide_id[c]) != 0) { 3631da177e4SLinus Torvalds j |= 0x01; 3641da177e4SLinus Torvalds } 3651da177e4SLinus Torvalds outb(j, tmport); 3661da177e4SLinus Torvalds while ((inb(tmport) & 0x01) != j) { 3671da177e4SLinus Torvalds outb(j,tmport); 3681da177e4SLinus Torvalds } 3691da177e4SLinus Torvalds if (dev->id[c][target_id].last_len == 0) { 3701da177e4SLinus Torvalds tmport = workport + 0x18; 3711da177e4SLinus Torvalds outb(0x08, tmport); 3721da177e4SLinus Torvalds dev->in_int[c] = 0; 3731da177e4SLinus Torvalds #ifdef ED_DBGP 3741da177e4SLinus Torvalds printk("dev->id[c][target_id].last_len = 0\n"); 3751da177e4SLinus Torvalds #endif 3761da177e4SLinus Torvalds goto handled; 3771da177e4SLinus Torvalds } 3781da177e4SLinus Torvalds #ifdef ED_DBGP 3791da177e4SLinus Torvalds printk("target_id = %d adrcnt = %d\n",target_id,adrcnt); 3801da177e4SLinus Torvalds #endif 3811da177e4SLinus Torvalds prd = dev->id[c][target_id].prd_pos; 3821da177e4SLinus Torvalds while (adrcnt != 0) { 3831da177e4SLinus Torvalds id = ((unsigned short int *)prd)[2]; 3841da177e4SLinus Torvalds if (id == 0) { 3851da177e4SLinus Torvalds k = 0x10000; 3861da177e4SLinus Torvalds } else { 3871da177e4SLinus Torvalds k = id; 3881da177e4SLinus Torvalds } 3891da177e4SLinus Torvalds if (k > adrcnt) { 3901da177e4SLinus Torvalds ((unsigned short int *)prd)[2] = (unsigned short int) 3911da177e4SLinus Torvalds (k - adrcnt); 3921da177e4SLinus Torvalds ((unsigned long *)prd)[0] += adrcnt; 3931da177e4SLinus Torvalds adrcnt = 0; 3941da177e4SLinus Torvalds dev->id[c][target_id].prd_pos = prd; 3951da177e4SLinus Torvalds } else { 3961da177e4SLinus Torvalds adrcnt -= k; 3971da177e4SLinus Torvalds dev->id[c][target_id].prdaddr += 0x08; 3981da177e4SLinus Torvalds prd += 0x08; 3991da177e4SLinus Torvalds if (adrcnt == 0) { 4001da177e4SLinus Torvalds dev->id[c][target_id].prd_pos = prd; 4011da177e4SLinus Torvalds } 4021da177e4SLinus Torvalds } 4031da177e4SLinus Torvalds } 4041da177e4SLinus Torvalds tmpcip = dev->pciport[c] + 0x04; 4051da177e4SLinus Torvalds outl(dev->id[c][target_id].prdaddr, tmpcip); 4061da177e4SLinus Torvalds #ifdef ED_DBGP 4071da177e4SLinus Torvalds printk("dev->id[%d][%d].prdaddr 0x%8x\n", c, target_id, dev->id[c][target_id].prdaddr); 4081da177e4SLinus Torvalds #endif 4091da177e4SLinus Torvalds if (dev->dev_id == ATP885_DEVID) { 4101da177e4SLinus Torvalds tmpcip -= 0x04; 4111da177e4SLinus Torvalds } else { 4121da177e4SLinus Torvalds tmpcip -= 0x02; 4131da177e4SLinus Torvalds outb(0x06, tmpcip); 4141da177e4SLinus Torvalds outb(0x00, tmpcip); 4151da177e4SLinus Torvalds tmpcip -= 0x02; 4161da177e4SLinus Torvalds } 4171da177e4SLinus Torvalds tmport = workport + 0x18; 4181da177e4SLinus Torvalds /* 4191da177e4SLinus Torvalds * Check transfer direction 4201da177e4SLinus Torvalds */ 4211da177e4SLinus Torvalds if (dev->id[c][target_id].dirct != 0) { 4221da177e4SLinus Torvalds outb(0x08, tmport); 4231da177e4SLinus Torvalds outb(0x01, tmpcip); 4241da177e4SLinus Torvalds dev->in_int[c] = 0; 4251da177e4SLinus Torvalds #ifdef ED_DBGP 4261da177e4SLinus Torvalds printk("status 0x80 return dirct != 0\n"); 4271da177e4SLinus Torvalds #endif 4281da177e4SLinus Torvalds goto handled; 4291da177e4SLinus Torvalds } 4301da177e4SLinus Torvalds outb(0x08, tmport); 4311da177e4SLinus Torvalds outb(0x09, tmpcip); 4321da177e4SLinus Torvalds dev->in_int[c] = 0; 4331da177e4SLinus Torvalds #ifdef ED_DBGP 4341da177e4SLinus Torvalds printk("status 0x80 return dirct = 0\n"); 4351da177e4SLinus Torvalds #endif 4361da177e4SLinus Torvalds goto handled; 4371da177e4SLinus Torvalds } 4381da177e4SLinus Torvalds 4391da177e4SLinus Torvalds /* 4401da177e4SLinus Torvalds * Current scsi request on this target 4411da177e4SLinus Torvalds */ 4421da177e4SLinus Torvalds 4431da177e4SLinus Torvalds workreq = dev->id[c][target_id].curr_req; 4441da177e4SLinus Torvalds 4451da177e4SLinus Torvalds if (i == 0x42) { 4461da177e4SLinus Torvalds if ((dev->last_cmd[c] & 0xf0) != 0x40) 4471da177e4SLinus Torvalds { 4481da177e4SLinus Torvalds dev->last_cmd[c] = 0xff; 4491da177e4SLinus Torvalds } 4501da177e4SLinus Torvalds errstus = 0x02; 4511da177e4SLinus Torvalds workreq->result = errstus; 4521da177e4SLinus Torvalds goto go_42; 4531da177e4SLinus Torvalds } 4541da177e4SLinus Torvalds if (i == 0x16) { 4551da177e4SLinus Torvalds if ((dev->last_cmd[c] & 0xf0) != 0x40) { 4561da177e4SLinus Torvalds dev->last_cmd[c] = 0xff; 4571da177e4SLinus Torvalds } 4581da177e4SLinus Torvalds errstus = 0; 4591da177e4SLinus Torvalds tmport -= 0x08; 4601da177e4SLinus Torvalds errstus = inb(tmport); 4611da177e4SLinus Torvalds if (((dev->r1f[c][target_id] & 0x10) != 0)&&(dev->dev_id==ATP885_DEVID)) { 4621da177e4SLinus Torvalds printk(KERN_WARNING "AEC67162 CRC ERROR !\n"); 4631da177e4SLinus Torvalds errstus = 0x02; 4641da177e4SLinus Torvalds } 4651da177e4SLinus Torvalds workreq->result = errstus; 4661da177e4SLinus Torvalds go_42: 4671da177e4SLinus Torvalds if (dev->dev_id == ATP885_DEVID) { 4681da177e4SLinus Torvalds j = inb(dev->baseport + 0x29) | 0x01; 4691da177e4SLinus Torvalds outb(j, dev->baseport + 0x29); 4701da177e4SLinus Torvalds } 4711da177e4SLinus Torvalds /* 4721da177e4SLinus Torvalds * Complete the command 4731da177e4SLinus Torvalds */ 4741da177e4SLinus Torvalds if (workreq->use_sg) { 4751da177e4SLinus Torvalds pci_unmap_sg(dev->pdev, 4765d5ff44fSChristoph Hellwig (struct scatterlist *)workreq->request_buffer, 4771da177e4SLinus Torvalds workreq->use_sg, 4781da177e4SLinus Torvalds workreq->sc_data_direction); 4791da177e4SLinus Torvalds } else if (workreq->request_bufflen && 4801da177e4SLinus Torvalds workreq->sc_data_direction != DMA_NONE) { 4811da177e4SLinus Torvalds pci_unmap_single(dev->pdev, 4821da177e4SLinus Torvalds workreq->SCp.dma_handle, 4831da177e4SLinus Torvalds workreq->request_bufflen, 4841da177e4SLinus Torvalds workreq->sc_data_direction); 4851da177e4SLinus Torvalds } 4861da177e4SLinus Torvalds spin_lock_irqsave(dev->host->host_lock, flags); 4871da177e4SLinus Torvalds (*workreq->scsi_done) (workreq); 4881da177e4SLinus Torvalds #ifdef ED_DBGP 4891da177e4SLinus Torvalds printk("workreq->scsi_done\n"); 4901da177e4SLinus Torvalds #endif 4911da177e4SLinus Torvalds /* 4921da177e4SLinus Torvalds * Clear it off the queue 4931da177e4SLinus Torvalds */ 4941da177e4SLinus Torvalds dev->id[c][target_id].curr_req = NULL; 4951da177e4SLinus Torvalds dev->working[c]--; 4961da177e4SLinus Torvalds spin_unlock_irqrestore(dev->host->host_lock, flags); 4971da177e4SLinus Torvalds /* 4981da177e4SLinus Torvalds * Take it back wide 4991da177e4SLinus Torvalds */ 5001da177e4SLinus Torvalds if (dev->wide_id[c] != 0) { 5011da177e4SLinus Torvalds tmport = workport + 0x1b; 5021da177e4SLinus Torvalds outb(0x01, tmport); 5031da177e4SLinus Torvalds while ((inb(tmport) & 0x01) != 0x01) { 5041da177e4SLinus Torvalds outb(0x01, tmport); 5051da177e4SLinus Torvalds } 5061da177e4SLinus Torvalds } 5071da177e4SLinus Torvalds /* 5081da177e4SLinus Torvalds * If there is stuff to send and nothing going then send it 5091da177e4SLinus Torvalds */ 5101da177e4SLinus Torvalds spin_lock_irqsave(dev->host->host_lock, flags); 5111da177e4SLinus Torvalds if (((dev->last_cmd[c] != 0xff) || (dev->quhd[c] != dev->quend[c])) && 5121da177e4SLinus Torvalds (dev->in_snd[c] == 0)) { 5131da177e4SLinus Torvalds #ifdef ED_DBGP 5141da177e4SLinus Torvalds printk("Call sent_s870(scsi_done)\n"); 5151da177e4SLinus Torvalds #endif 5161da177e4SLinus Torvalds send_s870(dev,c); 5171da177e4SLinus Torvalds } 5181da177e4SLinus Torvalds spin_unlock_irqrestore(dev->host->host_lock, flags); 5191da177e4SLinus Torvalds dev->in_int[c] = 0; 5201da177e4SLinus Torvalds goto handled; 5211da177e4SLinus Torvalds } 5221da177e4SLinus Torvalds if ((dev->last_cmd[c] & 0xf0) != 0x40) { 5231da177e4SLinus Torvalds dev->last_cmd[c] = 0xff; 5241da177e4SLinus Torvalds } 5251da177e4SLinus Torvalds if (i == 0x4f) { 5261da177e4SLinus Torvalds i = 0x89; 5271da177e4SLinus Torvalds } 5281da177e4SLinus Torvalds i &= 0x0f; 5291da177e4SLinus Torvalds if (i == 0x09) { 5301da177e4SLinus Torvalds tmpcip += 4; 5311da177e4SLinus Torvalds outl(dev->id[c][target_id].prdaddr, tmpcip); 5321da177e4SLinus Torvalds tmpcip = tmpcip - 2; 5331da177e4SLinus Torvalds outb(0x06, tmpcip); 5341da177e4SLinus Torvalds outb(0x00, tmpcip); 5351da177e4SLinus Torvalds tmpcip = tmpcip - 2; 5361da177e4SLinus Torvalds tmport = workport + 0x10; 5371da177e4SLinus Torvalds outb(0x41, tmport); 5381da177e4SLinus Torvalds if (dev->dev_id == ATP885_DEVID) { 5391da177e4SLinus Torvalds tmport += 2; 5401da177e4SLinus Torvalds k = dev->id[c][target_id].last_len; 5411da177e4SLinus Torvalds outb((unsigned char) (((unsigned char *) (&k))[2]), tmport++); 5421da177e4SLinus Torvalds outb((unsigned char) (((unsigned char *) (&k))[1]), tmport++); 5431da177e4SLinus Torvalds outb((unsigned char) (((unsigned char *) (&k))[0]), tmport); 5441da177e4SLinus Torvalds dev->id[c][target_id].dirct = 0x00; 5451da177e4SLinus Torvalds tmport += 0x04; 5461da177e4SLinus Torvalds } else { 5471da177e4SLinus Torvalds dev->id[c][target_id].dirct = 0x00; 5481da177e4SLinus Torvalds tmport += 0x08; 5491da177e4SLinus Torvalds } 5501da177e4SLinus Torvalds outb(0x08, tmport); 5511da177e4SLinus Torvalds outb(0x09, tmpcip); 5521da177e4SLinus Torvalds dev->in_int[c] = 0; 5531da177e4SLinus Torvalds goto handled; 5541da177e4SLinus Torvalds } 5551da177e4SLinus Torvalds if (i == 0x08) { 5561da177e4SLinus Torvalds tmpcip += 4; 5571da177e4SLinus Torvalds outl(dev->id[c][target_id].prdaddr, tmpcip); 5581da177e4SLinus Torvalds tmpcip = tmpcip - 2; 5591da177e4SLinus Torvalds outb(0x06, tmpcip); 5601da177e4SLinus Torvalds outb(0x00, tmpcip); 5611da177e4SLinus Torvalds tmpcip = tmpcip - 2; 5621da177e4SLinus Torvalds tmport = workport + 0x10; 5631da177e4SLinus Torvalds outb(0x41, tmport); 5641da177e4SLinus Torvalds if (dev->dev_id == ATP885_DEVID) { 5651da177e4SLinus Torvalds tmport += 2; 5661da177e4SLinus Torvalds k = dev->id[c][target_id].last_len; 5671da177e4SLinus Torvalds outb((unsigned char) (((unsigned char *) (&k))[2]), tmport++); 5681da177e4SLinus Torvalds outb((unsigned char) (((unsigned char *) (&k))[1]), tmport++); 5691da177e4SLinus Torvalds outb((unsigned char) (((unsigned char *) (&k))[0]), tmport++); 5701da177e4SLinus Torvalds } else { 5711da177e4SLinus Torvalds tmport += 5; 5721da177e4SLinus Torvalds } 5731da177e4SLinus Torvalds outb((unsigned char) (inb(tmport) | 0x20), tmport); 5741da177e4SLinus Torvalds dev->id[c][target_id].dirct = 0x20; 5751da177e4SLinus Torvalds tmport += 0x03; 5761da177e4SLinus Torvalds outb(0x08, tmport); 5771da177e4SLinus Torvalds outb(0x01, tmpcip); 5781da177e4SLinus Torvalds dev->in_int[c] = 0; 5791da177e4SLinus Torvalds goto handled; 5801da177e4SLinus Torvalds } 5811da177e4SLinus Torvalds tmport -= 0x07; 5821da177e4SLinus Torvalds if (i == 0x0a) { 5831da177e4SLinus Torvalds outb(0x30, tmport); 5841da177e4SLinus Torvalds } else { 5851da177e4SLinus Torvalds outb(0x46, tmport); 5861da177e4SLinus Torvalds } 5871da177e4SLinus Torvalds dev->id[c][target_id].dirct = 0x00; 5881da177e4SLinus Torvalds tmport += 0x02; 5891da177e4SLinus Torvalds outb(0x00, tmport++); 5901da177e4SLinus Torvalds outb(0x00, tmport++); 5911da177e4SLinus Torvalds outb(0x00, tmport++); 5921da177e4SLinus Torvalds tmport += 0x03; 5931da177e4SLinus Torvalds outb(0x08, tmport); 5941da177e4SLinus Torvalds dev->in_int[c] = 0; 5951da177e4SLinus Torvalds goto handled; 5961da177e4SLinus Torvalds } else { 5971da177e4SLinus Torvalds // tmport = workport + 0x17; 5981da177e4SLinus Torvalds // inb(tmport); 5991da177e4SLinus Torvalds // dev->working[c] = 0; 6001da177e4SLinus Torvalds dev->in_int[c] = 0; 6011da177e4SLinus Torvalds goto handled; 6021da177e4SLinus Torvalds } 6031da177e4SLinus Torvalds 6041da177e4SLinus Torvalds handled: 6051da177e4SLinus Torvalds #ifdef ED_DBGP 6061da177e4SLinus Torvalds printk("atp870u_intr_handle exit\n"); 6071da177e4SLinus Torvalds #endif 6081da177e4SLinus Torvalds return IRQ_HANDLED; 6091da177e4SLinus Torvalds } 6101da177e4SLinus Torvalds /** 6111da177e4SLinus Torvalds * atp870u_queuecommand - Queue SCSI command 6121da177e4SLinus Torvalds * @req_p: request block 6131da177e4SLinus Torvalds * @done: completion function 6141da177e4SLinus Torvalds * 6151da177e4SLinus Torvalds * Queue a command to the ATP queue. Called with the host lock held. 6161da177e4SLinus Torvalds */ 6171da177e4SLinus Torvalds static int atp870u_queuecommand(struct scsi_cmnd * req_p, 6181da177e4SLinus Torvalds void (*done) (struct scsi_cmnd *)) 6191da177e4SLinus Torvalds { 6201da177e4SLinus Torvalds unsigned char c; 6211da177e4SLinus Torvalds unsigned int tmport,m; 6221da177e4SLinus Torvalds struct atp_unit *dev; 6231da177e4SLinus Torvalds struct Scsi_Host *host; 6241da177e4SLinus Torvalds 625422c0d61SJeff Garzik c = scmd_channel(req_p); 6261da177e4SLinus Torvalds req_p->sense_buffer[0]=0; 6271da177e4SLinus Torvalds req_p->resid = 0; 628422c0d61SJeff Garzik if (scmd_channel(req_p) > 1) { 6291da177e4SLinus Torvalds req_p->result = 0x00040000; 6301da177e4SLinus Torvalds done(req_p); 6311da177e4SLinus Torvalds #ifdef ED_DBGP 6321da177e4SLinus Torvalds printk("atp870u_queuecommand : req_p->device->channel > 1\n"); 6331da177e4SLinus Torvalds #endif 6341da177e4SLinus Torvalds return 0; 6351da177e4SLinus Torvalds } 6361da177e4SLinus Torvalds 6371da177e4SLinus Torvalds host = req_p->device->host; 6381da177e4SLinus Torvalds dev = (struct atp_unit *)&host->hostdata; 6391da177e4SLinus Torvalds 6401da177e4SLinus Torvalds 6411da177e4SLinus Torvalds 6421da177e4SLinus Torvalds m = 1; 643422c0d61SJeff Garzik m = m << scmd_id(req_p); 6441da177e4SLinus Torvalds 6451da177e4SLinus Torvalds /* 6461da177e4SLinus Torvalds * Fake a timeout for missing targets 6471da177e4SLinus Torvalds */ 6481da177e4SLinus Torvalds 6491da177e4SLinus Torvalds if ((m & dev->active_id[c]) == 0) { 6501da177e4SLinus Torvalds req_p->result = 0x00040000; 6511da177e4SLinus Torvalds done(req_p); 6521da177e4SLinus Torvalds return 0; 6531da177e4SLinus Torvalds } 6541da177e4SLinus Torvalds 6551da177e4SLinus Torvalds if (done) { 6561da177e4SLinus Torvalds req_p->scsi_done = done; 6571da177e4SLinus Torvalds } else { 6581da177e4SLinus Torvalds #ifdef ED_DBGP 6591da177e4SLinus Torvalds printk( "atp870u_queuecommand: done can't be NULL\n"); 6601da177e4SLinus Torvalds #endif 6611da177e4SLinus Torvalds req_p->result = 0; 6621da177e4SLinus Torvalds done(req_p); 6631da177e4SLinus Torvalds return 0; 6641da177e4SLinus Torvalds } 6651da177e4SLinus Torvalds 6661da177e4SLinus Torvalds /* 6671da177e4SLinus Torvalds * Count new command 6681da177e4SLinus Torvalds */ 6691da177e4SLinus Torvalds dev->quend[c]++; 6701da177e4SLinus Torvalds if (dev->quend[c] >= qcnt) { 6711da177e4SLinus Torvalds dev->quend[c] = 0; 6721da177e4SLinus Torvalds } 6731da177e4SLinus Torvalds 6741da177e4SLinus Torvalds /* 6751da177e4SLinus Torvalds * Check queue state 6761da177e4SLinus Torvalds */ 6771da177e4SLinus Torvalds if (dev->quhd[c] == dev->quend[c]) { 6781da177e4SLinus Torvalds if (dev->quend[c] == 0) { 6791da177e4SLinus Torvalds dev->quend[c] = qcnt; 6801da177e4SLinus Torvalds } 6811da177e4SLinus Torvalds #ifdef ED_DBGP 6821da177e4SLinus Torvalds printk("atp870u_queuecommand : dev->quhd[c] == dev->quend[c]\n"); 6831da177e4SLinus Torvalds #endif 6841da177e4SLinus Torvalds dev->quend[c]--; 6851da177e4SLinus Torvalds req_p->result = 0x00020000; 6861da177e4SLinus Torvalds done(req_p); 6871da177e4SLinus Torvalds return 0; 6881da177e4SLinus Torvalds } 6891da177e4SLinus Torvalds dev->quereq[c][dev->quend[c]] = req_p; 6901da177e4SLinus Torvalds tmport = dev->ioport[c] + 0x1c; 6911da177e4SLinus Torvalds #ifdef ED_DBGP 6921da177e4SLinus Torvalds printk("dev->ioport[c] = %x inb(tmport) = %x dev->in_int[%d] = %d dev->in_snd[%d] = %d\n",dev->ioport[c],inb(tmport),c,dev->in_int[c],c,dev->in_snd[c]); 6931da177e4SLinus Torvalds #endif 6941da177e4SLinus Torvalds if ((inb(tmport) == 0) && (dev->in_int[c] == 0) && (dev->in_snd[c] == 0)) { 6951da177e4SLinus Torvalds #ifdef ED_DBGP 6961da177e4SLinus Torvalds printk("Call sent_s870(atp870u_queuecommand)\n"); 6971da177e4SLinus Torvalds #endif 6981da177e4SLinus Torvalds send_s870(dev,c); 6991da177e4SLinus Torvalds } 7001da177e4SLinus Torvalds #ifdef ED_DBGP 7011da177e4SLinus Torvalds printk("atp870u_queuecommand : exit\n"); 7021da177e4SLinus Torvalds #endif 7031da177e4SLinus Torvalds return 0; 7041da177e4SLinus Torvalds } 7051da177e4SLinus Torvalds 7061da177e4SLinus Torvalds /** 7071da177e4SLinus Torvalds * send_s870 - send a command to the controller 7081da177e4SLinus Torvalds * @host: host 7091da177e4SLinus Torvalds * 7101da177e4SLinus Torvalds * On entry there is work queued to be done. We move some of that work to the 7111da177e4SLinus Torvalds * controller itself. 7121da177e4SLinus Torvalds * 7131da177e4SLinus Torvalds * Caller holds the host lock. 7141da177e4SLinus Torvalds */ 7151da177e4SLinus Torvalds static void send_s870(struct atp_unit *dev,unsigned char c) 7161da177e4SLinus Torvalds { 7171da177e4SLinus Torvalds unsigned int tmport; 7181da177e4SLinus Torvalds struct scsi_cmnd *workreq; 7191da177e4SLinus Torvalds unsigned int i;//,k; 7201da177e4SLinus Torvalds unsigned char j, target_id; 7211da177e4SLinus Torvalds unsigned char *prd; 7221da177e4SLinus Torvalds unsigned short int tmpcip, w; 7231da177e4SLinus Torvalds unsigned long l, bttl = 0; 7241da177e4SLinus Torvalds unsigned int workport; 7251da177e4SLinus Torvalds struct scatterlist *sgpnt; 7261da177e4SLinus Torvalds unsigned long sg_count; 7271da177e4SLinus Torvalds 7281da177e4SLinus Torvalds if (dev->in_snd[c] != 0) { 7291da177e4SLinus Torvalds #ifdef ED_DBGP 7301da177e4SLinus Torvalds printk("cmnd in_snd\n"); 7311da177e4SLinus Torvalds #endif 7321da177e4SLinus Torvalds return; 7331da177e4SLinus Torvalds } 7341da177e4SLinus Torvalds #ifdef ED_DBGP 7351da177e4SLinus Torvalds printk("Sent_s870 enter\n"); 7361da177e4SLinus Torvalds #endif 7371da177e4SLinus Torvalds dev->in_snd[c] = 1; 7381da177e4SLinus Torvalds if ((dev->last_cmd[c] != 0xff) && ((dev->last_cmd[c] & 0x40) != 0)) { 7391da177e4SLinus Torvalds dev->last_cmd[c] &= 0x0f; 7401da177e4SLinus Torvalds workreq = dev->id[c][dev->last_cmd[c]].curr_req; 7411da177e4SLinus Torvalds if (workreq != NULL) { /* check NULL pointer */ 7421da177e4SLinus Torvalds goto cmd_subp; 7431da177e4SLinus Torvalds } 7441da177e4SLinus Torvalds dev->last_cmd[c] = 0xff; 7451da177e4SLinus Torvalds if (dev->quhd[c] == dev->quend[c]) { 7461da177e4SLinus Torvalds dev->in_snd[c] = 0; 7471da177e4SLinus Torvalds return ; 7481da177e4SLinus Torvalds } 7491da177e4SLinus Torvalds } 7501da177e4SLinus Torvalds if ((dev->last_cmd[c] != 0xff) && (dev->working[c] != 0)) { 7511da177e4SLinus Torvalds dev->in_snd[c] = 0; 7521da177e4SLinus Torvalds return ; 7531da177e4SLinus Torvalds } 7541da177e4SLinus Torvalds dev->working[c]++; 7551da177e4SLinus Torvalds j = dev->quhd[c]; 7561da177e4SLinus Torvalds dev->quhd[c]++; 7571da177e4SLinus Torvalds if (dev->quhd[c] >= qcnt) { 7581da177e4SLinus Torvalds dev->quhd[c] = 0; 7591da177e4SLinus Torvalds } 7601da177e4SLinus Torvalds workreq = dev->quereq[c][dev->quhd[c]]; 761422c0d61SJeff Garzik if (dev->id[c][scmd_id(workreq)].curr_req == 0) { 762422c0d61SJeff Garzik dev->id[c][scmd_id(workreq)].curr_req = workreq; 763422c0d61SJeff Garzik dev->last_cmd[c] = scmd_id(workreq); 7641da177e4SLinus Torvalds goto cmd_subp; 7651da177e4SLinus Torvalds } 7661da177e4SLinus Torvalds dev->quhd[c] = j; 7671da177e4SLinus Torvalds dev->working[c]--; 7681da177e4SLinus Torvalds dev->in_snd[c] = 0; 7691da177e4SLinus Torvalds return; 7701da177e4SLinus Torvalds cmd_subp: 7711da177e4SLinus Torvalds workport = dev->ioport[c]; 7721da177e4SLinus Torvalds tmport = workport + 0x1f; 7731da177e4SLinus Torvalds if ((inb(tmport) & 0xb0) != 0) { 7741da177e4SLinus Torvalds goto abortsnd; 7751da177e4SLinus Torvalds } 7761da177e4SLinus Torvalds tmport = workport + 0x1c; 7771da177e4SLinus Torvalds if (inb(tmport) == 0) { 7781da177e4SLinus Torvalds goto oktosend; 7791da177e4SLinus Torvalds } 7801da177e4SLinus Torvalds abortsnd: 7811da177e4SLinus Torvalds #ifdef ED_DBGP 7821da177e4SLinus Torvalds printk("Abort to Send\n"); 7831da177e4SLinus Torvalds #endif 7841da177e4SLinus Torvalds dev->last_cmd[c] |= 0x40; 7851da177e4SLinus Torvalds dev->in_snd[c] = 0; 7861da177e4SLinus Torvalds return; 7871da177e4SLinus Torvalds oktosend: 7881da177e4SLinus Torvalds #ifdef ED_DBGP 7891da177e4SLinus Torvalds printk("OK to Send\n"); 790422c0d61SJeff Garzik scmd_printk(KERN_DEBUG, workreq, "CDB"); 7911da177e4SLinus Torvalds for(i=0;i<workreq->cmd_len;i++) { 7921da177e4SLinus Torvalds printk(" %x",workreq->cmnd[i]); 7931da177e4SLinus Torvalds } 794422c0d61SJeff Garzik printk("\n"); 7951da177e4SLinus Torvalds #endif 7961da177e4SLinus Torvalds if (dev->dev_id == ATP885_DEVID) { 7971da177e4SLinus Torvalds j = inb(dev->baseport + 0x29) & 0xfe; 7981da177e4SLinus Torvalds outb(j, dev->baseport + 0x29); 799422c0d61SJeff Garzik dev->r1f[c][scmd_id(workreq)] = 0; 8001da177e4SLinus Torvalds } 8011da177e4SLinus Torvalds 8021da177e4SLinus Torvalds if (workreq->cmnd[0] == READ_CAPACITY) { 8031da177e4SLinus Torvalds if (workreq->request_bufflen > 8) { 8041da177e4SLinus Torvalds workreq->request_bufflen = 0x08; 8051da177e4SLinus Torvalds } 8061da177e4SLinus Torvalds } 8071da177e4SLinus Torvalds if (workreq->cmnd[0] == 0x00) { 8081da177e4SLinus Torvalds workreq->request_bufflen = 0; 8091da177e4SLinus Torvalds } 8101da177e4SLinus Torvalds 8111da177e4SLinus Torvalds tmport = workport + 0x1b; 8121da177e4SLinus Torvalds j = 0; 813422c0d61SJeff Garzik target_id = scmd_id(workreq); 8141da177e4SLinus Torvalds 8151da177e4SLinus Torvalds /* 8161da177e4SLinus Torvalds * Wide ? 8171da177e4SLinus Torvalds */ 8181da177e4SLinus Torvalds w = 1; 8191da177e4SLinus Torvalds w = w << target_id; 8201da177e4SLinus Torvalds if ((w & dev->wide_id[c]) != 0) { 8211da177e4SLinus Torvalds j |= 0x01; 8221da177e4SLinus Torvalds } 8231da177e4SLinus Torvalds outb(j, tmport); 8241da177e4SLinus Torvalds while ((inb(tmport) & 0x01) != j) { 8251da177e4SLinus Torvalds outb(j,tmport); 8261da177e4SLinus Torvalds #ifdef ED_DBGP 8271da177e4SLinus Torvalds printk("send_s870 while loop 1\n"); 8281da177e4SLinus Torvalds #endif 8291da177e4SLinus Torvalds } 8301da177e4SLinus Torvalds /* 8311da177e4SLinus Torvalds * Write the command 8321da177e4SLinus Torvalds */ 8331da177e4SLinus Torvalds 8341da177e4SLinus Torvalds tmport = workport; 8351da177e4SLinus Torvalds outb(workreq->cmd_len, tmport++); 8361da177e4SLinus Torvalds outb(0x2c, tmport++); 8371da177e4SLinus Torvalds if (dev->dev_id == ATP885_DEVID) { 8381da177e4SLinus Torvalds outb(0x7f, tmport++); 8391da177e4SLinus Torvalds } else { 8401da177e4SLinus Torvalds outb(0xcf, tmport++); 8411da177e4SLinus Torvalds } 8421da177e4SLinus Torvalds for (i = 0; i < workreq->cmd_len; i++) { 8431da177e4SLinus Torvalds outb(workreq->cmnd[i], tmport++); 8441da177e4SLinus Torvalds } 8451da177e4SLinus Torvalds tmport = workport + 0x0f; 8461da177e4SLinus Torvalds outb(workreq->device->lun, tmport); 8471da177e4SLinus Torvalds tmport += 0x02; 8481da177e4SLinus Torvalds /* 8491da177e4SLinus Torvalds * Write the target 8501da177e4SLinus Torvalds */ 8511da177e4SLinus Torvalds outb(dev->id[c][target_id].devsp, tmport++); 8521da177e4SLinus Torvalds #ifdef ED_DBGP 8531da177e4SLinus Torvalds printk("dev->id[%d][%d].devsp = %2x\n",c,target_id,dev->id[c][target_id].devsp); 8541da177e4SLinus Torvalds #endif 8551da177e4SLinus Torvalds /* 8561da177e4SLinus Torvalds * Figure out the transfer size 8571da177e4SLinus Torvalds */ 8581da177e4SLinus Torvalds if (workreq->use_sg) { 8591da177e4SLinus Torvalds #ifdef ED_DBGP 8601da177e4SLinus Torvalds printk("Using SGL\n"); 8611da177e4SLinus Torvalds #endif 8621da177e4SLinus Torvalds l = 0; 8631da177e4SLinus Torvalds 8641da177e4SLinus Torvalds sgpnt = (struct scatterlist *) workreq->request_buffer; 8651da177e4SLinus Torvalds sg_count = pci_map_sg(dev->pdev, sgpnt, workreq->use_sg, 8661da177e4SLinus Torvalds workreq->sc_data_direction); 8671da177e4SLinus Torvalds 8681da177e4SLinus Torvalds for (i = 0; i < workreq->use_sg; i++) { 8691da177e4SLinus Torvalds if (sgpnt[i].length == 0 || workreq->use_sg > ATP870U_SCATTER) { 8701da177e4SLinus Torvalds panic("Foooooooood fight!"); 8711da177e4SLinus Torvalds } 8721da177e4SLinus Torvalds l += sgpnt[i].length; 8731da177e4SLinus Torvalds } 8741da177e4SLinus Torvalds #ifdef ED_DBGP 8751da177e4SLinus Torvalds printk( "send_s870: workreq->use_sg %d, sg_count %d l %8ld\n", workreq->use_sg, sg_count, l); 8761da177e4SLinus Torvalds #endif 8771da177e4SLinus Torvalds } else if(workreq->request_bufflen && workreq->sc_data_direction != PCI_DMA_NONE) { 8781da177e4SLinus Torvalds #ifdef ED_DBGP 8791da177e4SLinus Torvalds printk("Not using SGL\n"); 8801da177e4SLinus Torvalds #endif 8811da177e4SLinus Torvalds workreq->SCp.dma_handle = pci_map_single(dev->pdev, workreq->request_buffer, 8821da177e4SLinus Torvalds workreq->request_bufflen, 8831da177e4SLinus Torvalds workreq->sc_data_direction); 8841da177e4SLinus Torvalds l = workreq->request_bufflen; 8851da177e4SLinus Torvalds #ifdef ED_DBGP 8861da177e4SLinus Torvalds printk( "send_s870: workreq->use_sg %d, l %8ld\n", workreq->use_sg, l); 8871da177e4SLinus Torvalds #endif 8881da177e4SLinus Torvalds } else l = 0; 8891da177e4SLinus Torvalds /* 8901da177e4SLinus Torvalds * Write transfer size 8911da177e4SLinus Torvalds */ 8921da177e4SLinus Torvalds outb((unsigned char) (((unsigned char *) (&l))[2]), tmport++); 8931da177e4SLinus Torvalds outb((unsigned char) (((unsigned char *) (&l))[1]), tmport++); 8941da177e4SLinus Torvalds outb((unsigned char) (((unsigned char *) (&l))[0]), tmport++); 8951da177e4SLinus Torvalds j = target_id; 8961da177e4SLinus Torvalds dev->id[c][j].last_len = l; 8971da177e4SLinus Torvalds dev->id[c][j].tran_len = 0; 8981da177e4SLinus Torvalds #ifdef ED_DBGP 8991da177e4SLinus Torvalds printk("dev->id[%2d][%2d].last_len = %d\n",c,j,dev->id[c][j].last_len); 9001da177e4SLinus Torvalds #endif 9011da177e4SLinus Torvalds /* 9021da177e4SLinus Torvalds * Flip the wide bits 9031da177e4SLinus Torvalds */ 9041da177e4SLinus Torvalds if ((j & 0x08) != 0) { 9051da177e4SLinus Torvalds j = (j & 0x07) | 0x40; 9061da177e4SLinus Torvalds } 9071da177e4SLinus Torvalds /* 9081da177e4SLinus Torvalds * Check transfer direction 9091da177e4SLinus Torvalds */ 9101da177e4SLinus Torvalds if (workreq->sc_data_direction == DMA_TO_DEVICE) { 9111da177e4SLinus Torvalds outb((unsigned char) (j | 0x20), tmport++); 9121da177e4SLinus Torvalds } else { 9131da177e4SLinus Torvalds outb(j, tmport++); 9141da177e4SLinus Torvalds } 9151da177e4SLinus Torvalds outb((unsigned char) (inb(tmport) | 0x80), tmport); 9161da177e4SLinus Torvalds outb(0x80, tmport); 9171da177e4SLinus Torvalds tmport = workport + 0x1c; 9181da177e4SLinus Torvalds dev->id[c][target_id].dirct = 0; 9191da177e4SLinus Torvalds if (l == 0) { 9201da177e4SLinus Torvalds if (inb(tmport) == 0) { 9211da177e4SLinus Torvalds tmport = workport + 0x18; 9221da177e4SLinus Torvalds #ifdef ED_DBGP 9231da177e4SLinus Torvalds printk("change SCSI_CMD_REG 0x08\n"); 9241da177e4SLinus Torvalds #endif 9251da177e4SLinus Torvalds outb(0x08, tmport); 9261da177e4SLinus Torvalds } else { 9271da177e4SLinus Torvalds dev->last_cmd[c] |= 0x40; 9281da177e4SLinus Torvalds } 9291da177e4SLinus Torvalds dev->in_snd[c] = 0; 9301da177e4SLinus Torvalds return; 9311da177e4SLinus Torvalds } 9321da177e4SLinus Torvalds tmpcip = dev->pciport[c]; 9331da177e4SLinus Torvalds prd = dev->id[c][target_id].prd_table; 9341da177e4SLinus Torvalds dev->id[c][target_id].prd_pos = prd; 9351da177e4SLinus Torvalds 9361da177e4SLinus Torvalds /* 9371da177e4SLinus Torvalds * Now write the request list. Either as scatter/gather or as 9381da177e4SLinus Torvalds * a linear chain. 9391da177e4SLinus Torvalds */ 9401da177e4SLinus Torvalds 9411da177e4SLinus Torvalds if (workreq->use_sg) { 9421da177e4SLinus Torvalds sgpnt = (struct scatterlist *) workreq->request_buffer; 9431da177e4SLinus Torvalds i = 0; 9441da177e4SLinus Torvalds for (j = 0; j < workreq->use_sg; j++) { 9451da177e4SLinus Torvalds bttl = sg_dma_address(&sgpnt[j]); 9461da177e4SLinus Torvalds l=sg_dma_len(&sgpnt[j]); 9471da177e4SLinus Torvalds #ifdef ED_DBGP 9481da177e4SLinus Torvalds printk("1. bttl %x, l %x\n",bttl, l); 9491da177e4SLinus Torvalds #endif 9501da177e4SLinus Torvalds while (l > 0x10000) { 9511da177e4SLinus Torvalds (((u16 *) (prd))[i + 3]) = 0x0000; 9521da177e4SLinus Torvalds (((u16 *) (prd))[i + 2]) = 0x0000; 9531da177e4SLinus Torvalds (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl); 9541da177e4SLinus Torvalds l -= 0x10000; 9551da177e4SLinus Torvalds bttl += 0x10000; 9561da177e4SLinus Torvalds i += 0x04; 9571da177e4SLinus Torvalds } 9581da177e4SLinus Torvalds (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl); 9591da177e4SLinus Torvalds (((u16 *) (prd))[i + 2]) = cpu_to_le16(l); 9601da177e4SLinus Torvalds (((u16 *) (prd))[i + 3]) = 0; 9611da177e4SLinus Torvalds i += 0x04; 9621da177e4SLinus Torvalds } 9631da177e4SLinus Torvalds (((u16 *) (prd))[i - 1]) = cpu_to_le16(0x8000); 9641da177e4SLinus Torvalds #ifdef ED_DBGP 9651da177e4SLinus Torvalds printk("prd %4x %4x %4x %4x\n",(((unsigned short int *)prd)[0]),(((unsigned short int *)prd)[1]),(((unsigned short int *)prd)[2]),(((unsigned short int *)prd)[3])); 9661da177e4SLinus Torvalds printk("2. bttl %x, l %x\n",bttl, l); 9671da177e4SLinus Torvalds #endif 9681da177e4SLinus Torvalds } else { 9691da177e4SLinus Torvalds /* 9701da177e4SLinus Torvalds * For a linear request write a chain of blocks 9711da177e4SLinus Torvalds */ 9721da177e4SLinus Torvalds bttl = workreq->SCp.dma_handle; 9731da177e4SLinus Torvalds l = workreq->request_bufflen; 9741da177e4SLinus Torvalds i = 0; 9751da177e4SLinus Torvalds #ifdef ED_DBGP 9761da177e4SLinus Torvalds printk("3. bttl %x, l %x\n",bttl, l); 9771da177e4SLinus Torvalds #endif 9781da177e4SLinus Torvalds while (l > 0x10000) { 9791da177e4SLinus Torvalds (((u16 *) (prd))[i + 3]) = 0x0000; 9801da177e4SLinus Torvalds (((u16 *) (prd))[i + 2]) = 0x0000; 9811da177e4SLinus Torvalds (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl); 9821da177e4SLinus Torvalds l -= 0x10000; 9831da177e4SLinus Torvalds bttl += 0x10000; 9841da177e4SLinus Torvalds i += 0x04; 9851da177e4SLinus Torvalds } 9861da177e4SLinus Torvalds (((u16 *) (prd))[i + 3]) = cpu_to_le16(0x8000); 9871da177e4SLinus Torvalds (((u16 *) (prd))[i + 2]) = cpu_to_le16(l); 9881da177e4SLinus Torvalds (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl); 9891da177e4SLinus Torvalds #ifdef ED_DBGP 9901da177e4SLinus Torvalds printk("prd %4x %4x %4x %4x\n",(((unsigned short int *)prd)[0]),(((unsigned short int *)prd)[1]),(((unsigned short int *)prd)[2]),(((unsigned short int *)prd)[3])); 9911da177e4SLinus Torvalds printk("4. bttl %x, l %x\n",bttl, l); 9921da177e4SLinus Torvalds #endif 9931da177e4SLinus Torvalds 9941da177e4SLinus Torvalds } 9951da177e4SLinus Torvalds tmpcip += 4; 9961da177e4SLinus Torvalds #ifdef ED_DBGP 9971da177e4SLinus Torvalds printk("send_s870: prdaddr_2 0x%8x tmpcip %x target_id %d\n", dev->id[c][target_id].prdaddr,tmpcip,target_id); 9981da177e4SLinus Torvalds #endif 999b5683557SJames Bottomley dev->id[c][target_id].prdaddr = dev->id[c][target_id].prd_bus; 10001da177e4SLinus Torvalds outl(dev->id[c][target_id].prdaddr, tmpcip); 10011da177e4SLinus Torvalds tmpcip = tmpcip - 2; 10021da177e4SLinus Torvalds outb(0x06, tmpcip); 10031da177e4SLinus Torvalds outb(0x00, tmpcip); 10041da177e4SLinus Torvalds if (dev->dev_id == ATP885_DEVID) { 10051da177e4SLinus Torvalds tmpcip--; 10061da177e4SLinus Torvalds j=inb(tmpcip) & 0xf3; 10071da177e4SLinus Torvalds if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || 10081da177e4SLinus Torvalds (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) { 10091da177e4SLinus Torvalds j |= 0x0c; 10101da177e4SLinus Torvalds } 10111da177e4SLinus Torvalds outb(j,tmpcip); 10121da177e4SLinus Torvalds tmpcip--; 10131da177e4SLinus Torvalds } else if ((dev->dev_id == ATP880_DEVID1) || 10141da177e4SLinus Torvalds (dev->dev_id == ATP880_DEVID2)) { 10151da177e4SLinus Torvalds tmpcip =tmpcip -2; 10161da177e4SLinus Torvalds tmport = workport - 0x05; 10171da177e4SLinus Torvalds if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) { 10181da177e4SLinus Torvalds outb((unsigned char) ((inb(tmport) & 0x3f) | 0xc0), tmport); 10191da177e4SLinus Torvalds } else { 10201da177e4SLinus Torvalds outb((unsigned char) (inb(tmport) & 0x3f), tmport); 10211da177e4SLinus Torvalds } 10221da177e4SLinus Torvalds } else { 10231da177e4SLinus Torvalds tmpcip =tmpcip -2; 10241da177e4SLinus Torvalds tmport = workport + 0x3a; 10251da177e4SLinus Torvalds if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) { 10261da177e4SLinus Torvalds outb((inb(tmport) & 0xf3) | 0x08, tmport); 10271da177e4SLinus Torvalds } else { 10281da177e4SLinus Torvalds outb(inb(tmport) & 0xf3, tmport); 10291da177e4SLinus Torvalds } 10301da177e4SLinus Torvalds } 10311da177e4SLinus Torvalds tmport = workport + 0x1c; 10321da177e4SLinus Torvalds 10331da177e4SLinus Torvalds if(workreq->sc_data_direction == DMA_TO_DEVICE) { 10341da177e4SLinus Torvalds dev->id[c][target_id].dirct = 0x20; 10351da177e4SLinus Torvalds if (inb(tmport) == 0) { 10361da177e4SLinus Torvalds tmport = workport + 0x18; 10371da177e4SLinus Torvalds outb(0x08, tmport); 10381da177e4SLinus Torvalds outb(0x01, tmpcip); 10391da177e4SLinus Torvalds #ifdef ED_DBGP 10401da177e4SLinus Torvalds printk( "start DMA(to target)\n"); 10411da177e4SLinus Torvalds #endif 10421da177e4SLinus Torvalds } else { 10431da177e4SLinus Torvalds dev->last_cmd[c] |= 0x40; 10441da177e4SLinus Torvalds } 10451da177e4SLinus Torvalds dev->in_snd[c] = 0; 10461da177e4SLinus Torvalds return; 10471da177e4SLinus Torvalds } 10481da177e4SLinus Torvalds if (inb(tmport) == 0) { 10491da177e4SLinus Torvalds tmport = workport + 0x18; 10501da177e4SLinus Torvalds outb(0x08, tmport); 10511da177e4SLinus Torvalds outb(0x09, tmpcip); 10521da177e4SLinus Torvalds #ifdef ED_DBGP 10531da177e4SLinus Torvalds printk( "start DMA(to host)\n"); 10541da177e4SLinus Torvalds #endif 10551da177e4SLinus Torvalds } else { 10561da177e4SLinus Torvalds dev->last_cmd[c] |= 0x40; 10571da177e4SLinus Torvalds } 10581da177e4SLinus Torvalds dev->in_snd[c] = 0; 10591da177e4SLinus Torvalds return; 10601da177e4SLinus Torvalds 10611da177e4SLinus Torvalds } 10621da177e4SLinus Torvalds 10631da177e4SLinus Torvalds static unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val) 10641da177e4SLinus Torvalds { 10651da177e4SLinus Torvalds unsigned int tmport; 10661da177e4SLinus Torvalds unsigned short int i, k; 10671da177e4SLinus Torvalds unsigned char j; 10681da177e4SLinus Torvalds 10691da177e4SLinus Torvalds tmport = dev->ioport[0] + 0x1c; 10701da177e4SLinus Torvalds outw(*val, tmport); 10711da177e4SLinus Torvalds FUN_D7: 10721da177e4SLinus Torvalds for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */ 10731da177e4SLinus Torvalds k = inw(tmport); 10741da177e4SLinus Torvalds j = (unsigned char) (k >> 8); 10751da177e4SLinus Torvalds if ((k & 0x8000) != 0) { /* DB7 all release? */ 10761da177e4SLinus Torvalds goto FUN_D7; 10771da177e4SLinus Torvalds } 10781da177e4SLinus Torvalds } 10791da177e4SLinus Torvalds *val |= 0x4000; /* assert DB6 */ 10801da177e4SLinus Torvalds outw(*val, tmport); 10811da177e4SLinus Torvalds *val &= 0xdfff; /* assert DB5 */ 10821da177e4SLinus Torvalds outw(*val, tmport); 10831da177e4SLinus Torvalds FUN_D5: 10841da177e4SLinus Torvalds for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */ 10851da177e4SLinus Torvalds if ((inw(tmport) & 0x2000) != 0) { /* DB5 all release? */ 10861da177e4SLinus Torvalds goto FUN_D5; 10871da177e4SLinus Torvalds } 10881da177e4SLinus Torvalds } 10891da177e4SLinus Torvalds *val |= 0x8000; /* no DB4-0, assert DB7 */ 10901da177e4SLinus Torvalds *val &= 0xe0ff; 10911da177e4SLinus Torvalds outw(*val, tmport); 10921da177e4SLinus Torvalds *val &= 0xbfff; /* release DB6 */ 10931da177e4SLinus Torvalds outw(*val, tmport); 10941da177e4SLinus Torvalds FUN_D6: 10951da177e4SLinus Torvalds for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */ 10961da177e4SLinus Torvalds if ((inw(tmport) & 0x4000) != 0) { /* DB6 all release? */ 10971da177e4SLinus Torvalds goto FUN_D6; 10981da177e4SLinus Torvalds } 10991da177e4SLinus Torvalds } 11001da177e4SLinus Torvalds 11011da177e4SLinus Torvalds return j; 11021da177e4SLinus Torvalds } 11031da177e4SLinus Torvalds 11041da177e4SLinus Torvalds static void tscam(struct Scsi_Host *host) 11051da177e4SLinus Torvalds { 11061da177e4SLinus Torvalds 11071da177e4SLinus Torvalds unsigned int tmport; 11081da177e4SLinus Torvalds unsigned char i, j, k; 11091da177e4SLinus Torvalds unsigned long n; 11101da177e4SLinus Torvalds unsigned short int m, assignid_map, val; 11111da177e4SLinus Torvalds unsigned char mbuf[33], quintet[2]; 11121da177e4SLinus Torvalds struct atp_unit *dev = (struct atp_unit *)&host->hostdata; 11131da177e4SLinus Torvalds static unsigned char g2q_tab[8] = { 11141da177e4SLinus Torvalds 0x38, 0x31, 0x32, 0x2b, 0x34, 0x2d, 0x2e, 0x27 11151da177e4SLinus Torvalds }; 11161da177e4SLinus Torvalds 11171da177e4SLinus Torvalds /* I can't believe we need this before we've even done anything. Remove it 11181da177e4SLinus Torvalds * and see if anyone bitches. 11191da177e4SLinus Torvalds for (i = 0; i < 0x10; i++) { 11201da177e4SLinus Torvalds udelay(0xffff); 11211da177e4SLinus Torvalds } 11221da177e4SLinus Torvalds */ 11231da177e4SLinus Torvalds 11241da177e4SLinus Torvalds tmport = dev->ioport[0] + 1; 11251da177e4SLinus Torvalds outb(0x08, tmport++); 11261da177e4SLinus Torvalds outb(0x7f, tmport); 11271da177e4SLinus Torvalds tmport = dev->ioport[0] + 0x11; 11281da177e4SLinus Torvalds outb(0x20, tmport); 11291da177e4SLinus Torvalds 11301da177e4SLinus Torvalds if ((dev->scam_on & 0x40) == 0) { 11311da177e4SLinus Torvalds return; 11321da177e4SLinus Torvalds } 11331da177e4SLinus Torvalds m = 1; 11341da177e4SLinus Torvalds m <<= dev->host_id[0]; 11351da177e4SLinus Torvalds j = 16; 11361da177e4SLinus Torvalds if (dev->chip_ver < 4) { 11371da177e4SLinus Torvalds m |= 0xff00; 11381da177e4SLinus Torvalds j = 8; 11391da177e4SLinus Torvalds } 11401da177e4SLinus Torvalds assignid_map = m; 11411da177e4SLinus Torvalds tmport = dev->ioport[0] + 0x02; 11421da177e4SLinus Torvalds outb(0x02, tmport++); /* 2*2=4ms,3EH 2/32*3E=3.9ms */ 11431da177e4SLinus Torvalds outb(0, tmport++); 11441da177e4SLinus Torvalds outb(0, tmport++); 11451da177e4SLinus Torvalds outb(0, tmport++); 11461da177e4SLinus Torvalds outb(0, tmport++); 11471da177e4SLinus Torvalds outb(0, tmport++); 11481da177e4SLinus Torvalds outb(0, tmport++); 11491da177e4SLinus Torvalds 11501da177e4SLinus Torvalds for (i = 0; i < j; i++) { 11511da177e4SLinus Torvalds m = 1; 11521da177e4SLinus Torvalds m = m << i; 11531da177e4SLinus Torvalds if ((m & assignid_map) != 0) { 11541da177e4SLinus Torvalds continue; 11551da177e4SLinus Torvalds } 11561da177e4SLinus Torvalds tmport = dev->ioport[0] + 0x0f; 11571da177e4SLinus Torvalds outb(0, tmport++); 11581da177e4SLinus Torvalds tmport += 0x02; 11591da177e4SLinus Torvalds outb(0, tmport++); 11601da177e4SLinus Torvalds outb(0, tmport++); 11611da177e4SLinus Torvalds outb(0, tmport++); 11621da177e4SLinus Torvalds if (i > 7) { 11631da177e4SLinus Torvalds k = (i & 0x07) | 0x40; 11641da177e4SLinus Torvalds } else { 11651da177e4SLinus Torvalds k = i; 11661da177e4SLinus Torvalds } 11671da177e4SLinus Torvalds outb(k, tmport++); 11681da177e4SLinus Torvalds tmport = dev->ioport[0] + 0x1b; 11691da177e4SLinus Torvalds if (dev->chip_ver == 4) { 11701da177e4SLinus Torvalds outb(0x01, tmport); 11711da177e4SLinus Torvalds } else { 11721da177e4SLinus Torvalds outb(0x00, tmport); 11731da177e4SLinus Torvalds } 11741da177e4SLinus Torvalds wait_rdyok: 11751da177e4SLinus Torvalds tmport = dev->ioport[0] + 0x18; 11761da177e4SLinus Torvalds outb(0x09, tmport); 11771da177e4SLinus Torvalds tmport += 0x07; 11781da177e4SLinus Torvalds 11791da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 11801da177e4SLinus Torvalds cpu_relax(); 11811da177e4SLinus Torvalds tmport -= 0x08; 11821da177e4SLinus Torvalds k = inb(tmport); 11831da177e4SLinus Torvalds if (k != 0x16) { 11841da177e4SLinus Torvalds if ((k == 0x85) || (k == 0x42)) { 11851da177e4SLinus Torvalds continue; 11861da177e4SLinus Torvalds } 11871da177e4SLinus Torvalds tmport = dev->ioport[0] + 0x10; 11881da177e4SLinus Torvalds outb(0x41, tmport); 11891da177e4SLinus Torvalds goto wait_rdyok; 11901da177e4SLinus Torvalds } 11911da177e4SLinus Torvalds assignid_map |= m; 11921da177e4SLinus Torvalds 11931da177e4SLinus Torvalds } 11941da177e4SLinus Torvalds tmport = dev->ioport[0] + 0x02; 11951da177e4SLinus Torvalds outb(0x7f, tmport); 11961da177e4SLinus Torvalds tmport = dev->ioport[0] + 0x1b; 11971da177e4SLinus Torvalds outb(0x02, tmport); 11981da177e4SLinus Torvalds 11991da177e4SLinus Torvalds outb(0, 0x80); 12001da177e4SLinus Torvalds 12011da177e4SLinus Torvalds val = 0x0080; /* bsy */ 12021da177e4SLinus Torvalds tmport = dev->ioport[0] + 0x1c; 12031da177e4SLinus Torvalds outw(val, tmport); 12041da177e4SLinus Torvalds val |= 0x0040; /* sel */ 12051da177e4SLinus Torvalds outw(val, tmport); 12061da177e4SLinus Torvalds val |= 0x0004; /* msg */ 12071da177e4SLinus Torvalds outw(val, tmport); 12081da177e4SLinus Torvalds inb(0x80); /* 2 deskew delay(45ns*2=90ns) */ 12091da177e4SLinus Torvalds val &= 0x007f; /* no bsy */ 12101da177e4SLinus Torvalds outw(val, tmport); 12111da177e4SLinus Torvalds mdelay(128); 12121da177e4SLinus Torvalds val &= 0x00fb; /* after 1ms no msg */ 12131da177e4SLinus Torvalds outw(val, tmport); 12141da177e4SLinus Torvalds wait_nomsg: 12151da177e4SLinus Torvalds if ((inb(tmport) & 0x04) != 0) { 12161da177e4SLinus Torvalds goto wait_nomsg; 12171da177e4SLinus Torvalds } 12181da177e4SLinus Torvalds outb(1, 0x80); 12191da177e4SLinus Torvalds udelay(100); 12201da177e4SLinus Torvalds for (n = 0; n < 0x30000; n++) { 12211da177e4SLinus Torvalds if ((inb(tmport) & 0x80) != 0) { /* bsy ? */ 12221da177e4SLinus Torvalds goto wait_io; 12231da177e4SLinus Torvalds } 12241da177e4SLinus Torvalds } 12251da177e4SLinus Torvalds goto TCM_SYNC; 12261da177e4SLinus Torvalds wait_io: 12271da177e4SLinus Torvalds for (n = 0; n < 0x30000; n++) { 12281da177e4SLinus Torvalds if ((inb(tmport) & 0x81) == 0x0081) { 12291da177e4SLinus Torvalds goto wait_io1; 12301da177e4SLinus Torvalds } 12311da177e4SLinus Torvalds } 12321da177e4SLinus Torvalds goto TCM_SYNC; 12331da177e4SLinus Torvalds wait_io1: 12341da177e4SLinus Torvalds inb(0x80); 12351da177e4SLinus Torvalds val |= 0x8003; /* io,cd,db7 */ 12361da177e4SLinus Torvalds outw(val, tmport); 12371da177e4SLinus Torvalds inb(0x80); 12381da177e4SLinus Torvalds val &= 0x00bf; /* no sel */ 12391da177e4SLinus Torvalds outw(val, tmport); 12401da177e4SLinus Torvalds outb(2, 0x80); 12411da177e4SLinus Torvalds TCM_SYNC: 12421da177e4SLinus Torvalds udelay(0x800); 12431da177e4SLinus Torvalds if ((inb(tmport) & 0x80) == 0x00) { /* bsy ? */ 12441da177e4SLinus Torvalds outw(0, tmport--); 12451da177e4SLinus Torvalds outb(0, tmport); 12461da177e4SLinus Torvalds tmport = dev->ioport[0] + 0x15; 12471da177e4SLinus Torvalds outb(0, tmport); 12481da177e4SLinus Torvalds tmport += 0x03; 12491da177e4SLinus Torvalds outb(0x09, tmport); 12501da177e4SLinus Torvalds tmport += 0x07; 12511da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0) 12521da177e4SLinus Torvalds cpu_relax(); 12531da177e4SLinus Torvalds tmport -= 0x08; 12541da177e4SLinus Torvalds inb(tmport); 12551da177e4SLinus Torvalds return; 12561da177e4SLinus Torvalds } 12571da177e4SLinus Torvalds val &= 0x00ff; /* synchronization */ 12581da177e4SLinus Torvalds val |= 0x3f00; 12591da177e4SLinus Torvalds fun_scam(dev, &val); 12601da177e4SLinus Torvalds outb(3, 0x80); 12611da177e4SLinus Torvalds val &= 0x00ff; /* isolation */ 12621da177e4SLinus Torvalds val |= 0x2000; 12631da177e4SLinus Torvalds fun_scam(dev, &val); 12641da177e4SLinus Torvalds outb(4, 0x80); 12651da177e4SLinus Torvalds i = 8; 12661da177e4SLinus Torvalds j = 0; 12671da177e4SLinus Torvalds TCM_ID: 12681da177e4SLinus Torvalds if ((inw(tmport) & 0x2000) == 0) { 12691da177e4SLinus Torvalds goto TCM_ID; 12701da177e4SLinus Torvalds } 12711da177e4SLinus Torvalds outb(5, 0x80); 12721da177e4SLinus Torvalds val &= 0x00ff; /* get ID_STRING */ 12731da177e4SLinus Torvalds val |= 0x2000; 12741da177e4SLinus Torvalds k = fun_scam(dev, &val); 12751da177e4SLinus Torvalds if ((k & 0x03) == 0) { 12761da177e4SLinus Torvalds goto TCM_5; 12771da177e4SLinus Torvalds } 12781da177e4SLinus Torvalds mbuf[j] <<= 0x01; 12791da177e4SLinus Torvalds mbuf[j] &= 0xfe; 12801da177e4SLinus Torvalds if ((k & 0x02) != 0) { 12811da177e4SLinus Torvalds mbuf[j] |= 0x01; 12821da177e4SLinus Torvalds } 12831da177e4SLinus Torvalds i--; 12841da177e4SLinus Torvalds if (i > 0) { 12851da177e4SLinus Torvalds goto TCM_ID; 12861da177e4SLinus Torvalds } 12871da177e4SLinus Torvalds j++; 12881da177e4SLinus Torvalds i = 8; 12891da177e4SLinus Torvalds goto TCM_ID; 12901da177e4SLinus Torvalds 12911da177e4SLinus Torvalds TCM_5: /* isolation complete.. */ 12921da177e4SLinus Torvalds /* mbuf[32]=0; 12931da177e4SLinus Torvalds printk(" \n%x %x %x %s\n ",assignid_map,mbuf[0],mbuf[1],&mbuf[2]); */ 12941da177e4SLinus Torvalds i = 15; 12951da177e4SLinus Torvalds j = mbuf[0]; 12961da177e4SLinus Torvalds if ((j & 0x20) != 0) { /* bit5=1:ID upto 7 */ 12971da177e4SLinus Torvalds i = 7; 12981da177e4SLinus Torvalds } 12991da177e4SLinus Torvalds if ((j & 0x06) == 0) { /* IDvalid? */ 13001da177e4SLinus Torvalds goto G2Q5; 13011da177e4SLinus Torvalds } 13021da177e4SLinus Torvalds k = mbuf[1]; 13031da177e4SLinus Torvalds small_id: 13041da177e4SLinus Torvalds m = 1; 13051da177e4SLinus Torvalds m <<= k; 13061da177e4SLinus Torvalds if ((m & assignid_map) == 0) { 13071da177e4SLinus Torvalds goto G2Q_QUIN; 13081da177e4SLinus Torvalds } 13091da177e4SLinus Torvalds if (k > 0) { 13101da177e4SLinus Torvalds k--; 13111da177e4SLinus Torvalds goto small_id; 13121da177e4SLinus Torvalds } 13131da177e4SLinus Torvalds G2Q5: /* srch from max acceptable ID# */ 13141da177e4SLinus Torvalds k = i; /* max acceptable ID# */ 13151da177e4SLinus Torvalds G2Q_LP: 13161da177e4SLinus Torvalds m = 1; 13171da177e4SLinus Torvalds m <<= k; 13181da177e4SLinus Torvalds if ((m & assignid_map) == 0) { 13191da177e4SLinus Torvalds goto G2Q_QUIN; 13201da177e4SLinus Torvalds } 13211da177e4SLinus Torvalds if (k > 0) { 13221da177e4SLinus Torvalds k--; 13231da177e4SLinus Torvalds goto G2Q_LP; 13241da177e4SLinus Torvalds } 13251da177e4SLinus Torvalds G2Q_QUIN: /* k=binID#, */ 13261da177e4SLinus Torvalds assignid_map |= m; 13271da177e4SLinus Torvalds if (k < 8) { 13281da177e4SLinus Torvalds quintet[0] = 0x38; /* 1st dft ID<8 */ 13291da177e4SLinus Torvalds } else { 13301da177e4SLinus Torvalds quintet[0] = 0x31; /* 1st ID>=8 */ 13311da177e4SLinus Torvalds } 13321da177e4SLinus Torvalds k &= 0x07; 13331da177e4SLinus Torvalds quintet[1] = g2q_tab[k]; 13341da177e4SLinus Torvalds 13351da177e4SLinus Torvalds val &= 0x00ff; /* AssignID 1stQuintet,AH=001xxxxx */ 13361da177e4SLinus Torvalds m = quintet[0] << 8; 13371da177e4SLinus Torvalds val |= m; 13381da177e4SLinus Torvalds fun_scam(dev, &val); 13391da177e4SLinus Torvalds val &= 0x00ff; /* AssignID 2ndQuintet,AH=001xxxxx */ 13401da177e4SLinus Torvalds m = quintet[1] << 8; 13411da177e4SLinus Torvalds val |= m; 13421da177e4SLinus Torvalds fun_scam(dev, &val); 13431da177e4SLinus Torvalds 13441da177e4SLinus Torvalds goto TCM_SYNC; 13451da177e4SLinus Torvalds 13461da177e4SLinus Torvalds } 13471da177e4SLinus Torvalds 13481da177e4SLinus Torvalds static void is870(struct atp_unit *dev, unsigned int wkport) 13491da177e4SLinus Torvalds { 13501da177e4SLinus Torvalds unsigned int tmport; 13511da177e4SLinus Torvalds unsigned char i, j, k, rmb, n; 13521da177e4SLinus Torvalds unsigned short int m; 13531da177e4SLinus Torvalds static unsigned char mbuf[512]; 13541da177e4SLinus Torvalds static unsigned char satn[9] = { 0, 0, 0, 0, 0, 0, 0, 6, 6 }; 13551da177e4SLinus Torvalds static unsigned char inqd[9] = { 0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6 }; 13561da177e4SLinus Torvalds static unsigned char synn[6] = { 0x80, 1, 3, 1, 0x19, 0x0e }; 13571da177e4SLinus Torvalds static unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0c, 0x0e }; 13581da177e4SLinus Torvalds static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x0c, 0x07 }; 13591da177e4SLinus Torvalds static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 }; 13601da177e4SLinus Torvalds 13611da177e4SLinus Torvalds tmport = wkport + 0x3a; 13621da177e4SLinus Torvalds outb((unsigned char) (inb(tmport) | 0x10), tmport); 13631da177e4SLinus Torvalds 13641da177e4SLinus Torvalds for (i = 0; i < 16; i++) { 13651da177e4SLinus Torvalds if ((dev->chip_ver != 4) && (i > 7)) { 13661da177e4SLinus Torvalds break; 13671da177e4SLinus Torvalds } 13681da177e4SLinus Torvalds m = 1; 13691da177e4SLinus Torvalds m = m << i; 13701da177e4SLinus Torvalds if ((m & dev->active_id[0]) != 0) { 13711da177e4SLinus Torvalds continue; 13721da177e4SLinus Torvalds } 13731da177e4SLinus Torvalds if (i == dev->host_id[0]) { 13741da177e4SLinus Torvalds printk(KERN_INFO " ID: %2d Host Adapter\n", dev->host_id[0]); 13751da177e4SLinus Torvalds continue; 13761da177e4SLinus Torvalds } 13771da177e4SLinus Torvalds tmport = wkport + 0x1b; 13781da177e4SLinus Torvalds if (dev->chip_ver == 4) { 13791da177e4SLinus Torvalds outb(0x01, tmport); 13801da177e4SLinus Torvalds } else { 13811da177e4SLinus Torvalds outb(0x00, tmport); 13821da177e4SLinus Torvalds } 13831da177e4SLinus Torvalds tmport = wkport + 1; 13841da177e4SLinus Torvalds outb(0x08, tmport++); 13851da177e4SLinus Torvalds outb(0x7f, tmport++); 13861da177e4SLinus Torvalds outb(satn[0], tmport++); 13871da177e4SLinus Torvalds outb(satn[1], tmport++); 13881da177e4SLinus Torvalds outb(satn[2], tmport++); 13891da177e4SLinus Torvalds outb(satn[3], tmport++); 13901da177e4SLinus Torvalds outb(satn[4], tmport++); 13911da177e4SLinus Torvalds outb(satn[5], tmport++); 13921da177e4SLinus Torvalds tmport += 0x06; 13931da177e4SLinus Torvalds outb(0, tmport); 13941da177e4SLinus Torvalds tmport += 0x02; 13951da177e4SLinus Torvalds outb(dev->id[0][i].devsp, tmport++); 13961da177e4SLinus Torvalds outb(0, tmport++); 13971da177e4SLinus Torvalds outb(satn[6], tmport++); 13981da177e4SLinus Torvalds outb(satn[7], tmport++); 13991da177e4SLinus Torvalds j = i; 14001da177e4SLinus Torvalds if ((j & 0x08) != 0) { 14011da177e4SLinus Torvalds j = (j & 0x07) | 0x40; 14021da177e4SLinus Torvalds } 14031da177e4SLinus Torvalds outb(j, tmport); 14041da177e4SLinus Torvalds tmport += 0x03; 14051da177e4SLinus Torvalds outb(satn[8], tmport); 14061da177e4SLinus Torvalds tmport += 0x07; 14071da177e4SLinus Torvalds 14081da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 14091da177e4SLinus Torvalds cpu_relax(); 14101da177e4SLinus Torvalds 14111da177e4SLinus Torvalds tmport -= 0x08; 14121da177e4SLinus Torvalds if (inb(tmport) != 0x11 && inb(tmport) != 0x8e) 14131da177e4SLinus Torvalds continue; 14141da177e4SLinus Torvalds 14151da177e4SLinus Torvalds while (inb(tmport) != 0x8e) 14161da177e4SLinus Torvalds cpu_relax(); 14171da177e4SLinus Torvalds 14181da177e4SLinus Torvalds dev->active_id[0] |= m; 14191da177e4SLinus Torvalds 14201da177e4SLinus Torvalds tmport = wkport + 0x10; 14211da177e4SLinus Torvalds outb(0x30, tmport); 14221da177e4SLinus Torvalds tmport = wkport + 0x04; 14231da177e4SLinus Torvalds outb(0x00, tmport); 14241da177e4SLinus Torvalds 14251da177e4SLinus Torvalds phase_cmd: 14261da177e4SLinus Torvalds tmport = wkport + 0x18; 14271da177e4SLinus Torvalds outb(0x08, tmport); 14281da177e4SLinus Torvalds tmport += 0x07; 14291da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 14301da177e4SLinus Torvalds cpu_relax(); 14311da177e4SLinus Torvalds tmport -= 0x08; 14321da177e4SLinus Torvalds j = inb(tmport); 14331da177e4SLinus Torvalds if (j != 0x16) { 14341da177e4SLinus Torvalds tmport = wkport + 0x10; 14351da177e4SLinus Torvalds outb(0x41, tmport); 14361da177e4SLinus Torvalds goto phase_cmd; 14371da177e4SLinus Torvalds } 14381da177e4SLinus Torvalds sel_ok: 14391da177e4SLinus Torvalds tmport = wkport + 3; 14401da177e4SLinus Torvalds outb(inqd[0], tmport++); 14411da177e4SLinus Torvalds outb(inqd[1], tmport++); 14421da177e4SLinus Torvalds outb(inqd[2], tmport++); 14431da177e4SLinus Torvalds outb(inqd[3], tmport++); 14441da177e4SLinus Torvalds outb(inqd[4], tmport++); 14451da177e4SLinus Torvalds outb(inqd[5], tmport); 14461da177e4SLinus Torvalds tmport += 0x07; 14471da177e4SLinus Torvalds outb(0, tmport); 14481da177e4SLinus Torvalds tmport += 0x02; 14491da177e4SLinus Torvalds outb(dev->id[0][i].devsp, tmport++); 14501da177e4SLinus Torvalds outb(0, tmport++); 14511da177e4SLinus Torvalds outb(inqd[6], tmport++); 14521da177e4SLinus Torvalds outb(inqd[7], tmport++); 14531da177e4SLinus Torvalds tmport += 0x03; 14541da177e4SLinus Torvalds outb(inqd[8], tmport); 14551da177e4SLinus Torvalds tmport += 0x07; 14561da177e4SLinus Torvalds 14571da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 14581da177e4SLinus Torvalds cpu_relax(); 14591da177e4SLinus Torvalds 14601da177e4SLinus Torvalds tmport -= 0x08; 14611da177e4SLinus Torvalds if (inb(tmport) != 0x11 && inb(tmport) != 0x8e) 14621da177e4SLinus Torvalds continue; 14631da177e4SLinus Torvalds 14641da177e4SLinus Torvalds while (inb(tmport) != 0x8e) 14651da177e4SLinus Torvalds cpu_relax(); 14661da177e4SLinus Torvalds 14671da177e4SLinus Torvalds tmport = wkport + 0x1b; 14681da177e4SLinus Torvalds if (dev->chip_ver == 4) 14691da177e4SLinus Torvalds outb(0x00, tmport); 14701da177e4SLinus Torvalds 14711da177e4SLinus Torvalds tmport = wkport + 0x18; 14721da177e4SLinus Torvalds outb(0x08, tmport); 14731da177e4SLinus Torvalds tmport += 0x07; 14741da177e4SLinus Torvalds j = 0; 14751da177e4SLinus Torvalds rd_inq_data: 14761da177e4SLinus Torvalds k = inb(tmport); 14771da177e4SLinus Torvalds if ((k & 0x01) != 0) { 14781da177e4SLinus Torvalds tmport -= 0x06; 14791da177e4SLinus Torvalds mbuf[j++] = inb(tmport); 14801da177e4SLinus Torvalds tmport += 0x06; 14811da177e4SLinus Torvalds goto rd_inq_data; 14821da177e4SLinus Torvalds } 14831da177e4SLinus Torvalds if ((k & 0x80) == 0) { 14841da177e4SLinus Torvalds goto rd_inq_data; 14851da177e4SLinus Torvalds } 14861da177e4SLinus Torvalds tmport -= 0x08; 14871da177e4SLinus Torvalds j = inb(tmport); 14881da177e4SLinus Torvalds if (j == 0x16) { 14891da177e4SLinus Torvalds goto inq_ok; 14901da177e4SLinus Torvalds } 14911da177e4SLinus Torvalds tmport = wkport + 0x10; 14921da177e4SLinus Torvalds outb(0x46, tmport); 14931da177e4SLinus Torvalds tmport += 0x02; 14941da177e4SLinus Torvalds outb(0, tmport++); 14951da177e4SLinus Torvalds outb(0, tmport++); 14961da177e4SLinus Torvalds outb(0, tmport++); 14971da177e4SLinus Torvalds tmport += 0x03; 14981da177e4SLinus Torvalds outb(0x08, tmport); 14991da177e4SLinus Torvalds tmport += 0x07; 15001da177e4SLinus Torvalds 15011da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 15021da177e4SLinus Torvalds cpu_relax(); 15031da177e4SLinus Torvalds 15041da177e4SLinus Torvalds tmport -= 0x08; 15051da177e4SLinus Torvalds if (inb(tmport) != 0x16) { 15061da177e4SLinus Torvalds goto sel_ok; 15071da177e4SLinus Torvalds } 15081da177e4SLinus Torvalds inq_ok: 15091da177e4SLinus Torvalds mbuf[36] = 0; 15101da177e4SLinus Torvalds printk(KERN_INFO " ID: %2d %s\n", i, &mbuf[8]); 15111da177e4SLinus Torvalds dev->id[0][i].devtype = mbuf[0]; 15121da177e4SLinus Torvalds rmb = mbuf[1]; 15131da177e4SLinus Torvalds n = mbuf[7]; 15141da177e4SLinus Torvalds if (dev->chip_ver != 4) { 15151da177e4SLinus Torvalds goto not_wide; 15161da177e4SLinus Torvalds } 15171da177e4SLinus Torvalds if ((mbuf[7] & 0x60) == 0) { 15181da177e4SLinus Torvalds goto not_wide; 15191da177e4SLinus Torvalds } 15201da177e4SLinus Torvalds if ((dev->global_map[0] & 0x20) == 0) { 15211da177e4SLinus Torvalds goto not_wide; 15221da177e4SLinus Torvalds } 15231da177e4SLinus Torvalds tmport = wkport + 0x1b; 15241da177e4SLinus Torvalds outb(0x01, tmport); 15251da177e4SLinus Torvalds tmport = wkport + 3; 15261da177e4SLinus Torvalds outb(satn[0], tmport++); 15271da177e4SLinus Torvalds outb(satn[1], tmport++); 15281da177e4SLinus Torvalds outb(satn[2], tmport++); 15291da177e4SLinus Torvalds outb(satn[3], tmport++); 15301da177e4SLinus Torvalds outb(satn[4], tmport++); 15311da177e4SLinus Torvalds outb(satn[5], tmport++); 15321da177e4SLinus Torvalds tmport += 0x06; 15331da177e4SLinus Torvalds outb(0, tmport); 15341da177e4SLinus Torvalds tmport += 0x02; 15351da177e4SLinus Torvalds outb(dev->id[0][i].devsp, tmport++); 15361da177e4SLinus Torvalds outb(0, tmport++); 15371da177e4SLinus Torvalds outb(satn[6], tmport++); 15381da177e4SLinus Torvalds outb(satn[7], tmport++); 15391da177e4SLinus Torvalds tmport += 0x03; 15401da177e4SLinus Torvalds outb(satn[8], tmport); 15411da177e4SLinus Torvalds tmport += 0x07; 15421da177e4SLinus Torvalds 15431da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 15441da177e4SLinus Torvalds cpu_relax(); 15451da177e4SLinus Torvalds 15461da177e4SLinus Torvalds tmport -= 0x08; 15471da177e4SLinus Torvalds if (inb(tmport) != 0x11 && inb(tmport) != 0x8e) 15481da177e4SLinus Torvalds continue; 15491da177e4SLinus Torvalds 15501da177e4SLinus Torvalds while (inb(tmport) != 0x8e) 15511da177e4SLinus Torvalds cpu_relax(); 15521da177e4SLinus Torvalds 15531da177e4SLinus Torvalds try_wide: 15541da177e4SLinus Torvalds j = 0; 15551da177e4SLinus Torvalds tmport = wkport + 0x14; 15561da177e4SLinus Torvalds outb(0x05, tmport); 15571da177e4SLinus Torvalds tmport += 0x04; 15581da177e4SLinus Torvalds outb(0x20, tmport); 15591da177e4SLinus Torvalds tmport += 0x07; 15601da177e4SLinus Torvalds 15611da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0) { 15621da177e4SLinus Torvalds if ((inb(tmport) & 0x01) != 0) { 15631da177e4SLinus Torvalds tmport -= 0x06; 15641da177e4SLinus Torvalds outb(wide[j++], tmport); 15651da177e4SLinus Torvalds tmport += 0x06; 15661da177e4SLinus Torvalds } 15671da177e4SLinus Torvalds } 15681da177e4SLinus Torvalds tmport -= 0x08; 15691da177e4SLinus Torvalds 15701da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 15711da177e4SLinus Torvalds cpu_relax(); 15721da177e4SLinus Torvalds 15731da177e4SLinus Torvalds j = inb(tmport) & 0x0f; 15741da177e4SLinus Torvalds if (j == 0x0f) { 15751da177e4SLinus Torvalds goto widep_in; 15761da177e4SLinus Torvalds } 15771da177e4SLinus Torvalds if (j == 0x0a) { 15781da177e4SLinus Torvalds goto widep_cmd; 15791da177e4SLinus Torvalds } 15801da177e4SLinus Torvalds if (j == 0x0e) { 15811da177e4SLinus Torvalds goto try_wide; 15821da177e4SLinus Torvalds } 15831da177e4SLinus Torvalds continue; 15841da177e4SLinus Torvalds widep_out: 15851da177e4SLinus Torvalds tmport = wkport + 0x18; 15861da177e4SLinus Torvalds outb(0x20, tmport); 15871da177e4SLinus Torvalds tmport += 0x07; 15881da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0) { 15891da177e4SLinus Torvalds if ((inb(tmport) & 0x01) != 0) { 15901da177e4SLinus Torvalds tmport -= 0x06; 15911da177e4SLinus Torvalds outb(0, tmport); 15921da177e4SLinus Torvalds tmport += 0x06; 15931da177e4SLinus Torvalds } 15941da177e4SLinus Torvalds } 15951da177e4SLinus Torvalds tmport -= 0x08; 15961da177e4SLinus Torvalds j = inb(tmport) & 0x0f; 15971da177e4SLinus Torvalds if (j == 0x0f) { 15981da177e4SLinus Torvalds goto widep_in; 15991da177e4SLinus Torvalds } 16001da177e4SLinus Torvalds if (j == 0x0a) { 16011da177e4SLinus Torvalds goto widep_cmd; 16021da177e4SLinus Torvalds } 16031da177e4SLinus Torvalds if (j == 0x0e) { 16041da177e4SLinus Torvalds goto widep_out; 16051da177e4SLinus Torvalds } 16061da177e4SLinus Torvalds continue; 16071da177e4SLinus Torvalds widep_in: 16081da177e4SLinus Torvalds tmport = wkport + 0x14; 16091da177e4SLinus Torvalds outb(0xff, tmport); 16101da177e4SLinus Torvalds tmport += 0x04; 16111da177e4SLinus Torvalds outb(0x20, tmport); 16121da177e4SLinus Torvalds tmport += 0x07; 16131da177e4SLinus Torvalds k = 0; 16141da177e4SLinus Torvalds widep_in1: 16151da177e4SLinus Torvalds j = inb(tmport); 16161da177e4SLinus Torvalds if ((j & 0x01) != 0) { 16171da177e4SLinus Torvalds tmport -= 0x06; 16181da177e4SLinus Torvalds mbuf[k++] = inb(tmport); 16191da177e4SLinus Torvalds tmport += 0x06; 16201da177e4SLinus Torvalds goto widep_in1; 16211da177e4SLinus Torvalds } 16221da177e4SLinus Torvalds if ((j & 0x80) == 0x00) { 16231da177e4SLinus Torvalds goto widep_in1; 16241da177e4SLinus Torvalds } 16251da177e4SLinus Torvalds tmport -= 0x08; 16261da177e4SLinus Torvalds j = inb(tmport) & 0x0f; 16271da177e4SLinus Torvalds if (j == 0x0f) { 16281da177e4SLinus Torvalds goto widep_in; 16291da177e4SLinus Torvalds } 16301da177e4SLinus Torvalds if (j == 0x0a) { 16311da177e4SLinus Torvalds goto widep_cmd; 16321da177e4SLinus Torvalds } 16331da177e4SLinus Torvalds if (j == 0x0e) { 16341da177e4SLinus Torvalds goto widep_out; 16351da177e4SLinus Torvalds } 16361da177e4SLinus Torvalds continue; 16371da177e4SLinus Torvalds widep_cmd: 16381da177e4SLinus Torvalds tmport = wkport + 0x10; 16391da177e4SLinus Torvalds outb(0x30, tmport); 16401da177e4SLinus Torvalds tmport = wkport + 0x14; 16411da177e4SLinus Torvalds outb(0x00, tmport); 16421da177e4SLinus Torvalds tmport += 0x04; 16431da177e4SLinus Torvalds outb(0x08, tmport); 16441da177e4SLinus Torvalds tmport += 0x07; 16451da177e4SLinus Torvalds 16461da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 16471da177e4SLinus Torvalds cpu_relax(); 16481da177e4SLinus Torvalds 16491da177e4SLinus Torvalds tmport -= 0x08; 16501da177e4SLinus Torvalds j = inb(tmport); 16511da177e4SLinus Torvalds if (j != 0x16) { 16521da177e4SLinus Torvalds if (j == 0x4e) { 16531da177e4SLinus Torvalds goto widep_out; 16541da177e4SLinus Torvalds } 16551da177e4SLinus Torvalds continue; 16561da177e4SLinus Torvalds } 16571da177e4SLinus Torvalds if (mbuf[0] != 0x01) { 16581da177e4SLinus Torvalds goto not_wide; 16591da177e4SLinus Torvalds } 16601da177e4SLinus Torvalds if (mbuf[1] != 0x02) { 16611da177e4SLinus Torvalds goto not_wide; 16621da177e4SLinus Torvalds } 16631da177e4SLinus Torvalds if (mbuf[2] != 0x03) { 16641da177e4SLinus Torvalds goto not_wide; 16651da177e4SLinus Torvalds } 16661da177e4SLinus Torvalds if (mbuf[3] != 0x01) { 16671da177e4SLinus Torvalds goto not_wide; 16681da177e4SLinus Torvalds } 16691da177e4SLinus Torvalds m = 1; 16701da177e4SLinus Torvalds m = m << i; 16711da177e4SLinus Torvalds dev->wide_id[0] |= m; 16721da177e4SLinus Torvalds not_wide: 16731da177e4SLinus Torvalds if ((dev->id[0][i].devtype == 0x00) || (dev->id[0][i].devtype == 0x07) || ((dev->id[0][i].devtype == 0x05) && ((n & 0x10) != 0))) { 16741da177e4SLinus Torvalds goto set_sync; 16751da177e4SLinus Torvalds } 16761da177e4SLinus Torvalds continue; 16771da177e4SLinus Torvalds set_sync: 16781da177e4SLinus Torvalds tmport = wkport + 0x1b; 16791da177e4SLinus Torvalds j = 0; 16801da177e4SLinus Torvalds if ((m & dev->wide_id[0]) != 0) { 16811da177e4SLinus Torvalds j |= 0x01; 16821da177e4SLinus Torvalds } 16831da177e4SLinus Torvalds outb(j, tmport); 16841da177e4SLinus Torvalds tmport = wkport + 3; 16851da177e4SLinus Torvalds outb(satn[0], tmport++); 16861da177e4SLinus Torvalds outb(satn[1], tmport++); 16871da177e4SLinus Torvalds outb(satn[2], tmport++); 16881da177e4SLinus Torvalds outb(satn[3], tmport++); 16891da177e4SLinus Torvalds outb(satn[4], tmport++); 16901da177e4SLinus Torvalds outb(satn[5], tmport++); 16911da177e4SLinus Torvalds tmport += 0x06; 16921da177e4SLinus Torvalds outb(0, tmport); 16931da177e4SLinus Torvalds tmport += 0x02; 16941da177e4SLinus Torvalds outb(dev->id[0][i].devsp, tmport++); 16951da177e4SLinus Torvalds outb(0, tmport++); 16961da177e4SLinus Torvalds outb(satn[6], tmport++); 16971da177e4SLinus Torvalds outb(satn[7], tmport++); 16981da177e4SLinus Torvalds tmport += 0x03; 16991da177e4SLinus Torvalds outb(satn[8], tmport); 17001da177e4SLinus Torvalds tmport += 0x07; 17011da177e4SLinus Torvalds 17021da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 17031da177e4SLinus Torvalds cpu_relax(); 17041da177e4SLinus Torvalds 17051da177e4SLinus Torvalds tmport -= 0x08; 17061da177e4SLinus Torvalds if (inb(tmport) != 0x11 && inb(tmport) != 0x8e) 17071da177e4SLinus Torvalds continue; 17081da177e4SLinus Torvalds 17091da177e4SLinus Torvalds while (inb(tmport) != 0x8e) 17101da177e4SLinus Torvalds cpu_relax(); 17111da177e4SLinus Torvalds 17121da177e4SLinus Torvalds try_sync: 17131da177e4SLinus Torvalds j = 0; 17141da177e4SLinus Torvalds tmport = wkport + 0x14; 17151da177e4SLinus Torvalds outb(0x06, tmport); 17161da177e4SLinus Torvalds tmport += 0x04; 17171da177e4SLinus Torvalds outb(0x20, tmport); 17181da177e4SLinus Torvalds tmport += 0x07; 17191da177e4SLinus Torvalds 17201da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0) { 17211da177e4SLinus Torvalds if ((inb(tmport) & 0x01) != 0) { 17221da177e4SLinus Torvalds tmport -= 0x06; 17231da177e4SLinus Torvalds if ((m & dev->wide_id[0]) != 0) { 17241da177e4SLinus Torvalds outb(synw[j++], tmport); 17251da177e4SLinus Torvalds } else { 17261da177e4SLinus Torvalds if ((m & dev->ultra_map[0]) != 0) { 17271da177e4SLinus Torvalds outb(synu[j++], tmport); 17281da177e4SLinus Torvalds } else { 17291da177e4SLinus Torvalds outb(synn[j++], tmport); 17301da177e4SLinus Torvalds } 17311da177e4SLinus Torvalds } 17321da177e4SLinus Torvalds tmport += 0x06; 17331da177e4SLinus Torvalds } 17341da177e4SLinus Torvalds } 17351da177e4SLinus Torvalds tmport -= 0x08; 17361da177e4SLinus Torvalds 17371da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 17381da177e4SLinus Torvalds cpu_relax(); 17391da177e4SLinus Torvalds 17401da177e4SLinus Torvalds j = inb(tmport) & 0x0f; 17411da177e4SLinus Torvalds if (j == 0x0f) { 17421da177e4SLinus Torvalds goto phase_ins; 17431da177e4SLinus Torvalds } 17441da177e4SLinus Torvalds if (j == 0x0a) { 17451da177e4SLinus Torvalds goto phase_cmds; 17461da177e4SLinus Torvalds } 17471da177e4SLinus Torvalds if (j == 0x0e) { 17481da177e4SLinus Torvalds goto try_sync; 17491da177e4SLinus Torvalds } 17501da177e4SLinus Torvalds continue; 17511da177e4SLinus Torvalds phase_outs: 17521da177e4SLinus Torvalds tmport = wkport + 0x18; 17531da177e4SLinus Torvalds outb(0x20, tmport); 17541da177e4SLinus Torvalds tmport += 0x07; 17551da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) { 17561da177e4SLinus Torvalds if ((inb(tmport) & 0x01) != 0x00) { 17571da177e4SLinus Torvalds tmport -= 0x06; 17581da177e4SLinus Torvalds outb(0x00, tmport); 17591da177e4SLinus Torvalds tmport += 0x06; 17601da177e4SLinus Torvalds } 17611da177e4SLinus Torvalds } 17621da177e4SLinus Torvalds tmport -= 0x08; 17631da177e4SLinus Torvalds j = inb(tmport); 17641da177e4SLinus Torvalds if (j == 0x85) { 17651da177e4SLinus Torvalds goto tar_dcons; 17661da177e4SLinus Torvalds } 17671da177e4SLinus Torvalds j &= 0x0f; 17681da177e4SLinus Torvalds if (j == 0x0f) { 17691da177e4SLinus Torvalds goto phase_ins; 17701da177e4SLinus Torvalds } 17711da177e4SLinus Torvalds if (j == 0x0a) { 17721da177e4SLinus Torvalds goto phase_cmds; 17731da177e4SLinus Torvalds } 17741da177e4SLinus Torvalds if (j == 0x0e) { 17751da177e4SLinus Torvalds goto phase_outs; 17761da177e4SLinus Torvalds } 17771da177e4SLinus Torvalds continue; 17781da177e4SLinus Torvalds phase_ins: 17791da177e4SLinus Torvalds tmport = wkport + 0x14; 17801da177e4SLinus Torvalds outb(0xff, tmport); 17811da177e4SLinus Torvalds tmport += 0x04; 17821da177e4SLinus Torvalds outb(0x20, tmport); 17831da177e4SLinus Torvalds tmport += 0x07; 17841da177e4SLinus Torvalds k = 0; 17851da177e4SLinus Torvalds phase_ins1: 17861da177e4SLinus Torvalds j = inb(tmport); 17871da177e4SLinus Torvalds if ((j & 0x01) != 0x00) { 17881da177e4SLinus Torvalds tmport -= 0x06; 17891da177e4SLinus Torvalds mbuf[k++] = inb(tmport); 17901da177e4SLinus Torvalds tmport += 0x06; 17911da177e4SLinus Torvalds goto phase_ins1; 17921da177e4SLinus Torvalds } 17931da177e4SLinus Torvalds if ((j & 0x80) == 0x00) { 17941da177e4SLinus Torvalds goto phase_ins1; 17951da177e4SLinus Torvalds } 17961da177e4SLinus Torvalds tmport -= 0x08; 17971da177e4SLinus Torvalds 17981da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 17991da177e4SLinus Torvalds cpu_relax(); 18001da177e4SLinus Torvalds 18011da177e4SLinus Torvalds j = inb(tmport); 18021da177e4SLinus Torvalds if (j == 0x85) { 18031da177e4SLinus Torvalds goto tar_dcons; 18041da177e4SLinus Torvalds } 18051da177e4SLinus Torvalds j &= 0x0f; 18061da177e4SLinus Torvalds if (j == 0x0f) { 18071da177e4SLinus Torvalds goto phase_ins; 18081da177e4SLinus Torvalds } 18091da177e4SLinus Torvalds if (j == 0x0a) { 18101da177e4SLinus Torvalds goto phase_cmds; 18111da177e4SLinus Torvalds } 18121da177e4SLinus Torvalds if (j == 0x0e) { 18131da177e4SLinus Torvalds goto phase_outs; 18141da177e4SLinus Torvalds } 18151da177e4SLinus Torvalds continue; 18161da177e4SLinus Torvalds phase_cmds: 18171da177e4SLinus Torvalds tmport = wkport + 0x10; 18181da177e4SLinus Torvalds outb(0x30, tmport); 18191da177e4SLinus Torvalds tar_dcons: 18201da177e4SLinus Torvalds tmport = wkport + 0x14; 18211da177e4SLinus Torvalds outb(0x00, tmport); 18221da177e4SLinus Torvalds tmport += 0x04; 18231da177e4SLinus Torvalds outb(0x08, tmport); 18241da177e4SLinus Torvalds tmport += 0x07; 18251da177e4SLinus Torvalds 18261da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 18271da177e4SLinus Torvalds cpu_relax(); 18281da177e4SLinus Torvalds 18291da177e4SLinus Torvalds tmport -= 0x08; 18301da177e4SLinus Torvalds j = inb(tmport); 18311da177e4SLinus Torvalds if (j != 0x16) { 18321da177e4SLinus Torvalds continue; 18331da177e4SLinus Torvalds } 18341da177e4SLinus Torvalds if (mbuf[0] != 0x01) { 18351da177e4SLinus Torvalds continue; 18361da177e4SLinus Torvalds } 18371da177e4SLinus Torvalds if (mbuf[1] != 0x03) { 18381da177e4SLinus Torvalds continue; 18391da177e4SLinus Torvalds } 18401da177e4SLinus Torvalds if (mbuf[4] == 0x00) { 18411da177e4SLinus Torvalds continue; 18421da177e4SLinus Torvalds } 18431da177e4SLinus Torvalds if (mbuf[3] > 0x64) { 18441da177e4SLinus Torvalds continue; 18451da177e4SLinus Torvalds } 18461da177e4SLinus Torvalds if (mbuf[4] > 0x0c) { 18471da177e4SLinus Torvalds mbuf[4] = 0x0c; 18481da177e4SLinus Torvalds } 18491da177e4SLinus Torvalds dev->id[0][i].devsp = mbuf[4]; 18501da177e4SLinus Torvalds if ((mbuf[3] < 0x0d) && (rmb == 0)) { 18511da177e4SLinus Torvalds j = 0xa0; 18521da177e4SLinus Torvalds goto set_syn_ok; 18531da177e4SLinus Torvalds } 18541da177e4SLinus Torvalds if (mbuf[3] < 0x1a) { 18551da177e4SLinus Torvalds j = 0x20; 18561da177e4SLinus Torvalds goto set_syn_ok; 18571da177e4SLinus Torvalds } 18581da177e4SLinus Torvalds if (mbuf[3] < 0x33) { 18591da177e4SLinus Torvalds j = 0x40; 18601da177e4SLinus Torvalds goto set_syn_ok; 18611da177e4SLinus Torvalds } 18621da177e4SLinus Torvalds if (mbuf[3] < 0x4c) { 18631da177e4SLinus Torvalds j = 0x50; 18641da177e4SLinus Torvalds goto set_syn_ok; 18651da177e4SLinus Torvalds } 18661da177e4SLinus Torvalds j = 0x60; 18671da177e4SLinus Torvalds set_syn_ok: 18681da177e4SLinus Torvalds dev->id[0][i].devsp = (dev->id[0][i].devsp & 0x0f) | j; 18691da177e4SLinus Torvalds } 18701da177e4SLinus Torvalds tmport = wkport + 0x3a; 18711da177e4SLinus Torvalds outb((unsigned char) (inb(tmport) & 0xef), tmport); 18721da177e4SLinus Torvalds } 18731da177e4SLinus Torvalds 18741da177e4SLinus Torvalds static void is880(struct atp_unit *dev, unsigned int wkport) 18751da177e4SLinus Torvalds { 18761da177e4SLinus Torvalds unsigned int tmport; 18771da177e4SLinus Torvalds unsigned char i, j, k, rmb, n, lvdmode; 18781da177e4SLinus Torvalds unsigned short int m; 18791da177e4SLinus Torvalds static unsigned char mbuf[512]; 18801da177e4SLinus Torvalds static unsigned char satn[9] = { 0, 0, 0, 0, 0, 0, 0, 6, 6 }; 18811da177e4SLinus Torvalds static unsigned char inqd[9] = { 0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6 }; 18821da177e4SLinus Torvalds static unsigned char synn[6] = { 0x80, 1, 3, 1, 0x19, 0x0e }; 18831da177e4SLinus Torvalds unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e }; 18841da177e4SLinus Torvalds static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x19, 0x0e }; 18851da177e4SLinus Torvalds unsigned char synuw[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e }; 18861da177e4SLinus Torvalds static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 }; 18871da177e4SLinus Torvalds static unsigned char u3[9] = { 0x80, 1, 6, 4, 0x09, 00, 0x0e, 0x01, 0x02 }; 18881da177e4SLinus Torvalds 18891da177e4SLinus Torvalds lvdmode = inb(wkport + 0x3f) & 0x40; 18901da177e4SLinus Torvalds 18911da177e4SLinus Torvalds for (i = 0; i < 16; i++) { 18921da177e4SLinus Torvalds m = 1; 18931da177e4SLinus Torvalds m = m << i; 18941da177e4SLinus Torvalds if ((m & dev->active_id[0]) != 0) { 18951da177e4SLinus Torvalds continue; 18961da177e4SLinus Torvalds } 18971da177e4SLinus Torvalds if (i == dev->host_id[0]) { 18981da177e4SLinus Torvalds printk(KERN_INFO " ID: %2d Host Adapter\n", dev->host_id[0]); 18991da177e4SLinus Torvalds continue; 19001da177e4SLinus Torvalds } 19011da177e4SLinus Torvalds tmport = wkport + 0x5b; 19021da177e4SLinus Torvalds outb(0x01, tmport); 19031da177e4SLinus Torvalds tmport = wkport + 0x41; 19041da177e4SLinus Torvalds outb(0x08, tmport++); 19051da177e4SLinus Torvalds outb(0x7f, tmport++); 19061da177e4SLinus Torvalds outb(satn[0], tmport++); 19071da177e4SLinus Torvalds outb(satn[1], tmport++); 19081da177e4SLinus Torvalds outb(satn[2], tmport++); 19091da177e4SLinus Torvalds outb(satn[3], tmport++); 19101da177e4SLinus Torvalds outb(satn[4], tmport++); 19111da177e4SLinus Torvalds outb(satn[5], tmport++); 19121da177e4SLinus Torvalds tmport += 0x06; 19131da177e4SLinus Torvalds outb(0, tmport); 19141da177e4SLinus Torvalds tmport += 0x02; 19151da177e4SLinus Torvalds outb(dev->id[0][i].devsp, tmport++); 19161da177e4SLinus Torvalds outb(0, tmport++); 19171da177e4SLinus Torvalds outb(satn[6], tmport++); 19181da177e4SLinus Torvalds outb(satn[7], tmport++); 19191da177e4SLinus Torvalds j = i; 19201da177e4SLinus Torvalds if ((j & 0x08) != 0) { 19211da177e4SLinus Torvalds j = (j & 0x07) | 0x40; 19221da177e4SLinus Torvalds } 19231da177e4SLinus Torvalds outb(j, tmport); 19241da177e4SLinus Torvalds tmport += 0x03; 19251da177e4SLinus Torvalds outb(satn[8], tmport); 19261da177e4SLinus Torvalds tmport += 0x07; 19271da177e4SLinus Torvalds 19281da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 19291da177e4SLinus Torvalds cpu_relax(); 19301da177e4SLinus Torvalds 19311da177e4SLinus Torvalds tmport -= 0x08; 19321da177e4SLinus Torvalds if (inb(tmport) != 0x11 && inb(tmport) != 0x8e) 19331da177e4SLinus Torvalds continue; 19341da177e4SLinus Torvalds 19351da177e4SLinus Torvalds while (inb(tmport) != 0x8e) 19361da177e4SLinus Torvalds cpu_relax(); 19371da177e4SLinus Torvalds 19381da177e4SLinus Torvalds dev->active_id[0] |= m; 19391da177e4SLinus Torvalds 19401da177e4SLinus Torvalds tmport = wkport + 0x50; 19411da177e4SLinus Torvalds outb(0x30, tmport); 19421da177e4SLinus Torvalds tmport = wkport + 0x54; 19431da177e4SLinus Torvalds outb(0x00, tmport); 19441da177e4SLinus Torvalds 19451da177e4SLinus Torvalds phase_cmd: 19461da177e4SLinus Torvalds tmport = wkport + 0x58; 19471da177e4SLinus Torvalds outb(0x08, tmport); 19481da177e4SLinus Torvalds tmport += 0x07; 19491da177e4SLinus Torvalds 19501da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 19511da177e4SLinus Torvalds cpu_relax(); 19521da177e4SLinus Torvalds 19531da177e4SLinus Torvalds tmport -= 0x08; 19541da177e4SLinus Torvalds j = inb(tmport); 19551da177e4SLinus Torvalds if (j != 0x16) { 19561da177e4SLinus Torvalds tmport = wkport + 0x50; 19571da177e4SLinus Torvalds outb(0x41, tmport); 19581da177e4SLinus Torvalds goto phase_cmd; 19591da177e4SLinus Torvalds } 19601da177e4SLinus Torvalds sel_ok: 19611da177e4SLinus Torvalds tmport = wkport + 0x43; 19621da177e4SLinus Torvalds outb(inqd[0], tmport++); 19631da177e4SLinus Torvalds outb(inqd[1], tmport++); 19641da177e4SLinus Torvalds outb(inqd[2], tmport++); 19651da177e4SLinus Torvalds outb(inqd[3], tmport++); 19661da177e4SLinus Torvalds outb(inqd[4], tmport++); 19671da177e4SLinus Torvalds outb(inqd[5], tmport); 19681da177e4SLinus Torvalds tmport += 0x07; 19691da177e4SLinus Torvalds outb(0, tmport); 19701da177e4SLinus Torvalds tmport += 0x02; 19711da177e4SLinus Torvalds outb(dev->id[0][i].devsp, tmport++); 19721da177e4SLinus Torvalds outb(0, tmport++); 19731da177e4SLinus Torvalds outb(inqd[6], tmport++); 19741da177e4SLinus Torvalds outb(inqd[7], tmport++); 19751da177e4SLinus Torvalds tmport += 0x03; 19761da177e4SLinus Torvalds outb(inqd[8], tmport); 19771da177e4SLinus Torvalds tmport += 0x07; 19781da177e4SLinus Torvalds 19791da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 19801da177e4SLinus Torvalds cpu_relax(); 19811da177e4SLinus Torvalds 19821da177e4SLinus Torvalds tmport -= 0x08; 19831da177e4SLinus Torvalds if (inb(tmport) != 0x11 && inb(tmport) != 0x8e) 19841da177e4SLinus Torvalds continue; 19851da177e4SLinus Torvalds 19861da177e4SLinus Torvalds while (inb(tmport) != 0x8e) 19871da177e4SLinus Torvalds cpu_relax(); 19881da177e4SLinus Torvalds 19891da177e4SLinus Torvalds tmport = wkport + 0x5b; 19901da177e4SLinus Torvalds outb(0x00, tmport); 19911da177e4SLinus Torvalds tmport = wkport + 0x58; 19921da177e4SLinus Torvalds outb(0x08, tmport); 19931da177e4SLinus Torvalds tmport += 0x07; 19941da177e4SLinus Torvalds j = 0; 19951da177e4SLinus Torvalds rd_inq_data: 19961da177e4SLinus Torvalds k = inb(tmport); 19971da177e4SLinus Torvalds if ((k & 0x01) != 0) { 19981da177e4SLinus Torvalds tmport -= 0x06; 19991da177e4SLinus Torvalds mbuf[j++] = inb(tmport); 20001da177e4SLinus Torvalds tmport += 0x06; 20011da177e4SLinus Torvalds goto rd_inq_data; 20021da177e4SLinus Torvalds } 20031da177e4SLinus Torvalds if ((k & 0x80) == 0) { 20041da177e4SLinus Torvalds goto rd_inq_data; 20051da177e4SLinus Torvalds } 20061da177e4SLinus Torvalds tmport -= 0x08; 20071da177e4SLinus Torvalds j = inb(tmport); 20081da177e4SLinus Torvalds if (j == 0x16) { 20091da177e4SLinus Torvalds goto inq_ok; 20101da177e4SLinus Torvalds } 20111da177e4SLinus Torvalds tmport = wkport + 0x50; 20121da177e4SLinus Torvalds outb(0x46, tmport); 20131da177e4SLinus Torvalds tmport += 0x02; 20141da177e4SLinus Torvalds outb(0, tmport++); 20151da177e4SLinus Torvalds outb(0, tmport++); 20161da177e4SLinus Torvalds outb(0, tmport++); 20171da177e4SLinus Torvalds tmport += 0x03; 20181da177e4SLinus Torvalds outb(0x08, tmport); 20191da177e4SLinus Torvalds tmport += 0x07; 20201da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 20211da177e4SLinus Torvalds cpu_relax(); 20221da177e4SLinus Torvalds 20231da177e4SLinus Torvalds tmport -= 0x08; 20241da177e4SLinus Torvalds if (inb(tmport) != 0x16) 20251da177e4SLinus Torvalds goto sel_ok; 20261da177e4SLinus Torvalds 20271da177e4SLinus Torvalds inq_ok: 20281da177e4SLinus Torvalds mbuf[36] = 0; 20291da177e4SLinus Torvalds printk(KERN_INFO " ID: %2d %s\n", i, &mbuf[8]); 20301da177e4SLinus Torvalds dev->id[0][i].devtype = mbuf[0]; 20311da177e4SLinus Torvalds rmb = mbuf[1]; 20321da177e4SLinus Torvalds n = mbuf[7]; 20331da177e4SLinus Torvalds if ((mbuf[7] & 0x60) == 0) { 20341da177e4SLinus Torvalds goto not_wide; 20351da177e4SLinus Torvalds } 20361da177e4SLinus Torvalds if ((i < 8) && ((dev->global_map[0] & 0x20) == 0)) { 20371da177e4SLinus Torvalds goto not_wide; 20381da177e4SLinus Torvalds } 20391da177e4SLinus Torvalds if (lvdmode == 0) { 20401da177e4SLinus Torvalds goto chg_wide; 20411da177e4SLinus Torvalds } 20421da177e4SLinus Torvalds if (dev->sp[0][i] != 0x04) // force u2 20431da177e4SLinus Torvalds { 20441da177e4SLinus Torvalds goto chg_wide; 20451da177e4SLinus Torvalds } 20461da177e4SLinus Torvalds 20471da177e4SLinus Torvalds tmport = wkport + 0x5b; 20481da177e4SLinus Torvalds outb(0x01, tmport); 20491da177e4SLinus Torvalds tmport = wkport + 0x43; 20501da177e4SLinus Torvalds outb(satn[0], tmport++); 20511da177e4SLinus Torvalds outb(satn[1], tmport++); 20521da177e4SLinus Torvalds outb(satn[2], tmport++); 20531da177e4SLinus Torvalds outb(satn[3], tmport++); 20541da177e4SLinus Torvalds outb(satn[4], tmport++); 20551da177e4SLinus Torvalds outb(satn[5], tmport++); 20561da177e4SLinus Torvalds tmport += 0x06; 20571da177e4SLinus Torvalds outb(0, tmport); 20581da177e4SLinus Torvalds tmport += 0x02; 20591da177e4SLinus Torvalds outb(dev->id[0][i].devsp, tmport++); 20601da177e4SLinus Torvalds outb(0, tmport++); 20611da177e4SLinus Torvalds outb(satn[6], tmport++); 20621da177e4SLinus Torvalds outb(satn[7], tmport++); 20631da177e4SLinus Torvalds tmport += 0x03; 20641da177e4SLinus Torvalds outb(satn[8], tmport); 20651da177e4SLinus Torvalds tmport += 0x07; 20661da177e4SLinus Torvalds 20671da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 20681da177e4SLinus Torvalds cpu_relax(); 20691da177e4SLinus Torvalds 20701da177e4SLinus Torvalds tmport -= 0x08; 20711da177e4SLinus Torvalds 20721da177e4SLinus Torvalds if (inb(tmport) != 0x11 && inb(tmport) != 0x8e) 20731da177e4SLinus Torvalds continue; 20741da177e4SLinus Torvalds 20751da177e4SLinus Torvalds while (inb(tmport) != 0x8e) 20761da177e4SLinus Torvalds cpu_relax(); 20771da177e4SLinus Torvalds 20781da177e4SLinus Torvalds try_u3: 20791da177e4SLinus Torvalds j = 0; 20801da177e4SLinus Torvalds tmport = wkport + 0x54; 20811da177e4SLinus Torvalds outb(0x09, tmport); 20821da177e4SLinus Torvalds tmport += 0x04; 20831da177e4SLinus Torvalds outb(0x20, tmport); 20841da177e4SLinus Torvalds tmport += 0x07; 20851da177e4SLinus Torvalds 20861da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0) { 20871da177e4SLinus Torvalds if ((inb(tmport) & 0x01) != 0) { 20881da177e4SLinus Torvalds tmport -= 0x06; 20891da177e4SLinus Torvalds outb(u3[j++], tmport); 20901da177e4SLinus Torvalds tmport += 0x06; 20911da177e4SLinus Torvalds } 20921da177e4SLinus Torvalds } 20931da177e4SLinus Torvalds tmport -= 0x08; 20941da177e4SLinus Torvalds 20951da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 20961da177e4SLinus Torvalds cpu_relax(); 20971da177e4SLinus Torvalds 20981da177e4SLinus Torvalds j = inb(tmport) & 0x0f; 20991da177e4SLinus Torvalds if (j == 0x0f) { 21001da177e4SLinus Torvalds goto u3p_in; 21011da177e4SLinus Torvalds } 21021da177e4SLinus Torvalds if (j == 0x0a) { 21031da177e4SLinus Torvalds goto u3p_cmd; 21041da177e4SLinus Torvalds } 21051da177e4SLinus Torvalds if (j == 0x0e) { 21061da177e4SLinus Torvalds goto try_u3; 21071da177e4SLinus Torvalds } 21081da177e4SLinus Torvalds continue; 21091da177e4SLinus Torvalds u3p_out: 21101da177e4SLinus Torvalds tmport = wkport + 0x58; 21111da177e4SLinus Torvalds outb(0x20, tmport); 21121da177e4SLinus Torvalds tmport += 0x07; 21131da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0) { 21141da177e4SLinus Torvalds if ((inb(tmport) & 0x01) != 0) { 21151da177e4SLinus Torvalds tmport -= 0x06; 21161da177e4SLinus Torvalds outb(0, tmport); 21171da177e4SLinus Torvalds tmport += 0x06; 21181da177e4SLinus Torvalds } 21191da177e4SLinus Torvalds } 21201da177e4SLinus Torvalds tmport -= 0x08; 21211da177e4SLinus Torvalds j = inb(tmport) & 0x0f; 21221da177e4SLinus Torvalds if (j == 0x0f) { 21231da177e4SLinus Torvalds goto u3p_in; 21241da177e4SLinus Torvalds } 21251da177e4SLinus Torvalds if (j == 0x0a) { 21261da177e4SLinus Torvalds goto u3p_cmd; 21271da177e4SLinus Torvalds } 21281da177e4SLinus Torvalds if (j == 0x0e) { 21291da177e4SLinus Torvalds goto u3p_out; 21301da177e4SLinus Torvalds } 21311da177e4SLinus Torvalds continue; 21321da177e4SLinus Torvalds u3p_in: 21331da177e4SLinus Torvalds tmport = wkport + 0x54; 21341da177e4SLinus Torvalds outb(0x09, tmport); 21351da177e4SLinus Torvalds tmport += 0x04; 21361da177e4SLinus Torvalds outb(0x20, tmport); 21371da177e4SLinus Torvalds tmport += 0x07; 21381da177e4SLinus Torvalds k = 0; 21391da177e4SLinus Torvalds u3p_in1: 21401da177e4SLinus Torvalds j = inb(tmport); 21411da177e4SLinus Torvalds if ((j & 0x01) != 0) { 21421da177e4SLinus Torvalds tmport -= 0x06; 21431da177e4SLinus Torvalds mbuf[k++] = inb(tmport); 21441da177e4SLinus Torvalds tmport += 0x06; 21451da177e4SLinus Torvalds goto u3p_in1; 21461da177e4SLinus Torvalds } 21471da177e4SLinus Torvalds if ((j & 0x80) == 0x00) { 21481da177e4SLinus Torvalds goto u3p_in1; 21491da177e4SLinus Torvalds } 21501da177e4SLinus Torvalds tmport -= 0x08; 21511da177e4SLinus Torvalds j = inb(tmport) & 0x0f; 21521da177e4SLinus Torvalds if (j == 0x0f) { 21531da177e4SLinus Torvalds goto u3p_in; 21541da177e4SLinus Torvalds } 21551da177e4SLinus Torvalds if (j == 0x0a) { 21561da177e4SLinus Torvalds goto u3p_cmd; 21571da177e4SLinus Torvalds } 21581da177e4SLinus Torvalds if (j == 0x0e) { 21591da177e4SLinus Torvalds goto u3p_out; 21601da177e4SLinus Torvalds } 21611da177e4SLinus Torvalds continue; 21621da177e4SLinus Torvalds u3p_cmd: 21631da177e4SLinus Torvalds tmport = wkport + 0x50; 21641da177e4SLinus Torvalds outb(0x30, tmport); 21651da177e4SLinus Torvalds tmport = wkport + 0x54; 21661da177e4SLinus Torvalds outb(0x00, tmport); 21671da177e4SLinus Torvalds tmport += 0x04; 21681da177e4SLinus Torvalds outb(0x08, tmport); 21691da177e4SLinus Torvalds tmport += 0x07; 21701da177e4SLinus Torvalds 21711da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 21721da177e4SLinus Torvalds cpu_relax(); 21731da177e4SLinus Torvalds 21741da177e4SLinus Torvalds tmport -= 0x08; 21751da177e4SLinus Torvalds j = inb(tmport); 21761da177e4SLinus Torvalds if (j != 0x16) { 21771da177e4SLinus Torvalds if (j == 0x4e) { 21781da177e4SLinus Torvalds goto u3p_out; 21791da177e4SLinus Torvalds } 21801da177e4SLinus Torvalds continue; 21811da177e4SLinus Torvalds } 21821da177e4SLinus Torvalds if (mbuf[0] != 0x01) { 21831da177e4SLinus Torvalds goto chg_wide; 21841da177e4SLinus Torvalds } 21851da177e4SLinus Torvalds if (mbuf[1] != 0x06) { 21861da177e4SLinus Torvalds goto chg_wide; 21871da177e4SLinus Torvalds } 21881da177e4SLinus Torvalds if (mbuf[2] != 0x04) { 21891da177e4SLinus Torvalds goto chg_wide; 21901da177e4SLinus Torvalds } 21911da177e4SLinus Torvalds if (mbuf[3] == 0x09) { 21921da177e4SLinus Torvalds m = 1; 21931da177e4SLinus Torvalds m = m << i; 21941da177e4SLinus Torvalds dev->wide_id[0] |= m; 21951da177e4SLinus Torvalds dev->id[0][i].devsp = 0xce; 21961da177e4SLinus Torvalds continue; 21971da177e4SLinus Torvalds } 21981da177e4SLinus Torvalds chg_wide: 21991da177e4SLinus Torvalds tmport = wkport + 0x5b; 22001da177e4SLinus Torvalds outb(0x01, tmport); 22011da177e4SLinus Torvalds tmport = wkport + 0x43; 22021da177e4SLinus Torvalds outb(satn[0], tmport++); 22031da177e4SLinus Torvalds outb(satn[1], tmport++); 22041da177e4SLinus Torvalds outb(satn[2], tmport++); 22051da177e4SLinus Torvalds outb(satn[3], tmport++); 22061da177e4SLinus Torvalds outb(satn[4], tmport++); 22071da177e4SLinus Torvalds outb(satn[5], tmport++); 22081da177e4SLinus Torvalds tmport += 0x06; 22091da177e4SLinus Torvalds outb(0, tmport); 22101da177e4SLinus Torvalds tmport += 0x02; 22111da177e4SLinus Torvalds outb(dev->id[0][i].devsp, tmport++); 22121da177e4SLinus Torvalds outb(0, tmport++); 22131da177e4SLinus Torvalds outb(satn[6], tmport++); 22141da177e4SLinus Torvalds outb(satn[7], tmport++); 22151da177e4SLinus Torvalds tmport += 0x03; 22161da177e4SLinus Torvalds outb(satn[8], tmport); 22171da177e4SLinus Torvalds tmport += 0x07; 22181da177e4SLinus Torvalds 22191da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 22201da177e4SLinus Torvalds cpu_relax(); 22211da177e4SLinus Torvalds 22221da177e4SLinus Torvalds tmport -= 0x08; 22231da177e4SLinus Torvalds if (inb(tmport) != 0x11 && inb(tmport) != 0x8e) 22241da177e4SLinus Torvalds continue; 22251da177e4SLinus Torvalds 22261da177e4SLinus Torvalds while (inb(tmport) != 0x8e) 22271da177e4SLinus Torvalds cpu_relax(); 22281da177e4SLinus Torvalds 22291da177e4SLinus Torvalds try_wide: 22301da177e4SLinus Torvalds j = 0; 22311da177e4SLinus Torvalds tmport = wkport + 0x54; 22321da177e4SLinus Torvalds outb(0x05, tmport); 22331da177e4SLinus Torvalds tmport += 0x04; 22341da177e4SLinus Torvalds outb(0x20, tmport); 22351da177e4SLinus Torvalds tmport += 0x07; 22361da177e4SLinus Torvalds 22371da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0) { 22381da177e4SLinus Torvalds if ((inb(tmport) & 0x01) != 0) { 22391da177e4SLinus Torvalds tmport -= 0x06; 22401da177e4SLinus Torvalds outb(wide[j++], tmport); 22411da177e4SLinus Torvalds tmport += 0x06; 22421da177e4SLinus Torvalds } 22431da177e4SLinus Torvalds } 22441da177e4SLinus Torvalds tmport -= 0x08; 22451da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 22461da177e4SLinus Torvalds cpu_relax(); 22471da177e4SLinus Torvalds 22481da177e4SLinus Torvalds j = inb(tmport) & 0x0f; 22491da177e4SLinus Torvalds if (j == 0x0f) { 22501da177e4SLinus Torvalds goto widep_in; 22511da177e4SLinus Torvalds } 22521da177e4SLinus Torvalds if (j == 0x0a) { 22531da177e4SLinus Torvalds goto widep_cmd; 22541da177e4SLinus Torvalds } 22551da177e4SLinus Torvalds if (j == 0x0e) { 22561da177e4SLinus Torvalds goto try_wide; 22571da177e4SLinus Torvalds } 22581da177e4SLinus Torvalds continue; 22591da177e4SLinus Torvalds widep_out: 22601da177e4SLinus Torvalds tmport = wkport + 0x58; 22611da177e4SLinus Torvalds outb(0x20, tmport); 22621da177e4SLinus Torvalds tmport += 0x07; 22631da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0) { 22641da177e4SLinus Torvalds if ((inb(tmport) & 0x01) != 0) { 22651da177e4SLinus Torvalds tmport -= 0x06; 22661da177e4SLinus Torvalds outb(0, tmport); 22671da177e4SLinus Torvalds tmport += 0x06; 22681da177e4SLinus Torvalds } 22691da177e4SLinus Torvalds } 22701da177e4SLinus Torvalds tmport -= 0x08; 22711da177e4SLinus Torvalds j = inb(tmport) & 0x0f; 22721da177e4SLinus Torvalds if (j == 0x0f) { 22731da177e4SLinus Torvalds goto widep_in; 22741da177e4SLinus Torvalds } 22751da177e4SLinus Torvalds if (j == 0x0a) { 22761da177e4SLinus Torvalds goto widep_cmd; 22771da177e4SLinus Torvalds } 22781da177e4SLinus Torvalds if (j == 0x0e) { 22791da177e4SLinus Torvalds goto widep_out; 22801da177e4SLinus Torvalds } 22811da177e4SLinus Torvalds continue; 22821da177e4SLinus Torvalds widep_in: 22831da177e4SLinus Torvalds tmport = wkport + 0x54; 22841da177e4SLinus Torvalds outb(0xff, tmport); 22851da177e4SLinus Torvalds tmport += 0x04; 22861da177e4SLinus Torvalds outb(0x20, tmport); 22871da177e4SLinus Torvalds tmport += 0x07; 22881da177e4SLinus Torvalds k = 0; 22891da177e4SLinus Torvalds widep_in1: 22901da177e4SLinus Torvalds j = inb(tmport); 22911da177e4SLinus Torvalds if ((j & 0x01) != 0) { 22921da177e4SLinus Torvalds tmport -= 0x06; 22931da177e4SLinus Torvalds mbuf[k++] = inb(tmport); 22941da177e4SLinus Torvalds tmport += 0x06; 22951da177e4SLinus Torvalds goto widep_in1; 22961da177e4SLinus Torvalds } 22971da177e4SLinus Torvalds if ((j & 0x80) == 0x00) { 22981da177e4SLinus Torvalds goto widep_in1; 22991da177e4SLinus Torvalds } 23001da177e4SLinus Torvalds tmport -= 0x08; 23011da177e4SLinus Torvalds j = inb(tmport) & 0x0f; 23021da177e4SLinus Torvalds if (j == 0x0f) { 23031da177e4SLinus Torvalds goto widep_in; 23041da177e4SLinus Torvalds } 23051da177e4SLinus Torvalds if (j == 0x0a) { 23061da177e4SLinus Torvalds goto widep_cmd; 23071da177e4SLinus Torvalds } 23081da177e4SLinus Torvalds if (j == 0x0e) { 23091da177e4SLinus Torvalds goto widep_out; 23101da177e4SLinus Torvalds } 23111da177e4SLinus Torvalds continue; 23121da177e4SLinus Torvalds widep_cmd: 23131da177e4SLinus Torvalds tmport = wkport + 0x50; 23141da177e4SLinus Torvalds outb(0x30, tmport); 23151da177e4SLinus Torvalds tmport = wkport + 0x54; 23161da177e4SLinus Torvalds outb(0x00, tmport); 23171da177e4SLinus Torvalds tmport += 0x04; 23181da177e4SLinus Torvalds outb(0x08, tmport); 23191da177e4SLinus Torvalds tmport += 0x07; 23201da177e4SLinus Torvalds 23211da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 23221da177e4SLinus Torvalds cpu_relax(); 23231da177e4SLinus Torvalds 23241da177e4SLinus Torvalds tmport -= 0x08; 23251da177e4SLinus Torvalds j = inb(tmport); 23261da177e4SLinus Torvalds if (j != 0x16) { 23271da177e4SLinus Torvalds if (j == 0x4e) { 23281da177e4SLinus Torvalds goto widep_out; 23291da177e4SLinus Torvalds } 23301da177e4SLinus Torvalds continue; 23311da177e4SLinus Torvalds } 23321da177e4SLinus Torvalds if (mbuf[0] != 0x01) { 23331da177e4SLinus Torvalds goto not_wide; 23341da177e4SLinus Torvalds } 23351da177e4SLinus Torvalds if (mbuf[1] != 0x02) { 23361da177e4SLinus Torvalds goto not_wide; 23371da177e4SLinus Torvalds } 23381da177e4SLinus Torvalds if (mbuf[2] != 0x03) { 23391da177e4SLinus Torvalds goto not_wide; 23401da177e4SLinus Torvalds } 23411da177e4SLinus Torvalds if (mbuf[3] != 0x01) { 23421da177e4SLinus Torvalds goto not_wide; 23431da177e4SLinus Torvalds } 23441da177e4SLinus Torvalds m = 1; 23451da177e4SLinus Torvalds m = m << i; 23461da177e4SLinus Torvalds dev->wide_id[0] |= m; 23471da177e4SLinus Torvalds not_wide: 23481da177e4SLinus Torvalds if ((dev->id[0][i].devtype == 0x00) || (dev->id[0][i].devtype == 0x07) || ((dev->id[0][i].devtype == 0x05) && ((n & 0x10) != 0))) { 23491da177e4SLinus Torvalds m = 1; 23501da177e4SLinus Torvalds m = m << i; 23511da177e4SLinus Torvalds if ((dev->async[0] & m) != 0) { 23521da177e4SLinus Torvalds goto set_sync; 23531da177e4SLinus Torvalds } 23541da177e4SLinus Torvalds } 23551da177e4SLinus Torvalds continue; 23561da177e4SLinus Torvalds set_sync: 23571da177e4SLinus Torvalds if (dev->sp[0][i] == 0x02) { 23581da177e4SLinus Torvalds synu[4] = 0x0c; 23591da177e4SLinus Torvalds synuw[4] = 0x0c; 23601da177e4SLinus Torvalds } else { 23611da177e4SLinus Torvalds if (dev->sp[0][i] >= 0x03) { 23621da177e4SLinus Torvalds synu[4] = 0x0a; 23631da177e4SLinus Torvalds synuw[4] = 0x0a; 23641da177e4SLinus Torvalds } 23651da177e4SLinus Torvalds } 23661da177e4SLinus Torvalds tmport = wkport + 0x5b; 23671da177e4SLinus Torvalds j = 0; 23681da177e4SLinus Torvalds if ((m & dev->wide_id[0]) != 0) { 23691da177e4SLinus Torvalds j |= 0x01; 23701da177e4SLinus Torvalds } 23711da177e4SLinus Torvalds outb(j, tmport); 23721da177e4SLinus Torvalds tmport = wkport + 0x43; 23731da177e4SLinus Torvalds outb(satn[0], tmport++); 23741da177e4SLinus Torvalds outb(satn[1], tmport++); 23751da177e4SLinus Torvalds outb(satn[2], tmport++); 23761da177e4SLinus Torvalds outb(satn[3], tmport++); 23771da177e4SLinus Torvalds outb(satn[4], tmport++); 23781da177e4SLinus Torvalds outb(satn[5], tmport++); 23791da177e4SLinus Torvalds tmport += 0x06; 23801da177e4SLinus Torvalds outb(0, tmport); 23811da177e4SLinus Torvalds tmport += 0x02; 23821da177e4SLinus Torvalds outb(dev->id[0][i].devsp, tmport++); 23831da177e4SLinus Torvalds outb(0, tmport++); 23841da177e4SLinus Torvalds outb(satn[6], tmport++); 23851da177e4SLinus Torvalds outb(satn[7], tmport++); 23861da177e4SLinus Torvalds tmport += 0x03; 23871da177e4SLinus Torvalds outb(satn[8], tmport); 23881da177e4SLinus Torvalds tmport += 0x07; 23891da177e4SLinus Torvalds 23901da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 23911da177e4SLinus Torvalds cpu_relax(); 23921da177e4SLinus Torvalds 23931da177e4SLinus Torvalds tmport -= 0x08; 23941da177e4SLinus Torvalds if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) { 23951da177e4SLinus Torvalds continue; 23961da177e4SLinus Torvalds } 23971da177e4SLinus Torvalds while (inb(tmport) != 0x8e) 23981da177e4SLinus Torvalds cpu_relax(); 23991da177e4SLinus Torvalds 24001da177e4SLinus Torvalds try_sync: 24011da177e4SLinus Torvalds j = 0; 24021da177e4SLinus Torvalds tmport = wkport + 0x54; 24031da177e4SLinus Torvalds outb(0x06, tmport); 24041da177e4SLinus Torvalds tmport += 0x04; 24051da177e4SLinus Torvalds outb(0x20, tmport); 24061da177e4SLinus Torvalds tmport += 0x07; 24071da177e4SLinus Torvalds 24081da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0) { 24091da177e4SLinus Torvalds if ((inb(tmport) & 0x01) != 0) { 24101da177e4SLinus Torvalds tmport -= 0x06; 24111da177e4SLinus Torvalds if ((m & dev->wide_id[0]) != 0) { 24121da177e4SLinus Torvalds if ((m & dev->ultra_map[0]) != 0) { 24131da177e4SLinus Torvalds outb(synuw[j++], tmport); 24141da177e4SLinus Torvalds } else { 24151da177e4SLinus Torvalds outb(synw[j++], tmport); 24161da177e4SLinus Torvalds } 24171da177e4SLinus Torvalds } else { 24181da177e4SLinus Torvalds if ((m & dev->ultra_map[0]) != 0) { 24191da177e4SLinus Torvalds outb(synu[j++], tmport); 24201da177e4SLinus Torvalds } else { 24211da177e4SLinus Torvalds outb(synn[j++], tmport); 24221da177e4SLinus Torvalds } 24231da177e4SLinus Torvalds } 24241da177e4SLinus Torvalds tmport += 0x06; 24251da177e4SLinus Torvalds } 24261da177e4SLinus Torvalds } 24271da177e4SLinus Torvalds tmport -= 0x08; 24281da177e4SLinus Torvalds 24291da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 24301da177e4SLinus Torvalds cpu_relax(); 24311da177e4SLinus Torvalds 24321da177e4SLinus Torvalds j = inb(tmport) & 0x0f; 24331da177e4SLinus Torvalds if (j == 0x0f) { 24341da177e4SLinus Torvalds goto phase_ins; 24351da177e4SLinus Torvalds } 24361da177e4SLinus Torvalds if (j == 0x0a) { 24371da177e4SLinus Torvalds goto phase_cmds; 24381da177e4SLinus Torvalds } 24391da177e4SLinus Torvalds if (j == 0x0e) { 24401da177e4SLinus Torvalds goto try_sync; 24411da177e4SLinus Torvalds } 24421da177e4SLinus Torvalds continue; 24431da177e4SLinus Torvalds phase_outs: 24441da177e4SLinus Torvalds tmport = wkport + 0x58; 24451da177e4SLinus Torvalds outb(0x20, tmport); 24461da177e4SLinus Torvalds tmport += 0x07; 24471da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) { 24481da177e4SLinus Torvalds if ((inb(tmport) & 0x01) != 0x00) { 24491da177e4SLinus Torvalds tmport -= 0x06; 24501da177e4SLinus Torvalds outb(0x00, tmport); 24511da177e4SLinus Torvalds tmport += 0x06; 24521da177e4SLinus Torvalds } 24531da177e4SLinus Torvalds } 24541da177e4SLinus Torvalds tmport -= 0x08; 24551da177e4SLinus Torvalds j = inb(tmport); 24561da177e4SLinus Torvalds if (j == 0x85) { 24571da177e4SLinus Torvalds goto tar_dcons; 24581da177e4SLinus Torvalds } 24591da177e4SLinus Torvalds j &= 0x0f; 24601da177e4SLinus Torvalds if (j == 0x0f) { 24611da177e4SLinus Torvalds goto phase_ins; 24621da177e4SLinus Torvalds } 24631da177e4SLinus Torvalds if (j == 0x0a) { 24641da177e4SLinus Torvalds goto phase_cmds; 24651da177e4SLinus Torvalds } 24661da177e4SLinus Torvalds if (j == 0x0e) { 24671da177e4SLinus Torvalds goto phase_outs; 24681da177e4SLinus Torvalds } 24691da177e4SLinus Torvalds continue; 24701da177e4SLinus Torvalds phase_ins: 24711da177e4SLinus Torvalds tmport = wkport + 0x54; 24721da177e4SLinus Torvalds outb(0x06, tmport); 24731da177e4SLinus Torvalds tmport += 0x04; 24741da177e4SLinus Torvalds outb(0x20, tmport); 24751da177e4SLinus Torvalds tmport += 0x07; 24761da177e4SLinus Torvalds k = 0; 24771da177e4SLinus Torvalds phase_ins1: 24781da177e4SLinus Torvalds j = inb(tmport); 24791da177e4SLinus Torvalds if ((j & 0x01) != 0x00) { 24801da177e4SLinus Torvalds tmport -= 0x06; 24811da177e4SLinus Torvalds mbuf[k++] = inb(tmport); 24821da177e4SLinus Torvalds tmport += 0x06; 24831da177e4SLinus Torvalds goto phase_ins1; 24841da177e4SLinus Torvalds } 24851da177e4SLinus Torvalds if ((j & 0x80) == 0x00) { 24861da177e4SLinus Torvalds goto phase_ins1; 24871da177e4SLinus Torvalds } 24881da177e4SLinus Torvalds tmport -= 0x08; 24891da177e4SLinus Torvalds 24901da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 24911da177e4SLinus Torvalds cpu_relax(); 24921da177e4SLinus Torvalds 24931da177e4SLinus Torvalds j = inb(tmport); 24941da177e4SLinus Torvalds if (j == 0x85) { 24951da177e4SLinus Torvalds goto tar_dcons; 24961da177e4SLinus Torvalds } 24971da177e4SLinus Torvalds j &= 0x0f; 24981da177e4SLinus Torvalds if (j == 0x0f) { 24991da177e4SLinus Torvalds goto phase_ins; 25001da177e4SLinus Torvalds } 25011da177e4SLinus Torvalds if (j == 0x0a) { 25021da177e4SLinus Torvalds goto phase_cmds; 25031da177e4SLinus Torvalds } 25041da177e4SLinus Torvalds if (j == 0x0e) { 25051da177e4SLinus Torvalds goto phase_outs; 25061da177e4SLinus Torvalds } 25071da177e4SLinus Torvalds continue; 25081da177e4SLinus Torvalds phase_cmds: 25091da177e4SLinus Torvalds tmport = wkport + 0x50; 25101da177e4SLinus Torvalds outb(0x30, tmport); 25111da177e4SLinus Torvalds tar_dcons: 25121da177e4SLinus Torvalds tmport = wkport + 0x54; 25131da177e4SLinus Torvalds outb(0x00, tmport); 25141da177e4SLinus Torvalds tmport += 0x04; 25151da177e4SLinus Torvalds outb(0x08, tmport); 25161da177e4SLinus Torvalds tmport += 0x07; 25171da177e4SLinus Torvalds 25181da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 25191da177e4SLinus Torvalds cpu_relax(); 25201da177e4SLinus Torvalds 25211da177e4SLinus Torvalds tmport -= 0x08; 25221da177e4SLinus Torvalds j = inb(tmport); 25231da177e4SLinus Torvalds if (j != 0x16) { 25241da177e4SLinus Torvalds continue; 25251da177e4SLinus Torvalds } 25261da177e4SLinus Torvalds if (mbuf[0] != 0x01) { 25271da177e4SLinus Torvalds continue; 25281da177e4SLinus Torvalds } 25291da177e4SLinus Torvalds if (mbuf[1] != 0x03) { 25301da177e4SLinus Torvalds continue; 25311da177e4SLinus Torvalds } 25321da177e4SLinus Torvalds if (mbuf[4] == 0x00) { 25331da177e4SLinus Torvalds continue; 25341da177e4SLinus Torvalds } 25351da177e4SLinus Torvalds if (mbuf[3] > 0x64) { 25361da177e4SLinus Torvalds continue; 25371da177e4SLinus Torvalds } 25381da177e4SLinus Torvalds if (mbuf[4] > 0x0e) { 25391da177e4SLinus Torvalds mbuf[4] = 0x0e; 25401da177e4SLinus Torvalds } 25411da177e4SLinus Torvalds dev->id[0][i].devsp = mbuf[4]; 25421da177e4SLinus Torvalds if (mbuf[3] < 0x0c) { 25431da177e4SLinus Torvalds j = 0xb0; 25441da177e4SLinus Torvalds goto set_syn_ok; 25451da177e4SLinus Torvalds } 25461da177e4SLinus Torvalds if ((mbuf[3] < 0x0d) && (rmb == 0)) { 25471da177e4SLinus Torvalds j = 0xa0; 25481da177e4SLinus Torvalds goto set_syn_ok; 25491da177e4SLinus Torvalds } 25501da177e4SLinus Torvalds if (mbuf[3] < 0x1a) { 25511da177e4SLinus Torvalds j = 0x20; 25521da177e4SLinus Torvalds goto set_syn_ok; 25531da177e4SLinus Torvalds } 25541da177e4SLinus Torvalds if (mbuf[3] < 0x33) { 25551da177e4SLinus Torvalds j = 0x40; 25561da177e4SLinus Torvalds goto set_syn_ok; 25571da177e4SLinus Torvalds } 25581da177e4SLinus Torvalds if (mbuf[3] < 0x4c) { 25591da177e4SLinus Torvalds j = 0x50; 25601da177e4SLinus Torvalds goto set_syn_ok; 25611da177e4SLinus Torvalds } 25621da177e4SLinus Torvalds j = 0x60; 25631da177e4SLinus Torvalds set_syn_ok: 25641da177e4SLinus Torvalds dev->id[0][i].devsp = (dev->id[0][i].devsp & 0x0f) | j; 25651da177e4SLinus Torvalds } 25661da177e4SLinus Torvalds } 25671da177e4SLinus Torvalds 25681da177e4SLinus Torvalds static void atp870u_free_tables(struct Scsi_Host *host) 25691da177e4SLinus Torvalds { 25701da177e4SLinus Torvalds struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata; 25711da177e4SLinus Torvalds int j, k; 25721da177e4SLinus Torvalds for (j=0; j < 2; j++) { 25731da177e4SLinus Torvalds for (k = 0; k < 16; k++) { 25741da177e4SLinus Torvalds if (!atp_dev->id[j][k].prd_table) 25751da177e4SLinus Torvalds continue; 2576b5683557SJames Bottomley pci_free_consistent(atp_dev->pdev, 1024, atp_dev->id[j][k].prd_table, atp_dev->id[j][k].prd_bus); 25771da177e4SLinus Torvalds atp_dev->id[j][k].prd_table = NULL; 25781da177e4SLinus Torvalds } 25791da177e4SLinus Torvalds } 25801da177e4SLinus Torvalds } 25811da177e4SLinus Torvalds 25821da177e4SLinus Torvalds static int atp870u_init_tables(struct Scsi_Host *host) 25831da177e4SLinus Torvalds { 25841da177e4SLinus Torvalds struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata; 25851da177e4SLinus Torvalds int c,k; 25861da177e4SLinus Torvalds for(c=0;c < 2;c++) { 25871da177e4SLinus Torvalds for(k=0;k<16;k++) { 2588b5683557SJames Bottomley atp_dev->id[c][k].prd_table = pci_alloc_consistent(atp_dev->pdev, 1024, &(atp_dev->id[c][k].prd_bus)); 25891da177e4SLinus Torvalds if (!atp_dev->id[c][k].prd_table) { 25901da177e4SLinus Torvalds printk("atp870u_init_tables fail\n"); 25911da177e4SLinus Torvalds atp870u_free_tables(host); 25921da177e4SLinus Torvalds return -ENOMEM; 25931da177e4SLinus Torvalds } 2594b5683557SJames Bottomley atp_dev->id[c][k].prdaddr = atp_dev->id[c][k].prd_bus; 25951da177e4SLinus Torvalds atp_dev->id[c][k].devsp=0x20; 25961da177e4SLinus Torvalds atp_dev->id[c][k].devtype = 0x7f; 25971da177e4SLinus Torvalds atp_dev->id[c][k].curr_req = NULL; 25981da177e4SLinus Torvalds } 25991da177e4SLinus Torvalds 26001da177e4SLinus Torvalds atp_dev->active_id[c] = 0; 26011da177e4SLinus Torvalds atp_dev->wide_id[c] = 0; 26021da177e4SLinus Torvalds atp_dev->host_id[c] = 0x07; 26031da177e4SLinus Torvalds atp_dev->quhd[c] = 0; 26041da177e4SLinus Torvalds atp_dev->quend[c] = 0; 26051da177e4SLinus Torvalds atp_dev->last_cmd[c] = 0xff; 26061da177e4SLinus Torvalds atp_dev->in_snd[c] = 0; 26071da177e4SLinus Torvalds atp_dev->in_int[c] = 0; 26081da177e4SLinus Torvalds 26091da177e4SLinus Torvalds for (k = 0; k < qcnt; k++) { 26101da177e4SLinus Torvalds atp_dev->quereq[c][k] = NULL; 26111da177e4SLinus Torvalds } 26121da177e4SLinus Torvalds for (k = 0; k < 16; k++) { 26131da177e4SLinus Torvalds atp_dev->id[c][k].curr_req = NULL; 26141da177e4SLinus Torvalds atp_dev->sp[c][k] = 0x04; 26151da177e4SLinus Torvalds } 26161da177e4SLinus Torvalds } 26171da177e4SLinus Torvalds return 0; 26181da177e4SLinus Torvalds } 26191da177e4SLinus Torvalds 26201da177e4SLinus Torvalds /* return non-zero on detection */ 26211da177e4SLinus Torvalds static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 26221da177e4SLinus Torvalds { 26231da177e4SLinus Torvalds unsigned char k, m, c; 26241da177e4SLinus Torvalds unsigned long flags; 26251da177e4SLinus Torvalds unsigned int base_io, tmport, error,n; 26261da177e4SLinus Torvalds unsigned char host_id; 26271da177e4SLinus Torvalds struct Scsi_Host *shpnt = NULL; 26281da177e4SLinus Torvalds struct atp_unit atp_dev, *p; 26291da177e4SLinus Torvalds unsigned char setupdata[2][16]; 26301da177e4SLinus Torvalds int count = 0; 26311da177e4SLinus Torvalds 26321da177e4SLinus Torvalds if (pci_enable_device(pdev)) 26331da177e4SLinus Torvalds return -EIO; 26341da177e4SLinus Torvalds 2635910638aeSMatthias Gehre if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { 26361da177e4SLinus Torvalds printk(KERN_INFO "atp870u: use 32bit DMA mask.\n"); 26371da177e4SLinus Torvalds } else { 26381da177e4SLinus Torvalds printk(KERN_ERR "atp870u: DMA mask required but not available.\n"); 26391da177e4SLinus Torvalds return -EIO; 26401da177e4SLinus Torvalds } 26411da177e4SLinus Torvalds 26421da177e4SLinus Torvalds memset(&atp_dev, 0, sizeof atp_dev); 26431da177e4SLinus Torvalds /* 26441da177e4SLinus Torvalds * It's probably easier to weed out some revisions like 26451da177e4SLinus Torvalds * this than via the PCI device table 26461da177e4SLinus Torvalds */ 26471da177e4SLinus Torvalds if (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610) { 26481da177e4SLinus Torvalds error = pci_read_config_byte(pdev, PCI_CLASS_REVISION, &atp_dev.chip_ver); 26491da177e4SLinus Torvalds if (atp_dev.chip_ver < 2) 26501da177e4SLinus Torvalds return -EIO; 26511da177e4SLinus Torvalds } 26521da177e4SLinus Torvalds 26531da177e4SLinus Torvalds switch (ent->device) { 26541da177e4SLinus Torvalds case PCI_DEVICE_ID_ARTOP_AEC7612UW: 26551da177e4SLinus Torvalds case PCI_DEVICE_ID_ARTOP_AEC7612SUW: 26561da177e4SLinus Torvalds case ATP880_DEVID1: 26571da177e4SLinus Torvalds case ATP880_DEVID2: 26581da177e4SLinus Torvalds case ATP885_DEVID: 26591da177e4SLinus Torvalds atp_dev.chip_ver = 0x04; 26601da177e4SLinus Torvalds default: 26611da177e4SLinus Torvalds break; 26621da177e4SLinus Torvalds } 26631da177e4SLinus Torvalds base_io = pci_resource_start(pdev, 0); 26641da177e4SLinus Torvalds base_io &= 0xfffffff8; 26651da177e4SLinus Torvalds 26661da177e4SLinus Torvalds if ((ent->device == ATP880_DEVID1)||(ent->device == ATP880_DEVID2)) { 26671da177e4SLinus Torvalds error = pci_read_config_byte(pdev, PCI_CLASS_REVISION, &atp_dev.chip_ver); 26681da177e4SLinus Torvalds pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80);//JCC082803 26691da177e4SLinus Torvalds 26701da177e4SLinus Torvalds host_id = inb(base_io + 0x39); 26711da177e4SLinus Torvalds host_id >>= 0x04; 26721da177e4SLinus Torvalds 26731da177e4SLinus Torvalds printk(KERN_INFO " ACARD AEC-67160 PCI Ultra3 LVD Host Adapter: %d" 26741da177e4SLinus Torvalds " IO:%x, IRQ:%d.\n", count, base_io, pdev->irq); 26751da177e4SLinus Torvalds atp_dev.ioport[0] = base_io + 0x40; 26761da177e4SLinus Torvalds atp_dev.pciport[0] = base_io + 0x28; 26771da177e4SLinus Torvalds atp_dev.dev_id = ent->device; 26781da177e4SLinus Torvalds atp_dev.host_id[0] = host_id; 26791da177e4SLinus Torvalds 26801da177e4SLinus Torvalds tmport = base_io + 0x22; 26811da177e4SLinus Torvalds atp_dev.scam_on = inb(tmport); 26821da177e4SLinus Torvalds tmport += 0x13; 26831da177e4SLinus Torvalds atp_dev.global_map[0] = inb(tmport); 26841da177e4SLinus Torvalds tmport += 0x07; 26851da177e4SLinus Torvalds atp_dev.ultra_map[0] = inw(tmport); 26861da177e4SLinus Torvalds 26871da177e4SLinus Torvalds n = 0x3f09; 26881da177e4SLinus Torvalds next_fblk_880: 26891da177e4SLinus Torvalds if (n >= 0x4000) 26901da177e4SLinus Torvalds goto flash_ok_880; 26911da177e4SLinus Torvalds 26921da177e4SLinus Torvalds m = 0; 26931da177e4SLinus Torvalds outw(n, base_io + 0x34); 26941da177e4SLinus Torvalds n += 0x0002; 26951da177e4SLinus Torvalds if (inb(base_io + 0x30) == 0xff) 26961da177e4SLinus Torvalds goto flash_ok_880; 26971da177e4SLinus Torvalds 26981da177e4SLinus Torvalds atp_dev.sp[0][m++] = inb(base_io + 0x30); 26991da177e4SLinus Torvalds atp_dev.sp[0][m++] = inb(base_io + 0x31); 27001da177e4SLinus Torvalds atp_dev.sp[0][m++] = inb(base_io + 0x32); 27011da177e4SLinus Torvalds atp_dev.sp[0][m++] = inb(base_io + 0x33); 27021da177e4SLinus Torvalds outw(n, base_io + 0x34); 27031da177e4SLinus Torvalds n += 0x0002; 27041da177e4SLinus Torvalds atp_dev.sp[0][m++] = inb(base_io + 0x30); 27051da177e4SLinus Torvalds atp_dev.sp[0][m++] = inb(base_io + 0x31); 27061da177e4SLinus Torvalds atp_dev.sp[0][m++] = inb(base_io + 0x32); 27071da177e4SLinus Torvalds atp_dev.sp[0][m++] = inb(base_io + 0x33); 27081da177e4SLinus Torvalds outw(n, base_io + 0x34); 27091da177e4SLinus Torvalds n += 0x0002; 27101da177e4SLinus Torvalds atp_dev.sp[0][m++] = inb(base_io + 0x30); 27111da177e4SLinus Torvalds atp_dev.sp[0][m++] = inb(base_io + 0x31); 27121da177e4SLinus Torvalds atp_dev.sp[0][m++] = inb(base_io + 0x32); 27131da177e4SLinus Torvalds atp_dev.sp[0][m++] = inb(base_io + 0x33); 27141da177e4SLinus Torvalds outw(n, base_io + 0x34); 27151da177e4SLinus Torvalds n += 0x0002; 27161da177e4SLinus Torvalds atp_dev.sp[0][m++] = inb(base_io + 0x30); 27171da177e4SLinus Torvalds atp_dev.sp[0][m++] = inb(base_io + 0x31); 27181da177e4SLinus Torvalds atp_dev.sp[0][m++] = inb(base_io + 0x32); 27191da177e4SLinus Torvalds atp_dev.sp[0][m++] = inb(base_io + 0x33); 27201da177e4SLinus Torvalds n += 0x0018; 27211da177e4SLinus Torvalds goto next_fblk_880; 27221da177e4SLinus Torvalds flash_ok_880: 27231da177e4SLinus Torvalds outw(0, base_io + 0x34); 27241da177e4SLinus Torvalds atp_dev.ultra_map[0] = 0; 27251da177e4SLinus Torvalds atp_dev.async[0] = 0; 27261da177e4SLinus Torvalds for (k = 0; k < 16; k++) { 27271da177e4SLinus Torvalds n = 1; 27281da177e4SLinus Torvalds n = n << k; 27291da177e4SLinus Torvalds if (atp_dev.sp[0][k] > 1) { 27301da177e4SLinus Torvalds atp_dev.ultra_map[0] |= n; 27311da177e4SLinus Torvalds } else { 27321da177e4SLinus Torvalds if (atp_dev.sp[0][k] == 0) 27331da177e4SLinus Torvalds atp_dev.async[0] |= n; 27341da177e4SLinus Torvalds } 27351da177e4SLinus Torvalds } 27361da177e4SLinus Torvalds atp_dev.async[0] = ~(atp_dev.async[0]); 27371da177e4SLinus Torvalds outb(atp_dev.global_map[0], base_io + 0x35); 27381da177e4SLinus Torvalds 27391da177e4SLinus Torvalds shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit)); 27401da177e4SLinus Torvalds if (!shpnt) 27411da177e4SLinus Torvalds return -ENOMEM; 27421da177e4SLinus Torvalds 27431da177e4SLinus Torvalds p = (struct atp_unit *)&shpnt->hostdata; 27441da177e4SLinus Torvalds 27451da177e4SLinus Torvalds atp_dev.host = shpnt; 27461da177e4SLinus Torvalds atp_dev.pdev = pdev; 27471da177e4SLinus Torvalds pci_set_drvdata(pdev, p); 27481da177e4SLinus Torvalds memcpy(p, &atp_dev, sizeof atp_dev); 27491da177e4SLinus Torvalds if (atp870u_init_tables(shpnt) < 0) { 27501da177e4SLinus Torvalds printk(KERN_ERR "Unable to allocate tables for Acard controller\n"); 27511da177e4SLinus Torvalds goto unregister; 27521da177e4SLinus Torvalds } 27531da177e4SLinus Torvalds 27541d6f359aSThomas Gleixner if (request_irq(pdev->irq, atp870u_intr_handle, IRQF_SHARED, "atp880i", shpnt)) { 27551da177e4SLinus Torvalds printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", pdev->irq); 27561da177e4SLinus Torvalds goto free_tables; 27571da177e4SLinus Torvalds } 27581da177e4SLinus Torvalds 27591da177e4SLinus Torvalds spin_lock_irqsave(shpnt->host_lock, flags); 27601da177e4SLinus Torvalds tmport = base_io + 0x38; 27611da177e4SLinus Torvalds k = inb(tmport) & 0x80; 27621da177e4SLinus Torvalds outb(k, tmport); 27631da177e4SLinus Torvalds tmport += 0x03; 27641da177e4SLinus Torvalds outb(0x20, tmport); 27651da177e4SLinus Torvalds mdelay(32); 27661da177e4SLinus Torvalds outb(0, tmport); 27671da177e4SLinus Torvalds mdelay(32); 27681da177e4SLinus Torvalds tmport = base_io + 0x5b; 27691da177e4SLinus Torvalds inb(tmport); 27701da177e4SLinus Torvalds tmport -= 0x04; 27711da177e4SLinus Torvalds inb(tmport); 27721da177e4SLinus Torvalds tmport = base_io + 0x40; 27731da177e4SLinus Torvalds outb((host_id | 0x08), tmport); 27741da177e4SLinus Torvalds tmport += 0x18; 27751da177e4SLinus Torvalds outb(0, tmport); 27761da177e4SLinus Torvalds tmport += 0x07; 27771da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0) 27781da177e4SLinus Torvalds mdelay(1); 27791da177e4SLinus Torvalds tmport -= 0x08; 27801da177e4SLinus Torvalds inb(tmport); 27811da177e4SLinus Torvalds tmport = base_io + 0x41; 27821da177e4SLinus Torvalds outb(8, tmport++); 27831da177e4SLinus Torvalds outb(0x7f, tmport); 27841da177e4SLinus Torvalds tmport = base_io + 0x51; 27851da177e4SLinus Torvalds outb(0x20, tmport); 27861da177e4SLinus Torvalds 27871da177e4SLinus Torvalds tscam(shpnt); 27881da177e4SLinus Torvalds is880(p, base_io); 27891da177e4SLinus Torvalds tmport = base_io + 0x38; 27901da177e4SLinus Torvalds outb(0xb0, tmport); 27911da177e4SLinus Torvalds shpnt->max_id = 16; 27921da177e4SLinus Torvalds shpnt->this_id = host_id; 27931da177e4SLinus Torvalds shpnt->unique_id = base_io; 27941da177e4SLinus Torvalds shpnt->io_port = base_io; 27951da177e4SLinus Torvalds shpnt->n_io_port = 0x60; /* Number of bytes of I/O space used */ 27961da177e4SLinus Torvalds shpnt->irq = pdev->irq; 27971da177e4SLinus Torvalds } else if (ent->device == ATP885_DEVID) { 27981da177e4SLinus Torvalds printk(KERN_INFO " ACARD AEC-67162 PCI Ultra3 LVD Host Adapter: IO:%x, IRQ:%d.\n" 27991da177e4SLinus Torvalds , base_io, pdev->irq); 28001da177e4SLinus Torvalds 28011da177e4SLinus Torvalds atp_dev.pdev = pdev; 28021da177e4SLinus Torvalds atp_dev.dev_id = ent->device; 28031da177e4SLinus Torvalds atp_dev.baseport = base_io; 28041da177e4SLinus Torvalds atp_dev.ioport[0] = base_io + 0x80; 28051da177e4SLinus Torvalds atp_dev.ioport[1] = base_io + 0xc0; 28061da177e4SLinus Torvalds atp_dev.pciport[0] = base_io + 0x40; 28071da177e4SLinus Torvalds atp_dev.pciport[1] = base_io + 0x50; 28081da177e4SLinus Torvalds 28091da177e4SLinus Torvalds shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit)); 28101da177e4SLinus Torvalds if (!shpnt) 28111da177e4SLinus Torvalds return -ENOMEM; 28121da177e4SLinus Torvalds 28131da177e4SLinus Torvalds p = (struct atp_unit *)&shpnt->hostdata; 28141da177e4SLinus Torvalds 28151da177e4SLinus Torvalds atp_dev.host = shpnt; 28161da177e4SLinus Torvalds atp_dev.pdev = pdev; 28171da177e4SLinus Torvalds pci_set_drvdata(pdev, p); 28181da177e4SLinus Torvalds memcpy(p, &atp_dev, sizeof(struct atp_unit)); 28191da177e4SLinus Torvalds if (atp870u_init_tables(shpnt) < 0) 28201da177e4SLinus Torvalds goto unregister; 28211da177e4SLinus Torvalds 28221da177e4SLinus Torvalds #ifdef ED_DBGP 28231da177e4SLinus Torvalds printk("request_irq() shpnt %p hostdata %p\n", shpnt, p); 28241da177e4SLinus Torvalds #endif 28251d6f359aSThomas Gleixner if (request_irq(pdev->irq, atp870u_intr_handle, IRQF_SHARED, "atp870u", shpnt)) { 28261da177e4SLinus Torvalds printk(KERN_ERR "Unable to allocate IRQ for Acard controller.\n"); 28271da177e4SLinus Torvalds goto free_tables; 28281da177e4SLinus Torvalds } 28291da177e4SLinus Torvalds 28301da177e4SLinus Torvalds spin_lock_irqsave(shpnt->host_lock, flags); 28311da177e4SLinus Torvalds 28321da177e4SLinus Torvalds c=inb(base_io + 0x29); 28331da177e4SLinus Torvalds outb((c | 0x04),base_io + 0x29); 28341da177e4SLinus Torvalds 28351da177e4SLinus Torvalds n=0x1f80; 28361da177e4SLinus Torvalds next_fblk_885: 28371da177e4SLinus Torvalds if (n >= 0x2000) { 28381da177e4SLinus Torvalds goto flash_ok_885; 28391da177e4SLinus Torvalds } 28401da177e4SLinus Torvalds outw(n,base_io + 0x3c); 28411da177e4SLinus Torvalds if (inl(base_io + 0x38) == 0xffffffff) { 28421da177e4SLinus Torvalds goto flash_ok_885; 28431da177e4SLinus Torvalds } 28441da177e4SLinus Torvalds for (m=0; m < 2; m++) { 28451da177e4SLinus Torvalds p->global_map[m]= 0; 28461da177e4SLinus Torvalds for (k=0; k < 4; k++) { 28471da177e4SLinus Torvalds outw(n++,base_io + 0x3c); 28481da177e4SLinus Torvalds ((unsigned long *)&setupdata[m][0])[k]=inl(base_io + 0x38); 28491da177e4SLinus Torvalds } 28501da177e4SLinus Torvalds for (k=0; k < 4; k++) { 28511da177e4SLinus Torvalds outw(n++,base_io + 0x3c); 28521da177e4SLinus Torvalds ((unsigned long *)&p->sp[m][0])[k]=inl(base_io + 0x38); 28531da177e4SLinus Torvalds } 28541da177e4SLinus Torvalds n += 8; 28551da177e4SLinus Torvalds } 28561da177e4SLinus Torvalds goto next_fblk_885; 28571da177e4SLinus Torvalds flash_ok_885: 28581da177e4SLinus Torvalds #ifdef ED_DBGP 28591da177e4SLinus Torvalds printk( "Flash Read OK\n"); 28601da177e4SLinus Torvalds #endif 28611da177e4SLinus Torvalds c=inb(base_io + 0x29); 28621da177e4SLinus Torvalds outb((c & 0xfb),base_io + 0x29); 28631da177e4SLinus Torvalds for (c=0;c < 2;c++) { 28641da177e4SLinus Torvalds p->ultra_map[c]=0; 28651da177e4SLinus Torvalds p->async[c] = 0; 28661da177e4SLinus Torvalds for (k=0; k < 16; k++) { 28671da177e4SLinus Torvalds n=1; 28681da177e4SLinus Torvalds n = n << k; 28691da177e4SLinus Torvalds if (p->sp[c][k] > 1) { 28701da177e4SLinus Torvalds p->ultra_map[c] |= n; 28711da177e4SLinus Torvalds } else { 28721da177e4SLinus Torvalds if (p->sp[c][k] == 0) { 28731da177e4SLinus Torvalds p->async[c] |= n; 28741da177e4SLinus Torvalds } 28751da177e4SLinus Torvalds } 28761da177e4SLinus Torvalds } 28771da177e4SLinus Torvalds p->async[c] = ~(p->async[c]); 28781da177e4SLinus Torvalds 28791da177e4SLinus Torvalds if (p->global_map[c] == 0) { 28801da177e4SLinus Torvalds k=setupdata[c][1]; 28811da177e4SLinus Torvalds if ((k & 0x40) != 0) 28821da177e4SLinus Torvalds p->global_map[c] |= 0x20; 28831da177e4SLinus Torvalds k &= 0x07; 28841da177e4SLinus Torvalds p->global_map[c] |= k; 28851da177e4SLinus Torvalds if ((setupdata[c][2] & 0x04) != 0) 28861da177e4SLinus Torvalds p->global_map[c] |= 0x08; 28871da177e4SLinus Torvalds p->host_id[c] = setupdata[c][0] & 0x07; 28881da177e4SLinus Torvalds } 28891da177e4SLinus Torvalds } 28901da177e4SLinus Torvalds 28911da177e4SLinus Torvalds k = inb(base_io + 0x28) & 0x8f; 28921da177e4SLinus Torvalds k |= 0x10; 28931da177e4SLinus Torvalds outb(k, base_io + 0x28); 28941da177e4SLinus Torvalds outb(0x80, base_io + 0x41); 28951da177e4SLinus Torvalds outb(0x80, base_io + 0x51); 28961da177e4SLinus Torvalds mdelay(100); 28971da177e4SLinus Torvalds outb(0, base_io + 0x41); 28981da177e4SLinus Torvalds outb(0, base_io + 0x51); 28991da177e4SLinus Torvalds mdelay(1000); 29001da177e4SLinus Torvalds inb(base_io + 0x9b); 29011da177e4SLinus Torvalds inb(base_io + 0x97); 29021da177e4SLinus Torvalds inb(base_io + 0xdb); 29031da177e4SLinus Torvalds inb(base_io + 0xd7); 29041da177e4SLinus Torvalds tmport = base_io + 0x80; 29051da177e4SLinus Torvalds k=p->host_id[0]; 29061da177e4SLinus Torvalds if (k > 7) 29071da177e4SLinus Torvalds k = (k & 0x07) | 0x40; 29081da177e4SLinus Torvalds k |= 0x08; 29091da177e4SLinus Torvalds outb(k, tmport); 29101da177e4SLinus Torvalds tmport += 0x18; 29111da177e4SLinus Torvalds outb(0, tmport); 29121da177e4SLinus Torvalds tmport += 0x07; 29131da177e4SLinus Torvalds 29141da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0) 29151da177e4SLinus Torvalds cpu_relax(); 29161da177e4SLinus Torvalds 29171da177e4SLinus Torvalds tmport -= 0x08; 29181da177e4SLinus Torvalds inb(tmport); 29191da177e4SLinus Torvalds tmport = base_io + 0x81; 29201da177e4SLinus Torvalds outb(8, tmport++); 29211da177e4SLinus Torvalds outb(0x7f, tmport); 29221da177e4SLinus Torvalds tmport = base_io + 0x91; 29231da177e4SLinus Torvalds outb(0x20, tmport); 29241da177e4SLinus Torvalds 29251da177e4SLinus Torvalds tmport = base_io + 0xc0; 29261da177e4SLinus Torvalds k=p->host_id[1]; 29271da177e4SLinus Torvalds if (k > 7) 29281da177e4SLinus Torvalds k = (k & 0x07) | 0x40; 29291da177e4SLinus Torvalds k |= 0x08; 29301da177e4SLinus Torvalds outb(k, tmport); 29311da177e4SLinus Torvalds tmport += 0x18; 29321da177e4SLinus Torvalds outb(0, tmport); 29331da177e4SLinus Torvalds tmport += 0x07; 29341da177e4SLinus Torvalds 29351da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0) 29361da177e4SLinus Torvalds cpu_relax(); 29371da177e4SLinus Torvalds 29381da177e4SLinus Torvalds tmport -= 0x08; 29391da177e4SLinus Torvalds inb(tmport); 29401da177e4SLinus Torvalds tmport = base_io + 0xc1; 29411da177e4SLinus Torvalds outb(8, tmport++); 29421da177e4SLinus Torvalds outb(0x7f, tmport); 29431da177e4SLinus Torvalds tmport = base_io + 0xd1; 29441da177e4SLinus Torvalds outb(0x20, tmport); 29451da177e4SLinus Torvalds 29461da177e4SLinus Torvalds tscam_885(); 29471da177e4SLinus Torvalds printk(KERN_INFO " Scanning Channel A SCSI Device ...\n"); 29481da177e4SLinus Torvalds is885(p, base_io + 0x80, 0); 29491da177e4SLinus Torvalds printk(KERN_INFO " Scanning Channel B SCSI Device ...\n"); 29501da177e4SLinus Torvalds is885(p, base_io + 0xc0, 1); 29511da177e4SLinus Torvalds 29521da177e4SLinus Torvalds k = inb(base_io + 0x28) & 0xcf; 29531da177e4SLinus Torvalds k |= 0xc0; 29541da177e4SLinus Torvalds outb(k, base_io + 0x28); 29551da177e4SLinus Torvalds k = inb(base_io + 0x1f) | 0x80; 29561da177e4SLinus Torvalds outb(k, base_io + 0x1f); 29571da177e4SLinus Torvalds k = inb(base_io + 0x29) | 0x01; 29581da177e4SLinus Torvalds outb(k, base_io + 0x29); 29591da177e4SLinus Torvalds #ifdef ED_DBGP 29601da177e4SLinus Torvalds //printk("atp885: atp_host[0] 0x%p\n", atp_host[0]); 29611da177e4SLinus Torvalds #endif 29621da177e4SLinus Torvalds shpnt->max_id = 16; 29631da177e4SLinus Torvalds shpnt->max_lun = (p->global_map[0] & 0x07) + 1; 29641da177e4SLinus Torvalds shpnt->max_channel = 1; 29651da177e4SLinus Torvalds shpnt->this_id = p->host_id[0]; 29661da177e4SLinus Torvalds shpnt->unique_id = base_io; 29671da177e4SLinus Torvalds shpnt->io_port = base_io; 29681da177e4SLinus Torvalds shpnt->n_io_port = 0xff; /* Number of bytes of I/O space used */ 29691da177e4SLinus Torvalds shpnt->irq = pdev->irq; 29701da177e4SLinus Torvalds 29711da177e4SLinus Torvalds } else { 29721da177e4SLinus Torvalds error = pci_read_config_byte(pdev, 0x49, &host_id); 29731da177e4SLinus Torvalds 29741da177e4SLinus Torvalds printk(KERN_INFO " ACARD AEC-671X PCI Ultra/W SCSI-2/3 Host Adapter: %d " 29751da177e4SLinus Torvalds "IO:%x, IRQ:%d.\n", count, base_io, pdev->irq); 29761da177e4SLinus Torvalds 29771da177e4SLinus Torvalds atp_dev.ioport[0] = base_io; 29781da177e4SLinus Torvalds atp_dev.pciport[0] = base_io + 0x20; 29791da177e4SLinus Torvalds atp_dev.dev_id = ent->device; 29801da177e4SLinus Torvalds host_id &= 0x07; 29811da177e4SLinus Torvalds atp_dev.host_id[0] = host_id; 29821da177e4SLinus Torvalds tmport = base_io + 0x22; 29831da177e4SLinus Torvalds atp_dev.scam_on = inb(tmport); 29841da177e4SLinus Torvalds tmport += 0x0b; 29851da177e4SLinus Torvalds atp_dev.global_map[0] = inb(tmport++); 29861da177e4SLinus Torvalds atp_dev.ultra_map[0] = inw(tmport); 29871da177e4SLinus Torvalds 29881da177e4SLinus Torvalds if (atp_dev.ultra_map[0] == 0) { 29891da177e4SLinus Torvalds atp_dev.scam_on = 0x00; 29901da177e4SLinus Torvalds atp_dev.global_map[0] = 0x20; 29911da177e4SLinus Torvalds atp_dev.ultra_map[0] = 0xffff; 29921da177e4SLinus Torvalds } 29931da177e4SLinus Torvalds 29941da177e4SLinus Torvalds shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit)); 29951da177e4SLinus Torvalds if (!shpnt) 29961da177e4SLinus Torvalds return -ENOMEM; 29971da177e4SLinus Torvalds 29981da177e4SLinus Torvalds p = (struct atp_unit *)&shpnt->hostdata; 29991da177e4SLinus Torvalds 30001da177e4SLinus Torvalds atp_dev.host = shpnt; 30011da177e4SLinus Torvalds atp_dev.pdev = pdev; 30021da177e4SLinus Torvalds pci_set_drvdata(pdev, p); 30031da177e4SLinus Torvalds memcpy(p, &atp_dev, sizeof atp_dev); 30041da177e4SLinus Torvalds if (atp870u_init_tables(shpnt) < 0) 30051da177e4SLinus Torvalds goto unregister; 30061da177e4SLinus Torvalds 30071d6f359aSThomas Gleixner if (request_irq(pdev->irq, atp870u_intr_handle, IRQF_SHARED, "atp870i", shpnt)) { 30081da177e4SLinus Torvalds printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", pdev->irq); 30091da177e4SLinus Torvalds goto free_tables; 30101da177e4SLinus Torvalds } 30111da177e4SLinus Torvalds 30121da177e4SLinus Torvalds spin_lock_irqsave(shpnt->host_lock, flags); 30131da177e4SLinus Torvalds if (atp_dev.chip_ver > 0x07) { /* check if atp876 chip then enable terminator */ 30141da177e4SLinus Torvalds tmport = base_io + 0x3e; 30151da177e4SLinus Torvalds outb(0x00, tmport); 30161da177e4SLinus Torvalds } 30171da177e4SLinus Torvalds 30181da177e4SLinus Torvalds tmport = base_io + 0x3a; 30191da177e4SLinus Torvalds k = (inb(tmport) & 0xf3) | 0x10; 30201da177e4SLinus Torvalds outb(k, tmport); 30211da177e4SLinus Torvalds outb((k & 0xdf), tmport); 30221da177e4SLinus Torvalds mdelay(32); 30231da177e4SLinus Torvalds outb(k, tmport); 30241da177e4SLinus Torvalds mdelay(32); 30251da177e4SLinus Torvalds tmport = base_io; 30261da177e4SLinus Torvalds outb((host_id | 0x08), tmport); 30271da177e4SLinus Torvalds tmport += 0x18; 30281da177e4SLinus Torvalds outb(0, tmport); 30291da177e4SLinus Torvalds tmport += 0x07; 30301da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0) 30311da177e4SLinus Torvalds mdelay(1); 30321da177e4SLinus Torvalds 30331da177e4SLinus Torvalds tmport -= 0x08; 30341da177e4SLinus Torvalds inb(tmport); 30351da177e4SLinus Torvalds tmport = base_io + 1; 30361da177e4SLinus Torvalds outb(8, tmport++); 30371da177e4SLinus Torvalds outb(0x7f, tmport); 30381da177e4SLinus Torvalds tmport = base_io + 0x11; 30391da177e4SLinus Torvalds outb(0x20, tmport); 30401da177e4SLinus Torvalds 30411da177e4SLinus Torvalds tscam(shpnt); 30421da177e4SLinus Torvalds is870(p, base_io); 30431da177e4SLinus Torvalds tmport = base_io + 0x3a; 30441da177e4SLinus Torvalds outb((inb(tmport) & 0xef), tmport); 30451da177e4SLinus Torvalds tmport++; 30461da177e4SLinus Torvalds outb((inb(tmport) | 0x20), tmport); 30471da177e4SLinus Torvalds if (atp_dev.chip_ver == 4) 30481da177e4SLinus Torvalds shpnt->max_id = 16; 30491da177e4SLinus Torvalds else 30502b89dad0SHannes Reinecke shpnt->max_id = 8; 30511da177e4SLinus Torvalds shpnt->this_id = host_id; 30521da177e4SLinus Torvalds shpnt->unique_id = base_io; 30531da177e4SLinus Torvalds shpnt->io_port = base_io; 30541da177e4SLinus Torvalds shpnt->n_io_port = 0x40; /* Number of bytes of I/O space used */ 30551da177e4SLinus Torvalds shpnt->irq = pdev->irq; 30561da177e4SLinus Torvalds } 30571da177e4SLinus Torvalds spin_unlock_irqrestore(shpnt->host_lock, flags); 30581da177e4SLinus Torvalds if(ent->device==ATP885_DEVID) { 30591da177e4SLinus Torvalds if(!request_region(base_io, 0xff, "atp870u")) /* Register the IO ports that we use */ 30601da177e4SLinus Torvalds goto request_io_fail; 30611da177e4SLinus Torvalds } else if((ent->device==ATP880_DEVID1)||(ent->device==ATP880_DEVID2)) { 30621da177e4SLinus Torvalds if(!request_region(base_io, 0x60, "atp870u")) /* Register the IO ports that we use */ 30631da177e4SLinus Torvalds goto request_io_fail; 30641da177e4SLinus Torvalds } else { 30651da177e4SLinus Torvalds if(!request_region(base_io, 0x40, "atp870u")) /* Register the IO ports that we use */ 30661da177e4SLinus Torvalds goto request_io_fail; 30671da177e4SLinus Torvalds } 30681da177e4SLinus Torvalds count++; 30691da177e4SLinus Torvalds if (scsi_add_host(shpnt, &pdev->dev)) 30701da177e4SLinus Torvalds goto scsi_add_fail; 30711da177e4SLinus Torvalds scsi_scan_host(shpnt); 30721da177e4SLinus Torvalds #ifdef ED_DBGP 30731da177e4SLinus Torvalds printk("atp870u_prob : exit\n"); 30741da177e4SLinus Torvalds #endif 30751da177e4SLinus Torvalds return 0; 30761da177e4SLinus Torvalds 30771da177e4SLinus Torvalds scsi_add_fail: 30781da177e4SLinus Torvalds printk("atp870u_prob:scsi_add_fail\n"); 30791da177e4SLinus Torvalds if(ent->device==ATP885_DEVID) { 30801da177e4SLinus Torvalds release_region(base_io, 0xff); 30811da177e4SLinus Torvalds } else if((ent->device==ATP880_DEVID1)||(ent->device==ATP880_DEVID2)) { 30821da177e4SLinus Torvalds release_region(base_io, 0x60); 30831da177e4SLinus Torvalds } else { 30841da177e4SLinus Torvalds release_region(base_io, 0x40); 30851da177e4SLinus Torvalds } 30861da177e4SLinus Torvalds request_io_fail: 30871da177e4SLinus Torvalds printk("atp870u_prob:request_io_fail\n"); 30881da177e4SLinus Torvalds free_irq(pdev->irq, shpnt); 30891da177e4SLinus Torvalds free_tables: 30901da177e4SLinus Torvalds printk("atp870u_prob:free_table\n"); 30911da177e4SLinus Torvalds atp870u_free_tables(shpnt); 30921da177e4SLinus Torvalds unregister: 30931da177e4SLinus Torvalds printk("atp870u_prob:unregister\n"); 30941da177e4SLinus Torvalds scsi_host_put(shpnt); 30951da177e4SLinus Torvalds return -1; 30961da177e4SLinus Torvalds } 30971da177e4SLinus Torvalds 30981da177e4SLinus Torvalds /* The abort command does not leave the device in a clean state where 30991da177e4SLinus Torvalds it is available to be used again. Until this gets worked out, we will 31001da177e4SLinus Torvalds leave it commented out. */ 31011da177e4SLinus Torvalds 31021da177e4SLinus Torvalds static int atp870u_abort(struct scsi_cmnd * SCpnt) 31031da177e4SLinus Torvalds { 31041da177e4SLinus Torvalds unsigned char j, k, c; 31051da177e4SLinus Torvalds struct scsi_cmnd *workrequ; 31061da177e4SLinus Torvalds unsigned int tmport; 31071da177e4SLinus Torvalds struct atp_unit *dev; 31081da177e4SLinus Torvalds struct Scsi_Host *host; 31091da177e4SLinus Torvalds host = SCpnt->device->host; 31101da177e4SLinus Torvalds 31111da177e4SLinus Torvalds dev = (struct atp_unit *)&host->hostdata; 3112422c0d61SJeff Garzik c = scmd_channel(SCpnt); 31131da177e4SLinus Torvalds printk(" atp870u: abort Channel = %x \n", c); 31141da177e4SLinus Torvalds printk("working=%x last_cmd=%x ", dev->working[c], dev->last_cmd[c]); 31151da177e4SLinus Torvalds printk(" quhdu=%x quendu=%x ", dev->quhd[c], dev->quend[c]); 31161da177e4SLinus Torvalds tmport = dev->ioport[c]; 31171da177e4SLinus Torvalds for (j = 0; j < 0x18; j++) { 31181da177e4SLinus Torvalds printk(" r%2x=%2x", j, inb(tmport++)); 31191da177e4SLinus Torvalds } 31201da177e4SLinus Torvalds tmport += 0x04; 31211da177e4SLinus Torvalds printk(" r1c=%2x", inb(tmport)); 31221da177e4SLinus Torvalds tmport += 0x03; 31231da177e4SLinus Torvalds printk(" r1f=%2x in_snd=%2x ", inb(tmport), dev->in_snd[c]); 31241da177e4SLinus Torvalds tmport= dev->pciport[c]; 31251da177e4SLinus Torvalds printk(" d00=%2x", inb(tmport)); 31261da177e4SLinus Torvalds tmport += 0x02; 31271da177e4SLinus Torvalds printk(" d02=%2x", inb(tmport)); 31281da177e4SLinus Torvalds for(j=0;j<16;j++) { 31291da177e4SLinus Torvalds if (dev->id[c][j].curr_req != NULL) { 31301da177e4SLinus Torvalds workrequ = dev->id[c][j].curr_req; 31311da177e4SLinus Torvalds printk("\n que cdb= "); 31321da177e4SLinus Torvalds for (k=0; k < workrequ->cmd_len; k++) { 31331da177e4SLinus Torvalds printk(" %2x ",workrequ->cmnd[k]); 31341da177e4SLinus Torvalds } 31351da177e4SLinus Torvalds printk(" last_lenu= %x ",(unsigned int)dev->id[c][j].last_len); 31361da177e4SLinus Torvalds } 31371da177e4SLinus Torvalds } 31381da177e4SLinus Torvalds return SUCCESS; 31391da177e4SLinus Torvalds } 31401da177e4SLinus Torvalds 31411da177e4SLinus Torvalds static const char *atp870u_info(struct Scsi_Host *notused) 31421da177e4SLinus Torvalds { 31431da177e4SLinus Torvalds static char buffer[128]; 31441da177e4SLinus Torvalds 31451da177e4SLinus Torvalds strcpy(buffer, "ACARD AEC-6710/6712/67160 PCI Ultra/W/LVD SCSI-3 Adapter Driver V2.6+ac "); 31461da177e4SLinus Torvalds 31471da177e4SLinus Torvalds return buffer; 31481da177e4SLinus Torvalds } 31491da177e4SLinus Torvalds 31501da177e4SLinus Torvalds #define BLS buffer + len + size 3151420b4a73SAdrian Bunk static int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer, 31521da177e4SLinus Torvalds char **start, off_t offset, int length, int inout) 31531da177e4SLinus Torvalds { 31541da177e4SLinus Torvalds static u8 buff[512]; 31551da177e4SLinus Torvalds int size = 0; 31561da177e4SLinus Torvalds int len = 0; 31571da177e4SLinus Torvalds off_t begin = 0; 31581da177e4SLinus Torvalds off_t pos = 0; 31591da177e4SLinus Torvalds 31601da177e4SLinus Torvalds if (inout) 31611da177e4SLinus Torvalds return -EINVAL; 31621da177e4SLinus Torvalds if (offset == 0) 31631da177e4SLinus Torvalds memset(buff, 0, sizeof(buff)); 31641da177e4SLinus Torvalds size += sprintf(BLS, "ACARD AEC-671X Driver Version: 2.6+ac\n"); 31651da177e4SLinus Torvalds len += size; 31661da177e4SLinus Torvalds pos = begin + len; 31671da177e4SLinus Torvalds size = 0; 31681da177e4SLinus Torvalds 31691da177e4SLinus Torvalds size += sprintf(BLS, "\n"); 31701da177e4SLinus Torvalds size += sprintf(BLS, "Adapter Configuration:\n"); 31711da177e4SLinus Torvalds size += sprintf(BLS, " Base IO: %#.4lx\n", HBAptr->io_port); 31721da177e4SLinus Torvalds size += sprintf(BLS, " IRQ: %d\n", HBAptr->irq); 31731da177e4SLinus Torvalds len += size; 31741da177e4SLinus Torvalds pos = begin + len; 31751da177e4SLinus Torvalds 31761da177e4SLinus Torvalds *start = buffer + (offset - begin); /* Start of wanted data */ 31771da177e4SLinus Torvalds len -= (offset - begin); /* Start slop */ 31781da177e4SLinus Torvalds if (len > length) { 31791da177e4SLinus Torvalds len = length; /* Ending slop */ 31801da177e4SLinus Torvalds } 31811da177e4SLinus Torvalds return (len); 31821da177e4SLinus Torvalds } 31831da177e4SLinus Torvalds 31841da177e4SLinus Torvalds 31851da177e4SLinus Torvalds static int atp870u_biosparam(struct scsi_device *disk, struct block_device *dev, 31861da177e4SLinus Torvalds sector_t capacity, int *ip) 31871da177e4SLinus Torvalds { 31881da177e4SLinus Torvalds int heads, sectors, cylinders; 31891da177e4SLinus Torvalds 31901da177e4SLinus Torvalds heads = 64; 31911da177e4SLinus Torvalds sectors = 32; 31921da177e4SLinus Torvalds cylinders = (unsigned long)capacity / (heads * sectors); 31931da177e4SLinus Torvalds if (cylinders > 1024) { 31941da177e4SLinus Torvalds heads = 255; 31951da177e4SLinus Torvalds sectors = 63; 31961da177e4SLinus Torvalds cylinders = (unsigned long)capacity / (heads * sectors); 31971da177e4SLinus Torvalds } 31981da177e4SLinus Torvalds ip[0] = heads; 31991da177e4SLinus Torvalds ip[1] = sectors; 32001da177e4SLinus Torvalds ip[2] = cylinders; 32011da177e4SLinus Torvalds 32021da177e4SLinus Torvalds return 0; 32031da177e4SLinus Torvalds } 32041da177e4SLinus Torvalds 32051da177e4SLinus Torvalds static void atp870u_remove (struct pci_dev *pdev) 32061da177e4SLinus Torvalds { 32071da177e4SLinus Torvalds struct atp_unit *devext = pci_get_drvdata(pdev); 32081da177e4SLinus Torvalds struct Scsi_Host *pshost = devext->host; 32091da177e4SLinus Torvalds 32101da177e4SLinus Torvalds 32111da177e4SLinus Torvalds scsi_remove_host(pshost); 32121da177e4SLinus Torvalds printk(KERN_INFO "free_irq : %d\n",pshost->irq); 32131da177e4SLinus Torvalds free_irq(pshost->irq, pshost); 32141da177e4SLinus Torvalds release_region(pshost->io_port, pshost->n_io_port); 32151da177e4SLinus Torvalds printk(KERN_INFO "atp870u_free_tables : %p\n",pshost); 32161da177e4SLinus Torvalds atp870u_free_tables(pshost); 32171da177e4SLinus Torvalds printk(KERN_INFO "scsi_host_put : %p\n",pshost); 32181da177e4SLinus Torvalds scsi_host_put(pshost); 32191da177e4SLinus Torvalds printk(KERN_INFO "pci_set_drvdata : %p\n",pdev); 32201da177e4SLinus Torvalds pci_set_drvdata(pdev, NULL); 32211da177e4SLinus Torvalds } 32221da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 32231da177e4SLinus Torvalds 32241da177e4SLinus Torvalds static struct scsi_host_template atp870u_template = { 32251da177e4SLinus Torvalds .module = THIS_MODULE, 32261da177e4SLinus Torvalds .name = "atp870u" /* name */, 32271da177e4SLinus Torvalds .proc_name = "atp870u", 32281da177e4SLinus Torvalds .proc_info = atp870u_proc_info, 32291da177e4SLinus Torvalds .info = atp870u_info /* info */, 32301da177e4SLinus Torvalds .queuecommand = atp870u_queuecommand /* queuecommand */, 32311da177e4SLinus Torvalds .eh_abort_handler = atp870u_abort /* abort */, 32321da177e4SLinus Torvalds .bios_param = atp870u_biosparam /* biosparm */, 32331da177e4SLinus Torvalds .can_queue = qcnt /* can_queue */, 32341da177e4SLinus Torvalds .this_id = 7 /* SCSI ID */, 32351da177e4SLinus Torvalds .sg_tablesize = ATP870U_SCATTER /*SG_ALL*/ /*SG_NONE*/, 32361da177e4SLinus Torvalds .cmd_per_lun = ATP870U_CMDLUN /* commands per lun */, 32371da177e4SLinus Torvalds .use_clustering = ENABLE_CLUSTERING, 32381da177e4SLinus Torvalds .max_sectors = ATP870U_MAX_SECTORS, 32391da177e4SLinus Torvalds }; 32401da177e4SLinus Torvalds 32411da177e4SLinus Torvalds static struct pci_device_id atp870u_id_table[] = { 32421da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP885_DEVID) }, 32431da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID1) }, 32441da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID2) }, 32451da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7610) }, 32461da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612UW) }, 32471da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612U) }, 32481da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612S) }, 32491da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612D) }, 32501da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612SUW) }, 32511da177e4SLinus Torvalds { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_8060) }, 32521da177e4SLinus Torvalds { 0, }, 32531da177e4SLinus Torvalds }; 32541da177e4SLinus Torvalds 32551da177e4SLinus Torvalds MODULE_DEVICE_TABLE(pci, atp870u_id_table); 32561da177e4SLinus Torvalds 32571da177e4SLinus Torvalds static struct pci_driver atp870u_driver = { 32581da177e4SLinus Torvalds .id_table = atp870u_id_table, 32591da177e4SLinus Torvalds .name = "atp870u", 32601da177e4SLinus Torvalds .probe = atp870u_probe, 32611da177e4SLinus Torvalds .remove = __devexit_p(atp870u_remove), 32621da177e4SLinus Torvalds }; 32631da177e4SLinus Torvalds 32641da177e4SLinus Torvalds static int __init atp870u_init(void) 32651da177e4SLinus Torvalds { 32661da177e4SLinus Torvalds #ifdef ED_DBGP 32671da177e4SLinus Torvalds printk("atp870u_init: Entry\n"); 32681da177e4SLinus Torvalds #endif 32691da177e4SLinus Torvalds return pci_register_driver(&atp870u_driver); 32701da177e4SLinus Torvalds } 32711da177e4SLinus Torvalds 32721da177e4SLinus Torvalds static void __exit atp870u_exit(void) 32731da177e4SLinus Torvalds { 32741da177e4SLinus Torvalds #ifdef ED_DBGP 32751da177e4SLinus Torvalds printk("atp870u_exit: Entry\n"); 32761da177e4SLinus Torvalds #endif 32771da177e4SLinus Torvalds pci_unregister_driver(&atp870u_driver); 32781da177e4SLinus Torvalds } 32791da177e4SLinus Torvalds 32801da177e4SLinus Torvalds static void tscam_885(void) 32811da177e4SLinus Torvalds { 32821da177e4SLinus Torvalds unsigned char i; 32831da177e4SLinus Torvalds 32841da177e4SLinus Torvalds for (i = 0; i < 0x2; i++) { 32851da177e4SLinus Torvalds mdelay(300); 32861da177e4SLinus Torvalds } 32871da177e4SLinus Torvalds return; 32881da177e4SLinus Torvalds } 32891da177e4SLinus Torvalds 32901da177e4SLinus Torvalds 32911da177e4SLinus Torvalds 32921da177e4SLinus Torvalds static void is885(struct atp_unit *dev, unsigned int wkport,unsigned char c) 32931da177e4SLinus Torvalds { 32941da177e4SLinus Torvalds unsigned int tmport; 32951da177e4SLinus Torvalds unsigned char i, j, k, rmb, n, lvdmode; 32961da177e4SLinus Torvalds unsigned short int m; 32971da177e4SLinus Torvalds static unsigned char mbuf[512]; 32981da177e4SLinus Torvalds static unsigned char satn[9] = {0, 0, 0, 0, 0, 0, 0, 6, 6}; 32991da177e4SLinus Torvalds static unsigned char inqd[9] = {0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6}; 33001da177e4SLinus Torvalds static unsigned char synn[6] = {0x80, 1, 3, 1, 0x19, 0x0e}; 33011da177e4SLinus Torvalds unsigned char synu[6] = {0x80, 1, 3, 1, 0x0a, 0x0e}; 33021da177e4SLinus Torvalds static unsigned char synw[6] = {0x80, 1, 3, 1, 0x19, 0x0e}; 33031da177e4SLinus Torvalds unsigned char synuw[6] = {0x80, 1, 3, 1, 0x0a, 0x0e}; 33041da177e4SLinus Torvalds static unsigned char wide[6] = {0x80, 1, 2, 3, 1, 0}; 33051da177e4SLinus Torvalds static unsigned char u3[9] = { 0x80,1,6,4,0x09,00,0x0e,0x01,0x02 }; 33061da177e4SLinus Torvalds 33071da177e4SLinus Torvalds lvdmode=inb(wkport + 0x1b) >> 7; 33081da177e4SLinus Torvalds 33091da177e4SLinus Torvalds for (i = 0; i < 16; i++) { 33101da177e4SLinus Torvalds m = 1; 33111da177e4SLinus Torvalds m = m << i; 33121da177e4SLinus Torvalds if ((m & dev->active_id[c]) != 0) { 33131da177e4SLinus Torvalds continue; 33141da177e4SLinus Torvalds } 33151da177e4SLinus Torvalds if (i == dev->host_id[c]) { 33161da177e4SLinus Torvalds printk(KERN_INFO " ID: %2d Host Adapter\n", dev->host_id[c]); 33171da177e4SLinus Torvalds continue; 33181da177e4SLinus Torvalds } 33191da177e4SLinus Torvalds tmport = wkport + 0x1b; 33201da177e4SLinus Torvalds outb(0x01, tmport); 33211da177e4SLinus Torvalds tmport = wkport + 0x01; 33221da177e4SLinus Torvalds outb(0x08, tmport++); 33231da177e4SLinus Torvalds outb(0x7f, tmport++); 33241da177e4SLinus Torvalds outb(satn[0], tmport++); 33251da177e4SLinus Torvalds outb(satn[1], tmport++); 33261da177e4SLinus Torvalds outb(satn[2], tmport++); 33271da177e4SLinus Torvalds outb(satn[3], tmport++); 33281da177e4SLinus Torvalds outb(satn[4], tmport++); 33291da177e4SLinus Torvalds outb(satn[5], tmport++); 33301da177e4SLinus Torvalds tmport += 0x06; 33311da177e4SLinus Torvalds outb(0, tmport); 33321da177e4SLinus Torvalds tmport += 0x02; 33331da177e4SLinus Torvalds outb(dev->id[c][i].devsp, tmport++); 33341da177e4SLinus Torvalds 33351da177e4SLinus Torvalds outb(0, tmport++); 33361da177e4SLinus Torvalds outb(satn[6], tmport++); 33371da177e4SLinus Torvalds outb(satn[7], tmport++); 33381da177e4SLinus Torvalds j = i; 33391da177e4SLinus Torvalds if ((j & 0x08) != 0) { 33401da177e4SLinus Torvalds j = (j & 0x07) | 0x40; 33411da177e4SLinus Torvalds } 33421da177e4SLinus Torvalds outb(j, tmport); 33431da177e4SLinus Torvalds tmport += 0x03; 33441da177e4SLinus Torvalds outb(satn[8], tmport); 33451da177e4SLinus Torvalds tmport += 0x07; 33461da177e4SLinus Torvalds 33471da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 33481da177e4SLinus Torvalds cpu_relax(); 33491da177e4SLinus Torvalds tmport -= 0x08; 33501da177e4SLinus Torvalds if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) { 33511da177e4SLinus Torvalds continue; 33521da177e4SLinus Torvalds } 33531da177e4SLinus Torvalds while (inb(tmport) != 0x8e) 33541da177e4SLinus Torvalds cpu_relax(); 33551da177e4SLinus Torvalds dev->active_id[c] |= m; 33561da177e4SLinus Torvalds 33571da177e4SLinus Torvalds tmport = wkport + 0x10; 33581da177e4SLinus Torvalds outb(0x30, tmport); 33591da177e4SLinus Torvalds tmport = wkport + 0x14; 33601da177e4SLinus Torvalds outb(0x00, tmport); 33611da177e4SLinus Torvalds 33621da177e4SLinus Torvalds phase_cmd: 33631da177e4SLinus Torvalds tmport = wkport + 0x18; 33641da177e4SLinus Torvalds outb(0x08, tmport); 33651da177e4SLinus Torvalds tmport += 0x07; 33661da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 33671da177e4SLinus Torvalds cpu_relax(); 33681da177e4SLinus Torvalds tmport -= 0x08; 33691da177e4SLinus Torvalds j = inb(tmport); 33701da177e4SLinus Torvalds if (j != 0x16) { 33711da177e4SLinus Torvalds tmport = wkport + 0x10; 33721da177e4SLinus Torvalds outb(0x41, tmport); 33731da177e4SLinus Torvalds goto phase_cmd; 33741da177e4SLinus Torvalds } 33751da177e4SLinus Torvalds sel_ok: 33761da177e4SLinus Torvalds tmport = wkport + 0x03; 33771da177e4SLinus Torvalds outb(inqd[0], tmport++); 33781da177e4SLinus Torvalds outb(inqd[1], tmport++); 33791da177e4SLinus Torvalds outb(inqd[2], tmport++); 33801da177e4SLinus Torvalds outb(inqd[3], tmport++); 33811da177e4SLinus Torvalds outb(inqd[4], tmport++); 33821da177e4SLinus Torvalds outb(inqd[5], tmport); 33831da177e4SLinus Torvalds tmport += 0x07; 33841da177e4SLinus Torvalds outb(0, tmport); 33851da177e4SLinus Torvalds tmport += 0x02; 33861da177e4SLinus Torvalds outb(dev->id[c][i].devsp, tmport++); 33871da177e4SLinus Torvalds outb(0, tmport++); 33881da177e4SLinus Torvalds outb(inqd[6], tmport++); 33891da177e4SLinus Torvalds outb(inqd[7], tmport++); 33901da177e4SLinus Torvalds tmport += 0x03; 33911da177e4SLinus Torvalds outb(inqd[8], tmport); 33921da177e4SLinus Torvalds tmport += 0x07; 33931da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 33941da177e4SLinus Torvalds cpu_relax(); 33951da177e4SLinus Torvalds tmport -= 0x08; 33961da177e4SLinus Torvalds if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) { 33971da177e4SLinus Torvalds continue; 33981da177e4SLinus Torvalds } 33991da177e4SLinus Torvalds while (inb(tmport) != 0x8e) 34001da177e4SLinus Torvalds cpu_relax(); 34011da177e4SLinus Torvalds tmport = wkport + 0x1b; 34021da177e4SLinus Torvalds outb(0x00, tmport); 34031da177e4SLinus Torvalds tmport = wkport + 0x18; 34041da177e4SLinus Torvalds outb(0x08, tmport); 34051da177e4SLinus Torvalds tmport += 0x07; 34061da177e4SLinus Torvalds j = 0; 34071da177e4SLinus Torvalds rd_inq_data: 34081da177e4SLinus Torvalds k = inb(tmport); 34091da177e4SLinus Torvalds if ((k & 0x01) != 0) { 34101da177e4SLinus Torvalds tmport -= 0x06; 34111da177e4SLinus Torvalds mbuf[j++] = inb(tmport); 34121da177e4SLinus Torvalds tmport += 0x06; 34131da177e4SLinus Torvalds goto rd_inq_data; 34141da177e4SLinus Torvalds } 34151da177e4SLinus Torvalds if ((k & 0x80) == 0) { 34161da177e4SLinus Torvalds goto rd_inq_data; 34171da177e4SLinus Torvalds } 34181da177e4SLinus Torvalds tmport -= 0x08; 34191da177e4SLinus Torvalds j = inb(tmport); 34201da177e4SLinus Torvalds if (j == 0x16) { 34211da177e4SLinus Torvalds goto inq_ok; 34221da177e4SLinus Torvalds } 34231da177e4SLinus Torvalds tmport = wkport + 0x10; 34241da177e4SLinus Torvalds outb(0x46, tmport); 34251da177e4SLinus Torvalds tmport += 0x02; 34261da177e4SLinus Torvalds outb(0, tmport++); 34271da177e4SLinus Torvalds outb(0, tmport++); 34281da177e4SLinus Torvalds outb(0, tmport++); 34291da177e4SLinus Torvalds tmport += 0x03; 34301da177e4SLinus Torvalds outb(0x08, tmport); 34311da177e4SLinus Torvalds tmport += 0x07; 34321da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 34331da177e4SLinus Torvalds cpu_relax(); 34341da177e4SLinus Torvalds tmport -= 0x08; 34351da177e4SLinus Torvalds if (inb(tmport) != 0x16) { 34361da177e4SLinus Torvalds goto sel_ok; 34371da177e4SLinus Torvalds } 34381da177e4SLinus Torvalds inq_ok: 34391da177e4SLinus Torvalds mbuf[36] = 0; 34401da177e4SLinus Torvalds printk( KERN_INFO" ID: %2d %s\n", i, &mbuf[8]); 34411da177e4SLinus Torvalds dev->id[c][i].devtype = mbuf[0]; 34421da177e4SLinus Torvalds rmb = mbuf[1]; 34431da177e4SLinus Torvalds n = mbuf[7]; 34441da177e4SLinus Torvalds if ((mbuf[7] & 0x60) == 0) { 34451da177e4SLinus Torvalds goto not_wide; 34461da177e4SLinus Torvalds } 34471da177e4SLinus Torvalds if ((i < 8) && ((dev->global_map[c] & 0x20) == 0)) { 34481da177e4SLinus Torvalds goto not_wide; 34491da177e4SLinus Torvalds } 34501da177e4SLinus Torvalds if (lvdmode == 0) { 34511da177e4SLinus Torvalds goto chg_wide; 34521da177e4SLinus Torvalds } 34531da177e4SLinus Torvalds if (dev->sp[c][i] != 0x04) { // force u2 34541da177e4SLinus Torvalds goto chg_wide; 34551da177e4SLinus Torvalds } 34561da177e4SLinus Torvalds 34571da177e4SLinus Torvalds tmport = wkport + 0x1b; 34581da177e4SLinus Torvalds outb(0x01, tmport); 34591da177e4SLinus Torvalds tmport = wkport + 0x03; 34601da177e4SLinus Torvalds outb(satn[0], tmport++); 34611da177e4SLinus Torvalds outb(satn[1], tmport++); 34621da177e4SLinus Torvalds outb(satn[2], tmport++); 34631da177e4SLinus Torvalds outb(satn[3], tmport++); 34641da177e4SLinus Torvalds outb(satn[4], tmport++); 34651da177e4SLinus Torvalds outb(satn[5], tmport++); 34661da177e4SLinus Torvalds tmport += 0x06; 34671da177e4SLinus Torvalds outb(0, tmport); 34681da177e4SLinus Torvalds tmport += 0x02; 34691da177e4SLinus Torvalds outb(dev->id[c][i].devsp, tmport++); 34701da177e4SLinus Torvalds outb(0, tmport++); 34711da177e4SLinus Torvalds outb(satn[6], tmport++); 34721da177e4SLinus Torvalds outb(satn[7], tmport++); 34731da177e4SLinus Torvalds tmport += 0x03; 34741da177e4SLinus Torvalds outb(satn[8], tmport); 34751da177e4SLinus Torvalds tmport += 0x07; 34761da177e4SLinus Torvalds 34771da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 34781da177e4SLinus Torvalds cpu_relax(); 34791da177e4SLinus Torvalds tmport -= 0x08; 34801da177e4SLinus Torvalds if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) { 34811da177e4SLinus Torvalds continue; 34821da177e4SLinus Torvalds } 34831da177e4SLinus Torvalds while (inb(tmport) != 0x8e) 34841da177e4SLinus Torvalds cpu_relax(); 34851da177e4SLinus Torvalds try_u3: 34861da177e4SLinus Torvalds j = 0; 34871da177e4SLinus Torvalds tmport = wkport + 0x14; 34881da177e4SLinus Torvalds outb(0x09, tmport); 34891da177e4SLinus Torvalds tmport += 0x04; 34901da177e4SLinus Torvalds outb(0x20, tmport); 34911da177e4SLinus Torvalds tmport += 0x07; 34921da177e4SLinus Torvalds 34931da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0) { 34941da177e4SLinus Torvalds if ((inb(tmport) & 0x01) != 0) { 34951da177e4SLinus Torvalds tmport -= 0x06; 34961da177e4SLinus Torvalds outb(u3[j++], tmport); 34971da177e4SLinus Torvalds tmport += 0x06; 34981da177e4SLinus Torvalds } 34991da177e4SLinus Torvalds cpu_relax(); 35001da177e4SLinus Torvalds } 35011da177e4SLinus Torvalds tmport -= 0x08; 35021da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 35031da177e4SLinus Torvalds cpu_relax(); 35041da177e4SLinus Torvalds j = inb(tmport) & 0x0f; 35051da177e4SLinus Torvalds if (j == 0x0f) { 35061da177e4SLinus Torvalds goto u3p_in; 35071da177e4SLinus Torvalds } 35081da177e4SLinus Torvalds if (j == 0x0a) { 35091da177e4SLinus Torvalds goto u3p_cmd; 35101da177e4SLinus Torvalds } 35111da177e4SLinus Torvalds if (j == 0x0e) { 35121da177e4SLinus Torvalds goto try_u3; 35131da177e4SLinus Torvalds } 35141da177e4SLinus Torvalds continue; 35151da177e4SLinus Torvalds u3p_out: 35161da177e4SLinus Torvalds tmport = wkport + 0x18; 35171da177e4SLinus Torvalds outb(0x20, tmport); 35181da177e4SLinus Torvalds tmport += 0x07; 35191da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0) { 35201da177e4SLinus Torvalds if ((inb(tmport) & 0x01) != 0) { 35211da177e4SLinus Torvalds tmport -= 0x06; 35221da177e4SLinus Torvalds outb(0, tmport); 35231da177e4SLinus Torvalds tmport += 0x06; 35241da177e4SLinus Torvalds } 35251da177e4SLinus Torvalds cpu_relax(); 35261da177e4SLinus Torvalds } 35271da177e4SLinus Torvalds tmport -= 0x08; 35281da177e4SLinus Torvalds j = inb(tmport) & 0x0f; 35291da177e4SLinus Torvalds if (j == 0x0f) { 35301da177e4SLinus Torvalds goto u3p_in; 35311da177e4SLinus Torvalds } 35321da177e4SLinus Torvalds if (j == 0x0a) { 35331da177e4SLinus Torvalds goto u3p_cmd; 35341da177e4SLinus Torvalds } 35351da177e4SLinus Torvalds if (j == 0x0e) { 35361da177e4SLinus Torvalds goto u3p_out; 35371da177e4SLinus Torvalds } 35381da177e4SLinus Torvalds continue; 35391da177e4SLinus Torvalds u3p_in: 35401da177e4SLinus Torvalds tmport = wkport + 0x14; 35411da177e4SLinus Torvalds outb(0x09, tmport); 35421da177e4SLinus Torvalds tmport += 0x04; 35431da177e4SLinus Torvalds outb(0x20, tmport); 35441da177e4SLinus Torvalds tmport += 0x07; 35451da177e4SLinus Torvalds k = 0; 35461da177e4SLinus Torvalds u3p_in1: 35471da177e4SLinus Torvalds j = inb(tmport); 35481da177e4SLinus Torvalds if ((j & 0x01) != 0) { 35491da177e4SLinus Torvalds tmport -= 0x06; 35501da177e4SLinus Torvalds mbuf[k++] = inb(tmport); 35511da177e4SLinus Torvalds tmport += 0x06; 35521da177e4SLinus Torvalds goto u3p_in1; 35531da177e4SLinus Torvalds } 35541da177e4SLinus Torvalds if ((j & 0x80) == 0x00) { 35551da177e4SLinus Torvalds goto u3p_in1; 35561da177e4SLinus Torvalds } 35571da177e4SLinus Torvalds tmport -= 0x08; 35581da177e4SLinus Torvalds j = inb(tmport) & 0x0f; 35591da177e4SLinus Torvalds if (j == 0x0f) { 35601da177e4SLinus Torvalds goto u3p_in; 35611da177e4SLinus Torvalds } 35621da177e4SLinus Torvalds if (j == 0x0a) { 35631da177e4SLinus Torvalds goto u3p_cmd; 35641da177e4SLinus Torvalds } 35651da177e4SLinus Torvalds if (j == 0x0e) { 35661da177e4SLinus Torvalds goto u3p_out; 35671da177e4SLinus Torvalds } 35681da177e4SLinus Torvalds continue; 35691da177e4SLinus Torvalds u3p_cmd: 35701da177e4SLinus Torvalds tmport = wkport + 0x10; 35711da177e4SLinus Torvalds outb(0x30, tmport); 35721da177e4SLinus Torvalds tmport = wkport + 0x14; 35731da177e4SLinus Torvalds outb(0x00, tmport); 35741da177e4SLinus Torvalds tmport += 0x04; 35751da177e4SLinus Torvalds outb(0x08, tmport); 35761da177e4SLinus Torvalds tmport += 0x07; 35771da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00); 35781da177e4SLinus Torvalds tmport -= 0x08; 35791da177e4SLinus Torvalds j = inb(tmport); 35801da177e4SLinus Torvalds if (j != 0x16) { 35811da177e4SLinus Torvalds if (j == 0x4e) { 35821da177e4SLinus Torvalds goto u3p_out; 35831da177e4SLinus Torvalds } 35841da177e4SLinus Torvalds continue; 35851da177e4SLinus Torvalds } 35861da177e4SLinus Torvalds if (mbuf[0] != 0x01) { 35871da177e4SLinus Torvalds goto chg_wide; 35881da177e4SLinus Torvalds } 35891da177e4SLinus Torvalds if (mbuf[1] != 0x06) { 35901da177e4SLinus Torvalds goto chg_wide; 35911da177e4SLinus Torvalds } 35921da177e4SLinus Torvalds if (mbuf[2] != 0x04) { 35931da177e4SLinus Torvalds goto chg_wide; 35941da177e4SLinus Torvalds } 35951da177e4SLinus Torvalds if (mbuf[3] == 0x09) { 35961da177e4SLinus Torvalds m = 1; 35971da177e4SLinus Torvalds m = m << i; 35981da177e4SLinus Torvalds dev->wide_id[c] |= m; 35991da177e4SLinus Torvalds dev->id[c][i].devsp = 0xce; 36001da177e4SLinus Torvalds #ifdef ED_DBGP 36011da177e4SLinus Torvalds printk("dev->id[%2d][%2d].devsp = %2x\n",c,i,dev->id[c][i].devsp); 36021da177e4SLinus Torvalds #endif 36031da177e4SLinus Torvalds continue; 36041da177e4SLinus Torvalds } 36051da177e4SLinus Torvalds chg_wide: 36061da177e4SLinus Torvalds tmport = wkport + 0x1b; 36071da177e4SLinus Torvalds outb(0x01, tmport); 36081da177e4SLinus Torvalds tmport = wkport + 0x03; 36091da177e4SLinus Torvalds outb(satn[0], tmport++); 36101da177e4SLinus Torvalds outb(satn[1], tmport++); 36111da177e4SLinus Torvalds outb(satn[2], tmport++); 36121da177e4SLinus Torvalds outb(satn[3], tmport++); 36131da177e4SLinus Torvalds outb(satn[4], tmport++); 36141da177e4SLinus Torvalds outb(satn[5], tmport++); 36151da177e4SLinus Torvalds tmport += 0x06; 36161da177e4SLinus Torvalds outb(0, tmport); 36171da177e4SLinus Torvalds tmport += 0x02; 36181da177e4SLinus Torvalds outb(dev->id[c][i].devsp, tmport++); 36191da177e4SLinus Torvalds outb(0, tmport++); 36201da177e4SLinus Torvalds outb(satn[6], tmport++); 36211da177e4SLinus Torvalds outb(satn[7], tmport++); 36221da177e4SLinus Torvalds tmport += 0x03; 36231da177e4SLinus Torvalds outb(satn[8], tmport); 36241da177e4SLinus Torvalds tmport += 0x07; 36251da177e4SLinus Torvalds 36261da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 36271da177e4SLinus Torvalds cpu_relax(); 36281da177e4SLinus Torvalds tmport -= 0x08; 36291da177e4SLinus Torvalds if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) { 36301da177e4SLinus Torvalds continue; 36311da177e4SLinus Torvalds } 36321da177e4SLinus Torvalds while (inb(tmport) != 0x8e) 36331da177e4SLinus Torvalds cpu_relax(); 36341da177e4SLinus Torvalds try_wide: 36351da177e4SLinus Torvalds j = 0; 36361da177e4SLinus Torvalds tmport = wkport + 0x14; 36371da177e4SLinus Torvalds outb(0x05, tmport); 36381da177e4SLinus Torvalds tmport += 0x04; 36391da177e4SLinus Torvalds outb(0x20, tmport); 36401da177e4SLinus Torvalds tmport += 0x07; 36411da177e4SLinus Torvalds 36421da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0) { 36431da177e4SLinus Torvalds if ((inb(tmport) & 0x01) != 0) { 36441da177e4SLinus Torvalds tmport -= 0x06; 36451da177e4SLinus Torvalds outb(wide[j++], tmport); 36461da177e4SLinus Torvalds tmport += 0x06; 36471da177e4SLinus Torvalds } 36481da177e4SLinus Torvalds cpu_relax(); 36491da177e4SLinus Torvalds } 36501da177e4SLinus Torvalds tmport -= 0x08; 36511da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 36521da177e4SLinus Torvalds cpu_relax(); 36531da177e4SLinus Torvalds j = inb(tmport) & 0x0f; 36541da177e4SLinus Torvalds if (j == 0x0f) { 36551da177e4SLinus Torvalds goto widep_in; 36561da177e4SLinus Torvalds } 36571da177e4SLinus Torvalds if (j == 0x0a) { 36581da177e4SLinus Torvalds goto widep_cmd; 36591da177e4SLinus Torvalds } 36601da177e4SLinus Torvalds if (j == 0x0e) { 36611da177e4SLinus Torvalds goto try_wide; 36621da177e4SLinus Torvalds } 36631da177e4SLinus Torvalds continue; 36641da177e4SLinus Torvalds widep_out: 36651da177e4SLinus Torvalds tmport = wkport + 0x18; 36661da177e4SLinus Torvalds outb(0x20, tmport); 36671da177e4SLinus Torvalds tmport += 0x07; 36681da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0) { 36691da177e4SLinus Torvalds if ((inb(tmport) & 0x01) != 0) { 36701da177e4SLinus Torvalds tmport -= 0x06; 36711da177e4SLinus Torvalds outb(0, tmport); 36721da177e4SLinus Torvalds tmport += 0x06; 36731da177e4SLinus Torvalds } 36741da177e4SLinus Torvalds cpu_relax(); 36751da177e4SLinus Torvalds } 36761da177e4SLinus Torvalds tmport -= 0x08; 36771da177e4SLinus Torvalds j = inb(tmport) & 0x0f; 36781da177e4SLinus Torvalds if (j == 0x0f) { 36791da177e4SLinus Torvalds goto widep_in; 36801da177e4SLinus Torvalds } 36811da177e4SLinus Torvalds if (j == 0x0a) { 36821da177e4SLinus Torvalds goto widep_cmd; 36831da177e4SLinus Torvalds } 36841da177e4SLinus Torvalds if (j == 0x0e) { 36851da177e4SLinus Torvalds goto widep_out; 36861da177e4SLinus Torvalds } 36871da177e4SLinus Torvalds continue; 36881da177e4SLinus Torvalds widep_in: 36891da177e4SLinus Torvalds tmport = wkport + 0x14; 36901da177e4SLinus Torvalds outb(0xff, tmport); 36911da177e4SLinus Torvalds tmport += 0x04; 36921da177e4SLinus Torvalds outb(0x20, tmport); 36931da177e4SLinus Torvalds tmport += 0x07; 36941da177e4SLinus Torvalds k = 0; 36951da177e4SLinus Torvalds widep_in1: 36961da177e4SLinus Torvalds j = inb(tmport); 36971da177e4SLinus Torvalds if ((j & 0x01) != 0) { 36981da177e4SLinus Torvalds tmport -= 0x06; 36991da177e4SLinus Torvalds mbuf[k++] = inb(tmport); 37001da177e4SLinus Torvalds tmport += 0x06; 37011da177e4SLinus Torvalds goto widep_in1; 37021da177e4SLinus Torvalds } 37031da177e4SLinus Torvalds if ((j & 0x80) == 0x00) { 37041da177e4SLinus Torvalds goto widep_in1; 37051da177e4SLinus Torvalds } 37061da177e4SLinus Torvalds tmport -= 0x08; 37071da177e4SLinus Torvalds j = inb(tmport) & 0x0f; 37081da177e4SLinus Torvalds if (j == 0x0f) { 37091da177e4SLinus Torvalds goto widep_in; 37101da177e4SLinus Torvalds } 37111da177e4SLinus Torvalds if (j == 0x0a) { 37121da177e4SLinus Torvalds goto widep_cmd; 37131da177e4SLinus Torvalds } 37141da177e4SLinus Torvalds if (j == 0x0e) { 37151da177e4SLinus Torvalds goto widep_out; 37161da177e4SLinus Torvalds } 37171da177e4SLinus Torvalds continue; 37181da177e4SLinus Torvalds widep_cmd: 37191da177e4SLinus Torvalds tmport = wkport + 0x10; 37201da177e4SLinus Torvalds outb(0x30, tmport); 37211da177e4SLinus Torvalds tmport = wkport + 0x14; 37221da177e4SLinus Torvalds outb(0x00, tmport); 37231da177e4SLinus Torvalds tmport += 0x04; 37241da177e4SLinus Torvalds outb(0x08, tmport); 37251da177e4SLinus Torvalds tmport += 0x07; 37261da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 37271da177e4SLinus Torvalds cpu_relax(); 37281da177e4SLinus Torvalds tmport -= 0x08; 37291da177e4SLinus Torvalds j = inb(tmport); 37301da177e4SLinus Torvalds if (j != 0x16) { 37311da177e4SLinus Torvalds if (j == 0x4e) { 37321da177e4SLinus Torvalds goto widep_out; 37331da177e4SLinus Torvalds } 37341da177e4SLinus Torvalds continue; 37351da177e4SLinus Torvalds } 37361da177e4SLinus Torvalds if (mbuf[0] != 0x01) { 37371da177e4SLinus Torvalds goto not_wide; 37381da177e4SLinus Torvalds } 37391da177e4SLinus Torvalds if (mbuf[1] != 0x02) { 37401da177e4SLinus Torvalds goto not_wide; 37411da177e4SLinus Torvalds } 37421da177e4SLinus Torvalds if (mbuf[2] != 0x03) { 37431da177e4SLinus Torvalds goto not_wide; 37441da177e4SLinus Torvalds } 37451da177e4SLinus Torvalds if (mbuf[3] != 0x01) { 37461da177e4SLinus Torvalds goto not_wide; 37471da177e4SLinus Torvalds } 37481da177e4SLinus Torvalds m = 1; 37491da177e4SLinus Torvalds m = m << i; 37501da177e4SLinus Torvalds dev->wide_id[c] |= m; 37511da177e4SLinus Torvalds not_wide: 37521da177e4SLinus Torvalds if ((dev->id[c][i].devtype == 0x00) || (dev->id[c][i].devtype == 0x07) || 37531da177e4SLinus Torvalds ((dev->id[c][i].devtype == 0x05) && ((n & 0x10) != 0))) { 37541da177e4SLinus Torvalds m = 1; 37551da177e4SLinus Torvalds m = m << i; 37561da177e4SLinus Torvalds if ((dev->async[c] & m) != 0) { 37571da177e4SLinus Torvalds goto set_sync; 37581da177e4SLinus Torvalds } 37591da177e4SLinus Torvalds } 37601da177e4SLinus Torvalds continue; 37611da177e4SLinus Torvalds set_sync: 37621da177e4SLinus Torvalds if (dev->sp[c][i] == 0x02) { 37631da177e4SLinus Torvalds synu[4]=0x0c; 37641da177e4SLinus Torvalds synuw[4]=0x0c; 37651da177e4SLinus Torvalds } else { 37661da177e4SLinus Torvalds if (dev->sp[c][i] >= 0x03) { 37671da177e4SLinus Torvalds synu[4]=0x0a; 37681da177e4SLinus Torvalds synuw[4]=0x0a; 37691da177e4SLinus Torvalds } 37701da177e4SLinus Torvalds } 37711da177e4SLinus Torvalds tmport = wkport + 0x1b; 37721da177e4SLinus Torvalds j = 0; 37731da177e4SLinus Torvalds if ((m & dev->wide_id[c]) != 0) { 37741da177e4SLinus Torvalds j |= 0x01; 37751da177e4SLinus Torvalds } 37761da177e4SLinus Torvalds outb(j, tmport); 37771da177e4SLinus Torvalds tmport = wkport + 0x03; 37781da177e4SLinus Torvalds outb(satn[0], tmport++); 37791da177e4SLinus Torvalds outb(satn[1], tmport++); 37801da177e4SLinus Torvalds outb(satn[2], tmport++); 37811da177e4SLinus Torvalds outb(satn[3], tmport++); 37821da177e4SLinus Torvalds outb(satn[4], tmport++); 37831da177e4SLinus Torvalds outb(satn[5], tmport++); 37841da177e4SLinus Torvalds tmport += 0x06; 37851da177e4SLinus Torvalds outb(0, tmport); 37861da177e4SLinus Torvalds tmport += 0x02; 37871da177e4SLinus Torvalds outb(dev->id[c][i].devsp, tmport++); 37881da177e4SLinus Torvalds outb(0, tmport++); 37891da177e4SLinus Torvalds outb(satn[6], tmport++); 37901da177e4SLinus Torvalds outb(satn[7], tmport++); 37911da177e4SLinus Torvalds tmport += 0x03; 37921da177e4SLinus Torvalds outb(satn[8], tmport); 37931da177e4SLinus Torvalds tmport += 0x07; 37941da177e4SLinus Torvalds 37951da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 37961da177e4SLinus Torvalds cpu_relax(); 37971da177e4SLinus Torvalds tmport -= 0x08; 37981da177e4SLinus Torvalds if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) { 37991da177e4SLinus Torvalds continue; 38001da177e4SLinus Torvalds } 38011da177e4SLinus Torvalds while (inb(tmport) != 0x8e) 38021da177e4SLinus Torvalds cpu_relax(); 38031da177e4SLinus Torvalds try_sync: 38041da177e4SLinus Torvalds j = 0; 38051da177e4SLinus Torvalds tmport = wkport + 0x14; 38061da177e4SLinus Torvalds outb(0x06, tmport); 38071da177e4SLinus Torvalds tmport += 0x04; 38081da177e4SLinus Torvalds outb(0x20, tmport); 38091da177e4SLinus Torvalds tmport += 0x07; 38101da177e4SLinus Torvalds 38111da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0) { 38121da177e4SLinus Torvalds if ((inb(tmport) & 0x01) != 0) { 38131da177e4SLinus Torvalds tmport -= 0x06; 38141da177e4SLinus Torvalds if ((m & dev->wide_id[c]) != 0) { 38151da177e4SLinus Torvalds if ((m & dev->ultra_map[c]) != 0) { 38161da177e4SLinus Torvalds outb(synuw[j++], tmport); 38171da177e4SLinus Torvalds } else { 38181da177e4SLinus Torvalds outb(synw[j++], tmport); 38191da177e4SLinus Torvalds } 38201da177e4SLinus Torvalds } else { 38211da177e4SLinus Torvalds if ((m & dev->ultra_map[c]) != 0) { 38221da177e4SLinus Torvalds outb(synu[j++], tmport); 38231da177e4SLinus Torvalds } else { 38241da177e4SLinus Torvalds outb(synn[j++], tmport); 38251da177e4SLinus Torvalds } 38261da177e4SLinus Torvalds } 38271da177e4SLinus Torvalds tmport += 0x06; 38281da177e4SLinus Torvalds } 38291da177e4SLinus Torvalds } 38301da177e4SLinus Torvalds tmport -= 0x08; 38311da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 38321da177e4SLinus Torvalds cpu_relax(); 38331da177e4SLinus Torvalds j = inb(tmport) & 0x0f; 38341da177e4SLinus Torvalds if (j == 0x0f) { 38351da177e4SLinus Torvalds goto phase_ins; 38361da177e4SLinus Torvalds } 38371da177e4SLinus Torvalds if (j == 0x0a) { 38381da177e4SLinus Torvalds goto phase_cmds; 38391da177e4SLinus Torvalds } 38401da177e4SLinus Torvalds if (j == 0x0e) { 38411da177e4SLinus Torvalds goto try_sync; 38421da177e4SLinus Torvalds } 38431da177e4SLinus Torvalds continue; 38441da177e4SLinus Torvalds phase_outs: 38451da177e4SLinus Torvalds tmport = wkport + 0x18; 38461da177e4SLinus Torvalds outb(0x20, tmport); 38471da177e4SLinus Torvalds tmport += 0x07; 38481da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) { 38491da177e4SLinus Torvalds if ((inb(tmport) & 0x01) != 0x00) { 38501da177e4SLinus Torvalds tmport -= 0x06; 38511da177e4SLinus Torvalds outb(0x00, tmport); 38521da177e4SLinus Torvalds tmport += 0x06; 38531da177e4SLinus Torvalds } 38541da177e4SLinus Torvalds cpu_relax(); 38551da177e4SLinus Torvalds } 38561da177e4SLinus Torvalds tmport -= 0x08; 38571da177e4SLinus Torvalds j = inb(tmport); 38581da177e4SLinus Torvalds if (j == 0x85) { 38591da177e4SLinus Torvalds goto tar_dcons; 38601da177e4SLinus Torvalds } 38611da177e4SLinus Torvalds j &= 0x0f; 38621da177e4SLinus Torvalds if (j == 0x0f) { 38631da177e4SLinus Torvalds goto phase_ins; 38641da177e4SLinus Torvalds } 38651da177e4SLinus Torvalds if (j == 0x0a) { 38661da177e4SLinus Torvalds goto phase_cmds; 38671da177e4SLinus Torvalds } 38681da177e4SLinus Torvalds if (j == 0x0e) { 38691da177e4SLinus Torvalds goto phase_outs; 38701da177e4SLinus Torvalds } 38711da177e4SLinus Torvalds continue; 38721da177e4SLinus Torvalds phase_ins: 38731da177e4SLinus Torvalds tmport = wkport + 0x14; 38741da177e4SLinus Torvalds outb(0x06, tmport); 38751da177e4SLinus Torvalds tmport += 0x04; 38761da177e4SLinus Torvalds outb(0x20, tmport); 38771da177e4SLinus Torvalds tmport += 0x07; 38781da177e4SLinus Torvalds k = 0; 38791da177e4SLinus Torvalds phase_ins1: 38801da177e4SLinus Torvalds j = inb(tmport); 38811da177e4SLinus Torvalds if ((j & 0x01) != 0x00) { 38821da177e4SLinus Torvalds tmport -= 0x06; 38831da177e4SLinus Torvalds mbuf[k++] = inb(tmport); 38841da177e4SLinus Torvalds tmport += 0x06; 38851da177e4SLinus Torvalds goto phase_ins1; 38861da177e4SLinus Torvalds } 38871da177e4SLinus Torvalds if ((j & 0x80) == 0x00) { 38881da177e4SLinus Torvalds goto phase_ins1; 38891da177e4SLinus Torvalds } 38901da177e4SLinus Torvalds tmport -= 0x08; 38911da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00); 38921da177e4SLinus Torvalds j = inb(tmport); 38931da177e4SLinus Torvalds if (j == 0x85) { 38941da177e4SLinus Torvalds goto tar_dcons; 38951da177e4SLinus Torvalds } 38961da177e4SLinus Torvalds j &= 0x0f; 38971da177e4SLinus Torvalds if (j == 0x0f) { 38981da177e4SLinus Torvalds goto phase_ins; 38991da177e4SLinus Torvalds } 39001da177e4SLinus Torvalds if (j == 0x0a) { 39011da177e4SLinus Torvalds goto phase_cmds; 39021da177e4SLinus Torvalds } 39031da177e4SLinus Torvalds if (j == 0x0e) { 39041da177e4SLinus Torvalds goto phase_outs; 39051da177e4SLinus Torvalds } 39061da177e4SLinus Torvalds continue; 39071da177e4SLinus Torvalds phase_cmds: 39081da177e4SLinus Torvalds tmport = wkport + 0x10; 39091da177e4SLinus Torvalds outb(0x30, tmport); 39101da177e4SLinus Torvalds tar_dcons: 39111da177e4SLinus Torvalds tmport = wkport + 0x14; 39121da177e4SLinus Torvalds outb(0x00, tmport); 39131da177e4SLinus Torvalds tmport += 0x04; 39141da177e4SLinus Torvalds outb(0x08, tmport); 39151da177e4SLinus Torvalds tmport += 0x07; 39161da177e4SLinus Torvalds while ((inb(tmport) & 0x80) == 0x00) 39171da177e4SLinus Torvalds cpu_relax(); 39181da177e4SLinus Torvalds tmport -= 0x08; 39191da177e4SLinus Torvalds j = inb(tmport); 39201da177e4SLinus Torvalds if (j != 0x16) { 39211da177e4SLinus Torvalds continue; 39221da177e4SLinus Torvalds } 39231da177e4SLinus Torvalds if (mbuf[0] != 0x01) { 39241da177e4SLinus Torvalds continue; 39251da177e4SLinus Torvalds } 39261da177e4SLinus Torvalds if (mbuf[1] != 0x03) { 39271da177e4SLinus Torvalds continue; 39281da177e4SLinus Torvalds } 39291da177e4SLinus Torvalds if (mbuf[4] == 0x00) { 39301da177e4SLinus Torvalds continue; 39311da177e4SLinus Torvalds } 39321da177e4SLinus Torvalds if (mbuf[3] > 0x64) { 39331da177e4SLinus Torvalds continue; 39341da177e4SLinus Torvalds } 39351da177e4SLinus Torvalds if (mbuf[4] > 0x0e) { 39361da177e4SLinus Torvalds mbuf[4] = 0x0e; 39371da177e4SLinus Torvalds } 39381da177e4SLinus Torvalds dev->id[c][i].devsp = mbuf[4]; 39391da177e4SLinus Torvalds if (mbuf[3] < 0x0c){ 39401da177e4SLinus Torvalds j = 0xb0; 39411da177e4SLinus Torvalds goto set_syn_ok; 39421da177e4SLinus Torvalds } 39431da177e4SLinus Torvalds if ((mbuf[3] < 0x0d) && (rmb == 0)) { 39441da177e4SLinus Torvalds j = 0xa0; 39451da177e4SLinus Torvalds goto set_syn_ok; 39461da177e4SLinus Torvalds } 39471da177e4SLinus Torvalds if (mbuf[3] < 0x1a) { 39481da177e4SLinus Torvalds j = 0x20; 39491da177e4SLinus Torvalds goto set_syn_ok; 39501da177e4SLinus Torvalds } 39511da177e4SLinus Torvalds if (mbuf[3] < 0x33) { 39521da177e4SLinus Torvalds j = 0x40; 39531da177e4SLinus Torvalds goto set_syn_ok; 39541da177e4SLinus Torvalds } 39551da177e4SLinus Torvalds if (mbuf[3] < 0x4c) { 39561da177e4SLinus Torvalds j = 0x50; 39571da177e4SLinus Torvalds goto set_syn_ok; 39581da177e4SLinus Torvalds } 39591da177e4SLinus Torvalds j = 0x60; 39601da177e4SLinus Torvalds set_syn_ok: 39611da177e4SLinus Torvalds dev->id[c][i].devsp = (dev->id[c][i].devsp & 0x0f) | j; 39621da177e4SLinus Torvalds #ifdef ED_DBGP 39631da177e4SLinus Torvalds printk("dev->id[%2d][%2d].devsp = %2x\n",c,i,dev->id[c][i].devsp); 39641da177e4SLinus Torvalds #endif 39651da177e4SLinus Torvalds } 39661da177e4SLinus Torvalds tmport = wkport + 0x16; 39671da177e4SLinus Torvalds outb(0x80, tmport); 39681da177e4SLinus Torvalds } 39691da177e4SLinus Torvalds 39701da177e4SLinus Torvalds module_init(atp870u_init); 39711da177e4SLinus Torvalds module_exit(atp870u_exit); 39721da177e4SLinus Torvalds 3973