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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [scsi/] [scsiiom.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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