Annotation of linux/kernel/blk_drv/scsi/seagate.c, revision 1.1.1.2

1.1       root        1: /*
                      2:  *     seagate.c Copyright (C) 1992 Drew Eckhardt 
                      3:  *     low level scsi driver for ST01/ST02 by
                      4:  *             Drew Eckhardt 
                      5:  *
                      6:  *     <[email protected]>
                      7:  */
                      8: 
                      9: #include <linux/config.h>
                     10: 
1.1.1.2 ! root       11: #if defined(CONFIG_SCSI_SEAGATE) || defined(CONFIG_SCSI_FD_88x) 
        !            12: #include <asm/io.h>
        !            13: #include <asm/system.h>
1.1       root       14: #include <linux/sched.h>
                     15: #include "seagate.h"
                     16: #include "scsi.h"
                     17: #include "hosts.h"
                     18: 
1.1.1.2 ! root       19: extern void seagate_intr(void);
        !            20: static int internal_command(unsigned char target, const void *cmnd,
        !            21:                         void *buff, int bufflen, int reselect);
        !            22: void (*do_seagate)(void) = NULL;
        !            23: 
1.1       root       24: static int incommand;                  /*
                     25:                                                set if arbitration has finished and we are 
                     26:                                                in some command phase.
                     27:                                        */
                     28: 
                     29: static void *base_address = NULL;      /*
                     30:                                                Where the card ROM starts,
                     31:                                                used to calculate memory mapped
                     32:                                                register location.
                     33:                                        */
                     34: static volatile int abort_confirm = 0;
                     35: 
1.1.1.2 ! root       36: static volatile void *st0x_cr_sr;       /*
1.1       root       37:                                                control register write,
                     38:                                                status register read.
                     39:                                                256 bytes in length.
                     40: 
                     41:                                                Read is status of SCSI BUS,
                     42:                                                as per STAT masks.
                     43: 
                     44:                                        */
                     45: 
                     46: 
                     47: static volatile void *st0x_dr;         /*
                     48:                                                data register, read write
                     49:                                                256 bytes in length.
                     50:                                        */
                     51: 
                     52: 
                     53: static volatile int st0x_aborted=0;    /* 
                     54:                                                set when we are aborted, ie by a time out, etc.
                     55:                                        */
                     56: 
                     57:                                        /*
                     58:                                                In theory, we have a nice auto
                     59:                                                detect routine - but this 
                     60:                                                overides it. 
                     61:                                        */
                     62: 
                     63:                        
                     64: #define retcode(result) (((result) << 16) | (message << 8) | status)                   
                     65: #define STATUS (*(unsigned char *) st0x_cr_sr)
                     66: #define CONTROL STATUS 
                     67: #define DATA (*(unsigned char *) st0x_dr)
                     68: 
                     69: #ifndef OVERRIDE               
                     70: static const char *  seagate_bases[] = {(char *) 0xc8000, (char *) 0xca000, (char *) 0xcc000, (char *) 0xce000, (char *) 0xce000,
                     71:                                        (char *) 0xdc000, (char *) 0xde000};
                     72: typedef struct 
                     73:        {
                     74:        char *signature ;
                     75:        unsigned offset;
                     76:        unsigned length;
                     77:        } Signature;
                     78:        
                     79: static const Signature signatures[] = {
1.1.1.2 ! root       80: #ifdef CONFIG_SCSI_SEAGATE
1.1       root       81: {"SCSI BIOS 2.00  (C) Copyright 1987 Seagate", 15, 40},
1.1.1.2 ! root       82: 
        !            83: /*
        !            84:        The following two lines are NOT mistakes.  One detects 
        !            85:        ROM revision 3.0.0, the other 3.2.  Since seagate
        !            86:        has only one type of SCSI adapter, and this is not 
        !            87:        going to change, the "SEAGATE" and "SCSI" together
        !            88:        are probably "good enough"
        !            89: */
        !            90: 
1.1       root       91: {"SEAGATE SCSI BIOS ",16, 17},
1.1.1.2 ! root       92: {"SEAGATE SCSI BIOS ",17, 17},
        !            93: #endif
        !            94: 
        !            95: /*
        !            96:        This is for the Future Domain 88x series.  I've been told that
        !            97:        the Seagate controllers are just repackages of these, and seeing
        !            98:        early seagate BIOS bearing the Future Domain copyright,
        !            99:        I believe it.
        !           100: */
        !           101: 
        !           102: #ifdef CONFIG_SCSI_FD_88x
        !           103: {"FUTURE DOMAIN CORP. (C) 1986-1989 V6.0A7/28/90", 5, 46},
        !           104: #endif
        !           105: }
        !           106: ;
1.1       root      107: /*
                    108:        Note that the last signature handles BIOS revisions 3.0.0 and 
                    109:        3.2 - the real ID's are 
                    110: 
                    111: SEAGATE SCSI BIOS REVISION 3.0.0
                    112: SEAGATE SCSI BIOS REVISION 3.2
                    113: 
                    114: */
                    115: 
                    116: #define NUM_SIGNATURES (sizeof(signatures) / sizeof(Signature))
                    117: #endif
                    118: 
1.1.1.2 ! root      119: /*
        !           120:  * hostno stores the hostnumber, as told to us by the init routine.
        !           121:  */
        !           122: 
        !           123: static int hostno = -1;
        !           124: 
1.1       root      125: int seagate_st0x_detect (int hostnum)
                    126:        {
1.1.1.2 ! root      127: #ifndef OVERRIDE
        !           128:        int i,j;
        !           129: #endif
1.1       root      130: 
1.1.1.2 ! root      131: /*
        !           132:  *     First, we try for the manual override.
        !           133:  */
        !           134: #ifdef DEBUG 
        !           135:        printk("Autodetecting seagate ST0x\n");
        !           136: #endif
        !           137:        
        !           138:        if (hostno != -1)
        !           139:                {
        !           140:                printk ("ERROR : seagate_st0x_detect() called twice.\n");
        !           141:                return 0;
        !           142:                }
1.1       root      143:        
                    144:        base_address = NULL;
1.1.1.2 ! root      145: #ifdef OVERRIDE
        !           146:        base_address = (void *) OVERRIDE;       
        !           147: #ifdef DEBUG
        !           148:        printk("Base address overridden to %x\n", base_address);
        !           149: #endif
        !           150: #else  
        !           151: /*
        !           152:  *     To detect this card, we simply look for the signature
        !           153:  *     from the BIOS version notice in all the possible locations
        !           154:  *     of the ROM's.  This has a nice sideeffect of not trashing
        !           155:  *     any register locations that might be used by something else.
        !           156:  */
1.1       root      157: 
                    158:        for (i = 0; i < (sizeof (seagate_bases) / sizeof (char  * )); ++i)
                    159:                for (j = 0; !base_address && j < NUM_SIGNATURES; ++j)
                    160:                if (!memcmp ((void *) (seagate_bases[i] +
                    161:                    signatures[j].offset), (void *) signatures[j].signature,
                    162:                    signatures[j].length))
                    163:                        base_address = (void *) seagate_bases[i];
1.1.1.2 ! root      164:  #endif
1.1       root      165:  
                    166:        if (base_address)
                    167:                {
                    168:                st0x_cr_sr =(void *) (((unsigned char *) base_address) + 0x1a00); 
                    169:                st0x_dr = (void *) (((unsigned char *) base_address )+ 0x1c00);
1.1.1.2 ! root      170: #ifdef DEBUG
        !           171:                printk("ST0x detected. Base address = %x, cr = %x, dr = %x\n", base_address, st0x_cr_sr, st0x_dr);
        !           172: #endif
        !           173:                hostno = hostnum;
        !           174: 
        !           175: /*
        !           176:  *     At all times, we will use IRQ 5.  
        !           177:  */
        !           178:                
        !           179: #if 1
        !           180:                set_intr_gate (0x25, seagate_intr);
        !           181:                __asm__("
        !           182:                inb     $0x21, %%al
        !           183:                andb    $0xdf, %%al
        !           184:                outb    %%al, $0x21"::);
        !           185: #endif
1.1       root      186:                return -1;
                    187:                }
                    188:        else
                    189:                {
1.1.1.2 ! root      190: #ifdef DEBUG
        !           191:                printk("ST0x not detected.\n");
        !           192: #endif
1.1       root      193:                return 0;
                    194:                }
                    195:        }
                    196:         
                    197: char *seagate_st0x_info(void)
                    198: {
                    199:        static char buffer[] = "Seagate ST-0X SCSI driver by Drew Eckhardt \n"
1.1.1.2 ! root      200: "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/seagate.c,v 1.1 1992/07/24 06:27:38 root Exp root $\n";
1.1       root      201:        return buffer;
                    202: }
                    203: 
1.1.1.2 ! root      204: /*
        !           205:  * These are our saved pointers for the outstanding command that is 
        !           206:  * waiting for a reconnect
        !           207:  */
        !           208: 
        !           209: static unsigned char current_target;
        !           210: static unsigned char *current_cmnd, *current_data;
        !           211: static int current_bufflen;
        !           212: static void (*done_fn)(int, int) = NULL;
        !           213: 
        !           214: /*
        !           215:  * These control weather or not disconnect / reconnect will be attempted,
        !           216:  * or are being attempted.
        !           217:  */
        !           218: 
        !           219: #define NO_RECONNECT   0
        !           220: #define RECONNECT_NOW  1
        !           221: #define CAN_RECONNECT  2
        !           222: 
        !           223: /*
        !           224:  * This determines if we are expecting to reconnect or not.
        !           225:  */
        !           226: 
        !           227: static int should_reconnect = 0;
1.1       root      228: 
1.1.1.2 ! root      229: void seagate_unexpected_intr (void)
        !           230:        {
        !           231:        printk("scsi%d: unexpected interrupt.\n", hostno);
        !           232:        }       
        !           233:        
        !           234: /*
        !           235:  * The seagate_reconnect_intr routine is called when a target reselects the 
        !           236:  * host adapter.  This occurs on the interrupt triggered by the target 
        !           237:  * asserting SEL.
        !           238:  */
1.1       root      239: 
1.1.1.2 ! root      240: void seagate_reconnect_intr (void)
        !           241:        {
        !           242:        int temp;
        !           243:        
        !           244: #if (DEBUG & PHASE_RESELECT)
        !           245:        printk("scsi%d : seagate_reconnect_intr() called\n", hostno);
        !           246: #endif
        !           247: 
        !           248:        if (!should_reconnect)
        !           249:                seagate_unexpected_intr();
        !           250:        else
        !           251:                {
        !           252:                should_reconnect = 0;
        !           253: 
        !           254: #if (DEBUG & PHASE_RESELECT)
        !           255:                printk("scsi%d : internal_command("
        !           256:                       "%d, %08x, %08x, %d, RECONNECT_NOW\n", hostno, 
        !           257:                        current_target, current_data, current_bufflen);
        !           258: #endif
        !           259:        
        !           260:                temp =  internal_command (current_target, 
        !           261:                        current_cmnd, current_data, current_bufflen,
        !           262:                        RECONNECT_NOW);
        !           263: 
        !           264:                if (msg_byte(temp) != DISCONNECT)
        !           265:                        {
        !           266:                        if (done_fn)
        !           267:                                {
        !           268: #if (DEBUG & PHASE_RESELECT)
        !           269:                                printk("scsi%d : done_fn(%d,%08x)", hostno, 
        !           270:                                hostno, temp);
        !           271: #endif
        !           272:                                done_fn (hostno, temp);
        !           273:                                }
        !           274:                        else
        !           275:                                printk("done_fn() not defined.\n");
        !           276:                        }
        !           277:                }
        !           278:        } 
        !           279: 
        !           280: /* 
        !           281:  * The seagate_st0x_queue_command() function provides a queued interface
        !           282:  * to the seagate SCSI driver.  Basically, it just passes control onto the
        !           283:  * seagate_command() function, after fixing it so that the done_fn()
        !           284:  * is set to the one passed to the function.
        !           285:  */
        !           286: 
        !           287: int seagate_st0x_queue_command (unsigned char target, const void *cmnd,
        !           288:                                void *buff, int bufflen, void (*fn)(int, 
        !           289:                                 int))
        !           290:        {
        !           291:        int result;
        !           292: 
        !           293:        done_fn = fn;
        !           294:        current_target = target;
        !           295:        (const void *) current_cmnd = cmnd;
        !           296:        current_data = buff;
        !           297:        current_bufflen = bufflen;
        !           298: 
        !           299:        result = internal_command (target, cmnd, buff, bufflen, 
        !           300:                                   CAN_RECONNECT);
        !           301:        if (msg_byte(result) == DISCONNECT)
        !           302:                return 0;
        !           303:        else 
        !           304:                {
        !           305:                done_fn (hostno, result); 
        !           306:                return 1; 
        !           307:                }
        !           308:        }
        !           309: 
        !           310: int seagate_st0x_command (unsigned char target, const void *cmnd, 
        !           311:                        void *buff, int bufflen)
        !           312:        {
        !           313:        return internal_command (target, cmnd, buff, bufflen, 
        !           314:                                 (int) NO_RECONNECT);
        !           315:        }
        !           316:        
        !           317: static int internal_command(unsigned char target, const void *cmnd,
        !           318:                         void *buff, int bufflen, int reselect)
1.1       root      319:        {
                    320:        int len;                        
                    321:        unsigned char *data;    
1.1.1.2 ! root      322:        int clock;                      
        !           323:        int temp;
1.1       root      324: 
1.1.1.2 ! root      325: 
        !           326: #if ((DEBUG & PHASE_ETC) || (DEBUG & PRINT_COMMAND) || (DEBUG & PHASE_EXIT))   
        !           327:        int i;
        !           328: #endif
        !           329: 
        !           330: #if (DEBUG & PHASE_ETC)
        !           331:        int phase=0, newphase;
        !           332: #endif
1.1       root      333: 
                    334:        int done = 0;
                    335:        unsigned char status = 0;       
                    336:        unsigned char message = 0;
                    337:        register unsigned char status_read;
                    338: 
1.1.1.2 ! root      339:        do_seagate = seagate_unexpected_intr;
1.1       root      340: 
                    341:        len=bufflen;
                    342:        data=(unsigned char *) buff;
                    343: 
                    344:        incommand = 0;
                    345:        st0x_aborted = 0;
                    346: 
1.1.1.2 ! root      347: #if (DEBUG & PRINT_COMMAND)
        !           348:        printk ("scsi%d : target = %d, command = ", hostno, target);
        !           349:        for (i = 0; i < COMMAND_SIZE(((unsigned char *)cmnd)[0]); ++i)
        !           350:                printk("%02x ",  ((unsigned char *) cmnd)[i]);
        !           351:        printk("\n");
        !           352: #endif
        !           353: 
        !           354: #if (DEBUG & PHASE_RESELECT)
        !           355:        switch (reselect)
        !           356:        {
        !           357:        case RECONNECT_NOW :
        !           358:                printk("scsi%d : reconnecting\n", hostno);
        !           359:                break;
        !           360:        case CAN_RECONNECT :
        !           361:                printk("scsi%d : allowed to reconnect\n", hostno);
        !           362:                break;
        !           363:        default :
        !           364:                printk("scsi%d : not allowed to reconnect\n", hostno);
        !           365:        }
        !           366: #endif
1.1       root      367:        
1.1.1.2 ! root      368: 
1.1       root      369:        if (target > 6)
1.1.1.2 ! root      370:                {
        !           371:                if (reselect == RECONNECT_NOW)
        !           372:                        eoi();
1.1       root      373:                return DID_BAD_TARGET;
1.1.1.2 ! root      374:                }
1.1       root      375: 
1.1.1.2 ! root      376: /*
        !           377:  *     We work it differently depending on if this is is "the first time,"
        !           378:  *     or a reconnect.  If this is a reselct phase, then SEL will 
        !           379:  *     be asserted, and we must skip selection / arbitration phases.
        !           380:  */
1.1       root      381: 
1.1.1.2 ! root      382:        if (reselect == RECONNECT_NOW) 
        !           383:                {
        !           384: #if (DEBUG & PHASE_RESELECT)
        !           385:                printk("scsi%d : phase RESELECT \n", hostno);
        !           386: #endif
1.1       root      387: 
1.1.1.2 ! root      388: /*
        !           389:  *     At this point, we should find the logical or of our ID and the original
        !           390:  *     target's ID on the BUS, with BSY, SEL, and I/O signals asserted.
        !           391:  *
        !           392:  *     After ARBITRATION phase is completed, only SEL, BSY, and the 
        !           393:  *     target ID are asserted.  A valid initator ID is not on the bus
        !           394:  *     until IO is asserted, so we must wait for that.
        !           395:  */
        !           396:                
        !           397:                for (clock = jiffies + 10, temp = 0; (jiffies < clock) &&
        !           398:                     !(STATUS & STAT_IO););
        !           399:                
        !           400:                if (jiffies >= clock)
        !           401:                        {
        !           402: #if (DEBUG & PHASE_RESELECT)
        !           403:                        printk("scsi%d : RESELECT timed out while waiting for IO .\n",
        !           404:                                hostno);
        !           405: #endif
        !           406:                        eoi();
        !           407:                        return (DID_BAD_INTR << 16);
        !           408:                        }
1.1       root      409: 
1.1.1.2 ! root      410: /* 
        !           411:  *     After I/O is asserted by the target, we can read our ID and its
        !           412:  *     ID off of the BUS.
        !           413:  */
        !           414:  
        !           415:                if (!((temp = DATA) & 0x80))
        !           416:                        {
        !           417: #if (DEBUG & PHASE_RESELECT)
        !           418:                        printk("scsi%d : detected reconnect request to different target.\n" 
        !           419:                               "\tData bus = %d\n", hostno, temp);
        !           420: #endif
        !           421:                        eoi();
        !           422:                        return (DID_BAD_INTR << 16);
        !           423:                        }
1.1       root      424: 
1.1.1.2 ! root      425:                if (!(temp & (1 << current_target)))
        !           426:                        {
        !           427:                        printk("scsi%d : Unexpected reselect interrupt.  Data bus = %d\n",
        !           428:                                hostno, temp);
        !           429:                        eoi();
        !           430:                        return (DID_BAD_INTR << 16);
        !           431:                        }
        !           432:                 data=current_data;      /* WDE add */
        !           433:                 cmnd=current_cmnd;      /* WDE add */
        !           434:                 len=current_bufflen;    /* WDE add */
1.1       root      435: 
1.1.1.2 ! root      436: /*
        !           437:  *     We have determined that we have been selected.  At this point, 
        !           438:  *     we must respond to the reselection by asserting BSY ourselves
        !           439:  */
1.1       root      440: 
1.1.1.2 ! root      441:                CONTROL = (BASE_CMD | CMD_DRVR_ENABLE | CMD_BSY);
1.1       root      442: 
1.1.1.2 ! root      443: /*
        !           444:  *     The target will drop SEL, and raise BSY, at which time we must drop
        !           445:  *     BSY.
        !           446:  */
        !           447: 
        !           448:                for (clock = jiffies + 10; (jiffies < clock) &&  (STATUS & STAT_SEL););
        !           449: 
        !           450:                if (jiffies >= clock)
        !           451:                        { 
        !           452:                        CONTROL = (BASE_CMD | CMD_INTR);
        !           453: #if (DEBUG & PHASE_RESELECT)
        !           454:                        printk("scsi%d : RESELECT timed out while waiting for SEL.\n",
        !           455:                                hostno);
        !           456: #endif
        !           457:                        eoi();
        !           458:                        return (DID_BAD_INTR << 16);                             
        !           459:                        }
1.1       root      460: 
1.1.1.2 ! root      461:                CONTROL = BASE_CMD;
1.1       root      462: 
1.1.1.2 ! root      463: /*
        !           464:  *     At this point, we have connected with the target and can get 
        !           465:  *     on with our lives.
        !           466:  */     
        !           467:                eoi();
        !           468:                }       
        !           469:        else
        !           470:                {       
        !           471: #if (DEBUG & PHASE_BUS_FREE)
        !           472:                printk ("scsi%d : phase = BUS FREE \n", hostno);
        !           473: #endif
1.1       root      474: 
1.1.1.2 ! root      475: /*
        !           476:  *     BUS FREE PHASE
        !           477:  *
        !           478:  *     On entry, we make sure that the BUS is in a BUS FREE
        !           479:  *     phase, by insuring that both BSY and SEL are low for
        !           480:  *     at least one bus settle delay.  Several reads help
        !           481:  *     eliminate wire glitch.
        !           482:  */
        !           483: 
        !           484:                clock = jiffies + ST0X_BUS_FREE_DELAY;  
        !           485: 
        !           486:                while (((STATUS |  STATUS | STATUS) & 
        !           487:                         (STAT_BSY | STAT_SEL)) && 
        !           488:                         (!st0x_aborted) && (jiffies < clock));
        !           489: 
        !           490:                if (jiffies > clock)
        !           491:                        return retcode(DID_BUS_BUSY);
        !           492:                else if (st0x_aborted)
        !           493:                        return retcode(st0x_aborted);
1.1       root      494: 
1.1.1.2 ! root      495: /*
        !           496:  *     Bus free has been detected, within BUS settle.  I used to 
        !           497:  *     support an arbitration phase - however, on the Seagate, this 
        !           498:  *     degraded performance by a factor > 10 - so it is no more.
        !           499:  */
1.1       root      500: 
1.1.1.2 ! root      501: /*
        !           502:  *     SELECTION PHASE
        !           503:  *
        !           504:  *     Now, we select the disk, giving it the SCSI ID at data
        !           505:  *     and a command of PARITY if necessary, and we raise SEL.
        !           506:  */
1.1       root      507: 
1.1.1.2 ! root      508: #if (DEBUG & PHASE_SELECTION)
        !           509:                printk("scsi%d : phase = SELECTION\n", hostno);
        !           510: #endif
        !           511: 
        !           512:                clock = jiffies + ST0X_SELECTION_DELAY;
        !           513: 
        !           514: /*
        !           515:  *     If we wish to disconnect, we should request a MESSAGE OUT
        !           516:  *     at this point.  Technically, ATTN should be raised before 
        !           517:  *     SEL = true and BSY = false (from arbitration), but I think this 
        !           518:  *     should do.
        !           519:  */
        !           520:                if (reselect)
        !           521:                        CONTROL = BASE_CMD | CMD_DRVR_ENABLE |
        !           522:                                CMD_ATTN;
        !           523:                
        !           524: /*
        !           525:  *     We must assert both our ID and our target's ID on the bus.
        !           526:  */
        !           527:                DATA = (unsigned char) ((1 << target) | 0x80);
        !           528: 
        !           529: /*
        !           530:  *     If we are allowing ourselves to reconnect, then I will keep 
        !           531:  *     ATTN raised so we get MSG OUT. 
        !           532:  */ 
        !           533:                CONTROL =  BASE_CMD | CMD_DRVR_ENABLE | CMD_SEL | 
        !           534:                        (reselect ? CMD_ATTN : 0);
        !           535: 
        !           536: /*
        !           537:  *     When the SCSI device decides that we're gawking at it, it will 
        !           538:  *     respond by asserting BUSY on the bus.
        !           539:  */
        !           540:                while (!((status_read = STATUS) & STAT_BSY) && 
        !           541:                        (jiffies < clock) && !st0x_aborted)
1.1       root      542: 
                    543: #if (DEBUG & PHASE_SELECTION)
                    544:                {
                    545:                temp = clock - jiffies;
                    546: 
                    547:                if (!(jiffies % 5))
                    548:                        printk("seagate_st0x_timeout : %d            \r",temp);
                    549:        
                    550:                }
                    551:                printk("Done.                                             \n\r");
1.1.1.2 ! root      552:                printk("scsi%d : status = %02x, seagate_st0x_timeout = %d, aborted = %02x \n", 
        !           553:                        hostno, status_read, temp, st0x_aborted);
1.1       root      554: #else
                    555:                ;
                    556: #endif
                    557:        
                    558: 
1.1.1.2 ! root      559:                if ((jiffies > clock)  || (!st0x_aborted && 
        !           560:                        !(status_read & STAT_BSY)))
1.1       root      561:                        {
1.1.1.2 ! root      562: #if (DEBUG & PHASE_SELECT)
        !           563:                        printk ("scsi%d : NO CONNECT with target %d, status = %x \n", 
        !           564:                                hostno, target, STATUS);
        !           565: #endif
        !           566:                        return retcode(DID_NO_CONNECT);
1.1       root      567:                        }
                    568: 
1.1.1.2 ! root      569: /*
        !           570:  *     If we have been aborted, and we have a command in progress, IE the 
        !           571:  *     target still has BSY asserted, then we will reset the bus, and 
        !           572:  *     notify the midlevel driver to expect sense.
        !           573:  */
1.1       root      574: 
1.1.1.2 ! root      575:                if (st0x_aborted)
        !           576:                        {
        !           577:                        CONTROL = BASE_CMD;
        !           578:                        if (STATUS & STAT_BSY)
        !           579:                                {
        !           580:                                seagate_st0x_reset();
        !           581:                                return retcode(DID_RESET);
        !           582:                                }
        !           583:                        return retcode(st0x_aborted);
        !           584:                        }       
        !           585:                }
1.1       root      586: 
1.1.1.2 ! root      587:        CONTROL = BASE_CMD | CMD_DRVR_ENABLE | 
        !           588:                ((reselect == CAN_RECONNECT) ? CMD_ATTN : 0) ;
        !           589:        
        !           590: /*
        !           591:  *     INFORMATION TRANSFER PHASE
        !           592:  *
        !           593:  *     The nasty looking read / write inline assembler loops we use for 
        !           594:  *     DATAIN and DATAOUT phases are approximately 4-5 times as fast as 
        !           595:  *     the 'C' versions - since we're moving 1024 bytes of data, this
        !           596:  *     really adds up.
        !           597:  */
        !           598: 
        !           599: #if (DEBUG & PHASE_ETC)
        !           600:        printk("scsi%d : phase = INFORMATION TRANSFER\n", hostno);
        !           601: #endif  
1.1       root      602: 
                    603:        incommand = 1;
                    604: 
                    605: 
1.1.1.2 ! root      606: /*
        !           607:  *     Now, we poll the device for status information,
        !           608:  *     and handle any requests it makes.  Note that since we are unsure of 
        !           609:  *     how much data will be flowing across the system, etc and cannot 
        !           610:  *     make reasonable timeouts, that we will instead have the midlevel
        !           611:  *     driver handle any timeouts that occur in this phase.
        !           612:  */
1.1       root      613: 
                    614:        while (((status_read = STATUS) & STAT_BSY) && !st0x_aborted && !done) 
1.1.1.2 ! root      615:                {
        !           616: #ifdef PARITY
        !           617:                if (status_read & STAT_PARITY)
1.1       root      618:                        {
1.1.1.2 ! root      619:                        done = 1;
        !           620:                        st0x_aborted = DID_PARITY;
        !           621:                        }       
        !           622: #endif
1.1       root      623: 
1.1.1.2 ! root      624:                if (status_read & STAT_REQ)
        !           625:                        {
        !           626: #if (DEBUG & PHASE_ETC)
        !           627:                        if ((newphase = (status_read & REQ_MASK)) != phase)
1.1       root      628:                                {
1.1.1.2 ! root      629:                                phase = newphase;
        !           630:                                switch (phase)
        !           631:                                {
        !           632:                                case REQ_DATAOUT: 
        !           633:                                        printk("scsi%d : phase = DATA OUT\n",
        !           634:                                                hostno); 
        !           635:                                        break;
        !           636:                                case REQ_DATAIN : 
        !           637:                                        printk("scsi%d : phase = DATA IN\n",
        !           638:                                                hostno); 
        !           639:                                        break;
        !           640:                                case REQ_CMDOUT : 
        !           641:                                        printk("scsi%d : phase = COMMAND OUT\n",
        !           642:                                                hostno); 
        !           643:                                        break;
        !           644:                                case REQ_STATIN :
        !           645:                                         printk("scsi%d : phase = STATUS IN\n",
        !           646:                                                hostno); 
        !           647:                                        break;
        !           648:                                case REQ_MSGOUT :
        !           649:                                        printk("scsi%d : phase = MESSAGE OUT\n",
        !           650:                                                hostno); 
        !           651:                                        break;
        !           652:                                case REQ_MSGIN :
        !           653:                                        printk("scsi%d : phase = MESSAGE IN\n",
        !           654:                                                hostno);
        !           655:                                        break;
        !           656:                                default : 
        !           657:                                        printk("scsi%d : phase = UNKNOWN\n",
        !           658:                                                hostno); 
        !           659:                                        st0x_aborted = 1; 
        !           660:                                        done = 1;
        !           661:                                }       
        !           662:                                }
        !           663: #endif
1.1       root      664: 
1.1.1.2 ! root      665:                switch (status_read & REQ_MASK)
        !           666:                {                       
        !           667:                case REQ_DATAOUT : 
        !           668: 
        !           669: /*
        !           670:  *     We loop as long as we are in a data out phase, there is data to send, 
        !           671:  *     and BSY is still active.
        !           672:  */
        !           673:                __asm__ ("
1.1       root      674: 
                    675: /*
                    676:        Local variables : 
                    677:        len = ecx
                    678:        data = esi
                    679:        st0x_cr_sr = ebx
                    680:        st0x_dr =  edi
                    681: 
                    682:        Test for any data here at all.
                    683: */
                    684:        movl %0, %%esi          /* local value of data */
                    685:        movl %1, %%ecx          /* local value of len */        
                    686:        orl %%ecx, %%ecx
                    687:        jz 2f
                    688: 
                    689:        cld
                    690: 
                    691:        movl _st0x_cr_sr, %%ebx
                    692:        movl _st0x_dr, %%edi
                    693:        
                    694: 1:     movb (%%ebx), %%al
                    695: /*
                    696:        Test for BSY
                    697: */
                    698: 
                    699:        test $1, %%al 
                    700:        jz 2f
                    701: 
                    702: /*
                    703:        Test for data out phase - STATUS & REQ_MASK should be REQ_DATAOUT, which is 0.
                    704: */
                    705:        test $0xe, %%al
                    706:        jnz 2f  
                    707: /*
                    708:        Test for REQ
                    709: */     
                    710:        test $0x10, %%al
                    711:        jz 1b
                    712:        lodsb
                    713:        movb %%al, (%%edi) 
                    714:        loop 1b
                    715: 
                    716: 2: 
                    717:        movl %%esi, %2
                    718:        movl %%ecx, %3
                    719:                                                                        ":
                    720: /* output */
                    721: "=r" (data), "=r" (len) :
                    722: /* input */
                    723: "0" (data), "1" (len) :
                    724: /* clobbered */
                    725: "ebx", "ecx", "edi", "esi"); 
                    726: 
1.1.1.2 ! root      727:                        break;
1.1       root      728: 
1.1.1.2 ! root      729:                case REQ_DATAIN : 
        !           730: /*
        !           731:  *     We loop as long as we are in a data in phase, there is room to read, 
        !           732:  *     and BSY is still active
        !           733:  */
1.1       root      734:  
1.1.1.2 ! root      735:                        __asm__ ("
1.1       root      736: /*
                    737:        Local variables : 
                    738:        ecx = len
                    739:        edi = data
                    740:        esi = st0x_cr_sr
                    741:        ebx = st0x_dr
                    742: 
                    743:        Test for room to read
                    744: */
                    745: 
                    746:        movl %0, %%edi          /* data */
                    747:        movl %1, %%ecx          /* len */
                    748:        orl %%ecx, %%ecx
                    749:        jz 2f
                    750: 
                    751:        cld
                    752:        movl _st0x_cr_sr, %%esi
                    753:        movl _st0x_dr, %%ebx
                    754: 
                    755: 1:     movb (%%esi), %%al
                    756: /*
                    757:        Test for BSY
                    758: */
                    759: 
                    760:        test $1, %%al 
                    761:        jz 2f
                    762: 
                    763: /*
                    764:        Test for data in phase - STATUS & REQ_MASK should be REQ_DATAIN, = STAT_IO, which is 4.
                    765: */
                    766:        movb $0xe, %%ah 
                    767:        andb %%al, %%ah
                    768:        cmpb $0x04, %%ah
                    769:        jne 2f
                    770:                
                    771: /*
                    772:        Test for REQ
                    773: */     
                    774:        test $0x10, %%al
                    775:        jz 1b
                    776: 
                    777:        movb (%%ebx), %%al      
                    778:        stosb   
                    779:        loop 1b
                    780: 
                    781: 2:     movl %%edi, %2          /* data */
                    782:        movl %%ecx, %3          /* len */
                    783:                                                                        ":
                    784: /* output */
                    785: "=r" (data), "=r" (len) :
                    786: /* input */
                    787: "0" (data), "1" (len) :
                    788: /* clobbered */
                    789: "ebx", "ecx", "edi", "esi"); 
1.1.1.2 ! root      790:                        break;
1.1       root      791: 
1.1.1.2 ! root      792:                case REQ_CMDOUT : 
        !           793:                        while (((status_read = STATUS) & STAT_BSY) && 
        !           794:                               ((status_read & REQ_MASK) == REQ_CMDOUT))
        !           795:                                if (status_read & STAT_REQ)
        !           796:                                        DATA = *(unsigned char *) cmnd ++;
        !           797:                        break;
        !           798:        
        !           799:                case REQ_STATIN : 
        !           800:                        status = DATA;
        !           801:                        break;
        !           802:                                
        !           803:                case REQ_MSGOUT : 
        !           804: /*
        !           805:  *     We can only have sent a MSG OUT if we requested to do this 
        !           806:  *     by raising ATTN.  So, we must drop ATTN.
        !           807:  */
        !           808: 
        !           809:                        CONTROL = BASE_CMD | CMD_DRVR_ENABLE;
        !           810: /*
        !           811:  *     If we are reconecting, then we must send an IDENTIFY message in 
        !           812:  *      response  to MSGOUT.
        !           813:  */
        !           814:                        if (reselect)
        !           815:                                {
        !           816:                                DATA = IDENTIFY(1,0);
        !           817: #if (DEBUG & (PHASE_RESELECT | PHASE_MSGOUT)) 
        !           818:                                printk("scsi%d : sent IDENTIFY message.\n", hostno);
        !           819: #endif
        !           820:                                }
        !           821:                        else  
        !           822:                                {
        !           823:                                DATA = MESSAGE_REJECT;
1.1       root      824:                                
1.1.1.2 ! root      825: #if (DEBUG & PHASE_MSGOUT)
        !           826:                                printk("scsi%d : sent MESSAGE REJECT message.\n", hostno);
        !           827: #endif
        !           828:                                }
        !           829:                        break;
1.1       root      830:                                        
1.1.1.2 ! root      831:                case REQ_MSGIN : 
        !           832:                        switch (message = DATA)
        !           833:                        {
        !           834:                        case DISCONNECT :
        !           835:                                should_reconnect = 1;
        !           836:                                 current_data = data;    /* WDE add */
        !           837:                                 current_bufflen = len;  /* WDE add */
        !           838: #if (DEBUG & (PHASE_RESELECT | PHASE_MSGIN))
        !           839:                                printk("scsi%d : disconnected.\n", hostno);
        !           840:                                done=1;
        !           841:                                break;
        !           842: #endif
        !           843:                        case COMMAND_COMPLETE :
        !           844: #if (DEBUG & PHASE_MSGIN)      
        !           845:                                printk("scsi%d : command complete.\n", hostno);
        !           846:                                done=1;
        !           847:                                break;
        !           848: #endif
        !           849:                        case ABORT :
        !           850: #if (DEBUG & PHASE_MSGIN)
        !           851:                                printk("scsi%d : abort message.\n", hostno);
        !           852: #endif
        !           853:                                done=1;
        !           854:                                break;
        !           855:                        case SAVE_POINTERS :
        !           856:                                current_data = data;    /* WDE mod */
        !           857:                                 current_bufflen = len;  /* WDE add */
        !           858: #if (DEBUG & PHASE_MSGIN)
        !           859:                                printk("scsi%d : pointers saved.\n", hostno);
        !           860: #endif 
        !           861:                                break;
        !           862:                        case RESTORE_POINTERS:
        !           863:                                data=current_data;      /* WDE mod */
        !           864:                                cmnd=current_cmnd;
        !           865: #if (DEBUG & PHASE_MSGIN)
        !           866:                                printk("scsi%d : pointers restored.\n", hostno);
        !           867: #endif
        !           868:                                break;
        !           869:                        default:
1.1       root      870: 
1.1.1.2 ! root      871: /*
        !           872:  *     IDENTIFY distinguishes itself from the other messages by setting the
        !           873:  *     high byte.
        !           874:  */
        !           875: 
        !           876:                                if (message & 0x80)
        !           877:                                        {
        !           878: #if (DEBUG & PHASE_MSGIN)
        !           879:                                        printk("scsi%d : IDENTIFY message received from id %d, lun %d.\n",
        !           880:                                                hostno, target, message & 7);
        !           881: #endif
1.1       root      882:                                        }       
1.1.1.2 ! root      883:                                else
        !           884:                                        {
        !           885:                        
        !           886: #if (DEBUG & PHASE_MSGIN)
        !           887:                                        printk("scsi%d : unknown message %d from target %d.\n",
        !           888:                                                hostno,  message,   target);
        !           889: #endif 
        !           890:                                        }
        !           891:                        }
        !           892:                        break;
1.1       root      893: 
1.1.1.2 ! root      894:                default : 
        !           895:                        printk("scsi%d : unknown phase.\n", hostno); 
        !           896:                        st0x_aborted = DID_ERROR; 
        !           897:                }       
        !           898:                } /* while ends */
        !           899:                } /* if ends */
1.1       root      900: 
                    901: #if (DEBUG & (PHASE_DATAIN | PHASE_DATAOUT | PHASE_EXIT))
                    902:        printk("Transfered %d bytes, allowed %d additional bytes\n", (bufflen - len), len);
                    903: #endif
                    904: 
                    905: #if (DEBUG & PHASE_EXIT)
1.1.1.2 ! root      906:        printk("Buffer : \n");
        !           907:        for (i = 0; i < 20; ++i) 
        !           908:                printk ("%02x  ", ((unsigned char *) data)[i]); /* WDE mod */
        !           909:        printk("\n");
        !           910:        printk("Status = %02x, message = %02x\n", status, message);
1.1       root      911: #endif
                    912: 
                    913:        
1.1.1.2 ! root      914:        if (st0x_aborted)
        !           915:                {
        !           916:                if (STATUS & STAT_BSY)
1.1       root      917:                        {
1.1.1.2 ! root      918:                        seagate_st0x_reset();
        !           919:                        st0x_aborted = DID_RESET;
        !           920:                        }
        !           921:                abort_confirm = 1;
        !           922:                }               
1.1       root      923: 
1.1.1.2 ! root      924:        if (should_reconnect)
        !           925:                {
        !           926: #if (DEBUG & PHASE_RESELECT)
        !           927:                printk("scsi%d : exiting seagate_st0x_queue_command() with reconnect enabled.\n",
        !           928:                        hostno);
1.1       root      929: #endif
1.1.1.2 ! root      930:                do_seagate = seagate_reconnect_intr;
        !           931:                CONTROL = BASE_CMD | CMD_INTR ;
        !           932:                }
        !           933:        else
        !           934:                CONTROL = BASE_CMD;
1.1       root      935: 
1.1.1.2 ! root      936:        return retcode (st0x_aborted);
1.1       root      937:        }
                    938: 
                    939: int seagate_st0x_abort (int code)
                    940:        {
                    941:        if (code)
                    942:                st0x_aborted = code;
                    943:        else
                    944:                st0x_aborted = DID_ABORT;
                    945: 
                    946:                return 0;
                    947:        }
                    948: 
                    949: /*
                    950:        the seagate_st0x_reset function resets the SCSI bus
                    951: */
                    952:        
                    953: int seagate_st0x_reset (void)
                    954:        {
                    955:        unsigned clock;
                    956:        /*
                    957:                No timeouts - this command is going to fail because 
                    958:                it was reset.
                    959:        */
                    960: 
                    961: #ifdef DEBUG
                    962:        printk("In seagate_st0x_reset()\n");
                    963: #endif
                    964: 
                    965: 
                    966:        /* assert  RESET signal on SCSI bus.  */
                    967:                
                    968:        CONTROL = BASE_CMD  | CMD_RST;
                    969:        clock=jiffies+2;
                    970: 
                    971:        
                    972:        /* Wait.  */
                    973:        
                    974:        while (jiffies < clock);
                    975: 
                    976:        CONTROL = BASE_CMD;
                    977:        
                    978:        st0x_aborted = DID_RESET;
                    979: 
                    980: #ifdef DEBUG
                    981:        printk("SCSI bus reset.\n");
                    982: #endif
                    983:        return 0;
                    984:        }
1.1.1.2 ! root      985: 
1.1       root      986: #endif 
1.1.1.2 ! root      987: 

unix.superglobalmegacorp.com

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