* Patch by Yuli Barcohen, 16 Jun 2004:
[platform/kernel/u-boot.git] / drivers / sym53c8xx.c
1 /*
2  * (C) Copyright 2001
3  * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  * partly derived from
23  * linux/drivers/scsi/sym53c8xx.c
24  *
25  */
26
27 /*
28  * SCSI support based on the chip sym53C810.
29  *
30  * 09-19-2001 Andreas Heppel, Sysgo RTS GmbH <aheppel@sysgo.de>
31  *              The local version of this driver for the BAB750 board does not
32  *              use interrupts but polls the chip instead (see the call of
33  *              'handle_scsi_int()' in 'scsi_issue()'.
34  */
35
36 #include <common.h>
37
38 #ifdef CONFIG_SCSI_SYM53C8XX
39
40 #include <command.h>
41 #include <pci.h>
42 #include <asm/processor.h>
43 #include <sym53c8xx.h>
44 #include <scsi.h>
45
46 #undef  SYM53C8XX_DEBUG
47
48 #ifdef  SYM53C8XX_DEBUG
49 #define PRINTF(fmt,args...)     printf (fmt ,##args)
50 #else
51 #define PRINTF(fmt,args...)
52 #endif
53
54 #if (CONFIG_COMMANDS & CFG_CMD_SCSI) && defined(CONFIG_SCSI_SYM53C8XX)
55
56 #undef SCSI_SINGLE_STEP
57 /*
58  * Single Step is only used for debug purposes
59  */
60 #ifdef SCSI_SINGLE_STEP
61 static unsigned long start_script_select;
62 static unsigned long start_script_msgout;
63 static unsigned long start_script_msgin;
64 static unsigned long start_script_msg_ext;
65 static unsigned long start_script_cmd;
66 static unsigned long start_script_data_in;
67 static unsigned long start_script_data_out;
68 static unsigned long start_script_status;
69 static unsigned long start_script_complete;
70 static unsigned long start_script_error;
71 static unsigned long start_script_reselection;
72 static unsigned int len_script_select;
73 static unsigned int len_script_msgout;
74 static unsigned int len_script_msgin;
75 static unsigned int len_script_msg_ext;
76 static unsigned int len_script_cmd;
77 static unsigned int len_script_data_in;
78 static unsigned int len_script_data_out;
79 static unsigned int len_script_status;
80 static unsigned int len_script_complete;
81 static unsigned int len_script_error;
82 static unsigned int len_script_reselection;
83 #endif
84
85
86 static unsigned short scsi_int_mask;            /* shadow register for SCSI related interrupts */
87 static unsigned char  script_int_mask;  /* shadow register for SCRIPT related interrupts */
88 static unsigned long script_select[8]; /* script for selection */
89 static unsigned long script_msgout[8]; /* script for message out phase (NOT USED) */
90 static unsigned long script_msgin[14]; /* script for message in phase */
91 static unsigned long script_msg_ext[32]; /* script for message in phase when more than 1 byte message */
92 static unsigned long script_cmd[18];    /* script for command phase */
93 static unsigned long script_data_in[8]; /* script for data in phase */
94 static unsigned long script_data_out[8]; /* script for data out phase */
95 static unsigned long script_status[6]; /* script for status phase */
96 static unsigned long script_complete[10]; /* script for complete */
97 static unsigned long script_reselection[4]; /* script for reselection (NOT USED) */
98 static unsigned long script_error[2]; /* script for error handling */
99
100 static unsigned long int_stat[3]; /* interrupt status */
101 static unsigned long scsi_mem_addr; /* base memory address =SCSI_MEM_ADDRESS; */
102
103 #define bus_to_phys(a)  pci_mem_to_phys(busdevfunc, (unsigned long) (a))
104 #define phys_to_bus(a)  pci_phys_to_mem(busdevfunc, (unsigned long) (a))
105
106 #define SCSI_MAX_RETRY 3 /* number of retries in scsi_issue() */
107
108 #define SCSI_MAX_RETRY_NOT_READY 10 /* number of retries when device is not ready */
109 #define SCSI_NOT_READY_TIME_OUT 500 /* timeout per retry when not ready */
110
111 /*********************************************************************************
112  * forward declerations
113  */
114
115 void scsi_chip_init(void);
116 void handle_scsi_int(void);
117
118
119 /********************************************************************************
120  * reports SCSI errors to the user
121  */
122 void scsi_print_error(ccb *pccb)
123 {
124         int i;
125         printf("SCSI Error: Target %d LUN %d Command %02X\n",pccb->target, pccb->lun, pccb->cmd[0]);
126         printf("       CCB: ");
127         for(i=0;i<pccb->cmdlen;i++)
128                 printf("%02X ",pccb->cmd[i]);
129         printf("(len=%d)\n",pccb->cmdlen);
130         printf("     Cntrl: ");
131         switch(pccb->contr_stat) {
132                 case SIR_COMPLETE:                                              printf("Complete (no Error)\n"); break;
133                 case SIR_SEL_ATN_NO_MSG_OUT:    printf("Selected with ATN no MSG out phase\n"); break;
134                 case SIR_CMD_OUT_ILL_PH:                        printf("Command out illegal phase\n"); break;
135                 case SIR_MSG_RECEIVED:                          printf("MSG received Error\n"); break;
136                 case SIR_DATA_IN_ERR:                           printf("Data in Error\n"); break;
137                 case SIR_DATA_OUT_ERR:                          printf("Data out Error\n"); break;
138                 case SIR_SCRIPT_ERROR:                          printf("Script Error\n"); break;
139                 case SIR_MSG_OUT_NO_CMD:                        printf("MSG out no Command phase\n"); break;
140                 case SIR_MSG_OVER7:                                     printf("MSG in over 7 bytes\n"); break;
141                 case INT_ON_FY:                                                         printf("Interrupt on fly\n"); break;
142                 case SCSI_SEL_TIME_OUT:                         printf("SCSI Selection Timeout\n"); break;
143                 case SCSI_HNS_TIME_OUT:                         printf("SCSI Handshake Timeout\n"); break;
144                 case SCSI_MA_TIME_OUT:                          printf("SCSI Phase Error\n"); break;
145                 case SCSI_UNEXP_DIS:                                    printf("SCSI unexpected disconnect\n"); break;
146                 default:                                                                                        printf("unknown status %lx\n",pccb->contr_stat); break;
147         }
148         printf("     Sense: SK %x (",pccb->sense_buf[2]&0x0f);
149         switch(pccb->sense_buf[2]&0xf) {
150                 case SENSE_NO_SENSE: printf("No Sense)"); break;
151                 case SENSE_RECOVERED_ERROR: printf("Recovered Error)"); break;
152                 case SENSE_NOT_READY:   printf("Not Ready)"); break;
153                 case SENSE_MEDIUM_ERROR: printf("Medium Error)"); break;
154                 case SENSE_HARDWARE_ERROR: printf("Hardware Error)"); break;
155                 case SENSE_ILLEGAL_REQUEST: printf("Illegal request)"); break;
156                 case SENSE_UNIT_ATTENTION: printf("Unit Attention)"); break;
157                 case SENSE_DATA_PROTECT: printf("Data Protect)"); break;
158                 case SENSE_BLANK_CHECK: printf("Blank check)"); break;
159                 case SENSE_VENDOR_SPECIFIC: printf("Vendor specific)"); break;
160                 case SENSE_COPY_ABORTED: printf("Copy aborted)"); break;
161                 case SENSE_ABORTED_COMMAND:     printf("Aborted Command)"); break;
162                 case SENSE_VOLUME_OVERFLOW:     printf("Volume overflow)"); break;
163                 case SENSE_MISCOMPARE: printf("Misscompare\n"); break;
164                 default: printf("Illegal Sensecode\n"); break;
165         }
166         printf(" ASC %x ASCQ %x\n",pccb->sense_buf[12],pccb->sense_buf[13]);
167         printf("    Status: ");
168         switch(pccb->status) {
169                 case S_GOOD :   printf("Good\n"); break;
170                 case S_CHECK_COND: printf("Check condition\n"); break;
171                 case S_COND_MET: printf("Condition Met\n"); break;
172                 case S_BUSY: printf("Busy\n"); break;
173                 case S_INT: printf("Intermediate\n"); break;
174                 case S_INT_COND_MET: printf("Intermediate condition met\n"); break;
175                 case S_CONFLICT: printf("Reservation conflict\n"); break;
176                 case S_TERMINATED: printf("Command terminated\n"); break;
177                 case S_QUEUE_FULL: printf("Task set full\n"); break;
178                 default: printf("unknown: %02X\n",pccb->status); break;
179         }
180
181 }
182
183
184 /******************************************************************************
185  * sets-up the SCSI controller
186  * the base memory address is retrived via the pci_read_config_dword
187  */
188 void scsi_low_level_init(int busdevfunc)
189 {
190         unsigned int cmd;
191         unsigned int addr;
192         unsigned char vec;
193
194         pci_read_config_byte(busdevfunc, PCI_INTERRUPT_LINE, &vec);
195         pci_read_config_dword(busdevfunc, PCI_BASE_ADDRESS_1, &addr);
196
197         addr = bus_to_phys(addr & ~0xf);
198
199         /*
200          * Enable bus mastering in case this has not been done, yet.
201          */
202         pci_read_config_dword(busdevfunc, PCI_COMMAND, &cmd);
203         cmd |= PCI_COMMAND_MASTER;
204         pci_write_config_dword(busdevfunc, PCI_COMMAND, cmd);
205
206         scsi_mem_addr = addr;
207
208         scsi_chip_init();
209         scsi_bus_reset();
210 }
211
212
213 /************************************************************************************
214  * Low level Part of SCSI Driver
215  */
216
217 /*
218  * big-endian -> little endian conversion for the script
219  */
220 unsigned long swap_script(unsigned long val)
221 {
222         unsigned long tmp;
223         tmp = ((val>>24)&0xff) | ((val>>8)&0xff00) | ((val<<8)&0xff0000) | ((val<<24)&0xff000000);
224         return tmp;
225 }
226
227
228 void scsi_write_byte(ulong offset,unsigned char val)
229 {
230         out8(scsi_mem_addr+offset,val);
231 }
232
233
234 unsigned char scsi_read_byte(ulong offset)
235 {
236         return(in8(scsi_mem_addr+offset));
237 }
238
239
240 /********************************************************************************
241  * interrupt handler
242  */
243 void handle_scsi_int(void)
244 {
245         unsigned char stat,stat1,stat2;
246         unsigned short sstat;
247         int i;
248 #ifdef SCSI_SINGLE_STEP
249         unsigned long tt;
250 #endif
251         stat=scsi_read_byte(ISTAT);
252         if((stat & DIP)==DIP) { /* DMA Interrupt pending */
253                 stat1=scsi_read_byte(DSTAT);
254 #ifdef SCSI_SINGLE_STEP
255                 if((stat1 & SSI)==SSI)
256                 {
257                         tt=in32r(scsi_mem_addr+DSP);
258                         if(((tt)>=start_script_select) && ((tt)<start_script_select+len_script_select)) {
259                                 printf("select %d\n",(tt-start_script_select)>>2);
260                                 goto end_single;
261                         }
262                         if(((tt)>=start_script_msgout) && ((tt)<start_script_msgout+len_script_msgout)) {
263                                 printf("msgout %d\n",(tt-start_script_msgout)>>2);
264                                 goto end_single;
265                         }
266                         if(((tt)>=start_script_msgin) && ((tt)<start_script_msgin+len_script_msgin)) {
267                                 printf("msgin %d\n",(tt-start_script_msgin)>>2);
268                                 goto end_single;
269                         }
270                         if(((tt)>=start_script_msg_ext) && ((tt)<start_script_msg_ext+len_script_msg_ext)) {
271                                 printf("msgin_ext %d\n",(tt-start_script_msg_ext)>>2);
272                                 goto end_single;
273                         }
274                         if(((tt)>=start_script_cmd) && ((tt)<start_script_cmd+len_script_cmd)) {
275                                 printf("cmd %d\n",(tt-start_script_cmd)>>2);
276                                 goto end_single;
277                         }
278                         if(((tt)>=start_script_data_in) && ((tt)<start_script_data_in+len_script_data_in)) {
279                                 printf("data_in %d\n",(tt-start_script_data_in)>>2);
280                                 goto end_single;
281                         }
282                         if(((tt)>=start_script_data_out) && ((tt)<start_script_data_out+len_script_data_out)) {
283                                 printf("data_out %d\n",(tt-start_script_data_out)>>2);
284                                 goto end_single;
285                         }
286                         if(((tt)>=start_script_status) && ((tt)<start_script_status+len_script_status)) {
287                                 printf("status %d\n",(tt-start_script_status)>>2);
288                                 goto end_single;
289                         }
290                         if(((tt)>=start_script_complete) && ((tt)<start_script_complete+len_script_complete)) {
291                                 printf("complete %d\n",(tt-start_script_complete)>>2);
292                                 goto end_single;
293                         }
294                         if(((tt)>=start_script_error) && ((tt)<start_script_error+len_script_error)) {
295                                 printf("error %d\n",(tt-start_script_error)>>2);
296                                 goto end_single;
297                         }
298                         if(((tt)>=start_script_reselection) && ((tt)<start_script_reselection+len_script_reselection)) {
299                                 printf("reselection %d\n",(tt-start_script_reselection)>>2);
300                                 goto end_single;
301                         }
302                         printf("sc: %lx\n",tt);
303 end_single:
304                         stat2=scsi_read_byte(DCNTL);
305                         stat2|=STD;
306                         scsi_write_byte(DCNTL,stat2);
307                 }
308 #endif
309                 if((stat1 & SIR)==SIR) /* script interrupt */
310                 {
311                         int_stat[0]=in32(scsi_mem_addr+DSPS);
312                 }
313                 if((stat1 & DFE)==0) { /* fifo not epmty */
314                         scsi_write_byte(CTEST3,CLF); /* Clear DMA FIFO */
315                         stat2=scsi_read_byte(STEST3);
316                         scsi_write_byte(STEST3,(stat2 | CSF)); /* Clear SCSI FIFO */
317                 }
318         }
319         if((stat & SIP)==SIP) {  /* scsi interrupt */
320                 sstat = (unsigned short)scsi_read_byte(SIST+1);
321                 sstat <<=8;
322                 sstat |= (unsigned short)scsi_read_byte(SIST);
323                 for(i=0;i<3;i++) {
324                         if(int_stat[i]==0)
325                                 break; /* found an empty int status */
326                 }
327                 int_stat[i]=SCSI_INT_STATE | sstat;
328                 stat1=scsi_read_byte(DSTAT);
329                 if((stat1 & DFE)==0) { /* fifo not epmty */
330                         scsi_write_byte(CTEST3,CLF); /* Clear DMA FIFO */
331                         stat2=scsi_read_byte(STEST3);
332                         scsi_write_byte(STEST3,(stat2 | CSF)); /* Clear SCSI FIFO */
333                 }
334         }
335         if((stat & INTF)==INTF) { /* interrupt on Fly */
336                 scsi_write_byte(ISTAT,stat); /* clear it */
337                 for(i=0;i<3;i++) {
338                         if(int_stat[i]==0)
339                                 break; /* found an empty int status */
340                 }
341                 int_stat[i]=INT_ON_FY;
342         }
343 }
344
345 void scsi_bus_reset(void)
346 {
347         unsigned char t;
348         int i;
349         int end = CFG_SCSI_SPIN_UP_TIME*1000;
350
351         t=scsi_read_byte(SCNTL1);
352         scsi_write_byte(SCNTL1,(t | CRST));
353         udelay(50);
354         scsi_write_byte(SCNTL1,t);
355
356         puts("waiting for devices to spin up");
357         for(i=0;i<end;i++) {
358                 udelay(1000); /* give the devices time to spin up */
359                 if (i % 1000 == 0)
360                         putc('.');
361         }
362         putc('\n');
363         scsi_chip_init(); /* reinit the chip ...*/
364
365 }
366
367 void scsi_int_enable(void)
368 {
369         scsi_write_byte(SIEN,(unsigned char)scsi_int_mask);
370         scsi_write_byte(SIEN+1,(unsigned char)(scsi_int_mask>>8));
371         scsi_write_byte(DIEN,script_int_mask);
372 }
373
374 void scsi_write_dsp(unsigned long start)
375 {
376         unsigned long val;
377 #ifdef SCSI_SINGLE_STEP
378         unsigned char t;
379 #endif
380         val = start;
381         out32r(scsi_mem_addr + DSP,start);
382 #ifdef SCSI_SINGLE_STEP
383         t=scsi_read_byte(DCNTL);
384   t|=STD;
385         scsi_write_byte(DCNTL,t);
386 #endif
387 }
388
389 /* only used for debug purposes */
390 void scsi_print_script(void)
391 {
392         printf("script_select @         0x%08lX\n",(unsigned long)&script_select[0]);
393         printf("script_msgout @         0x%08lX\n",(unsigned long)&script_msgout[0]);
394         printf("script_msgin @          0x%08lX\n",(unsigned long)&script_msgin[0]);
395         printf("script_msgext @         0x%08lX\n",(unsigned long)&script_msg_ext[0]);
396         printf("script_cmd @            0x%08lX\n",(unsigned long)&script_cmd[0]);
397         printf("script_data_in @        0x%08lX\n",(unsigned long)&script_data_in[0]);
398         printf("script_data_out @       0x%08lX\n",(unsigned long)&script_data_out[0]);
399         printf("script_status @         0x%08lX\n",(unsigned long)&script_status[0]);
400         printf("script_complete @       0x%08lX\n",(unsigned long)&script_complete[0]);
401         printf("script_error @          0x%08lX\n",(unsigned long)&script_error[0]);
402 }
403
404
405 void scsi_set_script(ccb *pccb)
406 {
407         int busdevfunc = pccb->priv;
408         int i;
409         i=0;
410         script_select[i++]=swap_script(SCR_REG_REG(GPREG, SCR_AND, 0xfe));
411         script_select[i++]=0; /* LED ON */
412         script_select[i++]=swap_script(SCR_CLR(SCR_TRG)); /* select initiator mode */
413         script_select[i++]=0;
414         /* script_select[i++]=swap_script(SCR_SEL_ABS_ATN | pccb->target << 16); */
415         script_select[i++]=swap_script(SCR_SEL_ABS | pccb->target << 16);
416         script_select[i++]=swap_script(phys_to_bus(&script_cmd[4])); /* error handling */
417         script_select[i++]=swap_script(SCR_JUMP); /* next section */
418         /*      script_select[i++]=swap_script((unsigned long)&script_msgout[0]); */ /* message out */
419         script_select[i++]=swap_script(phys_to_bus(&script_cmd[0])); /* command out */
420
421 #ifdef SCSI_SINGLE_STEP
422         start_script_select=(unsigned long)&script_select[0];
423         len_script_select=i*4;
424 #endif
425
426         i=0;
427         script_msgout[i++]=swap_script(SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)));
428         script_msgout[i++]=SIR_SEL_ATN_NO_MSG_OUT;
429         script_msgout[i++]=swap_script( SCR_MOVE_ABS(1) ^ SCR_MSG_OUT);
430         script_msgout[i++]=swap_script(phys_to_bus(&pccb->msgout[0]));
431         script_msgout[i++]=swap_script(SCR_JUMP ^ IFTRUE (WHEN (SCR_COMMAND))); /* if Command phase */
432         script_msgout[i++]=swap_script(phys_to_bus(&script_cmd[0])); /* switch to command */
433         script_msgout[i++]=swap_script(SCR_INT); /* interrupt if not */
434         script_msgout[i++]=SIR_MSG_OUT_NO_CMD;
435
436 #ifdef SCSI_SINGLE_STEP
437         start_script_msgout=(unsigned long)&script_msgout[0];
438         len_script_msgout=i*4;
439 #endif
440         i=0;
441         script_cmd[i++]=swap_script(SCR_MOVE_ABS(pccb->cmdlen) ^ SCR_COMMAND);
442         script_cmd[i++]=swap_script(phys_to_bus(&pccb->cmd[0]));
443         script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN))); /* message in ? */
444         script_cmd[i++]=swap_script(phys_to_bus(&script_msgin[0]));
445         script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (IF (SCR_DATA_OUT))); /* data out ? */
446         script_cmd[i++]=swap_script(phys_to_bus(&script_data_out[0]));
447         script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (IF (SCR_DATA_IN))); /* data in ? */
448         script_cmd[i++]=swap_script(phys_to_bus(&script_data_in[0]));
449         script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (IF (SCR_STATUS)));  /* status ? */
450         script_cmd[i++]=swap_script(phys_to_bus(&script_status[0]));
451         script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (IF (SCR_COMMAND)));  /* command ? */
452         script_cmd[i++]=swap_script(phys_to_bus(&script_cmd[0]));
453         script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (IF (SCR_MSG_OUT)));  /* message out ? */
454         script_cmd[i++]=swap_script(phys_to_bus(&script_msgout[0]));
455         script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (IF (SCR_MSG_IN))); /* just for error handling message in ? */
456         script_cmd[i++]=swap_script(phys_to_bus(&script_msgin[0]));
457         script_cmd[i++]=swap_script(SCR_INT); /* interrupt if not */
458         script_cmd[i++]=SIR_CMD_OUT_ILL_PH;
459 #ifdef SCSI_SINGLE_STEP
460         start_script_cmd=(unsigned long)&script_cmd[0];
461         len_script_cmd=i*4;
462 #endif
463         i=0;
464         script_data_out[i++]=swap_script(SCR_MOVE_ABS(pccb->datalen)^ SCR_DATA_OUT); /* move */
465         script_data_out[i++]=swap_script(phys_to_bus(pccb->pdata)); /* pointer to buffer */
466         script_data_out[i++]=swap_script(SCR_JUMP ^ IFTRUE (WHEN (SCR_STATUS)));
467         script_data_out[i++]=swap_script(phys_to_bus(&script_status[0]));
468         script_data_out[i++]=swap_script(SCR_INT);
469         script_data_out[i++]=SIR_DATA_OUT_ERR;
470
471 #ifdef SCSI_SINGLE_STEP
472         start_script_data_out=(unsigned long)&script_data_out[0];
473         len_script_data_out=i*4;
474 #endif
475         i=0;
476         script_data_in[i++]=swap_script(SCR_MOVE_ABS(pccb->datalen)^ SCR_DATA_IN); /* move  */
477         script_data_in[i++]=swap_script(phys_to_bus(pccb->pdata)); /* pointer to buffer */
478         script_data_in[i++]=swap_script(SCR_JUMP ^ IFTRUE (WHEN (SCR_STATUS)));
479         script_data_in[i++]=swap_script(phys_to_bus(&script_status[0]));
480         script_data_in[i++]=swap_script(SCR_INT);
481         script_data_in[i++]=SIR_DATA_IN_ERR;
482 #ifdef SCSI_SINGLE_STEP
483         start_script_data_in=(unsigned long)&script_data_in[0];
484         len_script_data_in=i*4;
485 #endif
486         i=0;
487         script_msgin[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN);
488         script_msgin[i++]=swap_script(phys_to_bus(&pccb->msgin[0]));
489         script_msgin[i++]=swap_script(SCR_JUMP ^ IFTRUE (DATA (M_COMPLETE)));
490         script_msgin[i++]=swap_script(phys_to_bus(&script_complete[0]));
491         script_msgin[i++]=swap_script(SCR_JUMP ^ IFTRUE (DATA (M_DISCONNECT)));
492         script_msgin[i++]=swap_script(phys_to_bus(&script_complete[0]));
493         script_msgin[i++]=swap_script(SCR_JUMP ^ IFTRUE (DATA (M_SAVE_DP)));
494         script_msgin[i++]=swap_script(phys_to_bus(&script_complete[0]));
495         script_msgin[i++]=swap_script(SCR_JUMP ^ IFTRUE (DATA (M_RESTORE_DP)));
496         script_msgin[i++]=swap_script(phys_to_bus(&script_complete[0]));
497         script_msgin[i++]=swap_script(SCR_JUMP ^ IFTRUE (DATA (M_EXTENDED)));
498         script_msgin[i++]=swap_script(phys_to_bus(&script_msg_ext[0]));
499         script_msgin[i++]=swap_script(SCR_INT);
500         script_msgin[i++]=SIR_MSG_RECEIVED;
501 #ifdef SCSI_SINGLE_STEP
502         start_script_msgin=(unsigned long)&script_msgin[0];
503         len_script_msgin=i*4;
504 #endif
505         i=0;
506         script_msg_ext[i++]=swap_script(SCR_CLR (SCR_ACK)); /* clear ACK */
507         script_msg_ext[i++]=0;
508         script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* assuming this is the msg length */
509         script_msg_ext[i++]=swap_script(phys_to_bus(&pccb->msgin[1]));
510         script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN)));
511         script_msg_ext[i++]=swap_script(phys_to_bus(&script_complete[0])); /* no more bytes */
512         script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* next */
513         script_msg_ext[i++]=swap_script(phys_to_bus(&pccb->msgin[2]));
514         script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN)));
515         script_msg_ext[i++]=swap_script(phys_to_bus(&script_complete[0])); /* no more bytes */
516         script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* next */
517         script_msg_ext[i++]=swap_script(phys_to_bus(&pccb->msgin[3]));
518         script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN)));
519         script_msg_ext[i++]=swap_script(phys_to_bus(&script_complete[0])); /* no more bytes */
520         script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* next */
521         script_msg_ext[i++]=swap_script(phys_to_bus(&pccb->msgin[4]));
522         script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN)));
523         script_msg_ext[i++]=swap_script(phys_to_bus(&script_complete[0])); /* no more bytes */
524         script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* next */
525         script_msg_ext[i++]=swap_script(phys_to_bus(&pccb->msgin[5]));
526         script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN)));
527         script_msg_ext[i++]=swap_script(phys_to_bus(&script_complete[0])); /* no more bytes */
528         script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* next */
529         script_msg_ext[i++]=swap_script(phys_to_bus(&pccb->msgin[6]));
530         script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN)));
531         script_msg_ext[i++]=swap_script(phys_to_bus(&script_complete[0])); /* no more bytes */
532         script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* next */
533         script_msg_ext[i++]=swap_script(phys_to_bus(&pccb->msgin[7]));
534         script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN)));
535         script_msg_ext[i++]=swap_script(phys_to_bus(&script_complete[0])); /* no more bytes */
536         script_msg_ext[i++]=swap_script(SCR_INT);
537         script_msg_ext[i++]=SIR_MSG_OVER7;
538 #ifdef SCSI_SINGLE_STEP
539         start_script_msg_ext=(unsigned long)&script_msg_ext[0];
540         len_script_msg_ext=i*4;
541 #endif
542         i=0;
543         script_status[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_STATUS);
544         script_status[i++]=swap_script(phys_to_bus(&pccb->status));
545         script_status[i++]=swap_script(SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)));
546         script_status[i++]=swap_script(phys_to_bus(&script_msgin[0]));
547         script_status[i++]=swap_script(SCR_INT);
548         script_status[i++]=SIR_STATUS_ILL_PH;
549 #ifdef SCSI_SINGLE_STEP
550         start_script_status=(unsigned long)&script_status[0];
551         len_script_status=i*4;
552 #endif
553         i=0;
554         script_complete[i++]=swap_script(SCR_REG_REG (SCNTL2, SCR_AND, 0x7f));
555         script_complete[i++]=0;
556         script_complete[i++]=swap_script(SCR_CLR (SCR_ACK|SCR_ATN));
557         script_complete[i++]=0;
558         script_complete[i++]=swap_script(SCR_WAIT_DISC);
559         script_complete[i++]=0;
560         script_complete[i++]=swap_script(SCR_REG_REG(GPREG, SCR_OR, 0x01));
561         script_complete[i++]=0; /* LED OFF */
562         script_complete[i++]=swap_script(SCR_INT);
563         script_complete[i++]=SIR_COMPLETE;
564 #ifdef SCSI_SINGLE_STEP
565         start_script_complete=(unsigned long)&script_complete[0];
566         len_script_complete=i*4;
567 #endif
568         i=0;
569         script_error[i++]=swap_script(SCR_INT); /* interrupt if error */
570         script_error[i++]=SIR_SCRIPT_ERROR;
571 #ifdef SCSI_SINGLE_STEP
572         start_script_error=(unsigned long)&script_error[0];
573         len_script_error=i*4;
574 #endif
575         i=0;
576         script_reselection[i++]=swap_script(SCR_CLR (SCR_TRG)); /* target status */
577         script_reselection[i++]=0;
578         script_reselection[i++]=swap_script(SCR_WAIT_RESEL);
579         script_reselection[i++]=swap_script(phys_to_bus(&script_select[0])); /* len = 4 */
580 #ifdef SCSI_SINGLE_STEP
581         start_script_reselection=(unsigned long)&script_reselection[0];
582         len_script_reselection=i*4;
583 #endif
584 }
585
586
587 void scsi_issue(ccb *pccb)
588 {
589         int busdevfunc = pccb->priv;
590         int i;
591         unsigned short sstat;
592         int retrycnt;  /* retry counter */
593         for(i=0;i<3;i++)
594                 int_stat[i]=0; /* delete all int status */
595         /* struct pccb must be set-up correctly */
596         retrycnt=0;
597         PRINTF("ID %d issue cmd %02X\n",pccb->target,pccb->cmd[0]);
598         pccb->trans_bytes=0; /* no bytes transfered yet */
599         scsi_set_script(pccb); /* fill in SCRIPT                */
600         scsi_int_mask=STO | UDC | MA; /* | CMP; / * Interrupts which are enabled */
601         script_int_mask=0xff; /* enable all Ints */
602         scsi_int_enable();
603         scsi_write_dsp(phys_to_bus(&script_select[0])); /* start script */
604         /* now we have to wait for IRQs */
605 retry:
606         /*
607          * This version of the driver is _not_ interrupt driven,
608          * but polls the chip's interrupt registers (ISTAT, DSTAT).
609          */
610         while(int_stat[0]==0)
611                 handle_scsi_int();
612
613         if(int_stat[0]==SIR_COMPLETE) {
614                 if(pccb->msgin[0]==M_DISCONNECT) {
615                         PRINTF("Wait for reselection\n");
616                         for(i=0;i<3;i++)
617                                 int_stat[i]=0; /* delete all int status */
618                         scsi_write_dsp(phys_to_bus(&script_reselection[0])); /* start reselection script */
619                         goto retry;
620                 }
621                 pccb->contr_stat=SIR_COMPLETE;
622                 return;
623         }
624         if((int_stat[0] & SCSI_INT_STATE)==SCSI_INT_STATE) { /* scsi interrupt */
625                 sstat=(unsigned short)int_stat[0];
626                 if((sstat & STO)==STO) { /* selection timeout */
627                         pccb->contr_stat=SCSI_SEL_TIME_OUT;
628                         scsi_write_byte(GPREG,0x01);
629                         PRINTF("ID: %X Selection Timeout\n",pccb->target);
630                         return;
631                 }
632                 if((sstat & UDC)==UDC) { /* unexpected disconnect */
633                         pccb->contr_stat=SCSI_UNEXP_DIS;
634                         scsi_write_byte(GPREG,0x01);
635                         PRINTF("ID: %X Unexpected Disconnect\n",pccb->target);
636                         return;
637                 }
638                 if((sstat & RSL)==RSL) { /* reselection */
639                         pccb->contr_stat=SCSI_UNEXP_DIS;
640                         scsi_write_byte(GPREG,0x01);
641                         PRINTF("ID: %X Unexpected Disconnect\n",pccb->target);
642                         return;
643                 }
644                 if(((sstat & MA)==MA)||((sstat & HTH)==HTH)) { /* phase missmatch */
645                         if(retrycnt<SCSI_MAX_RETRY) {
646                                 pccb->trans_bytes=pccb->datalen -
647                                         ((unsigned long)scsi_read_byte(DBC) |
648                                         ((unsigned long)scsi_read_byte(DBC+1)<<8) |
649                                         ((unsigned long)scsi_read_byte(DBC+2)<<16));
650                                 for(i=0;i<3;i++)
651                                         int_stat[i]=0; /* delete all int status */
652                                 retrycnt++;
653                                 PRINTF("ID: %X Phase Missmatch Retry %d Phase %02X transfered %lx\n",
654                                                 pccb->target,retrycnt,scsi_read_byte(SBCL),pccb->trans_bytes);
655                                 scsi_write_dsp(phys_to_bus(&script_cmd[4])); /* start retry script */
656                                 goto retry;
657                         }
658                         if((sstat & MA)==MA)
659                                 pccb->contr_stat=SCSI_MA_TIME_OUT;
660                         else
661                                 pccb->contr_stat=SCSI_HNS_TIME_OUT;
662                         PRINTF("Phase Missmatch stat %lx\n",pccb->contr_stat);
663                         return;
664                 } /* no phase int */
665 /*              if((sstat & CMP)==CMP) {
666                         pccb->contr_stat=SIR_COMPLETE;
667                         return;
668                 }
669 */
670                 PRINTF("SCSI INT %lX\n",int_stat[0]);
671                 pccb->contr_stat=int_stat[0];
672                 return;
673         } /* end scsi int */
674         PRINTF("SCRIPT INT %lX phase %02X\n",int_stat[0],scsi_read_byte(SBCL));
675         pccb->contr_stat=int_stat[0];
676         return;
677 }
678
679 int scsi_exec(ccb *pccb)
680 {
681         unsigned char tmpcmd[16],tmpstat;
682         int i,retrycnt,t;
683         unsigned long transbytes,datalen;
684         unsigned char *tmpptr;
685         retrycnt=0;
686 retry:
687         scsi_issue(pccb);
688         if(pccb->contr_stat!=SIR_COMPLETE)
689                 return FALSE;
690         if(pccb->status==S_GOOD)
691                 return TRUE;
692         if(pccb->status==S_CHECK_COND) { /* check condition */
693                 for(i=0;i<16;i++)
694                         tmpcmd[i]=pccb->cmd[i];
695                 pccb->cmd[0]=SCSI_REQ_SENSE;
696                 pccb->cmd[1]=pccb->lun<<5;
697                 pccb->cmd[2]=0;
698                 pccb->cmd[3]=0;
699                 pccb->cmd[4]=14;
700                 pccb->cmd[5]=0;
701                 pccb->cmdlen=6;
702                 pccb->msgout[0]=SCSI_IDENTIFY;
703                 transbytes=pccb->trans_bytes;
704                 tmpptr=pccb->pdata;
705                 pccb->pdata=&pccb->sense_buf[0];
706                 datalen=pccb->datalen;
707                 pccb->datalen=14;
708                 tmpstat=pccb->status;
709                 scsi_issue(pccb);
710                 for(i=0;i<16;i++)
711                         pccb->cmd[i]=tmpcmd[i];
712                 pccb->trans_bytes=transbytes;
713                 pccb->pdata=tmpptr;
714                 pccb->datalen=datalen;
715                 pccb->status=tmpstat;
716                 PRINTF("Request_sense sense key %x ASC %x ASCQ %x\n",pccb->sense_buf[2]&0x0f,
717                         pccb->sense_buf[12],pccb->sense_buf[13]);
718                 switch(pccb->sense_buf[2]&0xf) {
719                         case SENSE_NO_SENSE:
720                         case SENSE_RECOVERED_ERROR:
721                                 /* seems to be ok */
722                                 return TRUE;
723                                 break;
724                         case SENSE_NOT_READY:
725                                 if((pccb->sense_buf[12]!=0x04)||(pccb->sense_buf[13]!=0x01)) {
726                                         /* if device is not in process of becoming ready */
727                                         return FALSE;
728                                         break;
729                                 } /* else fall through */
730                         case SENSE_UNIT_ATTENTION:
731                                 if(retrycnt<SCSI_MAX_RETRY_NOT_READY) {
732                                         PRINTF("Target %d not ready, retry %d\n",pccb->target,retrycnt);
733                                         for(t=0;t<SCSI_NOT_READY_TIME_OUT;t++)
734                                                 udelay(1000); /* 1sec wait */
735                                         retrycnt++;
736                                         goto retry;
737                                 }
738                                 PRINTF("Target %d not ready, %d retried\n",pccb->target,retrycnt);
739                                 return FALSE;
740                         default:
741                                 return FALSE;
742                 }
743         }
744         PRINTF("Status = %X\n",pccb->status);
745         return FALSE;
746 }
747
748
749 void scsi_chip_init(void)
750 {
751         /* first we issue a soft reset */
752         scsi_write_byte(ISTAT,SRST);
753         udelay(1000);
754         scsi_write_byte(ISTAT,0);
755         /* setup chip */
756         scsi_write_byte(SCNTL0,0xC0); /* full arbitration no start, no message, parity disabled, master */
757         scsi_write_byte(SCNTL1,0x00);
758         scsi_write_byte(SCNTL2,0x00);
759 #ifndef CFG_SCSI_SYM53C8XX_CCF    /* config value for none 40 mhz clocks */
760         scsi_write_byte(SCNTL3,0x13); /* synchronous clock 40/4=10MHz, asynchronous 40MHz */
761 #else
762         scsi_write_byte(SCNTL3,CFG_SCSI_SYM53C8XX_CCF); /* config value for none 40 mhz clocks */
763 #endif
764         scsi_write_byte(SCID,0x47); /* ID=7, enable reselection */
765         scsi_write_byte(SXFER,0x00); /* synchronous transfer period 10MHz, asynchronous */
766         scsi_write_byte(SDID,0x00);  /* targed SCSI ID = 0 */
767         scsi_int_mask=0x0000; /* no Interrupt is enabled */
768         script_int_mask=0x00;
769         scsi_int_enable();
770         scsi_write_byte(GPREG,0x01); /* GPIO0 is LED (off) */
771         scsi_write_byte(GPCNTL,0x0E); /* GPIO0 is Output */
772         scsi_write_byte(STIME0,0x08); /* handshake timer disabled, selection timeout 512msec */
773         scsi_write_byte(RESPID,0x80); /* repond only to the own ID (reselection) */
774         scsi_write_byte(STEST1,0x00); /* not isolated, SCLK is used */
775         scsi_write_byte(STEST2,0x00); /* no Lowlevel Mode? */
776         scsi_write_byte(STEST3,0x80); /* enable tolerANT */
777         scsi_write_byte(CTEST3,0x04); /* clear FIFO */
778         scsi_write_byte(CTEST4,0x00);
779         scsi_write_byte(CTEST5,0x00);
780 #ifdef SCSI_SINGLE_STEP
781 /*      scsi_write_byte(DCNTL,IRQM | SSM);      */
782         scsi_write_byte(DCNTL,IRQD | SSM);
783         scsi_write_byte(DMODE,MAN);
784 #else
785 /*      scsi_write_byte(DCNTL,IRQM);    */
786         scsi_write_byte(DCNTL,IRQD);
787         scsi_write_byte(DMODE,0x00);
788 #endif
789 }
790 #endif /* (CONFIG_COMMANDS & CFG_CMD_SCSI) */
791
792
793 #endif /* CONFIG_SCSI_SYM53C8XX */