1 |
199 |
simons |
/* esp.c: EnhancedScsiProcessor Sun SCSI driver code.
|
2 |
|
|
*
|
3 |
|
|
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
|
4 |
|
|
*/
|
5 |
|
|
|
6 |
|
|
#include <linux/kernel.h>
|
7 |
|
|
#include <linux/delay.h>
|
8 |
|
|
#include <linux/types.h>
|
9 |
|
|
#include <linux/string.h>
|
10 |
|
|
#include <linux/malloc.h>
|
11 |
|
|
#include <linux/blk.h>
|
12 |
|
|
#include <linux/proc_fs.h>
|
13 |
|
|
#include <linux/stat.h>
|
14 |
|
|
|
15 |
|
|
#include "scsi.h"
|
16 |
|
|
#include "hosts.h"
|
17 |
|
|
#include "esp.h"
|
18 |
|
|
|
19 |
|
|
#include <asm/sbus.h>
|
20 |
|
|
#include <asm/dma.h>
|
21 |
|
|
#include <asm/system.h>
|
22 |
|
|
#include <asm/idprom.h>
|
23 |
|
|
#include <asm/machines.h>
|
24 |
|
|
#include <asm/ptrace.h>
|
25 |
|
|
#include <asm/pgtable.h>
|
26 |
|
|
#include <asm/oplib.h>
|
27 |
|
|
#include <asm/vaddrs.h>
|
28 |
|
|
#include <asm/io.h>
|
29 |
|
|
|
30 |
|
|
#define DEBUG_ESP
|
31 |
|
|
/* #define DEBUG_ESP_SG */
|
32 |
|
|
|
33 |
|
|
#if defined(DEBUG_ESP)
|
34 |
|
|
#define ESPLOG(foo) printk foo
|
35 |
|
|
#else
|
36 |
|
|
#define ESPLOG(foo)
|
37 |
|
|
#endif /* (DEBUG_ESP) */
|
38 |
|
|
|
39 |
|
|
#define INTERNAL_ESP_ERROR \
|
40 |
|
|
(panic ("Internal ESP driver error in file %s, line %d\n", \
|
41 |
|
|
__FILE__, __LINE__))
|
42 |
|
|
|
43 |
|
|
#define INTERNAL_ESP_ERROR_NOPANIC \
|
44 |
|
|
(printk ("Internal ESP driver error in file %s, line %d\n", \
|
45 |
|
|
__FILE__, __LINE__))
|
46 |
|
|
|
47 |
|
|
/* This enum will be expanded when we have sync code written. */
|
48 |
|
|
enum {
|
49 |
|
|
not_issued = 0x01, /* Still in the issue_SC queue. */
|
50 |
|
|
in_selection = 0x02, /* ESP is arbitrating, awaiting IRQ */
|
51 |
|
|
in_datain = 0x04, /* Data is transferring over the bus */
|
52 |
|
|
in_dataout = 0x08, /* Data is transferring over the bus */
|
53 |
|
|
in_status = 0x10, /* Awaiting status/msg bytes from target */
|
54 |
|
|
in_finale = 0x11, /* Sent Msg ack, awaiting disconnect */
|
55 |
|
|
};
|
56 |
|
|
|
57 |
|
|
struct proc_dir_entry proc_scsi_esp = {
|
58 |
|
|
PROC_SCSI_ESP, 3, "esp",
|
59 |
|
|
S_IFDIR | S_IRUGO | S_IXUGO, 2
|
60 |
|
|
};
|
61 |
|
|
|
62 |
|
|
struct Sparc_ESP *espchain;
|
63 |
|
|
|
64 |
|
|
static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs);
|
65 |
|
|
static void esp_done(struct Sparc_ESP *esp, int error);
|
66 |
|
|
|
67 |
|
|
/* Debugging routines */
|
68 |
|
|
struct esp_cmdstrings {
|
69 |
|
|
unchar cmdchar;
|
70 |
|
|
char *text;
|
71 |
|
|
} esp_cmd_strings[] = {
|
72 |
|
|
/* Miscellaneous */
|
73 |
|
|
{ ESP_CMD_NULL, "ESP_NOP", },
|
74 |
|
|
{ ESP_CMD_FLUSH, "FIFO_FLUSH", },
|
75 |
|
|
{ ESP_CMD_RC, "RSTESP", },
|
76 |
|
|
{ ESP_CMD_RS, "RSTSCSI", },
|
77 |
|
|
/* Disconnected State Group */
|
78 |
|
|
{ ESP_CMD_RSEL, "RESLCTSEQ", },
|
79 |
|
|
{ ESP_CMD_SEL, "SLCTNATN", },
|
80 |
|
|
{ ESP_CMD_SELA, "SLCTATN", },
|
81 |
|
|
{ ESP_CMD_SELAS, "SLCTATNSTOP", },
|
82 |
|
|
{ ESP_CMD_ESEL, "ENSLCTRESEL", },
|
83 |
|
|
{ ESP_CMD_DSEL, "DISSELRESEL", },
|
84 |
|
|
{ ESP_CMD_SA3, "SLCTATN3", },
|
85 |
|
|
{ ESP_CMD_RSEL3, "RESLCTSEQ", },
|
86 |
|
|
/* Target State Group */
|
87 |
|
|
{ ESP_CMD_SMSG, "SNDMSG", },
|
88 |
|
|
{ ESP_CMD_SSTAT, "SNDSTATUS", },
|
89 |
|
|
{ ESP_CMD_SDATA, "SNDDATA", },
|
90 |
|
|
{ ESP_CMD_DSEQ, "DISCSEQ", },
|
91 |
|
|
{ ESP_CMD_TSEQ, "TERMSEQ", },
|
92 |
|
|
{ ESP_CMD_TCCSEQ, "TRGTCMDCOMPSEQ", },
|
93 |
|
|
{ ESP_CMD_DCNCT, "DISC", },
|
94 |
|
|
{ ESP_CMD_RMSG, "RCVMSG", },
|
95 |
|
|
{ ESP_CMD_RCMD, "RCVCMD", },
|
96 |
|
|
{ ESP_CMD_RDATA, "RCVDATA", },
|
97 |
|
|
{ ESP_CMD_RCSEQ, "RCVCMDSEQ", },
|
98 |
|
|
/* Initiator State Group */
|
99 |
|
|
{ ESP_CMD_TI, "TRANSINFO", },
|
100 |
|
|
{ ESP_CMD_ICCSEQ, "INICMDSEQCOMP", },
|
101 |
|
|
{ ESP_CMD_MOK, "MSGACCEPTED", },
|
102 |
|
|
{ ESP_CMD_TPAD, "TPAD", },
|
103 |
|
|
{ ESP_CMD_SATN, "SATN", },
|
104 |
|
|
{ ESP_CMD_RATN, "RATN", },
|
105 |
|
|
};
|
106 |
|
|
#define NUM_ESP_COMMANDS ((sizeof(esp_cmd_strings)) / (sizeof(struct esp_cmdstrings)))
|
107 |
|
|
|
108 |
|
|
/* Print textual representation of an ESP command */
|
109 |
|
|
static inline void esp_print_cmd(unchar espcmd)
|
110 |
|
|
{
|
111 |
|
|
unchar dma_bit = espcmd & ESP_CMD_DMA;
|
112 |
|
|
int i;
|
113 |
|
|
|
114 |
|
|
espcmd &= ~dma_bit;
|
115 |
|
|
for(i=0; i<NUM_ESP_COMMANDS; i++)
|
116 |
|
|
if(esp_cmd_strings[i].cmdchar == espcmd)
|
117 |
|
|
break;
|
118 |
|
|
if(i==NUM_ESP_COMMANDS)
|
119 |
|
|
printk("ESP_Unknown");
|
120 |
|
|
else
|
121 |
|
|
printk("%s%s", esp_cmd_strings[i].text,
|
122 |
|
|
((dma_bit) ? "+DMA" : ""));
|
123 |
|
|
}
|
124 |
|
|
|
125 |
|
|
/* Print the status register's value */
|
126 |
|
|
static inline void esp_print_statreg(unchar statreg)
|
127 |
|
|
{
|
128 |
|
|
unchar phase;
|
129 |
|
|
|
130 |
|
|
printk("STATUS<");
|
131 |
|
|
phase = statreg & ESP_STAT_PMASK;
|
132 |
|
|
printk("%s,", (phase == ESP_DOP ? "DATA-OUT" :
|
133 |
|
|
(phase == ESP_DIP ? "DATA-IN" :
|
134 |
|
|
(phase == ESP_CMDP ? "COMMAND" :
|
135 |
|
|
(phase == ESP_STATP ? "STATUS" :
|
136 |
|
|
(phase == ESP_MOP ? "MSG-OUT" :
|
137 |
|
|
(phase == ESP_MIP ? "MSG_IN" :
|
138 |
|
|
"unknown")))))));
|
139 |
|
|
if(statreg & ESP_STAT_TDONE)
|
140 |
|
|
printk("TRANS_DONE,");
|
141 |
|
|
if(statreg & ESP_STAT_TCNT)
|
142 |
|
|
printk("TCOUNT_ZERO,");
|
143 |
|
|
if(statreg & ESP_STAT_PERR)
|
144 |
|
|
printk("P_ERROR,");
|
145 |
|
|
if(statreg & ESP_STAT_SPAM)
|
146 |
|
|
printk("SPAM,");
|
147 |
|
|
if(statreg & ESP_STAT_INTR)
|
148 |
|
|
printk("IRQ,");
|
149 |
|
|
printk(">");
|
150 |
|
|
}
|
151 |
|
|
|
152 |
|
|
/* Print the interrupt register's value */
|
153 |
|
|
static inline void esp_print_ireg(unchar intreg)
|
154 |
|
|
{
|
155 |
|
|
printk("INTREG< ");
|
156 |
|
|
if(intreg & ESP_INTR_S)
|
157 |
|
|
printk("SLCT_NATN ");
|
158 |
|
|
if(intreg & ESP_INTR_SATN)
|
159 |
|
|
printk("SLCT_ATN ");
|
160 |
|
|
if(intreg & ESP_INTR_RSEL)
|
161 |
|
|
printk("RSLCT ");
|
162 |
|
|
if(intreg & ESP_INTR_FDONE)
|
163 |
|
|
printk("FDONE ");
|
164 |
|
|
if(intreg & ESP_INTR_BSERV)
|
165 |
|
|
printk("BSERV ");
|
166 |
|
|
if(intreg & ESP_INTR_DC)
|
167 |
|
|
printk("DISCNCT ");
|
168 |
|
|
if(intreg & ESP_INTR_IC)
|
169 |
|
|
printk("ILL_CMD ");
|
170 |
|
|
if(intreg & ESP_INTR_SR)
|
171 |
|
|
printk("SCSI_BUS_RESET ");
|
172 |
|
|
printk(">");
|
173 |
|
|
}
|
174 |
|
|
|
175 |
|
|
/* Print the sequence step registers contents */
|
176 |
|
|
static inline void esp_print_seqreg(unchar stepreg)
|
177 |
|
|
{
|
178 |
|
|
stepreg &= ESP_STEP_VBITS;
|
179 |
|
|
printk("STEP<%s>",
|
180 |
|
|
(stepreg == ESP_STEP_ASEL ? "SLCT_ARB_CMPLT" :
|
181 |
|
|
(stepreg == ESP_STEP_SID ? "1BYTE_MSG_SENT" :
|
182 |
|
|
(stepreg == ESP_STEP_NCMD ? "NOT_IN_CMD_PHASE" :
|
183 |
|
|
(stepreg == ESP_STEP_PPC ? "CMD_BYTES_LOST" :
|
184 |
|
|
(stepreg == ESP_STEP_FINI ? "CMD_SENT_OK" :
|
185 |
|
|
"UNKNOWN"))))));
|
186 |
|
|
}
|
187 |
|
|
|
188 |
|
|
/* Manipulation of the ESP command queues. Thanks to the aha152x driver
|
189 |
|
|
* and its author, Juergen E. Fischer, for the methods used here.
|
190 |
|
|
* Note that these are per-ESP queues, not global queues like
|
191 |
|
|
* the aha152x driver uses.
|
192 |
|
|
*/
|
193 |
|
|
static inline void append_SC(Scsi_Cmnd **SC, Scsi_Cmnd *new_SC)
|
194 |
|
|
{
|
195 |
|
|
Scsi_Cmnd *end;
|
196 |
|
|
unsigned long flags;
|
197 |
|
|
|
198 |
|
|
save_flags(flags); cli();
|
199 |
|
|
new_SC->host_scribble = (unsigned char *) NULL;
|
200 |
|
|
if(!*SC)
|
201 |
|
|
*SC = new_SC;
|
202 |
|
|
else {
|
203 |
|
|
for(end=*SC;end->host_scribble;end=(Scsi_Cmnd *)end->host_scribble)
|
204 |
|
|
;
|
205 |
|
|
end->host_scribble = (unsigned char *) new_SC;
|
206 |
|
|
}
|
207 |
|
|
restore_flags(flags);
|
208 |
|
|
}
|
209 |
|
|
|
210 |
|
|
static inline Scsi_Cmnd *remove_first_SC(Scsi_Cmnd **SC)
|
211 |
|
|
{
|
212 |
|
|
Scsi_Cmnd *ptr;
|
213 |
|
|
unsigned long flags;
|
214 |
|
|
|
215 |
|
|
save_flags(flags); cli();
|
216 |
|
|
ptr = *SC;
|
217 |
|
|
if(ptr)
|
218 |
|
|
*SC = (Scsi_Cmnd *) (*SC)->host_scribble;
|
219 |
|
|
restore_flags(flags);
|
220 |
|
|
return ptr;
|
221 |
|
|
}
|
222 |
|
|
|
223 |
|
|
static inline Scsi_Cmnd *remove_SC(Scsi_Cmnd **SC, int target, int lun)
|
224 |
|
|
{
|
225 |
|
|
Scsi_Cmnd *ptr, *prev;
|
226 |
|
|
unsigned long flags;
|
227 |
|
|
|
228 |
|
|
save_flags(flags); cli();
|
229 |
|
|
for(ptr = *SC, prev = NULL;
|
230 |
|
|
ptr && ((ptr->target != target) || (ptr->lun != lun));
|
231 |
|
|
prev = ptr, ptr = (Scsi_Cmnd *) ptr->host_scribble)
|
232 |
|
|
;
|
233 |
|
|
if(ptr) {
|
234 |
|
|
if(prev)
|
235 |
|
|
prev->host_scribble=ptr->host_scribble;
|
236 |
|
|
else
|
237 |
|
|
*SC=(Scsi_Cmnd *)ptr->host_scribble;
|
238 |
|
|
}
|
239 |
|
|
restore_flags(flags);
|
240 |
|
|
return ptr;
|
241 |
|
|
}
|
242 |
|
|
|
243 |
|
|
static inline void do_pause(unsigned amount)
|
244 |
|
|
{
|
245 |
|
|
unsigned long the_time = jiffies + amount;
|
246 |
|
|
|
247 |
|
|
while(jiffies < the_time)
|
248 |
|
|
barrier(); /* Not really needed, but... */
|
249 |
|
|
}
|
250 |
|
|
|
251 |
|
|
/* This places the ESP into a known state at boot time. */
|
252 |
|
|
static inline void esp_bootup_reset(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs)
|
253 |
|
|
{
|
254 |
|
|
struct sparc_dma_registers *dregs = esp->dregs;
|
255 |
|
|
volatile unchar trash;
|
256 |
|
|
|
257 |
|
|
/* Punt the DVMA into a known state. */
|
258 |
|
|
dregs->cond_reg |= DMA_RST_SCSI;
|
259 |
|
|
do_pause(100);
|
260 |
|
|
dregs->cond_reg &= ~(DMA_RST_SCSI);
|
261 |
|
|
if(esp->dma->revision == dvmarev2)
|
262 |
|
|
if(esp->erev != esp100)
|
263 |
|
|
dregs->cond_reg |= DMA_3CLKS;
|
264 |
|
|
else if(esp->dma->revision == dvmarev3)
|
265 |
|
|
if(esp->erev == fas236 || esp->erev == fas100a) {
|
266 |
|
|
dregs->cond_reg &= ~(DMA_3CLKS);
|
267 |
|
|
dregs->cond_reg |= DMA_2CLKS;
|
268 |
|
|
}
|
269 |
|
|
else if(esp->dma->revision == dvmaesc1)
|
270 |
|
|
dregs->cond_reg |= DMA_ADD_ENABLE;
|
271 |
|
|
DMA_INTSON(dregs);
|
272 |
|
|
|
273 |
|
|
/* Now reset the ESP chip */
|
274 |
|
|
eregs->esp_cmd = ESP_CMD_RC;
|
275 |
|
|
eregs->esp_cmd = (ESP_CMD_NULL | ESP_CMD_DMA);
|
276 |
|
|
eregs->esp_cmd = (ESP_CMD_NULL | ESP_CMD_DMA); /* borken hardware... */
|
277 |
|
|
|
278 |
|
|
/* Reload the configuration registers */
|
279 |
|
|
eregs->esp_cfg1 = esp->config1;
|
280 |
|
|
eregs->esp_cfact = esp->cfact;
|
281 |
|
|
eregs->esp_stp = 0;
|
282 |
|
|
eregs->esp_soff = 0;
|
283 |
|
|
eregs->esp_timeo = esp->sync_defp;
|
284 |
|
|
if(esp->erev == esp100a || esp->erev == esp236)
|
285 |
|
|
eregs->esp_cfg2 = esp->config2;
|
286 |
|
|
if(esp->erev == esp236)
|
287 |
|
|
eregs->esp_cfg3 = esp->config3[0];
|
288 |
|
|
/* Eat any bitrot in the chip */
|
289 |
|
|
trash = eregs->esp_intrpt;
|
290 |
|
|
|
291 |
|
|
/* Reset the SCSI bus, but tell ESP not to generate an irq */
|
292 |
|
|
eregs->esp_cfg1 |= ESP_CONFIG1_SRRDISAB;
|
293 |
|
|
eregs->esp_cmd = ESP_CMD_RS;
|
294 |
|
|
do_pause(200);
|
295 |
|
|
eregs->esp_cfg1 = esp->config1;
|
296 |
|
|
|
297 |
|
|
/* Eat any bitrot in the chip and we are done... */
|
298 |
|
|
trash = eregs->esp_intrpt;
|
299 |
|
|
}
|
300 |
|
|
|
301 |
|
|
/* Detecting ESP chips on the machine. This is the simple and easy
|
302 |
|
|
* version.
|
303 |
|
|
*/
|
304 |
|
|
int esp_detect(Scsi_Host_Template *tpnt)
|
305 |
|
|
{
|
306 |
|
|
struct Sparc_ESP *esp, *elink;
|
307 |
|
|
struct Scsi_Host *esp_host;
|
308 |
|
|
struct linux_sbus *sbus;
|
309 |
|
|
struct linux_sbus_device *esp_dev, *sbdev_iter;
|
310 |
|
|
struct Sparc_ESP_regs *eregs;
|
311 |
|
|
struct sparc_dma_registers *dregs;
|
312 |
|
|
struct Linux_SBus_DMA *dma, *dlink;
|
313 |
|
|
unsigned int fmhz;
|
314 |
|
|
unchar ccf, bsizes, bsizes_more;
|
315 |
|
|
int nesps = 0;
|
316 |
|
|
int esp_node;
|
317 |
|
|
|
318 |
|
|
espchain = 0;
|
319 |
|
|
if(!SBus_chain)
|
320 |
|
|
panic("No SBUS in esp_detect()");
|
321 |
|
|
for_each_sbus(sbus) {
|
322 |
|
|
for_each_sbusdev(sbdev_iter, sbus) {
|
323 |
|
|
/* Is it an esp sbus device? */
|
324 |
|
|
esp_dev = sbdev_iter;
|
325 |
|
|
if(strcmp(esp_dev->prom_name, "esp") &&
|
326 |
|
|
strcmp(esp_dev->prom_name, "SUNW,esp")) {
|
327 |
|
|
if(!esp_dev->child ||
|
328 |
|
|
strcmp(esp_dev->prom_name, "espdma"))
|
329 |
|
|
continue; /* nope... */
|
330 |
|
|
esp_dev = esp_dev->child;
|
331 |
|
|
if(strcmp(esp_dev->prom_name, "esp") &&
|
332 |
|
|
strcmp(esp_dev->prom_name, "SUNW,esp"))
|
333 |
|
|
continue; /* how can this happen? */
|
334 |
|
|
}
|
335 |
|
|
esp_host = scsi_register(tpnt, sizeof(struct Sparc_ESP));
|
336 |
|
|
if(!esp_host)
|
337 |
|
|
panic("Cannot register ESP SCSI host");
|
338 |
|
|
esp = (struct Sparc_ESP *) esp_host->hostdata;
|
339 |
|
|
if(!esp)
|
340 |
|
|
panic("No esp in hostdata");
|
341 |
|
|
esp->ehost = esp_host;
|
342 |
|
|
esp->edev = esp_dev;
|
343 |
|
|
/* Put into the chain of esp chips detected */
|
344 |
|
|
if(espchain) {
|
345 |
|
|
elink = espchain;
|
346 |
|
|
while(elink->next) elink = elink->next;
|
347 |
|
|
elink->next = esp;
|
348 |
|
|
} else {
|
349 |
|
|
espchain = esp;
|
350 |
|
|
}
|
351 |
|
|
esp->next = 0;
|
352 |
|
|
|
353 |
|
|
/* Get misc. prom information */
|
354 |
|
|
#define ESP_IS_MY_DVMA(esp, dma) \
|
355 |
|
|
((esp->edev->my_bus == dma->SBus_dev->my_bus) && \
|
356 |
|
|
(esp->edev->slot == dma->SBus_dev->slot) && \
|
357 |
|
|
(!strcmp(dma->SBus_dev->prom_name, "dma") || \
|
358 |
|
|
!strcmp(dma->SBus_dev->prom_name, "espdma")))
|
359 |
|
|
|
360 |
|
|
esp_node = esp_dev->prom_node;
|
361 |
|
|
prom_getstring(esp_node, "name", esp->prom_name,
|
362 |
|
|
sizeof(esp->prom_name));
|
363 |
|
|
esp->prom_node = esp_node;
|
364 |
|
|
for_each_dvma(dlink) {
|
365 |
|
|
if(ESP_IS_MY_DVMA(esp, dlink) && !dlink->allocated)
|
366 |
|
|
break;
|
367 |
|
|
}
|
368 |
|
|
#undef ESP_IS_MY_DVMA
|
369 |
|
|
/* If we don't know how to handle the dvma, do not use this device */
|
370 |
|
|
if(!dlink){
|
371 |
|
|
printk ("Cannot find dvma for ESP SCSI\n");
|
372 |
|
|
scsi_unregister (esp_host);
|
373 |
|
|
continue;
|
374 |
|
|
}
|
375 |
|
|
if (dlink->allocated){
|
376 |
|
|
printk ("esp: can't use my espdma\n");
|
377 |
|
|
scsi_unregister (esp_host);
|
378 |
|
|
continue;
|
379 |
|
|
}
|
380 |
|
|
dlink->allocated = 1;
|
381 |
|
|
dma = dlink;
|
382 |
|
|
esp->dma = dma;
|
383 |
|
|
esp->dregs = dregs = dma->regs;
|
384 |
|
|
|
385 |
|
|
/* Map in the ESP registers from I/O space */
|
386 |
|
|
prom_apply_sbus_ranges(esp->edev->reg_addrs, 1);
|
387 |
|
|
esp->eregs = eregs = (struct Sparc_ESP_regs *)
|
388 |
|
|
sparc_alloc_io(esp->edev->reg_addrs[0].phys_addr, 0,
|
389 |
|
|
PAGE_SIZE, "ESP Registers",
|
390 |
|
|
esp->edev->reg_addrs[0].which_io, 0x0);
|
391 |
|
|
if(!eregs)
|
392 |
|
|
panic("ESP registers unmappable");
|
393 |
|
|
esp->esp_command =
|
394 |
|
|
sparc_dvma_malloc(16, "ESP DVMA Cmd Block");
|
395 |
|
|
if(!esp->esp_command)
|
396 |
|
|
panic("ESP DVMA transport area unmappable");
|
397 |
|
|
|
398 |
|
|
/* Set up the irq's etc. */
|
399 |
|
|
esp->ehost->base = (unsigned char *) esp->eregs;
|
400 |
|
|
esp->ehost->io_port = (unsigned int) esp->eregs;
|
401 |
|
|
esp->ehost->n_io_port = (unsigned char)
|
402 |
|
|
esp->edev->reg_addrs[0].reg_size;
|
403 |
|
|
/* XXX The following may be different on sun4ms XXX */
|
404 |
|
|
esp->ehost->irq = esp->irq = esp->edev->irqs[0].pri;
|
405 |
|
|
|
406 |
|
|
/* Allocate the irq only if necessary */
|
407 |
|
|
for_each_esp(elink) {
|
408 |
|
|
if((elink != esp) && (esp->irq == elink->irq)) {
|
409 |
|
|
goto esp_irq_acquired; /* BASIC rulez */
|
410 |
|
|
}
|
411 |
|
|
}
|
412 |
|
|
/* XXX We have shared interrupts per level now, maybe
|
413 |
|
|
* XXX use them, maybe not...
|
414 |
|
|
*/
|
415 |
|
|
if(request_irq(esp->ehost->irq, esp_intr, SA_INTERRUPT,
|
416 |
|
|
"Sparc ESP SCSI", NULL))
|
417 |
|
|
panic("Cannot acquire ESP irq line");
|
418 |
|
|
esp_irq_acquired:
|
419 |
|
|
printk("esp%d: IRQ %d ", nesps, esp->ehost->irq);
|
420 |
|
|
/* Figure out our scsi ID on the bus */
|
421 |
|
|
esp->scsi_id = prom_getintdefault(esp->prom_node,
|
422 |
|
|
"initiator-id", -1);
|
423 |
|
|
if(esp->scsi_id == -1)
|
424 |
|
|
esp->scsi_id = prom_getintdefault(esp->prom_node,
|
425 |
|
|
"scsi-initiator-id", -1);
|
426 |
|
|
if(esp->scsi_id == -1)
|
427 |
|
|
esp->scsi_id =
|
428 |
|
|
prom_getintdefault(esp->edev->my_bus->prom_node,
|
429 |
|
|
"scsi-initiator-id", 7);
|
430 |
|
|
esp->ehost->this_id = esp->scsi_id;
|
431 |
|
|
esp->scsi_id_mask = (1 << esp->scsi_id);
|
432 |
|
|
/* Check for differential bus */
|
433 |
|
|
esp->diff = prom_getintdefault(esp->prom_node, "differential", -1);
|
434 |
|
|
esp->diff = (esp->diff == -1) ? 0 : 1;
|
435 |
|
|
/* Check out the clock properties of the chip */
|
436 |
|
|
fmhz = prom_getintdefault(esp->prom_node, "clock-frequency", -1);
|
437 |
|
|
if(fmhz==-1)
|
438 |
|
|
fmhz = prom_getintdefault(esp->edev->my_bus->prom_node,
|
439 |
|
|
"clock-frequency", -1);
|
440 |
|
|
if(fmhz <= (5000))
|
441 |
|
|
ccf = 0;
|
442 |
|
|
else
|
443 |
|
|
ccf = (((5000 - 1) + (fmhz))/(5000));
|
444 |
|
|
if(!ccf || ccf > 8) {
|
445 |
|
|
ccf = ESP_CCF_F4;
|
446 |
|
|
fmhz = (5000 * 4);
|
447 |
|
|
}
|
448 |
|
|
if(ccf==(ESP_CCF_F7+1))
|
449 |
|
|
esp->cfact = ESP_CCF_F0;
|
450 |
|
|
else if(ccf == ESP_CCF_NEVER)
|
451 |
|
|
esp->cfact = ESP_CCF_F2;
|
452 |
|
|
else
|
453 |
|
|
esp->cfact = ccf;
|
454 |
|
|
esp->cfreq = fmhz;
|
455 |
|
|
esp->ccycle = ((1000000000) / ((fmhz)/1000));
|
456 |
|
|
esp->ctick = ((7682 * esp->cfact * esp->ccycle)/1000);
|
457 |
|
|
esp->sync_defp = ((7682 + esp->ctick - 1) / esp->ctick);
|
458 |
|
|
|
459 |
|
|
/* XXX HACK HACK HACK XXX */
|
460 |
|
|
if (esp->sync_defp < 153)
|
461 |
|
|
esp->sync_defp = 153;
|
462 |
|
|
|
463 |
|
|
printk("SCSI ID %d Clock %d MHz Period %2x ", esp->scsi_id,
|
464 |
|
|
(fmhz / 1000), esp->sync_defp);
|
465 |
|
|
|
466 |
|
|
/* Find the burst sizes this dma supports. */
|
467 |
|
|
bsizes = prom_getintdefault(esp->prom_node, "burst-sizes", 0xff);
|
468 |
|
|
bsizes_more = prom_getintdefault(esp->edev->my_bus->prom_node,
|
469 |
|
|
"burst-sizes", 0xff);
|
470 |
|
|
if(bsizes_more != 0xff) bsizes &= bsizes_more;
|
471 |
|
|
if(bsizes == 0xff || (bsizes & DMA_BURST16)==0 ||
|
472 |
|
|
(bsizes & DMA_BURST32)==0)
|
473 |
|
|
bsizes = (DMA_BURST32 - 1);
|
474 |
|
|
esp->bursts = bsizes;
|
475 |
|
|
|
476 |
|
|
/* Probe the revision of this esp */
|
477 |
|
|
esp->config1 = (ESP_CONFIG1_PENABLE | (esp->scsi_id & 7));
|
478 |
|
|
esp->config2 = (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY);
|
479 |
|
|
esp->config3[0] = ESP_CONFIG3_TENB;
|
480 |
|
|
eregs->esp_cfg2 = esp->config2;
|
481 |
|
|
if((eregs->esp_cfg2 & ~(ESP_CONFIG2_MAGIC)) !=
|
482 |
|
|
(ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY)) {
|
483 |
|
|
printk("NCR53C90(esp100) detected\n");
|
484 |
|
|
esp->erev = esp100;
|
485 |
|
|
} else {
|
486 |
|
|
eregs->esp_cfg2 = esp->config2 = 0;
|
487 |
|
|
eregs->esp_cfg3 = 0;
|
488 |
|
|
eregs->esp_cfg3 = esp->config3[0] = 5;
|
489 |
|
|
if(eregs->esp_cfg3 != 5) {
|
490 |
|
|
printk("NCR53C90A(esp100a) detected\n");
|
491 |
|
|
esp->erev = esp100a;
|
492 |
|
|
} else {
|
493 |
|
|
int target;
|
494 |
|
|
|
495 |
|
|
for(target=0; target<8; target++)
|
496 |
|
|
esp->config3[target] = 0;
|
497 |
|
|
eregs->esp_cfg3 = 0;
|
498 |
|
|
if(esp->cfact > ESP_CCF_F5) {
|
499 |
|
|
printk("NCR53C9XF(espfast) detected\n");
|
500 |
|
|
esp->erev = fast;
|
501 |
|
|
esp->config2 |= ESP_CONFIG2_FENAB;
|
502 |
|
|
eregs->esp_cfg2 = esp->config2;
|
503 |
|
|
} else {
|
504 |
|
|
printk("NCR53C9x(esp236) detected\n");
|
505 |
|
|
esp->erev = esp236;
|
506 |
|
|
eregs->esp_cfg2 = esp->config2 = 0;
|
507 |
|
|
}
|
508 |
|
|
}
|
509 |
|
|
}
|
510 |
|
|
|
511 |
|
|
/* Initialize the command queues */
|
512 |
|
|
esp->current_SC = 0;
|
513 |
|
|
esp->disconnected_SC = 0;
|
514 |
|
|
esp->issue_SC = 0;
|
515 |
|
|
|
516 |
|
|
/* Reset the thing before we try anything... */
|
517 |
|
|
esp_bootup_reset(esp, eregs);
|
518 |
|
|
|
519 |
|
|
nesps++;
|
520 |
|
|
#ifdef THREADED_ESP_DRIVER
|
521 |
|
|
kernel_thread(esp_kernel_thread, esp, 0);
|
522 |
|
|
#endif
|
523 |
|
|
} /* for each sbusdev */
|
524 |
|
|
} /* for each sbus */
|
525 |
|
|
return nesps;
|
526 |
|
|
}
|
527 |
|
|
|
528 |
|
|
/*
|
529 |
|
|
* The info function will return whatever useful
|
530 |
|
|
* information the developer sees fit. If not provided, then
|
531 |
|
|
* the name field will be used instead.
|
532 |
|
|
*/
|
533 |
|
|
const char *esp_info(struct Scsi_Host *host)
|
534 |
|
|
{
|
535 |
|
|
struct Sparc_ESP *esp;
|
536 |
|
|
|
537 |
|
|
esp = (struct Sparc_ESP *) host->hostdata;
|
538 |
|
|
switch(esp->erev) {
|
539 |
|
|
case esp100:
|
540 |
|
|
return "Sparc ESP100 (NCR53C90)";
|
541 |
|
|
case esp100a:
|
542 |
|
|
return "Sparc ESP100A (NCR53C90A)";
|
543 |
|
|
case esp236:
|
544 |
|
|
return "Sparc ESP236";
|
545 |
|
|
case fast:
|
546 |
|
|
return "Sparc ESP-FAST (236 or 100A)";
|
547 |
|
|
case fas236:
|
548 |
|
|
return "Sparc ESP236-FAST";
|
549 |
|
|
case fas100a:
|
550 |
|
|
return "Sparc ESP100A-FAST";
|
551 |
|
|
default:
|
552 |
|
|
panic("Bogon ESP revision");
|
553 |
|
|
};
|
554 |
|
|
}
|
555 |
|
|
|
556 |
|
|
/* Execute a SCSI command when the bus is free. All callers
|
557 |
|
|
* turn off all interrupts, so we don't need to explicitly do
|
558 |
|
|
* it here.
|
559 |
|
|
*/
|
560 |
|
|
static inline void esp_exec_cmd(struct Sparc_ESP *esp)
|
561 |
|
|
{
|
562 |
|
|
struct sparc_dma_registers *dregs;
|
563 |
|
|
struct Sparc_ESP_regs *eregs;
|
564 |
|
|
Scsi_Cmnd *SCptr;
|
565 |
|
|
int i;
|
566 |
|
|
|
567 |
|
|
eregs = esp->eregs;
|
568 |
|
|
dregs = esp->dregs;
|
569 |
|
|
|
570 |
|
|
/* Grab first member of the issue queue. */
|
571 |
|
|
SCptr = esp->current_SC = remove_first_SC(&esp->issue_SC);
|
572 |
|
|
if(!SCptr)
|
573 |
|
|
goto bad;
|
574 |
|
|
SCptr->SCp.phase = in_selection;
|
575 |
|
|
|
576 |
|
|
/* NCR docs say:
|
577 |
|
|
* 1) Load select/reselect Bus ID register with target ID
|
578 |
|
|
* 2) Load select/reselect Timeout Reg with desired value
|
579 |
|
|
* 3) Load Synchronous offset register with zero (for
|
580 |
|
|
* asynchronous transfers).
|
581 |
|
|
* 4) Load Synchronous Transfer Period register (if
|
582 |
|
|
* synchronous)
|
583 |
|
|
* 5) Load FIFO with 6, 10, or 12 byte SCSI command
|
584 |
|
|
* 6) Issue SELECTION_WITHOUT_ATTENTION command
|
585 |
|
|
*
|
586 |
|
|
* They also mention that a DMA NOP command must be issued
|
587 |
|
|
* to the SCSI chip under many circumstances, plus it's
|
588 |
|
|
* also a good idea to flush out the fifo just in case.
|
589 |
|
|
*/
|
590 |
|
|
|
591 |
|
|
/* Load zeros into COUNTER via 2 DMA NOP chip commands
|
592 |
|
|
* due to flaky implementations of the 53C9x which don't
|
593 |
|
|
* get the idea the first time around.
|
594 |
|
|
*/
|
595 |
|
|
dregs->cond_reg = (DMA_INT_ENAB | DMA_FIFO_INV);
|
596 |
|
|
|
597 |
|
|
eregs->esp_tclow = 0;
|
598 |
|
|
eregs->esp_tcmed = 0;
|
599 |
|
|
eregs->esp_cmd = (ESP_CMD_NULL | ESP_CMD_DMA);
|
600 |
|
|
|
601 |
|
|
/* Flush the fifo of excess garbage. */
|
602 |
|
|
eregs->esp_cmd = ESP_CMD_FLUSH;
|
603 |
|
|
|
604 |
|
|
/* Load bus-id and timeout values. */
|
605 |
|
|
eregs->esp_busid = (SCptr->target & 7);
|
606 |
|
|
eregs->esp_timeo = esp->sync_defp;
|
607 |
|
|
|
608 |
|
|
eregs->esp_soff = 0; /* This means async transfer... */
|
609 |
|
|
eregs->esp_stp = 0;
|
610 |
|
|
|
611 |
|
|
/* Load FIFO with the actual SCSI command. */
|
612 |
|
|
for(i=0; i < SCptr->cmd_len; i++)
|
613 |
|
|
eregs->esp_fdata = SCptr->cmnd[i];
|
614 |
|
|
|
615 |
|
|
/* Make sure the dvma forwards the ESP interrupt. */
|
616 |
|
|
dregs->cond_reg = DMA_INT_ENAB;
|
617 |
|
|
|
618 |
|
|
/* Tell ESP to SELECT without asserting ATN. */
|
619 |
|
|
eregs->esp_cmd = ESP_CMD_SEL;
|
620 |
|
|
return;
|
621 |
|
|
|
622 |
|
|
bad:
|
623 |
|
|
panic("esp: daaarrrkk starrr crashesss....");
|
624 |
|
|
}
|
625 |
|
|
|
626 |
|
|
/* Queue a SCSI command delivered from the mid-level Linux SCSI code. */
|
627 |
|
|
int esp_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
|
628 |
|
|
{
|
629 |
|
|
struct Sparc_ESP *esp;
|
630 |
|
|
unsigned long flags;
|
631 |
|
|
|
632 |
|
|
save_flags(flags); cli();
|
633 |
|
|
|
634 |
|
|
/* Set up func ptr and initial driver cmd-phase. */
|
635 |
|
|
SCpnt->scsi_done = done;
|
636 |
|
|
SCpnt->SCp.phase = not_issued;
|
637 |
|
|
|
638 |
|
|
esp = (struct Sparc_ESP *) SCpnt->host->hostdata;
|
639 |
|
|
|
640 |
|
|
/* We use the scratch area. */
|
641 |
|
|
if(!SCpnt->use_sg) {
|
642 |
|
|
SCpnt->SCp.this_residual = SCpnt->request_bufflen;
|
643 |
|
|
SCpnt->SCp.buffer =
|
644 |
|
|
(struct scatterlist *) SCpnt->request_buffer;
|
645 |
|
|
SCpnt->SCp.buffers_residual = 0;
|
646 |
|
|
SCpnt->SCp.Status = CHECK_CONDITION;
|
647 |
|
|
SCpnt->SCp.Message = 0;
|
648 |
|
|
SCpnt->SCp.have_data_in = 0;
|
649 |
|
|
SCpnt->SCp.sent_command = 0;
|
650 |
|
|
SCpnt->SCp.ptr = mmu_get_scsi_one((char *)SCpnt->SCp.buffer,
|
651 |
|
|
SCpnt->SCp.this_residual,
|
652 |
|
|
esp->edev->my_bus);
|
653 |
|
|
} else {
|
654 |
|
|
#ifdef DEBUG_ESP_SG
|
655 |
|
|
printk("esp: sglist at %p with %d buffers\n",
|
656 |
|
|
SCpnt->buffer, SCpnt->use_sg);
|
657 |
|
|
#endif
|
658 |
|
|
SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->buffer;
|
659 |
|
|
SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1;
|
660 |
|
|
SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;
|
661 |
|
|
mmu_get_scsi_sgl((struct mmu_sglist *) SCpnt->SCp.buffer,
|
662 |
|
|
SCpnt->SCp.buffers_residual,
|
663 |
|
|
esp->edev->my_bus);
|
664 |
|
|
SCpnt->SCp.ptr = (char *) SCpnt->SCp.buffer->alt_address;
|
665 |
|
|
}
|
666 |
|
|
|
667 |
|
|
/* Place into our queue. */
|
668 |
|
|
append_SC(&esp->issue_SC, SCpnt);
|
669 |
|
|
|
670 |
|
|
/* Run it now if we can */
|
671 |
|
|
if(!esp->current_SC)
|
672 |
|
|
esp_exec_cmd(esp);
|
673 |
|
|
|
674 |
|
|
restore_flags(flags);
|
675 |
|
|
return 0;
|
676 |
|
|
}
|
677 |
|
|
|
678 |
|
|
/* Only queuing supported in this ESP driver. */
|
679 |
|
|
int esp_command(Scsi_Cmnd *SCpnt)
|
680 |
|
|
{
|
681 |
|
|
ESPLOG(("esp: esp_command() called...\n"));
|
682 |
|
|
return -1;
|
683 |
|
|
}
|
684 |
|
|
|
685 |
|
|
/* Abort a command. Those that are on the bus force a SCSI bus
|
686 |
|
|
* reset.
|
687 |
|
|
*/
|
688 |
|
|
int esp_abort(Scsi_Cmnd *SCpnt)
|
689 |
|
|
{
|
690 |
|
|
ESPLOG(("esp_abort: Not implemented yet\n"));
|
691 |
|
|
return SCSI_ABORT_ERROR;
|
692 |
|
|
}
|
693 |
|
|
|
694 |
|
|
/* Reset ESP chip, reset hanging bus, then kill active and
|
695 |
|
|
* disconnected commands for targets without soft reset.
|
696 |
|
|
*/
|
697 |
|
|
int esp_reset(Scsi_Cmnd *SCptr, unsigned int how)
|
698 |
|
|
{
|
699 |
|
|
ESPLOG(("esp_reset: Not implemented yet\n"));
|
700 |
|
|
return SCSI_RESET_ERROR;
|
701 |
|
|
}
|
702 |
|
|
|
703 |
|
|
/* Internal ESP done function. */
|
704 |
|
|
static inline void esp_done(struct Sparc_ESP *esp, int error)
|
705 |
|
|
{
|
706 |
|
|
unsigned long flags;
|
707 |
|
|
Scsi_Cmnd *done_SC;
|
708 |
|
|
|
709 |
|
|
if(esp->current_SC) {
|
710 |
|
|
/* Critical section... */
|
711 |
|
|
save_flags(flags); cli();
|
712 |
|
|
done_SC = esp->current_SC;
|
713 |
|
|
esp->current_SC = NULL;
|
714 |
|
|
/* Free dvma entry. */
|
715 |
|
|
if(!done_SC->use_sg) {
|
716 |
|
|
mmu_release_scsi_one(done_SC->SCp.ptr,
|
717 |
|
|
done_SC->SCp.this_residual,
|
718 |
|
|
esp->edev->my_bus);
|
719 |
|
|
} else {
|
720 |
|
|
struct scatterlist *scl = (struct scatterlist *)done_SC->buffer;
|
721 |
|
|
#ifdef DEBUG_ESP_SG
|
722 |
|
|
printk("esp: unmapping sg ");
|
723 |
|
|
#endif
|
724 |
|
|
mmu_release_scsi_sgl((struct mmu_sglist *) scl,
|
725 |
|
|
done_SC->use_sg - 1,
|
726 |
|
|
esp->edev->my_bus);
|
727 |
|
|
#ifdef DEBUG_ESP_SG
|
728 |
|
|
printk("done.\n");
|
729 |
|
|
#endif
|
730 |
|
|
}
|
731 |
|
|
done_SC->result = error;
|
732 |
|
|
if(done_SC->scsi_done)
|
733 |
|
|
done_SC->scsi_done(done_SC);
|
734 |
|
|
else
|
735 |
|
|
panic("esp: esp->current_SC->scsi_done() == NULL");
|
736 |
|
|
|
737 |
|
|
/* Bus is free, issue any commands in the queue. */
|
738 |
|
|
if(esp->issue_SC)
|
739 |
|
|
esp_exec_cmd(esp);
|
740 |
|
|
|
741 |
|
|
restore_flags(flags);
|
742 |
|
|
/* End of critical section... */
|
743 |
|
|
} else
|
744 |
|
|
panic("esp: done() called with NULL esp->current_SC");
|
745 |
|
|
}
|
746 |
|
|
|
747 |
|
|
#ifdef THREADED_ESP_DRIVER /* planning stage... */
|
748 |
|
|
|
749 |
|
|
/* With multiple lots of commands being processed I frequently
|
750 |
|
|
* see a situation where we see galloping esp herds. esp_done()
|
751 |
|
|
* wakes the entire world up and each interrupt causes a reschedule.
|
752 |
|
|
* This kernel thread fixes some of these unwanted effects during
|
753 |
|
|
* IO intensive activity.... I hope...
|
754 |
|
|
*/
|
755 |
|
|
|
756 |
|
|
static void esp_kernel_thread(void *opaque)
|
757 |
|
|
{
|
758 |
|
|
struct Sparc_ESP *esp = opaque;
|
759 |
|
|
|
760 |
|
|
for(;;) {
|
761 |
|
|
unsigned long flags;
|
762 |
|
|
|
763 |
|
|
while(esp->eatme_SC) {
|
764 |
|
|
struct Scsi_Cmnd *SCpnt;
|
765 |
|
|
|
766 |
|
|
SCpnt = remove_first_SC(esp->eatme_SC);
|
767 |
|
|
esp_done(esp, error, SCpnt);
|
768 |
|
|
}
|
769 |
|
|
sleep();
|
770 |
|
|
}
|
771 |
|
|
}
|
772 |
|
|
#endif
|
773 |
|
|
|
774 |
|
|
/* Read the interrupt status registers on this ESP board */
|
775 |
|
|
static inline void esp_updatesoft(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs)
|
776 |
|
|
{
|
777 |
|
|
/* Update our software copies of the three ESP status
|
778 |
|
|
* registers for this ESP. Be careful, reading the
|
779 |
|
|
* ESP interrupt register clears the status and sequence
|
780 |
|
|
* step registers (unlatches them, you get the idea).
|
781 |
|
|
* So read the interrupt register last.
|
782 |
|
|
*/
|
783 |
|
|
|
784 |
|
|
esp->seqreg = eregs->esp_sstep;
|
785 |
|
|
esp->sreg = eregs->esp_status;
|
786 |
|
|
|
787 |
|
|
/* Supposedly, the ESP100A and above assert the highest
|
788 |
|
|
* bit in the status register if an interrupt is pending.
|
789 |
|
|
* I've never seen this work properly, so let's clear it
|
790 |
|
|
* manually while we are here. If I see any esp chips
|
791 |
|
|
* for which this bit is reliable I will conditionalize
|
792 |
|
|
* this. However, I don't see what this extra bit can
|
793 |
|
|
* buy me with all the tests I'll have to place all over
|
794 |
|
|
* the code to actually use it when I 'can'. Plus the
|
795 |
|
|
* 'pending interrupt' condition can more than reliably
|
796 |
|
|
* be obtained from the DVMA control register.
|
797 |
|
|
*
|
798 |
|
|
* "Broken hardware" -Linus
|
799 |
|
|
*/
|
800 |
|
|
esp->sreg &= (~ESP_STAT_INTR);
|
801 |
|
|
esp->ireg = eregs->esp_intrpt; /* Must be last or we lose */
|
802 |
|
|
}
|
803 |
|
|
|
804 |
|
|
/* #define ESP_IRQ_TRACE */
|
805 |
|
|
|
806 |
|
|
#ifdef ESP_IRQ_TRACE
|
807 |
|
|
#define ETRACE(foo) printk foo
|
808 |
|
|
#else
|
809 |
|
|
#define ETRACE(foo)
|
810 |
|
|
#endif
|
811 |
|
|
|
812 |
|
|
static char last_fflags, last_status, last_msg;
|
813 |
|
|
|
814 |
|
|
/* Main interrupt handler for an esp adapter. */
|
815 |
|
|
static inline void esp_handle(struct Sparc_ESP *esp)
|
816 |
|
|
{
|
817 |
|
|
struct sparc_dma_registers *dregs;
|
818 |
|
|
struct Sparc_ESP_regs *eregs;
|
819 |
|
|
Scsi_Cmnd *SCptr;
|
820 |
|
|
|
821 |
|
|
eregs = esp->eregs;
|
822 |
|
|
dregs = esp->dregs;
|
823 |
|
|
SCptr = esp->current_SC;
|
824 |
|
|
|
825 |
|
|
DMA_IRQ_ENTRY(esp->dma, dregs);
|
826 |
|
|
esp_updatesoft(esp, eregs);
|
827 |
|
|
|
828 |
|
|
ETRACE(("ESPIRQ: <%2x,%2x,%2x> --> ", esp->ireg, esp->sreg, esp->seqreg));
|
829 |
|
|
|
830 |
|
|
/* Check for errors. */
|
831 |
|
|
if(!SCptr)
|
832 |
|
|
panic("esp_handle: current_SC == penguin within interrupt!");
|
833 |
|
|
|
834 |
|
|
/* At this point in time, this esp driver should not see
|
835 |
|
|
* scsibus resets, parity errors, or gross errors unless
|
836 |
|
|
* something truly terrible happens which we are not ready
|
837 |
|
|
* to properly recover from yet.
|
838 |
|
|
*/
|
839 |
|
|
if((esp->ireg & (ESP_INTR_SR | ESP_INTR_IC)) ||
|
840 |
|
|
(esp->sreg & (ESP_STAT_PERR | ESP_STAT_SPAM))) {
|
841 |
|
|
printk("esp: really bad error detected\n");
|
842 |
|
|
printk("esp: intr<%2x> stat<%2x> seq<%2x>",
|
843 |
|
|
esp->ireg, esp->sreg, esp->seqreg);
|
844 |
|
|
printk("esp: SCptr->SCp.phase = %d\n", SCptr->SCp.phase);
|
845 |
|
|
panic("esp: cannot continue\n");
|
846 |
|
|
}
|
847 |
|
|
if(dregs->cond_reg & DMA_HNDL_ERROR) {
|
848 |
|
|
printk("esp: DMA shows an error cond_reg<%08lx> addr<%p>\n",
|
849 |
|
|
dregs->cond_reg, dregs->st_addr);
|
850 |
|
|
printk("esp: intr<%2x> stat<%2x> seq<%2x>",
|
851 |
|
|
esp->ireg, esp->sreg, esp->seqreg);
|
852 |
|
|
printk("esp: SCptr->SCp.phase = %d\n", SCptr->SCp.phase);
|
853 |
|
|
panic("esp: cannot continue\n");
|
854 |
|
|
}
|
855 |
|
|
if(esp->sreg & ESP_STAT_PERR) {
|
856 |
|
|
printk("esp: SCSI bus parity error\n");
|
857 |
|
|
printk("esp: intr<%2x> stat<%2x> seq<%2x>",
|
858 |
|
|
esp->ireg, esp->sreg, esp->seqreg);
|
859 |
|
|
printk("esp: SCptr->SCp.phase = %d\n", SCptr->SCp.phase);
|
860 |
|
|
panic("esp: cannot continue\n");
|
861 |
|
|
}
|
862 |
|
|
|
863 |
|
|
/* Service interrupt. */
|
864 |
|
|
switch(SCptr->SCp.phase) {
|
865 |
|
|
case not_issued:
|
866 |
|
|
panic("Unexpected ESP interrupt, current_SC not issued.");
|
867 |
|
|
break;
|
868 |
|
|
case in_selection:
|
869 |
|
|
if(esp->ireg & ESP_INTR_RSEL) {
|
870 |
|
|
/* XXX Some day XXX */
|
871 |
|
|
panic("ESP penguin reselected in async mode.");
|
872 |
|
|
} else if(esp->ireg & ESP_INTR_DC) {
|
873 |
|
|
/* Either we are scanning the bus and no-one
|
874 |
|
|
* lives at this target or it didn't respond.
|
875 |
|
|
*/
|
876 |
|
|
ETRACE(("DISCONNECT\n"));
|
877 |
|
|
#ifdef THREADED_ESP_DRIVER
|
878 |
|
|
append_SC(esp->eatme_SC, esp->current_SC);
|
879 |
|
|
esp->current_SC = 0;
|
880 |
|
|
wake_up(esp_kernel_thread);
|
881 |
|
|
#else
|
882 |
|
|
esp_done(esp, (DID_NO_CONNECT << 16));
|
883 |
|
|
#endif
|
884 |
|
|
goto esp_handle_done;
|
885 |
|
|
} else if((esp->ireg & (ESP_INTR_FDONE | ESP_INTR_BSERV)) ==
|
886 |
|
|
(ESP_INTR_FDONE | ESP_INTR_BSERV)) {
|
887 |
|
|
/* Selection successful, check the sequence step. */
|
888 |
|
|
/* XXX I know, I know... add error recovery. XXX */
|
889 |
|
|
switch(esp->seqreg & ESP_STEP_VBITS) {
|
890 |
|
|
case ESP_STEP_NCMD:
|
891 |
|
|
panic("esp: penguin didn't enter cmd phase.");
|
892 |
|
|
break;
|
893 |
|
|
case ESP_STEP_PPC:
|
894 |
|
|
panic("esp: penguin prematurely changed from cmd phase.");
|
895 |
|
|
break;
|
896 |
|
|
case ESP_STEP_FINI:
|
897 |
|
|
/* At the completion of every command
|
898 |
|
|
* or message-out phase, we _must_
|
899 |
|
|
* unlatch the fifo-flags register
|
900 |
|
|
* with an ESP nop command.
|
901 |
|
|
*/
|
902 |
|
|
eregs->esp_cmd = ESP_CMD_NULL;
|
903 |
|
|
|
904 |
|
|
/* Selection/Command sequence completed. We
|
905 |
|
|
* (at least for this driver) will be in
|
906 |
|
|
* either one of the data phases or status
|
907 |
|
|
* phase, check the status register to find
|
908 |
|
|
* out.
|
909 |
|
|
*/
|
910 |
|
|
switch(esp->sreg & ESP_STAT_PMASK) {
|
911 |
|
|
default:
|
912 |
|
|
printk("esp: Not datain/dataout/status.\n");
|
913 |
|
|
panic("esp: penguin phase transition after selection.");
|
914 |
|
|
break;
|
915 |
|
|
case ESP_DOP:
|
916 |
|
|
/* Data out phase. */
|
917 |
|
|
dregs->cond_reg |= DMA_FIFO_INV;
|
918 |
|
|
while(dregs->cond_reg & DMA_FIFO_ISDRAIN)
|
919 |
|
|
barrier();
|
920 |
|
|
SCptr->SCp.phase = in_dataout;
|
921 |
|
|
#ifdef DEBUG_ESP_SG
|
922 |
|
|
if(SCptr->use_sg)
|
923 |
|
|
printk("esp: sg-start <%p,%d>",
|
924 |
|
|
SCptr->SCp.ptr,
|
925 |
|
|
SCptr->SCp.this_residual);
|
926 |
|
|
#endif
|
927 |
|
|
eregs->esp_tclow = SCptr->SCp.this_residual;
|
928 |
|
|
eregs->esp_tcmed = (SCptr->SCp.this_residual>>8);
|
929 |
|
|
eregs->esp_cmd = (ESP_CMD_DMA | ESP_CMD_NULL);
|
930 |
|
|
|
931 |
|
|
/* This is either the one buffer dvma ptr,
|
932 |
|
|
* or the first one in the scatter gather
|
933 |
|
|
* list. Check out esp_queue to see how
|
934 |
|
|
* this is set up.
|
935 |
|
|
*/
|
936 |
|
|
dregs->st_addr = SCptr->SCp.ptr;
|
937 |
|
|
dregs->cond_reg &= ~(DMA_ST_WRITE);
|
938 |
|
|
dregs->cond_reg |= (DMA_ENABLE | DMA_INT_ENAB);
|
939 |
|
|
eregs->esp_cmd = (ESP_CMD_DMA | ESP_CMD_TI);
|
940 |
|
|
ETRACE(("DATA_OUT\n"));
|
941 |
|
|
goto esp_handle_done;
|
942 |
|
|
case ESP_DIP:
|
943 |
|
|
/* Data in phase. */
|
944 |
|
|
dregs->cond_reg |= DMA_FIFO_INV;
|
945 |
|
|
while(dregs->cond_reg & DMA_FIFO_ISDRAIN)
|
946 |
|
|
barrier();
|
947 |
|
|
SCptr->SCp.phase = in_datain;
|
948 |
|
|
#ifdef DEBUG_ESP_SG
|
949 |
|
|
if(SCptr->use_sg)
|
950 |
|
|
printk("esp: sg-start <%p,%d>",
|
951 |
|
|
SCptr->SCp.ptr,
|
952 |
|
|
SCptr->SCp.this_residual);
|
953 |
|
|
#endif
|
954 |
|
|
eregs->esp_tclow = SCptr->SCp.this_residual;
|
955 |
|
|
eregs->esp_tcmed = (SCptr->SCp.this_residual>>8);
|
956 |
|
|
eregs->esp_cmd = (ESP_CMD_DMA | ESP_CMD_NULL);
|
957 |
|
|
|
958 |
|
|
/* This is either the one buffer dvma ptr,
|
959 |
|
|
* or the first one in the scatter gather
|
960 |
|
|
* list. Check out esp_queue to see how
|
961 |
|
|
* this is set up.
|
962 |
|
|
*/
|
963 |
|
|
dregs->st_addr = SCptr->SCp.ptr;
|
964 |
|
|
dregs->cond_reg |= (DMA_ENABLE | DMA_ST_WRITE | DMA_INT_ENAB);
|
965 |
|
|
eregs->esp_cmd = (ESP_CMD_DMA | ESP_CMD_TI);
|
966 |
|
|
ETRACE(("DATA_IN\n"));
|
967 |
|
|
goto esp_handle_done;
|
968 |
|
|
case ESP_STATP:
|
969 |
|
|
/* Status phase. */
|
970 |
|
|
SCptr->SCp.phase = in_status;
|
971 |
|
|
eregs->esp_cmd = ESP_CMD_ICCSEQ;
|
972 |
|
|
ETRACE(("STATUS\n"));
|
973 |
|
|
goto esp_handle_done; /* Wait for message. */
|
974 |
|
|
};
|
975 |
|
|
};
|
976 |
|
|
} else if(esp->ireg & ESP_INTR_FDONE) {
|
977 |
|
|
/* I'd like to investigate why this happens... */
|
978 |
|
|
ESPLOG(("esp: This is weird, halfway through "));
|
979 |
|
|
ESPLOG(("selection, trying to continue anyways.\n"));
|
980 |
|
|
goto esp_handle_done;
|
981 |
|
|
} else {
|
982 |
|
|
panic("esp: Did not get bus service during selection.");
|
983 |
|
|
goto esp_handle_done;
|
984 |
|
|
}
|
985 |
|
|
panic("esp: Mr. Potatoe Head is on the loose!");
|
986 |
|
|
|
987 |
|
|
case in_datain:
|
988 |
|
|
/* Drain the fifo for writes to memory. */
|
989 |
|
|
switch(esp->dma->revision) {
|
990 |
|
|
case dvmarev0:
|
991 |
|
|
case dvmarev1:
|
992 |
|
|
case dvmarevplus:
|
993 |
|
|
case dvmarev2:
|
994 |
|
|
case dvmarev3:
|
995 |
|
|
/* Force a drain. */
|
996 |
|
|
dregs->cond_reg |= DMA_FIFO_STDRAIN;
|
997 |
|
|
|
998 |
|
|
/* fall through */
|
999 |
|
|
case dvmaesc1:
|
1000 |
|
|
/* Wait for the fifo to drain completely. */
|
1001 |
|
|
while(dregs->cond_reg & DMA_FIFO_ISDRAIN)
|
1002 |
|
|
barrier();
|
1003 |
|
|
break;
|
1004 |
|
|
};
|
1005 |
|
|
|
1006 |
|
|
case in_dataout:
|
1007 |
|
|
dregs->cond_reg &= ~DMA_ENABLE;
|
1008 |
|
|
|
1009 |
|
|
/* We may be pipelining an sg-list. */
|
1010 |
|
|
if(SCptr->use_sg) {
|
1011 |
|
|
if(SCptr->SCp.buffers_residual) {
|
1012 |
|
|
/* If we do not see a BUS SERVICE interrupt
|
1013 |
|
|
* at this point, or we see that we have left
|
1014 |
|
|
* the current data phase, then we lose.
|
1015 |
|
|
*/
|
1016 |
|
|
if(!(esp->ireg & ESP_INTR_BSERV) ||
|
1017 |
|
|
((esp->sreg & ESP_STAT_PMASK) > 1))
|
1018 |
|
|
panic("esp: Aiee penguin on the SCSI-bus.");
|
1019 |
|
|
|
1020 |
|
|
++SCptr->SCp.buffer;
|
1021 |
|
|
--SCptr->SCp.buffers_residual;
|
1022 |
|
|
SCptr->SCp.this_residual = SCptr->SCp.buffer->length;
|
1023 |
|
|
SCptr->SCp.ptr = SCptr->SCp.buffer->alt_address;
|
1024 |
|
|
|
1025 |
|
|
#ifdef DEBUG_ESP_SG
|
1026 |
|
|
printk("<%p,%d> ", SCptr->SCp.ptr,
|
1027 |
|
|
SCptr->SCp.this_residual);
|
1028 |
|
|
#endif
|
1029 |
|
|
|
1030 |
|
|
/* Latch in new esp counters... */
|
1031 |
|
|
eregs->esp_tclow = SCptr->SCp.this_residual;
|
1032 |
|
|
eregs->esp_tcmed = (SCptr->SCp.this_residual>>8);
|
1033 |
|
|
eregs->esp_cmd = (ESP_CMD_DMA | ESP_CMD_NULL);
|
1034 |
|
|
|
1035 |
|
|
/* Reload DVMA gate array with new vaddr and enab. */
|
1036 |
|
|
dregs->st_addr = SCptr->SCp.ptr;
|
1037 |
|
|
dregs->cond_reg |= DMA_ENABLE;
|
1038 |
|
|
|
1039 |
|
|
/* Tell the esp to start transferring. */
|
1040 |
|
|
eregs->esp_cmd = (ESP_CMD_DMA | ESP_CMD_TI);
|
1041 |
|
|
goto esp_handle_done;
|
1042 |
|
|
}
|
1043 |
|
|
#ifdef DEBUG_ESP_SG
|
1044 |
|
|
printk("done.\n");
|
1045 |
|
|
#endif
|
1046 |
|
|
}
|
1047 |
|
|
/* Take a look at what happened. */
|
1048 |
|
|
if(esp->ireg & ESP_INTR_DC) {
|
1049 |
|
|
panic("esp: target disconnects during data transfer.");
|
1050 |
|
|
goto esp_handle_done;
|
1051 |
|
|
} else if(esp->ireg & ESP_INTR_BSERV) {
|
1052 |
|
|
if((esp->sreg & ESP_STAT_PMASK) != ESP_STATP) {
|
1053 |
|
|
panic("esp: Not status phase after data phase.");
|
1054 |
|
|
goto esp_handle_done;
|
1055 |
|
|
}
|
1056 |
|
|
SCptr->SCp.phase = in_status;
|
1057 |
|
|
eregs->esp_cmd = ESP_CMD_ICCSEQ;
|
1058 |
|
|
ETRACE(("STATUS\n"));
|
1059 |
|
|
goto esp_handle_done; /* Wait for message. */
|
1060 |
|
|
} else {
|
1061 |
|
|
printk("esp: did not get bus service after data transfer.");
|
1062 |
|
|
printk("esp_status: intr<%2x> stat<%2x> seq<%2x>\n",
|
1063 |
|
|
esp->ireg, esp->sreg, esp->seqreg);
|
1064 |
|
|
panic("esp: penguin data transfer.");
|
1065 |
|
|
goto esp_handle_done;
|
1066 |
|
|
}
|
1067 |
|
|
case in_status:
|
1068 |
|
|
if(esp->ireg & ESP_INTR_DC) {
|
1069 |
|
|
panic("esp: penguin disconnects in status phase.");
|
1070 |
|
|
goto esp_handle_done;
|
1071 |
|
|
} else if (esp->ireg & ESP_INTR_FDONE) {
|
1072 |
|
|
/* Status and Message now sit in the fifo for us. */
|
1073 |
|
|
last_fflags = eregs->esp_fflags;
|
1074 |
|
|
SCptr->SCp.phase = in_finale;
|
1075 |
|
|
last_status = SCptr->SCp.Status = eregs->esp_fdata;
|
1076 |
|
|
last_msg = SCptr->SCp.Message = eregs->esp_fdata;
|
1077 |
|
|
eregs->esp_cmd = ESP_CMD_MOK;
|
1078 |
|
|
ETRACE(("FINALE\n"));
|
1079 |
|
|
goto esp_handle_done;
|
1080 |
|
|
} else {
|
1081 |
|
|
panic("esp: penguin status phase.");
|
1082 |
|
|
}
|
1083 |
|
|
case in_finale:
|
1084 |
|
|
if(esp->ireg & ESP_INTR_BSERV) {
|
1085 |
|
|
panic("esp: penguin doesn't disconnect after status msg-ack.");
|
1086 |
|
|
goto esp_handle_done;
|
1087 |
|
|
} else if(esp->ireg & ESP_INTR_DC) {
|
1088 |
|
|
/* Nexus is complete. */
|
1089 |
|
|
#ifdef THREADED_ESP_DRIVER
|
1090 |
|
|
append_SC(esp->eatme_SC, esp->current_SC);
|
1091 |
|
|
esp->current_SC = 0;
|
1092 |
|
|
wake_up(esp_kernel_thread);
|
1093 |
|
|
#else
|
1094 |
|
|
esp_done(esp, ((SCptr->SCp.Status & 0xff) |
|
1095 |
|
|
((SCptr->SCp.Message & 0xff) << 8) |
|
1096 |
|
|
(DID_OK << 16)));
|
1097 |
|
|
#endif
|
1098 |
|
|
ETRACE(("NEXUS_COMPLETE\n"));
|
1099 |
|
|
goto esp_handle_done;
|
1100 |
|
|
} else {
|
1101 |
|
|
printk("esp: wacky state while in in_finale phase.\n");
|
1102 |
|
|
printk("esp_status: intr<%2x> stat<%2x> seq<%2x>\n",
|
1103 |
|
|
esp->ireg, esp->sreg, esp->seqreg);
|
1104 |
|
|
panic("esp: penguin esp state.");
|
1105 |
|
|
goto esp_handle_done;
|
1106 |
|
|
}
|
1107 |
|
|
default:
|
1108 |
|
|
panic("esp: detected penguin phase.");
|
1109 |
|
|
goto esp_handle_done;
|
1110 |
|
|
}
|
1111 |
|
|
panic("esp: Heading to the promised land.");
|
1112 |
|
|
|
1113 |
|
|
esp_handle_done:
|
1114 |
|
|
DMA_IRQ_EXIT(esp->dma, dregs);
|
1115 |
|
|
return;
|
1116 |
|
|
}
|
1117 |
|
|
|
1118 |
|
|
static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
|
1119 |
|
|
{
|
1120 |
|
|
struct Sparc_ESP *esp;
|
1121 |
|
|
|
1122 |
|
|
/* Handle all ESP interrupts showing */
|
1123 |
|
|
for_each_esp(esp) {
|
1124 |
|
|
if(DMA_IRQ_P(esp->dregs)) {
|
1125 |
|
|
esp_handle(esp);
|
1126 |
|
|
}
|
1127 |
|
|
}
|
1128 |
|
|
}
|