1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77#define DEBUG_INTERRUPT 0
78#define DEBUG_QUEUE 0
79#define DEBUG_STATE 0
80#define INT_DISC 0
81
82
83#ifndef CVT_LINUX_VERSION
84#define CVT_LINUX_VERSION(V,P,S) (V * 65536 + P * 256 + S)
85#endif
86
87#ifndef LINUX_VERSION_CODE
88#include <linux/version.h>
89#endif
90
91#include <linux/sched.h>
92#include <linux/delay.h>
93#include <linux/blk.h>
94#include <asm/io.h>
95
96#include "i91uscsi.h"
97
98
99static void tul_se2_wait(void);
100
101
102static SCB *tul_find_busy_scb(HCS * pCurHcb, WORD tarlun);
103static SCB *tul_find_done_scb(HCS * pCurHcb);
104
105static int tulip_main(HCS * pCurHcb);
106
107static int tul_next_state(HCS * pCurHcb);
108static int tul_state_1(HCS * pCurHcb);
109static int tul_state_2(HCS * pCurHcb);
110static int tul_state_3(HCS * pCurHcb);
111static int tul_state_4(HCS * pCurHcb);
112static int tul_state_5(HCS * pCurHcb);
113static int tul_state_6(HCS * pCurHcb);
114static int tul_state_7(HCS * pCurHcb);
115static int tul_xfer_data_in(HCS * pCurHcb);
116static int tul_xfer_data_out(HCS * pCurHcb);
117static int tul_xpad_in(HCS * pCurHcb);
118static int tul_xpad_out(HCS * pCurHcb);
119static int tul_status_msg(HCS * pCurHcb);
120
121static int tul_msgin(HCS * pCurHcb);
122static int tul_msgin_sync(HCS * pCurHcb);
123static int tul_msgin_accept(HCS * pCurHcb);
124static int tul_msgout_reject(HCS * pCurHcb);
125static int tul_msgin_extend(HCS * pCurHcb);
126
127static int tul_msgout_ide(HCS * pCurHcb);
128static int tul_msgout_abort_targ(HCS * pCurHcb);
129static int tul_msgout_abort_tag(HCS * pCurHcb);
130
131static int tul_bus_device_reset(HCS * pCurHcb);
132static void tul_select_atn(HCS * pCurHcb, SCB * pCurScb);
133static void tul_select_atn3(HCS * pCurHcb, SCB * pCurScb);
134static void tul_select_atn_stop(HCS * pCurHcb, SCB * pCurScb);
135static int int_tul_busfree(HCS * pCurHcb);
136int int_tul_scsi_rst(HCS * pCurHcb);
137static int int_tul_bad_seq(HCS * pCurHcb);
138static int int_tul_resel(HCS * pCurHcb);
139static int tul_sync_done(HCS * pCurHcb);
140static int wdtr_done(HCS * pCurHcb);
141static int wait_tulip(HCS * pCurHcb);
142static int tul_wait_done_disc(HCS * pCurHcb);
143static int tul_wait_disc(HCS * pCurHcb);
144static void tulip_scsi(HCS * pCurHcb);
145static int tul_post_scsi_rst(HCS * pCurHcb);
146
147static void tul_se2_ew_en(WORD CurBase);
148static void tul_se2_ew_ds(WORD CurBase);
149static int tul_se2_rd_all(WORD CurBase);
150static void tul_se2_update_all(WORD CurBase);
151static void tul_read_eeprom(WORD CurBase);
152
153
154HCS tul_hcs[MAX_SUPPORTED_ADAPTERS];
155
156static INI_ADPT_STRUCT i91u_adpt[MAX_SUPPORTED_ADAPTERS];
157
158
159static NVRAM i91unvram;
160static NVRAM *i91unvramp;
161
162
163
164static UCHAR i91udftNvRam[64] =
165{
166
167 0x25, 0xc9,
168 0x40,
169 0x01,
170
171 0x95,
172 0x00,
173 0x00,
174 0x01,
175 NBC1_DEFAULT,
176 0,
177 0,
178 0,
179
180 7,
181 NCC1_DEFAULT,
182 0,
183 0x10,
184
185 NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
186 NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
187 NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
188 NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
189
190
191 7,
192 NCC1_DEFAULT,
193 0,
194 0x10,
195
196 NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
197 NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
198 NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
199 NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
200 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
201 0, 0};
202
203
204static UCHAR tul_rate_tbl[8] =
205{
206
207 12,
208 18,
209 25,
210 31,
211 37,
212 43,
213 50,
214 62
215};
216
217extern int tul_num_ch;
218
219
220static void tul_do_pause(unsigned amount)
221{
222 unsigned long the_time = jiffies + amount;
223
224#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
225 while (time_before_eq(jiffies, the_time));
226#else
227 while (jiffies < the_time);
228#endif
229}
230
231
232
233
234
235
236void tul_se2_wait()
237{
238#if 1
239 udelay(30);
240#else
241 UCHAR readByte;
242
243 readByte = TUL_RD(0, 0x61);
244 if ((readByte & 0x10) == 0x10) {
245 for (;;) {
246 readByte = TUL_RD(0, 0x61);
247 if ((readByte & 0x10) == 0x10)
248 break;
249 }
250 for (;;) {
251 readByte = TUL_RD(0, 0x61);
252 if ((readByte & 0x10) != 0x10)
253 break;
254 }
255 } else {
256 for (;;) {
257 readByte = TUL_RD(0, 0x61);
258 if ((readByte & 0x10) == 0x10)
259 break;
260 }
261 for (;;) {
262 readByte = TUL_RD(0, 0x61);
263 if ((readByte & 0x10) != 0x10)
264 break;
265 }
266 }
267#endif
268}
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301void tul_se2_instr(WORD CurBase, UCHAR instr)
302{
303 int i;
304 UCHAR b;
305
306 TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2DO);
307 tul_se2_wait();
308 TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK | SE2DO);
309 tul_se2_wait();
310
311 for (i = 0; i < 8; i++) {
312 if (instr & 0x80)
313 b = SE2CS | SE2DO;
314 else
315 b = SE2CS;
316 TUL_WR(CurBase + TUL_NVRAM, b);
317 tul_se2_wait();
318 TUL_WR(CurBase + TUL_NVRAM, b | SE2CLK);
319 tul_se2_wait();
320 instr <<= 1;
321 }
322 TUL_WR(CurBase + TUL_NVRAM, SE2CS);
323 tul_se2_wait();
324 return;
325}
326
327
328
329
330
331
332void tul_se2_ew_en(WORD CurBase)
333{
334 tul_se2_instr(CurBase, 0x30);
335 TUL_WR(CurBase + TUL_NVRAM, 0);
336 tul_se2_wait();
337 return;
338}
339
340
341
342
343
344void tul_se2_ew_ds(WORD CurBase)
345{
346 tul_se2_instr(CurBase, 0);
347 TUL_WR(CurBase + TUL_NVRAM, 0);
348 tul_se2_wait();
349 return;
350}
351
352
353
354
355
356
357USHORT tul_se2_rd(WORD CurBase, ULONG adr)
358{
359 UCHAR instr, readByte;
360 USHORT readWord;
361 int i;
362
363 instr = (UCHAR) (adr | 0x80);
364 tul_se2_instr(CurBase, instr);
365 readWord = 0;
366
367 for (i = 15; i >= 0; i--) {
368 TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK);
369 tul_se2_wait();
370 TUL_WR(CurBase + TUL_NVRAM, SE2CS);
371
372
373 readByte = TUL_RD(CurBase, TUL_NVRAM);
374 readByte &= SE2DI;
375 readWord += (readByte << i);
376 tul_se2_wait();
377 }
378
379 TUL_WR(CurBase + TUL_NVRAM, 0);
380 tul_se2_wait();
381 return readWord;
382}
383
384
385
386
387
388void tul_se2_wr(WORD CurBase, UCHAR adr, USHORT writeWord)
389{
390 UCHAR readByte;
391 UCHAR instr;
392 int i;
393
394 instr = (UCHAR) (adr | 0x40);
395 tul_se2_instr(CurBase, instr);
396 for (i = 15; i >= 0; i--) {
397 if (writeWord & 0x8000)
398 TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2DO);
399 else
400 TUL_WR(CurBase + TUL_NVRAM, SE2CS);
401 tul_se2_wait();
402 TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK);
403 tul_se2_wait();
404 writeWord <<= 1;
405 }
406 TUL_WR(CurBase + TUL_NVRAM, SE2CS);
407 tul_se2_wait();
408 TUL_WR(CurBase + TUL_NVRAM, 0);
409 tul_se2_wait();
410
411 TUL_WR(CurBase + TUL_NVRAM, SE2CS);
412 tul_se2_wait();
413
414 for (;;) {
415 TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK);
416 tul_se2_wait();
417 TUL_WR(CurBase + TUL_NVRAM, SE2CS);
418 tul_se2_wait();
419 if ((readByte = TUL_RD(CurBase, TUL_NVRAM)) & SE2DI)
420 break;
421 }
422 TUL_WR(CurBase + TUL_NVRAM, 0);
423 return;
424}
425
426
427
428
429
430int tul_se2_rd_all(WORD CurBase)
431{
432 int i;
433 ULONG chksum = 0;
434 USHORT *np;
435
436 i91unvramp = &i91unvram;
437 np = (USHORT *) i91unvramp;
438 for (i = 0; i < 32; i++) {
439 *np++ = tul_se2_rd(CurBase, i);
440 }
441
442
443 if (i91unvramp->NVM_Signature != INI_SIGNATURE)
444 return -1;
445
446 np = (USHORT *) i91unvramp;
447 for (i = 0; i < 31; i++)
448 chksum += *np++;
449 if (i91unvramp->NVM_CheckSum != (USHORT) chksum)
450 return -1;
451 return 1;
452}
453
454
455
456
457
458void tul_se2_update_all(WORD CurBase)
459{
460 int i;
461 ULONG chksum = 0;
462 USHORT *np, *np1;
463
464 i91unvramp = &i91unvram;
465
466 np = (USHORT *) i91udftNvRam;
467 for (i = 0; i < 31; i++)
468 chksum += *np++;
469 *np = (USHORT) chksum;
470 tul_se2_ew_en(CurBase);
471
472 np = (USHORT *) i91udftNvRam;
473 np1 = (USHORT *) i91unvramp;
474 for (i = 0; i < 32; i++, np++, np1++) {
475 if (*np != *np1) {
476 tul_se2_wr(CurBase, i, *np);
477 }
478 }
479
480 tul_se2_ew_ds(CurBase);
481 return;
482}
483
484
485
486
487void tul_read_eeprom(WORD CurBase)
488{
489 UCHAR gctrl;
490
491 i91unvramp = &i91unvram;
492
493 gctrl = TUL_RD(CurBase, TUL_GCTRL);
494 TUL_WR(CurBase + TUL_GCTRL, gctrl | TUL_GCTRL_EEPROM_BIT);
495 if (tul_se2_rd_all(CurBase) != 1) {
496 tul_se2_update_all(CurBase);
497 tul_se2_rd_all(CurBase);
498 }
499
500 gctrl = TUL_RD(CurBase, TUL_GCTRL);
501 TUL_WR(CurBase + TUL_GCTRL, gctrl & ~TUL_GCTRL_EEPROM_BIT);
502}
503
504int Addi91u_into_Adapter_table(WORD wBIOS, WORD wBASE, BYTE bInterrupt,
505 BYTE bBus, BYTE bDevice)
506{
507 int i, j;
508
509 for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) {
510 if (i91u_adpt[i].ADPT_BIOS < wBIOS)
511 continue;
512 if (i91u_adpt[i].ADPT_BIOS == wBIOS) {
513 if (i91u_adpt[i].ADPT_BASE == wBASE) {
514 if (i91u_adpt[i].ADPT_Bus != 0xFF)
515 return (FAILURE);
516 } else if (i91u_adpt[i].ADPT_BASE < wBASE)
517 continue;
518 }
519 for (j = MAX_SUPPORTED_ADAPTERS - 1; j > i; j--) {
520 i91u_adpt[j].ADPT_BASE = i91u_adpt[j - 1].ADPT_BASE;
521 i91u_adpt[j].ADPT_INTR = i91u_adpt[j - 1].ADPT_INTR;
522 i91u_adpt[j].ADPT_BIOS = i91u_adpt[j - 1].ADPT_BIOS;
523 i91u_adpt[j].ADPT_Bus = i91u_adpt[j - 1].ADPT_Bus;
524 i91u_adpt[j].ADPT_Device = i91u_adpt[j - 1].ADPT_Device;
525 }
526 i91u_adpt[i].ADPT_BASE = wBASE;
527 i91u_adpt[i].ADPT_INTR = bInterrupt;
528 i91u_adpt[i].ADPT_BIOS = wBIOS;
529 i91u_adpt[i].ADPT_Bus = bBus;
530 i91u_adpt[i].ADPT_Device = bDevice;
531 return (SUCCESSFUL);
532 }
533 return (FAILURE);
534}
535
536void init_i91uAdapter_table(void)
537{
538 int i;
539
540 for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) {
541 i91u_adpt[i].ADPT_BIOS = 0xffff;
542 i91u_adpt[i].ADPT_BASE = 0xffff;
543 i91u_adpt[i].ADPT_INTR = 0xff;
544 i91u_adpt[i].ADPT_Bus = 0xff;
545 i91u_adpt[i].ADPT_Device = 0xff;
546 }
547 return;
548}
549
550void tul_stop_bm(HCS * pCurHcb)
551{
552
553 if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) {
554 TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT | TAX_X_CLR_FIFO);
555
556 while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & XABT) == 0);
557 }
558 TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
559}
560
561
562void get_tulipPCIConfig(HCS * pCurHcb, int ch_idx)
563{
564 pCurHcb->HCS_Base = i91u_adpt[ch_idx].ADPT_BASE;
565 pCurHcb->HCS_BIOS = i91u_adpt[ch_idx].ADPT_BIOS;
566 pCurHcb->HCS_Intr = i91u_adpt[ch_idx].ADPT_INTR;
567 return;
568}
569
570
571int tul_reset_scsi(HCS * pCurHcb, int seconds)
572{
573 TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_RST_BUS);
574
575 while (!((pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt)) & TSS_SCSIRST_INT));
576
577
578 TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, 0);
579
580
581
582 tul_do_pause(seconds * HZ);
583
584 TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
585
586 return (SCSI_RESET_SUCCESS);
587}
588
589
590int init_tulip(HCS * pCurHcb, SCB * scbp, int tul_num_scb, BYTE * pbBiosAdr, int seconds)
591{
592 int i;
593 BYTE *pwFlags;
594 BYTE *pbHeads;
595 SCB *pTmpScb, *pPrevScb = NULL;
596
597 pCurHcb->HCS_NumScbs = tul_num_scb;
598 pCurHcb->HCS_Semaph = 1;
599#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
600 pCurHcb->HCS_SemaphLock = SPIN_LOCK_UNLOCKED;
601#endif
602 pCurHcb->HCS_JSStatus0 = 0;
603 pCurHcb->HCS_Scb = scbp;
604 pCurHcb->HCS_NxtPend = scbp;
605 pCurHcb->HCS_NxtAvail = scbp;
606 for (i = 0, pTmpScb = scbp; i < tul_num_scb; i++, pTmpScb++) {
607 pTmpScb->SCB_TagId = i;
608 if (i != 0)
609 pPrevScb->SCB_NxtScb = pTmpScb;
610 pPrevScb = pTmpScb;
611 }
612 pPrevScb->SCB_NxtScb = NULL;
613 pCurHcb->HCS_ScbEnd = pTmpScb;
614 pCurHcb->HCS_FirstAvail = scbp;
615 pCurHcb->HCS_LastAvail = pPrevScb;
616#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
617 pCurHcb->HCS_AvailLock = SPIN_LOCK_UNLOCKED;
618#endif
619 pCurHcb->HCS_FirstPend = NULL;
620 pCurHcb->HCS_LastPend = NULL;
621 pCurHcb->HCS_FirstBusy = NULL;
622 pCurHcb->HCS_LastBusy = NULL;
623 pCurHcb->HCS_FirstDone = NULL;
624 pCurHcb->HCS_LastDone = NULL;
625 pCurHcb->HCS_ActScb = NULL;
626 pCurHcb->HCS_ActTcs = NULL;
627
628 tul_read_eeprom(pCurHcb->HCS_Base);
629
630 if (i91unvramp->NVM_SCSIInfo[0].NVM_NumOfTarg == 8)
631 pCurHcb->HCS_MaxTar = 8;
632 else
633 pCurHcb->HCS_MaxTar = 16;
634
635 pCurHcb->HCS_Config = i91unvramp->NVM_SCSIInfo[0].NVM_ChConfig1;
636
637 pCurHcb->HCS_SCSI_ID = i91unvramp->NVM_SCSIInfo[0].NVM_ChSCSIID;
638 pCurHcb->HCS_IdMask = ~(1 << pCurHcb->HCS_SCSI_ID);
639
640#if CHK_PARITY
641
642 TUL_WR(pCurHcb->HCS_Base + TUL_PCMD, TUL_RD(pCurHcb->HCS_Base, TUL_PCMD) | 0x40);
643#endif
644
645
646 TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
647
648 tul_stop_bm(pCurHcb);
649
650 TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_RST_CHIP);
651
652
653 TUL_WR(pCurHcb->HCS_Base + TUL_SScsiId, pCurHcb->HCS_SCSI_ID << 4);
654
655
656
657 if (pCurHcb->HCS_Config & HCC_EN_PAR)
658 pCurHcb->HCS_SConf1 = (TSC_INITDEFAULT | TSC_EN_SCSI_PAR);
659 else
660 pCurHcb->HCS_SConf1 = (TSC_INITDEFAULT);
661 TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurHcb->HCS_SConf1);
662
663
664 TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);
665
666 TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, 0);
667
668
669 TUL_WR(pCurHcb->HCS_Base + TUL_STimeOut, 153);
670
671
672 TUL_WR(pCurHcb->HCS_Base + TUL_XCtrl, (pCurHcb->HCS_Config & (HCC_ACT_TERM1 | HCC_ACT_TERM2)));
673 TUL_WR(pCurHcb->HCS_Base + TUL_GCTRL1,
674 ((pCurHcb->HCS_Config & HCC_AUTO_TERM) >> 4) | (TUL_RD(pCurHcb->HCS_Base, TUL_GCTRL1) & 0xFE));
675
676 for (i = 0,
677 pwFlags = & (i91unvramp->NVM_SCSIInfo[0].NVM_Targ0Config),
678 pbHeads = pbBiosAdr + 0x180;
679 i < pCurHcb->HCS_MaxTar;
680 i++, pwFlags++) {
681 pCurHcb->HCS_Tcs[i].TCS_Flags = *pwFlags & ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
682 if (pCurHcb->HCS_Tcs[i].TCS_Flags & TCF_EN_255)
683 pCurHcb->HCS_Tcs[i].TCS_DrvFlags = TCF_DRV_255_63;
684 else
685 pCurHcb->HCS_Tcs[i].TCS_DrvFlags = 0;
686 pCurHcb->HCS_Tcs[i].TCS_JS_Period = 0;
687 pCurHcb->HCS_Tcs[i].TCS_SConfig0 = pCurHcb->HCS_SConf1;
688 pCurHcb->HCS_Tcs[i].TCS_DrvHead = *pbHeads++;
689 if (pCurHcb->HCS_Tcs[i].TCS_DrvHead == 255)
690 pCurHcb->HCS_Tcs[i].TCS_DrvFlags = TCF_DRV_255_63;
691 else
692 pCurHcb->HCS_Tcs[i].TCS_DrvFlags = 0;
693 pCurHcb->HCS_Tcs[i].TCS_DrvSector = *pbHeads++;
694 pCurHcb->HCS_Tcs[i].TCS_Flags &= ~TCF_BUSY;
695 pCurHcb->HCS_ActTags[i] = 0;
696 pCurHcb->HCS_MaxTags[i] = 0xFF;
697 }
698 printk("i91u: PCI Base=0x%04X, IRQ=%d, BIOS=0x%04X0, SCSI ID=%d\n",
699 pCurHcb->HCS_Base, pCurHcb->HCS_Intr,
700 pCurHcb->HCS_BIOS, pCurHcb->HCS_SCSI_ID);
701
702 if (pCurHcb->HCS_Config & HCC_SCSI_RESET) {
703 printk("i91u: Reset SCSI Bus ... \n");
704 tul_reset_scsi(pCurHcb, seconds);
705 }
706 TUL_WR(pCurHcb->HCS_Base + TUL_SCFG1, 0x17);
707 TUL_WR(pCurHcb->HCS_Base + TUL_SIntEnable, 0xE9);
708 return (0);
709}
710
711
712SCB *tul_alloc_scb(HCS * hcsp)
713{
714 SCB *pTmpScb;
715 ULONG flags;
716#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
717 spin_lock_irqsave(&(hcsp->HCS_AvailLock), flags);
718#else
719 save_flags(flags);
720 cli();
721#endif
722 if ((pTmpScb = hcsp->HCS_FirstAvail) != NULL) {
723#if DEBUG_QUEUE
724 printk("find scb at %08lx\n", (ULONG) pTmpScb);
725#endif
726 if ((hcsp->HCS_FirstAvail = pTmpScb->SCB_NxtScb) == NULL)
727 hcsp->HCS_LastAvail = NULL;
728 pTmpScb->SCB_NxtScb = NULL;
729 pTmpScb->SCB_Status = SCB_RENT;
730 }
731#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
732 spin_unlock_irqrestore(&(hcsp->HCS_AvailLock), flags);
733#else
734 restore_flags(flags);
735#endif
736 return (pTmpScb);
737}
738
739
740void tul_release_scb(HCS * hcsp, SCB * scbp)
741{
742 ULONG flags;
743
744#if DEBUG_QUEUE
745 printk("Release SCB %lx; ", (ULONG) scbp);
746#endif
747#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
748 spin_lock_irqsave(&(hcsp->HCS_AvailLock), flags);
749#else
750 save_flags(flags);
751 cli();
752#endif
753 scbp->SCB_Srb = 0;
754 scbp->SCB_Status = 0;
755 scbp->SCB_NxtScb = NULL;
756 if (hcsp->HCS_LastAvail != NULL) {
757 hcsp->HCS_LastAvail->SCB_NxtScb = scbp;
758 hcsp->HCS_LastAvail = scbp;
759 } else {
760 hcsp->HCS_FirstAvail = scbp;
761 hcsp->HCS_LastAvail = scbp;
762 }
763#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
764 spin_unlock_irqrestore(&(hcsp->HCS_AvailLock), flags);
765#else
766 restore_flags(flags);
767#endif
768}
769
770
771void tul_append_pend_scb(HCS * pCurHcb, SCB * scbp)
772{
773
774#if DEBUG_QUEUE
775 printk("Append pend SCB %lx; ", (ULONG) scbp);
776#endif
777 scbp->SCB_Status = SCB_PEND;
778 scbp->SCB_NxtScb = NULL;
779 if (pCurHcb->HCS_LastPend != NULL) {
780 pCurHcb->HCS_LastPend->SCB_NxtScb = scbp;
781 pCurHcb->HCS_LastPend = scbp;
782 } else {
783 pCurHcb->HCS_FirstPend = scbp;
784 pCurHcb->HCS_LastPend = scbp;
785 }
786}
787
788
789void tul_push_pend_scb(HCS * pCurHcb, SCB * scbp)
790{
791
792#if DEBUG_QUEUE
793 printk("Push pend SCB %lx; ", (ULONG) scbp);
794#endif
795 scbp->SCB_Status = SCB_PEND;
796 if ((scbp->SCB_NxtScb = pCurHcb->HCS_FirstPend) != NULL) {
797 pCurHcb->HCS_FirstPend = scbp;
798 } else {
799 pCurHcb->HCS_FirstPend = scbp;
800 pCurHcb->HCS_LastPend = scbp;
801 }
802}
803
804
805SCB *tul_find_first_pend_scb(HCS * pCurHcb)
806{
807 SCB *pFirstPend;
808
809
810 pFirstPend = pCurHcb->HCS_FirstPend;
811 while (pFirstPend != NULL) {
812 if (pFirstPend->SCB_Opcode != ExecSCSI) {
813 return (pFirstPend);
814 }
815 if (pFirstPend->SCB_TagMsg == 0) {
816 if ((pCurHcb->HCS_ActTags[pFirstPend->SCB_Target] == 0) &&
817 !(pCurHcb->HCS_Tcs[pFirstPend->SCB_Target].TCS_Flags & TCF_BUSY)) {
818 return (pFirstPend);
819 }
820 } else {
821 if ((pCurHcb->HCS_ActTags[pFirstPend->SCB_Target] >=
822 pCurHcb->HCS_MaxTags[pFirstPend->SCB_Target]) |
823 (pCurHcb->HCS_Tcs[pFirstPend->SCB_Target].TCS_Flags & TCF_BUSY)) {
824 pFirstPend = pFirstPend->SCB_NxtScb;
825 continue;
826 }
827 return (pFirstPend);
828 }
829 pFirstPend = pFirstPend->SCB_NxtScb;
830 }
831
832
833 return (pFirstPend);
834}
835
836SCB *tul_pop_pend_scb(HCS * pCurHcb)
837{
838 SCB *pTmpScb;
839
840 if ((pTmpScb = pCurHcb->HCS_FirstPend) != NULL) {
841 if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL)
842 pCurHcb->HCS_LastPend = NULL;
843 pTmpScb->SCB_NxtScb = NULL;
844 }
845#if DEBUG_QUEUE
846 printk("Pop pend SCB %lx; ", (ULONG) pTmpScb);
847#endif
848 return (pTmpScb);
849}
850
851
852
853void tul_unlink_pend_scb(HCS * pCurHcb, SCB * pCurScb)
854{
855 SCB *pTmpScb, *pPrevScb;
856
857#if DEBUG_QUEUE
858 printk("unlink pend SCB %lx; ", (ULONG) pCurScb);
859#endif
860
861 pPrevScb = pTmpScb = pCurHcb->HCS_FirstPend;
862 while (pTmpScb != NULL) {
863 if (pCurScb == pTmpScb) {
864 if (pTmpScb == pCurHcb->HCS_FirstPend) {
865 if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL)
866 pCurHcb->HCS_LastPend = NULL;
867 } else {
868 pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
869 if (pTmpScb == pCurHcb->HCS_LastPend)
870 pCurHcb->HCS_LastPend = pPrevScb;
871 }
872 pTmpScb->SCB_NxtScb = NULL;
873 break;
874 }
875 pPrevScb = pTmpScb;
876 pTmpScb = pTmpScb->SCB_NxtScb;
877 }
878 return;
879}
880
881void tul_append_busy_scb(HCS * pCurHcb, SCB * scbp)
882{
883
884#if DEBUG_QUEUE
885 printk("append busy SCB %lx; ", (ULONG) scbp);
886#endif
887 if (scbp->SCB_TagMsg)
888 pCurHcb->HCS_ActTags[scbp->SCB_Target]++;
889 else
890 pCurHcb->HCS_Tcs[scbp->SCB_Target].TCS_Flags |= TCF_BUSY;
891 scbp->SCB_Status = SCB_BUSY;
892 scbp->SCB_NxtScb = NULL;
893 if (pCurHcb->HCS_LastBusy != NULL) {
894 pCurHcb->HCS_LastBusy->SCB_NxtScb = scbp;
895 pCurHcb->HCS_LastBusy = scbp;
896 } else {
897 pCurHcb->HCS_FirstBusy = scbp;
898 pCurHcb->HCS_LastBusy = scbp;
899 }
900}
901
902
903SCB *tul_pop_busy_scb(HCS * pCurHcb)
904{
905 SCB *pTmpScb;
906
907
908 if ((pTmpScb = pCurHcb->HCS_FirstBusy) != NULL) {
909 if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)
910 pCurHcb->HCS_LastBusy = NULL;
911 pTmpScb->SCB_NxtScb = NULL;
912 if (pTmpScb->SCB_TagMsg)
913 pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--;
914 else
915 pCurHcb->HCS_Tcs[pTmpScb->SCB_Target].TCS_Flags &= ~TCF_BUSY;
916 }
917#if DEBUG_QUEUE
918 printk("Pop busy SCB %lx; ", (ULONG) pTmpScb);
919#endif
920 return (pTmpScb);
921}
922
923
924void tul_unlink_busy_scb(HCS * pCurHcb, SCB * pCurScb)
925{
926 SCB *pTmpScb, *pPrevScb;
927
928#if DEBUG_QUEUE
929 printk("unlink busy SCB %lx; ", (ULONG) pCurScb);
930#endif
931
932 pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy;
933 while (pTmpScb != NULL) {
934 if (pCurScb == pTmpScb) {
935 if (pTmpScb == pCurHcb->HCS_FirstBusy) {
936 if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)
937 pCurHcb->HCS_LastBusy = NULL;
938 } else {
939 pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
940 if (pTmpScb == pCurHcb->HCS_LastBusy)
941 pCurHcb->HCS_LastBusy = pPrevScb;
942 }
943 pTmpScb->SCB_NxtScb = NULL;
944 if (pTmpScb->SCB_TagMsg)
945 pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--;
946 else
947 pCurHcb->HCS_Tcs[pTmpScb->SCB_Target].TCS_Flags &= ~TCF_BUSY;
948 break;
949 }
950 pPrevScb = pTmpScb;
951 pTmpScb = pTmpScb->SCB_NxtScb;
952 }
953 return;
954}
955
956
957SCB *tul_find_busy_scb(HCS * pCurHcb, WORD tarlun)
958{
959 SCB *pTmpScb, *pPrevScb;
960 WORD scbp_tarlun;
961
962
963 pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy;
964 while (pTmpScb != NULL) {
965 scbp_tarlun = (pTmpScb->SCB_Lun << 8) | (pTmpScb->SCB_Target);
966 if (scbp_tarlun == tarlun) {
967 break;
968 }
969 pPrevScb = pTmpScb;
970 pTmpScb = pTmpScb->SCB_NxtScb;
971 }
972#if DEBUG_QUEUE
973 printk("find busy SCB %lx; ", (ULONG) pTmpScb);
974#endif
975 return (pTmpScb);
976}
977
978
979void tul_append_done_scb(HCS * pCurHcb, SCB * scbp)
980{
981
982#if DEBUG_QUEUE
983 printk("append done SCB %lx; ", (ULONG) scbp);
984#endif
985
986 scbp->SCB_Status = SCB_DONE;
987 scbp->SCB_NxtScb = NULL;
988 if (pCurHcb->HCS_LastDone != NULL) {
989 pCurHcb->HCS_LastDone->SCB_NxtScb = scbp;
990 pCurHcb->HCS_LastDone = scbp;
991 } else {
992 pCurHcb->HCS_FirstDone = scbp;
993 pCurHcb->HCS_LastDone = scbp;
994 }
995}
996
997
998SCB *tul_find_done_scb(HCS * pCurHcb)
999{
1000 SCB *pTmpScb;
1001
1002
1003 if ((pTmpScb = pCurHcb->HCS_FirstDone) != NULL) {
1004 if ((pCurHcb->HCS_FirstDone = pTmpScb->SCB_NxtScb) == NULL)
1005 pCurHcb->HCS_LastDone = NULL;
1006 pTmpScb->SCB_NxtScb = NULL;
1007 }
1008#if DEBUG_QUEUE
1009 printk("find done SCB %lx; ", (ULONG) pTmpScb);
1010#endif
1011 return (pTmpScb);
1012}
1013
1014
1015int tul_abort_srb(HCS * pCurHcb, ULONG srbp)
1016{
1017 ULONG flags;
1018 SCB *pTmpScb, *pPrevScb;
1019
1020#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1021 spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
1022#else
1023 save_flags(flags);
1024 cli();
1025#endif
1026
1027 if ((pCurHcb->HCS_Semaph == 0) && (pCurHcb->HCS_ActScb == NULL)) {
1028 TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
1029
1030
1031#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1032 spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1033#endif
1034
1035 tulip_main(pCurHcb);
1036
1037#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1038 spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
1039#endif
1040
1041 pCurHcb->HCS_Semaph = 1;
1042 TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
1043
1044#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1045 spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1046#else
1047 restore_flags(flags);
1048#endif
1049
1050 return SCSI_ABORT_SNOOZE;
1051 }
1052 pPrevScb = pTmpScb = pCurHcb->HCS_FirstPend;
1053 while (pTmpScb != NULL) {
1054
1055 if (pTmpScb->SCB_Srb == (unsigned char *) srbp) {
1056 if (pTmpScb == pCurHcb->HCS_ActScb) {
1057#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1058 spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1059#else
1060 restore_flags(flags);
1061#endif
1062 return SCSI_ABORT_BUSY;
1063 } else if (pTmpScb == pCurHcb->HCS_FirstPend) {
1064 if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL)
1065 pCurHcb->HCS_LastPend = NULL;
1066 } else {
1067 pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
1068 if (pTmpScb == pCurHcb->HCS_LastPend)
1069 pCurHcb->HCS_LastPend = pPrevScb;
1070 }
1071 pTmpScb->SCB_HaStat = HOST_ABORTED;
1072 pTmpScb->SCB_Flags |= SCF_DONE;
1073 if (pTmpScb->SCB_Flags & SCF_POST)
1074 (*pTmpScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pTmpScb);
1075#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1076 spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1077#else
1078 restore_flags(flags);
1079#endif
1080 return SCSI_ABORT_SUCCESS;
1081 }
1082 pPrevScb = pTmpScb;
1083 pTmpScb = pTmpScb->SCB_NxtScb;
1084 }
1085
1086 pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy;
1087 while (pTmpScb != NULL) {
1088
1089 if (pTmpScb->SCB_Srb == (unsigned char *) srbp) {
1090
1091 if (pTmpScb == pCurHcb->HCS_ActScb) {
1092#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1093 spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1094#else
1095 restore_flags(flags);
1096#endif
1097 return SCSI_ABORT_BUSY;
1098 } else if (pTmpScb->SCB_TagMsg == 0) {
1099#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1100 spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1101#else
1102 restore_flags(flags);
1103#endif
1104 return SCSI_ABORT_BUSY;
1105 } else {
1106 pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--;
1107 if (pTmpScb == pCurHcb->HCS_FirstBusy) {
1108 if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)
1109 pCurHcb->HCS_LastBusy = NULL;
1110 } else {
1111 pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
1112 if (pTmpScb == pCurHcb->HCS_LastBusy)
1113 pCurHcb->HCS_LastBusy = pPrevScb;
1114 }
1115 pTmpScb->SCB_NxtScb = NULL;
1116
1117
1118 pTmpScb->SCB_HaStat = HOST_ABORTED;
1119 pTmpScb->SCB_Flags |= SCF_DONE;
1120 if (pTmpScb->SCB_Flags & SCF_POST)
1121 (*pTmpScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pTmpScb);
1122#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1123 spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1124#else
1125 restore_flags(flags);
1126#endif
1127 return SCSI_ABORT_SUCCESS;
1128 }
1129 }
1130 pPrevScb = pTmpScb;
1131 pTmpScb = pTmpScb->SCB_NxtScb;
1132 }
1133#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1134 spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1135#else
1136 restore_flags(flags);
1137#endif
1138 return (SCSI_ABORT_NOT_RUNNING);
1139}
1140
1141
1142int tul_bad_seq(HCS * pCurHcb)
1143{
1144 SCB *pCurScb;
1145
1146 printk("tul_bad_seg c=%d\n", pCurHcb->HCS_Index);
1147
1148 if ((pCurScb = pCurHcb->HCS_ActScb) != NULL) {
1149 tul_unlink_busy_scb(pCurHcb, pCurScb);
1150 pCurScb->SCB_HaStat = HOST_BAD_PHAS;
1151 pCurScb->SCB_TaStat = 0;
1152 tul_append_done_scb(pCurHcb, pCurScb);
1153 }
1154 tul_stop_bm(pCurHcb);
1155
1156 tul_reset_scsi(pCurHcb, 8);
1157
1158 return (tul_post_scsi_rst(pCurHcb));
1159}
1160
1161
1162int tul_device_reset(HCS * pCurHcb, ULONG pSrb, unsigned int target, unsigned int ResetFlags)
1163{
1164 ULONG flags;
1165 SCB *pScb;
1166#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1167 spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
1168#else
1169 save_flags(flags);
1170 cli();
1171#endif
1172
1173 if (ResetFlags & SCSI_RESET_ASYNCHRONOUS) {
1174
1175 if ((pCurHcb->HCS_Semaph == 0) && (pCurHcb->HCS_ActScb == NULL)) {
1176 TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
1177
1178
1179#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1180 spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1181#endif
1182
1183 tulip_main(pCurHcb);
1184
1185#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1186 spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
1187#endif
1188
1189 pCurHcb->HCS_Semaph = 1;
1190 TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
1191
1192#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1193 spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1194#else
1195 restore_flags(flags);
1196#endif
1197
1198 return SCSI_RESET_SNOOZE;
1199 }
1200 pScb = pCurHcb->HCS_FirstBusy;
1201 while (pScb != NULL) {
1202 if (pScb->SCB_Srb == (unsigned char *) pSrb)
1203 break;
1204 pScb = pScb->SCB_NxtScb;
1205 }
1206 if (pScb == NULL) {
1207 printk("Unable to Reset - No SCB Found\n");
1208
1209#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1210 spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1211#else
1212 restore_flags(flags);
1213#endif
1214 return SCSI_RESET_NOT_RUNNING;
1215 }
1216 }
1217 if ((pScb = tul_alloc_scb(pCurHcb)) == NULL) {
1218#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1219 spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1220#else
1221 restore_flags(flags);
1222#endif
1223 return SCSI_RESET_NOT_RUNNING;
1224 }
1225 pScb->SCB_Opcode = BusDevRst;
1226 pScb->SCB_Flags = SCF_POST;
1227 pScb->SCB_Target = target;
1228 pScb->SCB_Mode = 0;
1229
1230 pScb->SCB_Srb = 0;
1231 if (ResetFlags & SCSI_RESET_SYNCHRONOUS) {
1232 pScb->SCB_Srb = (unsigned char *) pSrb;
1233 }
1234 tul_push_pend_scb(pCurHcb, pScb);
1235
1236 if (pCurHcb->HCS_Semaph == 1) {
1237 TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
1238
1239 pCurHcb->HCS_Semaph = 0;
1240
1241#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1242 spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1243#endif
1244
1245 tulip_main(pCurHcb);
1246
1247#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1248 spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
1249#endif
1250
1251 pCurHcb->HCS_Semaph = 1;
1252 TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
1253 }
1254#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1255 spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1256#else
1257 restore_flags(flags);
1258#endif
1259 return SCSI_RESET_PENDING;
1260}
1261
1262int tul_reset_scsi_bus(HCS * pCurHcb)
1263{
1264 ULONG flags;
1265
1266#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1267 spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
1268#else
1269 save_flags(flags);
1270 cli();
1271#endif
1272 TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
1273 pCurHcb->HCS_Semaph = 0;
1274
1275#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1276 spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1277#else
1278 restore_flags(flags);
1279#endif
1280
1281 tul_stop_bm(pCurHcb);
1282
1283 tul_reset_scsi(pCurHcb, 2);
1284
1285#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1286 spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
1287#else
1288 save_flags(flags);
1289 cli();
1290#endif
1291 tul_post_scsi_rst(pCurHcb);
1292
1293#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1294 spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1295#endif
1296
1297 tulip_main(pCurHcb);
1298
1299#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1300 spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
1301#endif
1302
1303 pCurHcb->HCS_Semaph = 1;
1304 TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
1305#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1306 spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1307#else
1308 restore_flags(flags);
1309#endif
1310 return (SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET);
1311}
1312
1313
1314void tul_exec_scb(HCS * pCurHcb, SCB * pCurScb)
1315{
1316 ULONG flags;
1317
1318 pCurScb->SCB_Mode = 0;
1319
1320 pCurScb->SCB_SGIdx = 0;
1321 pCurScb->SCB_SGMax = pCurScb->SCB_SGLen;
1322
1323#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1324 spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
1325#else
1326 save_flags(flags);
1327 cli();
1328#endif
1329
1330 tul_append_pend_scb(pCurHcb, pCurScb);
1331
1332
1333 if (pCurHcb->HCS_Semaph == 1) {
1334 TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
1335
1336 pCurHcb->HCS_Semaph = 0;
1337
1338#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1339 spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1340#endif
1341
1342 tulip_main(pCurHcb);
1343
1344#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1345 spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
1346#endif
1347
1348 pCurHcb->HCS_Semaph = 1;
1349 TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
1350 }
1351#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1352 spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1353#else
1354 restore_flags(flags);
1355#endif
1356 return;
1357}
1358
1359
1360int tul_isr(HCS * pCurHcb)
1361{
1362
1363
1364 if (TUL_RD(pCurHcb->HCS_Base, TUL_Int) & TSS_INT_PENDING) {
1365 if (pCurHcb->HCS_Semaph == 1) {
1366 TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
1367
1368 pCurHcb->HCS_Semaph = 0;
1369
1370 tulip_main(pCurHcb);
1371
1372 pCurHcb->HCS_Semaph = 1;
1373 TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
1374 return (1);
1375 }
1376 }
1377 return (0);
1378}
1379
1380
1381int tulip_main(HCS * pCurHcb)
1382{
1383 SCB *pCurScb;
1384
1385 for (;;) {
1386
1387 tulip_scsi(pCurHcb);
1388
1389 while ((pCurScb = tul_find_done_scb(pCurHcb)) != NULL) {
1390 if (pCurScb->SCB_TaStat == QUEUE_FULL) {
1391 pCurHcb->HCS_MaxTags[pCurScb->SCB_Target] =
1392 pCurHcb->HCS_ActTags[pCurScb->SCB_Target] - 1;
1393 pCurScb->SCB_TaStat = 0;
1394 tul_append_pend_scb(pCurHcb, pCurScb);
1395 continue;
1396 }
1397 if (!(pCurScb->SCB_Mode & SCM_RSENS)) {
1398 if (pCurScb->SCB_TaStat == 2) {
1399
1400
1401
1402 if (pCurScb->SCB_Flags & SCF_SENSE) {
1403 BYTE len;
1404 len = pCurScb->SCB_SenseLen;
1405 if (len == 0)
1406 len = 1;
1407 pCurScb->SCB_BufLen = pCurScb->SCB_SenseLen;
1408 pCurScb->SCB_BufPtr = pCurScb->SCB_SensePtr;
1409 pCurScb->SCB_Flags &= ~(SCF_SG | SCF_DIR);
1410
1411
1412
1413 pCurScb->SCB_Mode = SCM_RSENS;
1414 pCurScb->SCB_Ident &= 0xBF;
1415 pCurScb->SCB_TagMsg = 0;
1416 pCurScb->SCB_TaStat = 0;
1417 pCurScb->SCB_CDBLen = 6;
1418 pCurScb->SCB_CDB[0] = SCSICMD_RequestSense;
1419 pCurScb->SCB_CDB[1] = 0;
1420 pCurScb->SCB_CDB[2] = 0;
1421 pCurScb->SCB_CDB[3] = 0;
1422 pCurScb->SCB_CDB[4] = len;
1423 pCurScb->SCB_CDB[5] = 0;
1424 tul_push_pend_scb(pCurHcb, pCurScb);
1425 break;
1426 }
1427 }
1428 } else {
1429
1430 if (pCurScb->SCB_TaStat == 2) {
1431
1432 pCurScb->SCB_HaStat = HOST_BAD_PHAS;
1433 }
1434 pCurScb->SCB_TaStat = 2;
1435 }
1436 pCurScb->SCB_Flags |= SCF_DONE;
1437 if (pCurScb->SCB_Flags & SCF_POST) {
1438 (*pCurScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pCurScb);
1439 }
1440 }
1441
1442
1443 if (TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0) & TSS_INT_PENDING)
1444 continue;
1445
1446 if (pCurHcb->HCS_ActScb) {
1447 return 1;
1448 }
1449
1450 if (tul_find_first_pend_scb(pCurHcb) == NULL) {
1451 return 1;
1452 }
1453 }
1454
1455}
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467void tulip_scsi(HCS * pCurHcb)
1468{
1469 SCB *pCurScb;
1470 TCS *pCurTcb;
1471
1472
1473
1474 if ((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0)) & TSS_INT_PENDING) {
1475
1476 pCurHcb->HCS_Phase = pCurHcb->HCS_JSStatus0 & TSS_PH_MASK;
1477 pCurHcb->HCS_JSStatus1 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1);
1478 pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
1479 if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) {
1480 int_tul_scsi_rst(pCurHcb);
1481 return;
1482 }
1483 if (pCurHcb->HCS_JSInt & TSS_RESEL_INT) {
1484 if (int_tul_resel(pCurHcb) == 0)
1485 tul_next_state(pCurHcb);
1486 return;
1487 }
1488 if (pCurHcb->HCS_JSInt & TSS_SEL_TIMEOUT) {
1489 int_tul_busfree(pCurHcb);
1490 return;
1491 }
1492 if (pCurHcb->HCS_JSInt & TSS_DISC_INT) {
1493 int_tul_busfree(pCurHcb);
1494 return;
1495 }
1496 if (pCurHcb->HCS_JSInt & (TSS_FUNC_COMP | TSS_BUS_SERV)) {
1497 if ((pCurScb = pCurHcb->HCS_ActScb) != NULL)
1498 tul_next_state(pCurHcb);
1499 return;
1500 }
1501 }
1502 if (pCurHcb->HCS_ActScb != NULL)
1503 return;
1504
1505 if ((pCurScb = tul_find_first_pend_scb(pCurHcb)) == NULL)
1506 return;
1507
1508
1509 TUL_WR(pCurHcb->HCS_Base + TUL_SScsiId,
1510 (pCurHcb->HCS_SCSI_ID << 4) | (pCurScb->SCB_Target & 0x0F));
1511 if (pCurScb->SCB_Opcode == ExecSCSI) {
1512 pCurTcb = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target];
1513
1514 if (pCurScb->SCB_TagMsg)
1515 pCurTcb->TCS_DrvFlags |= TCF_DRV_EN_TAG;
1516 else
1517 pCurTcb->TCS_DrvFlags &= ~TCF_DRV_EN_TAG;
1518
1519 TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurTcb->TCS_JS_Period);
1520 if ((pCurTcb->TCS_Flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) {
1521 tul_select_atn_stop(pCurHcb, pCurScb);
1522 } else {
1523 if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {
1524 tul_select_atn_stop(pCurHcb, pCurScb);
1525 } else {
1526 if (pCurScb->SCB_TagMsg)
1527 tul_select_atn3(pCurHcb, pCurScb);
1528 else
1529 tul_select_atn(pCurHcb, pCurScb);
1530 }
1531 }
1532 if (pCurScb->SCB_Flags & SCF_POLL) {
1533 while (wait_tulip(pCurHcb) != -1) {
1534 if (tul_next_state(pCurHcb) == -1)
1535 break;
1536 }
1537 }
1538 } else if (pCurScb->SCB_Opcode == BusDevRst) {
1539 tul_select_atn_stop(pCurHcb, pCurScb);
1540 pCurScb->SCB_NxtStat = 8;
1541 if (pCurScb->SCB_Flags & SCF_POLL) {
1542 while (wait_tulip(pCurHcb) != -1) {
1543 if (tul_next_state(pCurHcb) == -1)
1544 break;
1545 }
1546 }
1547 } else if (pCurScb->SCB_Opcode == AbortCmd) {
1548 ULONG srbp;
1549
1550 srbp = (ULONG) pCurScb->SCB_Srb;
1551
1552 if (tul_abort_srb(pCurHcb, srbp) != 0) {
1553
1554
1555 tul_unlink_pend_scb(pCurHcb, pCurScb);
1556
1557 tul_release_scb(pCurHcb, pCurScb);
1558 } else {
1559 pCurScb->SCB_Opcode = BusDevRst;
1560 tul_select_atn_stop(pCurHcb, pCurScb);
1561 pCurScb->SCB_NxtStat = 8;
1562 }
1563
1564
1565 } else {
1566 tul_unlink_pend_scb(pCurHcb, pCurScb);
1567 pCurScb->SCB_HaStat = 0x16;
1568 tul_append_done_scb(pCurHcb, pCurScb);
1569 }
1570 return;
1571}
1572
1573
1574
1575int tul_next_state(HCS * pCurHcb)
1576{
1577 int next;
1578
1579 next = pCurHcb->HCS_ActScb->SCB_NxtStat;
1580 for (;;) {
1581 switch (next) {
1582 case 1:
1583 next = tul_state_1(pCurHcb);
1584 break;
1585 case 2:
1586 next = tul_state_2(pCurHcb);
1587 break;
1588 case 3:
1589 next = tul_state_3(pCurHcb);
1590 break;
1591 case 4:
1592 next = tul_state_4(pCurHcb);
1593 break;
1594 case 5:
1595 next = tul_state_5(pCurHcb);
1596 break;
1597 case 6:
1598 next = tul_state_6(pCurHcb);
1599 break;
1600 case 7:
1601 next = tul_state_7(pCurHcb);
1602 break;
1603 case 8:
1604 return (tul_bus_device_reset(pCurHcb));
1605 default:
1606 return (tul_bad_seq(pCurHcb));
1607 }
1608 if (next <= 0)
1609 return next;
1610 }
1611}
1612
1613
1614
1615
1616int tul_state_1(HCS * pCurHcb)
1617{
1618 SCB *pCurScb = pCurHcb->HCS_ActScb;
1619 TCS *pCurTcb = pCurHcb->HCS_ActTcs;
1620#if DEBUG_STATE
1621 printk("-s1-");
1622#endif
1623
1624 tul_unlink_pend_scb(pCurHcb, pCurScb);
1625 tul_append_busy_scb(pCurHcb, pCurScb);
1626
1627 TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0);
1628
1629 if (pCurHcb->HCS_Phase == MSG_OUT) {
1630
1631 TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, (TSC_EN_BUS_IN | TSC_HW_RESELECT));
1632
1633 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_Ident);
1634
1635 if (pCurScb->SCB_TagMsg) {
1636 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagMsg);
1637 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagId);
1638 }
1639 if ((pCurTcb->TCS_Flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) {
1640
1641 pCurTcb->TCS_Flags |= TCF_WDTR_DONE;
1642
1643 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
1644 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 2);
1645 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);
1646 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1);
1647 } else if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {
1648
1649 pCurTcb->TCS_Flags |= TCF_SYNC_DONE;
1650
1651 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
1652 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);
1653 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1);
1654 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, tul_rate_tbl[pCurTcb->TCS_Flags & TCF_SCSI_RATE]);
1655 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MAX_OFFSET);
1656 }
1657 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
1658 if (wait_tulip(pCurHcb) == -1)
1659 return (-1);
1660 }
1661 TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
1662 TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)));
1663 return (3);
1664}
1665
1666
1667
1668
1669
1670int tul_state_2(HCS * pCurHcb)
1671{
1672 SCB *pCurScb = pCurHcb->HCS_ActScb;
1673 TCS *pCurTcb = pCurHcb->HCS_ActTcs;
1674#if DEBUG_STATE
1675 printk("-s2-");
1676#endif
1677
1678 tul_unlink_pend_scb(pCurHcb, pCurScb);
1679 tul_append_busy_scb(pCurHcb, pCurScb);
1680
1681 TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0);
1682
1683 if (pCurHcb->HCS_JSStatus1 & TSS_CMD_PH_CMP) {
1684 return (4);
1685 }
1686 TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
1687 TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)));
1688 return (3);
1689}
1690
1691
1692
1693int tul_state_3(HCS * pCurHcb)
1694{
1695 SCB *pCurScb = pCurHcb->HCS_ActScb;
1696 TCS *pCurTcb = pCurHcb->HCS_ActTcs;
1697 int i;
1698
1699#if DEBUG_STATE
1700 printk("-s3-");
1701#endif
1702 for (;;) {
1703 switch (pCurHcb->HCS_Phase) {
1704 case CMD_OUT:
1705 for (i = 0; i < (int) pCurScb->SCB_CDBLen; i++)
1706 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_CDB[i]);
1707 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
1708 if (wait_tulip(pCurHcb) == -1)
1709 return (-1);
1710 if (pCurHcb->HCS_Phase == CMD_OUT) {
1711 return (tul_bad_seq(pCurHcb));
1712 }
1713 return (4);
1714
1715 case MSG_IN:
1716 pCurScb->SCB_NxtStat = 3;
1717 if (tul_msgin(pCurHcb) == -1)
1718 return (-1);
1719 break;
1720
1721 case STATUS_IN:
1722 if (tul_status_msg(pCurHcb) == -1)
1723 return (-1);
1724 break;
1725
1726 case MSG_OUT:
1727 if (pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) {
1728
1729 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP);
1730 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
1731 if (wait_tulip(pCurHcb) == -1)
1732 return (-1);
1733
1734 } else {
1735 pCurTcb->TCS_Flags |= TCF_SYNC_DONE;
1736
1737 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
1738 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);
1739 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1);
1740 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, tul_rate_tbl[pCurTcb->TCS_Flags & TCF_SCSI_RATE]);
1741 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MAX_OFFSET);
1742 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
1743 if (wait_tulip(pCurHcb) == -1)
1744 return (-1);
1745 TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
1746 TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7));
1747
1748 }
1749 break;
1750
1751 default:
1752 return (tul_bad_seq(pCurHcb));
1753 }
1754 }
1755}
1756
1757
1758
1759int tul_state_4(HCS * pCurHcb)
1760{
1761 SCB *pCurScb = pCurHcb->HCS_ActScb;
1762
1763#if DEBUG_STATE
1764 printk("-s4-");
1765#endif
1766 if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_NO_XF) {
1767 return (6);
1768 }
1769 for (;;) {
1770 if (pCurScb->SCB_BufLen == 0)
1771 return (6);
1772
1773 switch (pCurHcb->HCS_Phase) {
1774
1775 case STATUS_IN:
1776 if ((pCurScb->SCB_Flags & SCF_DIR) != 0) {
1777 pCurScb->SCB_HaStat = HOST_DO_DU;
1778 }
1779 if ((tul_status_msg(pCurHcb)) == -1)
1780 return (-1);
1781 break;
1782
1783 case MSG_IN:
1784 pCurScb->SCB_NxtStat = 0x4;
1785 if (tul_msgin(pCurHcb) == -1)
1786 return (-1);
1787 break;
1788
1789 case MSG_OUT:
1790 if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) {
1791 pCurScb->SCB_BufLen = 0;
1792 pCurScb->SCB_HaStat = HOST_DO_DU;
1793 if (tul_msgout_ide(pCurHcb) == -1)
1794 return (-1);
1795 return (6);
1796 } else {
1797 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP);
1798 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
1799 if (wait_tulip(pCurHcb) == -1)
1800 return (-1);
1801 }
1802 break;
1803
1804 case DATA_IN:
1805 return (tul_xfer_data_in(pCurHcb));
1806
1807 case DATA_OUT:
1808 return (tul_xfer_data_out(pCurHcb));
1809
1810 default:
1811 return (tul_bad_seq(pCurHcb));
1812 }
1813 }
1814}
1815
1816
1817
1818
1819int tul_state_5(HCS * pCurHcb)
1820{
1821 SCB *pCurScb = pCurHcb->HCS_ActScb;
1822 long cnt, xcnt;
1823
1824#if DEBUG_STATE
1825 printk("-s5-");
1826#endif
1827
1828
1829 cnt = TUL_RDLONG(pCurHcb->HCS_Base, TUL_SCnt0) & 0x0FFFFFF;
1830
1831 if (TUL_RD(pCurHcb->HCS_Base, TUL_XCmd) & 0x20) {
1832
1833
1834 if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) {
1835 pCurScb->SCB_HaStat = HOST_DO_DU;
1836 }
1837 if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) {
1838
1839 TUL_WR(pCurHcb->HCS_Base + TUL_XCtrl, TUL_RD(pCurHcb->HCS_Base, TUL_XCtrl) | 0x80);
1840
1841 while (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND);
1842 }
1843 } else {
1844
1845 if ((TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1) & TSS_XFER_CMP) == 0) {
1846 if (pCurHcb->HCS_ActTcs->TCS_JS_Period & TSC_WIDE_SCSI)
1847 cnt += (TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F) << 1;
1848 else
1849 cnt += (TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F);
1850 }
1851 if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) {
1852 TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT);
1853
1854 while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & XABT) == 0);
1855 }
1856 if ((cnt == 1) && (pCurHcb->HCS_Phase == DATA_OUT)) {
1857 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
1858 if (wait_tulip(pCurHcb) == -1) {
1859 return (-1);
1860 }
1861 cnt = 0;
1862 } else {
1863 if ((TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1) & TSS_XFER_CMP) == 0)
1864 TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
1865 }
1866 }
1867
1868 if (cnt == 0) {
1869 pCurScb->SCB_BufLen = 0;
1870 return (6);
1871 }
1872
1873 xcnt = (long) pCurScb->SCB_BufLen - cnt;
1874 pCurScb->SCB_BufLen = (U32) cnt;
1875 if (pCurScb->SCB_Flags & SCF_SG) {
1876 register SG *sgp;
1877 ULONG i;
1878
1879 sgp = &pCurScb->SCB_SGList[pCurScb->SCB_SGIdx];
1880 for (i = pCurScb->SCB_SGIdx; i < pCurScb->SCB_SGMax; sgp++, i++) {
1881 xcnt -= (long) sgp->SG_Len;
1882 if (xcnt < 0) {
1883 xcnt += (long) sgp->SG_Len;
1884 sgp->SG_Ptr += (U32) xcnt;
1885 sgp->SG_Len -= (U32) xcnt;
1886 pCurScb->SCB_BufPtr += ((U32) (i - pCurScb->SCB_SGIdx) << 3);
1887
1888 pCurScb->SCB_SGLen = (BYTE) (pCurScb->SCB_SGMax - i);
1889
1890 pCurScb->SCB_SGIdx = (WORD) i;
1891
1892 return (4);
1893 }
1894
1895 }
1896 return (6);
1897 } else {
1898 pCurScb->SCB_BufPtr += (U32) xcnt;
1899 }
1900 return (4);
1901}
1902
1903
1904
1905int tul_state_6(HCS * pCurHcb)
1906{
1907 SCB *pCurScb = pCurHcb->HCS_ActScb;
1908
1909#if DEBUG_STATE
1910 printk("-s6-");
1911#endif
1912 for (;;) {
1913 switch (pCurHcb->HCS_Phase) {
1914 case STATUS_IN:
1915 if ((tul_status_msg(pCurHcb)) == -1)
1916 return (-1);
1917 break;
1918
1919 case MSG_IN:
1920 pCurScb->SCB_NxtStat = 6;
1921 if ((tul_msgin(pCurHcb)) == -1)
1922 return (-1);
1923 break;
1924
1925 case MSG_OUT:
1926 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP);
1927 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
1928 if (wait_tulip(pCurHcb) == -1)
1929 return (-1);
1930 break;
1931
1932 case DATA_IN:
1933 return (tul_xpad_in(pCurHcb));
1934
1935 case DATA_OUT:
1936 return (tul_xpad_out(pCurHcb));
1937
1938 default:
1939 return (tul_bad_seq(pCurHcb));
1940 }
1941 }
1942}
1943
1944
1945int tul_state_7(HCS * pCurHcb)
1946{
1947 int cnt, i;
1948
1949#if DEBUG_STATE
1950 printk("-s7-");
1951#endif
1952
1953 cnt = TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F;
1954 if (cnt) {
1955 for (i = 0; i < cnt; i++)
1956 TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
1957 }
1958 switch (pCurHcb->HCS_Phase) {
1959 case DATA_IN:
1960 case DATA_OUT:
1961 return (tul_bad_seq(pCurHcb));
1962 default:
1963 return (6);
1964 }
1965}
1966
1967
1968int tul_xfer_data_in(HCS * pCurHcb)
1969{
1970 SCB *pCurScb = pCurHcb->HCS_ActScb;
1971
1972 if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_DOUT) {
1973 return (6);
1974 }
1975 TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, pCurScb->SCB_BufLen);
1976
1977 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_DMA_IN);
1978
1979 if (pCurScb->SCB_Flags & SCF_SG) {
1980 TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, ((ULONG) pCurScb->SCB_SGLen) << 3);
1981 TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);
1982 TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_SG_IN);
1983 } else {
1984 TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, pCurScb->SCB_BufLen);
1985 TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);
1986 TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_IN);
1987 }
1988 pCurScb->SCB_NxtStat = 0x5;
1989 return (0);
1990}
1991
1992
1993
1994int tul_xfer_data_out(HCS * pCurHcb)
1995{
1996 SCB *pCurScb = pCurHcb->HCS_ActScb;
1997
1998 if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_DIN) {
1999 return (6);
2000 }
2001 TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, pCurScb->SCB_BufLen);
2002 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_DMA_OUT);
2003
2004 if (pCurScb->SCB_Flags & SCF_SG) {
2005 TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, ((ULONG) pCurScb->SCB_SGLen) << 3);
2006 TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);
2007 TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_SG_OUT);
2008 } else {
2009 TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, pCurScb->SCB_BufLen);
2010 TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);
2011 TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_OUT);
2012 }
2013
2014 pCurScb->SCB_NxtStat = 0x5;
2015 return (0);
2016}
2017
2018
2019
2020int tul_xpad_in(HCS * pCurHcb)
2021{
2022 SCB *pCurScb = pCurHcb->HCS_ActScb;
2023 TCS *pCurTcb = pCurHcb->HCS_ActTcs;
2024
2025 if ((pCurScb->SCB_Flags & SCF_DIR) != SCF_NO_DCHK) {
2026 pCurScb->SCB_HaStat = HOST_DO_DU;
2027 }
2028 for (;;) {
2029 if (pCurTcb->TCS_JS_Period & TSC_WIDE_SCSI)
2030 TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 2);
2031 else
2032 TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
2033
2034 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
2035 if ((wait_tulip(pCurHcb)) == -1) {
2036 return (-1);
2037 }
2038 if (pCurHcb->HCS_Phase != DATA_IN) {
2039 TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
2040 return (6);
2041 }
2042 TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
2043 }
2044}
2045
2046int tul_xpad_out(HCS * pCurHcb)
2047{
2048 SCB *pCurScb = pCurHcb->HCS_ActScb;
2049 TCS *pCurTcb = pCurHcb->HCS_ActTcs;
2050
2051 if ((pCurScb->SCB_Flags & SCF_DIR) != SCF_NO_DCHK) {
2052 pCurScb->SCB_HaStat = HOST_DO_DU;
2053 }
2054 for (;;) {
2055 if (pCurTcb->TCS_JS_Period & TSC_WIDE_SCSI)
2056 TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 2);
2057 else
2058 TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
2059
2060 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 0);
2061 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
2062 if ((wait_tulip(pCurHcb)) == -1) {
2063 return (-1);
2064 }
2065 if (pCurHcb->HCS_Phase != DATA_OUT) {
2066 TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);
2067 TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
2068 return (6);
2069 }
2070 }
2071}
2072
2073
2074
2075int tul_status_msg(HCS * pCurHcb)
2076{
2077 SCB *pCurScb = pCurHcb->HCS_ActScb;
2078 BYTE msg;
2079
2080 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_CMD_COMP);
2081 if ((wait_tulip(pCurHcb)) == -1) {
2082 return (-1);
2083 }
2084
2085 pCurScb->SCB_TaStat = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
2086
2087 if (pCurHcb->HCS_Phase == MSG_OUT) {
2088 if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) {
2089 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_PARITY);
2090 } else {
2091 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP);
2092 }
2093 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
2094 return (wait_tulip(pCurHcb));
2095 }
2096 if (pCurHcb->HCS_Phase == MSG_IN) {
2097 msg = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
2098 if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) {
2099 if ((tul_msgin_accept(pCurHcb)) == -1)
2100 return (-1);
2101 if (pCurHcb->HCS_Phase != MSG_OUT)
2102 return (tul_bad_seq(pCurHcb));
2103 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_PARITY);
2104 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
2105 return (wait_tulip(pCurHcb));
2106 }
2107 if (msg == 0) {
2108
2109 if ((pCurScb->SCB_TaStat & 0x18) == 0x10) {
2110 return (tul_bad_seq(pCurHcb));
2111 }
2112 TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
2113 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT);
2114 return tul_wait_done_disc(pCurHcb);
2115
2116 }
2117 if ((msg == MSG_LINK_COMP) || (msg == MSG_LINK_FLAG)) {
2118 if ((pCurScb->SCB_TaStat & 0x18) == 0x10)
2119 return (tul_msgin_accept(pCurHcb));
2120 }
2121 }
2122 return (tul_bad_seq(pCurHcb));
2123}
2124
2125
2126
2127
2128int int_tul_busfree(HCS * pCurHcb)
2129{
2130 SCB *pCurScb = pCurHcb->HCS_ActScb;
2131
2132 if (pCurScb != NULL) {
2133 if (pCurScb->SCB_Status & SCB_SELECT) {
2134 tul_unlink_pend_scb(pCurHcb, pCurScb);
2135 pCurScb->SCB_HaStat = HOST_SEL_TOUT;
2136 tul_append_done_scb(pCurHcb, pCurScb);
2137 } else {
2138 tul_unlink_busy_scb(pCurHcb, pCurScb);
2139 pCurScb->SCB_HaStat = HOST_BUS_FREE;
2140 tul_append_done_scb(pCurHcb, pCurScb);
2141 }
2142 pCurHcb->HCS_ActScb = NULL;
2143 pCurHcb->HCS_ActTcs = NULL;
2144 }
2145 TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
2146 TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
2147 TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);
2148 return (-1);
2149}
2150
2151
2152
2153
2154int int_tul_scsi_rst(HCS * pCurHcb)
2155{
2156 SCB *pCurScb;
2157 int i;
2158
2159
2160 if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & 0x01) {
2161 TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT | TAX_X_CLR_FIFO);
2162
2163 while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & 0x04) == 0);
2164 TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
2165 }
2166
2167 while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) {
2168 pCurScb->SCB_HaStat = HOST_BAD_PHAS;
2169 tul_append_done_scb(pCurHcb, pCurScb);
2170 }
2171 pCurHcb->HCS_ActScb = NULL;
2172 pCurHcb->HCS_ActTcs = NULL;
2173
2174
2175 for (i = 0; i < pCurHcb->HCS_MaxTar; i++) {
2176 pCurHcb->HCS_Tcs[i].TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
2177 }
2178 return (-1);
2179}
2180
2181
2182
2183
2184int int_tul_resel(HCS * pCurHcb)
2185{
2186 SCB *pCurScb;
2187 TCS *pCurTcb;
2188 BYTE tag, msg = 0;
2189 BYTE tar, lun;
2190
2191 if ((pCurScb = pCurHcb->HCS_ActScb) != NULL) {
2192 if (pCurScb->SCB_Status & SCB_SELECT) {
2193 pCurScb->SCB_Status &= ~SCB_SELECT;
2194 }
2195 pCurHcb->HCS_ActScb = NULL;
2196 }
2197
2198 tar = TUL_RD(pCurHcb->HCS_Base, TUL_SBusId);
2199
2200 lun = TUL_RD(pCurHcb->HCS_Base, TUL_SIdent) & 0x0F;
2201
2202 pCurTcb = &pCurHcb->HCS_Tcs[tar];
2203 pCurHcb->HCS_ActTcs = pCurTcb;
2204 TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0);
2205 TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurTcb->TCS_JS_Period);
2206
2207
2208
2209 if (pCurTcb->TCS_DrvFlags & TCF_DRV_EN_TAG) {
2210 if ((tul_msgin_accept(pCurHcb)) == -1)
2211 return (-1);
2212 if (pCurHcb->HCS_Phase != MSG_IN)
2213 goto no_tag;
2214 TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
2215 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
2216 if ((wait_tulip(pCurHcb)) == -1)
2217 return (-1);
2218 msg = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
2219
2220 if ((msg < MSG_STAG) || (msg > MSG_OTAG))
2221 goto no_tag;
2222
2223 if ((tul_msgin_accept(pCurHcb)) == -1)
2224 return (-1);
2225
2226 if (pCurHcb->HCS_Phase != MSG_IN)
2227 goto no_tag;
2228
2229 TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
2230 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
2231 if ((wait_tulip(pCurHcb)) == -1)
2232 return (-1);
2233 tag = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
2234 pCurScb = pCurHcb->HCS_Scb + tag;
2235 if ((pCurScb->SCB_Target != tar) || (pCurScb->SCB_Lun != lun)) {
2236 return tul_msgout_abort_tag(pCurHcb);
2237 }
2238 if (pCurScb->SCB_Status != SCB_BUSY) {
2239 return tul_msgout_abort_tag(pCurHcb);
2240 }
2241 pCurHcb->HCS_ActScb = pCurScb;
2242 if ((tul_msgin_accept(pCurHcb)) == -1)
2243 return (-1);
2244 } else {
2245 no_tag:
2246 if ((pCurScb = tul_find_busy_scb(pCurHcb, tar | (lun << 8))) == NULL) {
2247 return tul_msgout_abort_targ(pCurHcb);
2248 }
2249 pCurHcb->HCS_ActScb = pCurScb;
2250 if (!(pCurTcb->TCS_DrvFlags & TCF_DRV_EN_TAG)) {
2251 if ((tul_msgin_accept(pCurHcb)) == -1)
2252 return (-1);
2253 }
2254 }
2255 return 0;
2256}
2257
2258
2259
2260int int_tul_bad_seq(HCS * pCurHcb)
2261{
2262 SCB *pCurScb;
2263 int i;
2264
2265 tul_reset_scsi(pCurHcb, 10);
2266
2267 while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) {
2268 pCurScb->SCB_HaStat = HOST_BAD_PHAS;
2269 tul_append_done_scb(pCurHcb, pCurScb);
2270 }
2271 for (i = 0; i < pCurHcb->HCS_MaxTar; i++) {
2272 pCurHcb->HCS_Tcs[i].TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);;
2273 }
2274 return (-1);
2275}
2276
2277
2278
2279int tul_msgout_abort_targ(HCS * pCurHcb)
2280{
2281
2282 TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
2283 if (tul_msgin_accept(pCurHcb) == -1)
2284 return (-1);
2285 if (pCurHcb->HCS_Phase != MSG_OUT)
2286 return (tul_bad_seq(pCurHcb));
2287
2288 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_ABORT);
2289 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
2290
2291 return tul_wait_disc(pCurHcb);
2292}
2293
2294
2295int tul_msgout_abort_tag(HCS * pCurHcb)
2296{
2297
2298 TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
2299 if (tul_msgin_accept(pCurHcb) == -1)
2300 return (-1);
2301 if (pCurHcb->HCS_Phase != MSG_OUT)
2302 return (tul_bad_seq(pCurHcb));
2303
2304 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_ABORT_TAG);
2305 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
2306
2307 return tul_wait_disc(pCurHcb);
2308
2309}
2310
2311
2312int tul_msgin(HCS * pCurHcb)
2313{
2314 TCS *pCurTcb;
2315
2316 for (;;) {
2317
2318 TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
2319
2320 TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
2321 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
2322 if ((wait_tulip(pCurHcb)) == -1)
2323 return (-1);
2324
2325 switch (TUL_RD(pCurHcb->HCS_Base, TUL_SFifo)) {
2326 case MSG_DISC:
2327 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT);
2328
2329 return tul_wait_disc(pCurHcb);
2330
2331 case MSG_SDP:
2332 case MSG_RESTORE:
2333 case MSG_NOP:
2334 tul_msgin_accept(pCurHcb);
2335 break;
2336
2337 case MSG_REJ:
2338 TUL_WR(pCurHcb->HCS_Base + TUL_SSignal,
2339 (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)));
2340 pCurTcb = pCurHcb->HCS_ActTcs;
2341 if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {
2342 TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
2343 }
2344 tul_msgin_accept(pCurHcb);
2345 break;
2346
2347 case MSG_EXTEND:
2348 tul_msgin_extend(pCurHcb);
2349 break;
2350
2351 case MSG_IGNOREWIDE:
2352 tul_msgin_accept(pCurHcb);
2353 break;
2354
2355
2356 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
2357 if (wait_tulip(pCurHcb) == -1)
2358 return -1;
2359
2360 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 0);
2361 TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
2362 TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
2363
2364 tul_msgin_accept(pCurHcb);
2365 break;
2366
2367 case MSG_COMP:
2368 {
2369 TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
2370 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT);
2371 return tul_wait_done_disc(pCurHcb);
2372 }
2373 default:
2374 tul_msgout_reject(pCurHcb);
2375 break;
2376 }
2377 if (pCurHcb->HCS_Phase != MSG_IN)
2378 return (pCurHcb->HCS_Phase);
2379 }
2380
2381}
2382
2383
2384
2385
2386
2387int tul_msgout_reject(HCS * pCurHcb)
2388{
2389
2390 TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
2391
2392 if ((tul_msgin_accept(pCurHcb)) == -1)
2393 return (-1);
2394
2395 if (pCurHcb->HCS_Phase == MSG_OUT) {
2396 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_REJ);
2397 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
2398 return (wait_tulip(pCurHcb));
2399 }
2400 return (pCurHcb->HCS_Phase);
2401}
2402
2403
2404
2405
2406int tul_msgout_ide(HCS * pCurHcb)
2407{
2408 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_IDE);
2409 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
2410 return (wait_tulip(pCurHcb));
2411}
2412
2413
2414
2415int tul_msgin_extend(HCS * pCurHcb)
2416{
2417 BYTE len, idx;
2418
2419 if (tul_msgin_accept(pCurHcb) != MSG_IN)
2420 return (pCurHcb->HCS_Phase);
2421
2422
2423 TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
2424 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
2425 if (wait_tulip(pCurHcb) == -1)
2426 return (-1);
2427
2428 len = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
2429 pCurHcb->HCS_Msg[0] = len;
2430 for (idx = 1; len != 0; len--) {
2431
2432 if ((tul_msgin_accept(pCurHcb)) != MSG_IN)
2433 return (pCurHcb->HCS_Phase);
2434 TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
2435 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
2436 if (wait_tulip(pCurHcb) == -1)
2437 return (-1);
2438 pCurHcb->HCS_Msg[idx++] = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
2439 }
2440 if (pCurHcb->HCS_Msg[1] == 1) {
2441 if (pCurHcb->HCS_Msg[0] != 3)
2442 return (tul_msgout_reject(pCurHcb));
2443 if (pCurHcb->HCS_ActTcs->TCS_Flags & TCF_NO_SYNC_NEGO) {
2444 pCurHcb->HCS_Msg[3] = 0;
2445 } else {
2446 if ((tul_msgin_sync(pCurHcb) == 0) &&
2447 (pCurHcb->HCS_ActTcs->TCS_Flags & TCF_SYNC_DONE)) {
2448 tul_sync_done(pCurHcb);
2449 return (tul_msgin_accept(pCurHcb));
2450 }
2451 }
2452
2453 TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
2454 if ((tul_msgin_accept(pCurHcb)) != MSG_OUT)
2455 return (pCurHcb->HCS_Phase);
2456
2457 TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
2458
2459 tul_sync_done(pCurHcb);
2460
2461 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
2462 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);
2463 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1);
2464 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurHcb->HCS_Msg[2]);
2465 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurHcb->HCS_Msg[3]);
2466
2467 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
2468 return (wait_tulip(pCurHcb));
2469 }
2470 if ((pCurHcb->HCS_Msg[0] != 2) || (pCurHcb->HCS_Msg[1] != 3))
2471 return (tul_msgout_reject(pCurHcb));
2472
2473 if (pCurHcb->HCS_ActTcs->TCS_Flags & TCF_NO_WDTR) {
2474 pCurHcb->HCS_Msg[2] = 0;
2475 } else {
2476 if (pCurHcb->HCS_Msg[2] > 2)
2477 return (tul_msgout_reject(pCurHcb));
2478 if (pCurHcb->HCS_Msg[2] == 2) {
2479 pCurHcb->HCS_Msg[2] = 1;
2480 } else {
2481 if ((pCurHcb->HCS_ActTcs->TCS_Flags & TCF_NO_WDTR) == 0) {
2482 wdtr_done(pCurHcb);
2483 if ((pCurHcb->HCS_ActTcs->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0)
2484 TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
2485 return (tul_msgin_accept(pCurHcb));
2486 }
2487 }
2488 }
2489 TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
2490
2491 if (tul_msgin_accept(pCurHcb) != MSG_OUT)
2492 return (pCurHcb->HCS_Phase);
2493
2494 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
2495 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 2);
2496 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);
2497 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurHcb->HCS_Msg[2]);
2498 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
2499 return (wait_tulip(pCurHcb));
2500}
2501
2502
2503int tul_msgin_sync(HCS * pCurHcb)
2504{
2505 char default_period;
2506
2507 default_period = tul_rate_tbl[pCurHcb->HCS_ActTcs->TCS_Flags & TCF_SCSI_RATE];
2508 if (pCurHcb->HCS_Msg[3] > MAX_OFFSET) {
2509 pCurHcb->HCS_Msg[3] = MAX_OFFSET;
2510 if (pCurHcb->HCS_Msg[2] < default_period) {
2511 pCurHcb->HCS_Msg[2] = default_period;
2512 return 1;
2513 }
2514 if (pCurHcb->HCS_Msg[2] >= 59) {
2515 pCurHcb->HCS_Msg[3] = 0;
2516 }
2517 return 1;
2518 }
2519
2520 if (pCurHcb->HCS_Msg[3] == 0) {
2521 return 0;
2522 }
2523 if (pCurHcb->HCS_Msg[2] < default_period) {
2524 pCurHcb->HCS_Msg[2] = default_period;
2525 return 1;
2526 }
2527 if (pCurHcb->HCS_Msg[2] >= 59) {
2528 pCurHcb->HCS_Msg[3] = 0;
2529 return 1;
2530 }
2531 return 0;
2532}
2533
2534
2535
2536int wdtr_done(HCS * pCurHcb)
2537{
2538 pCurHcb->HCS_ActTcs->TCS_Flags &= ~TCF_SYNC_DONE;
2539 pCurHcb->HCS_ActTcs->TCS_Flags |= TCF_WDTR_DONE;
2540
2541 pCurHcb->HCS_ActTcs->TCS_JS_Period = 0;
2542 if (pCurHcb->HCS_Msg[2]) {
2543 pCurHcb->HCS_ActTcs->TCS_JS_Period |= TSC_WIDE_SCSI;
2544 }
2545 pCurHcb->HCS_ActTcs->TCS_SConfig0 &= ~TSC_ALT_PERIOD;
2546 TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurHcb->HCS_ActTcs->TCS_SConfig0);
2547 TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurHcb->HCS_ActTcs->TCS_JS_Period);
2548
2549 return 1;
2550}
2551
2552
2553int tul_sync_done(HCS * pCurHcb)
2554{
2555 int i;
2556
2557 pCurHcb->HCS_ActTcs->TCS_Flags |= TCF_SYNC_DONE;
2558
2559 if (pCurHcb->HCS_Msg[3]) {
2560 pCurHcb->HCS_ActTcs->TCS_JS_Period |= pCurHcb->HCS_Msg[3];
2561 for (i = 0; i < 8; i++) {
2562 if (tul_rate_tbl[i] >= pCurHcb->HCS_Msg[2])
2563 break;
2564 }
2565 pCurHcb->HCS_ActTcs->TCS_JS_Period |= (i << 4);
2566 pCurHcb->HCS_ActTcs->TCS_SConfig0 |= TSC_ALT_PERIOD;
2567 }
2568 TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurHcb->HCS_ActTcs->TCS_SConfig0);
2569 TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurHcb->HCS_ActTcs->TCS_JS_Period);
2570
2571 return (-1);
2572}
2573
2574
2575int tul_post_scsi_rst(HCS * pCurHcb)
2576{
2577 SCB *pCurScb;
2578 TCS *pCurTcb;
2579 int i;
2580
2581 pCurHcb->HCS_ActScb = 0;
2582 pCurHcb->HCS_ActTcs = 0;
2583 pCurHcb->HCS_Flags = 0;
2584
2585 while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) {
2586 pCurScb->SCB_HaStat = HOST_BAD_PHAS;
2587 tul_append_done_scb(pCurHcb, pCurScb);
2588 }
2589
2590 pCurTcb = &pCurHcb->HCS_Tcs[0];
2591 for (i = 0; i < pCurHcb->HCS_MaxTar; pCurTcb++, i++) {
2592 pCurTcb->TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
2593
2594 pCurTcb->TCS_JS_Period = 0;
2595 pCurTcb->TCS_SConfig0 = pCurHcb->HCS_SConf1;
2596 pCurHcb->HCS_ActTags[0] = 0;
2597 pCurHcb->HCS_Tcs[i].TCS_Flags &= ~TCF_BUSY;
2598 }
2599
2600 return (-1);
2601}
2602
2603
2604void tul_select_atn_stop(HCS * pCurHcb, SCB * pCurScb)
2605{
2606 pCurScb->SCB_Status |= SCB_SELECT;
2607 pCurScb->SCB_NxtStat = 0x1;
2608 pCurHcb->HCS_ActScb = pCurScb;
2609 pCurHcb->HCS_ActTcs = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target];
2610 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_SELATNSTOP);
2611 return;
2612}
2613
2614
2615
2616void tul_select_atn(HCS * pCurHcb, SCB * pCurScb)
2617{
2618 int i;
2619
2620 pCurScb->SCB_Status |= SCB_SELECT;
2621 pCurScb->SCB_NxtStat = 0x2;
2622
2623 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_Ident);
2624 for (i = 0; i < (int) pCurScb->SCB_CDBLen; i++)
2625 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_CDB[i]);
2626 pCurHcb->HCS_ActTcs = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target];
2627 pCurHcb->HCS_ActScb = pCurScb;
2628 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_SEL_ATN);
2629 return;
2630}
2631
2632
2633void tul_select_atn3(HCS * pCurHcb, SCB * pCurScb)
2634{
2635 int i;
2636
2637 pCurScb->SCB_Status |= SCB_SELECT;
2638 pCurScb->SCB_NxtStat = 0x2;
2639
2640 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_Ident);
2641 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagMsg);
2642 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagId);
2643 for (i = 0; i < (int) pCurScb->SCB_CDBLen; i++)
2644 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_CDB[i]);
2645 pCurHcb->HCS_ActTcs = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target];
2646 pCurHcb->HCS_ActScb = pCurScb;
2647 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_SEL_ATN3);
2648 return;
2649}
2650
2651
2652
2653int tul_bus_device_reset(HCS * pCurHcb)
2654{
2655 SCB *pCurScb = pCurHcb->HCS_ActScb;
2656 TCS *pCurTcb = pCurHcb->HCS_ActTcs;
2657 SCB *pTmpScb, *pPrevScb;
2658 BYTE tar;
2659
2660 if (pCurHcb->HCS_Phase != MSG_OUT) {
2661 return (int_tul_bad_seq(pCurHcb));
2662 }
2663 tul_unlink_pend_scb(pCurHcb, pCurScb);
2664 tul_release_scb(pCurHcb, pCurScb);
2665
2666
2667 tar = pCurScb->SCB_Target;
2668 pCurTcb->TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE | TCF_BUSY);
2669
2670
2671
2672 pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy;
2673 while (pTmpScb != NULL) {
2674
2675 if (pTmpScb->SCB_Target == tar) {
2676
2677 if (pTmpScb == pCurHcb->HCS_FirstBusy) {
2678 if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)
2679 pCurHcb->HCS_LastBusy = NULL;
2680 } else {
2681 pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
2682 if (pTmpScb == pCurHcb->HCS_LastBusy)
2683 pCurHcb->HCS_LastBusy = pPrevScb;
2684 }
2685 pTmpScb->SCB_HaStat = HOST_ABORTED;
2686 tul_append_done_scb(pCurHcb, pTmpScb);
2687 }
2688
2689 else {
2690 pPrevScb = pTmpScb;
2691 }
2692 pTmpScb = pTmpScb->SCB_NxtScb;
2693 }
2694
2695 TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_DEVRST);
2696 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
2697
2698 return tul_wait_disc(pCurHcb);
2699
2700}
2701
2702
2703int tul_msgin_accept(HCS * pCurHcb)
2704{
2705 TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT);
2706 return (wait_tulip(pCurHcb));
2707}
2708
2709
2710int wait_tulip(HCS * pCurHcb)
2711{
2712
2713 while (!((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0))
2714 & TSS_INT_PENDING));
2715
2716 pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
2717 pCurHcb->HCS_Phase = pCurHcb->HCS_JSStatus0 & TSS_PH_MASK;
2718 pCurHcb->HCS_JSStatus1 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1);
2719
2720 if (pCurHcb->HCS_JSInt & TSS_RESEL_INT) {
2721 return (int_tul_resel(pCurHcb));
2722 }
2723 if (pCurHcb->HCS_JSInt & TSS_SEL_TIMEOUT) {
2724 return (int_tul_busfree(pCurHcb));
2725 }
2726 if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) {
2727 return (int_tul_scsi_rst(pCurHcb));
2728 }
2729 if (pCurHcb->HCS_JSInt & TSS_DISC_INT) {
2730 if (pCurHcb->HCS_Flags & HCF_EXPECT_DONE_DISC) {
2731 TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
2732 tul_unlink_busy_scb(pCurHcb, pCurHcb->HCS_ActScb);
2733 pCurHcb->HCS_ActScb->SCB_HaStat = 0;
2734 tul_append_done_scb(pCurHcb, pCurHcb->HCS_ActScb);
2735 pCurHcb->HCS_ActScb = NULL;
2736 pCurHcb->HCS_ActTcs = NULL;
2737 pCurHcb->HCS_Flags &= ~HCF_EXPECT_DONE_DISC;
2738 TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
2739 TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);
2740 return (-1);
2741 }
2742 if (pCurHcb->HCS_Flags & HCF_EXPECT_DISC) {
2743 TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
2744 pCurHcb->HCS_ActScb = NULL;
2745 pCurHcb->HCS_ActTcs = NULL;
2746 pCurHcb->HCS_Flags &= ~HCF_EXPECT_DISC;
2747 TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
2748 TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);
2749 return (-1);
2750 }
2751 return (int_tul_busfree(pCurHcb));
2752 }
2753 if (pCurHcb->HCS_JSInt & (TSS_FUNC_COMP | TSS_BUS_SERV)) {
2754 return (pCurHcb->HCS_Phase);
2755 }
2756 return (pCurHcb->HCS_Phase);
2757}
2758
2759int tul_wait_disc(HCS * pCurHcb)
2760{
2761
2762 while (!((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0))
2763 & TSS_INT_PENDING));
2764
2765
2766 pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
2767
2768 if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) {
2769 return (int_tul_scsi_rst(pCurHcb));
2770 }
2771 if (pCurHcb->HCS_JSInt & TSS_DISC_INT) {
2772 TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
2773 TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
2774 TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);
2775 pCurHcb->HCS_ActScb = NULL;
2776 return (-1);
2777 }
2778 return (tul_bad_seq(pCurHcb));
2779}
2780
2781
2782int tul_wait_done_disc(HCS * pCurHcb)
2783{
2784
2785
2786 while (!((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0))
2787 & TSS_INT_PENDING));
2788
2789 pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
2790
2791
2792 if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) {
2793 return (int_tul_scsi_rst(pCurHcb));
2794 }
2795 if (pCurHcb->HCS_JSInt & TSS_DISC_INT) {
2796 TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
2797 TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
2798 TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);
2799 tul_unlink_busy_scb(pCurHcb, pCurHcb->HCS_ActScb);
2800
2801 tul_append_done_scb(pCurHcb, pCurHcb->HCS_ActScb);
2802 pCurHcb->HCS_ActScb = NULL;
2803 return (-1);
2804 }
2805 return (tul_bad_seq(pCurHcb));
2806}
2807
2808
2809