blob: 29eeccd9a8f79c6934fb94aadc627d1c38debeb2 [file] [log] [blame]
wdenk1df49e22002-09-17 21:37:55 +00001/*
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>
wdenk1df49e22002-09-17 21:37:55 +000041#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
Jon Loeliger82ecaad2007-07-09 17:39:42 -050054#if defined(CONFIG_CMD_SCSI) && defined(CONFIG_SCSI_SYM53C8XX)
wdenk1df49e22002-09-17 21:37:55 +000055
56#undef SCSI_SINGLE_STEP
57/*
58 * Single Step is only used for debug purposes
59 */
60#ifdef SCSI_SINGLE_STEP
61static unsigned long start_script_select;
62static unsigned long start_script_msgout;
63static unsigned long start_script_msgin;
64static unsigned long start_script_msg_ext;
65static unsigned long start_script_cmd;
66static unsigned long start_script_data_in;
67static unsigned long start_script_data_out;
68static unsigned long start_script_status;
69static unsigned long start_script_complete;
70static unsigned long start_script_error;
71static unsigned long start_script_reselection;
72static unsigned int len_script_select;
73static unsigned int len_script_msgout;
74static unsigned int len_script_msgin;
75static unsigned int len_script_msg_ext;
76static unsigned int len_script_cmd;
77static unsigned int len_script_data_in;
78static unsigned int len_script_data_out;
79static unsigned int len_script_status;
80static unsigned int len_script_complete;
81static unsigned int len_script_error;
82static unsigned int len_script_reselection;
83#endif
84
85
86static unsigned short scsi_int_mask; /* shadow register for SCSI related interrupts */
87static unsigned char script_int_mask; /* shadow register for SCRIPT related interrupts */
88static unsigned long script_select[8]; /* script for selection */
89static unsigned long script_msgout[8]; /* script for message out phase (NOT USED) */
90static unsigned long script_msgin[14]; /* script for message in phase */
91static unsigned long script_msg_ext[32]; /* script for message in phase when more than 1 byte message */
92static unsigned long script_cmd[18]; /* script for command phase */
93static unsigned long script_data_in[8]; /* script for data in phase */
94static unsigned long script_data_out[8]; /* script for data out phase */
95static unsigned long script_status[6]; /* script for status phase */
96static unsigned long script_complete[10]; /* script for complete */
97static unsigned long script_reselection[4]; /* script for reselection (NOT USED) */
98static unsigned long script_error[2]; /* script for error handling */
99
100static unsigned long int_stat[3]; /* interrupt status */
101static 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
115void scsi_chip_init(void);
116void handle_scsi_int(void);
117
118
119/********************************************************************************
120 * reports SCSI errors to the user
121 */
122void 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
wdenk1df49e22002-09-17 21:37:55 +0000184/******************************************************************************
185 * sets-up the SCSI controller
186 * the base memory address is retrived via the pci_read_config_dword
187 */
188void 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 */
220unsigned 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
228void scsi_write_byte(ulong offset,unsigned char val)
229{
230 out8(scsi_mem_addr+offset,val);
231}
232
233
234unsigned char scsi_read_byte(ulong offset)
235{
236 return(in8(scsi_mem_addr+offset));
237}
238
239
240/********************************************************************************
241 * interrupt handler
242 */
243void 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);
303end_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
345void 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
367void 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
374void 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 */
390void 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
wdenk1df49e22002-09-17 21:37:55 +0000405void 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
wdenk1df49e22002-09-17 21:37:55 +0000587void 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 */
605retry:
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
679int 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;
686retry:
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
wdenk1df49e22002-09-17 21:37:55 +0000749void 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}
Jon Loeliger82ecaad2007-07-09 17:39:42 -0500790#endif
wdenk1df49e22002-09-17 21:37:55 +0000791
792
793#endif /* CONFIG_SCSI_SYM53C8XX */