Annotation of Gnu-Mach/linux/src/drivers/scsi/ppa.c, revision 1.1

1.1     ! root        1: /* ppa.c   --  low level driver for the IOMEGA PPA3 
        !             2:  * parallel port SCSI host adapter.
        !             3:  * 
        !             4:  * (The PPA3 is the embedded controller in the ZIP drive.)
        !             5:  * 
        !             6:  * (c) 1995,1996 Grant R. Guenther, [email protected],
        !             7:  * under the terms of the GNU Public License.
        !             8:  *
        !             9:  * Current Maintainer: David Campbell (Perth, Western Australia)
        !            10:  *                     [email protected]
        !            11:  *                     [email protected]
        !            12:  *
        !            13:  * My unoffical company acronym list is 21 pages long:
        !            14:  *      FLA:    Four letter acronym with built in facility for
        !            15:  *              future expansion to five letters.
        !            16:  */
        !            17: 
        !            18: #include <linux/config.h>
        !            19: 
        !            20: /* The following #define is to avoid a clash with hosts.c */
        !            21: #define PPA_CODE 1
        !            22: #ifndef HAVE_PC87332
        !            23: #define HAVE_PC87332    0
        !            24: #endif
        !            25: #define PPA_PROBE_SPP   0x0001
        !            26: #define PPA_PROBE_PS2   0x0002
        !            27: #define PPA_PROBE_ECR   0x0010
        !            28: #define PPA_PROBE_EPP17 0x0100
        !            29: #define PPA_PROBE_EPP19 0x0200
        !            30: int port_probe(unsigned short);
        !            31: 
        !            32: #include <linux/blk.h>
        !            33: #include "sd.h"
        !            34: #include "hosts.h"
        !            35: typedef struct {
        !            36:     int base;                  /* Actual port address          */
        !            37:     int mode;                  /* Transfer mode                */
        !            38:     int host;                  /* Host number (for proc)       */
        !            39:     Scsi_Cmnd *cur_cmd;                /* Current queued command       */
        !            40:     struct tq_struct ppa_tq;   /* Polling interupt stuff       */
        !            41:     unsigned long jstart;      /* Jiffies at start             */
        !            42:     unsigned failed:1;         /* Failure flag                 */
        !            43: } ppa_struct;
        !            44: 
        !            45: #define PPA_EMPTY \
        !            46: {-1,            /* base */      \
        !            47: PPA_AUTODETECT, /* mode */      \
        !            48: -1,             /* host */      \
        !            49: NULL,           /* cur_cmd */   \
        !            50: {0, 0, ppa_interrupt, NULL},    \
        !            51: 0,              /* jstart */    \
        !            52: 0               /* failed */    \
        !            53: }
        !            54: 
        !            55: #include "ppa.h"
        !            56: #undef CONFIG_PARPORT
        !            57: #define NO_HOSTS 4
        !            58: static ppa_struct ppa_hosts[NO_HOSTS] =
        !            59: {PPA_EMPTY, PPA_EMPTY, PPA_EMPTY, PPA_EMPTY};
        !            60: 
        !            61: #define PPA_BASE(x)    ppa_hosts[(x)].base
        !            62: 
        !            63: int base[NO_HOSTS] =
        !            64: {0x03bc, 0x0378, 0x0278, 0x0000};
        !            65: #define parbus_base    base
        !            66: #define parbus_no      NO_HOSTS
        !            67: 
        !            68: static inline int ppa_pb_claim(int host_no)
        !            69: {
        !            70:     if (ppa_hosts[host_no].cur_cmd)
        !            71:        ppa_hosts[host_no].cur_cmd->SCp.phase++;
        !            72:     return 0;
        !            73: }
        !            74: 
        !            75: /***************************************************************************
        !            76:  *                   Parallel port probing routines                        *
        !            77:  ***************************************************************************/
        !            78:   
        !            79: #ifndef MODULE
        !            80: /*
        !            81:  * Command line parameters (for built-in driver):
        !            82:  *
        !            83:  * Syntax:  ppa=base[,mode[,use_sg]]
        !            84:  *
        !            85:  * For example:  ppa=0x378   or   ppa=0x378,0,3
        !            86:  *
        !            87:  */
        !            88: 
        !            89: void ppa_setup(char *str, int *ints)
        !            90: {
        !            91:     static int x = 0;
        !            92: 
        !            93:     if (x == 0) {              /* Disable ALL known ports */
        !            94:        int i;
        !            95: 
        !            96:        for (i = 0; i < NO_HOSTS; i++)
        !            97:            parbus_base[i] = 0x0000;
        !            98:     }
        !            99:     switch (ints[0]) {
        !           100:     case 3:
        !           101:        ppa_sg = ints[3];
        !           102:     case 2:
        !           103:        ppa_hosts[x].mode = ints[2];
        !           104:        parbus_base[x] = ints[1];
        !           105:        break;
        !           106:     default:
        !           107:        printk("PPA: I only use between 2 to 3 parameters.\n");
        !           108:        break;
        !           109:     }
        !           110:     x++;
        !           111:   }
        !           112: #else
        !           113: Scsi_Host_Template driver_template = PPA;
        !           114: #include  "scsi_module.c"
        !           115: #endif
        !           116:   
        !           117: /*
        !           118:  * Start of Chipset kludges
        !           119:  */
        !           120: 
        !           121: #if HAVE_PC87332 > 0
        !           122: #warning PC87332 Kludge code included
        !           123: static inline int pc87332_port(int host_no)
        !           124: {
        !           125:     /* A routine to detect and kludge pc87332 chipsets into the
        !           126:      * "optimum" mode for parallel port data transfer.
        !           127:      * This assumes EPP is better than ECP...
        !           128:      * (Which it is for disk drives but not printers and scanners)
        !           129:      */
        !           130:     int base = ppa_hosts[host_no].base;
        !           131: 
        !           132:     /* This is where an pc87332 can hide */
        !           133:     unsigned short index_addr[4] =
        !           134:     {
        !           135:        0x0398, 0x026e, 0x015c, 0x002e
        !           136:     };
        !           137: 
        !           138:     /* Bits 0&1 of FAR (Function Address Register) which specify where
        !           139:      * the LPT port will show up at.
        !           140:      */
        !           141:     unsigned short port_ref[4] =
        !           142:     {
        !           143:        0x378, 0x3bc, 0x278, 0xffff
        !           144:     };
        !           145: 
        !           146:     unsigned char a;
        !           147:     int loop;
        !           148: 
        !           149:     for (loop = 0; loop < 4; loop++) {
        !           150:        /* Clear the "wax" out of the pc87332, only needed after hard
        !           151:         * reset.
        !           152:         */
        !           153:        inb(index_addr[loop]);
        !           154:        inb(index_addr[loop]);
        !           155:        inb(index_addr[loop]);
        !           156:        inb(index_addr[loop]);
        !           157: 
        !           158:        /* Anyone home ?? */
        !           159:        outb(0xff, index_addr[loop]);
        !           160:        a = inb(index_addr[loop]);
        !           161:        switch (a) {
        !           162:        case (0x0f):            /* PC87732 */
        !           163:            break;
        !           164:        case (0x1f):            /* PC87306 */
        !           165:            break;
        !           166:        case (0x7f):            /* PC87??? */
        !           167:            break;
        !           168:        default:
        !           169:            continue;
        !           170:        }                       /* Is this pc87332 on the desired port */
        !           171:        outb(0x01, index_addr[loop]);
        !           172:        a = inb(index_addr[loop] + 1);
        !           173:        if (port_ref[a & 0x03] != base)
        !           174:            continue;
        !           175: 
        !           176:        /* Found a pc87332 */
        !           177:        printk("NatSemi PC87332 (or variant) at 0x%04x\n", base);
        !           178: 
        !           179:        /* Try to enable EPP modes
        !           180:         * with hardware data direction
        !           181:         */
        !           182:        if (base != 0x3bc) {
        !           183:            /* EPP 1.9 */
        !           184:            outb(0x04, index_addr[loop]);
        !           185:            a = inb(index_addr[loop] + 1);
        !           186:            printk("Old reg1 = %02x\n", a);
        !           187:            /* 0x01 for EPP 1.7, 0x03 for EPP 1.9, 0x0c for ECP */
        !           188:            a = (a & 0xf0) | 0x03;
        !           189:            outb(a, index_addr[loop] + 1);
        !           190:            outb(a, index_addr[loop] + 1);
        !           191: 
        !           192:            /* Software data direction selection */
        !           193:            outb(0x02, index_addr[loop]);
        !           194:            a = inb(index_addr[loop] + 1);
        !           195:            printk("Old reg2 = %02x\n", a);
        !           196:            /* 0x80 for software, 0x00 for hardware */
        !           197:            a = (a & 0x7f) | 0x80;
        !           198:            outb(a, index_addr[loop] + 1);
        !           199:            outb(a, index_addr[loop] + 1);
        !           200:            ppa_hosts[host_no].mode = PPA_EPP_32;
        !           201:        } else {
        !           202:            /* There is not enough address space for the 0x3bc port
        !           203:             * to have EPP registers so we will kludge it into an
        !           204:             * ECP
        !           205:             * port to allow bi-directional byte mode...
        !           206:             */
        !           207:            /* ECP */
        !           208:            outb(0x04, index_addr[loop]);
        !           209:            a = inb(index_addr[loop] + 1);
        !           210:            a = (a & 0xfb) | 0x06;
        !           211:            outb(a, index_addr[loop] + 1);
        !           212:            outb(a, index_addr[loop] + 1);
        !           213:            ppa_hosts[host_no].mode = PPA_PS2;
        !           214:        }
        !           215: 
        !           216:        outb(0x04, index_addr[loop]);
        !           217:        a = inb(index_addr[loop] + 1);
        !           218:        return ppa_hosts[host_no].mode;
        !           219:     }
        !           220:     return 0;
        !           221:   }
        !           222: #else
        !           223: #define pc87332_port(x)
        !           224: #endif                         /* HAVE_PC87332 */
        !           225:   
        !           226: static inline int generic_port(int host_no)
        !           227: {
        !           228:     /* Generic parallel port detection
        !           229:      * This will try to discover if the port is
        !           230:      * EPP, ECP, PS/2 or NIBBLE (In that order, approx....)
        !           231:      */
        !           232:     unsigned int save_ctr, save_ecr, r;
        !           233:     int ppb = PPA_BASE(host_no);
        !           234: 
        !           235:     save_ctr = r_ctr(ppb);
        !           236:     save_ecr = r_ecr(ppb);
        !           237:     r = port_probe(ppb);
        !           238:     w_ecr(ppb, save_ecr);
        !           239:     w_ctr(ppb, save_ctr);
        !           240: 
        !           241:     if (r & PPA_PROBE_SPP)
        !           242:        ppa_hosts[host_no].mode = PPA_NIBBLE;
        !           243: 
        !           244:     if (r & PPA_PROBE_PS2) {
        !           245:        ppa_hosts[host_no].mode = PPA_PS2;
        !           246:        if (r & PPA_PROBE_ECR)
        !           247:            w_ecr(ppb, 0x20);
        !           248:     }
        !           249:     if ((r & PPA_PROBE_EPP17) || (r & PPA_PROBE_EPP19)) {
        !           250:        /* ppa_hosts[host_no].mode = PPA_EPP_32; */
        !           251:        if (r & PPA_PROBE_ECR)
        !           252:            w_ecr(ppb, 0x80);
        !           253:     }
        !           254:     return ppa_hosts[host_no].mode;
        !           255: }
        !           256: 
        !           257: int ppa_detect(Scsi_Host_Template * host)
        !           258: {
        !           259:     struct Scsi_Host *hreg;
        !           260:     int ports;
        !           261:     int i, nhosts;
        !           262:     unsigned short ppb;
        !           263: 
        !           264:     printk("ppa: Version %s\n", PPA_VERSION);
        !           265:     nhosts = 0;
        !           266: 
        !           267:     for (i = 0; i < parbus_no; i++) {
        !           268:        if (parbus_base[i] == 0x0000)
        !           269:            continue;
        !           270:        ppb = ppa_hosts[i].base = parbus_base[i];
        !           271: 
        !           272:        /* sanity checks */
        !           273:        if (check_region(parbus_base[i],
        !           274:                         (parbus_base[i] == 0x03bc) ? 3 : 8))
        !           275:            continue;
        !           276: 
        !           277:        pc87332_port(i);
        !           278:        if (!generic_port(i))
        !           279:            continue;
        !           280: 
        !           281:        if (ppa_init(i))
        !           282:            continue;
        !           283: 
        !           284:        /* now the glue ... */
        !           285:        switch (ppa_hosts[i].mode) {
        !           286:        case PPA_NIBBLE:
        !           287:        case PPA_PS2:
        !           288:            ports = 3;
        !           289:            break;
        !           290:        case PPA_EPP_8:
        !           291:        case PPA_EPP_16:
        !           292:        case PPA_EPP_32:
        !           293:            ports = 8;
        !           294:            break;
        !           295:        default:                /* Never gets here */
        !           296:            continue;
        !           297:        }
        !           298:        request_region(ppa_hosts[i].base, ports, "ppa");
        !           299:        host->can_queue = PPA_CAN_QUEUE;
        !           300:        host->sg_tablesize = ppa_sg;
        !           301:        hreg = scsi_register(host, 0);
        !           302:        hreg->io_port = ppa_hosts[i].base;
        !           303:        hreg->n_io_port = ports;
        !           304:        hreg->dma_channel = -1;
        !           305:        hreg->unique_id = i;
        !           306:        ppa_hosts[i].host = hreg->host_no;
        !           307:        nhosts++;
        !           308:     }
        !           309:     if (nhosts == 0)
        !           310:        return 0;
        !           311:     else
        !           312:        return 1;               /* return number of hosts detected */
        !           313: }
        !           314: 
        !           315: /* This is to give the ppa driver a way to modify the timings (and other
        !           316:  * parameters) by writing to the /proc/scsi/ppa/0 file.
        !           317:  * Very simple method really... (To simple, no error checking :( )
        !           318:  * Reason: Kernel hackers HATE having to unload and reload modules for
        !           319:  * testing...
        !           320:  * Also gives a method to use a script to obtain optimum timings (TODO)
        !           321:  */
        !           322: 
        !           323: static inline int ppa_strncmp(const char *a, const char *b, int len)
        !           324: {
        !           325:     int loop;
        !           326:     for (loop = 0; loop < len; loop++)
        !           327:        if (a[loop] != b[loop])
        !           328:            return 1;
        !           329: 
        !           330:     return 0;
        !           331: }
        !           332: static inline int ppa_proc_write(int hostno, char *buffer, int length)
        !           333: {
        !           334:     unsigned long x;
        !           335: 
        !           336:     if ((length > 5) && (ppa_strncmp(buffer, "mode=", 5) == 0)) {
        !           337:        x = simple_strtoul(buffer + 5, NULL, 0);
        !           338:        ppa_hosts[hostno].mode = x;
        !           339:        return length;
        !           340:     }
        !           341:     printk("ppa /proc: invalid variable\n");
        !           342:     return (-EINVAL);
        !           343: }
        !           344: 
        !           345: int ppa_proc_info(char *buffer, char **start, off_t offset,
        !           346:                  int length, int hostno, int inout)
        !           347: {
        !           348:     int i;
        !           349:     int len = 0;
        !           350: 
        !           351:     for (i = 0; i < 4; i++)
        !           352:        if (ppa_hosts[i].host == hostno)
        !           353:            break;
        !           354: 
        !           355:     if (inout)
        !           356:        return ppa_proc_write(i, buffer, length);
        !           357: 
        !           358:     len += sprintf(buffer + len, "Version : %s\n", PPA_VERSION);
        !           359:     len += sprintf(buffer + len, "Port    : 0x%04x\n", ppa_hosts[i].base);
        !           360:     len += sprintf(buffer + len, "Mode    : %s\n", PPA_MODE_STRING[ppa_hosts[i].mode]);
        !           361: 
        !           362:     /* Request for beyond end of buffer */
        !           363:     if (offset > len)
        !           364:        return 0;
        !           365: 
        !           366:     *start = buffer + offset;
        !           367:     len -= offset;
        !           368:     if (len > length)
        !           369:        len = length;
        !           370:     return len;
        !           371: }                              /* end of ppa.c */
        !           372: static int device_check(int host_no);
        !           373: 
        !           374: #if PPA_DEBUG > 0
        !           375: #define ppa_fail(x,y) printk("ppa: ppa_fail(%i) from %s at line %d\n",\
        !           376:           y, __FUNCTION__, __LINE__); ppa_fail_func(x,y);
        !           377: static inline void ppa_fail_func(int host_no, int error_code)
        !           378: #else
        !           379: static inline void ppa_fail(int host_no, int error_code)
        !           380:   #endif
        !           381: {
        !           382:     /* If we fail a device then we trash status / message bytes */
        !           383:     if (ppa_hosts[host_no].cur_cmd) {
        !           384:        ppa_hosts[host_no].cur_cmd->result = error_code << 16;
        !           385:        ppa_hosts[host_no].failed = 1;
        !           386:     }
        !           387: }
        !           388: 
        !           389: /*
        !           390:  * Wait for the high bit to be set.
        !           391:  * 
        !           392:  * In principle, this could be tied to an interrupt, but the adapter
        !           393:  * doesn't appear to be designed to support interrupts.  We spin on
        !           394:  * the 0x80 ready bit. 
        !           395:  */
        !           396: static unsigned char ppa_wait(int host_no)
        !           397: {
        !           398:     int k;
        !           399:     unsigned short ppb = PPA_BASE(host_no);
        !           400:     unsigned char r;
        !           401: 
        !           402:     k = PPA_SPIN_TMO;
        !           403:     do {
        !           404:        r = r_str(ppb);
        !           405:        k--;
        !           406:        udelay(1);
        !           407:     }
        !           408:     while (!(r & 0x80) && (k));
        !           409: 
        !           410:     /*
        !           411:      * return some status information.
        !           412:      * Semantics: 0xc0 = ZIP wants more data
        !           413:      *            0xd0 = ZIP wants to send more data
        !           414:      *            0xe0 = ZIP is expecting SCSI command data
        !           415:      *            0xf0 = end of transfer, ZIP is sending status
        !           416:      */
        !           417:     if (k)
        !           418:        return (r & 0xf0);
        !           419: 
        !           420:     /* Counter expired - Time out occurred */
        !           421:     ppa_fail(host_no, DID_TIME_OUT);
        !           422:     printk("ppa timeout in ppa_wait\n");
        !           423:     return 0;                  /* command timed out */
        !           424: }
        !           425: 
        !           426: /*
        !           427:  * output a string, in whatever mode is available, according to the
        !           428:  * PPA protocol. 
        !           429:  */
        !           430: static inline void epp_reset(unsigned short ppb)
        !           431: {
        !           432:     int i;
        !           433: 
        !           434:     i = r_str(ppb);
        !           435:     w_str(ppb, i);
        !           436:     w_str(ppb, i & 0xfe);
        !           437: }
        !           438: 
        !           439: static inline void ecp_sync(unsigned short ppb)
        !           440: {
        !           441:     int i;
        !           442: 
        !           443:     if ((r_ecr(ppb) & 0xe0) != 0x80)
        !           444:        return;
        !           445: 
        !           446:     for (i = 0; i < 100; i++) {
        !           447:        if (r_ecr(ppb) & 0x01)
        !           448:            return;
        !           449:        udelay(5);
        !           450:     }
        !           451:     printk("ppa: ECP sync failed as data still present in FIFO.\n");
        !           452: }
        !           453: 
        !           454: /*
        !           455:  * Here is the asm code for the SPP/PS2 protocols for the i386.
        !           456:  * This has been optimised for speed on 386/486 machines. There will
        !           457:  * be very little improvement on the current 586+ machines as it is the
        !           458:  * IO statements which will limit throughput.
        !           459:  */
        !           460: #ifdef __i386__
        !           461: #define BYTE_OUT(reg) \
        !           462:        "       movb " #reg ",%%al\n" \
        !           463:        "       outb %%al,(%%dx)\n" \
        !           464:        "       addl $2,%%edx\n" \
        !           465:        "       movb $0x0e,%%al\n" \
        !           466:        "       outb %%al,(%%dx)\n" \
        !           467:        "       movb $0x0c,%%al\n" \
        !           468:        "       outb %%al,(%%dx)\n" \
        !           469:        "       subl $2,%%edx\n"
        !           470: 
        !           471: static inline int ppa_byte_out(unsigned short base, char *buffer, unsigned int len)
        !           472: {
        !           473:     /*
        !           474:      * %eax scratch
        !           475:      * %ebx Data to transfer
        !           476:      * %ecx Counter (Don't touch!!)
        !           477:      * %edx Port
        !           478:      * %esi Source buffer (mem pointer)
        !           479:      *
        !           480:      * In case you are wondering what the last line of the asm does...
        !           481:      * <output allocation> : <input allocation> : <trashed registers>
        !           482:      */
        !           483:     asm("shr $2,%%ecx\n" \
        !           484:        "       jz .no_more_bulk_bo\n" \
        !           485:        "       .align 4\n" \
        !           486:        ".loop_bulk_bo:\n" \
        !           487:        "       movl (%%esi),%%ebx\n" \
        !           488:        BYTE_OUT(%%bl) \
        !           489:        BYTE_OUT(%%bh) \
        !           490:        "       rorl $16,%%ebx\n" \
        !           491:        BYTE_OUT(%%bl) \
        !           492:        BYTE_OUT(%%bh) \
        !           493:        "       addl $4,%%esi\n" \
        !           494:        "       loop .loop_bulk_bo\n" \
        !           495:        "       .align 4\n" \
        !           496:        ".no_more_bulk_bo:" \
        !           497:   : "=S"(buffer): "c"(len), "d"(base), "S"(buffer):"eax", "ebx", "ecx");
        !           498: 
        !           499:     asm("andl $3,%%ecx\n" \
        !           500:        "       jz .no_more_loose_bo\n" \
        !           501:        "       .align 4\n" \
        !           502:        ".loop_loose_bo:\n" \
        !           503:        BYTE_OUT((%%esi)) \
        !           504:        "       incl %%esi\n" \
        !           505:        "       loop .loop_loose_bo\n" \
        !           506:        ".no_more_loose_bo:\n" \
        !           507:   : /* no output */ : "c"(len), "d"(base), "S"(buffer):"eax", "ebx", "ecx");
        !           508:     return 1;                  /* All went well - we hope! */
        !           509: }
        !           510: 
        !           511: #define BYTE_IN(reg) \
        !           512:        "       inb (%%dx),%%al\n" \
        !           513:        "       movb %%al," #reg "\n" \
        !           514:        "       addl $2,%%edx\n" \
        !           515:        "       movb $0x27,%%al\n" \
        !           516:        "       outb %%al,(%%dx)\n" \
        !           517:        "       movb $0x25,%%al\n" \
        !           518:        "       outb %%al,(%%dx)\n" \
        !           519:        "       subl $2,%%edx\n"
        !           520: 
        !           521: static inline int ppa_byte_in(unsigned short base, char *buffer, int len)
        !           522: {
        !           523:     /*
        !           524:      * %eax scratch
        !           525:      * %ebx Data to transfer
        !           526:      * %ecx Counter (Don't touch!!)
        !           527:      * %edx Port
        !           528:      * %esi Source buffer (mem pointer)
        !           529:      *
        !           530:      * In case you are wondering what the last line of the asm does...
        !           531:      * <output allocation> : <input allocation> : <trashed registers>
        !           532:      */
        !           533:     asm("shr $2,%%ecx\n" \
        !           534:        "       jz .no_more_bulk_bi\n" \
        !           535:        "       .align 4\n" \
        !           536:        ".loop_bulk_bi:\n" \
        !           537:        BYTE_IN(%%bl) \
        !           538:        BYTE_IN(%%bh) \
        !           539:        "       rorl $16,%%ebx\n" \
        !           540:        BYTE_IN(%%bl) \
        !           541:        BYTE_IN(%%bh) \
        !           542:        "       rorl $16,%%ebx\n" \
        !           543:        "       movl %%ebx,(%%esi)\n" \
        !           544:        "       addl $4,%%esi\n" \
        !           545:        "       loop .loop_bulk_bi\n" \
        !           546:        "       .align 4\n" \
        !           547:        ".no_more_bulk_bi:" \
        !           548:   : "=S"(buffer): "c"(len), "d"(base), "S"(buffer):"eax", "ebx", "ecx");
        !           549: 
        !           550:     asm("andl $3,%%ecx\n" \
        !           551:        "       jz .no_more_loose_bi\n" \
        !           552:        "       .align 4\n" \
        !           553:        ".loop_loose_bi:\n" \
        !           554:        BYTE_IN((%%esi)) \
        !           555:        "       incl %%esi\n" \
        !           556:        "       loop .loop_loose_bi\n" \
        !           557:        ".no_more_loose_bi:\n" \
        !           558:   : /* no output */ : "c"(len), "d"(base), "S"(buffer):"eax", "ebx", "ecx");
        !           559:     return 1;                  /* All went well - we hope! */
        !           560: }
        !           561: 
        !           562: #define NIBBLE_IN(reg) \
        !           563:        "       incl %%edx\n" \
        !           564:        "       movb $0x04,%%al\n" \
        !           565:        "       outb %%al,(%%dx)\n" \
        !           566:        "       decl %%edx\n" \
        !           567:        "       inb (%%dx),%%al\n" \
        !           568:        "       andb $0xf0,%%al\n" \
        !           569:        "       movb %%al," #reg "\n" \
        !           570:        "       incl %%edx\n" \
        !           571:        "       movb $0x06,%%al\n" \
        !           572:        "       outb %%al,(%%dx)\n" \
        !           573:        "       decl %%edx\n" \
        !           574:        "       inb (%%dx),%%al\n" \
        !           575:        "       shrb $4,%%al\n" \
        !           576:        "       orb %%al," #reg "\n"
        !           577: 
        !           578: static inline int ppa_nibble_in(unsigned short str_p, char *buffer, int len)
        !           579: {
        !           580:     /*
        !           581:      * %eax scratch
        !           582:      * %ebx Data to transfer
        !           583:      * %ecx Counter (Don't touch!!)
        !           584:      * %edx Port
        !           585:      * %esi Source buffer (mem pointer)
        !           586:      *
        !           587:      * In case you are wondering what the last line of the asm does...
        !           588:      * <output allocation> : <input allocation> : <trashed registers>
        !           589:      */
        !           590:     asm("shr $2,%%ecx\n" \
        !           591:        "       jz .no_more_bulk_ni\n" \
        !           592:        "       .align 4\n" \
        !           593:        ".loop_bulk_ni:\n" \
        !           594:        NIBBLE_IN(%%bl) \
        !           595:        NIBBLE_IN(%%bh) \
        !           596:        "       rorl $16,%%ebx\n" \
        !           597:        NIBBLE_IN(%%bl) \
        !           598:        NIBBLE_IN(%%bh) \
        !           599:        "       rorl $16,%%ebx\n" \
        !           600:        "       movl %%ebx,(%%esi)\n" \
        !           601:        "       addl $4,%%esi\n" \
        !           602:        "       loop .loop_bulk_ni\n" \
        !           603:        "       .align 4\n" \
        !           604:        ".no_more_bulk_ni:" \
        !           605:   : "=S"(buffer): "c"(len), "d"(str_p), "S"(buffer):"eax", "ebx", "ecx");
        !           606: 
        !           607:     asm("andl $3,%%ecx\n" \
        !           608:        "       jz .no_more_loose_ni\n" \
        !           609:        "       .align 4\n" \
        !           610:        ".loop_loose_ni:\n" \
        !           611:        NIBBLE_IN((%%esi)) \
        !           612:        "       incl %%esi\n" \
        !           613:        "       loop .loop_loose_ni\n" \
        !           614:        ".no_more_loose_ni:\n" \
        !           615:   : /* no output */ : "c"(len), "d"(str_p), "S"(buffer):"eax", "ebx", "ecx");
        !           616:     return 1;                  /* All went well - we hope! */
        !           617: }
        !           618: #else                          /* Old style C routines */
        !           619: 
        !           620: static inline int ppa_byte_out(unsigned short base, const char *buffer, int len)
        !           621: {
        !           622:     unsigned short ctr_p = base + 2;
        !           623:     int i;
        !           624: 
        !           625:     for (i = len; i; i--) {
        !           626:        outb(*buffer++, base);
        !           627:        outb(0xe, ctr_p);
        !           628:        outb(0xc, ctr_p);
        !           629:     }
        !           630:     return 1;                  /* All went well - we hope! */
        !           631: }
        !           632: 
        !           633: static inline int ppa_byte_in(unsigned short base, char *buffer, int len)
        !           634: {
        !           635:     unsigned short ctr_p = base + 2;
        !           636:     int i;
        !           637: 
        !           638:     for (i = len; i; i--) {
        !           639:        *buffer++ = inb(base);
        !           640:        outb(0x27, ctr_p);
        !           641:        outb(0x25, ctr_p);
        !           642:     }
        !           643:     return 1;                  /* All went well - we hope! */
        !           644: }
        !           645: 
        !           646: static inline int ppa_nibble_in(unsigned short str_p, char *buffer, int len)
        !           647: {
        !           648:     unsigned short ctr_p = str_p + 1;
        !           649:     unsigned char h, l;
        !           650:     int i;
        !           651: 
        !           652:     for (i = len; i; i--) {
        !           653:        outb(0x4, ctr_p);
        !           654:        h = inb(str_p);
        !           655:        outb(0x6, ctr_p);
        !           656:        l = inb(str_p);
        !           657:        *buffer++ = (h & 0xf0) | ((l & 0xf0) >> 4);
        !           658:     }
        !           659:     return 1;                  /* All went well - we hope! */
        !           660:   }
        !           661:   #endif
        !           662:   
        !           663: static inline int ppa_epp_out(unsigned short epp_p, unsigned short str_p, const char *buffer, int len)
        !           664: {
        !           665:     int i;
        !           666:     for (i = len; i; i--) {
        !           667:        outb(*buffer++, epp_p);
        !           668: #ifdef CONFIG_SCSI_PPA_HAVE_PEDANTIC
        !           669:        if (inb(str_p) & 0x01)
        !           670:            return 0;
        !           671:   #endif
        !           672:     }
        !           673:     return 1;
        !           674:   }
        !           675:   
        !           676: static int ppa_out(int host_no, char *buffer, int len)
        !           677: {
        !           678:     int r;
        !           679:     unsigned short ppb = PPA_BASE(host_no);
        !           680: 
        !           681:     r = ppa_wait(host_no);
        !           682: 
        !           683:     if ((r & 0x50) != 0x40) {
        !           684:        ppa_fail(host_no, DID_ERROR);
        !           685:        return 0;
        !           686:     }
        !           687:     switch (ppa_hosts[host_no].mode) {
        !           688:     case PPA_NIBBLE:
        !           689:     case PPA_PS2:
        !           690:        /* 8 bit output, with a loop */
        !           691:        r = ppa_byte_out(ppb, buffer, len);
        !           692:        break;
        !           693: 
        !           694:     case PPA_EPP_32:
        !           695:     case PPA_EPP_16:
        !           696:     case PPA_EPP_8:
        !           697:        epp_reset(ppb);
        !           698:        w_ctr(ppb, 0x4);
        !           699: #ifdef CONFIG_SCSI_PPA_HAVE_PEDANTIC
        !           700:        r = ppa_epp_out(ppb + 4, ppb + 1, buffer, len);
        !           701: #else
        !           702:        if (!(((long) buffer | len) & 0x03))
        !           703:            outsl(ppb + 4, buffer, len >> 2);
        !           704:        else
        !           705:            outsb(ppb + 4, buffer, len);
        !           706:        w_ctr(ppb, 0xc);
        !           707:        r = !(r_str(ppb) & 0x01);
        !           708: #endif
        !           709:        w_ctr(ppb, 0xc);
        !           710:        ecp_sync(ppb);
        !           711:        break;
        !           712: 
        !           713:     default:
        !           714:        printk("PPA: bug in ppa_out()\n");
        !           715:        r = 0;
        !           716:     }
        !           717:     return r;
        !           718: }
        !           719: 
        !           720: static inline int ppa_epp_in(int epp_p, int str_p, char *buffer, int len)
        !           721: {
        !           722:     int i;
        !           723:     for (i = len; i; i--) {
        !           724:        *buffer++ = inb(epp_p);
        !           725: #ifdef CONFIG_SCSI_PPA_HAVE_PEDANTIC
        !           726:        if (inb(str_p) & 0x01)
        !           727:            return 0;
        !           728: #endif
        !           729:     }
        !           730:     return 1;
        !           731:   }
        !           732:   
        !           733: static int ppa_in(int host_no, char *buffer, int len)
        !           734: {
        !           735:     int r;
        !           736:     unsigned short ppb = PPA_BASE(host_no);
        !           737: 
        !           738:     r = ppa_wait(host_no);
        !           739: 
        !           740:     if ((r & 0x50) != 0x50) {
        !           741:        ppa_fail(host_no, DID_ERROR);
        !           742:        return 0;
        !           743:     }
        !           744:     switch (ppa_hosts[host_no].mode) {
        !           745:     case PPA_NIBBLE:
        !           746:        /* 4 bit input, with a loop */
        !           747:        r = ppa_nibble_in(ppb + 1, buffer, len);
        !           748:        w_ctr(ppb, 0xc);
        !           749:        break;
        !           750: 
        !           751:     case PPA_PS2:
        !           752:        /* 8 bit input, with a loop */
        !           753:        w_ctr(ppb, 0x25);
        !           754:        r = ppa_byte_in(ppb, buffer, len);
        !           755:        w_ctr(ppb, 0x4);
        !           756:        w_ctr(ppb, 0xc);
        !           757:        break;
        !           758: 
        !           759:     case PPA_EPP_32:
        !           760:     case PPA_EPP_16:
        !           761:     case PPA_EPP_8:
        !           762:        epp_reset(ppb);
        !           763:        w_ctr(ppb, 0x24);
        !           764: #ifdef CONFIG_SCSI_PPA_HAVE_PEDANTIC
        !           765:        r = ppa_epp_in(ppb + 4, ppb + 1, buffer, len);
        !           766:   #else
        !           767:        if (!(((long) buffer | len) & 0x03))
        !           768:            insl(ppb + 4, buffer, len >> 2);
        !           769:        else
        !           770:            insb(ppb + 4, buffer, len);
        !           771:        w_ctr(ppb, 0x2c);
        !           772:        r = !(r_str(ppb) & 0x01);
        !           773: #endif
        !           774:        w_ctr(ppb, 0x2c);
        !           775:        ecp_sync(ppb);
        !           776:        break;
        !           777: 
        !           778:     default:
        !           779:        printk("PPA: bug in ppa_ins()\n");
        !           780:        r = 0;
        !           781:        break;
        !           782:     }
        !           783:     return r;
        !           784: }
        !           785: 
        !           786: /* end of ppa_io.h */
        !           787: static inline void ppa_d_pulse(unsigned short ppb, unsigned char b)
        !           788: {
        !           789:     w_dtr(ppb, b);
        !           790:     w_ctr(ppb, 0xc);
        !           791:     w_ctr(ppb, 0xe);
        !           792:     w_ctr(ppb, 0xc);
        !           793:     w_ctr(ppb, 0x4);
        !           794:     w_ctr(ppb, 0xc);
        !           795: }
        !           796: 
        !           797: static void ppa_disconnect(int host_no)
        !           798: {
        !           799:     unsigned short ppb = PPA_BASE(host_no);
        !           800: 
        !           801:     ppa_d_pulse(ppb, 0);
        !           802:     ppa_d_pulse(ppb, 0x3c);
        !           803:     ppa_d_pulse(ppb, 0x20);
        !           804:     ppa_d_pulse(ppb, 0xf);
        !           805: }
        !           806: 
        !           807: static inline void ppa_c_pulse(unsigned short ppb, unsigned char b)
        !           808: {
        !           809:     w_dtr(ppb, b);
        !           810:     w_ctr(ppb, 0x4);
        !           811:     w_ctr(ppb, 0x6);
        !           812:     w_ctr(ppb, 0x4);
        !           813:     w_ctr(ppb, 0xc);
        !           814: }
        !           815: 
        !           816: static inline void ppa_connect(int host_no, int flag)
        !           817: {
        !           818:     unsigned short ppb = PPA_BASE(host_no);
        !           819: 
        !           820:     ppa_c_pulse(ppb, 0);
        !           821:     ppa_c_pulse(ppb, 0x3c);
        !           822:     ppa_c_pulse(ppb, 0x20);
        !           823:     if ((flag == CONNECT_EPP_MAYBE) &&
        !           824:        IN_EPP_MODE(ppa_hosts[host_no].mode))
        !           825:        ppa_c_pulse(ppb, 0xcf);
        !           826:     else
        !           827:        ppa_c_pulse(ppb, 0x8f);
        !           828: }
        !           829: 
        !           830: static int ppa_select(int host_no, int target)
        !           831: {
        !           832:     int k;
        !           833:     unsigned short ppb = PPA_BASE(host_no);
        !           834: 
        !           835:     /*
        !           836:      * Bit 6 (0x40) is the device selected bit.
        !           837:      * First we must wait till the current device goes off line...
        !           838:      */
        !           839:     k = PPA_SELECT_TMO;
        !           840:     do {
        !           841:        k--;
        !           842:     } while ((r_str(ppb) & 0x40) && (k));
        !           843:     if (!k)
        !           844:        return 0;
        !           845: 
        !           846:     w_dtr(ppb, (1 << target));
        !           847:     w_ctr(ppb, 0xe);
        !           848:     w_ctr(ppb, 0xc);
        !           849:     w_dtr(ppb, 0x80);          /* This is NOT the initator */
        !           850:     w_ctr(ppb, 0x8);
        !           851: 
        !           852:     k = PPA_SELECT_TMO;
        !           853:     do {
        !           854:        k--;
        !           855:     }
        !           856:     while (!(r_str(ppb) & 0x40) && (k));
        !           857:     if (!k)
        !           858:        return 0;
        !           859: 
        !           860:     return 1;
        !           861: }
        !           862: 
        !           863: /* 
        !           864:  * This is based on a trace of what the Iomega DOS 'guest' driver does.
        !           865:  * I've tried several different kinds of parallel ports with guest and
        !           866:  * coded this to react in the same ways that it does.
        !           867:  * 
        !           868:  * The return value from this function is just a hint about where the
        !           869:  * handshaking failed.
        !           870:  * 
        !           871:  */
        !           872: static int ppa_init(int host_no)
        !           873: {
        !           874:     int retv;
        !           875:     unsigned short ppb = PPA_BASE(host_no);
        !           876: 
        !           877:     ppa_disconnect(host_no);
        !           878:     ppa_connect(host_no, CONNECT_NORMAL);
        !           879: 
        !           880:     retv = 2;                  /* Failed */
        !           881: 
        !           882:     w_ctr(ppb, 0xe);
        !           883:     if ((r_str(ppb) & 0x08) == 0x08)
        !           884:        retv--;
        !           885: 
        !           886:     w_ctr(ppb, 0xc);
        !           887:     if ((r_str(ppb) & 0x08) == 0x00)
        !           888:        retv--;
        !           889: 
        !           890:     /* This is a SCSI BUS reset signal */
        !           891:     if (!retv) {
        !           892:        w_dtr(ppb, 0x40);
        !           893:        w_ctr(ppb, 0x08);
        !           894:        udelay(30);
        !           895:        w_ctr(ppb, 0x0c);
        !           896:        udelay(1000);           /* Allow devices to settle down */
        !           897:     }
        !           898:     ppa_disconnect(host_no);
        !           899:     udelay(1000);              /* Another delay to allow devices to settle */
        !           900: 
        !           901:     if (!retv)
        !           902:        retv = device_check(host_no);
        !           903: 
        !           904:     return retv;
        !           905: }
        !           906: 
        !           907: static inline int ppa_send_command(Scsi_Cmnd * cmd)
        !           908: {
        !           909:     int host_no = cmd->host->unique_id;
        !           910:     int k;
        !           911: 
        !           912:     w_ctr(PPA_BASE(host_no), 0x0c);
        !           913: 
        !           914:     for (k = 0; k < cmd->cmd_len; k++)
        !           915:        if (!ppa_out(host_no, &cmd->cmnd[k], 1))
        !           916:            return 0;
        !           917:     return 1;
        !           918: }
        !           919: 
        !           920: /*
        !           921:  * The bulk flag enables some optimisations in the data transfer loops,
        !           922:  * it should be true for any command that transfers data in integral
        !           923:  * numbers of sectors.
        !           924:  * 
        !           925:  * The driver appears to remain stable if we speed up the parallel port
        !           926:  * i/o in this function, but not elsewhere.
        !           927:  */
        !           928: static int ppa_completion(Scsi_Cmnd * cmd)
        !           929: {
        !           930:     /* Return codes:
        !           931:      * -1     Error
        !           932:      *  0     Told to schedule
        !           933:      *  1     Finished data transfer
        !           934:      */
        !           935:     int host_no = cmd->host->unique_id;
        !           936:     unsigned short ppb = PPA_BASE(host_no);
        !           937:     unsigned long start_jiffies = jiffies;
        !           938: 
        !           939:     unsigned char r, v;
        !           940:     int fast, bulk, status;
        !           941: 
        !           942:     v = cmd->cmnd[0];
        !           943:     bulk = ((v == READ_6) ||
        !           944:            (v == READ_10) ||
        !           945:            (v == WRITE_6) ||
        !           946:            (v == WRITE_10));
        !           947: 
        !           948:     /*
        !           949:      * We only get here if the drive is ready to comunicate,
        !           950:      * hence no need for a full ppa_wait.
        !           951:      */
        !           952:     r = (r_str(ppb) & 0xf0);
        !           953: 
        !           954:     while (r != (unsigned char) 0xf0) {
        !           955:        /*
        !           956:         * If we have been running for more than a full timer tick
        !           957:         * then take a rest.
        !           958:         */
        !           959:        if (jiffies > start_jiffies + 1)
        !           960:            return 0;
        !           961: 
        !           962:        if (((r & 0xc0) != 0xc0) || (cmd->SCp.this_residual <= 0)) {
        !           963:            ppa_fail(host_no, DID_ERROR);
        !           964:            return -1;          /* ERROR_RETURN */
        !           965:        }
        !           966:        /* determine if we should use burst I/O */ fast = (bulk && (cmd->SCp.this_residual >= PPA_BURST_SIZE))
        !           967:            ? PPA_BURST_SIZE : 1;
        !           968: 
        !           969:        if (r == (unsigned char) 0xc0)
        !           970:            status = ppa_out(host_no, cmd->SCp.ptr, fast);
        !           971:        else
        !           972:            status = ppa_in(host_no, cmd->SCp.ptr, fast);
        !           973: 
        !           974:        cmd->SCp.ptr += fast;
        !           975:        cmd->SCp.this_residual -= fast;
        !           976: 
        !           977:        if (!status) {
        !           978:            ppa_fail(host_no, DID_BUS_BUSY);
        !           979:            return -1;          /* ERROR_RETURN */
        !           980:        }
        !           981:        if (cmd->SCp.buffer && !cmd->SCp.this_residual) {
        !           982:            /* if scatter/gather, advance to the next segment */
        !           983:            if (cmd->SCp.buffers_residual--) {
        !           984:                cmd->SCp.buffer++;
        !           985:                cmd->SCp.this_residual = cmd->SCp.buffer->length;
        !           986:                cmd->SCp.ptr = cmd->SCp.buffer->address;
        !           987:            }
        !           988:        }
        !           989:        /* Now check to see if the drive is ready to comunicate */
        !           990:        r = (r_str(ppb) & 0xf0);
        !           991:        /* If not, drop back down to the scheduler and wait a timer tick */
        !           992:        if (!(r & 0x80))
        !           993:            return 0;
        !           994:     }
        !           995:     return 1;                  /* FINISH_RETURN */
        !           996: }
        !           997: 
        !           998: /*
        !           999:  * Since the PPA itself doesn't generate interrupts, we use
        !          1000:  * the scheduler's task queue to generate a stream of call-backs and
        !          1001:  * complete the request when the drive is ready.
        !          1002:  */
        !          1003: static void ppa_interrupt(void *data)
        !          1004: {
        !          1005:     ppa_struct *tmp = (ppa_struct *) data;
        !          1006:     Scsi_Cmnd *cmd = tmp->cur_cmd;
        !          1007: 
        !          1008:     if (!cmd) {
        !          1009:        printk("PPA: bug in ppa_interrupt\n");
        !          1010:        return;
        !          1011:     }
        !          1012:     if (ppa_engine(tmp, cmd)) {
        !          1013:        tmp->ppa_tq.data = (void *) tmp;
        !          1014:        tmp->ppa_tq.sync = 0;
        !          1015:        queue_task(&tmp->ppa_tq, &tq_timer);
        !          1016:        return;
        !          1017:     }
        !          1018:     /* Command must of completed hence it is safe to let go... */
        !          1019: #if PPA_DEBUG > 0
        !          1020:     switch ((cmd->result >> 16) & 0xff) {
        !          1021:     case DID_OK:
        !          1022:        break;
        !          1023:     case DID_NO_CONNECT:
        !          1024:        printk("ppa: no device at SCSI ID %i\n", cmd->target);
        !          1025:        break;
        !          1026:     case DID_BUS_BUSY:
        !          1027:        printk("ppa: BUS BUSY - EPP timeout detected\n");
        !          1028:        break;
        !          1029:     case DID_TIME_OUT:
        !          1030:        printk("ppa: unknown timeout\n");
        !          1031:        break;
        !          1032:     case DID_ABORT:
        !          1033:        printk("ppa: told to abort\n");
        !          1034:        break;
        !          1035:     case DID_PARITY:
        !          1036:        printk("ppa: parity error (???)\n");
        !          1037:        break;
        !          1038:     case DID_ERROR:
        !          1039:        printk("ppa: internal driver error\n");
        !          1040:        break;
        !          1041:     case DID_RESET:
        !          1042:        printk("ppa: told to reset device\n");
        !          1043:        break;
        !          1044:     case DID_BAD_INTR:
        !          1045:        printk("ppa: bad interrupt (???)\n");
        !          1046:        break;
        !          1047:     default:
        !          1048:        printk("ppa: bad return code (%02x)\n", (cmd->result >> 16) & 0xff);
        !          1049:     }
        !          1050:   #endif
        !          1051:   
        !          1052:     if (cmd->SCp.phase > 1)
        !          1053:        ppa_disconnect(cmd->host->unique_id);
        !          1054: 
        !          1055:     tmp->cur_cmd = 0;
        !          1056:     cmd->scsi_done(cmd);
        !          1057:     return;
        !          1058: }
        !          1059: 
        !          1060: static int ppa_engine(ppa_struct * tmp, Scsi_Cmnd * cmd)
        !          1061: {
        !          1062:     int host_no = cmd->host->unique_id;
        !          1063:     unsigned short ppb = PPA_BASE(host_no);
        !          1064:     unsigned char l = 0, h = 0;
        !          1065:     int retv;
        !          1066: 
        !          1067:     /* First check for any errors that may have occurred
        !          1068:      * Here we check for internal errors
        !          1069:      */
        !          1070:     if (tmp->failed)
        !          1071:        return 0;
        !          1072: 
        !          1073:     switch (cmd->SCp.phase) {
        !          1074:     case 0:                    /* Phase 0 - Waiting for parport */
        !          1075:        if ((jiffies - tmp->jstart) > HZ) {
        !          1076:            /*
        !          1077:             * We waited more than a second
        !          1078:             * for parport to call us
        !          1079:             */
        !          1080:            ppa_fail(host_no, DID_BUS_BUSY);
        !          1081:            return 0;
        !          1082:        }
        !          1083:        return 1;               /* wait until ppa_wakeup claims parport */
        !          1084:     case 1:                    /* Phase 1 - Connected */
        !          1085:        {                       /* Perform a sanity check for cable unplugged */
        !          1086:            int retv = 2;       /* Failed */
        !          1087: 
        !          1088:            ppa_connect(host_no, CONNECT_EPP_MAYBE);
        !          1089: 
        !          1090:            w_ctr(ppb, 0xe);
        !          1091:            if ((r_str(ppb) & 0x08) == 0x08)
        !          1092:                retv--;
        !          1093: 
        !          1094:            w_ctr(ppb, 0xc);
        !          1095:            if ((r_str(ppb) & 0x08) == 0x00)
        !          1096:                retv--;
        !          1097: 
        !          1098:            if (retv)
        !          1099:                if ((jiffies - tmp->jstart) > (1 * HZ)) {
        !          1100:                    printk("ppa: Parallel port cable is unplugged!!\n");
        !          1101:                    ppa_fail(host_no, DID_BUS_BUSY);
        !          1102:                    return 0;
        !          1103:                } else {
        !          1104:                    ppa_disconnect(host_no);
        !          1105:                    return 1;   /* Try again in a jiffy */
        !          1106:                }
        !          1107:            cmd->SCp.phase++;
        !          1108:        }
        !          1109: 
        !          1110:     case 2:                    /* Phase 2 - We are now talking to the scsi bus */
        !          1111:        if (!ppa_select(host_no, cmd->target)) {
        !          1112:            ppa_fail(host_no, DID_NO_CONNECT);
        !          1113:            return 0;
        !          1114:        }
        !          1115:        cmd->SCp.phase++;
        !          1116: 
        !          1117:     case 3:                    /* Phase 3 - Ready to accept a command */
        !          1118:        w_ctr(ppb, 0x0c);
        !          1119:        if (!(r_str(ppb) & 0x80))
        !          1120:            return 1;
        !          1121: 
        !          1122:        if (!ppa_send_command(cmd))
        !          1123:            return 0;
        !          1124:        cmd->SCp.phase++;
        !          1125: 
        !          1126:     case 4:                    /* Phase 4 - Setup scatter/gather buffers */
        !          1127:        if (cmd->use_sg) {
        !          1128:            /* if many buffers are available, start filling the first */
        !          1129:            cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer;
        !          1130:            cmd->SCp.this_residual = cmd->SCp.buffer->length;
        !          1131:            cmd->SCp.ptr = cmd->SCp.buffer->address;
        !          1132:        } else {
        !          1133:            /* else fill the only available buffer */
        !          1134:            cmd->SCp.buffer = NULL;
        !          1135:            cmd->SCp.this_residual = cmd->request_bufflen;
        !          1136:            cmd->SCp.ptr = cmd->request_buffer;
        !          1137:        }
        !          1138:        cmd->SCp.buffers_residual = cmd->use_sg;
        !          1139:        cmd->SCp.phase++;
        !          1140: 
        !          1141:     case 5:                    /* Phase 5 - Data transfer stage */
        !          1142:        w_ctr(ppb, 0x0c);
        !          1143:        if (!(r_str(ppb) & 0x80))
        !          1144:            return 1;
        !          1145: 
        !          1146:        retv = ppa_completion(cmd);
        !          1147:        if (retv == -1)
        !          1148:            return 0;
        !          1149:        if (retv == 0)
        !          1150:            return 1;
        !          1151:        cmd->SCp.phase++;
        !          1152: 
        !          1153:     case 6:                    /* Phase 6 - Read status/message */
        !          1154:        cmd->result = DID_OK << 16;
        !          1155:        /* Check for data overrun */
        !          1156:        if (ppa_wait(host_no) != (unsigned char) 0xf0) {
        !          1157:            ppa_fail(host_no, DID_ERROR);
        !          1158:            return 0;
        !          1159:        }
        !          1160:        if (ppa_in(host_no, &l, 1)) {   /* read status byte */
        !          1161:            /* Check for optional message byte */
        !          1162:            if (ppa_wait(host_no) == (unsigned char) 0xf0)
        !          1163:                ppa_in(host_no, &h, 1);
        !          1164:            cmd->result = (DID_OK << 16) + (h << 8) + (l & STATUS_MASK);
        !          1165:        }
        !          1166:        return 0;               /* Finished */
        !          1167:        break;
        !          1168: 
        !          1169:     default:
        !          1170:        printk("ppa: Invalid scsi phase\n");
        !          1171:     }
        !          1172:     return 0;
        !          1173: }
        !          1174: 
        !          1175: int ppa_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
        !          1176: {
        !          1177:     int host_no = cmd->host->unique_id;
        !          1178: 
        !          1179:     if (ppa_hosts[host_no].cur_cmd) {
        !          1180:        printk("PPA: bug in ppa_queuecommand\n");
        !          1181:        return 0;
        !          1182:     }
        !          1183:     ppa_hosts[host_no].failed = 0;
        !          1184:     ppa_hosts[host_no].jstart = jiffies;
        !          1185:     ppa_hosts[host_no].cur_cmd = cmd;
        !          1186:     cmd->scsi_done = done;
        !          1187:     cmd->result = DID_ERROR << 16;     /* default return code */
        !          1188:     cmd->SCp.phase = 0;                /* bus free */
        !          1189: 
        !          1190:     ppa_pb_claim(host_no);
        !          1191: 
        !          1192:     ppa_hosts[host_no].ppa_tq.data = ppa_hosts + host_no;
        !          1193:     ppa_hosts[host_no].ppa_tq.sync = 0;
        !          1194:     queue_task(&ppa_hosts[host_no].ppa_tq, &tq_immediate);
        !          1195:     mark_bh(IMMEDIATE_BH);
        !          1196: 
        !          1197:     return 0;
        !          1198: }
        !          1199: 
        !          1200: /*
        !          1201:  * Apparently the disk->capacity attribute is off by 1 sector 
        !          1202:  * for all disk drives.  We add the one here, but it should really
        !          1203:  * be done in sd.c.  Even if it gets fixed there, this will still
        !          1204:  * work.
        !          1205:  */
        !          1206: int ppa_biosparam(Disk * disk, kdev_t dev, int ip[])
        !          1207: {
        !          1208:     ip[0] = 0x40;
        !          1209:     ip[1] = 0x20;
        !          1210:     ip[2] = (disk->capacity + 1) / (ip[0] * ip[1]);
        !          1211:     if (ip[2] > 1024) {
        !          1212:        ip[0] = 0xff;
        !          1213:        ip[1] = 0x3f;
        !          1214:        ip[2] = (disk->capacity + 1) / (ip[0] * ip[1]);
        !          1215:        if (ip[2] > 1023)
        !          1216:            ip[2] = 1023;
        !          1217:     }
        !          1218:     return 0;
        !          1219: }
        !          1220: 
        !          1221: int ppa_abort(Scsi_Cmnd * cmd)
        !          1222: {
        !          1223:     /*
        !          1224:      * There is no method for aborting commands since Iomega
        !          1225:      * have tied the SCSI_MESSAGE line high in the interface
        !          1226:      */
        !          1227: 
        !          1228:     switch (cmd->SCp.phase) {
        !          1229:     case 0:                    /* Do not have access to parport */
        !          1230:     case 1:                    /* Have not connected to interface */
        !          1231:        cmd->result = DID_ABORT;
        !          1232:        cmd->done(cmd);
        !          1233:        return SCSI_ABORT_SUCCESS;
        !          1234:        break;
        !          1235:     default:                   /* SCSI command sent, can not abort */
        !          1236:        return SCSI_ABORT_BUSY;
        !          1237:        break;
        !          1238:     }
        !          1239: }
        !          1240: 
        !          1241: int ppa_reset(Scsi_Cmnd * cmd, unsigned int x)
        !          1242: {
        !          1243:     int host_no = cmd->host->unique_id;
        !          1244:     int ppb = PPA_BASE(host_no);
        !          1245: 
        !          1246:     /*
        !          1247:      * PHASE1:
        !          1248:      * Bring the interface crashing down on whatever is running
        !          1249:      * hopefully this will kill the request.
        !          1250:      * Bring back up the interface, reset the drive (and anything
        !          1251:      * attached for that manner)
        !          1252:      */
        !          1253:     if (cmd)
        !          1254:        if (cmd->SCp.phase)
        !          1255:            ppa_disconnect(cmd->host->unique_id);
        !          1256: 
        !          1257:     ppa_connect(host_no, CONNECT_NORMAL);
        !          1258:     w_dtr(ppb, 0x40);
        !          1259:     w_ctr(ppb, 0x8);
        !          1260:     udelay(30);
        !          1261:     w_ctr(ppb, 0xc);
        !          1262:     udelay(1000);              /* delay for devices to settle down */
        !          1263:     ppa_disconnect(host_no);
        !          1264:     udelay(1000);              /* Additional delay to allow devices to settle down */
        !          1265: 
        !          1266:     /*
        !          1267:      * PHASE2:
        !          1268:      * Sanity check for the sake of mid-level driver
        !          1269:      */
        !          1270:     if (!cmd) {
        !          1271:        printk("ppa bus reset called for invalid command.\n");
        !          1272:        return SCSI_RESET_NOT_RUNNING;
        !          1273:     }
        !          1274:     /*
        !          1275:      * PHASE3:
        !          1276:      * Flag the current command as having died due to reset
        !          1277:      */
        !          1278:     ppa_connect(host_no, CONNECT_NORMAL);
        !          1279:     ppa_fail(host_no, DID_RESET);
        !          1280: 
        !          1281:     /* Since the command was already on the timer queue ppa_interrupt
        !          1282:      * will be called shortly.
        !          1283:      */
        !          1284:     return SCSI_RESET_PENDING;
        !          1285: }
        !          1286: 
        !          1287: static int device_check(int host_no)
        !          1288: {
        !          1289:     /* This routine looks for a device and then attempts to use EPP
        !          1290:        to send a command. If all goes as planned then EPP is available. */
        !          1291: 
        !          1292:     static char cmd[6] =
        !          1293:     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
        !          1294:     int loop, old_mode, status, k, ppb = PPA_BASE(host_no);
        !          1295:     unsigned char l;
        !          1296: 
        !          1297:     old_mode = ppa_hosts[host_no].mode;
        !          1298:     for (loop = 0; loop < 8; loop++) {
        !          1299:        /* Attempt to use EPP for Test Unit Ready */
        !          1300:        if ((ppb & 0x0007) == 0x0000)
        !          1301:            ppa_hosts[host_no].mode = PPA_EPP_32;
        !          1302: 
        !          1303:       second_pass:
        !          1304:        ppa_connect(host_no, CONNECT_EPP_MAYBE);
        !          1305:        /* Select SCSI device */
        !          1306:        if (!ppa_select(host_no, loop)) {
        !          1307:            ppa_disconnect(host_no);
        !          1308:            continue;
        !          1309:        }
        !          1310:        printk("ppa: Found device at ID %i, Attempting to use %s\n", loop,
        !          1311:               PPA_MODE_STRING[ppa_hosts[host_no].mode]);
        !          1312: 
        !          1313:        /* Send SCSI command */
        !          1314:        status = 1;
        !          1315:        w_ctr(ppb, 0x0c);
        !          1316:        for (l = 0; (l < 6) && (status); l++)
        !          1317:            status = ppa_out(host_no, cmd, 1);
        !          1318: 
        !          1319:        if (!status) {
        !          1320:            ppa_disconnect(host_no);
        !          1321:            ppa_connect(host_no, CONNECT_EPP_MAYBE);
        !          1322:            w_dtr(ppb, 0x40);
        !          1323:            w_ctr(ppb, 0x08);
        !          1324:            udelay(30);
        !          1325:            w_ctr(ppb, 0x0c);
        !          1326:            udelay(1000);
        !          1327:            ppa_disconnect(host_no);
        !          1328:            udelay(1000);
        !          1329:            if (ppa_hosts[host_no].mode == PPA_EPP_32) {
        !          1330:                ppa_hosts[host_no].mode = old_mode;
        !          1331:                goto second_pass;
        !          1332:            }
        !          1333:            printk("ppa: Unable to establish communication, aborting driver load.\n");
        !          1334:            return 1;
        !          1335:        }
        !          1336:        w_ctr(ppb, 0x0c);
        !          1337:        k = 1000000;            /* 1 Second */
        !          1338:        do {
        !          1339:            l = r_str(ppb);
        !          1340:            k--;
        !          1341:            udelay(1);
        !          1342:        } while (!(l & 0x80) && (k));
        !          1343: 
        !          1344:        l &= 0xf0;
        !          1345: 
        !          1346:        if (l != 0xf0) {
        !          1347:            ppa_disconnect(host_no);
        !          1348:            ppa_connect(host_no, CONNECT_EPP_MAYBE);
        !          1349:            w_dtr(ppb, 0x40);
        !          1350:            w_ctr(ppb, 0x08);
        !          1351:            udelay(30);
        !          1352:            w_ctr(ppb, 0x0c);
        !          1353:            udelay(1000);
        !          1354:            ppa_disconnect(host_no);
        !          1355:            udelay(1000);
        !          1356:            if (ppa_hosts[host_no].mode == PPA_EPP_32) {
        !          1357:                ppa_hosts[host_no].mode = old_mode;
        !          1358:                goto second_pass;
        !          1359:            }
        !          1360:            printk("ppa: Unable to establish communication, aborting driver load.\n");
        !          1361:            return 1;
        !          1362:        }
        !          1363:        ppa_disconnect(host_no);
        !          1364:        printk("ppa: Communication established with ID %i using %s\n", loop,
        !          1365:               PPA_MODE_STRING[ppa_hosts[host_no].mode]);
        !          1366:        return 0;
        !          1367:     }
        !          1368:     printk("ppa: No devices found, aborting driver load.\n");
        !          1369:     return 1;
        !          1370: }
        !          1371: 
        !          1372: #define PPA_ID "ppa: "
        !          1373: 
        !          1374: int port_probe(unsigned short port)
        !          1375: {
        !          1376:     int retv = 0;
        !          1377:     unsigned char a, b, c;
        !          1378:     unsigned int i, j;
        !          1379: 
        !          1380: 
        !          1381:     printk(PPA_ID "Probing port %04x\n", port);
        !          1382: 
        !          1383: /*                 #####  ######  ######
        !          1384:  *                #     # #     # #     #
        !          1385:  *                #       #     # #     #
        !          1386:  *                 #####  ######  ######
        !          1387:  *                      # #       #
        !          1388:  *                #     # #       #
        !          1389:  *                 #####  #       #
        !          1390:  */
        !          1391: 
        !          1392:     outb(0x0c, port + 0x402);
        !          1393:     outb(0x0c, port + 0x002);
        !          1394:     outb(0x55, port);
        !          1395:     a = inb(port);
        !          1396:     if (a != 0x55)
        !          1397:        return retv;
        !          1398:     printk(PPA_ID "    SPP port present\n");
        !          1399: 
        !          1400:     retv += PPA_PROBE_SPP;
        !          1401: 
        !          1402: /*                #######  #####  ######
        !          1403:  *                #       #     # #     #
        !          1404:  *                #       #       #     #
        !          1405:  *                #####   #       ######
        !          1406:  *                #       #       #
        !          1407:  *                #       #     # #
        !          1408:  *                #######  #####  #
        !          1409:  */
        !          1410: 
        !          1411:     for (i = 1024; i > 0; i--) {       /* clear at most 1k of data from FIFO */
        !          1412:        a = inb(port + 0x402);
        !          1413:        if ((a & 0x03) == 0x03)
        !          1414:            goto no_ecp;
        !          1415:        if (a & 0x01)
        !          1416:            break;
        !          1417:        inb(port + 0x400);      /* Remove byte from FIFO */
        !          1418:     }
        !          1419: 
        !          1420:     if (i <= 0)
        !          1421:        goto no_ecp;
        !          1422: 
        !          1423:     b = a ^ 3;
        !          1424:     outb(b, port + 0x402);
        !          1425:     c = inb(port + 0x402);
        !          1426: 
        !          1427:     if (a == c) {
        !          1428:        outb(0xc0, port + 0x402);       /* FIFO test */
        !          1429:        j = 0;
        !          1430:        while (!(inb(port + 0x402) & 0x01) && (j < 1024)) {
        !          1431:            inb(port + 0x400);
        !          1432:            j++;
        !          1433:        }
        !          1434:        if (j >= 1024)
        !          1435:            goto no_ecp;
        !          1436:        i = 0;
        !          1437:        j = 0;
        !          1438:        while (!(inb(port + 0x402) & 0x02) && (j < 1024)) {
        !          1439:            outb(0x00, port + 0x400);
        !          1440:            i++;
        !          1441:            j++;
        !          1442:        }
        !          1443:        if (j >= 1024)
        !          1444:            goto no_ecp;
        !          1445:        j = 0;
        !          1446:        while (!(inb(port + 0x402) & 0x01) && (j < 1024)) {
        !          1447:            inb(port + 0x400);
        !          1448:            j++;
        !          1449:        }
        !          1450:        if (j >= 1024)
        !          1451:            goto no_ecp;
        !          1452:        printk(PPA_ID "    ECP with a %i byte FIFO present\n", i);
        !          1453: 
        !          1454:        retv += PPA_PROBE_ECR;
        !          1455:     }
        !          1456: /*                ######   #####   #####
        !          1457:  *                #     # #     # #     #
        !          1458:  *                #     # #             #
        !          1459:  *                ######   #####   #####
        !          1460:  *                #             # #
        !          1461:  *                #       #     # #
        !          1462:  *                #        #####  #######
        !          1463:  */
        !          1464: 
        !          1465:   no_ecp:
        !          1466:     if (retv & PPA_PROBE_ECR)
        !          1467:        outb(0x20, port + 0x402);
        !          1468: 
        !          1469:     outb(0x55, port);
        !          1470:     outb(0x0c, port + 2);
        !          1471:     a = inb(port);
        !          1472:     outb(0x55, port);
        !          1473:     outb(0x2c, port + 2);
        !          1474:     b = inb(port);
        !          1475:     if (a != b) {
        !          1476:        printk(PPA_ID "    PS/2 bidirectional port present\n");
        !          1477:        retv += PPA_PROBE_PS2;
        !          1478:     }
        !          1479: /*                ####### ######  ######
        !          1480:  *                #       #     # #     #
        !          1481:  *                #       #     # #     #
        !          1482:  *                #####   ######  ######
        !          1483:  *                #       #       #
        !          1484:  *                #       #       #
        !          1485:  *                ####### #       #
        !          1486:  */
        !          1487: 
        !          1488:     if (port & 0x007) {
        !          1489:        printk(PPA_ID "    EPP not supported at this address\n");
        !          1490:        return retv;
        !          1491:     }
        !          1492:     if (retv & PPA_PROBE_ECR) {
        !          1493:        for (i = 0x00; i < 0x80; i += 0x20) {
        !          1494:            outb(i, port + 0x402);
        !          1495: 
        !          1496:            a = inb(port + 1);
        !          1497:            outb(a, port + 1);
        !          1498:            outb(a & 0xfe, port + 1);
        !          1499:            a = inb(port + 1);
        !          1500:            if (!(a & 0x01)) {
        !          1501:                printk(PPA_ID "    Failed Intel bug check. (Phony EPP in ECP)\n");
        !          1502:                return retv;
        !          1503:            }
        !          1504:        }
        !          1505:        printk(PPA_ID "    Passed Intel bug check.\n");
        !          1506:        outb(0x80, port + 0x402);
        !          1507:     }
        !          1508:     a = inb(port + 1);
        !          1509:     outb(a, port + 1);
        !          1510:     outb(a & 0xfe, port + 1);
        !          1511:     a = inb(port + 1);
        !          1512: 
        !          1513:     if (a & 0x01) {
        !          1514:        outb(0x0c, port + 0x402);
        !          1515:        outb(0x0c, port + 0x002);
        !          1516:        return retv;
        !          1517:     }
        !          1518: 
        !          1519:     outb(0x04, port + 2);
        !          1520:     inb(port + 4);
        !          1521:     a = inb(port + 1);
        !          1522:     outb(a, port + 1);
        !          1523:     outb(a & 0xfe, port + 1);
        !          1524: 
        !          1525:     if (a & 0x01) {
        !          1526:        printk(PPA_ID "    EPP 1.9 with hardware direction protocol\n");
        !          1527:        retv += PPA_PROBE_EPP19;
        !          1528:     } else {
        !          1529:        /* The EPP timeout bit was not set, this could either be:
        !          1530:         * EPP 1.7
        !          1531:         * EPP 1.9 with software direction
        !          1532:         */
        !          1533:        outb(0x24, port + 2);
        !          1534:        inb(port + 4);
        !          1535:        a = inb(port + 1);
        !          1536:        outb(a, port + 1);
        !          1537:        outb(a & 0xfe, port + 1);
        !          1538:        if (a & 0x01) {
        !          1539:            printk(PPA_ID "    EPP 1.9 with software direction protocol\n");
        !          1540:            retv += PPA_PROBE_EPP19;
        !          1541:        } else {
        !          1542:            printk(PPA_ID "    EPP 1.7\n");
        !          1543:            retv += PPA_PROBE_EPP17;
        !          1544:        }
        !          1545:     }
        !          1546: 
        !          1547:     outb(0x0c, port + 0x402);
        !          1548:     outb(0x0c, port + 0x002);
        !          1549:     return retv;
        !          1550: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.