|
|
1.1 root 1: /***********************************************************************
2: * FILE NAME : TMSCSIM.C *
3: * BY : C.L. Huang, [email protected] *
4: * Description: Device Driver for Tekram DC-390(T) PCI SCSI *
5: * Bus Master Host Adapter *
6: * (C)Copyright 1995-1996 Tekram Technology Co., Ltd. *
7: ***********************************************************************/
8: /* Minor enhancements and bugfixes by *
9: * Kurt Garloff <[email protected]> *
10: ***********************************************************************/
11: /* HISTORY: *
12: * *
13: * REV# DATE NAME DESCRIPTION *
14: * 1.00 04/24/96 CLH First release *
15: * 1.01 06/12/96 CLH Fixed bug of Media Change for Removable *
16: * Device, scan all LUN. Support Pre2.0.10 *
17: * 1.02 06/18/96 CLH Fixed bug of Command timeout ... *
18: * 1.03 09/25/96 KG Added tmscsim_proc_info() *
19: * 1.04 10/11/96 CLH Updating for support KV 2.0.x *
20: * 1.05 10/18/96 KG Fixed bug in DC390_abort(null ptr deref)*
21: * 1.06 10/25/96 KG Fixed module support *
22: * 1.07 11/09/96 KG Fixed tmscsim_proc_info() *
23: * 1.08 11/18/96 KG Fixed null ptr in DC390_Disconnect() *
24: * 1.09 11/30/96 KG Added register the allocated IO space *
25: * 1.10 12/05/96 CLH Modified tmscsim_proc_info(), and reset *
26: * pending interrupt in DC390_detect() *
27: * 1.11 02/05/97 KG/CLH Fixeds problem with partitions greater *
28: * than 1GB *
29: ***********************************************************************/
30:
31:
32: #define DC390_DEBUG
33:
34: #define SCSI_MALLOC
35:
36: #ifdef MODULE
37: #include <linux/module.h>
38: #endif
39:
40: #include <asm/dma.h>
41: #include <asm/io.h>
42: #include <asm/system.h>
43: #include <linux/delay.h>
44: #include <linux/signal.h>
45: #include <linux/sched.h>
46: #include <linux/errno.h>
47: #include <linux/kernel.h>
48: #include <linux/ioport.h>
49: #include <linux/bios32.h>
50: #include <linux/pci.h>
51: #include <linux/proc_fs.h>
52: #include <linux/string.h>
53: #include <linux/mm.h>
54: #include <linux/config.h>
55:
56: #include <linux/version.h>
57: #if LINUX_VERSION_CODE < 66354 /* 1.3.50 */
58: #include "../block/blk.h"
59: #else
60: #include <linux/blk.h>
61: #endif
62:
63: #include "scsi.h"
64: #include "hosts.h"
65: #include "tmscsim.h"
66: #include "constants.h"
67: #include "sd.h"
68: #include <linux/stat.h>
69:
70: #include "dc390.h"
71:
72: #define PCI_DEVICE_ID_AMD53C974 PCI_DEVICE_ID_AMD_SCSI
73:
74:
75: #ifndef VERSION_ELF_1_2_13
76: struct proc_dir_entry proc_scsi_tmscsim ={
77: PROC_SCSI_DC390T, 7 ,"tmscsim",
78: S_IFDIR | S_IRUGO | S_IXUGO, 2
79: };
80: #endif
81:
82: static USHORT DC390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB );
83: static void DC390_DataOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
84: static void DC390_DataIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
85: static void DC390_Command_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
86: static void DC390_Status_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
87: static void DC390_MsgOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
88: static void DC390_MsgIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
89: static void DC390_DataOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
90: static void DC390_DataInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
91: static void DC390_CommandPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
92: static void DC390_StatusPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
93: static void DC390_MsgOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
94: static void DC390_MsgInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
95: static void DC390_Nop_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
96: static void DC390_Nop_1( PACB pACB, PSRB pSRB, PUCHAR psstatus);
97:
98: static void SetXferRate( PACB pACB, PDCB pDCB );
99: static void DC390_Disconnect( PACB pACB );
100: static void DC390_Reselect( PACB pACB );
101: static void SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB );
102: static void DoingSRB_Done( PACB pACB );
103: static void DC390_ScsiRstDetect( PACB pACB );
104: static void DC390_ResetSCSIBus( PACB pACB );
105: static void RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB );
106: static void EnableMsgOut2( PACB pACB, PSRB pSRB );
107: static void EnableMsgOut( PACB pACB, PSRB pSRB );
108: static void DC390_InvalidCmd( PACB pACB );
109:
110: int DC390_initAdapter( PSH psh, ULONG io_port, UCHAR Irq, USHORT index );
111: void DC390_initDCB( PACB pACB, PDCB pDCB, PSCSICMD cmd );
112:
113: #ifdef MODULE
114: static int DC390_release(struct Scsi_Host *host);
115: static int DC390_shutdown (struct Scsi_Host *host);
116: #endif
117:
118:
119: static PSHT pSHT_start = NULL;
120: static PSH pSH_start = NULL;
121: static PSH pSH_current = NULL;
122: static PACB pACB_start= NULL;
123: static PACB pACB_current = NULL;
124: static PDCB pPrevDCB = NULL;
125: static USHORT adapterCnt = 0;
126: static USHORT InitialTime = 0;
127: static USHORT CurrSyncOffset = 0;
128: static ULONG mech1addr;
129: static UCHAR mech2bus, mech2Agent, mech2CfgSPenR;
130:
131: static PVOID DC390_phase0[]={
132: DC390_DataOut_0,
133: DC390_DataIn_0,
134: DC390_Command_0,
135: DC390_Status_0,
136: DC390_Nop_0,
137: DC390_Nop_0,
138: DC390_MsgOut_0,
139: DC390_MsgIn_0,
140: DC390_Nop_1
141: };
142:
143: static PVOID DC390_phase1[]={
144: DC390_DataOutPhase,
145: DC390_DataInPhase,
146: DC390_CommandPhase,
147: DC390_StatusPhase,
148: DC390_Nop_0,
149: DC390_Nop_0,
150: DC390_MsgOutPhase,
151: DC390_MsgInPhase,
152: DC390_Nop_1,
153: };
154:
155: UCHAR eepromBuf[MAX_ADAPTER_NUM][128];
156:
157:
158: UCHAR clock_period1[] = {4, 5, 6, 7, 8, 10, 13, 20};
159:
160: UCHAR baddevname1[2][28] ={
161: "SEAGATE ST3390N 9546",
162: "HP C3323-300 4269"};
163:
164: #define BADDEVCNT 2
165:
166:
167: /***********************************************************************
168: *
169: *
170: *
171: **********************************************************************/
172: static void
173: QLinkcmd( PSCSICMD cmd, PDCB pDCB )
174: {
175: ULONG flags;
176: PSCSICMD pcmd;
177:
178: save_flags(flags);
179: cli();
180:
181: if( !pDCB->QIORBCnt )
182: {
183: pDCB->pQIORBhead = cmd;
184: pDCB->pQIORBtail = cmd;
185: pDCB->QIORBCnt++;
186: cmd->next = NULL;
187: }
188: else
189: {
190: pcmd = pDCB->pQIORBtail;
191: pcmd->next = cmd;
192: pDCB->pQIORBtail = cmd;
193: pDCB->QIORBCnt++;
194: cmd->next = NULL;
195: }
196:
197: restore_flags(flags);
198: }
199:
200:
201: static PSCSICMD
202: Getcmd( PDCB pDCB )
203: {
204: ULONG flags;
205: PSCSICMD pcmd;
206:
207: save_flags(flags);
208: cli();
209:
210: pcmd = pDCB->pQIORBhead;
211: pDCB->pQIORBhead = pcmd->next;
212: pcmd->next = NULL;
213: pDCB->QIORBCnt--;
214:
215: restore_flags(flags);
216: return( pcmd );
217: }
218:
219:
220: static PSRB
221: GetSRB( PACB pACB )
222: {
223: ULONG flags;
224: PSRB pSRB;
225:
226: save_flags(flags);
227: cli();
228:
229: pSRB = pACB->pFreeSRB;
230: if( pSRB )
231: {
232: pACB->pFreeSRB = pSRB->pNextSRB;
233: pSRB->pNextSRB = NULL;
234: }
235: restore_flags(flags);
236: return( pSRB );
237: }
238:
239:
240: static void
241: RewaitSRB0( PDCB pDCB, PSRB pSRB )
242: {
243: PSRB psrb1;
244: ULONG flags;
245:
246: save_flags(flags);
247: cli();
248:
249: if( (psrb1 = pDCB->pWaitingSRB) )
250: {
251: pSRB->pNextSRB = psrb1;
252: pDCB->pWaitingSRB = pSRB;
253: }
254: else
255: {
256: pSRB->pNextSRB = NULL;
257: pDCB->pWaitingSRB = pSRB;
258: pDCB->pWaitLast = pSRB;
259: }
260: restore_flags(flags);
261: }
262:
263:
264: static void
265: RewaitSRB( PDCB pDCB, PSRB pSRB )
266: {
267: PSRB psrb1;
268: ULONG flags;
269: UCHAR bval;
270:
271: save_flags(flags);
272: cli();
273: pDCB->GoingSRBCnt--;
274: psrb1 = pDCB->pGoingSRB;
275: if( pSRB == psrb1 )
276: {
277: pDCB->pGoingSRB = psrb1->pNextSRB;
278: }
279: else
280: {
281: while( pSRB != psrb1->pNextSRB )
282: psrb1 = psrb1->pNextSRB;
283: psrb1->pNextSRB = pSRB->pNextSRB;
284: if( pSRB == pDCB->pGoingLast )
285: pDCB->pGoingLast = psrb1;
286: }
287: if( (psrb1 = pDCB->pWaitingSRB) )
288: {
289: pSRB->pNextSRB = psrb1;
290: pDCB->pWaitingSRB = pSRB;
291: }
292: else
293: {
294: pSRB->pNextSRB = NULL;
295: pDCB->pWaitingSRB = pSRB;
296: pDCB->pWaitLast = pSRB;
297: }
298:
299: bval = pSRB->TagNumber;
300: pDCB->TagMask &= (~(1 << bval)); /* Free TAG number */
301: restore_flags(flags);
302: }
303:
304:
305: static void
306: DoWaitingSRB( PACB pACB )
307: {
308: ULONG flags;
309: PDCB ptr, ptr1;
310: PSRB pSRB;
311:
312: save_flags(flags);
313: cli();
314:
315: if( !(pACB->pActiveDCB) && !(pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) ) )
316: {
317: ptr = pACB->pDCBRunRobin;
318: if( !ptr )
319: {
320: ptr = pACB->pLinkDCB;
321: pACB->pDCBRunRobin = ptr;
322: }
323: ptr1 = ptr;
324: for( ;ptr1; )
325: {
326: pACB->pDCBRunRobin = ptr1->pNextDCB;
327: if( !( ptr1->MaxCommand > ptr1->GoingSRBCnt ) ||
328: !( pSRB = ptr1->pWaitingSRB ) )
329: {
330: if(pACB->pDCBRunRobin == ptr)
331: break;
332: ptr1 = ptr1->pNextDCB;
333: }
334: else
335: {
336: if( !DC390_StartSCSI(pACB, ptr1, pSRB) )
337: {
338: ptr1->GoingSRBCnt++;
339: if( ptr1->pWaitLast == pSRB )
340: {
341: ptr1->pWaitingSRB = NULL;
342: ptr1->pWaitLast = NULL;
343: }
344: else
345: {
346: ptr1->pWaitingSRB = pSRB->pNextSRB;
347: }
348: pSRB->pNextSRB = NULL;
349:
350: if( ptr1->pGoingSRB )
351: ptr1->pGoingLast->pNextSRB = pSRB;
352: else
353: ptr1->pGoingSRB = pSRB;
354: ptr1->pGoingLast = pSRB;
355: }
356: break;
357: }
358: }
359: }
360: restore_flags(flags);
361: return;
362: }
363:
364:
365: static void
366: SRBwaiting( PDCB pDCB, PSRB pSRB)
367: {
368: if( pDCB->pWaitingSRB )
369: {
370: pDCB->pWaitLast->pNextSRB = pSRB;
371: pDCB->pWaitLast = pSRB;
372: pSRB->pNextSRB = NULL;
373: }
374: else
375: {
376: pDCB->pWaitingSRB = pSRB;
377: pDCB->pWaitLast = pSRB;
378: }
379: }
380:
381:
382: static void
383: SendSRB( PSCSICMD pcmd, PACB pACB, PSRB pSRB )
384: {
385: ULONG flags;
386: PDCB pDCB;
387:
388: save_flags(flags);
389: cli();
390:
391: pDCB = pSRB->pSRBDCB;
392: if( !(pDCB->MaxCommand > pDCB->GoingSRBCnt) || (pACB->pActiveDCB) ||
393: (pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV)) )
394: {
395: SRBwaiting(pDCB, pSRB);
396: goto SND_EXIT;
397: }
398:
399: if( pDCB->pWaitingSRB )
400: {
401: SRBwaiting(pDCB, pSRB);
402: /* pSRB = GetWaitingSRB(pDCB); */
403: pSRB = pDCB->pWaitingSRB;
404: pDCB->pWaitingSRB = pSRB->pNextSRB;
405: pSRB->pNextSRB = NULL;
406: }
407:
408: if( !DC390_StartSCSI(pACB, pDCB, pSRB) )
409: {
410: pDCB->GoingSRBCnt++;
411: if( pDCB->pGoingSRB )
412: {
413: pDCB->pGoingLast->pNextSRB = pSRB;
414: pDCB->pGoingLast = pSRB;
415: }
416: else
417: {
418: pDCB->pGoingSRB = pSRB;
419: pDCB->pGoingLast = pSRB;
420: }
421: }
422: else
423: RewaitSRB0( pDCB, pSRB );
424:
425: SND_EXIT:
426: restore_flags(flags);
427: return;
428: }
429:
430:
431: /***********************************************************************
432: * Function : static int DC390_queue_command (Scsi_Cmnd *cmd,
433: * void (*done)(Scsi_Cmnd *))
434: *
435: * Purpose : enqueues a SCSI command
436: *
437: * Inputs : cmd - SCSI command, done - function called on completion, with
438: * a pointer to the command descriptor.
439: *
440: * Returns : 0
441: *
442: ***********************************************************************/
443:
444: int
445: DC390_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *))
446: {
447: USHORT ioport, i;
448: Scsi_Cmnd *pcmd;
449: struct Scsi_Host *psh;
450: PACB pACB;
451: PDCB pDCB;
452: PSRB pSRB;
453: ULONG flags;
454: PUCHAR ptr,ptr1;
455:
456: psh = cmd->host;
457: pACB = (PACB ) psh->hostdata;
458: ioport = pACB->IOPortBase;
459:
460: #ifdef DC390_DEBUG0
461: /* if(pACB->scan_devices) */
462: printk("Cmd=%2x,ID=%d,LUN=%d,",cmd->cmnd[0],cmd->target,cmd->lun);
463: #endif
464:
465: if( (pACB->scan_devices == END_SCAN) && (cmd->cmnd[0] != INQUIRY) )
466: {
467: pACB->scan_devices = 0;
468: pPrevDCB->pNextDCB = pACB->pLinkDCB;
469: }
470: else if( (pACB->scan_devices) && (cmd->cmnd[0] == 8) )
471: {
472: pACB->scan_devices = 0;
473: pPrevDCB->pNextDCB = pACB->pLinkDCB;
474: }
475:
476: if ( ( cmd->target > pACB->max_id ) || (cmd->lun > pACB->max_lun) )
477: {
478: /* printk("DC390: Ignore target %d lun %d\n",
479: cmd->target, cmd->lun); */
480: cmd->result = (DID_BAD_TARGET << 16);
481: done(cmd);
482: return( 0 );
483: }
484:
485: if( (pACB->scan_devices) && !(pACB->DCBmap[cmd->target] & (1 << cmd->lun)) )
486: {
487: if( pACB->DeviceCnt < MAX_DEVICES )
488: {
489: pACB->DCBmap[cmd->target] |= (1 << cmd->lun);
490: pDCB = pACB->pDCB_free;
491: #ifdef DC390_DEBUG0
492: printk("pDCB=%8x,ID=%2x,", (UINT) pDCB, cmd->target);
493: #endif
494: DC390_initDCB( pACB, pDCB, cmd );
495: }
496: else /* ???? */
497: {
498: /* printk("DC390: Ignore target %d lun %d\n",
499: cmd->target, cmd->lun); */
500: cmd->result = (DID_BAD_TARGET << 16);
501: done(cmd);
502: return(0);
503: }
504: }
505: else if( !(pACB->scan_devices) && !(pACB->DCBmap[cmd->target] & (1 << cmd->lun)) )
506: {
507: /* printk("DC390: Ignore target %d lun %d\n",
508: cmd->target, cmd->lun); */
509: cmd->result = (DID_BAD_TARGET << 16);
510: done(cmd);
511: return(0);
512: }
513: else
514: {
515: pDCB = pACB->pLinkDCB;
516: while( (pDCB->UnitSCSIID != cmd->target) ||
517: (pDCB->UnitSCSILUN != cmd->lun) )
518: {
519: pDCB = pDCB->pNextDCB;
520: }
521: #ifdef DC390_DEBUG0
522: printk("pDCB=%8x,ID=%2x,", (UINT) pDCB, cmd->target);
523: #endif
524: }
525:
526: cmd->scsi_done = done;
527: cmd->result = 0;
528:
529: save_flags(flags);
530: cli();
531:
532: if( pDCB->QIORBCnt )
533: {
534: QLinkcmd( cmd, pDCB );
535: pcmd = Getcmd( pDCB );
536: }
537: else
538: pcmd = cmd;
539:
540: pSRB = GetSRB( pACB );
541:
542: if( !pSRB )
543: {
544: QLinkcmd( pcmd, pDCB );
545: restore_flags(flags);
546: return(0);
547: }
548:
549: /* BuildSRB(pSRB); */
550:
551: pSRB->pSRBDCB = pDCB;
552: pSRB->pcmd = pcmd;
553: ptr = (PUCHAR) pSRB->CmdBlock;
554: ptr1 = (PUCHAR) pcmd->cmnd;
555: pSRB->ScsiCmdLen = pcmd->cmd_len;
556: for(i=0; i< pcmd->cmd_len; i++)
557: {
558: *ptr = *ptr1;
559: ptr++;
560: ptr1++;
561: }
562: if( pcmd->use_sg )
563: {
564: pSRB->SGcount = (UCHAR) pcmd->use_sg;
565: pSRB->pSegmentList = (PSGL) pcmd->request_buffer;
566: }
567: else if( pcmd->request_buffer )
568: {
569: pSRB->SGcount = 1;
570: pSRB->pSegmentList = (PSGL) &pSRB->Segmentx;
571: pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer;
572: pSRB->Segmentx.length = pcmd->request_bufflen;
573: }
574: else
575: pSRB->SGcount = 0;
576:
577: pSRB->SGIndex = 0;
578: pSRB->AdaptStatus = 0;
579: pSRB->TargetStatus = 0;
580: pSRB->MsgCnt = 0;
581: if( pDCB->DevType != TYPE_TAPE )
582: pSRB->RetryCnt = 1;
583: else
584: pSRB->RetryCnt = 0;
585: pSRB->SRBStatus = 0;
586: pSRB->SRBFlag = 0;
587: pSRB->SRBState = 0;
588: pSRB->TotalXferredLen = 0;
589: pSRB->SGPhysAddr = 0;
590: pSRB->SGToBeXferLen = 0;
591: pSRB->ScsiPhase = 0;
592: pSRB->EndMessage = 0;
593: SendSRB( pcmd, pACB, pSRB );
594:
595: restore_flags(flags);
596: return(0);
597: }
598:
599:
600: static void
601: DoNextCmd( PACB pACB, PDCB pDCB )
602: {
603: Scsi_Cmnd *pcmd;
604: PSRB pSRB;
605: ULONG flags;
606: PUCHAR ptr,ptr1;
607: USHORT i;
608:
609:
610: if( pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) )
611: return;
612: save_flags(flags);
613: cli();
614:
615: pcmd = Getcmd( pDCB );
616: pSRB = GetSRB( pACB );
617: if( !pSRB )
618: {
619: QLinkcmd( pcmd, pDCB );
620: restore_flags(flags);
621: return;
622: }
623:
624: pSRB->pSRBDCB = pDCB;
625: pSRB->pcmd = pcmd;
626: ptr = (PUCHAR) pSRB->CmdBlock;
627: ptr1 = (PUCHAR) pcmd->cmnd;
628: pSRB->ScsiCmdLen = pcmd->cmd_len;
629: for(i=0; i< pcmd->cmd_len; i++)
630: {
631: *ptr = *ptr1;
632: ptr++;
633: ptr1++;
634: }
635: if( pcmd->use_sg )
636: {
637: pSRB->SGcount = (UCHAR) pcmd->use_sg;
638: pSRB->pSegmentList = (PSGL) pcmd->request_buffer;
639: }
640: else if( pcmd->request_buffer )
641: {
642: pSRB->SGcount = 1;
643: pSRB->pSegmentList = (PSGL) &pSRB->Segmentx;
644: pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer;
645: pSRB->Segmentx.length = pcmd->request_bufflen;
646: }
647: else
648: pSRB->SGcount = 0;
649:
650: pSRB->SGIndex = 0;
651: pSRB->AdaptStatus = 0;
652: pSRB->TargetStatus = 0;
653: pSRB->MsgCnt = 0;
654: if( pDCB->DevType != TYPE_TAPE )
655: pSRB->RetryCnt = 1;
656: else
657: pSRB->RetryCnt = 0;
658: pSRB->SRBStatus = 0;
659: pSRB->SRBFlag = 0;
660: pSRB->SRBState = 0;
661: pSRB->TotalXferredLen = 0;
662: pSRB->SGPhysAddr = 0;
663: pSRB->SGToBeXferLen = 0;
664: pSRB->ScsiPhase = 0;
665: pSRB->EndMessage = 0;
666: SendSRB( pcmd, pACB, pSRB );
667:
668: restore_flags(flags);
669: return;
670: }
671:
672:
673: /***********************************************************************
674: * Function:
675: * DC390_bios_param
676: *
677: * Description:
678: * Return the disk geometry for the given SCSI device.
679: ***********************************************************************/
680: #ifdef VERSION_ELF_1_2_13
681: int DC390_bios_param(Disk *disk, int devno, int geom[])
682: #else
683: int DC390_bios_param(Disk *disk, kdev_t devno, int geom[])
684: #endif
685: {
686: int heads, sectors, cylinders;
687: PACB pACB;
688:
689: pACB = (PACB) disk->device->host->hostdata;
690: heads = 64;
691: sectors = 32;
692: cylinders = disk->capacity / (heads * sectors);
693:
694: if ( (pACB->Gmode2 & GREATER_1G) && (cylinders > 1024) )
695: {
696: heads = 255;
697: sectors = 63;
698: cylinders = disk->capacity / (heads * sectors);
699: }
700:
701: geom[0] = heads;
702: geom[1] = sectors;
703: geom[2] = cylinders;
704:
705: return (0);
706: }
707:
708:
709: /***********************************************************************
710: * Function : int DC390_abort (Scsi_Cmnd *cmd)
711: *
712: * Purpose : Abort an errant SCSI command
713: *
714: * Inputs : cmd - command to abort
715: *
716: * Returns : 0 on success, -1 on failure.
717: ***********************************************************************/
718:
719: int
720: DC390_abort (Scsi_Cmnd *cmd)
721: {
722: ULONG flags;
723: PACB pACB;
724: PDCB pDCB, pdcb;
725: PSRB pSRB, psrb;
726: USHORT count, i;
727: PSCSICMD pcmd, pcmd1;
728: int status;
729:
730:
731: #ifdef DC390_DEBUG0
732: printk("DC390 : Abort Cmd.");
733: #endif
734:
735: save_flags(flags);
736: cli();
737:
738: pACB = (PACB) cmd->host->hostdata;
739: pDCB = pACB->pLinkDCB;
740: pdcb = pDCB;
741: while( (pDCB->UnitSCSIID != cmd->target) ||
742: (pDCB->UnitSCSILUN != cmd->lun) )
743: {
744: pDCB = pDCB->pNextDCB;
745: if( pDCB == pdcb )
746: goto NOT_RUN;
747: }
748:
749: if( pDCB->QIORBCnt )
750: {
751: pcmd = pDCB->pQIORBhead;
752: if( pcmd == cmd )
753: {
754: pDCB->pQIORBhead = pcmd->next;
755: pcmd->next = NULL;
756: pDCB->QIORBCnt--;
757: status = SCSI_ABORT_SUCCESS;
758: goto ABO_X;
759: }
760: for( count = pDCB->QIORBCnt, i=0; i<count-1; i++)
761: {
762: if( pcmd->next == cmd )
763: {
764: pcmd1 = pcmd->next;
765: pcmd->next = pcmd1->next;
766: pcmd1->next = NULL;
767: pDCB->QIORBCnt--;
768: status = SCSI_ABORT_SUCCESS;
769: goto ABO_X;
770: }
771: else
772: {
773: pcmd = pcmd->next;
774: }
775: }
776: }
777:
778: pSRB = pDCB->pWaitingSRB;
779: if( !pSRB )
780: goto ON_GOING;
781: if( pSRB->pcmd == cmd )
782: {
783: pDCB->pWaitingSRB = pSRB->pNextSRB;
784: goto IN_WAIT;
785: }
786: else
787: {
788: psrb = pSRB;
789: if( !(psrb->pNextSRB) )
790: goto ON_GOING;
791: while( psrb->pNextSRB->pcmd != cmd )
792: {
793: psrb = psrb->pNextSRB;
794: if( !(psrb->pNextSRB) )
795: goto ON_GOING;
796: }
797: pSRB = psrb->pNextSRB;
798: psrb->pNextSRB = pSRB->pNextSRB;
799: if( pSRB == pDCB->pWaitLast )
800: pDCB->pWaitLast = psrb; /* No check for psrb == NULL ? */
801: IN_WAIT:
802: pSRB->pNextSRB = pACB->pFreeSRB;
803: pACB->pFreeSRB = pSRB;
804: cmd->next = NULL;
805: status = SCSI_ABORT_SUCCESS;
806: goto ABO_X;
807: }
808:
809: ON_GOING:
810: pSRB = pDCB->pGoingSRB;
811: for( count = pDCB->GoingSRBCnt, i=0; i<count; i++)
812: {
813: if( pSRB->pcmd != cmd )
814: pSRB = pSRB->pNextSRB;
815: else
816: {
817: if( (pACB->pActiveDCB == pDCB) && (pDCB->pActiveSRB == pSRB) )
818: {
819: status = SCSI_ABORT_BUSY;
820: goto ABO_X;
821: }
822: else
823: {
824: status = SCSI_ABORT_SNOOZE;
825: goto ABO_X;
826: }
827: }
828: }
829:
830: NOT_RUN:
831: status = SCSI_ABORT_NOT_RUNNING;
832:
833: ABO_X:
834: cmd->result = DID_ABORT << 16;
835: cmd->scsi_done(cmd);
836: restore_flags(flags);
837: return( status );
838: }
839:
840:
841: static void
842: ResetDevParam( PACB pACB )
843: {
844: PDCB pDCB, pdcb;
845:
846: pDCB = pACB->pLinkDCB;
847: if( pDCB == NULL )
848: return;
849: pdcb = pDCB;
850: do
851: {
852: pDCB->SyncMode &= ~SYNC_NEGO_DONE;
853: pDCB->SyncPeriod = 0;
854: pDCB->SyncOffset = 0;
855: pDCB->CtrlR3 = FAST_CLK;
856: pDCB->CtrlR4 &= NEGATE_REQACKDATA;
857: pDCB->CtrlR4 |= EATER_25NS;
858: pDCB = pDCB->pNextDCB;
859: }
860: while( pdcb != pDCB );
861: }
862:
863:
864: static void
865: RecoverSRB( PACB pACB )
866: {
867: PDCB pDCB, pdcb;
868: PSRB psrb, psrb2;
869: USHORT cnt, i;
870:
871: pDCB = pACB->pLinkDCB;
872: if( pDCB == NULL )
873: return;
874: pdcb = pDCB;
875: do
876: {
877: cnt = pdcb->GoingSRBCnt;
878: psrb = pdcb->pGoingSRB;
879: for (i=0; i<cnt; i++)
880: {
881: psrb2 = psrb;
882: psrb = psrb->pNextSRB;
883: /* RewaitSRB( pDCB, psrb ); */
884: if( pdcb->pWaitingSRB )
885: {
886: psrb2->pNextSRB = pdcb->pWaitingSRB;
887: pdcb->pWaitingSRB = psrb2;
888: }
889: else
890: {
891: pdcb->pWaitingSRB = psrb2;
892: pdcb->pWaitLast = psrb2;
893: psrb2->pNextSRB = NULL;
894: }
895: }
896: pdcb->GoingSRBCnt = 0;
897: pdcb->pGoingSRB = NULL;
898: pdcb->TagMask = 0;
899: pdcb = pdcb->pNextDCB;
900: }
901: while( pdcb != pDCB );
902: }
903:
904:
905: /***********************************************************************
906: * Function : int DC390_reset (Scsi_Cmnd *cmd, ...)
907: *
908: * Purpose : perform a hard reset on the SCSI bus
909: *
910: * Inputs : cmd - command which caused the SCSI RESET
911: *
912: * Returns : 0 on success.
913: ***********************************************************************/
914:
915: #ifdef VERSION_2_0_0
916: int DC390_reset(Scsi_Cmnd *cmd, unsigned int resetFlags)
917: #else
918: int DC390_reset (Scsi_Cmnd *cmd)
919: #endif
920: {
921: USHORT ioport;
922: unsigned long flags;
923: PACB pACB;
924: UCHAR bval;
925: USHORT i;
926:
927:
928: #ifdef DC390_DEBUG1
929: printk("DC390: RESET,");
930: #endif
931:
932: pACB = (PACB ) cmd->host->hostdata;
933: ioport = pACB->IOPortBase;
934: save_flags(flags);
935: cli();
936: bval = inb(ioport+CtrlReg1);
937: bval |= DIS_INT_ON_SCSI_RST;
938: outb(bval,ioport+CtrlReg1); /* disable interrupt */
939: DC390_ResetSCSIBus( pACB );
940: for( i=0; i<500; i++ )
941: udelay(1000);
942: bval = inb(ioport+CtrlReg1);
943: bval &= ~DIS_INT_ON_SCSI_RST;
944: outb(bval,ioport+CtrlReg1); /* re-enable interrupt */
945:
946: bval = DMA_IDLE_CMD;
947: outb(bval,ioport+DMA_Cmd);
948: bval = CLEAR_FIFO_CMD;
949: outb(bval,ioport+ScsiCmd);
950:
951: ResetDevParam( pACB );
952: DoingSRB_Done( pACB );
953: pACB->pActiveDCB = NULL;
954:
955: pACB->ACBFlag = 0;
956: DoWaitingSRB( pACB );
957:
958: restore_flags(flags);
959: #ifdef DC390_DEBUG1
960: printk("DC390: RESET1,");
961: #endif
962: return( SCSI_RESET_SUCCESS );
963: }
964:
965:
966: #include "scsiiom.c"
967:
968:
969: /***********************************************************************
970: * Function : static void DC390_initDCB
971: *
972: * Purpose : initialize the internal structures for a given DCB
973: *
974: * Inputs : cmd - pointer to this scsi cmd request block structure
975: *
976: ***********************************************************************/
977: void DC390_initDCB( PACB pACB, PDCB pDCB, PSCSICMD cmd )
978: {
979: PEEprom prom;
980: UCHAR bval;
981: USHORT index;
982:
983: if( pACB->DeviceCnt == 0 )
984: {
985: pACB->pLinkDCB = pDCB;
986: pACB->pDCBRunRobin = pDCB;
987: pDCB->pNextDCB = pDCB;
988: pPrevDCB = pDCB;
989: }
990: else
991: pPrevDCB->pNextDCB = pDCB;
992:
993: pDCB->pDCBACB = pACB;
994: pDCB->QIORBCnt = 0;
995: pDCB->UnitSCSIID = cmd->target;
996: pDCB->UnitSCSILUN = cmd->lun;
997: pDCB->pWaitingSRB = NULL;
998: pDCB->pGoingSRB = NULL;
999: pDCB->GoingSRBCnt = 0;
1000: pDCB->pActiveSRB = NULL;
1001: pDCB->TagMask = 0;
1002: pDCB->MaxCommand = 1;
1003: pDCB->AdaptIndex = pACB->AdapterIndex;
1004: index = pACB->AdapterIndex;
1005: pDCB->DCBFlag = 0;
1006:
1007: prom = (PEEprom) &eepromBuf[index][cmd->target << 2];
1008: pDCB->DevMode = prom->EE_MODE1;
1009: pDCB->AdpMode = eepromBuf[index][EE_MODE2];
1010:
1011: if( pDCB->DevMode & EN_DISCONNECT_ )
1012: bval = 0xC0;
1013: else
1014: bval = 0x80;
1015: bval |= cmd->lun;
1016: pDCB->IdentifyMsg = bval;
1017:
1018: pDCB->SyncMode = 0;
1019: if( pDCB->DevMode & SYNC_NEGO_ )
1020: {
1021: if( !(cmd->lun) || CurrSyncOffset )
1022: pDCB->SyncMode = SYNC_ENABLE;
1023: }
1024:
1025: pDCB->SyncPeriod = 0;
1026: pDCB->SyncOffset = 0;
1027: pDCB->NegoPeriod = (clock_period1[prom->EE_SPEED] * 25) >> 2;
1028:
1029: pDCB->CtrlR1 = pACB->AdaptSCSIID;
1030: if( pDCB->DevMode & PARITY_CHK_ )
1031: pDCB->CtrlR1 |= PARITY_ERR_REPO;
1032:
1033: pDCB->CtrlR3 = FAST_CLK;
1034:
1035: pDCB->CtrlR4 = EATER_25NS;
1036: if( pDCB->AdpMode & ACTIVE_NEGATION)
1037: pDCB->CtrlR4 |= NEGATE_REQACKDATA;
1038: }
1039:
1040:
1041: /***********************************************************************
1042: * Function : static void DC390_initSRB
1043: *
1044: * Purpose : initialize the internal structures for a given SRB
1045: *
1046: * Inputs : psrb - pointer to this scsi request block structure
1047: *
1048: ***********************************************************************/
1049: void DC390_initSRB( PSRB psrb )
1050: {
1051: #ifndef VERSION_ELF_1_2_13
1052: #ifdef DC390_DEBUG0
1053: printk("DC390 init: %08lx %08lx,",(ULONG)psrb,(ULONG)virt_to_bus(psrb));
1054: #endif
1055: psrb->PhysSRB = virt_to_bus( psrb );
1056: #else
1057: psrb->PhysSRB = (ULONG) psrb;
1058: #endif
1059: }
1060:
1061:
1062: void DC390_linkSRB( PACB pACB )
1063: {
1064: USHORT count, i;
1065: PSRB psrb;
1066:
1067: count = pACB->SRBCount;
1068:
1069: for( i=0; i< count; i++)
1070: {
1071: if( i != count - 1)
1072: pACB->SRB_array[i].pNextSRB = &pACB->SRB_array[i+1];
1073: else
1074: pACB->SRB_array[i].pNextSRB = NULL;
1075: psrb = (PSRB) &pACB->SRB_array[i];
1076: DC390_initSRB( psrb );
1077: }
1078: }
1079:
1080:
1081: /***********************************************************************
1082: * Function : static void DC390_initACB
1083: *
1084: * Purpose : initialize the internal structures for a given SCSI host
1085: *
1086: * Inputs : psh - pointer to this host adapter's structure
1087: *
1088: ***********************************************************************/
1089: void DC390_initACB( PSH psh, ULONG io_port, UCHAR Irq, USHORT index )
1090: {
1091: PACB pACB;
1092: USHORT i;
1093:
1094: psh->can_queue = MAX_CMD_QUEUE;
1095: psh->cmd_per_lun = MAX_CMD_PER_LUN;
1096: psh->this_id = (int) eepromBuf[index][EE_ADAPT_SCSI_ID];
1097: psh->io_port = io_port;
1098: psh->n_io_port = 0x80;
1099: psh->irq = Irq;
1100:
1101: pACB = (PACB) psh->hostdata;
1102:
1103: #ifndef VERSION_ELF_1_2_13
1104: psh->max_id = 8;
1105: #ifdef CONFIG_SCSI_MULTI_LUN
1106: if( eepromBuf[index][EE_MODE2] & LUN_CHECK )
1107: psh->max_lun = 8;
1108: else
1109: #endif
1110: psh->max_lun = 1;
1111: #endif
1112:
1113: pACB->max_id = 7;
1114: if( pACB->max_id == eepromBuf[index][EE_ADAPT_SCSI_ID] )
1115: pACB->max_id--;
1116: #ifdef CONFIG_SCSI_MULTI_LUN
1117: if( eepromBuf[index][EE_MODE2] & LUN_CHECK )
1118: pACB->max_lun = 7;
1119: else
1120: #endif
1121: pACB->max_lun = 0;
1122:
1123: pACB->pScsiHost = psh;
1124: pACB->IOPortBase = (USHORT) io_port;
1125: pACB->pLinkDCB = NULL;
1126: pACB->pDCBRunRobin = NULL;
1127: pACB->pActiveDCB = NULL;
1128: pACB->pFreeSRB = pACB->SRB_array;
1129: pACB->SRBCount = MAX_SRB_CNT;
1130: pACB->AdapterIndex = index;
1131: pACB->status = 0;
1132: pACB->AdaptSCSIID = eepromBuf[index][EE_ADAPT_SCSI_ID];
1133: pACB->HostID_Bit = (1 << pACB->AdaptSCSIID);
1134: pACB->AdaptSCSILUN = 0;
1135: pACB->DeviceCnt = 0;
1136: pACB->IRQLevel = Irq;
1137: pACB->TagMaxNum = eepromBuf[index][EE_TAG_CMD_NUM] << 2;
1138: pACB->ACBFlag = 0;
1139: pACB->scan_devices = 1;
1140: pACB->Gmode2 = eepromBuf[index][EE_MODE2];
1141: if( eepromBuf[index][EE_MODE2] & LUN_CHECK )
1142: pACB->LUNchk = 1;
1143: pACB->pDCB_free = &pACB->DCB_array[0];
1144: DC390_linkSRB( pACB );
1145: pACB->pTmpSRB = &pACB->TmpSRB;
1146: DC390_initSRB( pACB->pTmpSRB );
1147: for(i=0; i<MAX_SCSI_ID; i++)
1148: pACB->DCBmap[i] = 0;
1149: }
1150:
1151:
1152: /***********************************************************************
1153: * Function : static int DC390_initAdapter
1154: *
1155: * Purpose : initialize the SCSI chip ctrl registers
1156: *
1157: * Inputs : psh - pointer to this host adapter's structure
1158: *
1159: ***********************************************************************/
1160: int DC390_initAdapter( PSH psh, ULONG io_port, UCHAR Irq, USHORT index )
1161: {
1162: USHORT ioport;
1163: UCHAR bval;
1164: PACB pACB, pacb;
1165: USHORT used_irq = 0;
1166:
1167: pacb = pACB_start;
1168: if( pacb != NULL )
1169: {
1170: for ( ; (pacb != (PACB) -1) ; )
1171: {
1172: if( pacb->IRQLevel == Irq )
1173: {
1174: used_irq = 1;
1175: break;
1176: }
1177: else
1178: pacb = pacb->pNextACB;
1179: }
1180: }
1181:
1182: if( !used_irq )
1183: {
1184: #ifdef VERSION_ELF_1_2_13
1185: if( request_irq(Irq, DC390_Interrupt, SA_INTERRUPT, "tmscsim"))
1186: #else
1187: if( request_irq(Irq, DC390_Interrupt, SA_INTERRUPT | SA_SHIRQ, "tmscsim", NULL))
1188: #endif
1189: {
1190: printk("DC390: register IRQ error!\n");
1191: return( -1 );
1192: }
1193: }
1194:
1195: request_region(io_port,psh->n_io_port,"tmscsim");
1196:
1197: ioport = (USHORT) io_port;
1198:
1199: pACB = (PACB) psh->hostdata;
1200: bval = SEL_TIMEOUT; /* 250ms selection timeout */
1201: outb(bval,ioport+Scsi_TimeOut);
1202:
1203: bval = CLK_FREQ_40MHZ; /* Conversion factor = 0 , 40MHz clock */
1204: outb(bval,ioport+Clk_Factor);
1205:
1206: bval = NOP_CMD; /* NOP cmd - clear command register */
1207: outb(bval,ioport+ScsiCmd);
1208:
1209: bval = EN_FEATURE+EN_SCSI2_CMD; /* Enable Feature and SCSI-2 */
1210: outb(bval,ioport+CtrlReg2);
1211:
1212: bval = FAST_CLK; /* fast clock */
1213: outb(bval,ioport+CtrlReg3);
1214:
1215: bval = EATER_25NS;
1216: if( eepromBuf[index][EE_MODE2] & ACTIVE_NEGATION )
1217: bval |= NEGATE_REQACKDATA;
1218: outb(bval,ioport+CtrlReg4);
1219:
1220: bval = DIS_INT_ON_SCSI_RST; /* Disable SCSI bus reset interrupt */
1221: outb(bval,ioport+CtrlReg1);
1222:
1223: return(0);
1224: }
1225:
1226:
1227: void
1228: DC390_EnableCfg( USHORT mechnum, UCHAR regval )
1229: {
1230: ULONG wlval;
1231:
1232: if(mechnum == 2)
1233: {
1234: outb(mech2bus, PCI_CFG2_FORWARD_REG);
1235: outb(mech2CfgSPenR, PCI_CFG2_ENABLE_REG);
1236: }
1237: else
1238: {
1239: regval &= 0xFC;
1240: wlval = mech1addr;
1241: wlval |= (((ULONG)regval) & 0xff);
1242: outl(wlval, PCI_CFG1_ADDRESS_REG);
1243: }
1244: }
1245:
1246:
1247: void
1248: DC390_DisableCfg( USHORT mechnum )
1249: {
1250:
1251: if(mechnum == 2)
1252: outb(0, PCI_CFG2_ENABLE_REG);
1253: else
1254: outl(0, PCI_CFG1_ADDRESS_REG);
1255: }
1256:
1257:
1258: UCHAR
1259: DC390_inByte( USHORT mechnum, UCHAR regval )
1260: {
1261: UCHAR bval;
1262: ULONG wval;
1263: ULONG flags;
1264:
1265: save_flags(flags);
1266: cli();
1267: DC390_EnableCfg( mechnum, regval );
1268: if(mechnum == 2)
1269: {
1270: wval = mech2Agent;
1271: wval <<= 8;
1272: wval |= ((USHORT) regval) & 0xff;
1273: bval = inb(wval);
1274: }
1275: else
1276: {
1277: regval &= 3;
1278: bval = inb(PCI_CFG1_DATA_REG | regval);
1279: }
1280: DC390_DisableCfg(mechnum);
1281: restore_flags(flags);
1282: return(bval);
1283: }
1284:
1285:
1286: USHORT
1287: DC390_inWord( USHORT mechnum, UCHAR regval )
1288: {
1289: USHORT wval;
1290: ULONG flags;
1291:
1292: save_flags(flags);
1293: cli();
1294: DC390_EnableCfg(mechnum,regval);
1295: if(mechnum == 2)
1296: {
1297: wval = mech2Agent;
1298: wval <<= 8;
1299: wval |= regval;
1300: wval = inw(wval);
1301: }
1302: else
1303: {
1304: regval &= 3;
1305: wval = inw(PCI_CFG1_DATA_REG | regval);
1306: }
1307: DC390_DisableCfg(mechnum);
1308: restore_flags(flags);
1309: return(wval);
1310: }
1311:
1312:
1313: ULONG
1314: DC390_inDword(USHORT mechnum, UCHAR regval )
1315: {
1316: ULONG wlval;
1317: ULONG flags;
1318: USHORT wval;
1319:
1320: save_flags(flags);
1321: cli();
1322: DC390_EnableCfg(mechnum,regval);
1323: if(mechnum == 2)
1324: {
1325: wval = mech2Agent;
1326: wval <<= 8;
1327: wval |= regval;
1328: wlval = inl(wval);
1329: }
1330: else
1331: {
1332: wlval = inl(PCI_CFG1_DATA_REG);
1333: }
1334: DC390_DisableCfg(mechnum);
1335: restore_flags(flags);
1336: return(wlval);
1337: }
1338:
1339:
1340: void
1341: DC390_OutB(USHORT mechnum, UCHAR regval, UCHAR bval )
1342: {
1343:
1344: USHORT wval;
1345: ULONG flags;
1346:
1347: save_flags(flags);
1348: cli();
1349: DC390_EnableCfg(mechnum,regval);
1350: if(mechnum == 2)
1351: {
1352: wval = mech2Agent;
1353: wval <<= 8;
1354: wval |= regval;
1355: outb(bval, wval);
1356: }
1357: else
1358: {
1359: regval &= 3;
1360: outb(bval, PCI_CFG1_DATA_REG | regval);
1361: }
1362: DC390_DisableCfg(mechnum);
1363: restore_flags(flags);
1364: }
1365:
1366:
1367: void
1368: DC390_EnDisableCE( UCHAR mode, USHORT mechnum, PUCHAR regval )
1369: {
1370:
1371: UCHAR bval;
1372:
1373: bval = 0;
1374: if(mode == ENABLE_CE)
1375: *regval = 0xc0;
1376: else
1377: *regval = 0x80;
1378: DC390_OutB(mechnum,*regval,bval);
1379: if(mode == DISABLE_CE)
1380: DC390_OutB(mechnum,*regval,bval);
1381: udelay(160);
1382: }
1383:
1384:
1385: void
1386: DC390_EEpromOutDI( USHORT mechnum, PUCHAR regval, USHORT Carry )
1387: {
1388: UCHAR bval;
1389:
1390: bval = 0;
1391: if(Carry)
1392: {
1393: bval = 0x40;
1394: *regval = 0x80;
1395: DC390_OutB(mechnum,*regval,bval);
1396: }
1397: udelay(160);
1398: bval |= 0x80;
1399: DC390_OutB(mechnum,*regval,bval);
1400: udelay(160);
1401: bval = 0;
1402: DC390_OutB(mechnum,*regval,bval);
1403: udelay(160);
1404: }
1405:
1406:
1407: UCHAR
1408: DC390_EEpromInDO( USHORT mechnum )
1409: {
1410: UCHAR bval,regval;
1411:
1412: regval = 0x80;
1413: bval = 0x80;
1414: DC390_OutB(mechnum,regval,bval);
1415: udelay(160);
1416: bval = 0x40;
1417: DC390_OutB(mechnum,regval,bval);
1418: udelay(160);
1419: regval = 0x0;
1420: bval = DC390_inByte(mechnum,regval);
1421: if(bval == 0x22)
1422: return(1);
1423: else
1424: return(0);
1425: }
1426:
1427:
1428: USHORT
1429: EEpromGetData1( USHORT mechnum )
1430: {
1431: UCHAR i;
1432: UCHAR carryFlag;
1433: USHORT wval;
1434:
1435: wval = 0;
1436: for(i=0; i<16; i++)
1437: {
1438: wval <<= 1;
1439: carryFlag = DC390_EEpromInDO(mechnum);
1440: wval |= carryFlag;
1441: }
1442: return(wval);
1443: }
1444:
1445:
1446: void
1447: DC390_Prepare( USHORT mechnum, PUCHAR regval, UCHAR EEpromCmd )
1448: {
1449: UCHAR i,j;
1450: USHORT carryFlag;
1451:
1452: carryFlag = 1;
1453: j = 0x80;
1454: for(i=0; i<9; i++)
1455: {
1456: DC390_EEpromOutDI(mechnum,regval,carryFlag);
1457: carryFlag = (EEpromCmd & j) ? 1 : 0;
1458: j >>= 1;
1459: }
1460: }
1461:
1462:
1463: void
1464: DC390_ReadEEprom( USHORT mechnum, USHORT index )
1465: {
1466: UCHAR regval,cmd;
1467: PUSHORT ptr;
1468: USHORT i;
1469:
1470: ptr = (PUSHORT) &eepromBuf[index][0];
1471: cmd = EEPROM_READ;
1472: for(i=0; i<0x40; i++)
1473: {
1474: DC390_EnDisableCE(ENABLE_CE, mechnum, ®val);
1475: DC390_Prepare(mechnum, ®val, cmd);
1476: *ptr = EEpromGetData1(mechnum);
1477: ptr++;
1478: cmd++;
1479: DC390_EnDisableCE(DISABLE_CE,mechnum,®val);
1480: }
1481: }
1482:
1483:
1484: USHORT
1485: DC390_CheckEEpromCheckSum( USHORT MechNum, USHORT index )
1486: {
1487: USHORT wval, rc, *ptr;
1488: UCHAR i;
1489:
1490: DC390_ReadEEprom( MechNum, index );
1491: wval = 0;
1492: ptr = (PUSHORT) &eepromBuf[index][0];
1493: for(i=0; i<128 ;i+=2, ptr++)
1494: wval += *ptr;
1495: if( wval == 0x1234 )
1496: rc = 0;
1497: else
1498: rc = -1;
1499: return( rc );
1500: }
1501:
1502:
1503: USHORT
1504: DC390_ToMech( USHORT Mechnum, USHORT BusDevFunNum )
1505: {
1506: USHORT devnum;
1507:
1508: devnum = BusDevFunNum;
1509:
1510: if(Mechnum == 2)
1511: {
1512: if(devnum & 0x80)
1513: return(-1);
1514: mech2bus = (UCHAR)((devnum & 0xff00) >> 8); /* Bus num */
1515: mech2Agent = ((UCHAR)(devnum & 0xff)) >> 3; /* Dev num */
1516: mech2Agent |= 0xc0;
1517: mech2CfgSPenR = ((UCHAR)(devnum & 0xff)) & 0x07; /* Fun num */
1518: mech2CfgSPenR = (mech2CfgSPenR << 1) | 0x20;
1519: }
1520: else /* use mech #1 method */
1521: {
1522: mech1addr = 0x80000000 | ((ULONG)devnum << 8);
1523: }
1524: return(0);
1525: }
1526:
1527: /***********************************************************************
1528: * Function : static int DC390_init (struct Scsi_Host *host)
1529: *
1530: * Purpose : initialize the internal structures for a given SCSI host
1531: *
1532: * Inputs : host - pointer to this host adapter's structure/
1533: *
1534: * Preconditions : when this function is called, the chip_type
1535: * field of the pACB structure MUST have been set.
1536: ***********************************************************************/
1537:
1538: static int
1539: DC390_init (PSHT psht, ULONG io_port, UCHAR Irq, USHORT index, USHORT MechNum)
1540: {
1541: PSH psh;
1542: PACB pACB;
1543:
1544: if( !DC390_CheckEEpromCheckSum( MechNum, index) )
1545: {
1546: psh = scsi_register( psht, sizeof(DC390_ACB) );
1547: if( !psh )
1548: return( -1 );
1549: if( !pSH_start )
1550: {
1551: pSH_start = psh;
1552: pSH_current = psh;
1553: }
1554: else
1555: {
1556: pSH_current->next = psh;
1557: pSH_current = psh;
1558: }
1559:
1560: #ifdef DC390_DEBUG0
1561: printk("DC390: pSH = %8x,", (UINT) psh);
1562: printk("DC390: Index %02i,", index);
1563: #endif
1564:
1565: DC390_initACB( psh, io_port, Irq, index );
1566: if( !DC390_initAdapter( psh, io_port, Irq, index ) )
1567: {
1568: pACB = (PACB) psh->hostdata;
1569: if( !pACB_start )
1570: {
1571: pACB_start = pACB;
1572: pACB_current = pACB;
1573: pACB->pNextACB = (PACB) -1;
1574: }
1575: else
1576: {
1577: pACB_current->pNextACB = pACB;
1578: pACB_current = pACB;
1579: pACB->pNextACB = (PACB) -1;
1580: }
1581:
1582: #ifdef DC390_DEBUG0
1583: printk("DC390: pACB = %8x, pDCB_array = %8x, pSRB_array = %8x\n",
1584: (UINT) pACB, (UINT) pACB->DCB_array, (UINT) pACB->SRB_array);
1585: printk("DC390: ACB size= %4x, DCB size= %4x, SRB size= %4x\n",
1586: sizeof(DC390_ACB), sizeof(DC390_DCB), sizeof(DC390_SRB) );
1587: #endif
1588:
1589: }
1590: else
1591: {
1592: pSH_start = NULL;
1593: scsi_unregister( psh );
1594: return( -1 );
1595: }
1596: return( 0 );
1597: }
1598: else
1599: {
1600: printk("DC390_init: EEPROM reading error!\n");
1601: return( -1 );
1602: }
1603: }
1604:
1605:
1606: /***********************************************************************
1607: * Function : int DC390_detect(Scsi_Host_Template *psht)
1608: *
1609: * Purpose : detects and initializes AMD53C974 SCSI chips
1610: * that were autoprobed, overridden on the LILO command line,
1611: * or specified at compile time.
1612: *
1613: * Inputs : psht - template for this SCSI adapter
1614: *
1615: * Returns : number of host adapters detected
1616: *
1617: ***********************************************************************/
1618:
1619: int
1620: DC390_detect(Scsi_Host_Template *psht)
1621: {
1622: #ifdef FOR_PCI_OK
1623: UCHAR pci_bus, pci_device_fn;
1624: int error = 0;
1625: USHORT chipType = 0;
1626: USHORT i;
1627: #endif
1628:
1629: UCHAR irq;
1630: UCHAR istatus;
1631: #ifndef VERSION_ELF_1_2_13
1632: UINT io_port;
1633: #else
1634: ULONG io_port;
1635: #endif
1636: USHORT adaptCnt = 0; /* Number of boards detected */
1637: USHORT pci_index = 0; /* Device index to PCI BIOS calls */
1638: USHORT MechNum, BusDevFunNum;
1639: ULONG wlval;
1640:
1641: #ifndef VERSION_ELF_1_2_13
1642: psht->proc_dir = &proc_scsi_tmscsim;
1643: #endif
1644:
1645: InitialTime = 1;
1646: pSHT_start = psht;
1647: pACB_start = NULL;
1648:
1649: MechNum = 1;
1650: for( ; (MechNum < 3) && (!adaptCnt); MechNum++)
1651: {
1652: BusDevFunNum = 0;
1653: for (; adaptCnt < MAX_ADAPTER_NUM ;)
1654: {
1655: if( !DC390_ToMech( MechNum, BusDevFunNum) )
1656: {
1657: wlval = DC390_inDword( MechNum, PCI_VENDOR_ID);
1658: if(wlval == ( (PCI_DEVICE_ID_AMD53C974 << 16)+
1659: PCI_VENDOR_ID_AMD) )
1660: {
1661: io_port =DC390_inDword(MechNum,PCI_BASE_ADDRESS_0) & 0xFFFE;
1662: irq = DC390_inByte( MechNum, PCI_INTERRUPT_LINE);
1663: #ifdef DC390_DEBUG0
1664: printk("DC390: IO_PORT=%4x,IRQ=%x,\n",(UINT) io_port, irq);
1665: #endif
1666: if( !DC390_init(psht, io_port, irq, pci_index, MechNum) )
1667: {
1668: adaptCnt++;
1669: pci_index++;
1670: istatus = inb( (USHORT)io_port+INT_Status ); /* Reset Pending INT */
1671: #ifdef DC390_DEBUG0
1672: printk("DC390: Mech=%2x,\n",(UCHAR) MechNum);
1673: #endif
1674: }
1675: }
1676: }
1677: if( BusDevFunNum != 0xfff8 )
1678: BusDevFunNum += 8; /* next device # */
1679: else
1680: break;
1681: }
1682: }
1683:
1684: #ifdef FOR_PCI_OK
1685: if ( pcibios_present() )
1686: {
1687: for (i = 0; i < MAX_ADAPTER_NUM; ++i)
1688: {
1689: if( !pcibios_find_device( PCI_VENDOR_ID_AMD,
1690: PCI_DEVICE_ID_AMD53C974,
1691: pci_index, &pci_bus, &pci_device_fn) )
1692: {
1693: chipType = PCI_DEVICE_ID_AMD53C974;
1694: pci_index++;
1695: }
1696:
1697: if( chipType )
1698: {
1699:
1700: error = pcibios_read_config_dword(pci_bus, pci_device_fn,
1701: PCI_BASE_ADDRESS_0, &io_port);
1702: error |= pcibios_read_config_byte(pci_bus, pci_device_fn,
1703: PCI_INTERRUPT_LINE, &irq);
1704: if( error )
1705: {
1706: printk("DC390_detect: reading configuration registers error!\n");
1707: InitialTime = 0;
1708: return( 0 );
1709: }
1710:
1711: (USHORT) io_port = (USHORT) io_port & 0xFFFE;
1712: #ifdef DC390_DEBUG0
1713: printk("DC390: IO_PORT=%4x,IRQ=%x,\n",(UINT) io_port, irq);
1714: #endif
1715: if( !DC390_init(psht, io_port, irq, i) )
1716: adaptCnt++;
1717: chipType = 0;
1718: }
1719: else
1720: break;
1721: }
1722: }
1723: #endif
1724:
1725: InitialTime = 0;
1726: adapterCnt = adaptCnt;
1727: return( adaptCnt );
1728: }
1729:
1730:
1731: #ifndef VERSION_ELF_1_2_13
1732:
1733: /********************************************************************
1734: * Function: tmscsim_set_info()
1735: *
1736: * Purpose: Set adapter info (!)
1737: *
1738: * Not yet implemented
1739: *
1740: *******************************************************************/
1741:
1742: int tmscsim_set_info(char *buffer, int length, struct Scsi_Host *shpnt)
1743: {
1744: return(-ENOSYS); /* Currently this is a no-op */
1745: }
1746:
1747: /********************************************************************
1748: * Function: tmscsim_proc_info(char* buffer, char **start,
1749: * off_t offset, int length, int hostno, int inout)
1750: *
1751: * Purpose: return SCSI Adapter/Device Info
1752: *
1753: * Input: buffer: Pointer to a buffer where to write info
1754: * start :
1755: * offset:
1756: * hostno: Host adapter index
1757: * inout : Read (=0) or set(!=0) info
1758: *
1759: * Output: buffer: contains info
1760: * length; length of info in buffer
1761: *
1762: * return value: length
1763: *
1764: ********************************************************************/
1765:
1766: /* KG: proc_info taken from driver aha152x.c */
1767:
1768: #undef SPRINTF
1769: #define SPRINTF(args...) pos += sprintf(pos, ## args)
1770:
1771: #define YESNO(YN)\
1772: if (YN) SPRINTF(" Yes ");\
1773: else SPRINTF(" No ")
1774:
1775: int tmscsim_proc_info(char *buffer, char **start,
1776: off_t offset, int length, int hostno, int inout)
1777: {
1778: int dev, spd, spd1;
1779: char *pos = buffer;
1780: PSH shpnt;
1781: PACB acbpnt;
1782: PDCB dcbpnt;
1783: unsigned long flags;
1784: /* Scsi_Cmnd *ptr; */
1785:
1786: acbpnt = pACB_start;
1787:
1788: while(acbpnt != (PACB)-1)
1789: {
1790: shpnt = acbpnt->pScsiHost;
1791: if (shpnt->host_no == hostno) break;
1792: acbpnt = acbpnt->pNextACB;
1793: }
1794:
1795: if (acbpnt == (PACB)-1) return(-ESRCH);
1796: if(!shpnt) return(-ESRCH);
1797:
1798: if(inout) /* Has data been written to the file ? */
1799: return(tmscsim_set_info(buffer, length, shpnt));
1800:
1801: SPRINTF("Tekram DC390(T) PCI SCSI Host Adadpter, ");
1802: SPRINTF("Driver Version 1.10, 1996/12/05\n");
1803:
1804: save_flags(flags);
1805: cli();
1806:
1807: SPRINTF("SCSI Host Nr %i, ", shpnt->host_no);
1808: SPRINTF("DC390 Adapter Nr %i\n", acbpnt->AdapterIndex);
1809: SPRINTF("IOPortBase 0x%04x, ", acbpnt->IOPortBase);
1810: SPRINTF("IRQLevel 0x%02x\n", acbpnt->IRQLevel);
1811:
1812: SPRINTF("MaxID %i, MaxLUN %i, ",acbpnt->max_id, acbpnt->max_lun);
1813: SPRINTF("AdapterID %i, AdapterLUN %i\n", acbpnt->AdaptSCSIID, acbpnt->AdaptSCSILUN);
1814:
1815: SPRINTF("TagMaxNum %i, Status %i\n", acbpnt->TagMaxNum, acbpnt->status);
1816:
1817: SPRINTF("Nr of attached devices: %i\n", acbpnt->DeviceCnt);
1818:
1819: SPRINTF("Un ID LUN Prty Sync DsCn SndS TagQ NegoPeriod SyncSpeed SyncOffs\n");
1820:
1821: dcbpnt = acbpnt->pLinkDCB;
1822: for (dev = 0; dev < acbpnt->DeviceCnt; dev++)
1823: {
1824: SPRINTF("%02i %02i %02i ", dev, dcbpnt->UnitSCSIID, dcbpnt->UnitSCSILUN);
1825: YESNO(dcbpnt->DevMode & PARITY_CHK_);
1826: YESNO(dcbpnt->SyncMode & SYNC_NEGO_DONE);
1827: YESNO(dcbpnt->DevMode & EN_DISCONNECT_);
1828: YESNO(dcbpnt->DevMode & SEND_START_);
1829: YESNO(dcbpnt->SyncMode & EN_TAG_QUEUING);
1830: SPRINTF(" %03i ns ", (dcbpnt->NegoPeriod) << 2);
1831: if (dcbpnt->SyncOffset & 0x0f)
1832: {
1833: spd = 1000/(dcbpnt->NegoPeriod <<2);
1834: spd1 = 1000%(dcbpnt->NegoPeriod <<2);
1835: spd1 = (spd1 * 10)/(dcbpnt->NegoPeriod <<2);
1836: SPRINTF(" %2i.%1i M %02i\n", spd, spd1, (dcbpnt->SyncOffset & 0x0f));
1837: }
1838: else SPRINTF("\n");
1839: /* Add more info ...*/
1840: dcbpnt = dcbpnt->pNextDCB;
1841: }
1842:
1843: restore_flags(flags);
1844: *start = buffer + offset;
1845:
1846: if (pos - buffer < offset)
1847: return 0;
1848: else if (pos - buffer - offset < length)
1849: return pos - buffer - offset;
1850: else
1851: return length;
1852: }
1853: #endif /* VERSION_ELF_1_2_13 */
1854:
1855:
1856: #ifdef MODULE
1857:
1858: /***********************************************************************
1859: * Function : static int DC390_shutdown (struct Scsi_Host *host)
1860: *
1861: * Purpose : does a clean (we hope) shutdown of the SCSI chip.
1862: * Use prior to dumping core, unloading the driver, etc.
1863: *
1864: * Returns : 0 on success
1865: ***********************************************************************/
1866: static int
1867: DC390_shutdown (struct Scsi_Host *host)
1868: {
1869: UCHAR bval;
1870: USHORT ioport;
1871: unsigned long flags;
1872: PACB pACB = (PACB)(host->hostdata);
1873:
1874: ioport = (unsigned int) pACB->IOPortBase;
1875:
1876: save_flags (flags);
1877: cli();
1878:
1879: /* pACB->soft_reset(host); */
1880:
1881: #ifdef DC390_DEBUG0
1882: printk("DC390: shutdown,");
1883: #endif
1884:
1885: bval = inb(ioport+CtrlReg1);
1886: bval |= DIS_INT_ON_SCSI_RST;
1887: outb(bval,ioport+CtrlReg1); /* disable interrupt */
1888: DC390_ResetSCSIBus( pACB );
1889:
1890: restore_flags (flags);
1891: return( 0 );
1892: }
1893:
1894:
1895: int DC390_release(struct Scsi_Host *host)
1896: {
1897: int irq_count;
1898: struct Scsi_Host *tmp;
1899:
1900: DC390_shutdown (host);
1901:
1902: if (host->irq != IRQ_NONE)
1903: {
1904: for (irq_count = 0, tmp = pSH_start; tmp; tmp = tmp->next)
1905: {
1906: if ( tmp->irq == host->irq )
1907: ++irq_count;
1908: }
1909: if (irq_count == 1)
1910: {
1911: #ifdef DC390_DEBUG0
1912: printk("DC390: Free IRQ %i.",host->irq);
1913: #endif
1914: #ifndef VERSION_ELF_1_2_13
1915: free_irq(host->irq,NULL);
1916: #else
1917: free_irq(host->irq);
1918: #endif
1919: }
1920: }
1921:
1922: release_region(host->io_port,host->n_io_port);
1923:
1924: return( 1 );
1925: }
1926:
1927: Scsi_Host_Template driver_template = DC390_T;
1928: #include "scsi_module.c"
1929: #endif /* def MODULE */
1930:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.