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