FreeBSD/Linux Kernel Cross Reference
sys/pci/tek390.c
1 /***********************************************************************
2 * FILE NAME : TEK390.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 * (C)Copyright 1995-1996 Tekram Technology Co., Ltd. *
7 ***********************************************************************/
8 /***********************************************************************
9 * HISTORY: *
10 * *
11 * REV# DATE NAME DESCRIPTION *
12 * 1.00 07/02/96 CLH First release for RELEASE-2.1.0 *
13 * 1.01 08/20/96 CLH Update for RELEASE-2.1.5 *
14 * *
15 ***********************************************************************/
16
17 /**************************************************************************
18 *
19 *
20 * Redistribution and use in source and binary forms, with or without
21 * modification, are permitted provided that the following conditions
22 * are met:
23 * 1. Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer.
25 * 2. Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in the
27 * documentation and/or other materials provided with the distribution.
28 * 3. The name of the author may not be used to endorse or promote products
29 * derived from this software without specific prior written permission.
30 *
31 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
32 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
33 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
34 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
35 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
40 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 *
42 **************************************************************************/
43
44 /**************************************************************************/
45 /* Imported into FreeBSD source repository, and updated to compile under */
46 /* FreeBSD-3.0-DEVELOPMENT, by Stefan Esser <se@FreeBSD.Org>, 1996-12-17 */
47 /**************************************************************************/
48
49 /* #define REL_2_1_0 */
50 #define REL_2_1_5
51
52 #define DC390_DEBUG
53
54 #include <sys/param.h>
55
56 /* XXX this doesn't actually compile unless KERNEL is defined. */
57 #ifdef KERNEL
58 #include <sys/systm.h>
59 #include <sys/malloc.h>
60 #include <sys/buf.h>
61 #include <sys/kernel.h>
62
63 #include <vm/vm.h>
64 #include <vm/pmap.h>
65 #endif /* KERNEL */
66
67 #include <pci/pcivar.h>
68 #include <pci/pcireg.h>
69
70 #include <scsi/scsiconf.h>
71
72 #include <machine/clock.h>
73
74 #include <pci/tek390.h>
75
76 #define INT32 int32
77 #define U_INT32 u_int32
78
79
80 #define OutB(val, port) outb(port, val)
81 #define OutW(val, port) outw(port, val)
82 #define OutL(val, port) outl(port, val)
83
84 #define PCI_DEVICE_ID_AMD53C974 0x20201022ul
85 #define PCI_BASE_ADDR0 0x10
86
87
88 #ifdef REL_2_1_0
89 static int DC390_Interrupt (PACB pACB);
90 #endif
91 #ifdef REL_2_1_5
92 static void DC390_Interrupt (PACB pACB);
93 #endif
94 static USHORT DC390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB );
95 static void DC390_DataOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
96 static void DC390_DataIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
97 static void DC390_Command_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
98 static void DC390_Status_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
99 static void DC390_MsgOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
100 static void DC390_MsgIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
101 static void DC390_DataOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
102 static void DC390_DataInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
103 static void DC390_CommandPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
104 static void DC390_StatusPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
105 static void DC390_MsgOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
106 static void DC390_MsgInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);
107 static void DC390_Nop_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);
108 static void DC390_Nop_1( PACB pACB, PSRB pSRB, PUCHAR psstatus);
109
110 static void SetXferRate( PACB pACB, PDCB pDCB );
111 static void DC390_Disconnect( PACB pACB );
112 static void DC390_Reselect( PACB pACB );
113 static void SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB );
114 static void DoingSRB_Done( PACB pACB );
115 static void DC390_ScsiRstDetect( PACB pACB );
116 static void DC390_ResetSCSIBus( PACB pACB );
117 static void RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB );
118 static void EnableMsgOut2( PACB pACB, PSRB pSRB );
119 static void EnableMsgOut( PACB pACB, PSRB pSRB );
120 static void DC390_InvalidCmd( PACB pACB );
121
122 static void DC390_timeout( void *arg1);
123 static void DC390_reset (PACB pACB);
124 static PUCHAR phystovirt( PSRB pSRB, ULONG xferCnt );
125
126 void DC390_initDCB( PACB pACB, PDCB pDCB, PSCSICMD cmd );
127 void DC390_initSRB( PSRB psrb );
128 void DC390_linkSRB( PACB pACB );
129 void DC390_initACB( PACB pACB, ULONG io_port, UCHAR Irq, USHORT index );
130 int DC390_initAdapter( PACB pACB, ULONG io_port, UCHAR Irq, USHORT index,
131 pcici_t config_id );
132 void DC390_EnableCfg( USHORT mechnum, UCHAR regval );
133 void DC390_DisableCfg( USHORT mechnum );
134 UCHAR DC390_inByte( USHORT mechnum, UCHAR regval );
135 USHORT DC390_inWord( USHORT mechnum, UCHAR regval );
136 ULONG DC390_inDword(USHORT mechnum, UCHAR regval );
137 void DC390_OutB(USHORT mechnum, UCHAR regval, UCHAR bval );
138 void DC390_EnDisableCE( UCHAR mode, USHORT mechnum, PUCHAR regval );
139 void DC390_EEpromOutDI( USHORT mechnum, PUCHAR regval, USHORT Carry );
140 UCHAR DC390_EEpromInDO( USHORT mechnum );
141 USHORT EEpromGetData1( USHORT mechnum );
142 void DC390_Prepare( USHORT mechnum, PUCHAR regval, UCHAR EEpromCmd );
143 void DC390_ReadEEprom( USHORT mechnum, USHORT index );
144 USHORT DC390_DefaultEEprom( USHORT mechnum, USHORT index );
145 USHORT DC390_CheckEEpromCheckSum( USHORT MechNum, USHORT index );
146 USHORT DC390_ToMech( USHORT Mechnum, pcici_t config_id );
147
148
149 #ifdef KERNEL
150
151 static char* trmamd_probe( pcici_t tag, pcidi_t type);
152 static void trmamd_attach( pcici_t tag, int unit);
153
154 #ifdef REL_2_1_0
155 static int32 trmamd_scsi_cmd( struct scsi_xfer *sx);
156 #endif
157
158 #ifdef REL_2_1_5
159 static int32_t trmamd_scsi_cmd( struct scsi_xfer *sx);
160 #endif
161
162 static void trmamd_min_phys( struct buf *pbuf);
163
164 #ifdef REL_2_1_0
165 static u_int32 trmamd_info( int unit );
166 #endif
167
168 #endif /* KERNEL */
169
170
171 static u_long trmamd_count;
172
173 struct pci_device trmamd_device = {
174 "amd",
175 trmamd_probe,
176 trmamd_attach,
177 &trmamd_count,
178 NULL
179 };
180
181 DATA_SET (pcidevice_set, trmamd_device);
182
183
184
185 struct scsi_adapter trmamd_switch =
186 {
187 trmamd_scsi_cmd,
188 trmamd_min_phys,
189 0,
190 0,
191 #ifdef REL_2_1_0
192 trmamd_info,
193 #endif
194 #ifdef REL_2_1_5
195 0,
196 #endif
197 "amd",
198 };
199
200 struct scsi_device trmamd_dev =
201 {
202 NULL, /* Use default error handler */
203 NULL, /* have a queue, served by this */
204 NULL, /* have no async handler */
205 NULL, /* Use default 'done' routine */
206 "amd",
207 };
208
209
210 static PACB pACB0[MAX_ADAPTER_NUM]={0};
211 static PACB pACB_start= NULL;
212 static PACB pACB_current = NULL;
213 static PDCB pPrevDCB = NULL;
214 static USHORT adapterCnt = 0;
215 static USHORT CurrSyncOffset = 0;
216 static USHORT mech2Agent;
217 static ULONG mech1addr;
218 static UCHAR mech2bus, mech2CfgSPenR, CurrentID, CurrentLUN;
219
220 static PVOID DC390_phase0[]={
221 DC390_DataOut_0,
222 DC390_DataIn_0,
223 DC390_Command_0,
224 DC390_Status_0,
225 DC390_Nop_0,
226 DC390_Nop_0,
227 DC390_MsgOut_0,
228 DC390_MsgIn_0,
229 DC390_Nop_1
230 };
231
232 static PVOID DC390_phase1[]={
233 DC390_DataOutPhase,
234 DC390_DataInPhase,
235 DC390_CommandPhase,
236 DC390_StatusPhase,
237 DC390_Nop_0,
238 DC390_Nop_0,
239 DC390_MsgOutPhase,
240 DC390_MsgInPhase,
241 DC390_Nop_1,
242 };
243
244 UCHAR eepromBuf[MAX_ADAPTER_NUM][128];
245
246
247 UCHAR clock_period1[] = {4, 5, 6, 7 ,8, 10, 13, 20};
248
249 UCHAR baddevname1[2][28] ={
250 "SEAGATE ST3390N ??? 9546",
251 "HP C3323-300 4269"};
252
253 #define BADDEVCNT 2
254
255
256 /***********************************************************************
257 *
258 *
259 *
260 **********************************************************************/
261 static PSRB
262 GetSRB( PACB pACB )
263 {
264 int flags;
265 PSRB pSRB;
266
267 flags = splbio();
268
269 pSRB = pACB->pFreeSRB;
270 if( pSRB )
271 {
272 pACB->pFreeSRB = pSRB->pNextSRB;
273 pSRB->pNextSRB = NULL;
274 }
275 splx(flags);
276 return( pSRB );
277 }
278
279
280 static void
281 RewaitSRB0( PDCB pDCB, PSRB pSRB )
282 {
283 PSRB psrb1;
284 int flags;
285
286 flags = splbio();
287
288 if( (psrb1 = pDCB->pWaitingSRB) )
289 {
290 pSRB->pNextSRB = psrb1;
291 pDCB->pWaitingSRB = pSRB;
292 }
293 else
294 {
295 pSRB->pNextSRB = NULL;
296 pDCB->pWaitingSRB = pSRB;
297 pDCB->pWaitLast = pSRB;
298 }
299 splx(flags);
300 }
301
302
303 static void
304 RewaitSRB( PDCB pDCB, PSRB pSRB )
305 {
306 PSRB psrb1;
307 int flags;
308 UCHAR bval;
309
310 flags = splbio();
311
312 pDCB->GoingSRBCnt--;
313 psrb1 = pDCB->pGoingSRB;
314 if( pSRB == psrb1 )
315 {
316 pDCB->pGoingSRB = psrb1->pNextSRB;
317 }
318 else
319 {
320 while( pSRB != psrb1->pNextSRB )
321 psrb1 = psrb1->pNextSRB;
322 psrb1->pNextSRB = pSRB->pNextSRB;
323 if( pSRB == pDCB->pGoingLast )
324 pDCB->pGoingLast = psrb1;
325 }
326 if( (psrb1 = pDCB->pWaitingSRB) )
327 {
328 pSRB->pNextSRB = psrb1;
329 pDCB->pWaitingSRB = pSRB;
330 }
331 else
332 {
333 pSRB->pNextSRB = NULL;
334 pDCB->pWaitingSRB = pSRB;
335 pDCB->pWaitLast = pSRB;
336 }
337
338 bval = pSRB->TagNumber;
339 pDCB->TagMask &= (~(1 << bval)); /* Free TAG number */
340 splx(flags);
341 }
342
343
344 static void
345 DoWaitingSRB( PACB pACB )
346 {
347 int flags;
348 PDCB ptr, ptr1;
349 PSRB pSRB;
350
351 flags = splbio();
352
353 if( !(pACB->pActiveDCB) && !(pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) ) )
354 {
355 ptr = pACB->pDCBRunRobin;
356 if( !ptr )
357 {
358 ptr = pACB->pLinkDCB;
359 pACB->pDCBRunRobin = ptr;
360 }
361 ptr1 = ptr;
362 for( ;ptr1; )
363 {
364 pACB->pDCBRunRobin = ptr1->pNextDCB;
365 if( !( ptr1->MaxCommand > ptr1->GoingSRBCnt ) ||
366 !( pSRB = ptr1->pWaitingSRB ) )
367 {
368 if(pACB->pDCBRunRobin == ptr)
369 break;
370 ptr1 = ptr1->pNextDCB;
371 }
372 else
373 {
374 if( !DC390_StartSCSI(pACB, ptr1, pSRB) )
375 {
376 ptr1->GoingSRBCnt++;
377 if( ptr1->pWaitLast == pSRB )
378 {
379 ptr1->pWaitingSRB = NULL;
380 ptr1->pWaitLast = NULL;
381 }
382 else
383 {
384 ptr1->pWaitingSRB = pSRB->pNextSRB;
385 }
386 pSRB->pNextSRB = NULL;
387
388 if( ptr1->pGoingSRB )
389 ptr1->pGoingLast->pNextSRB = pSRB;
390 else
391 ptr1->pGoingSRB = pSRB;
392 ptr1->pGoingLast = pSRB;
393 }
394 break;
395 }
396 }
397 }
398 splx(flags);
399 return;
400 }
401
402
403 static void
404 SRBwaiting( PDCB pDCB, PSRB pSRB)
405 {
406 if( pDCB->pWaitingSRB )
407 {
408 pDCB->pWaitLast->pNextSRB = pSRB;
409 pDCB->pWaitLast = pSRB;
410 pSRB->pNextSRB = NULL;
411 }
412 else
413 {
414 pDCB->pWaitingSRB = pSRB;
415 pDCB->pWaitLast = pSRB;
416 }
417 }
418
419
420 static void
421 SendSRB( PSCSICMD pcmd, PACB pACB, PSRB pSRB )
422 {
423 int flags;
424 PDCB pDCB;
425
426 flags = splbio();
427
428 pDCB = pSRB->pSRBDCB;
429 if( !(pDCB->MaxCommand > pDCB->GoingSRBCnt) || (pACB->pActiveDCB) ||
430 (pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV)) )
431 {
432 SRBwaiting(pDCB, pSRB);
433 goto SND_EXIT;
434 }
435
436 if( pDCB->pWaitingSRB )
437 {
438 SRBwaiting(pDCB, pSRB);
439 /* pSRB = GetWaitingSRB(pDCB); */
440 pSRB = pDCB->pWaitingSRB;
441 pDCB->pWaitingSRB = pSRB->pNextSRB;
442 pSRB->pNextSRB = NULL;
443 }
444
445 if( !DC390_StartSCSI(pACB, pDCB, pSRB) )
446 {
447 pDCB->GoingSRBCnt++;
448 if( pDCB->pGoingSRB )
449 {
450 pDCB->pGoingLast->pNextSRB = pSRB;
451 pDCB->pGoingLast = pSRB;
452 }
453 else
454 {
455 pDCB->pGoingSRB = pSRB;
456 pDCB->pGoingLast = pSRB;
457 }
458 }
459 else
460 RewaitSRB0( pDCB, pSRB );
461
462 SND_EXIT:
463 splx(flags);
464 return;
465 }
466
467
468 /***********************************************************************
469 * Function : static int32 dc390_scsi_cmd (struct scsi_xfer *cmd)
470 * Purpose : enqueues a SCSI command
471 ***********************************************************************/
472
473 #ifdef REL_2_1_0
474 int32
475 #endif
476 #ifdef REL_2_1_5
477 int32_t
478 #endif
479 trmamd_scsi_cmd ( PSCSICMD cmd )
480 {
481 USHORT ioport, i;
482 PSCSICMD pcmd;
483 PSCLINK plink;
484 PACB pACB;
485 PDCB pDCB;
486 PSRB pSRB;
487 int flags, cflags, unit, CurrPgVaddr;
488 ULONG sglen, pglen, datalen, CurrPgPaddr, NextPgPaddr;
489 PUCHAR ptr,ptr1;
490 PSEG psg;
491 UCHAR sgc, sstatus;
492
493 plink = cmd->sc_link;
494 unit = plink->adapter_unit;
495 pACB = pACB0[unit];
496 ioport = pACB->IOPortBase;
497
498 #ifdef DC390_DEBUG0
499 printf("Cmd=%2x,ID=%d,LUN=%d,",cmd->cmd->opcode,
500 plink->target, plink->lun);
501 #endif
502
503 if( pACB->scan_devices )
504 {
505 if( (plink->target > CurrentID) ||
506 (plink->target == CurrentID) && (plink->lun >= CurrentLUN) )
507 {
508 CurrentID = plink->target;
509 CurrentLUN = plink->lun;
510 }
511 else
512 {
513 pACB->scan_devices = 0;
514 pPrevDCB->pNextDCB = pACB->pLinkDCB;
515 }
516 }
517
518 if ( ( plink->target > pACB->max_id ) || ( plink->lun > pACB->max_lun ) )
519 {
520 #ifdef DC390_DEBUG0
521 printf("DC390: Ignore target %d lun %d\n",
522 plink->target, plink->lun);
523 #endif
524 cmd->error = XS_DRIVER_STUFFUP;
525 return( COMPLETE );
526 }
527
528 if( (pACB->scan_devices) && !(pACB->DCBmap[plink->target] & (1 << plink->lun)) )
529 {
530 if( pACB->DeviceCnt < MAX_DEVICES )
531 {
532 pACB->DCBmap[plink->target] |= (1 << plink->lun);
533 pDCB = pACB->pDCB_free;
534 #ifdef DC390_DEBUG0
535 printf("pDCB=%8x,ID=%2x,", (UINT) pDCB, plink->target);
536 #endif
537 DC390_initDCB( pACB, pDCB, cmd );
538 }
539 else /* ???? */
540 {
541 #ifdef DC390_DEBUG0
542 printf("DC390: Ignore target %d lun %d\n",
543 plink->target, plink->lun);
544 #endif
545 cmd->error = XS_DRIVER_STUFFUP;
546 return( COMPLETE );
547 }
548 }
549 else if( !(pACB->scan_devices) && !(pACB->DCBmap[plink->target] & (1 << plink->lun)) )
550 {
551 #ifdef DC390_DEBUG0
552 printf("DC390: Ignore target %d lun %d\n",
553 plink->target, plink->lun);
554 #endif
555 cmd->error = XS_DRIVER_STUFFUP;
556 return( COMPLETE );
557 }
558 else
559 {
560 pDCB = pACB->pLinkDCB;
561 while( (pDCB->UnitSCSIID != plink->target) ||
562 (pDCB->UnitSCSILUN != plink->lun) )
563 {
564 pDCB = pDCB->pNextDCB;
565 }
566 #ifdef DC390_DEBUG0
567 printf("pDCB=%8x,ID=%2x,", (UINT) pDCB, plink->target);
568 #endif
569 }
570
571 cflags = cmd->flags;
572 if(cflags & SCSI_RESET)
573 {
574 DC390_reset (pACB);
575 cmd->error = XS_NOERROR;
576 return(COMPLETE);
577 }
578
579 if( cflags & ITSDONE )
580 {
581 printf("DC390: Is it done?\n");
582 cmd->flags &= ~ITSDONE;
583 }
584 if( !(cflags & INUSE) )
585 {
586 printf("DC390: In Use?\n");
587 cmd->flags |= INUSE;
588 }
589
590 cmd->error = 0;
591 cmd->resid = 0;
592
593 flags = splbio();
594
595 pcmd = cmd;
596
597 pSRB = GetSRB( pACB );
598
599 if( !pSRB )
600 {
601 pcmd->error = XS_DRIVER_STUFFUP;
602 splx(flags);
603 return( TRY_AGAIN_LATER);
604 }
605
606 /* BuildSRB(pSRB); */
607
608 pSRB->pSRBDCB = pDCB;
609 pSRB->pcmd = pcmd;
610 ptr = (PUCHAR) pSRB->CmdBlock;
611 ptr1 = (PUCHAR) pcmd->cmd;
612 pSRB->ScsiCmdLen = pcmd->cmdlen;
613 for(i=0; i< pcmd->cmdlen; i++)
614 {
615 *ptr = *ptr1;
616 ptr++;
617 ptr1++;
618 }
619 if( pcmd->datalen )
620 {
621 psg = (PSEG) &pSRB->SGsegment[0];
622 pSRB->pSegmentList = psg;
623 sgc = 0;
624
625 /* Set up the scatter gather list */
626 datalen = pcmd->datalen;
627 CurrPgVaddr = (int) pcmd->data;
628 CurrPgPaddr = vtophys(CurrPgVaddr);
629
630 while ((datalen) && (sgc < MAX_SG_ENTRY))
631 {
632 sglen = 0;
633 psg->SGXPtr = CurrPgPaddr;
634 NextPgPaddr = CurrPgPaddr;
635 while ((datalen) && (CurrPgPaddr == NextPgPaddr))
636 {
637 /*
638 * This page is contiguous (physically) with the the last,
639 * just extend the length
640 */
641
642 NextPgPaddr = (CurrPgPaddr & (~(PAGELEN - 1))) + PAGELEN;
643 pglen = NextPgPaddr - CurrPgPaddr;
644
645 if( datalen < pglen )
646 pglen = datalen;
647 sglen += pglen;
648 datalen -= pglen;
649 CurrPgVaddr = (CurrPgVaddr & (~(PAGELEN - 1))) + PAGELEN;
650 if( datalen )
651 CurrPgPaddr = vtophys(CurrPgVaddr);
652 }
653 /*
654 next page isn't contiguous, finish this segment
655 */
656 psg->SGXLen = sglen;
657 psg++;
658 sgc++;
659 }
660 pSRB->SGcount = sgc;
661
662 if (datalen)
663 {
664 printf("DC390: Out Of Segment Buffer!\n");
665 pSRB->pNextSRB = pACB->pFreeSRB;
666 pACB->pFreeSRB = pSRB;
667 pcmd->error = XS_DRIVER_STUFFUP;
668 splx(flags);
669 return (HAD_ERROR);
670 }
671 }
672 else
673 pSRB->SGcount = 0;
674
675 pSRB->SGIndex = 0;
676 pSRB->AdaptStatus = 0;
677 pSRB->TargetStatus = 0;
678 pSRB->MsgCnt = 0;
679 if( pDCB->DevType != SCSI_SEQACESS )
680 pSRB->RetryCnt = 1;
681 else
682 pSRB->RetryCnt = 0;
683 pSRB->SRBStatus = 0;
684 pSRB->SRBFlag = 0;
685 pSRB->SRBState = 0;
686 pSRB->TotalXferredLen = 0;
687 pSRB->SGPhysAddr = 0;
688 pSRB->SGToBeXferLen = 0;
689 pSRB->ScsiPhase = 0;
690 pSRB->EndMessage = 0;
691 splx(flags);
692
693 if( !(cflags & SCSI_NOMASK) )
694 {
695 flags = splbio();
696 SendSRB( pcmd, pACB, pSRB );
697 timeout(DC390_timeout, (caddr_t)pSRB, (pcmd->timeout * hz)/1000);
698 splx(flags);
699 return( SUCCESSFULLY_QUEUED);
700 }
701 else
702 {
703 SendSRB( pcmd, pACB, pSRB );
704 do
705 {
706 while(--pcmd->timeout)
707 {
708 DELAY(1000);
709 sstatus = inb( ioport+Scsi_Status );
710 if( sstatus & INTERRUPT )
711 break;
712 }
713 if( pcmd->timeout == 0 )
714 {
715 return(HAD_ERROR);
716 }
717 else
718 {
719 DC390_Interrupt( pACB );
720 }
721 }
722 while( !(pcmd->flags & ITSDONE) );
723 if( pcmd->error == XS_TIMEOUT)
724 return(HAD_ERROR);
725 else
726 return(COMPLETE);
727 }
728 }
729
730
731 void
732 trmamd_min_phys( struct buf *bp )
733 {
734 if (bp->b_bcount > ((MAX_SG_ENTRY - 1) * PAGELEN))
735 bp->b_bcount = ((MAX_SG_ENTRY - 1) * PAGELEN);
736 }
737
738
739 #ifdef REL_2_1_0
740 u_int32
741 trmamd_info( int unit )
742 {
743 return (MAX_CMD_PER_LUN); /* outstanding requests at a time per device */
744 }
745 #endif
746
747
748 static PUCHAR phystovirt( PSRB pSRB, ULONG xferCnt )
749 {
750 int dataPtr;
751 PSCSICMD pcmd;
752 UCHAR i;
753 PSEG pseg;
754
755 pcmd = pSRB->pcmd;
756 dataPtr = (int) pcmd->data;
757 pseg = pSRB->SGsegment;
758 for(i=0; i < pSRB->SGIndex; i++)
759 {
760 dataPtr += (int) pseg->SGXLen;
761 pseg++;
762 }
763 dataPtr += (int) xferCnt;
764 return( (PUCHAR) dataPtr);
765 }
766
767
768 /***********************************************************************
769 * Function : int DC390_abort (SCSICMD *cmd)
770 *
771 * Purpose : Abort an errant SCSI command
772 *
773 * Inputs : cmd - command to abort
774 *
775 * Returns : 0 on success, -1 on failure.
776 ***********************************************************************/
777 /*
778 int
779 DC390_abort (SCSICMD *cmd)
780 {
781 int flags;
782 PACB pACB;
783 PDCB pDCB, pdcb;
784 PSRB pSRB, psrb;
785 USHORT count, i;
786 PSCSICMD pcmd, pcmd1;
787 int status;
788
789
790 #ifdef DC390_DEBUG0
791 printf("DC390 : Abort Cmd.");
792 #endif
793
794 flags = splbio();
795
796 pACB = (PACB) cmd->host->hostdata;
797 pDCB = pACB->pLinkDCB;
798 pdcb = pDCB;
799 while( (pDCB->UnitSCSIID != cmd->sc_link->target) ||
800 (pDCB->UnitSCSILUN != cmd->sc_link->lun) )
801 {
802 pDCB = pDCB->pNextDCB;
803 if( pDCB == pdcb )
804 goto NOT_RUN;
805 }
806
807
808 pSRB = pDCB->pWaitingSRB;
809 if( !pSRB )
810 goto ON_GOING;
811 if( pSRB->pcmd == cmd )
812 {
813 pDCB->pWaitingSRB = pSRB->pNextSRB;
814 goto IN_WAIT;
815 }
816 else
817 {
818 psrb = pSRB;
819 while( psrb->pNextSRB->pcmd != cmd )
820 {
821 psrb = psrb->pNextSRB;
822 if( !psrb )
823 goto ON_GOING;
824 }
825 pSRB = psrb->pNextSRB;
826 psrb->pNextSRB = pSRB->pNextSRB;
827 if( pSRB == pDCB->pWaitLast )
828 pDCB->pWaitLast = psrb;
829 IN_WAIT:
830 pSRB->pNextSRB = pACB->pFreeSRB;
831 pACB->pFreeSRB = pSRB;
832 cmd->next = NULL;
833 status = SCSI_ABORT_SUCCESS;
834 goto ABO_X;
835 }
836
837 ON_GOING:
838 pSRB = pDCB->pGoingSRB;
839 for( count = pDCB->GoingSRBCnt, i=0; i<count; i++)
840 {
841 if( pSRB->pcmd != cmd )
842 pSRB = pSRB->pNextSRB;
843 else
844 {
845 if( (pACB->pActiveDCB == pDCB) && (pDCB->pActiveSRB == pSRB) )
846 {
847 status = SCSI_ABORT_BUSY;
848 goto ABO_X;
849 }
850 else
851 {
852 status = SCSI_ABORT_SNOOZE;
853 goto ABO_X;
854 }
855 }
856 }
857
858 NOT_RUN:
859 status = SCSI_ABORT_NOT_RUNNING;
860
861 ABO_X:
862 cmd->error = XS_NOERROR;
863 scsi_done(cmd);
864 splx(flags);
865 return( status );
866 }
867 */
868
869 static void
870 ResetDevParam( PACB pACB )
871 {
872 PDCB pDCB, pdcb;
873
874 pDCB = pACB->pLinkDCB;
875 if( pDCB == NULL )
876 return;
877 pdcb = pDCB;
878 do
879 {
880 pDCB->SyncMode &= ~SYNC_NEGO_DONE;
881 pDCB->SyncPeriod = 0;
882 pDCB->SyncOffset = 0;
883 pDCB->CtrlR3 = FAST_CLK;
884 pDCB->CtrlR4 &= NEGATE_REQACKDATA;
885 pDCB->CtrlR4 |= EATER_25NS;
886 pDCB = pDCB->pNextDCB;
887 }
888 while( pdcb != pDCB );
889 }
890
891
892 static void
893 RecoverSRB( PACB pACB )
894 {
895 PDCB pDCB, pdcb;
896 PSRB psrb, psrb2;
897 USHORT cnt, i;
898
899 pDCB = pACB->pLinkDCB;
900 if( pDCB == NULL )
901 return;
902 pdcb = pDCB;
903 do
904 {
905 cnt = pdcb->GoingSRBCnt;
906 psrb = pdcb->pGoingSRB;
907 for (i=0; i<cnt; i++)
908 {
909 psrb2 = psrb;
910 psrb = psrb->pNextSRB;
911 /* RewaitSRB( pDCB, psrb ); */
912 if( pdcb->pWaitingSRB )
913 {
914 psrb2->pNextSRB = pdcb->pWaitingSRB;
915 pdcb->pWaitingSRB = psrb2;
916 }
917 else
918 {
919 pdcb->pWaitingSRB = psrb2;
920 pdcb->pWaitLast = psrb2;
921 psrb2->pNextSRB = NULL;
922 }
923 }
924 pdcb->GoingSRBCnt = 0;
925 pdcb->pGoingSRB = NULL;
926 pdcb->TagMask = 0;
927 pdcb = pdcb->pNextDCB;
928 }
929 while( pdcb != pDCB );
930 }
931
932
933 /***********************************************************************
934 * Function : DC390_reset (PACB pACB)
935 *
936 * Purpose : perform a hard reset on the SCSI bus( and AMD chip).
937 *
938 * Inputs : cmd - command which caused the SCSI RESET
939 *
940 ***********************************************************************/
941
942 static void
943 DC390_reset (PACB pACB)
944 {
945 USHORT ioport;
946 int flags;
947 UCHAR bval;
948 USHORT i;
949
950
951 #ifdef DC390_DEBUG0
952 printf("DC390: RESET,");
953 #endif
954
955 flags = splbio();
956
957 ioport = pACB->IOPortBase;
958 bval = inb(ioport+CtrlReg1);
959 bval |= DIS_INT_ON_SCSI_RST;
960 OutB(bval,ioport+CtrlReg1); /* disable interrupt */
961 DC390_ResetSCSIBus( pACB );
962 for( i=0; i<500; i++ )
963 DELAY(1000);
964 bval = inb(ioport+CtrlReg1);
965 bval &= ~DIS_INT_ON_SCSI_RST;
966 OutB(bval,ioport+CtrlReg1); /* re-enable interrupt */
967
968 bval = DMA_IDLE_CMD;
969 OutB(bval,ioport+DMA_Cmd);
970 bval = CLEAR_FIFO_CMD;
971 OutB(bval,ioport+ScsiCmd);
972
973 ResetDevParam( pACB );
974 DoingSRB_Done( pACB );
975 pACB->pActiveDCB = NULL;
976
977 pACB->ACBFlag = 0;
978 DoWaitingSRB( pACB );
979 splx(flags);
980 return;
981 }
982
983
984 void
985 DC390_timeout( void *arg1)
986 {
987 PSRB pSRB;
988
989 pSRB = (PSRB) arg1;
990 }
991
992
993 #include <pci/scsiiom.c>
994
995
996 /***********************************************************************
997 * Function : static void DC390_initDCB
998 *
999 * Purpose : initialize the internal structures for a given DCB
1000 *
1001 * Inputs : cmd - pointer to this scsi cmd request block structure
1002 *
1003 ***********************************************************************/
1004 void DC390_initDCB( PACB pACB, PDCB pDCB, PSCSICMD cmd )
1005 {
1006 PEEprom prom;
1007 UCHAR bval;
1008 USHORT index;
1009 PSCLINK plink;
1010
1011 if( pACB->DeviceCnt == 0 )
1012 {
1013 pACB->pLinkDCB = pDCB;
1014 pACB->pDCBRunRobin = pDCB;
1015 pDCB->pNextDCB = pDCB;
1016 pPrevDCB = pDCB;
1017 }
1018 else
1019 pPrevDCB->pNextDCB = pDCB;
1020
1021 plink = cmd->sc_link;
1022 pDCB->pDCBACB = pACB;
1023 pDCB->UnitSCSIID = plink->target;
1024 pDCB->UnitSCSILUN = plink->lun;
1025 pDCB->pWaitingSRB = NULL;
1026 pDCB->pGoingSRB = NULL;
1027 pDCB->GoingSRBCnt = 0;
1028 pDCB->pActiveSRB = NULL;
1029 pDCB->TagMask = 0;
1030 pDCB->MaxCommand = 1;
1031 pDCB->AdaptIndex = pACB->AdapterIndex;
1032 index = pACB->AdapterIndex;
1033 pDCB->DCBFlag = 0;
1034
1035 prom = (PEEprom) &eepromBuf[index][plink->target << 2];
1036 pDCB->DevMode = prom->EE_MODE1;
1037 pDCB->AdpMode = eepromBuf[index][EE_MODE2];
1038
1039 if( pDCB->DevMode & EN_DISCONNECT_ )
1040 bval = 0xC0;
1041 else
1042 bval = 0x80;
1043 bval |= plink->lun;
1044 pDCB->IdentifyMsg = bval;
1045
1046 pDCB->SyncMode = 0;
1047 if( pDCB->DevMode & SYNC_NEGO_ )
1048 {
1049 if( !(plink->lun) || CurrSyncOffset )
1050 pDCB->SyncMode = SYNC_ENABLE;
1051 }
1052
1053 pDCB->SyncPeriod = 0;
1054 pDCB->SyncOffset = 0;
1055 pDCB->NegoPeriod = (clock_period1[prom->EE_SPEED] * 25) >> 2;
1056
1057 pDCB->CtrlR1 = pACB->AdaptSCSIID;
1058 if( pDCB->DevMode & PARITY_CHK_ )
1059 pDCB->CtrlR1 |= PARITY_ERR_REPO;
1060
1061 pDCB->CtrlR3 = FAST_CLK;
1062
1063 pDCB->CtrlR4 = EATER_25NS;
1064 if( pDCB->AdpMode & ACTIVE_NEGATION)
1065 pDCB->CtrlR4 |= NEGATE_REQACKDATA;
1066 }
1067
1068
1069 /***********************************************************************
1070 * Function : static void DC390_initSRB
1071 *
1072 * Purpose : initialize the internal structures for a given SRB
1073 *
1074 * Inputs : psrb - pointer to this scsi request block structure
1075 *
1076 ***********************************************************************/
1077 void DC390_initSRB( PSRB psrb )
1078 {
1079 psrb->PhysSRB = vtophys( psrb );
1080 }
1081
1082
1083 void DC390_linkSRB( PACB pACB )
1084 {
1085 USHORT count, i;
1086 PSRB psrb;
1087
1088 count = pACB->SRBCount;
1089
1090 for( i=0; i< count; i++)
1091 {
1092 if( i != count - 1)
1093 pACB->SRB_array[i].pNextSRB = &pACB->SRB_array[i+1];
1094 else
1095 pACB->SRB_array[i].pNextSRB = NULL;
1096 psrb = (PSRB) &pACB->SRB_array[i];
1097 DC390_initSRB( psrb );
1098 }
1099 }
1100
1101
1102 /***********************************************************************
1103 * Function : static void DC390_initACB
1104 *
1105 * Purpose : initialize the internal structures for a given SCSI host
1106 *
1107 * Inputs : psh - pointer to this host adapter's structure
1108 *
1109 ***********************************************************************/
1110 void DC390_initACB( PACB pACB, ULONG io_port, UCHAR Irq, USHORT index )
1111 {
1112 USHORT i;
1113
1114
1115 pACB->max_id = 7;
1116 if( pACB->max_id == eepromBuf[index][EE_ADAPT_SCSI_ID] )
1117 pACB->max_id--;
1118 if( eepromBuf[index][EE_MODE2] & LUN_CHECK )
1119 pACB->max_lun = 7;
1120 else
1121 pACB->max_lun = 0;
1122
1123 pACB->IOPortBase = (USHORT) io_port;
1124 pACB->pLinkDCB = NULL;
1125 pACB->pDCBRunRobin = NULL;
1126 pACB->pActiveDCB = NULL;
1127 pACB->pFreeSRB = pACB->SRB_array;
1128 pACB->SRBCount = MAX_SRB_CNT;
1129 pACB->AdapterIndex = index;
1130 pACB->status = 0;
1131 pACB->AdaptSCSIID = eepromBuf[index][EE_ADAPT_SCSI_ID];
1132 pACB->HostID_Bit = (1 << pACB->AdaptSCSIID);
1133 pACB->AdaptSCSILUN = 0;
1134 pACB->DeviceCnt = 0;
1135 pACB->IRQLevel = Irq;
1136 pACB->TagMaxNum = (eepromBuf[index][EE_TAG_CMD_NUM]) << 2;
1137 pACB->ACBFlag = 0;
1138 pACB->scan_devices = 1;
1139 pACB->Gmode2 = eepromBuf[index][EE_MODE2];
1140 if( eepromBuf[index][EE_MODE2] & LUN_CHECK )
1141 pACB->LUNchk = 1;
1142 pACB->pDCB_free = &pACB->DCB_array[0];
1143 DC390_linkSRB( pACB );
1144 pACB->pTmpSRB = &pACB->TmpSRB;
1145 DC390_initSRB( pACB->pTmpSRB );
1146 for(i=0; i<MAX_SCSI_ID; i++)
1147 pACB->DCBmap[i] = 0;
1148
1149 pACB->ScsiLink.adapter_unit = index;
1150 pACB->ScsiLink.adapter_targ = pACB->AdaptSCSIID;
1151 pACB->ScsiLink.fordriver = 0;
1152 pACB->ScsiLink.opennings = 2;
1153 pACB->ScsiLink.adapter = &trmamd_switch;
1154 pACB->ScsiLink.device = &trmamd_dev;
1155 pACB->ScsiLink.flags = 0;
1156 }
1157
1158
1159 /***********************************************************************
1160 * Function : static int DC390_initAdapter
1161 *
1162 * Purpose : initialize the SCSI chip ctrl registers
1163 *
1164 * Inputs : psh - pointer to this host adapter's structure
1165 *
1166 ***********************************************************************/
1167 int DC390_initAdapter( PACB pACB, ULONG io_port, UCHAR Irq, USHORT index,
1168 pcici_t config_id )
1169 {
1170 USHORT ioport;
1171 UCHAR bval;
1172
1173 #ifdef CHECK_SHARE_INT
1174 PACB pacb;
1175 USHORT used_irq = 0;
1176
1177 pacb = pACB_start;
1178 if( pacb != NULL )
1179 {
1180 for ( ; (pacb != (PACB) -1) ; )
1181 {
1182 if( pacb->IRQLevel == Irq )
1183 {
1184 used_irq = 1;
1185 break;
1186 }
1187 else
1188 pacb = pacb->pNextACB;
1189 }
1190 }
1191
1192 if( !used_irq )
1193 {
1194 #endif
1195 if( !pci_map_int (config_id, (PVOID)DC390_Interrupt, pACB, &bio_imask) )
1196 {
1197 if(bootverbose)
1198 printf("DC390: register Interrupt handler error!\n");
1199 return( -1 );
1200 }
1201
1202 #ifdef CHECK_SHARE_INT
1203 }
1204 #endif
1205
1206 ioport = (USHORT) io_port;
1207 bval = 153; /* 250ms selection timeout */
1208 OutB(bval,ioport+Scsi_TimeOut);
1209
1210 bval = CLK_FREQ_40MHZ; /* Conversion factor = 0 , 40MHz clock */
1211 OutB(bval,ioport+Clk_Factor);
1212
1213 bval = NOP_CMD; /* NOP cmd - clear command register */
1214 OutB(bval,ioport+ScsiCmd);
1215
1216 bval = EN_FEATURE+EN_SCSI2_CMD; /* Enable Feature and SCSI-2 */
1217 OutB(bval,ioport+CtrlReg2);
1218
1219 bval = FAST_CLK; /* fast clock */
1220 OutB(bval,ioport+CtrlReg3);
1221
1222 bval = EATER_25NS;
1223 if( eepromBuf[index][EE_MODE2] & ACTIVE_NEGATION )
1224 bval |= NEGATE_REQACKDATA;
1225 OutB(bval,ioport+CtrlReg4);
1226
1227 bval = DIS_INT_ON_SCSI_RST; /* Disable SCSI bus reset interrupt */
1228 OutB(bval,ioport+CtrlReg1);
1229
1230 return(0);
1231 }
1232
1233
1234 void
1235 DC390_EnableCfg( USHORT mechnum, UCHAR regval )
1236 {
1237 ULONG wlval;
1238
1239 if(mechnum == 2)
1240 {
1241 OutB(mech2bus, PCI_CFG2_FORWARD_REG);
1242 OutB(mech2CfgSPenR, PCI_CFG2_ENABLE_REG);
1243 }
1244 else
1245 {
1246 regval &= 0xFC;
1247 wlval = mech1addr;
1248 wlval |= (((ULONG)regval) & 0xff);
1249 OutL(wlval, PCI_CFG1_ADDRESS_REG);
1250 }
1251 }
1252
1253
1254 void
1255 DC390_DisableCfg( USHORT mechnum )
1256 {
1257
1258 if(mechnum == 2)
1259 OutB(0, PCI_CFG2_ENABLE_REG);
1260 else
1261 OutL(0, PCI_CFG1_ADDRESS_REG);
1262 }
1263
1264
1265 UCHAR
1266 DC390_inByte( USHORT mechnum, UCHAR regval )
1267 {
1268 UCHAR bval;
1269 USHORT wval;
1270 int flags;
1271
1272 flags = splbio();
1273 DC390_EnableCfg( mechnum, regval );
1274 if(mechnum == 2)
1275 {
1276 wval = mech2Agent;
1277 wval <<= 8;
1278 wval |= ((USHORT) regval) & 0xff;
1279 bval = inb(wval);
1280 }
1281 else
1282 {
1283 regval &= 3;
1284 bval = inb(PCI_CFG1_DATA_REG | regval);
1285 }
1286 DC390_DisableCfg(mechnum);
1287 splx(flags);
1288 return(bval);
1289 }
1290
1291
1292 USHORT
1293 DC390_inWord( USHORT mechnum, UCHAR regval )
1294 {
1295 USHORT wval;
1296 int flags;
1297
1298 flags = splbio();
1299 DC390_EnableCfg(mechnum,regval);
1300 if(mechnum == 2)
1301 {
1302 wval = mech2Agent;
1303 wval <<= 8;
1304 wval |= regval;
1305 wval = inw(wval);
1306 }
1307 else
1308 {
1309 regval &= 3;
1310 wval = inw(PCI_CFG1_DATA_REG | regval);
1311 }
1312 DC390_DisableCfg(mechnum);
1313 splx(flags);
1314 return(wval);
1315 }
1316
1317
1318 ULONG
1319 DC390_inDword(USHORT mechnum, UCHAR regval )
1320 {
1321 ULONG wlval;
1322 int flags;
1323 USHORT wval;
1324
1325 flags = splbio();
1326 DC390_EnableCfg(mechnum,regval);
1327 if(mechnum == 2)
1328 {
1329 wval = mech2Agent;
1330 wval <<= 8;
1331 wval |= regval;
1332 wlval = inl(wval);
1333 }
1334 else
1335 {
1336 wlval = inl(PCI_CFG1_DATA_REG);
1337 }
1338 DC390_DisableCfg(mechnum);
1339 splx(flags);
1340 return(wlval);
1341 }
1342
1343
1344 void
1345 DC390_OutB(USHORT mechnum, UCHAR regval, UCHAR bval )
1346 {
1347
1348 USHORT wval;
1349 int flags;
1350
1351 flags = splbio();
1352 DC390_EnableCfg(mechnum,regval);
1353 if(mechnum == 2)
1354 {
1355 wval = mech2Agent;
1356 wval <<= 8;
1357 wval |= regval;
1358 OutB(bval, wval);
1359 }
1360 else
1361 {
1362 regval &= 3;
1363 OutB(bval, PCI_CFG1_DATA_REG | regval);
1364 }
1365 DC390_DisableCfg(mechnum);
1366 splx(flags);
1367 }
1368
1369
1370 void
1371 DC390_EnDisableCE( UCHAR mode, USHORT mechnum, PUCHAR regval )
1372 {
1373
1374 UCHAR bval;
1375
1376 bval = 0;
1377 if(mode == ENABLE_CE)
1378 *regval = 0xc0;
1379 else
1380 *regval = 0x80;
1381 DC390_OutB(mechnum,*regval,bval);
1382 if(mode == DISABLE_CE)
1383 DC390_OutB(mechnum,*regval,bval);
1384 DELAY(160);
1385 }
1386
1387
1388 void
1389 DC390_EEpromOutDI( USHORT mechnum, PUCHAR regval, USHORT Carry )
1390 {
1391 UCHAR bval;
1392
1393 bval = 0;
1394 if(Carry)
1395 {
1396 bval = 0x40;
1397 *regval = 0x80;
1398 DC390_OutB(mechnum,*regval,bval);
1399 }
1400 DELAY(160);
1401 bval |= 0x80;
1402 DC390_OutB(mechnum,*regval,bval);
1403 DELAY(160);
1404 bval = 0;
1405 DC390_OutB(mechnum,*regval,bval);
1406 DELAY(160);
1407 }
1408
1409
1410 UCHAR
1411 DC390_EEpromInDO( USHORT mechnum )
1412 {
1413 UCHAR bval,regval;
1414
1415 regval = 0x80;
1416 bval = 0x80;
1417 DC390_OutB(mechnum,regval,bval);
1418 DELAY(160);
1419 bval = 0x40;
1420 DC390_OutB(mechnum,regval,bval);
1421 DELAY(160);
1422 regval = 0x0;
1423 bval = DC390_inByte(mechnum,regval);
1424 if(bval == 0x22)
1425 return(1);
1426 else
1427 return(0);
1428 }
1429
1430
1431 USHORT
1432 EEpromGetData1( USHORT mechnum )
1433 {
1434 UCHAR i;
1435 UCHAR carryFlag;
1436 USHORT wval;
1437
1438 wval = 0;
1439 for(i=0; i<16; i++)
1440 {
1441 wval <<= 1;
1442 carryFlag = DC390_EEpromInDO(mechnum);
1443 wval |= carryFlag;
1444 }
1445 return(wval);
1446 }
1447
1448
1449 void
1450 DC390_Prepare( USHORT mechnum, PUCHAR regval, UCHAR EEpromCmd )
1451 {
1452 UCHAR i,j;
1453 USHORT carryFlag;
1454
1455 carryFlag = 1;
1456 j = 0x80;
1457 for(i=0; i<9; i++)
1458 {
1459 DC390_EEpromOutDI(mechnum,regval,carryFlag);
1460 carryFlag = (EEpromCmd & j) ? 1 : 0;
1461 j >>= 1;
1462 }
1463 }
1464
1465
1466 void
1467 DC390_ReadEEprom( USHORT mechnum, USHORT index )
1468 {
1469 UCHAR regval,cmd;
1470 PUSHORT ptr;
1471 USHORT i;
1472
1473 ptr = (PUSHORT) &eepromBuf[index][0];
1474 cmd = EEPROM_READ;
1475 for(i=0; i<0x40; i++)
1476 {
1477 DC390_EnDisableCE(ENABLE_CE, mechnum, ®val);
1478 DC390_Prepare(mechnum, ®val, cmd);
1479 *ptr = EEpromGetData1(mechnum);
1480 ptr++;
1481 cmd++;
1482 DC390_EnDisableCE(DISABLE_CE,mechnum,®val);
1483 }
1484 }
1485
1486
1487 USHORT
1488 DC390_DefaultEEprom( USHORT mechnum, USHORT index )
1489 {
1490 PUCHAR ptr;
1491 USHORT i;
1492
1493 ptr = (PUCHAR) &eepromBuf[index][0];
1494 bzero (ptr, sizeof eepromBuf[index]);
1495 for(i=0; i<0x40; i++)
1496 {
1497 *ptr = (TAG_QUEUING_|EN_DISCONNECT_|SYNC_NEGO_|PARITY_CHK_);
1498 ptr += 4;
1499 }
1500 eepromBuf[index][EE_ADAPT_SCSI_ID] = 7;
1501 eepromBuf[index][EE_MODE2] = (LUN_CHECK|ACTIVE_NEGATION);
1502 eepromBuf[index][EE_TAG_CMD_NUM] = 4;
1503 return 0;
1504 }
1505
1506
1507 USHORT
1508 DC390_CheckEEpromCheckSum( USHORT MechNum, USHORT index )
1509 {
1510 USHORT wval, rc, *ptr;
1511 UCHAR i;
1512
1513 DC390_ReadEEprom( MechNum, index );
1514 wval = 0;
1515 ptr = (PUSHORT) &eepromBuf[index][0];
1516 for(i=0; i<128 ;i+=2, ptr++)
1517 wval += *ptr;
1518 if( wval == 0x1234 )
1519 rc = 0;
1520 else
1521 rc = DC390_DefaultEEprom( MechNum, index);
1522 return( rc );
1523 }
1524
1525
1526 USHORT
1527 DC390_ToMech( USHORT Mechnum, pcici_t config_id )
1528 {
1529
1530 if(Mechnum == 2)
1531 {
1532 mech2bus = config_id.cfg2.forward; /* Bus num */
1533 mech2Agent = config_id.cfg2.port >> 8; /* Dev num */
1534 mech2CfgSPenR = config_id.cfg2.enable; /* Fun num */
1535 }
1536 else /* use mech #1 method */
1537 {
1538 mech1addr = config_id.cfg1;
1539 }
1540 return(0);
1541 }
1542
1543 /***********************************************************************
1544 * Function : static int DC390_init (struct Scsi_Host *host)
1545 *
1546 * Purpose : initialize the internal structures for a given SCSI host
1547 *
1548 * Inputs : host - pointer to this host adapter's structure/
1549 *
1550 * Preconditions : when this function is called, the chip_type
1551 * field of the pACB structure MUST have been set.
1552 ***********************************************************************/
1553
1554 static int
1555 DC390_init( ULONG io_port, UCHAR Irq, USHORT index, USHORT MechNum,
1556 pcici_t config_id)
1557 {
1558 PACB pACB;
1559
1560 if( !DC390_CheckEEpromCheckSum( MechNum, index) )
1561 {
1562 pACB = (PACB) malloc (sizeof (struct _ACB), M_DEVBUF, M_WAITOK);
1563 if( !pACB )
1564 {
1565 printf("DC390%d: cannot allocate ACB !\n", index);
1566 return( -1 );
1567 }
1568 bzero (pACB, sizeof (struct _ACB));
1569 DC390_initACB( pACB, io_port, Irq, index );
1570 if( !DC390_initAdapter( pACB, io_port, Irq, index, config_id) )
1571 {
1572 if( !pACB_start )
1573 {
1574 pACB_start = pACB;
1575 pACB_current = pACB;
1576 pACB->pNextACB = (PACB) -1;
1577 }
1578 else
1579 {
1580 pACB_current->pNextACB = pACB;
1581 pACB_current = pACB;
1582 pACB->pNextACB = (PACB) -1;
1583 }
1584 pACB0[index] = pACB;
1585
1586 #ifdef DC390_DEBUG0
1587 printf("DC390: pACB = %8x, pDCB_array = %8x, pSRB_array = %8x\n",
1588 (UINT) pACB, (UINT) pACB->DCB_array, (UINT) pACB->SRB_array);
1589 printf("DC390: ACB size= %4x, DCB size= %4x, SRB size= %4x\n",
1590 sizeof(DC390_ACB), sizeof(DC390_DCB), sizeof(DC390_SRB) );
1591 #endif
1592
1593 return( 0 );
1594 }
1595 else
1596 {
1597 free( pACB, M_DEVBUF);
1598 return( -1 );
1599 }
1600 }
1601 else
1602 {
1603 printf("DC390_init: EEPROM reading error!\n");
1604 return( -1 );
1605 }
1606 }
1607
1608
1609
1610 void
1611 trmamd_attach (pcici_t config_id, int unit)
1612 {
1613 struct scsibus_data *scbus;
1614 UCHAR irq;
1615 USHORT MechNum;
1616 ULONG io_port, wlval;
1617 PACB pACB = 0;
1618 int flags;
1619
1620 if( unit >= MAX_ADAPTER_NUM )
1621 return;
1622
1623 if( pACB0[unit] )
1624 return;
1625
1626 CurrentID = 0;
1627 CurrentLUN = 0;
1628 MechNum = pci_mechanism;
1629
1630 #ifdef DC390_DEBUG0
1631 if(bootverbose)
1632 printf("DC390: Mech=%2x,\n",(UCHAR) MechNum);
1633 #endif
1634
1635 if( !DC390_ToMech( MechNum, config_id ) )
1636 {
1637 wlval = DC390_inDword( MechNum, PCI_ID_REG);
1638 if(wlval == PCI_DEVICE_ID_AMD53C974 )
1639 {
1640 io_port =DC390_inDword(MechNum,PCI_BASE_ADDR0) & 0xFFFE;
1641 irq = DC390_inByte( MechNum, PCI_INTERRUPT_REG);
1642 #ifdef DC390_DEBUG0
1643 if(bootverbose)
1644 printf("DC390: IO_PORT=%4x,IRQ=%x,\n",(UINT) io_port, irq);
1645 #endif
1646 if( !DC390_init( io_port, irq, (USHORT) unit, MechNum, config_id) )
1647 {
1648 adapterCnt++;
1649 }
1650 else
1651 return;
1652 }
1653 }
1654
1655 pACB = pACB0[unit];
1656
1657 /*
1658 Now let the generic SCSI driver look for the SCSI devices on the bus
1659 */
1660
1661 flags = splbio();
1662
1663 scbus = scsi_alloc_bus();
1664 if(!scbus)
1665 {
1666 splx(flags);
1667 return;
1668 }
1669 scbus->adapter_link = &pACB->ScsiLink;
1670 scbus->maxtarg = pACB->max_id;
1671
1672 #ifdef DC390_DEBUG
1673 if(bootverbose)
1674 printf("\nDC390: scanning for devices ...\n\n");
1675 #endif
1676
1677 scsi_attachdevs (scbus);
1678 scbus = NULL; /* Upper-level SCSI code owns this now */
1679
1680 #ifdef DC390_DEBUG
1681 if(bootverbose)
1682 printf("\n\nDC390: Attach devices return\n");
1683 #endif
1684
1685 splx(flags);
1686 }
1687
1688
1689 static char*
1690 trmamd_probe (pcici_t tag, pcidi_t type)
1691 {
1692 if( type == PCI_DEVICE_ID_AMD53C974 )
1693 return ("amd 53c974 scsi");
1694 else
1695 return (NULL);
1696 }
1697
Cache object: c347c721bc0820929915cae4ef697f51
|