OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [scsi/] [scsiiom.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1626 jcastillo
/***********************************************************************
2
 *      FILE NAME : SCSIIOM.C                                          *
3
 *           BY   : C.L. Huang,    ching@tekram.com.tw                 *
4
 *      Description: Device Driver for Tekram DC-390 (T) PCI SCSI      *
5
 *                   Bus Master Host Adapter                           *
6
 ***********************************************************************/
7
/* $Id: scsiiom.c,v 1.1 2005-12-20 10:17:45 jcastillo Exp $ */
8
 
9
UCHAR
10
dc390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB )
11
{
12
    USHORT wlval;
13
    UCHAR  bval, bval1;
14
 
15
    pSRB->TagNumber = 31;
16
    DC390_write8 (Scsi_Dest_ID, pDCB->UnitSCSIID);
17
    DC390_write8 (Sync_Period, pDCB->SyncPeriod);
18
    DC390_write8 (Sync_Offset, pDCB->SyncOffset);
19
    DC390_write8 (CtrlReg1, pDCB->CtrlR1);
20
    DC390_write8 (CtrlReg3, pDCB->CtrlR3);
21
    DC390_write8 (CtrlReg4, pDCB->CtrlR4);
22
    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);             /* Flush FIFO */
23
    DEBUG1(printk (KERN_INFO "DC390: Start SCSI command: %02x (Sync:%02x)\n",\
24
            pSRB->CmdBlock[0], pDCB->SyncMode);)
25
    pSRB->ScsiPhase = SCSI_NOP0;
26
    //pSRB->MsgOutBuf[0] = MSG_NOP;
27
    //pSRB->MsgCnt = 0;
28
    bval = pDCB->IdentifyMsg;
29
    if( !(pDCB->SyncMode & EN_ATN_STOP) )       /* Don't always try send Extended messages on arbitration */
30
    {
31
        if( (pSRB->CmdBlock[0] == INQUIRY) ||
32
            (pSRB->CmdBlock[0] == REQUEST_SENSE) ||
33
            (pSRB->SRBFlag & AUTO_REQSENSE) )
34
        {
35
            bval &= 0xBF;       /* No DisConn */
36
            DC390_write8 (ScsiFifo, bval);
37
            bval1 = SEL_W_ATN;
38
            pSRB->SRBState = SRB_START_;
39
            DEBUG1(printk (KERN_DEBUG "DC390: No DisCn, No TagQ (%02x, %02x)\n", bval, bval1);)
40
            if( pDCB->SyncMode & SYNC_ENABLE )
41
                {
42
                if( !(pDCB->IdentifyMsg & 7) ||         /* LUN == 0 || Cmd != INQUIRY */
43
                    (pSRB->CmdBlock[0] != INQUIRY) )
44
                {
45
                    bval1 = SEL_W_ATN_STOP;     /* Try to establish SYNC nego */
46
                    pSRB->SRBState = SRB_MSGOUT;
47
                }
48
            }
49
        }
50
        else    /* TagQ ? */
51
        {
52
            DC390_write8 (ScsiFifo, bval);
53
            if(pDCB->SyncMode & EN_TAG_QUEUEING)
54
            {
55
                DC390_write8 (ScsiFifo, MSG_SIMPLE_QTAG);
56
                DEBUG1(printk (KERN_DEBUG "DC390: %sDisCn, TagQ (%02x, %02x, %08lx)\n", (bval&0x40?"":"No "), bval, SEL_W_ATN3, pDCB->TagMask);)
57
                bval = 0; wlval = 1;
58
                while (wlval & pDCB->TagMask)
59
                  { bval++; wlval <<= 1; };
60
                pDCB->TagMask |= wlval;
61
                DC390_write8 (ScsiFifo, bval);
62
                pSRB->TagNumber = bval;
63
                DEBUG1(printk (KERN_DEBUG "DC390: SRB %p (Cmd %li), Tag %02x queued\n", pSRB, pSRB->pcmd->pid, bval);)
64
                bval1 = SEL_W_ATN3;
65
                pSRB->SRBState = SRB_START_;
66
            }
67
            else        /* No TagQ */
68
            {
69
                bval1 = SEL_W_ATN;
70
                DEBUG1(printk (KERN_DEBUG "DC390: %sDisCn, No TagQ (%02x, %02x, %08lx)\n", (bval&0x40?"":"No "), bval, bval1, pDCB->TagMask);)
71
                pSRB->SRBState = SRB_START_;
72
            }
73
        }
74
 
75
    }
76
    else        /* ATN_STOP: Always try to establish Sync nego */
77
    {
78
        if( (pSRB->CmdBlock[0] == INQUIRY) ||
79
            (pSRB->CmdBlock[0] == REQUEST_SENSE) ||
80
            (pSRB->SRBFlag & AUTO_REQSENSE) )
81
        {
82
            bval &= 0xBF;       /* No DisConn */
83
            DC390_write8 (ScsiFifo, bval);
84
            bval1 = SEL_W_ATN;
85
            DEBUG1(printk (KERN_DEBUG "DC390: No DisCn, No TagQ (%02x, %02x)\n", bval, bval1);)
86
            pSRB->SRBState = SRB_START_;
87
              /* ??? */
88
            if( pDCB->SyncMode & SYNC_ENABLE )
89
            {
90
                if( !(pDCB->IdentifyMsg & 7) ||         /* LUN == 0 || Cmd != INQUIRY */
91
                    (pSRB->CmdBlock[0] != INQUIRY) )
92
                {
93
                    bval1 = SEL_W_ATN_STOP;     /* Try to establish Sync nego */
94
                    pSRB->SRBState = SRB_MSGOUT;
95
                }
96
            }
97
        }
98
        else    /* TagQ ? */
99
        {
100
            DC390_write8 (ScsiFifo, bval);
101
            if(pDCB->SyncMode & EN_TAG_QUEUEING)
102
            {
103
                pSRB->MsgOutBuf[0] = MSG_SIMPLE_QTAG;
104
                DEBUG1(printk (KERN_DEBUG "DC390: %sDisCn, TagQ (%02x, %02x, %08lx)\n", (bval&0x40?"":"No "), bval, SEL_W_ATN_STOP, pDCB->TagMask);)
105
                bval = 0; wlval = 1;
106
                while (wlval & pDCB->TagMask)
107
                  { bval++; wlval <<= 1; };
108
                pDCB->TagMask |= wlval;
109
                pSRB->TagNumber = bval;
110
                DEBUG1(printk (KERN_DEBUG "DC390: SRB %p (Cmd %li), Tag %02x queued\n", pSRB, pSRB->pcmd->pid, bval);)
111
                pSRB->MsgOutBuf[1] = bval;
112
                pSRB->MsgCnt = 2;
113
                bval1 = SEL_W_ATN_STOP;
114
                pSRB->SRBState = SRB_START_;    /* ?? */
115
            }
116
            else        /* No TagQ */
117
            {
118
                pSRB->MsgOutBuf[0] = MSG_NOP;
119
                pSRB->MsgCnt = 1;
120
                pSRB->SRBState = SRB_START_;
121
                bval1 = SEL_W_ATN_STOP;
122
                DEBUG1(printk (KERN_DEBUG "DC390: %sDisCn, No TagQ (%02x, %02x, %08lx)\n", (bval&0x40?"":"No "), bval, bval1, pDCB->TagMask);)
123
            };
124
        }
125
    }
126
    if (bval1 != SEL_W_ATN_STOP)
127
      { /* Command is written in CommandPhase, if SEL_W_ATN_STOP ... */
128
        if( pSRB->SRBFlag & AUTO_REQSENSE )
129
          {
130
            bval = 0;
131
            DC390_write8 (ScsiFifo, REQUEST_SENSE);
132
            DC390_write8 (ScsiFifo, pDCB->IdentifyMsg << 5);
133
            DC390_write8 (ScsiFifo, bval);
134
            DC390_write8 (ScsiFifo, bval);
135
            DC390_write8 (ScsiFifo, sizeof(pSRB->pcmd->sense_buffer));
136
            DC390_write8 (ScsiFifo, bval);
137
            DEBUG1(printk (KERN_DEBUG "DC390: AutoReqSense !\n");)
138
          }
139
        else    /* write cmnd to bus */
140
          {
141
            PUCHAR ptr; UCHAR i;
142
            ptr = (PUCHAR) pSRB->CmdBlock;
143
            for (i=0; i<pSRB->ScsiCmdLen; i++)
144
              DC390_write8 (ScsiFifo, *(ptr++));
145
          };
146
      }
147
 
148
    /* Check if we can't win arbitration */
149
    if (DC390_read8 (Scsi_Status) & INTERRUPT)
150
    {
151
        pSRB->SRBState = SRB_READY;
152
        pDCB->TagMask &= ~( 1 << pSRB->TagNumber );
153
        DEBUG0(printk (KERN_WARNING "DC390: Interrupt during StartSCSI!\n");)
154
        return 1;
155
    }
156
    else
157
    {
158
        pSRB->ScsiPhase = SCSI_NOP1;
159
        DEBUG0(if (pACB->pActiveDCB)    \
160
                    printk (KERN_WARNING "DC390: ActiveDCB != 0\n");)
161
        DEBUG0(if (pDCB->pActiveSRB)    \
162
                    printk (KERN_WARNING "DC390: ActiveSRB != 0\n");)
163
        pACB->pActiveDCB = pDCB;
164
        pDCB->pActiveSRB = pSRB;
165
        //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
166
        DC390_write8 (ScsiCmd, bval1);
167
        return 0;
168
    }
169
}
170
 
171
//#define DMA_INT EN_DMA_INT /*| EN_PAGE_INT*/
172
#define DMA_INT 0
173
 
174
#if DMA_INT
175
/* This is similar to AM53C974.c ... */
176
static UCHAR
177
dc390_dma_intr (PACB pACB)
178
{
179
  PSRB pSRB;
180
  UCHAR dstate;
181
  DEBUG0(USHORT pstate;PDEVDECL1;)
182
 
183
  DEBUG0(PDEVSET1;)
184
  DEBUG0(PCI_READ_CONFIG_WORD (PDEV, PCI_STATUS, &pstate);)
185
  DEBUG0(if (pstate & (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY))\
186
        { printk(KERN_WARNING "DC390: PCI state = %04x!\n", pstate); \
187
          PCI_WRITE_CONFIG_WORD (PDEV, PCI_STATUS, (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY));};)
188
 
189
  dstate = DC390_read8 (DMA_Status);
190
 
191
  if (! pACB->pActiveDCB || ! pACB->pActiveDCB->pActiveSRB) return dstate;
192
  else pSRB  = pACB->pActiveDCB->pActiveSRB;
193
 
194
  if (dstate & (DMA_XFER_ABORT | DMA_XFER_ERROR | POWER_DOWN | PCI_MS_ABORT))
195
    {
196
        printk (KERN_ERR "DC390: DMA error (%02x)!\n", dstate);
197
        return dstate;
198
    };
199
  if (dstate & DMA_XFER_DONE)
200
    {
201
        ULONG residual, xferCnt; int ctr = 5000000;
202
        if (! (DC390_read8 (DMA_Cmd) & READ_DIRECTION))
203
          {
204
            do
205
              {
206
                DEBUG1(printk (KERN_DEBUG "DC390: read residual bytes ... \n");)
207
                dstate = DC390_read8 (DMA_Status);
208
                residual = DC390_read8 (CtcReg_Low) | DC390_read8 (CtcReg_Mid) << 8 |
209
                  DC390_read8 (CtcReg_High) << 16;
210
                residual += DC390_read8 (Current_Fifo) & 0x1f;
211
              } while (residual && ! (dstate & SCSI_INTERRUPT) && --ctr);
212
            if (!ctr) printk (KERN_CRIT "DC390: dma_intr: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32 (DMA_Wk_ByteCntr));
213
            /* residual =  ... */
214
          }
215
        else
216
            residual = 0;
217
 
218
        /* ??? */
219
 
220
        xferCnt = pSRB->SGToBeXferLen - residual;
221
        pSRB->SGBusAddr += xferCnt;
222
        pSRB->TotalXferredLen += xferCnt;
223
        pSRB->SGToBeXferLen = residual;
224
# ifdef DC390_DEBUG0
225
        printk (KERN_INFO "DC390: DMA: residual = %i, xfer = %i\n",
226
                (unsigned int)residual, (unsigned int)xferCnt);
227
# endif
228
 
229
        DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
230
    }
231
  dc390_laststatus &= ~0xff000000; dc390_laststatus |= dstate << 24;
232
  return dstate;
233
};
234
#endif
235
 
236
void __inline__
237
DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs)
238
{
239
    PACB   pACB;
240
    PDCB   pDCB;
241
    PSRB   pSRB;
242
    UCHAR  sstatus=0;
243
    UCHAR  phase, i;
244
    void   (*stateV)( PACB, PSRB, PUCHAR );
245
    UCHAR  istate, istatus;
246
#if DMA_INT
247
    UCHAR  dstatus;
248
#endif
249
    DC390_AFLAGS DC390_IFLAGS DC390_DFLAGS
250
 
251
    pACB = dc390_pACB_start;
252
 
253
    if (pACB == 0)
254
    {
255
        printk(KERN_WARNING "DC390: Interrupt on uninitialized adapter!\n");
256
        return;
257
    }
258
    DC390_LOCK_DRV;
259
 
260
    for( i=0; i < dc390_adapterCnt; i++ )
261
    {
262
        if( pACB->IRQLevel == (UCHAR) irq )
263
        {
264
             sstatus = DC390_read8 (Scsi_Status);
265
             if( sstatus & INTERRUPT )
266
                 break;
267
             else
268
                pACB = pACB->pNextACB;
269
        }
270
        else
271
        {
272
            pACB = pACB->pNextACB;
273
        }
274
    }
275
 
276
    DEBUG1(printk (KERN_DEBUG "sstatus=%02x,", sstatus);)
277
 
278
    if( !pACB ) { DC390_UNLOCK_DRV; return; };
279
 
280
#if DMA_INT
281
    DC390_LOCK_IO;
282
    DC390_LOCK_ACB;
283
    dstatus = dc390_dma_intr (pACB);
284
    DC390_UNLOCK_ACB;
285
    DC390_UNLOCK_IO;
286
 
287
    DEBUG1(printk (KERN_DEBUG "dstatus=%02x,", dstatus);)
288
    if (! (dstatus & SCSI_INTERRUPT))
289
      {
290
        DEBUG0(printk (KERN_WARNING "DC390 Int w/o SCSI actions (only DMA?)\n");)
291
        DC390_UNLOCK_DRV;
292
        return;
293
      };
294
#else
295
    //DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);
296
    //dstatus = DC390_read8 (DMA_Status);
297
    //DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
298
#endif
299
 
300
    DC390_LOCK_IO;
301
    DC390_LOCK_ACB;
302
    DC390_UNLOCK_DRV_NI; /* Allow _other_ CPUs to process IRQ (useful for shared IRQs) */
303
 
304
    istate = DC390_read8 (Intern_State);
305
    istatus = DC390_read8 (INT_Status); /* This clears Scsi_Status, Intern_State and INT_Status ! */
306
 
307
    DEBUG1(printk (KERN_INFO "Istatus(Res,Inv,Dis,Serv,Succ,ReS,SelA,Sel)=%02x,",istatus);)
308
    dc390_laststatus &= ~0x00ffffff;
309
    dc390_laststatus |= /* dstatus<<24 | */ sstatus<<16 | istate<<8 | istatus;
310
 
311
    if (sstatus & ILLEGAL_OP_ERR)
312
    {
313
        printk ("DC390: Illegal Operation detected (%08lx)!\n", dc390_laststatus);
314
        dc390_dumpinfo (pACB, pACB->pActiveDCB, pACB->pActiveDCB->pActiveSRB);
315
    };
316
 
317
    if(istatus &  DISCONNECTED)
318
    {
319
        dc390_Disconnect( pACB );
320
        goto unlock;
321
    }
322
 
323
    if(istatus &  RESELECTED)
324
    {
325
        dc390_Reselect( pACB );
326
        goto unlock;
327
    }
328
 
329
    if( istatus & (SUCCESSFUL_OP|SERVICE_REQUEST) )
330
    {
331
        pDCB = pACB->pActiveDCB;
332
        if (!pDCB)
333
        {
334
                printk (KERN_ERR "DC390: Suc. op/ Serv. req: pActiveDCB = 0!\n");
335
                goto unlock;
336
        };
337
        pSRB = pDCB->pActiveSRB;
338
        if( pDCB->DCBFlag & ABORT_DEV_ )
339
          dc390_EnableMsgOut_Abort (pACB, pSRB);
340
 
341
        phase = pSRB->ScsiPhase;
342
        DEBUG1(printk (KERN_INFO "DC390: [%i]%s(0) (%02x)\n", phase, dc390_p0_str[phase], sstatus);)
343
        stateV = (void *) dc390_phase0[phase];
344
        ( *stateV )( pACB, pSRB, &sstatus );
345
 
346
        pSRB->ScsiPhase = sstatus & 7;
347
        phase = (UCHAR) sstatus & 7;
348
        DEBUG1(printk (KERN_INFO "DC390: [%i]%s(1) (%02x)\n", phase, dc390_p1_str[phase], sstatus);)
349
        stateV = (void *) dc390_phase1[phase];
350
        ( *stateV )( pACB, pSRB, &sstatus );
351
        goto unlock;
352
    }
353
 
354
    if(istatus &  INVALID_CMD)
355
    {
356
        dc390_InvalidCmd( pACB );
357
        goto unlock;
358
    }
359
 
360
    if(istatus &  SCSI_RESET)
361
    {
362
        dc390_ScsiRstDetect( pACB );
363
        goto unlock;
364
    }
365
 
366
 unlock:
367
    DC390_LOCK_DRV_NI;
368
    DC390_UNLOCK_ACB;
369
    DC390_UNLOCK_IO;
370
    DC390_UNLOCK_DRV; /* Restore initial flags */
371
}
372
 
373
void
374
do_DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs)
375
{
376
    DEBUG1(printk (KERN_INFO "DC390: Irq (%i) caught: ", irq);)
377
    /* Locking is done in DC390_Interrupt */
378
    DC390_Interrupt(irq, dev_id, regs);
379
    DEBUG1(printk (".. IRQ returned\n");)
380
}
381
 
382
void
383
dc390_DataOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
384
{
385
    UCHAR   sstatus;
386
    PSGL    psgl;
387
    ULONG   ResidCnt, xferCnt;
388
    UCHAR   dstate = 0;
389
 
390
    sstatus = *psstatus;
391
 
392
    if( !(pSRB->SRBState & SRB_XFERPAD) )
393
    {
394
        if( sstatus & (PARITY_ERR | ILLEGAL_OP_ERR) )
395
            pSRB->SRBStatus |= PARITY_ERROR;
396
 
397
        if( sstatus & COUNT_2_ZERO )
398
        {
399
            int ctr = 5000000; /* only try for about a tenth of a second */
400
            while( --ctr && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE) && pSRB->SGToBeXferLen );
401
            if (!ctr) printk (KERN_CRIT "DC390: Deadlock in DataOut_0: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32 (DMA_Wk_ByteCntr));
402
            dc390_laststatus &= ~0xff000000; dc390_laststatus |= dstate << 24;
403
            pSRB->TotalXferredLen += pSRB->SGToBeXferLen;
404
            pSRB->SGIndex++;
405
            if( pSRB->SGIndex < pSRB->SGcount )
406
            {
407
                pSRB->pSegmentList++;
408
                psgl = pSRB->pSegmentList;
409
 
410
                pSRB->SGBusAddr = virt_to_bus( psgl->address );
411
                pSRB->SGToBeXferLen = (ULONG) psgl->length;
412
            }
413
            else
414
                pSRB->SGToBeXferLen = 0;
415
        }
416
        else
417
        {
418
            ResidCnt = (ULONG) DC390_read8 (Current_Fifo) & 0x1f;
419
            ResidCnt |= (ULONG) DC390_read8 (CtcReg_High) << 16;
420
            ResidCnt |= (ULONG) DC390_read8 (CtcReg_Mid) << 8;
421
            ResidCnt += (ULONG) DC390_read8 (CtcReg_Low);
422
 
423
            xferCnt = pSRB->SGToBeXferLen - ResidCnt;
424
            pSRB->SGBusAddr += xferCnt;
425
            pSRB->TotalXferredLen += xferCnt;
426
            pSRB->SGToBeXferLen = ResidCnt;
427
        }
428
    }
429
    DC390_write8 (DMA_Cmd, WRITE_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */
430
}
431
 
432
void
433
dc390_DataIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
434
{
435
    UCHAR   sstatus, residual, bval;
436
    PSGL    psgl;
437
    ULONG   ResidCnt, xferCnt, i;
438
    PUCHAR  ptr;
439
 
440
    sstatus = *psstatus;
441
 
442
    if( !(pSRB->SRBState & SRB_XFERPAD) )
443
    {
444
        if( sstatus & (PARITY_ERR | ILLEGAL_OP_ERR))
445
            pSRB->SRBStatus |= PARITY_ERROR;
446
 
447
        if( sstatus & COUNT_2_ZERO )
448
        {
449
            int ctr = 5000000; /* only try for about a tenth of a second */
450
            int dstate = 0;
451
            while( --ctr && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE) && pSRB->SGToBeXferLen );
452
            if (!ctr) printk (KERN_CRIT "DC390: Deadlock in DataIn_0: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32 (DMA_Wk_ByteCntr));
453
            if (!ctr) printk (KERN_CRIT "DC390: DataIn_0: DMA State: %i\n", dstate);
454
            dc390_laststatus &= ~0xff000000; dc390_laststatus |= dstate << 24;
455
            DEBUG1(ResidCnt = ((ULONG) DC390_read8 (CtcReg_High) << 16) \
456
                + ((ULONG) DC390_read8 (CtcReg_Mid) << 8)               \
457
                + ((ULONG) DC390_read8 (CtcReg_Low));)
458
            DEBUG1(printk (KERN_DEBUG "Count_2_Zero (ResidCnt=%li,ToBeXfer=%li),", ResidCnt, pSRB->SGToBeXferLen);)
459
 
460
            DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */
461
 
462
            pSRB->TotalXferredLen += pSRB->SGToBeXferLen;
463
            pSRB->SGIndex++;
464
            if( pSRB->SGIndex < pSRB->SGcount )
465
            {
466
                pSRB->pSegmentList++;
467
                psgl = pSRB->pSegmentList;
468
 
469
                pSRB->SGBusAddr = virt_to_bus( psgl->address );
470
                pSRB->SGToBeXferLen = (ULONG) psgl->length;
471
            }
472
            else
473
                pSRB->SGToBeXferLen = 0;
474
        }
475
        else    /* phase changed */
476
        {
477
            residual = 0;
478
            bval = DC390_read8 (Current_Fifo);
479
            while( bval & 0x1f )
480
            {
481
                DEBUG1(printk (KERN_DEBUG "Check for residuals,");)
482
                if( (bval & 0x1f) == 1 )
483
                {
484
                    for(i=0; i < 0x100; i++)
485
                    {
486
                        bval = DC390_read8 (Current_Fifo);
487
                        if( !(bval & 0x1f) )
488
                            goto din_1;
489
                        else if( i == 0x0ff )
490
                        {
491
                            residual = 1;   /* ;1 residual byte */
492
                            goto din_1;
493
                        }
494
                    }
495
                }
496
                else
497
                    bval = DC390_read8 (Current_Fifo);
498
            }
499
din_1:
500
            DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_BLAST_CMD);
501
            for (i = 0xa000; i; i--)
502
            {
503
                bval = DC390_read8 (DMA_Status);
504
                if (bval & BLAST_COMPLETE)
505
                    break;
506
            }
507
            /* It seems a DMA Blast abort isn't that bad ... */
508
            if (!i) printk (KERN_ERR "DC390: DMA Blast aborted unfinished!\n");
509
            //DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */
510
            dc390_laststatus &= ~0xff000000; dc390_laststatus |= bval << 24;
511
 
512
            DEBUG1(printk (KERN_DEBUG "Blast: Read %li times DMA_Status %02x", 0xa000-i, bval);)
513
            ResidCnt = (ULONG) DC390_read8 (CtcReg_High);
514
            ResidCnt <<= 8;
515
            ResidCnt |= (ULONG) DC390_read8 (CtcReg_Mid);
516
            ResidCnt <<= 8;
517
            ResidCnt |= (ULONG) DC390_read8 (CtcReg_Low);
518
 
519
            xferCnt = pSRB->SGToBeXferLen - ResidCnt;
520
            pSRB->SGBusAddr += xferCnt;
521
            pSRB->TotalXferredLen += xferCnt;
522
            pSRB->SGToBeXferLen = ResidCnt;
523
 
524
            if( residual )
525
            {
526
                bval = DC390_read8 (ScsiFifo);      /* get one residual byte */
527
                ptr = (PUCHAR) bus_to_virt( pSRB->SGBusAddr );
528
                *ptr = bval;
529
                pSRB->SGBusAddr++; xferCnt++;
530
                pSRB->TotalXferredLen++;
531
                pSRB->SGToBeXferLen--;
532
            }
533
            DEBUG1(printk (KERN_DEBUG "Xfered: %li, Total: %li, Remaining: %li\n", xferCnt,\
534
                           pSRB->TotalXferredLen, pSRB->SGToBeXferLen);)
535
 
536
        }
537
    }
538
}
539
 
540
static void
541
dc390_Command_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
542
{
543
}
544
 
545
static void
546
dc390_Status_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
547
{
548
 
549
    pSRB->TargetStatus = DC390_read8 (ScsiFifo);
550
    //udelay (1);
551
    pSRB->EndMessage = DC390_read8 (ScsiFifo);  /* get message */
552
 
553
    *psstatus = SCSI_NOP0;
554
    pSRB->SRBState = SRB_COMPLETED;
555
    DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD);
556
}
557
 
558
static void
559
dc390_MsgOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
560
{
561
    if( pSRB->SRBState & (SRB_UNEXPECT_RESEL+SRB_ABORT_SENT) )
562
        *psstatus = SCSI_NOP0;
563
    //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
564
}
565
 
566
 
567
static void __inline__
568
dc390_reprog (PACB pACB, PDCB pDCB)
569
{
570
  DC390_write8 (Sync_Period, pDCB->SyncPeriod);
571
  DC390_write8 (Sync_Offset, pDCB->SyncOffset);
572
  DC390_write8 (CtrlReg3, pDCB->CtrlR3);
573
  DC390_write8 (CtrlReg4, pDCB->CtrlR4);
574
  dc390_SetXferRate (pACB, pDCB);
575
};
576
 
577
 
578
#ifdef DC390_DEBUG0
579
static void
580
dc390_printMsg (UCHAR *MsgBuf, UCHAR len)
581
{
582
  int i;
583
  printk (" %02x", MsgBuf[0]);
584
  for (i = 1; i < len; i++)
585
    printk (" %02x", MsgBuf[i]);
586
  printk ("\n");
587
};
588
#endif
589
 
590
#define DC390_ENABLE_MSGOUT DC390_write8 (ScsiCmd, SET_ATN_CMD)
591
 
592
/* reject_msg */
593
static void __inline__
594
dc390_MsgIn_reject (PACB pACB, PSRB pSRB)
595
{
596
  pSRB->MsgOutBuf[0] = MSG_REJECT_;
597
  pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;
598
  DEBUG0 (printk (KERN_INFO "DC390: Reject message\n");)
599
}
600
 
601
/* abort command */
602
static void __inline__
603
dc390_EnableMsgOut_Abort ( PACB pACB, PSRB pSRB )
604
{
605
    pSRB->MsgOutBuf[0] = MSG_ABORT;
606
    pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;
607
    pSRB->pSRBDCB->DCBFlag &= ~ABORT_DEV_;
608
}
609
 
610
static PSRB
611
dc390_MsgIn_QTag (PACB pACB, PDCB pDCB, UCHAR tag)
612
{
613
  PSRB lastSRB = pDCB->pGoingLast;
614
  PSRB pSRB = pDCB->pGoingSRB;
615
 
616
  if (pSRB)
617
    {
618
      for( ;pSRB ; )
619
        {
620
          if (pSRB->TagNumber == tag) break;
621
          if (pSRB == lastSRB) goto mingx0;
622
          pSRB = pSRB->pNextSRB;
623
        }
624
 
625
      if( pDCB->DCBFlag & ABORT_DEV_ )
626
        {
627
          pSRB->SRBState = SRB_ABORT_SENT;
628
          dc390_EnableMsgOut_Abort( pACB, pSRB );
629
        }
630
 
631
      if( !(pSRB->SRBState & SRB_DISCONNECT) )
632
        goto  mingx0;
633
 
634
      pDCB->pActiveSRB = pSRB;
635
      pSRB->SRBState = SRB_DATA_XFER;
636
    }
637
  else
638
    {
639
    mingx0:
640
      pSRB = pACB->pTmpSRB;
641
      pSRB->SRBState = SRB_UNEXPECT_RESEL;
642
      pDCB->pActiveSRB = pSRB;
643
      pSRB->MsgOutBuf[0] = MSG_ABORT_TAG;
644
      pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;
645
    }
646
  return pSRB;
647
}
648
 
649
 
650
/* set async transfer mode */
651
static void
652
dc390_MsgIn_set_async (PACB pACB, PSRB pSRB)
653
{
654
  PDCB pDCB = pSRB->pSRBDCB;
655
  if (!(pSRB->SRBState & DO_SYNC_NEGO))
656
    printk ("DC390: Target %i initiates Non-Sync?\n", pDCB->UnitSCSIID);
657
  pSRB->SRBState &= ~DO_SYNC_NEGO;
658
  pDCB->SyncMode &= ~(SYNC_ENABLE+SYNC_NEGO_DONE);
659
  pDCB->SyncPeriod = 0;
660
  pDCB->SyncOffset = 0;
661
  //pDCB->NegoPeriod = 50; /* 200ns <=> 5 MHz */
662
  pDCB->CtrlR3 = FAST_CLK;      /* fast clock / normal scsi */
663
  pDCB->CtrlR4 &= 0x3f;
664
  pDCB->CtrlR4 |= pACB->glitch_cfg;     /* glitch eater */
665
  dc390_reprog (pACB, pDCB);
666
}
667
 
668
/* set sync transfer mode */
669
static void
670
dc390_MsgIn_set_sync (PACB pACB, PSRB pSRB)
671
{
672
  UCHAR bval;
673
  USHORT wval, wval1;
674
  PDCB pDCB = pSRB->pSRBDCB;
675
  UCHAR oldsyncperiod = pDCB->SyncPeriod;
676
  UCHAR oldsyncoffset = pDCB->SyncOffset;
677
 
678
  if (!(pSRB->SRBState & DO_SYNC_NEGO))
679
    {
680
      printk ("DC390: Target %i initiates Sync: %ins %i ... answer ...\n",
681
              pDCB->UnitSCSIID, pSRB->MsgInBuf[3]<<2, pSRB->MsgInBuf[4]);
682
 
683
      /* reject */
684
      //dc390_MsgIn_reject (pACB, pSRB);
685
      //return dc390_MsgIn_set_async (pACB, pSRB);
686
 
687
      /* Reply with corrected SDTR Message */
688
      if (pSRB->MsgInBuf[4] > 15)
689
        {
690
          printk ("DC390: Lower Sync Offset to 15\n");
691
          pSRB->MsgInBuf[4] = 15;
692
        }
693
      if (pSRB->MsgInBuf[3] < pDCB->NegoPeriod)
694
        {
695
          printk ("DC390: Set sync nego period to %ins\n", pDCB->NegoPeriod << 2);
696
          pSRB->MsgInBuf[3] = pDCB->NegoPeriod;
697
        };
698
      memcpy (pSRB->MsgOutBuf, pSRB->MsgInBuf, 5);
699
      pSRB->MsgCnt = 5;
700
      DC390_ENABLE_MSGOUT;
701
    };
702
 
703
  pSRB->SRBState &= ~DO_SYNC_NEGO;
704
  pDCB->SyncMode |= SYNC_ENABLE+SYNC_NEGO_DONE;
705
  pDCB->SyncOffset &= 0x0f0;
706
  pDCB->SyncOffset |= pSRB->MsgInBuf[4];
707
  pDCB->NegoPeriod = pSRB->MsgInBuf[3];
708
 
709
  wval = (USHORT) pSRB->MsgInBuf[3];
710
  wval = wval << 2; wval -= 3; wval1 = wval / 25;       /* compute speed */
711
  if( (wval1 * 25) != wval) wval1++;
712
  bval = FAST_CLK+FAST_SCSI;    /* fast clock / fast scsi */
713
 
714
  pDCB->CtrlR4 &= 0x3f;         /* Glitch eater: 12ns less than normal */
715
  if (pACB->glitch_cfg != NS_TO_GLITCH(0))
716
    pDCB->CtrlR4 |= NS_TO_GLITCH(((GLITCH_TO_NS(pACB->glitch_cfg)) - 1));
717
  else
718
    pDCB->CtrlR4 |= NS_TO_GLITCH(0);
719
  if (wval1 < 4) pDCB->CtrlR4 |= NS_TO_GLITCH(0); /* Ultra */
720
 
721
  if (wval1 >= 8)
722
    {
723
      wval1--;  /* Timing computation differs by 1 from FAST_SCSI */
724
      bval = FAST_CLK;          /* fast clock / normal scsi */
725
      pDCB->CtrlR4 |= pACB->glitch_cfg;         /* glitch eater */
726
    }
727
 
728
  pDCB->CtrlR3 = bval;
729
  pDCB->SyncPeriod = (UCHAR)wval1;
730
 
731
  if ((oldsyncperiod != wval1 || oldsyncoffset != pDCB->SyncOffset) && pDCB->UnitSCSILUN == 0)
732
    {
733
      if (! (bval & FAST_SCSI)) wval1++;
734
      printk ("DC390: Target %i: Sync transfer %i.%1i MHz, Offset %i\n", pDCB->UnitSCSIID,
735
              40/wval1, ((40%wval1)*10+wval1/2)/wval1, pDCB->SyncOffset & 0x0f);
736
    }
737
 
738
  dc390_reprog (pACB, pDCB);
739
};
740
 
741
 
742
/* According to the docs, the AM53C974 reads the message and
743
 * generates a Succesful Operation IRQ before asserting ACK for
744
 * the last byte (how does it know whether it's the last ?) */
745
/* The old code handled it in another way, indicating, that on
746
 * every message byte an IRQ is generated and every byte has to
747
 * be manually ACKed. Hmmm ?  (KG, 98/11/28) */
748
/* The old implementation was correct. Sigh! */
749
 
750
/* Check if the message is complete */
751
static UCHAR __inline__
752
dc390_MsgIn_complete (UCHAR *msgbuf, ULONG len)
753
{
754
  if (*msgbuf == MSG_EXTENDED)
755
    {
756
      if (len < 2) return 0;
757
      if (len < msgbuf[1] + 2) return 0;
758
    }
759
  else if (*msgbuf >= 0x20 && *msgbuf <= 0x2f) // two byte messages
760
    if (len < 2) return 0;
761
  return 1;
762
}
763
 
764
 
765
 
766
/* read and eval received messages */
767
void
768
dc390_MsgIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
769
{
770
    PDCB   pDCB = pACB->pActiveDCB;
771
 
772
    /* Read the msg */
773
 
774
    pSRB->MsgInBuf[pACB->MsgLen++] = DC390_read8 (ScsiFifo);
775
    //pSRB->SRBState = 0;
776
 
777
    /* Msg complete ? */
778
    if (dc390_MsgIn_complete (pSRB->MsgInBuf, pACB->MsgLen))
779
      {
780
        DEBUG0 (printk (KERN_INFO "DC390: MsgIn:"); dc390_printMsg (pSRB->MsgInBuf, pACB->MsgLen);)
781
        /* Now eval the msg */
782
        switch (pSRB->MsgInBuf[0])
783
          {
784
          case MSG_DISCONNECT:
785
            pSRB->SRBState = SRB_DISCONNECT; break;
786
 
787
          case MSG_SIMPLE_QTAG:
788
          case MSG_HEAD_QTAG:
789
          case MSG_ORDER_QTAG:
790
            pSRB = dc390_MsgIn_QTag (pACB, pDCB, pSRB->MsgInBuf[1]);
791
            break;
792
 
793
          case MSG_REJECT_:
794
            DC390_write8 (ScsiCmd, RESET_ATN_CMD);
795
            pDCB->NegoPeriod = 50; /* 200ns <=> 5 MHz */
796
            if( pSRB->SRBState & DO_SYNC_NEGO)
797
              dc390_MsgIn_set_async (pACB, pSRB);
798
            break;
799
 
800
          case MSG_EXTENDED:
801
            /* reject every extended msg but SDTR */
802
            if (pSRB->MsgInBuf[1] != 3 || pSRB->MsgInBuf[2] != EXTENDED_SDTR)
803
              dc390_MsgIn_reject (pACB, pSRB);
804
            else
805
              {
806
                if (pSRB->MsgInBuf[3] == 0 || pSRB->MsgInBuf[4] == 0)
807
                  dc390_MsgIn_set_async (pACB, pSRB);
808
                else
809
                  dc390_MsgIn_set_sync (pACB, pSRB);
810
              };
811
 
812
            // nothing has to be done
813
          case MSG_COMPLETE: break;
814
 
815
            // SAVE POINTER my be ignored as we have the PSRB associated with the
816
            // scsi command. Thanks, Gerard, for pointing it out.
817
          case MSG_SAVE_PTR: break;
818
            // The device might want to restart transfer with a RESTORE
819
          case MSG_RESTORE_PTR:
820
            printk ("DC390: RESTORE POINTER message received ... reject\n");
821
            // fall through
822
 
823
            // reject unknown messages
824
          default: dc390_MsgIn_reject (pACB, pSRB);
825
          }
826
 
827
        /* Clear counter and MsgIn state */
828
        pSRB->SRBState &= ~SRB_MSGIN;
829
        pACB->MsgLen = 0;
830
      };
831
 
832
    *psstatus = SCSI_NOP0;
833
    DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD);
834
    //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
835
}
836
 
837
 
838
void
839
dc390_DataIO_Comm( PACB pACB, PSRB pSRB, UCHAR ioDir)
840
{
841
    PSGL   psgl;
842
    ULONG  lval;
843
 
844
    if( pSRB->SGIndex < pSRB->SGcount )
845
    {
846
        DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir /* | DMA_INT */);
847
        if( !pSRB->SGToBeXferLen )
848
        {
849
            psgl = pSRB->pSegmentList;
850
            pSRB->SGBusAddr = virt_to_bus( psgl->address );
851
            pSRB->SGToBeXferLen = (ULONG) psgl->length;
852
            DEBUG1(printk (KERN_DEBUG " DC390: Next SG segment.");)
853
        }
854
        lval = pSRB->SGToBeXferLen;
855
        DEBUG1(printk (KERN_DEBUG " DC390: Transfer %li bytes (address %08lx)\n", lval, pSRB->SGBusAddr);)
856
        DC390_write8 (CtcReg_Low, (UCHAR) lval);
857
        lval >>= 8;
858
        DC390_write8 (CtcReg_Mid, (UCHAR) lval);
859
        lval >>= 8;
860
        DC390_write8 (CtcReg_High, (UCHAR) lval);
861
 
862
        DC390_write32 (DMA_XferCnt, pSRB->SGToBeXferLen);
863
        DC390_write32 (DMA_XferAddr, pSRB->SGBusAddr);
864
 
865
        //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); /* | DMA_INT; */
866
        pSRB->SRBState = SRB_DATA_XFER;
867
 
868
        DC390_write8 (ScsiCmd, DMA_COMMAND+INFO_XFER_CMD);
869
 
870
        DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir | DMA_INT);
871
        //DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);)
872
        //DEBUG1(printk (KERN_DEBUG "DC390: DMA_Status: %02x\n", DC390_read8 (DMA_Status));)
873
        //DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);)
874
    }
875
    else    /* xfer pad */
876
    {
877
        if( pSRB->SGcount )
878
        {
879
            pSRB->AdaptStatus = H_OVER_UNDER_RUN;
880
            pSRB->SRBStatus |= OVER_RUN;
881
            DEBUG0(printk (KERN_WARNING " DC390: Overrun -");)
882
        }
883
        DEBUG0(printk (KERN_WARNING " Clear transfer pad \n");)
884
        DC390_write8 (CtcReg_Low, 0);
885
        DC390_write8 (CtcReg_Mid, 0);
886
        DC390_write8 (CtcReg_High, 0);
887
 
888
        pSRB->SRBState |= SRB_XFERPAD;
889
        DC390_write8 (ScsiCmd, DMA_COMMAND+XFER_PAD_BYTE);
890
/*
891
        DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); // | DMA_INT;
892
        DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir | DMA_INT);
893
*/
894
    }
895
}
896
 
897
 
898
static void
899
dc390_DataOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
900
{
901
    dc390_DataIO_Comm (pACB, pSRB, WRITE_DIRECTION);
902
}
903
 
904
static void
905
dc390_DataInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
906
{
907
    dc390_DataIO_Comm (pACB, pSRB, READ_DIRECTION);
908
}
909
 
910
void
911
dc390_CommandPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
912
{
913
    PDCB   pDCB;
914
    UCHAR  i, cnt;
915
    PUCHAR ptr;
916
 
917
    DC390_write8 (ScsiCmd, RESET_ATN_CMD);
918
    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
919
    if( !(pSRB->SRBFlag & AUTO_REQSENSE) )
920
    {
921
        cnt = (UCHAR) pSRB->ScsiCmdLen;
922
        ptr = (PUCHAR) pSRB->CmdBlock;
923
        for(i=0; i < cnt; i++)
924
            DC390_write8 (ScsiFifo, *(ptr++));
925
    }
926
    else
927
    {
928
        UCHAR bval = 0;
929
        DC390_write8 (ScsiFifo, REQUEST_SENSE);
930
        pDCB = pACB->pActiveDCB;
931
        DC390_write8 (ScsiFifo, pDCB->IdentifyMsg << 5);
932
        DC390_write8 (ScsiFifo, bval);
933
        DC390_write8 (ScsiFifo, bval);
934
        DC390_write8 (ScsiFifo, sizeof(pSRB->pcmd->sense_buffer));
935
        DC390_write8 (ScsiFifo, bval);
936
    }
937
    pSRB->SRBState = SRB_COMMAND;
938
    DC390_write8 (ScsiCmd, INFO_XFER_CMD);
939
}
940
 
941
static void
942
dc390_StatusPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
943
{
944
    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
945
    pSRB->SRBState = SRB_STATUS;
946
    DC390_write8 (ScsiCmd, INITIATOR_CMD_CMPLTE);
947
    //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
948
}
949
 
950
void
951
dc390_MsgOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
952
{
953
    UCHAR   bval, i, cnt;
954
    PUCHAR  ptr;
955
    PDCB    pDCB;
956
 
957
    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
958
    pDCB = pACB->pActiveDCB;
959
    if( !(pSRB->SRBState & SRB_MSGOUT) )
960
    {
961
        cnt = pSRB->MsgCnt;
962
        if( cnt )
963
        {
964
            ptr = (PUCHAR) pSRB->MsgOutBuf;
965
            for(i=0; i < cnt; i++)
966
                DC390_write8 (ScsiFifo, *(ptr++));
967
            pSRB->MsgCnt = 0;
968
            if( (pDCB->DCBFlag & ABORT_DEV_) &&
969
                (pSRB->MsgOutBuf[0] == MSG_ABORT) )
970
                pSRB->SRBState = SRB_ABORT_SENT;
971
        }
972
        else
973
        {
974
            bval = MSG_ABORT;   /* ??? MSG_NOP */
975
            if( (pSRB->CmdBlock[0] == INQUIRY ) ||
976
                (pSRB->CmdBlock[0] == REQUEST_SENSE) ||
977
                (pSRB->SRBFlag & AUTO_REQSENSE) )
978
            {
979
                if( pDCB->SyncMode & SYNC_ENABLE )
980
                    goto  mop1;
981
            }
982
            DC390_write8 (ScsiFifo, bval);
983
        }
984
        DC390_write8 (ScsiCmd, INFO_XFER_CMD);
985
    }
986
    else
987
    {
988
mop1:
989
        //printk ("DC390: Send SDTR message to %i %i ... \n", pDCB->UnitSCSIID, pDCB->UnitSCSILUN);
990
        DC390_write8 (ScsiFifo, MSG_EXTENDED);
991
        DC390_write8 (ScsiFifo, 3);     /*    ;length of extended msg */
992
        DC390_write8 (ScsiFifo, EXTENDED_SDTR); /*    ; sync nego */
993
        DC390_write8 (ScsiFifo, pDCB->NegoPeriod);
994
        if (pDCB->SyncOffset & 0x0f)
995
                    DC390_write8 (ScsiFifo, pDCB->SyncOffset);
996
        else
997
                    DC390_write8 (ScsiFifo, SYNC_NEGO_OFFSET);
998
        pSRB->SRBState |= DO_SYNC_NEGO;
999
        DC390_write8 (ScsiCmd, INFO_XFER_CMD);
1000
    }
1001
}
1002
 
1003
static void
1004
dc390_MsgInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus)
1005
{
1006
    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
1007
    if( !(pSRB->SRBState & SRB_MSGIN) )
1008
    {
1009
        pSRB->SRBState &= ~SRB_DISCONNECT;
1010
        pSRB->SRBState |= SRB_MSGIN;
1011
    }
1012
    DC390_write8 (ScsiCmd, INFO_XFER_CMD);
1013
    //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
1014
}
1015
 
1016
static void
1017
dc390_Nop_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
1018
{
1019
}
1020
 
1021
static void
1022
dc390_Nop_1( PACB pACB, PSRB pSRB, PUCHAR psstatus)
1023
{
1024
}
1025
 
1026
 
1027
static void
1028
dc390_SetXferRate( PACB pACB, PDCB pDCB )
1029
{
1030
    UCHAR  bval, i, cnt;
1031
    PDCB   ptr;
1032
 
1033
    if( !(pDCB->IdentifyMsg & 0x07) )
1034
    {
1035
        if( pACB->scan_devices )
1036
        {
1037
            dc390_CurrSyncOffset = pDCB->SyncOffset;
1038
        }
1039
        else
1040
        {
1041
            ptr = pACB->pLinkDCB;
1042
            cnt = pACB->DCBCnt;
1043
            bval = pDCB->UnitSCSIID;
1044
            for(i=0; i<cnt; i++)
1045
            {
1046
                if( ptr->UnitSCSIID == bval )
1047
                {
1048
                    ptr->SyncPeriod = pDCB->SyncPeriod;
1049
                    ptr->SyncOffset = pDCB->SyncOffset;
1050
                    ptr->CtrlR3 = pDCB->CtrlR3;
1051
                    ptr->CtrlR4 = pDCB->CtrlR4;
1052
                    ptr->SyncMode = pDCB->SyncMode;
1053
                }
1054
                ptr = ptr->pNextDCB;
1055
            }
1056
        }
1057
    }
1058
    return;
1059
}
1060
 
1061
 
1062
void
1063
dc390_Disconnect( PACB pACB )
1064
{
1065
    PDCB   pDCB;
1066
    PSRB   pSRB, psrb;
1067
    UCHAR  i, cnt;
1068
 
1069
    DEBUG0(printk(KERN_INFO "DISC,");)
1070
 
1071
    pDCB = pACB->pActiveDCB;
1072
    if (!pDCB)
1073
     {
1074
        int j = 400;
1075
        DEBUG0(printk(KERN_WARNING "ACB:%08lx->ActiveDCB:%08lx IOPort:%04x IRQ:%02x !\n",\
1076
               (ULONG)pACB,(ULONG)pDCB,pACB->IOPortBase,pACB->IRQLevel);)
1077
        while (--j) udelay (1000);
1078
        DC390_read8 (INT_Status);       /* Reset Pending INT */
1079
        DC390_write8 (ScsiCmd, EN_SEL_RESEL);
1080
        return;
1081
     }
1082
    pSRB = pDCB->pActiveSRB;
1083
    pACB->pActiveDCB = 0;
1084
    pSRB->ScsiPhase = SCSI_NOP0;
1085
    DC390_write8 (ScsiCmd, EN_SEL_RESEL);
1086
    if( pSRB->SRBState & SRB_UNEXPECT_RESEL )
1087
    {
1088
        pSRB->SRBState = 0;
1089
        dc390_DoWaitingSRB( pACB );
1090
    }
1091
    else if( pSRB->SRBState & SRB_ABORT_SENT )
1092
    {
1093
        pDCB->TagMask = 0;
1094
        pDCB->DCBFlag = 0;
1095
        cnt = pDCB->GoingSRBCnt;
1096
        pDCB->GoingSRBCnt = 0;
1097
        pSRB = pDCB->pGoingSRB;
1098
        for( i=0; i < cnt; i++)
1099
        {
1100
            psrb = pSRB->pNextSRB;
1101
            pSRB->pNextSRB = pACB->pFreeSRB;
1102
            pACB->pFreeSRB = pSRB;
1103
            pSRB = psrb;
1104
        }
1105
        pDCB->pGoingSRB = 0;
1106
        dc390_DoWaitingSRB( pACB );
1107
    }
1108
    else
1109
    {
1110
        if( (pSRB->SRBState & (SRB_START_+SRB_MSGOUT)) ||
1111
           !(pSRB->SRBState & (SRB_DISCONNECT+SRB_COMPLETED)) )
1112
        {       /* Selection time out */
1113
            if( !(pACB->scan_devices) )
1114
            {
1115
                pSRB->SRBState = SRB_READY;
1116
                dc390_RewaitSRB( pDCB, pSRB);
1117
            }
1118
            else
1119
            {
1120
                pSRB->TargetStatus = SCSI_STAT_SEL_TIMEOUT;
1121
                goto  disc1;
1122
            }
1123
        }
1124
        else if( pSRB->SRBState & SRB_DISCONNECT )
1125
        {
1126
            dc390_DoWaitingSRB( pACB );
1127
        }
1128
        else if( pSRB->SRBState & SRB_COMPLETED )
1129
        {
1130
disc1:
1131
            if(pDCB->MaxCommand > 1)
1132
            {
1133
               pDCB->TagMask &= (~(1 << pSRB->TagNumber));   /* free tag mask */
1134
            }
1135
            pDCB->pActiveSRB = 0;
1136
            pSRB->SRBState = SRB_FREE;
1137
            dc390_SRBdone( pACB, pDCB, pSRB);
1138
        }
1139
    }
1140
    pACB->MsgLen = 0;
1141
}
1142
 
1143
 
1144
void
1145
dc390_Reselect( PACB pACB )
1146
{
1147
    PDCB   pDCB;
1148
    PSRB   pSRB;
1149
    USHORT wval;
1150
    UCHAR  bval;
1151
 
1152
    DEBUG0(printk(KERN_INFO "RSEL,");)
1153
    pDCB = pACB->pActiveDCB;
1154
    if( pDCB )
1155
    {   /* Arbitration lost but Reselection won */
1156
        DEBUG0(printk ("(ActiveDCB != 0)");)
1157
        pSRB = pDCB->pActiveSRB;
1158
        if( !( pACB->scan_devices ) )
1159
        {
1160
            pSRB->SRBState = SRB_READY;
1161
            dc390_RewaitSRB( pDCB, pSRB);
1162
        }
1163
    }
1164
    bval = DC390_read8 (ScsiFifo);      /* get ID */
1165
    DEBUG0(printk ("Dev %02x,", bval);)
1166
    bval ^= 1 << pACB->pScsiHost->this_id; /* Mask AdapterID */
1167
    wval = 0;
1168
    while (bval >>= 1) wval++;
1169
    wval |=  ( (USHORT) DC390_read8 (ScsiFifo) & 7) << 8;  /* get LUN */
1170
    DEBUG0(printk ("(ID %02x, LUN %02x),", wval & 0xff, (wval & 0xff00) >> 8);)
1171
    pDCB = pACB->pLinkDCB;
1172
    while( wval != *((PUSHORT) &pDCB->UnitSCSIID) )
1173
    {
1174
        pDCB = pDCB->pNextDCB;
1175
        if( pDCB == pACB->pLinkDCB )
1176
         {
1177
            printk (KERN_ERR "DC390: Reselect from non existing device (ID %02x, LUN %02x)\n",
1178
                    wval & 0xff, (wval & 0xff00) >> 8);
1179
            return;
1180
         }
1181
    }
1182
    pACB->pActiveDCB = pDCB;
1183
    if( pDCB->SyncMode & EN_TAG_QUEUEING )
1184
    {
1185
        pSRB = pACB->pTmpSRB; /* ?? */
1186
        pDCB->pActiveSRB = pSRB;
1187
    }
1188
    else
1189
    {
1190
        pSRB = pDCB->pActiveSRB;
1191
        if( !pSRB || !(pSRB->SRBState & SRB_DISCONNECT) )
1192
        {
1193
            pSRB= pACB->pTmpSRB;
1194
            pSRB->SRBState = SRB_UNEXPECT_RESEL;
1195
            printk (KERN_ERR "DC390: Reselect without outstanding cmnd (ID %02x, LUN %02x)\n",
1196
                    wval & 0xff, (wval & 0xff00) >> 8);
1197
            pDCB->pActiveSRB = pSRB;
1198
            dc390_EnableMsgOut_Abort ( pACB, pSRB );
1199
        }
1200
        else
1201
        {
1202
            if( pDCB->DCBFlag & ABORT_DEV_ )
1203
            {
1204
                pSRB->SRBState = SRB_ABORT_SENT;
1205
                printk (KERN_INFO "DC390: Reselect: Abort (ID %02x, LUN %02x)\n",
1206
                        wval & 0xff, (wval & 0xff00) >> 8);
1207
                dc390_EnableMsgOut_Abort( pACB, pSRB );
1208
            }
1209
            else
1210
                pSRB->SRBState = SRB_DATA_XFER;
1211
        }
1212
    }
1213
 
1214
    DEBUG1(printk (KERN_DEBUG "Resel SRB(%p): TagNum (%02x)\n", pSRB, pSRB->TagNumber);)
1215
    pSRB->ScsiPhase = SCSI_NOP0;
1216
    DC390_write8 (Scsi_Dest_ID, pDCB->UnitSCSIID);
1217
    DC390_write8 (Sync_Period, pDCB->SyncPeriod);
1218
    DC390_write8 (Sync_Offset, pDCB->SyncOffset);
1219
    DC390_write8 (CtrlReg1, pDCB->CtrlR1);
1220
    DC390_write8 (CtrlReg3, pDCB->CtrlR3);
1221
    DC390_write8 (CtrlReg4, pDCB->CtrlR4);      /* ; Glitch eater */
1222
    DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD);   /* ;to release the /ACK signal */
1223
}
1224
 
1225
 
1226
static void
1227
dc390_remove_dev (PACB pACB, PDCB pDCB)
1228
{
1229
   PDCB pPrevDCB = pACB->pLinkDCB;
1230
 
1231
   pACB->DCBmap[pDCB->UnitSCSIID] &= ~(1 << pDCB->UnitSCSILUN);
1232
   if (pDCB->GoingSRBCnt > 1)
1233
     {
1234
        DCBDEBUG(printk (KERN_INFO "DC390: Driver won't free DCB (ID %i, LUN %i): 0x%08x because of SRBCnt %i\n",\
1235
                pDCB->UnitSCSIID, pDCB->UnitSCSILUN, (int)pDCB, pDCB->GoingSRBCnt);)
1236
        return;
1237
     };
1238
 
1239
   if (pDCB == pACB->pLinkDCB)
1240
     {
1241
        if (pDCB->pNextDCB == pDCB) pDCB->pNextDCB = 0;
1242
        pACB->pLinkDCB = pDCB->pNextDCB;
1243
        pACB->pLastDCB->pNextDCB = pDCB->pNextDCB;
1244
     }
1245
   else
1246
     {
1247
        while (pPrevDCB->pNextDCB != pDCB) pPrevDCB = pPrevDCB->pNextDCB;
1248
        pPrevDCB->pNextDCB = pDCB->pNextDCB;
1249
        if (pDCB == pACB->pLastDCB) pACB->pLastDCB = pPrevDCB;
1250
     }
1251
 
1252
   DCBDEBUG(printk (KERN_INFO "DC390: Driver about to free DCB (ID %i, LUN %i): 0x%08x\n",\
1253
           pDCB->UnitSCSIID, pDCB->UnitSCSILUN, (int)pDCB);)
1254
   kfree (pDCB); if (pDCB == pACB->pActiveDCB) pACB->pActiveDCB = 0;
1255
   pACB->DCBCnt--;
1256
   /* pACB->DeviceCnt--; */
1257
};
1258
 
1259
 
1260
static UCHAR __inline__
1261
dc390_tagq_blacklist (char* name)
1262
{
1263
   UCHAR i;
1264
   for(i=0; i<BADDEVCNT; i++)
1265
     if (memcmp (name, dc390_baddevname1[i], 28) == 0)
1266
        return 1;
1267
   return 0;
1268
};
1269
 
1270
 
1271
static void
1272
dc390_disc_tagq_set (PDCB pDCB, PSCSI_INQDATA ptr)
1273
{
1274
   /* Check for SCSI format (ANSI and Response data format) */
1275
   if ( (ptr->Vers & 0x07) >= 2 || (ptr->RDF & 0x0F) == 2 )
1276
   {
1277
        if ( (ptr->Flags & SCSI_INQ_CMDQUEUE) &&
1278
            (pDCB->DevMode & TAG_QUEUEING_) &&
1279
            /* ((pDCB->DevType == TYPE_DISK)
1280
                || (pDCB->DevType == TYPE_MOD)) &&*/
1281
            !dc390_tagq_blacklist (((char*)ptr)+8) )
1282
          {
1283
             pDCB->MaxCommand = pDCB->pDCBACB->TagMaxNum;
1284
             pDCB->SyncMode |= EN_TAG_QUEUEING /* | EN_ATN_STOP */;
1285
             pDCB->TagMask = 0;
1286
          }
1287
        else
1288
          {
1289
             /* Do we really need to check for DevType here ? */
1290
             if ( 0 /*(pDCB->DevMode & EN_DISCONNECT_)*/
1291
                 /* && ((pDCB->DevType == TYPE_DISK)
1292
                     || (pDCB->DevType == TYPE_MOD))*/ )
1293
                pDCB->SyncMode |= EN_ATN_STOP;
1294
             else
1295
               //pDCB->SyncMode &= ~EN_ATN_STOP;
1296
               pDCB->SyncMode &= ~0;
1297
          }
1298
     }
1299
};
1300
 
1301
 
1302
static void
1303
dc390_add_dev (PACB pACB, PDCB pDCB, PSCSI_INQDATA ptr)
1304
{
1305
   UCHAR bval1 = ptr->DevType & SCSI_DEVTYPE;
1306
   pDCB->DevType = bval1;
1307
   /* if (bval1 == TYPE_DISK || bval1 == TYPE_MOD) */
1308
        dc390_disc_tagq_set (pDCB, ptr);
1309
};
1310
 
1311
 
1312
void
1313
dc390_SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB )
1314
{
1315
    PSRB   psrb;
1316
    UCHAR  bval, status, i;
1317
    PSCSICMD pcmd;
1318
    PSCSI_INQDATA  ptr;
1319
    PSGL   ptr2;
1320
    ULONG  swlval;
1321
 
1322
    pcmd = pSRB->pcmd;
1323
    status = pSRB->TargetStatus;
1324
    DEBUG0(printk (" SRBdone (%02x,%08x), SRB %p, pid %li\n", status, pcmd->result,\
1325
                pSRB, pcmd->pid);)
1326
    if(pSRB->SRBFlag & AUTO_REQSENSE)
1327
    {   /* Last command was a Request Sense */
1328
        pSRB->SRBFlag &= ~AUTO_REQSENSE;
1329
        pSRB->AdaptStatus = 0;
1330
        pSRB->TargetStatus = SCSI_STAT_CHECKCOND;
1331
#ifdef DC390_REMOVABLEDEBUG
1332
        switch (pcmd->sense_buffer[2] & 0x0f)
1333
        {
1334
         case NOT_READY: printk (KERN_INFO "DC390: ReqSense: NOT_READY (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n",
1335
                                 pcmd->cmnd[0], pDCB->UnitSCSIID, pDCB->UnitSCSILUN,
1336
                                 status, pACB->scan_devices); break;
1337
         case UNIT_ATTENTION: printk (KERN_INFO "DC390: ReqSense: UNIT_ATTENTION (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n",
1338
                                      pcmd->cmnd[0], pDCB->UnitSCSIID, pDCB->UnitSCSILUN,
1339
                                      status, pACB->scan_devices); break;
1340
         case ILLEGAL_REQUEST: printk (KERN_INFO "DC390: ReqSense: ILLEGAL_REQUEST (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n",
1341
                                       pcmd->cmnd[0], pDCB->UnitSCSIID, pDCB->UnitSCSILUN,
1342
                                       status, pACB->scan_devices); break;
1343
         case MEDIUM_ERROR: printk (KERN_INFO "DC390: ReqSense: MEDIUM_ERROR (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n",
1344
                                    pcmd->cmnd[0], pDCB->UnitSCSIID, pDCB->UnitSCSILUN,
1345
                                    status, pACB->scan_devices); break;
1346
         case HARDWARE_ERROR: printk (KERN_INFO "DC390: ReqSense: HARDWARE_ERROR (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n",
1347
                                      pcmd->cmnd[0], pDCB->UnitSCSIID, pDCB->UnitSCSILUN,
1348
                                      status, pACB->scan_devices); break;
1349
        }
1350
#endif
1351
        //pcmd->result = DRIVER_SENSE << 24 | DID_OK << 16 | status;
1352
        if(status == SCSI_STAT_CHECKCOND)
1353
        {
1354
            pcmd->result = DID_BAD_TARGET << 16;
1355
            goto ckc_e;
1356
        }
1357
        if(pSRB->RetryCnt == 0)
1358
        {
1359
            (ULONG)(pSRB->CmdBlock[0]) = pSRB->Segment0[0];
1360
            pSRB->TotalXferredLen = pSRB->Segment1[1];
1361
            if( (pSRB->TotalXferredLen) &&
1362
                (pSRB->TotalXferredLen >= pcmd->underflow) )
1363
                pcmd->result |= (DID_OK << 16);
1364
            else
1365
                pcmd->result = (DRIVER_SENSE << 24) | (DRIVER_OK << 16) |
1366
                                SCSI_STAT_CHECKCOND;
1367
            REMOVABLEDEBUG(printk(KERN_INFO "Cmd=%02x,Result=%08x,XferL=%08x\n",pSRB->CmdBlock[0],\
1368
                (UINT) pcmd->result, (UINT) pSRB->TotalXferredLen);)
1369
            goto ckc_e;
1370
        }
1371
        else /* Retry */
1372
        {
1373
            pSRB->RetryCnt--;
1374
            pSRB->AdaptStatus = 0;
1375
            pSRB->TargetStatus = 0;
1376
            *((PULONG) &(pSRB->CmdBlock[0])) = pSRB->Segment0[0];
1377
            *((PULONG) &(pSRB->CmdBlock[4])) = pSRB->Segment0[1];
1378
            /* Don't retry on TEST_UNIT_READY */
1379
            if( pSRB->CmdBlock[0] == TEST_UNIT_READY /* || pSRB->CmdBlock[0] == START_STOP */)
1380
            {
1381
                pcmd->result = (DRIVER_SENSE << 24) | (DRIVER_OK << 16)
1382
                            | SCSI_STAT_CHECKCOND;
1383
                REMOVABLEDEBUG(printk(KERN_INFO "Cmd=%02x, Result=%08x, XferL=%08x\n",pSRB->CmdBlock[0],\
1384
                       (UINT) pcmd->result, (UINT) pSRB->TotalXferredLen);)
1385
                goto ckc_e;
1386
            }
1387
            pcmd->result |= (DRIVER_SENSE << 24);
1388
            pSRB->SGcount        = (UCHAR) pSRB->Segment1[0];
1389
            pSRB->ScsiCmdLen     = (UCHAR) (pSRB->Segment1[0] >> 8);
1390
            pSRB->SGIndex = 0;
1391
            pSRB->TotalXferredLen = 0;
1392
            pSRB->SGToBeXferLen = 0;
1393
            if( pcmd->use_sg )
1394
                pSRB->pSegmentList = (PSGL) pcmd->request_buffer;
1395
            else if( pcmd->request_buffer )
1396
            {
1397
                pSRB->pSegmentList = (PSGL) &pSRB->Segmentx;
1398
                pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer;
1399
                pSRB->Segmentx.length = pcmd->request_bufflen;
1400
            }
1401
            if( dc390_StartSCSI( pACB, pDCB, pSRB ) )
1402
                dc390_RewaitSRB( pDCB, pSRB );
1403
            return;
1404
        }
1405
    }
1406
    if( status )
1407
    {
1408
        if( status == SCSI_STAT_CHECKCOND)
1409
        {
1410
            REMOVABLEDEBUG(printk (KERN_INFO "DC390: Scsi_Stat_CheckCond (Cmd %02x, Id %02x, LUN %02x)\n",\
1411
                    pcmd->cmnd[0], pDCB->UnitSCSIID, pDCB->UnitSCSILUN);)
1412
            if( (pSRB->SGIndex < pSRB->SGcount) && (pSRB->SGcount) && (pSRB->SGToBeXferLen) )
1413
            {
1414
                bval = pSRB->SGcount;
1415
                swlval = 0;
1416
                ptr2 = pSRB->pSegmentList;
1417
                for( i=pSRB->SGIndex; i < bval; i++)
1418
                {
1419
                    swlval += ptr2->length;
1420
                    ptr2++;
1421
                }
1422
                REMOVABLEDEBUG(printk(KERN_INFO "XferredLen=%08x,NotXferLen=%08x\n",\
1423
                        (UINT) pSRB->TotalXferredLen, (UINT) swlval);)
1424
            }
1425
            dc390_RequestSense( pACB, pDCB, pSRB );
1426
            return;
1427
        }
1428
        else if( status == SCSI_STAT_QUEUEFULL )
1429
        {
1430
            bval = (UCHAR) pDCB->GoingSRBCnt;
1431
            bval--;
1432
            pDCB->MaxCommand = bval;
1433
            dc390_RewaitSRB( pDCB, pSRB );
1434
            pSRB->AdaptStatus = 0;
1435
            pSRB->TargetStatus = 0;
1436
            return;
1437
        }
1438
        else if(status == SCSI_STAT_SEL_TIMEOUT)
1439
        {
1440
            pSRB->AdaptStatus = H_SEL_TIMEOUT;
1441
            pSRB->TargetStatus = 0;
1442
            pcmd->result = DID_BAD_TARGET << 16;
1443
            /* Devices are removed below ... */
1444
        }
1445
        else if (status == SCSI_STAT_BUSY &&
1446
                 (pSRB->CmdBlock[0] == TEST_UNIT_READY || pSRB->CmdBlock[0] == INQUIRY) &&
1447
                 pACB->scan_devices)
1448
        {
1449
            pSRB->AdaptStatus = 0;
1450
            pSRB->TargetStatus = status;
1451
            pcmd->result = (ULONG) (pSRB->EndMessage << 8)
1452
                                /* | (ULONG) status */;
1453
        }
1454
        else
1455
        {   /* Another error */
1456
            pSRB->AdaptStatus = 0;
1457
            if( pSRB->RetryCnt )
1458
            {   /* Retry */
1459
                pSRB->RetryCnt--;
1460
                pSRB->TargetStatus = 0;
1461
                pSRB->SGIndex = 0;
1462
                pSRB->TotalXferredLen = 0;
1463
                pSRB->SGToBeXferLen = 0;
1464
                if( pcmd->use_sg )
1465
                    pSRB->pSegmentList = (PSGL) pcmd->request_buffer;
1466
                else if( pcmd->request_buffer )
1467
                {
1468
                    pSRB->pSegmentList = (PSGL) &pSRB->Segmentx;
1469
                    pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer;
1470
                    pSRB->Segmentx.length = pcmd->request_bufflen;
1471
                }
1472
                if( dc390_StartSCSI( pACB, pDCB, pSRB ) )
1473
                    dc390_RewaitSRB( pDCB, pSRB );
1474
                return;
1475
            }
1476
            else
1477
            {   /* Report error */
1478
                pcmd->result |= (DID_ERROR << 16) | (ULONG) (pSRB->EndMessage << 8) |
1479
                               (ULONG) status;
1480
            }
1481
        }
1482
    }
1483
    else
1484
    {   /*  Target status == 0 */
1485
        status = pSRB->AdaptStatus;
1486
        if(status & H_OVER_UNDER_RUN)
1487
        {
1488
            pSRB->TargetStatus = 0;
1489
            pcmd->result |= (DID_OK << 16) | (pSRB->EndMessage << 8);
1490
        }
1491
        else if( pSRB->SRBStatus & PARITY_ERROR)
1492
        {
1493
            pcmd->result |= (DID_PARITY << 16) | (pSRB->EndMessage << 8);
1494
        }
1495
        else                   /* No error */
1496
        {
1497
            pSRB->AdaptStatus = 0;
1498
            pSRB->TargetStatus = 0;
1499
            pcmd->result |= (DID_OK << 16);
1500
        }
1501
    }
1502
 
1503
ckc_e:
1504
    if( pACB->scan_devices )
1505
    {
1506
        if( pSRB->CmdBlock[0] == TEST_UNIT_READY )
1507
        {
1508
#ifdef DC390_DEBUG0
1509
            printk (KERN_INFO "DC390: Test_Unit_Ready: result: %08x", pcmd->result);
1510
            if (pcmd->result & DRIVER_SENSE << 24) printk (" (sense: %02x %02x %02x %02x)\n",
1511
                                   pcmd->sense_buffer[0], pcmd->sense_buffer[1],
1512
                                   pcmd->sense_buffer[2], pcmd->sense_buffer[3]);
1513
            else printk ("\n");
1514
#endif
1515
            if((pcmd->result != (DID_OK << 16) && !(pcmd->result & SCSI_STAT_CHECKCOND) && !(pcmd->result & SCSI_STAT_BUSY)) ||
1516
               ((pcmd->result & DRIVER_SENSE << 24) && (pcmd->sense_buffer[0] & 0x70) == 0x70 &&
1517
                (pcmd->sense_buffer[2] & 0xf) == ILLEGAL_REQUEST) || pcmd->result & DID_ERROR << 16)
1518
            {
1519
               /* device not present: remove */
1520
               dc390_remove_dev (pACB, pDCB);
1521
 
1522
               if( (pcmd->target == pACB->pScsiHost->max_id - 1) &&
1523
                  ((pcmd->lun == 0) || (pcmd->lun == pACB->pScsiHost->max_lun - 1)) )
1524
                 pACB->scan_devices = 0;
1525
            }
1526
            else
1527
            {
1528
                /* device present: add */
1529
                if( (pcmd->target == pACB->pScsiHost->max_id - 1) &&
1530
                    (pcmd->lun == pACB->pScsiHost->max_lun - 1) )
1531
                    pACB->scan_devices = END_SCAN ;
1532
                /* pACB->DeviceCnt++; */ /* Dev is added on INQUIRY */
1533
            }
1534
        }
1535
    }
1536
 
1537
   if( pSRB->CmdBlock[0] == INQUIRY &&
1538
      (pcmd->result == DID_OK << 16 || pcmd->result & SCSI_STAT_CHECKCOND) )
1539
     {
1540
        ptr = (PSCSI_INQDATA) (pcmd->request_buffer);
1541
        if( pcmd->use_sg )
1542
          ptr = (PSCSI_INQDATA) (((PSGL) ptr)->address);
1543
        if ((ptr->DevType & SCSI_DEVTYPE) == TYPE_NODEV)
1544
          {
1545
             /* device not present: remove */
1546
             dc390_remove_dev (pACB, pDCB);
1547
          }
1548
        else
1549
          {
1550
             /* device found: add */
1551
             dc390_add_dev (pACB, pDCB, ptr);
1552
             if (pACB->scan_devices) pACB->DeviceCnt++;
1553
          }
1554
        if( (pcmd->target == pACB->pScsiHost->max_id - 1) &&
1555
            (pcmd->lun == pACB->pScsiHost->max_lun - 1) )
1556
          pACB->scan_devices = 0;
1557
     };
1558
/*  dc390_ReleaseSRB( pDCB, pSRB ); */
1559
 
1560
    if(pSRB == pDCB->pGoingSRB )
1561
    {
1562
        pDCB->pGoingSRB = pSRB->pNextSRB;
1563
    }
1564
    else
1565
    {
1566
        psrb = pDCB->pGoingSRB;
1567
        while( psrb->pNextSRB != pSRB )
1568
            psrb = psrb->pNextSRB;
1569
        psrb->pNextSRB = pSRB->pNextSRB;
1570
        if( pSRB == pDCB->pGoingLast )
1571
            pDCB->pGoingLast = psrb;
1572
    }
1573
    pSRB->pNextSRB = pACB->pFreeSRB;
1574
    pACB->pFreeSRB = pSRB;
1575
    pDCB->GoingSRBCnt--;
1576
 
1577
    dc390_DoWaitingSRB( pACB );
1578
 
1579
    DC390_UNLOCK_ACB_NI;
1580
    pcmd->scsi_done( pcmd );
1581
    DC390_LOCK_ACB_NI;
1582
 
1583
    if( pDCB->QIORBCnt )
1584
        dc390_DoNextCmd( pACB, pDCB );
1585
    return;
1586
}
1587
 
1588
 
1589
/* Remove all SRBs and tell midlevel code DID_RESET */
1590
void
1591
dc390_DoingSRB_Done( PACB pACB )
1592
{
1593
    PDCB   pDCB, pdcb;
1594
    PSRB   psrb, psrb2;
1595
    UCHAR  i;
1596
    PSCSICMD pcmd;
1597
 
1598
    pDCB = pACB->pLinkDCB;
1599
    pdcb = pDCB;
1600
    if (! pdcb) return;
1601
    do
1602
    {
1603
        psrb = pdcb->pGoingSRB;
1604
        for( i=0; i<pdcb->GoingSRBCnt; i++)
1605
        {
1606
            psrb2 = psrb->pNextSRB;
1607
            pcmd = psrb->pcmd;
1608
            pcmd->result = DID_RESET << 16;
1609
 
1610
/*          ReleaseSRB( pDCB, pSRB ); */
1611
 
1612
            psrb->pNextSRB = pACB->pFreeSRB;
1613
            pACB->pFreeSRB = psrb;
1614
 
1615
            DC390_UNLOCK_ACB_NI;
1616
            pcmd->scsi_done( pcmd );
1617
            DC390_LOCK_ACB_NI;
1618
            psrb  = psrb2;
1619
        }
1620
        pdcb->GoingSRBCnt = 0;;
1621
        pdcb->pGoingSRB = NULL;
1622
        pdcb->TagMask = 0;
1623
        pdcb = pdcb->pNextDCB;
1624
    } while( pdcb != pDCB );
1625
}
1626
 
1627
 
1628
static void
1629
dc390_ResetSCSIBus( PACB pACB )
1630
{
1631
    pACB->ACBFlag |= RESET_DEV;
1632
 
1633
    DC390_write8 (ScsiCmd, RST_DEVICE_CMD);
1634
    udelay (250);
1635
    DC390_write8 (ScsiCmd, NOP_CMD);
1636
 
1637
    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
1638
    DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
1639
    DC390_write8 (ScsiCmd, RST_SCSI_BUS_CMD);
1640
 
1641
    return;
1642
}
1643
 
1644
static void
1645
dc390_ScsiRstDetect( PACB pACB )
1646
{
1647
    printk ("DC390: Rst_Detect: laststat = %08lx\n", dc390_laststatus);
1648
    //DEBUG0(printk(KERN_INFO "RST_DETECT,");)
1649
 
1650
    DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
1651
    /* Unlock before ? */
1652
    /* delay a second */
1653
    { unsigned int msec = 1*1000; while (--msec) udelay(1000); }
1654
    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
1655
 
1656
    if( pACB->ACBFlag & RESET_DEV )
1657
        pACB->ACBFlag |= RESET_DONE;
1658
    else
1659
    {
1660
        pACB->ACBFlag |= RESET_DETECT;
1661
 
1662
        dc390_ResetDevParam( pACB );
1663
/*      dc390_DoingSRB_Done( pACB ); ???? */
1664
        dc390_RecoverSRB( pACB );
1665
        pACB->pActiveDCB = NULL;
1666
        pACB->ACBFlag = 0;
1667
        dc390_DoWaitingSRB( pACB );
1668
    }
1669
    return;
1670
}
1671
 
1672
 
1673
static void __inline__
1674
dc390_RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB )
1675
{
1676
    PSCSICMD  pcmd;
1677
 
1678
    REMOVABLEDEBUG(printk (KERN_INFO "DC390: RequestSense (Cmd %02x, Id %02x, LUN %02x)\n",\
1679
            pSRB->CmdBlock[0], pDCB->UnitSCSIID, pDCB->UnitSCSILUN);)
1680
 
1681
    pSRB->SRBFlag |= AUTO_REQSENSE;
1682
    pSRB->Segment0[0] = (ULONG) pSRB->CmdBlock[0];
1683
    pSRB->Segment0[1] = (ULONG) pSRB->CmdBlock[4];
1684
    pSRB->Segment1[0] = (ULONG) ((pSRB->ScsiCmdLen << 8) + pSRB->SGcount);
1685
    pSRB->Segment1[1] = pSRB->TotalXferredLen;
1686
    pSRB->AdaptStatus = 0;
1687
    pSRB->TargetStatus = 0; /* SCSI_STAT_CHECKCOND; */
1688
 
1689
    pcmd = pSRB->pcmd;
1690
 
1691
    pSRB->Segmentx.address = (PUCHAR) &(pcmd->sense_buffer);
1692
    pSRB->Segmentx.length = sizeof(pcmd->sense_buffer);
1693
    pSRB->pSegmentList = &pSRB->Segmentx;
1694
    pSRB->SGcount = 1;
1695
    pSRB->SGIndex = 0;
1696
 
1697
    pSRB->CmdBlock[0] = REQUEST_SENSE;
1698
    pSRB->CmdBlock[1] = pDCB->IdentifyMsg << 5;
1699
    (USHORT) pSRB->CmdBlock[2] = 0;
1700
    (USHORT) pSRB->CmdBlock[4] = sizeof(pcmd->sense_buffer);
1701
    pSRB->ScsiCmdLen = 6;
1702
 
1703
    pSRB->TotalXferredLen = 0;
1704
    pSRB->SGToBeXferLen = 0;
1705
    if( dc390_StartSCSI( pACB, pDCB, pSRB ) )
1706
        dc390_RewaitSRB( pDCB, pSRB );
1707
}
1708
 
1709
 
1710
 
1711
static void __inline__
1712
dc390_InvalidCmd( PACB pACB )
1713
{
1714
    if( pACB->pActiveDCB->pActiveSRB->SRBState & (SRB_START_+SRB_MSGOUT) )
1715
        DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
1716
}
1717
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.