File: | obj-scan-build/../linux/src/drivers/scsi/ncr53c8xx.c |
Location: | line 8571, column 2 |
Description: | Dereference of null pointer |
1 | /****************************************************************************** | |||||
2 | ** Device driver for the PCI-SCSI NCR538XX controller family. | |||||
3 | ** | |||||
4 | ** Copyright (C) 1994 Wolfgang Stanglmeier | |||||
5 | ** | |||||
6 | ** This program is free software; you can redistribute it and/or modify | |||||
7 | ** it under the terms of the GNU General Public License as published by | |||||
8 | ** the Free Software Foundation; either version 2 of the License, or | |||||
9 | ** (at your option) any later version. | |||||
10 | ** | |||||
11 | ** This program is distributed in the hope that it will be useful, | |||||
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
14 | ** GNU General Public License for more details. | |||||
15 | ** | |||||
16 | ** You should have received a copy of the GNU General Public License | |||||
17 | ** along with this program; if not, write to the Free Software | |||||
18 | ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
19 | ** | |||||
20 | **----------------------------------------------------------------------------- | |||||
21 | ** | |||||
22 | ** This driver has been ported to Linux from the FreeBSD NCR53C8XX driver | |||||
23 | ** and is currently maintained by | |||||
24 | ** | |||||
25 | ** Gerard Roudier <groudier@club-internet.fr> | |||||
26 | ** | |||||
27 | ** Being given that this driver originates from the FreeBSD version, and | |||||
28 | ** in order to keep synergy on both, any suggested enhancements and corrections | |||||
29 | ** received on Linux are automatically a potential candidate for the FreeBSD | |||||
30 | ** version. | |||||
31 | ** | |||||
32 | ** The original driver has been written for 386bsd and FreeBSD by | |||||
33 | ** Wolfgang Stanglmeier <wolf@cologne.de> | |||||
34 | ** Stefan Esser <se@mi.Uni-Koeln.de> | |||||
35 | ** | |||||
36 | ** And has been ported to NetBSD by | |||||
37 | ** Charles M. Hannum <mycroft@gnu.ai.mit.edu> | |||||
38 | ** | |||||
39 | **----------------------------------------------------------------------------- | |||||
40 | ** | |||||
41 | ** Brief history | |||||
42 | ** | |||||
43 | ** December 10 1995 by Gerard Roudier: | |||||
44 | ** Initial port to Linux. | |||||
45 | ** | |||||
46 | ** June 23 1996 by Gerard Roudier: | |||||
47 | ** Support for 64 bits architectures (Alpha). | |||||
48 | ** | |||||
49 | ** November 30 1996 by Gerard Roudier: | |||||
50 | ** Support for Fast-20 scsi. | |||||
51 | ** Support for large DMA fifo and 128 dwords bursting. | |||||
52 | ** | |||||
53 | ** February 27 1997 by Gerard Roudier: | |||||
54 | ** Support for Fast-40 scsi. | |||||
55 | ** Support for on-Board RAM. | |||||
56 | ** | |||||
57 | ** May 3 1997 by Gerard Roudier: | |||||
58 | ** Full support for scsi scripts instructions pre-fetching. | |||||
59 | ** | |||||
60 | ** May 19 1997 by Richard Waltham <dormouse@farsrobt.demon.co.uk>: | |||||
61 | ** Support for NvRAM detection and reading. | |||||
62 | ** | |||||
63 | ** August 18 1997 by Cort <cort@cs.nmt.edu>: | |||||
64 | ** Support for Power/PC (Big Endian). | |||||
65 | ** | |||||
66 | ******************************************************************************* | |||||
67 | */ | |||||
68 | ||||||
69 | /* | |||||
70 | ** 30 January 1998, version 2.5f.1 | |||||
71 | ** | |||||
72 | ** Supported SCSI-II features: | |||||
73 | ** Synchronous negotiation | |||||
74 | ** Wide negotiation (depends on the NCR Chip) | |||||
75 | ** Enable disconnection | |||||
76 | ** Tagged command queuing | |||||
77 | ** Parity checking | |||||
78 | ** Etc... | |||||
79 | ** | |||||
80 | ** Supported NCR chips: | |||||
81 | ** 53C810 (8 bits, Fast SCSI-2, no rom BIOS) | |||||
82 | ** 53C815 (8 bits, Fast SCSI-2, on board rom BIOS) | |||||
83 | ** 53C820 (Wide, Fast SCSI-2, no rom BIOS) | |||||
84 | ** 53C825 (Wide, Fast SCSI-2, on board rom BIOS) | |||||
85 | ** 53C860 (8 bits, Fast 20, no rom BIOS) | |||||
86 | ** 53C875 (Wide, Fast 20, on board rom BIOS) | |||||
87 | ** 53C895 (Wide, Fast 40, on board rom BIOS) | |||||
88 | ** | |||||
89 | ** Other features: | |||||
90 | ** Memory mapped IO (linux-1.3.X and above only) | |||||
91 | ** Module | |||||
92 | ** Shared IRQ (since linux-1.3.72) | |||||
93 | */ | |||||
94 | ||||||
95 | #define SCSI_NCR_DEBUG_FLAGS(0) (0) | |||||
96 | ||||||
97 | #define NCR_GETCC_WITHMSG | |||||
98 | ||||||
99 | /*========================================================== | |||||
100 | ** | |||||
101 | ** Include files | |||||
102 | ** | |||||
103 | **========================================================== | |||||
104 | */ | |||||
105 | ||||||
106 | #define LinuxVersionCode(v, p, s)(((v)<<16)+((p)<<8)+(s)) (((v)<<16)+((p)<<8)+(s)) | |||||
107 | ||||||
108 | #ifdef MODULE | |||||
109 | #include <linux/module.h> | |||||
110 | #endif | |||||
111 | ||||||
112 | #include <asm/dma.h> | |||||
113 | #include <asm/io.h> | |||||
114 | #include <asm/system.h> | |||||
115 | #include <linux/delay.h> | |||||
116 | #include <linux/signal.h> | |||||
117 | #include <linux/sched.h> | |||||
118 | #include <linux/errno.h> | |||||
119 | #include <linux/bios32.h> | |||||
120 | #include <linux/pci.h> | |||||
121 | #include <linux/string.h> | |||||
122 | #include <linux/malloc.h> | |||||
123 | #include <linux/mm.h> | |||||
124 | #include <linux/ioport.h> | |||||
125 | #include <linux/time.h> | |||||
126 | #include <linux/timer.h> | |||||
127 | #include <linux/stat.h> | |||||
128 | ||||||
129 | #include <linux/version.h> | |||||
130 | #if LINUX_VERSION_CODE131108 >= LinuxVersionCode(1,3,0)(((1)<<16)+((3)<<8)+(0)) | |||||
131 | #include <linux/blk.h> | |||||
132 | #else | |||||
133 | #include "../block/blk.h" | |||||
134 | #endif | |||||
135 | ||||||
136 | #if LINUX_VERSION_CODE131108 >= LinuxVersionCode(2,1,35)(((2)<<16)+((1)<<8)+(35)) | |||||
137 | #include <linux/init.h> | |||||
138 | #else | |||||
139 | #ifndef __initdata | |||||
140 | #define __initdata | |||||
141 | #endif | |||||
142 | #ifndef __initfunc | |||||
143 | #define __initfunc(__arginit)__arginit __arginit | |||||
144 | #endif | |||||
145 | #endif | |||||
146 | ||||||
147 | #include "scsi.h" | |||||
148 | #include "hosts.h" | |||||
149 | #include "constants.h" | |||||
150 | #include "sd.h" | |||||
151 | ||||||
152 | #include <linux/types.h> | |||||
153 | ||||||
154 | /* | |||||
155 | ** Define the BSD style u_int32 type | |||||
156 | */ | |||||
157 | typedef u32 u_int32; | |||||
158 | ||||||
159 | #include "ncr53c8xx.h" | |||||
160 | ||||||
161 | /*========================================================== | |||||
162 | ** | |||||
163 | ** Configuration and Debugging | |||||
164 | ** | |||||
165 | **========================================================== | |||||
166 | */ | |||||
167 | ||||||
168 | /* | |||||
169 | ** SCSI address of this device. | |||||
170 | ** The boot routines should have set it. | |||||
171 | ** If not, use this. | |||||
172 | */ | |||||
173 | ||||||
174 | #ifndef SCSI_NCR_MYADDR(7) | |||||
175 | #define SCSI_NCR_MYADDR(7) (7) | |||||
176 | #endif | |||||
177 | ||||||
178 | /* | |||||
179 | ** The maximum number of tags per logic unit. | |||||
180 | ** Used only for disk devices that support tags. | |||||
181 | */ | |||||
182 | ||||||
183 | #ifndef SCSI_NCR_MAX_TAGS(4) | |||||
184 | #define SCSI_NCR_MAX_TAGS(4) (4) | |||||
185 | #endif | |||||
186 | ||||||
187 | /* | |||||
188 | ** Number of targets supported by the driver. | |||||
189 | ** n permits target numbers 0..n-1. | |||||
190 | ** Default is 7, meaning targets #0..#6. | |||||
191 | ** #7 .. is myself. | |||||
192 | */ | |||||
193 | ||||||
194 | #ifdef SCSI_NCR_MAX_TARGET(16) | |||||
195 | #define MAX_TARGET((16)) (SCSI_NCR_MAX_TARGET(16)) | |||||
196 | #else | |||||
197 | #define MAX_TARGET((16)) (16) | |||||
198 | #endif | |||||
199 | ||||||
200 | /* | |||||
201 | ** Number of logic units supported by the driver. | |||||
202 | ** n enables logic unit numbers 0..n-1. | |||||
203 | ** The common SCSI devices require only | |||||
204 | ** one lun, so take 1 as the default. | |||||
205 | */ | |||||
206 | ||||||
207 | #ifdef SCSI_NCR_MAX_LUN(8) | |||||
208 | #define MAX_LUN(8) SCSI_NCR_MAX_LUN(8) | |||||
209 | #else | |||||
210 | #define MAX_LUN(8) (1) | |||||
211 | #endif | |||||
212 | ||||||
213 | /* | |||||
214 | ** Asynchronous pre-scaler (ns). Shall be 40 | |||||
215 | */ | |||||
216 | ||||||
217 | #ifndef SCSI_NCR_MIN_ASYNC(40) | |||||
218 | #define SCSI_NCR_MIN_ASYNC(40) (40) | |||||
219 | #endif | |||||
220 | ||||||
221 | /* | |||||
222 | ** The maximum number of jobs scheduled for starting. | |||||
223 | ** There should be one slot per target, and one slot | |||||
224 | ** for each tag of each target in use. | |||||
225 | ** The calculation below is actually quite silly ... | |||||
226 | */ | |||||
227 | ||||||
228 | #ifdef SCSI_NCR_CAN_QUEUE(7*(4)) | |||||
229 | #define MAX_START((7*(4)) + 4) (SCSI_NCR_CAN_QUEUE(7*(4)) + 4) | |||||
230 | #else | |||||
231 | #define MAX_START((7*(4)) + 4) (MAX_TARGET((16)) + 7 * SCSI_NCR_MAX_TAGS(4)) | |||||
232 | #endif | |||||
233 | ||||||
234 | /* | |||||
235 | ** The maximum number of segments a transfer is split into. | |||||
236 | */ | |||||
237 | ||||||
238 | #define MAX_SCATTER((127)) (SCSI_NCR_MAX_SCATTER(127)) | |||||
239 | ||||||
240 | /* | |||||
241 | ** Io mapped or memory mapped. | |||||
242 | */ | |||||
243 | ||||||
244 | #if defined(SCSI_NCR_IOMAPPED) | |||||
245 | #define NCR_IOMAPPED | |||||
246 | #endif | |||||
247 | ||||||
248 | /* | |||||
249 | ** other | |||||
250 | */ | |||||
251 | ||||||
252 | #define NCR_SNOOP_TIMEOUT(1000000) (1000000) | |||||
253 | ||||||
254 | /*========================================================== | |||||
255 | ** | |||||
256 | ** Defines for Linux. | |||||
257 | ** | |||||
258 | ** Linux and Bsd kernel functions are quite different. | |||||
259 | ** These defines allow a minimum change of the original | |||||
260 | ** code. | |||||
261 | ** | |||||
262 | **========================================================== | |||||
263 | */ | |||||
264 | ||||||
265 | /* | |||||
266 | ** Obvious definitions | |||||
267 | */ | |||||
268 | ||||||
269 | #define printfprintk printk | |||||
270 | #define u_charunsigned char unsigned char | |||||
271 | #define u_shortunsigned short unsigned short | |||||
272 | #define u_intunsigned int unsigned int | |||||
273 | #define u_longunsigned long unsigned long | |||||
274 | ||||||
275 | #ifndef MACH1 | |||||
276 | typedef u_longunsigned long vm_offset_t; | |||||
277 | typedef int vm_size_t; | |||||
278 | #endif | |||||
279 | ||||||
280 | #define bcopy(s, d, n)(__builtin_constant_p((n)) ? __constant_memcpy(((d)),((s)),(( n))) : __memcpy(((d)),((s)),((n)))) memcpy((d), (s), (n))(__builtin_constant_p((n)) ? __constant_memcpy(((d)),((s)),(( n))) : __memcpy(((d)),((s)),((n)))) | |||||
281 | #define bzero(d, n)(__builtin_constant_p(0) ? (__builtin_constant_p(((n))) ? __constant_c_and_count_memset ((((d))),((0x01010101UL*(unsigned char)(0))),(((n)))) : __constant_c_memset ((((d))),((0x01010101UL*(unsigned char)(0))),(((n))))) : (__builtin_constant_p (((n))) ? __memset_generic(((((d)))),(((0))),((((n))))) : __memset_generic ((((d))),((0)),(((n)))))) memset((d), 0, (n))(__builtin_constant_p(0) ? (__builtin_constant_p(((n))) ? __constant_c_and_count_memset ((((d))),((0x01010101UL*(unsigned char)(0))),(((n)))) : __constant_c_memset ((((d))),((0x01010101UL*(unsigned char)(0))),(((n))))) : (__builtin_constant_p (((n))) ? __memset_generic(((((d)))),(((0))),((((n))))) : __memset_generic ((((d))),((0)),(((n)))))) | |||||
282 | ||||||
283 | #ifndef offsetof | |||||
284 | #define offsetof(t, m)((size_t) (&((t *)0)->m)) ((size_t) (&((t *)0)->m)) | |||||
285 | #endif | |||||
286 | ||||||
287 | /* | |||||
288 | ** Address translation | |||||
289 | ** | |||||
290 | ** On Linux 1.3.X, virt_to_bus() must be used to translate | |||||
291 | ** virtual memory addresses of the kernel data segment into | |||||
292 | ** IO bus adresses. | |||||
293 | ** On i386 architecture, IO bus addresses match the physical | |||||
294 | ** addresses. But on other architectures they can be different. | |||||
295 | ** In the original Bsd driver, vtophys() is called to translate | |||||
296 | ** data addresses to IO bus addresses. In order to minimize | |||||
297 | ** change, I decide to define vtophys() as virt_to_bus(). | |||||
298 | */ | |||||
299 | ||||||
300 | #if LINUX_VERSION_CODE131108 >= LinuxVersionCode(1,3,0)(((1)<<16)+((3)<<8)+(0)) | |||||
301 | #define vtophys(p)virt_to_phys(p) virt_to_busvirt_to_phys(p) | |||||
302 | ||||||
303 | /* | |||||
304 | ** Memory mapped IO | |||||
305 | ** | |||||
306 | ** Since linux-2.1, we must use ioremap() to map the io memory space. | |||||
307 | ** iounmap() to unmap it. That allows portability. | |||||
308 | ** Linux 1.3.X and 2.0.X allow to remap physical pages addresses greater | |||||
309 | ** than the highest physical memory address to kernel virtual pages with | |||||
310 | ** vremap() / vfree(). That was not portable but worked with i386 | |||||
311 | ** architecture. | |||||
312 | */ | |||||
313 | ||||||
314 | #ifndef NCR_IOMAPPED | |||||
315 | __initfunc(static vm_offset_t remap_pci_mem(unsigned long base, unsigned long size) | |||||
316 | static vm_offset_t remap_pci_mem(u_long base, u_long size)static vm_offset_t remap_pci_mem(unsigned long base, unsigned long size) | |||||
317 | )static vm_offset_t remap_pci_mem(unsigned long base, unsigned long size) | |||||
318 | { | |||||
319 | u_longunsigned long page_base = ((u_longunsigned long) base) & PAGE_MASK((1 << 12)-1); | |||||
320 | u_longunsigned long page_offs = ((u_longunsigned long) base) - page_base; | |||||
321 | #if LINUX_VERSION_CODE131108 >= LinuxVersionCode(2,1,0)(((2)<<16)+((1)<<8)+(0)) | |||||
322 | u_longunsigned long page_remapped = (u_longunsigned long) ioremap(page_base, page_offs+size); | |||||
323 | #else | |||||
324 | u_longunsigned long page_remapped = (u_longunsigned long) vremap(page_base, page_offs+size); | |||||
325 | #endif | |||||
326 | ||||||
327 | return (vm_offset_t) (page_remapped ? (page_remapped + page_offs) : 0UL); | |||||
328 | } | |||||
329 | ||||||
330 | __initfunc(static void unmap_pci_mem(vm_offset_t vaddr, unsigned long size ) | |||||
331 | static void unmap_pci_mem(vm_offset_t vaddr, u_long size)static void unmap_pci_mem(vm_offset_t vaddr, unsigned long size ) | |||||
332 | )static void unmap_pci_mem(vm_offset_t vaddr, unsigned long size ) | |||||
333 | { | |||||
334 | if (vaddr) | |||||
335 | #if LINUX_VERSION_CODE131108 >= LinuxVersionCode(2,1,0)(((2)<<16)+((1)<<8)+(0)) | |||||
336 | iounmap((void *) (vaddr & PAGE_MASK((1 << 12)-1))); | |||||
337 | #else | |||||
338 | vfree((void *) (vaddr & PAGE_MASK((1 << 12)-1))); | |||||
339 | #endif | |||||
340 | } | |||||
341 | #endif /* !NCR_IOMAPPED */ | |||||
342 | ||||||
343 | #else /* linux-1.2.13 */ | |||||
344 | ||||||
345 | /* | |||||
346 | ** Linux 1.2.X assumes that addresses (virtual, physical, bus) | |||||
347 | ** are the same. | |||||
348 | ** | |||||
349 | ** I have not found how to do MMIO. It seems that only processes can | |||||
350 | ** map high physical pages to virtual (Xservers can do MMIO). | |||||
351 | */ | |||||
352 | ||||||
353 | #define vtophys(p)virt_to_phys(p) ((u_longunsigned long) (p)) | |||||
354 | #endif | |||||
355 | ||||||
356 | /* | |||||
357 | ** Insert a delay in micro-seconds. | |||||
358 | */ | |||||
359 | ||||||
360 | static void DELAY(long us) | |||||
361 | { | |||||
362 | for (;us>1000;us-=1000) udelay(1000)(__builtin_constant_p(1000) ? __const_udelay((1000) * 0x10c6ul ) : __udelay(1000)); | |||||
363 | if (us) udelay(us)(__builtin_constant_p(us) ? __const_udelay((us) * 0x10c6ul) : __udelay(us)); | |||||
364 | } | |||||
365 | ||||||
366 | /* | |||||
367 | ** Internal data structure allocation. | |||||
368 | ** | |||||
369 | ** Linux scsi memory poor pool is adjusted for the need of | |||||
370 | ** middle-level scsi driver. | |||||
371 | ** We allocate our control blocks in the kernel memory pool | |||||
372 | ** to avoid scsi pool shortage. | |||||
373 | ** I notice that kmalloc() returns NULL during host attach under | |||||
374 | ** Linux 1.2.13. But this ncr driver is reliable enough to | |||||
375 | ** accomodate with this joke. | |||||
376 | ** | |||||
377 | ** kmalloc() only ensure 8 bytes boundary alignment. | |||||
378 | ** The NCR need better alignment for cache line bursting. | |||||
379 | ** The global header is moved betewen the NCB and CCBs and need | |||||
380 | ** origin and destination addresses to have same lower four bits. | |||||
381 | ** | |||||
382 | ** We use 32 boundary alignment for NCB and CCBs and offset multiple | |||||
383 | ** of 32 for global header fields. That's too much but at least enough. | |||||
384 | */ | |||||
385 | ||||||
386 | #define ALIGN_SIZE(shift)(1UL << shift) (1UL << shift) | |||||
387 | #define ALIGN_MASK(shift)(~((1UL << shift)-1)) (~(ALIGN_SIZE(shift)(1UL << shift)-1)) | |||||
388 | ||||||
389 | #define NCB_ALIGN_SHIFT5 5 | |||||
390 | #define CCB_ALIGN_SHIFT5 5 | |||||
391 | #define LCB_ALIGN_SHIFT5 5 | |||||
392 | #define SCR_ALIGN_SHIFT5 5 | |||||
393 | ||||||
394 | #define NCB_ALIGN_SIZE(1UL << 5) ALIGN_SIZE(NCB_ALIGN_SHIFT)(1UL << 5) | |||||
395 | #define NCB_ALIGN_MASK(~((1UL << 5)-1)) ALIGN_MASK(NCB_ALIGN_SHIFT)(~((1UL << 5)-1)) | |||||
396 | #define CCB_ALIGN_SIZE(1UL << 5) ALIGN_SIZE(CCB_ALIGN_SHIFT)(1UL << 5) | |||||
397 | #define CCB_ALIGN_MASK(~((1UL << 5)-1)) ALIGN_MASK(CCB_ALIGN_SHIFT)(~((1UL << 5)-1)) | |||||
398 | #define SCR_ALIGN_SIZE(1UL << 5) ALIGN_SIZE(SCR_ALIGN_SHIFT)(1UL << 5) | |||||
399 | #define SCR_ALIGN_MASK(~((1UL << 5)-1)) ALIGN_MASK(SCR_ALIGN_SHIFT)(~((1UL << 5)-1)) | |||||
400 | ||||||
401 | static void *m_alloc(int size, int a_shift) | |||||
402 | { | |||||
403 | u_longunsigned long addr; | |||||
404 | void *ptr; | |||||
405 | u_longunsigned long a_size, a_mask; | |||||
406 | ||||||
407 | if (a_shift < 3) | |||||
408 | a_shift = 3; | |||||
409 | ||||||
410 | a_size = ALIGN_SIZE(a_shift)(1UL << a_shift); | |||||
411 | a_mask = ALIGN_MASK(a_shift)(~((1UL << a_shift)-1)); | |||||
412 | ||||||
413 | ptr = (void *) kmalloclinux_kmalloc(size + a_size, GFP_ATOMIC0x01); | |||||
414 | if (ptr) { | |||||
415 | addr = (((u_longunsigned long) ptr) + a_size) & a_mask; | |||||
416 | *((void **) (addr - sizeof(void *))) = ptr; | |||||
417 | ptr = (void *) addr; | |||||
418 | } | |||||
419 | ||||||
420 | return ptr; | |||||
421 | } | |||||
422 | ||||||
423 | #ifdef MODULE | |||||
424 | static void m_free(void *ptr, int size) | |||||
425 | { | |||||
426 | u_longunsigned long addr; | |||||
427 | ||||||
428 | if (ptr) { | |||||
429 | addr = (u_longunsigned long) ptr; | |||||
430 | ptr = *((void **) (addr - sizeof(void *))); | |||||
431 | ||||||
432 | kfreelinux_kfree(ptr); | |||||
433 | } | |||||
434 | } | |||||
435 | #endif | |||||
436 | ||||||
437 | /* | |||||
438 | ** Transfer direction | |||||
439 | ** | |||||
440 | ** Low-level scsi drivers under Linux do not receive the expected | |||||
441 | ** data transfer direction from upper scsi drivers. | |||||
442 | ** The driver will only check actual data direction for common | |||||
443 | ** scsi opcodes. Other ones may cause problem, since they may | |||||
444 | ** depend on device type or be vendor specific. | |||||
445 | ** I would prefer to never trust the device for data direction, | |||||
446 | ** but that is not possible. | |||||
447 | ** | |||||
448 | ** The original driver requires the expected direction to be known. | |||||
449 | ** The Linux version of the driver has been enhanced in order to | |||||
450 | ** be able to transfer data in the direction choosen by the target. | |||||
451 | */ | |||||
452 | ||||||
453 | #define XferNone0 0 | |||||
454 | #define XferIn1 1 | |||||
455 | #define XferOut2 2 | |||||
456 | #define XferBoth3 3 | |||||
457 | static int guess_xfer_direction(int opcode); | |||||
458 | ||||||
459 | /* | |||||
460 | ** Head of list of NCR boards | |||||
461 | ** | |||||
462 | ** For kernel version < 1.3.70, host is retrieved by its irq level. | |||||
463 | ** For later kernels, the internal host control block address | |||||
464 | ** (struct ncb) is used as device id parameter of the irq stuff. | |||||
465 | */ | |||||
466 | ||||||
467 | static struct Scsi_Host *first_host = NULL((void *) 0); | |||||
468 | static Scsi_Host_Template *the_template = NULL((void *) 0); | |||||
469 | ||||||
470 | ||||||
471 | /* | |||||
472 | ** /proc directory entry and proc_info function | |||||
473 | */ | |||||
474 | ||||||
475 | #if LINUX_VERSION_CODE131108 >= LinuxVersionCode(1,3,0)(((1)<<16)+((3)<<8)+(0)) | |||||
476 | struct proc_dir_entry proc_scsi_ncr53c8xx = { | |||||
477 | PROC_SCSI_NCR53C8XX, 9, "ncr53c8xx", | |||||
478 | S_IFDIR0040000 | S_IRUGO(00400|00040|00004) | S_IXUGO(00100|00010|00001), 2 | |||||
479 | }; | |||||
480 | # ifdef SCSI_NCR_PROC_INFO_SUPPORT | |||||
481 | int ncr53c8xx_proc_info(char *buffer, char **start, off_t offset, | |||||
482 | int length, int hostno, int func); | |||||
483 | # endif | |||||
484 | #endif | |||||
485 | ||||||
486 | /* | |||||
487 | ** Table of target capabilities. | |||||
488 | ** | |||||
489 | ** This bitmap is anded with the byte 7 of inquiry data on completion of | |||||
490 | ** INQUIRY command. | |||||
491 | ** The driver never see zeroed bits and will ignore the corresponding | |||||
492 | ** capabilities of the target. | |||||
493 | */ | |||||
494 | ||||||
495 | static struct { | |||||
496 | unsigned char and_map[MAX_TARGET((16))]; | |||||
497 | } target_capabilities[SCSI_NCR_MAX_HOST(2)] = { NCR53C8XX_TARGET_CAPABILITIES{ { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff , 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, } }, { { 0xff, 0xff, 0xff , 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, } } }; | |||||
498 | ||||||
499 | /* | |||||
500 | ** Driver setup. | |||||
501 | ** | |||||
502 | ** This structure is initialized from linux config options. | |||||
503 | ** It can be overridden at boot-up by the boot command line. | |||||
504 | */ | |||||
505 | struct ncr_driver_setup { | |||||
506 | unsigned master_parity : 1; | |||||
507 | unsigned scsi_parity : 1; | |||||
508 | unsigned disconnection : 1; | |||||
509 | unsigned special_features : 2; | |||||
510 | unsigned ultra_scsi : 2; | |||||
511 | unsigned force_sync_nego: 1; | |||||
512 | unsigned reverse_probe: 1; | |||||
513 | unsigned pci_fix_up: 4; | |||||
514 | u_charunsigned char use_nvram; | |||||
515 | u_charunsigned char verbose; | |||||
516 | u_charunsigned char default_tags; | |||||
517 | u_shortunsigned short default_sync; | |||||
518 | u_shortunsigned short debug; | |||||
519 | u_charunsigned char burst_max; | |||||
520 | u_charunsigned char led_pin; | |||||
521 | u_charunsigned char max_wide; | |||||
522 | u_charunsigned char settle_delay; | |||||
523 | u_charunsigned char diff_support; | |||||
524 | u_charunsigned char irqm; | |||||
525 | u_charunsigned char bus_check; | |||||
526 | }; | |||||
527 | ||||||
528 | static struct ncr_driver_setup | |||||
529 | driver_setup = SCSI_NCR_DRIVER_SETUP{ (1), (1), (1), (3), (2), (0), 0, 0, 1, 1, (0), (50), 0x00, 7 , (0), 1, (2), (0), 0, 1 }; | |||||
530 | ||||||
531 | #ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT | |||||
532 | static struct ncr_driver_setup | |||||
533 | driver_safe_setup __initdata = SCSI_NCR_DRIVER_SAFE_SETUP{ 0, 1, 0, 0, 0, 0, 0, 0, 1, 2, 0, 255, 0x00, 255, 0, 0, 10, 1 , 1, 1 }; | |||||
534 | #ifdef MODULE | |||||
535 | char *ncr53c8xx = 0; /* command line passed by insmod */ | |||||
536 | #endif | |||||
537 | #endif | |||||
538 | ||||||
539 | /* | |||||
540 | ** Other Linux definitions | |||||
541 | */ | |||||
542 | ||||||
543 | #define ScsiResult(host_code, scsi_code)(((host_code) << 16) + ((scsi_code) & 0x7f)) (((host_code) << 16) + ((scsi_code) & 0x7f)) | |||||
544 | ||||||
545 | #if LINUX_VERSION_CODE131108 >= LinuxVersionCode(2,0,0)(((2)<<16)+((0)<<8)+(0)) | |||||
546 | static void ncr53c8xx_select_queue_depths(struct Scsi_Host *host, struct scsi_device *devlist); | |||||
547 | #endif | |||||
548 | ||||||
549 | #if LINUX_VERSION_CODE131108 >= LinuxVersionCode(1,3,70)(((1)<<16)+((3)<<8)+(70)) | |||||
550 | static void ncr53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs); | |||||
551 | #else | |||||
552 | static void ncr53c8xx_intr(int irq, struct pt_regs * regs); | |||||
553 | #endif | |||||
554 | ||||||
555 | static void ncr53c8xx_timeout(unsigned long np); | |||||
556 | ||||||
557 | #define initverbose(driver_setup.verbose) (driver_setup.verbose) | |||||
558 | #define bootverbose(np->verbose) (np->verbose) | |||||
559 | ||||||
560 | #ifdef SCSI_NCR_NVRAM_SUPPORT | |||||
561 | /* | |||||
562 | ** Symbios NvRAM data format | |||||
563 | */ | |||||
564 | #define SYMBIOS_NVRAM_SIZE 368 | |||||
565 | #define SYMBIOS_NVRAM_ADDRESS 0x100 | |||||
566 | ||||||
567 | struct Symbios_nvram { | |||||
568 | /* Header 6 bytes */ | |||||
569 | u_shortunsigned short start_marker; /* 0x0000 */ | |||||
570 | u_shortunsigned short byte_count; /* excluding header/trailer */ | |||||
571 | u_shortunsigned short checksum; | |||||
572 | ||||||
573 | /* Controller set up 20 bytes */ | |||||
574 | u_shortunsigned short word0; /* 0x3000 */ | |||||
575 | u_shortunsigned short word2; /* 0x0000 */ | |||||
576 | u_shortunsigned short word4; /* 0x0000 */ | |||||
577 | u_shortunsigned short flags; | |||||
578 | #define SYMBIOS_SCAM_ENABLE (1) | |||||
579 | #define SYMBIOS_PARITY_ENABLE (1<<1) | |||||
580 | #define SYMBIOS_VERBOSE_MSGS (1<<2) | |||||
581 | u_shortunsigned short flags1; | |||||
582 | #define SYMBIOS_SCAN_HI_LO (1) | |||||
583 | u_shortunsigned short word10; /* 0x00 */ | |||||
584 | u_shortunsigned short flags3; /* 0x00 */ | |||||
585 | #define SYMBIOS_REMOVABLE_FLAGS (3) /* 0=none, 1=bootable, 2=all */ | |||||
586 | u_charunsigned char host_id; | |||||
587 | u_charunsigned char byte15; /* 0x04 */ | |||||
588 | u_shortunsigned short word16; /* 0x0410 */ | |||||
589 | u_shortunsigned short word18; /* 0x0000 */ | |||||
590 | ||||||
591 | /* Boot order 14 bytes * 4 */ | |||||
592 | struct Symbios_host{ | |||||
593 | u_charunsigned char word0; /* 0x0004:ok / 0x0000:nok */ | |||||
594 | u_shortunsigned short device_id; /* PCI device id */ | |||||
595 | u_shortunsigned short vendor_id; /* PCI vendor id */ | |||||
596 | u_charunsigned char byte6; /* 0x00 */ | |||||
597 | u_charunsigned char device_fn; /* PCI device/function number << 3*/ | |||||
598 | u_shortunsigned short word8; | |||||
599 | u_shortunsigned short flags; | |||||
600 | #define SYMBIOS_INIT_SCAN_AT_BOOT (1) | |||||
601 | u_shortunsigned short io_port; /* PCI io_port address */ | |||||
602 | } host[4]; | |||||
603 | ||||||
604 | /* Targets 8 bytes * 16 */ | |||||
605 | struct Symbios_target { | |||||
606 | u_shortunsigned short flags; | |||||
607 | #define SYMBIOS_DISCONNECT_ENABLE (1) | |||||
608 | #define SYMBIOS_SCAN_AT_BOOT_TIME (1<<1) | |||||
609 | #define SYMBIOS_SCAN_LUNS (1<<2) | |||||
610 | #define SYMBIOS_QUEUE_TAGS_ENABLED (1<<3) | |||||
611 | u_charunsigned char bus_width; /* 0x08/0x10 */ | |||||
612 | u_charunsigned char sync_offset; | |||||
613 | u_charunsigned char sync_period; /* 4*period factor */ | |||||
614 | u_charunsigned char byte6; /* 0x00 */ | |||||
615 | u_shortunsigned short timeout; | |||||
616 | } target[16]; | |||||
617 | u_charunsigned char spare_devices[19*8]; | |||||
618 | u_charunsigned char trailer[6]; /* 0xfe 0xfe 0x00 0x00 0x00 0x00 */ | |||||
619 | }; | |||||
620 | typedef struct Symbios_nvram Symbios_nvram; | |||||
621 | typedef struct Symbios_host Symbios_host; | |||||
622 | typedef struct Symbios_target Symbios_target; | |||||
623 | ||||||
624 | /* | |||||
625 | ** Tekram NvRAM data format. | |||||
626 | */ | |||||
627 | #define TEKRAM_NVRAM_SIZE 64 | |||||
628 | #define TEKRAM_NVRAM_ADDRESS 0 | |||||
629 | ||||||
630 | struct Tekram_nvram { | |||||
631 | struct Tekram_target { | |||||
632 | u_charunsigned char flags; | |||||
633 | #define TEKRAM_PARITY_CHECK (1) | |||||
634 | #define TEKRAM_SYNC_NEGO (1<<1) | |||||
635 | #define TEKRAM_DISCONNECT_ENABLE (1<<2) | |||||
636 | #define TEKRAM_START_CMD (1<<3) | |||||
637 | #define TEKRAM_TAGGED_COMMANDS (1<<4) | |||||
638 | #define TEKRAM_WIDE_NEGO (1<<5) | |||||
639 | u_charunsigned char sync_index; | |||||
640 | u_shortunsigned short word2; | |||||
641 | } target[16]; | |||||
642 | u_charunsigned char host_id; | |||||
643 | u_charunsigned char flags; | |||||
644 | #define TEKRAM_MORE_THAN_2_DRIVES (1) | |||||
645 | #define TEKRAM_DRIVES_SUP_1GB (1<<1) | |||||
646 | #define TEKRAM_RESET_ON_POWER_ON (1<<2) | |||||
647 | #define TEKRAM_ACTIVE_NEGATION (1<<3) | |||||
648 | #define TEKRAM_IMMEDIATE_SEEK (1<<4) | |||||
649 | #define TEKRAM_SCAN_LUNS (1<<5) | |||||
650 | #define TEKRAM_REMOVABLE_FLAGS (3<<6) /* 0: disable; 1: boot device; 2:all */ | |||||
651 | u_charunsigned char boot_delay_index; | |||||
652 | u_charunsigned char max_tags_index; | |||||
653 | u_shortunsigned short flags1; | |||||
654 | #define TEKRAM_F2_F6_ENABLED (1) | |||||
655 | u_shortunsigned short spare[29]; | |||||
656 | }; | |||||
657 | typedef struct Tekram_nvram Tekram_nvram; | |||||
658 | typedef struct Tekram_target Tekram_target; | |||||
659 | ||||||
660 | static u_charunsigned char Tekram_sync[12] __initdata = {25,31,37,43,50,62,75,125,12,15,18,21}; | |||||
661 | ||||||
662 | #endif /* SCSI_NCR_NVRAM_SUPPORT */ | |||||
663 | ||||||
664 | /* | |||||
665 | ** Structures used by ncr53c8xx_detect/ncr53c8xx_pci_init to | |||||
666 | ** transmit device configuration to the ncr_attach() function. | |||||
667 | */ | |||||
668 | typedef struct { | |||||
669 | int bus; | |||||
670 | u_charunsigned char device_fn; | |||||
671 | u_intunsigned int base; | |||||
672 | u_intunsigned int base_2; | |||||
673 | u_intunsigned int io_port; | |||||
674 | int irq; | |||||
675 | /* port and reg fields to use INB, OUTB macros */ | |||||
676 | u_intunsigned int port; | |||||
677 | volatile struct ncr_reg *reg; | |||||
678 | } ncr_slot; | |||||
679 | ||||||
680 | typedef struct { | |||||
681 | int type; | |||||
682 | #define SCSI_NCR_SYMBIOS_NVRAM(1) (1) | |||||
683 | #define SCSI_NCR_TEKRAM_NVRAM(2) (2) | |||||
684 | #ifdef SCSI_NCR_NVRAM_SUPPORT | |||||
685 | union { | |||||
686 | Symbios_nvram Symbios; | |||||
687 | Tekram_nvram Tekram; | |||||
688 | } data; | |||||
689 | #endif | |||||
690 | } ncr_nvram; | |||||
691 | ||||||
692 | /* | |||||
693 | ** Structure used by ncr53c8xx_detect/ncr53c8xx_pci_init | |||||
694 | ** to save data on each detected board for ncr_attach(). | |||||
695 | */ | |||||
696 | typedef struct { | |||||
697 | ncr_slot slot; | |||||
698 | ncr_chip chip; | |||||
699 | ncr_nvram *nvram; | |||||
700 | int attach_done; | |||||
701 | } ncr_device; | |||||
702 | ||||||
703 | /*========================================================== | |||||
704 | ** | |||||
705 | ** Debugging tags | |||||
706 | ** | |||||
707 | **========================================================== | |||||
708 | */ | |||||
709 | ||||||
710 | #define DEBUG_ALLOC(0x0001) (0x0001) | |||||
711 | #define DEBUG_PHASE(0x0002) (0x0002) | |||||
712 | #define DEBUG_POLL(0x0004) (0x0004) | |||||
713 | #define DEBUG_QUEUE(0x0008) (0x0008) | |||||
714 | #define DEBUG_RESULT(0x0010) (0x0010) | |||||
715 | #define DEBUG_SCATTER(0x0020) (0x0020) | |||||
716 | #define DEBUG_SCRIPT(0x0040) (0x0040) | |||||
717 | #define DEBUG_TINY(0x0080) (0x0080) | |||||
718 | #define DEBUG_TIMING(0x0100) (0x0100) | |||||
719 | #define DEBUG_NEGO(0x0200) (0x0200) | |||||
720 | #define DEBUG_TAGS(0x0400) (0x0400) | |||||
721 | #define DEBUG_FREEZE(0x0800) (0x0800) | |||||
722 | #define DEBUG_RESTART(0x1000) (0x1000) | |||||
723 | ||||||
724 | /* | |||||
725 | ** Enable/Disable debug messages. | |||||
726 | ** Can be changed at runtime too. | |||||
727 | */ | |||||
728 | ||||||
729 | #ifdef SCSI_NCR_DEBUG_INFO_SUPPORT | |||||
730 | #define DEBUG_FLAGSncr_debug ncr_debug | |||||
731 | #else | |||||
732 | #define DEBUG_FLAGSncr_debug SCSI_NCR_DEBUG_FLAGS(0) | |||||
733 | #endif | |||||
734 | ||||||
735 | ||||||
736 | ||||||
737 | /*========================================================== | |||||
738 | ** | |||||
739 | ** assert () | |||||
740 | ** | |||||
741 | **========================================================== | |||||
742 | ** | |||||
743 | ** modified copy from 386bsd:/usr/include/sys/assert.h | |||||
744 | ** | |||||
745 | **---------------------------------------------------------- | |||||
746 | */ | |||||
747 | ||||||
748 | #define assert(expression){ if (!(expression)) { (void)printk( "assertion \"%s\" failed: file \"%s\", line %d\n" , "expression", "../linux/src/drivers/scsi/ncr53c8xx.c", 748) ; } } { \ | |||||
749 | if (!(expression)) { \ | |||||
750 | (void)printfprintk(\ | |||||
751 | "assertion \"%s\" failed: file \"%s\", line %d\n", \ | |||||
752 | #expression, \ | |||||
753 | __FILE__"../linux/src/drivers/scsi/ncr53c8xx.c", __LINE__753); \ | |||||
754 | } \ | |||||
755 | } | |||||
756 | ||||||
757 | /*========================================================== | |||||
758 | ** | |||||
759 | ** Big/Little endian support. | |||||
760 | ** | |||||
761 | **========================================================== | |||||
762 | */ | |||||
763 | ||||||
764 | /* | |||||
765 | ** If the NCR uses big endian addressing mode over the | |||||
766 | ** PCI, actual io register addresses for byte and word | |||||
767 | ** accesses must be changed according to lane routing. | |||||
768 | ** Btw, ncr_offb() and ncr_offw() macros only apply to | |||||
769 | ** constants and so donnot generate bloated code. | |||||
770 | */ | |||||
771 | ||||||
772 | #if defined(SCSI_NCR_BIG_ENDIAN) | |||||
773 | ||||||
774 | #define ncr_offb(o)(o) (((o)&~3)+((~((o)&3))&3)) | |||||
775 | #define ncr_offw(o)(o) (((o)&~3)+((~((o)&3))&2)) | |||||
776 | ||||||
777 | #else | |||||
778 | ||||||
779 | #define ncr_offb(o)(o) (o) | |||||
780 | #define ncr_offw(o)(o) (o) | |||||
781 | ||||||
782 | #endif | |||||
783 | ||||||
784 | /* | |||||
785 | ** If the CPU and the NCR use same endian-ness adressing, | |||||
786 | ** no byte reordering is needed for script patching. | |||||
787 | ** Macro cpu_to_scr() is to be used for script patching. | |||||
788 | ** Macro scr_to_cpu() is to be used for getting a DWORD | |||||
789 | ** from the script. | |||||
790 | */ | |||||
791 | ||||||
792 | #if defined(__BIG_ENDIAN) && !defined(SCSI_NCR_BIG_ENDIAN) | |||||
793 | ||||||
794 | #define cpu_to_scr(dw)(dw) cpu_to_le32(dw) | |||||
795 | #define scr_to_cpu(dw)(dw) le32_to_cpu(dw) | |||||
796 | ||||||
797 | #elif defined(__LITTLE_ENDIAN) && defined(SCSI_NCR_BIG_ENDIAN) | |||||
798 | ||||||
799 | #define cpu_to_scr(dw)(dw) cpu_to_be32(dw) | |||||
800 | #define scr_to_cpu(dw)(dw) be32_to_cpu(dw) | |||||
801 | ||||||
802 | #else | |||||
803 | ||||||
804 | #define cpu_to_scr(dw)(dw) (dw) | |||||
805 | #define scr_to_cpu(dw)(dw) (dw) | |||||
806 | ||||||
807 | #endif | |||||
808 | ||||||
809 | /*========================================================== | |||||
810 | ** | |||||
811 | ** Access to the controller chip. | |||||
812 | ** | |||||
813 | ** If NCR_IOMAPPED is defined, only IO are used by the driver. | |||||
814 | ** | |||||
815 | **========================================================== | |||||
816 | */ | |||||
817 | ||||||
818 | /* | |||||
819 | ** If the CPU and the NCR use same endian-ness adressing, | |||||
820 | ** no byte reordering is needed for accessing chip io | |||||
821 | ** registers. Functions suffixed by '_raw' are assumed | |||||
822 | ** to access the chip over the PCI without doing byte | |||||
823 | ** reordering. Functions suffixed by '_l2b' are | |||||
824 | ** assumed to perform little-endian to big-endian byte | |||||
825 | ** reordering, those suffixed by '_b2l' blah, blah, | |||||
826 | ** blah, ... | |||||
827 | */ | |||||
828 | ||||||
829 | #if defined(NCR_IOMAPPED) | |||||
830 | ||||||
831 | /* | |||||
832 | ** IO mapped only input / ouput | |||||
833 | */ | |||||
834 | ||||||
835 | #define INB_OFF(o)(*(volatile unsigned char *) ((char *)np->reg + (o))) inb (np->port + ncr_offb(o))((__builtin_constant_p((np->port + (o))) && (np-> port + (o)) < 256) ? __inbc(np->port + (o)) : __inb(np-> port + (o))) | |||||
836 | #define OUTB_OFF(o, val)((*(volatile unsigned char *) ((char *)np->reg + (o))) = ( (val))) outb ((val), np->port + ncr_offb(o))((__builtin_constant_p((np->port + (o))) && (np-> port + (o)) < 256) ? __outbc(((val)),(np->port + (o))) : __outb(((val)),(np->port + (o)))) | |||||
837 | ||||||
838 | #if defined(__BIG_ENDIAN) && !defined(SCSI_NCR_BIG_ENDIAN) | |||||
839 | ||||||
840 | #define INW_OFF(o)(*(volatile unsigned short *) ((char *)np->reg + (o))) inw_l2b (np->port + ncr_offw(o)(o)) | |||||
841 | #define INL_OFF(o)(*(volatile unsigned int *) ((char *)np->reg + (o))) inl_l2b (np->port + (o)) | |||||
842 | ||||||
843 | #define OUTW_OFF(o, val)((*(volatile unsigned short *) ((char *)np->reg + (o))) = ( (val))) outw_b2l ((val), np->port + ncr_offw(o)(o)) | |||||
844 | #define OUTL_OFF(o, val)((*(volatile unsigned int *) ((char *)np->reg + (o))) = (( val))) outl_b2l ((val), np->port + (o)) | |||||
845 | ||||||
846 | #elif defined(__LITTLE_ENDIAN) && defined(SCSI_NCR_BIG_ENDIAN) | |||||
847 | ||||||
848 | #define INW_OFF(o)(*(volatile unsigned short *) ((char *)np->reg + (o))) inw_b2l (np->port + ncr_offw(o)(o)) | |||||
849 | #define INL_OFF(o)(*(volatile unsigned int *) ((char *)np->reg + (o))) inl_b2l (np->port + (o)) | |||||
850 | ||||||
851 | #define OUTW_OFF(o, val)((*(volatile unsigned short *) ((char *)np->reg + (o))) = ( (val))) outw_l2b ((val), np->port + ncr_offw(o)(o)) | |||||
852 | #define OUTL_OFF(o, val)((*(volatile unsigned int *) ((char *)np->reg + (o))) = (( val))) outl_l2b ((val), np->port + (o)) | |||||
853 | ||||||
854 | #else | |||||
855 | ||||||
856 | #define INW_OFF(o)(*(volatile unsigned short *) ((char *)np->reg + (o))) inw_raw (np->port + ncr_offw(o))((__builtin_constant_p((np->port + (o))) && (np-> port + (o)) < 256) ? __inwc(np->port + (o)) : __inw(np-> port + (o))) | |||||
857 | #define INL_OFF(o)(*(volatile unsigned int *) ((char *)np->reg + (o))) inl_raw (np->port + (o))((__builtin_constant_p((np->port + (o))) && (np-> port + (o)) < 256) ? __inlc(np->port + (o)) : __inl(np-> port + (o))) | |||||
858 | ||||||
859 | #define OUTW_OFF(o, val)((*(volatile unsigned short *) ((char *)np->reg + (o))) = ( (val))) outw_raw ((val), np->port + ncr_offw(o))((__builtin_constant_p((np->port + (o))) && (np-> port + (o)) < 256) ? __outwc(((val)),(np->port + (o))) : __outw(((val)),(np->port + (o)))) | |||||
860 | #define OUTL_OFF(o, val)((*(volatile unsigned int *) ((char *)np->reg + (o))) = (( val))) outl_raw ((val), np->port + (o))((__builtin_constant_p((np->port + (o))) && (np-> port + (o)) < 256) ? __outlc(((val)),(np->port + (o))) : __outl(((val)),(np->port + (o)))) | |||||
861 | ||||||
862 | #endif /* ENDIANs */ | |||||
863 | ||||||
864 | #else /* defined NCR_IOMAPPED */ | |||||
865 | ||||||
866 | /* | |||||
867 | ** MEMORY mapped IO input / output | |||||
868 | */ | |||||
869 | ||||||
870 | #define INB_OFF(o)(*(volatile unsigned char *) ((char *)np->reg + (o))) readb((char *)np->reg + ncr_offb(o))(*(volatile unsigned char *) ((char *)np->reg + (o))) | |||||
871 | #define OUTB_OFF(o, val)((*(volatile unsigned char *) ((char *)np->reg + (o))) = ( (val))) writeb((val), (char *)np->reg + ncr_offb(o))((*(volatile unsigned char *) ((char *)np->reg + (o))) = ( (val))) | |||||
872 | ||||||
873 | #if defined(__BIG_ENDIAN) && !defined(SCSI_NCR_BIG_ENDIAN) | |||||
874 | ||||||
875 | #define INW_OFF(o)(*(volatile unsigned short *) ((char *)np->reg + (o))) readw_l2b((char *)np->reg + ncr_offw(o)(o)) | |||||
876 | #define INL_OFF(o)(*(volatile unsigned int *) ((char *)np->reg + (o))) readl_l2b((char *)np->reg + (o)) | |||||
877 | ||||||
878 | #define OUTW_OFF(o, val)((*(volatile unsigned short *) ((char *)np->reg + (o))) = ( (val))) writew_b2l((val), (char *)np->reg + ncr_offw(o)(o)) | |||||
879 | #define OUTL_OFF(o, val)((*(volatile unsigned int *) ((char *)np->reg + (o))) = (( val))) writel_b2l((val), (char *)np->reg + (o)) | |||||
880 | ||||||
881 | #elif defined(__LITTLE_ENDIAN) && defined(SCSI_NCR_BIG_ENDIAN) | |||||
882 | ||||||
883 | #define INW_OFF(o)(*(volatile unsigned short *) ((char *)np->reg + (o))) readw_b2l((char *)np->reg + ncr_offw(o)(o)) | |||||
884 | #define INL_OFF(o)(*(volatile unsigned int *) ((char *)np->reg + (o))) readl_b2l((char *)np->reg + (o)) | |||||
885 | ||||||
886 | #define OUTW_OFF(o, val)((*(volatile unsigned short *) ((char *)np->reg + (o))) = ( (val))) writew_l2b((val), (char *)np->reg + ncr_offw(o)(o)) | |||||
887 | #define OUTL_OFF(o, val)((*(volatile unsigned int *) ((char *)np->reg + (o))) = (( val))) writel_l2b((val), (char *)np->reg + (o)) | |||||
888 | ||||||
889 | #else | |||||
890 | ||||||
891 | #define INW_OFF(o)(*(volatile unsigned short *) ((char *)np->reg + (o))) readw_raw((char *)np->reg + ncr_offw(o))(*(volatile unsigned short *) ((char *)np->reg + (o))) | |||||
892 | #define INL_OFF(o)(*(volatile unsigned int *) ((char *)np->reg + (o))) readl_raw((char *)np->reg + (o))(*(volatile unsigned int *) ((char *)np->reg + (o))) | |||||
893 | ||||||
894 | #define OUTW_OFF(o, val)((*(volatile unsigned short *) ((char *)np->reg + (o))) = ( (val))) writew_raw((val), (char *)np->reg + ncr_offw(o))((*(volatile unsigned short *) ((char *)np->reg + (o))) = ( (val))) | |||||
895 | #define OUTL_OFF(o, val)((*(volatile unsigned int *) ((char *)np->reg + (o))) = (( val))) writel_raw((val), (char *)np->reg + (o))((*(volatile unsigned int *) ((char *)np->reg + (o))) = (( val))) | |||||
896 | ||||||
897 | #endif | |||||
898 | ||||||
899 | #endif /* defined NCR_IOMAPPED */ | |||||
900 | ||||||
901 | #define INB(r)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->r))))) INB_OFF (offsetof(struct ncr_reg,r))(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->r))))) | |||||
902 | #define INW(r)(*(volatile unsigned short *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->r))))) INW_OFF (offsetof(struct ncr_reg,r))(*(volatile unsigned short *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->r))))) | |||||
903 | #define INL(r)(*(volatile unsigned int *) ((char *)np->reg + (((size_t) ( &((struct ncr_reg *)0)->r))))) INL_OFF (offsetof(struct ncr_reg,r))(*(volatile unsigned int *) ((char *)np->reg + (((size_t) ( &((struct ncr_reg *)0)->r))))) | |||||
904 | ||||||
905 | #define OUTB(r, val)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->r))))) = (((val)))) OUTB_OFF (offsetof(struct ncr_reg,r), (val))((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->r))))) = (((val)))) | |||||
906 | #define OUTW(r, val)((*(volatile unsigned short *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->r))))) = (((val)))) OUTW_OFF (offsetof(struct ncr_reg,r), (val))((*(volatile unsigned short *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->r))))) = (((val)))) | |||||
907 | #define OUTL(r, val)((*(volatile unsigned int *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->r))))) = (((val)))) OUTL_OFF (offsetof(struct ncr_reg,r), (val))((*(volatile unsigned int *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->r))))) = (((val)))) | |||||
908 | ||||||
909 | /* | |||||
910 | ** Set bit field ON, OFF | |||||
911 | */ | |||||
912 | ||||||
913 | #define OUTONB(r, m)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->r))))) = ((((*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->r))))) | (m))))) OUTB(r, INB(r) | (m))((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->r))))) = ((((*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->r))))) | (m))))) | |||||
914 | #define OUTOFFB(r, m)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->r))))) = ((((*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->r))))) & ~(m))))) OUTB(r, INB(r) & ~(m))((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->r))))) = ((((*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->r))))) & ~(m))))) | |||||
915 | #define OUTONW(r, m)((*(volatile unsigned short *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->r))))) = ((((*(volatile unsigned short *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->r))))) | (m))))) OUTW(r, INW(r) | (m))((*(volatile unsigned short *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->r))))) = ((((*(volatile unsigned short *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->r))))) | (m))))) | |||||
916 | #define OUTOFFW(r, m)((*(volatile unsigned short *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->r))))) = ((((*(volatile unsigned short *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->r))))) & ~(m))))) OUTW(r, INW(r) & ~(m))((*(volatile unsigned short *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->r))))) = ((((*(volatile unsigned short *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->r))))) & ~(m))))) | |||||
917 | #define OUTONL(r, m)((*(volatile unsigned int *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->r))))) = ((((*(volatile unsigned int *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->r))))) | (m))))) OUTL(r, INL(r) | (m))((*(volatile unsigned int *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->r))))) = ((((*(volatile unsigned int *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->r))))) | (m))))) | |||||
918 | #define OUTOFFL(r, m)((*(volatile unsigned int *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->r))))) = ((((*(volatile unsigned int *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->r))))) & ~(m))))) OUTL(r, INL(r) & ~(m))((*(volatile unsigned int *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->r))))) = ((((*(volatile unsigned int *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->r))))) & ~(m))))) | |||||
919 | ||||||
920 | ||||||
921 | /*========================================================== | |||||
922 | ** | |||||
923 | ** Command control block states. | |||||
924 | ** | |||||
925 | **========================================================== | |||||
926 | */ | |||||
927 | ||||||
928 | #define HS_IDLE(0) (0) | |||||
929 | #define HS_BUSY(1) (1) | |||||
930 | #define HS_NEGOTIATE(2) (2) /* sync/wide data transfer*/ | |||||
931 | #define HS_DISCONNECT(3) (3) /* Disconnected by target */ | |||||
932 | ||||||
933 | #define HS_COMPLETE(4) (4) | |||||
934 | #define HS_SEL_TIMEOUT(5) (5) /* Selection timeout */ | |||||
935 | #define HS_RESET(6) (6) /* SCSI reset */ | |||||
936 | #define HS_ABORTED(7) (7) /* Transfer aborted */ | |||||
937 | #define HS_TIMEOUT(8) (8) /* Software timeout */ | |||||
938 | #define HS_FAIL(9) (9) /* SCSI or PCI bus errors */ | |||||
939 | #define HS_UNEXPECTED(10) (10) /* Unexpected disconnect */ | |||||
940 | ||||||
941 | #define HS_DONEMASK(0xfc) (0xfc) | |||||
942 | ||||||
943 | /*========================================================== | |||||
944 | ** | |||||
945 | ** Software Interrupt Codes | |||||
946 | ** | |||||
947 | **========================================================== | |||||
948 | */ | |||||
949 | ||||||
950 | #define SIR_SENSE_RESTART(1) (1) | |||||
951 | #define SIR_SENSE_FAILED(2) (2) | |||||
952 | #define SIR_STALL_RESTART(3) (3) | |||||
953 | #define SIR_STALL_QUEUE(4) (4) | |||||
954 | #define SIR_NEGO_SYNC(5) (5) | |||||
955 | #define SIR_NEGO_WIDE(6) (6) | |||||
956 | #define SIR_NEGO_FAILED(7) (7) | |||||
957 | #define SIR_NEGO_PROTO(8) (8) | |||||
958 | #define SIR_REJECT_RECEIVED(9) (9) | |||||
959 | #define SIR_REJECT_SENT(10) (10) | |||||
960 | #define SIR_IGN_RESIDUE(11) (11) | |||||
961 | #define SIR_MISSING_SAVE(12) (12) | |||||
962 | #define SIR_DATA_IO_IS_OUT(13) (13) | |||||
963 | #define SIR_DATA_IO_IS_IN(14) (14) | |||||
964 | #define SIR_MAX(14) (14) | |||||
965 | ||||||
966 | /*========================================================== | |||||
967 | ** | |||||
968 | ** Extended error codes. | |||||
969 | ** xerr_status field of struct ccb. | |||||
970 | ** | |||||
971 | **========================================================== | |||||
972 | */ | |||||
973 | ||||||
974 | #define XE_OK(0) (0) | |||||
975 | #define XE_EXTRA_DATA(1) (1) /* unexpected data phase */ | |||||
976 | #define XE_BAD_PHASE(2) (2) /* illegal phase (4/5) */ | |||||
977 | ||||||
978 | /*========================================================== | |||||
979 | ** | |||||
980 | ** Negotiation status. | |||||
981 | ** nego_status field of struct ccb. | |||||
982 | ** | |||||
983 | **========================================================== | |||||
984 | */ | |||||
985 | ||||||
986 | #define NS_SYNC(1) (1) | |||||
987 | #define NS_WIDE(2) (2) | |||||
988 | ||||||
989 | /*========================================================== | |||||
990 | ** | |||||
991 | ** "Special features" of targets. | |||||
992 | ** quirks field of struct tcb. | |||||
993 | ** actualquirks field of struct ccb. | |||||
994 | ** | |||||
995 | **========================================================== | |||||
996 | */ | |||||
997 | ||||||
998 | #define QUIRK_AUTOSAVE(0x01) (0x01) | |||||
999 | #define QUIRK_NOMSG(0x02) (0x02) | |||||
1000 | #define QUIRK_NOSYNC(0x10) (0x10) | |||||
1001 | #define QUIRK_NOWIDE16(0x20) (0x20) | |||||
1002 | #define QUIRK_UPDATE(0x80) (0x80) | |||||
1003 | ||||||
1004 | /*========================================================== | |||||
1005 | ** | |||||
1006 | ** Capability bits in Inquire response byte 7. | |||||
1007 | ** | |||||
1008 | **========================================================== | |||||
1009 | */ | |||||
1010 | ||||||
1011 | #define INQ7_QUEUE(0x02) (0x02) | |||||
1012 | #define INQ7_SYNC(0x10) (0x10) | |||||
1013 | #define INQ7_WIDE16(0x20) (0x20) | |||||
1014 | ||||||
1015 | /*========================================================== | |||||
1016 | ** | |||||
1017 | ** Misc. | |||||
1018 | ** | |||||
1019 | **========================================================== | |||||
1020 | */ | |||||
1021 | ||||||
1022 | #define CCB_MAGIC(0xf2691ad2) (0xf2691ad2) | |||||
1023 | ||||||
1024 | /*========================================================== | |||||
1025 | ** | |||||
1026 | ** Declaration of structs. | |||||
1027 | ** | |||||
1028 | **========================================================== | |||||
1029 | */ | |||||
1030 | ||||||
1031 | struct tcb; | |||||
1032 | struct lcb; | |||||
1033 | struct ccb; | |||||
1034 | struct ncb; | |||||
1035 | struct script; | |||||
1036 | ||||||
1037 | typedef struct ncb * ncb_p; | |||||
1038 | typedef struct tcb * tcb_p; | |||||
1039 | typedef struct lcb * lcb_p; | |||||
1040 | typedef struct ccb * ccb_p; | |||||
1041 | ||||||
1042 | struct link { | |||||
1043 | ncrcmd l_cmd; | |||||
1044 | ncrcmd l_paddr; | |||||
1045 | }; | |||||
1046 | ||||||
1047 | struct usrcmd { | |||||
1048 | u_longunsigned long target; | |||||
1049 | u_longunsigned long lun; | |||||
1050 | u_longunsigned long data; | |||||
1051 | u_longunsigned long cmd; | |||||
1052 | }; | |||||
1053 | ||||||
1054 | #define UC_SETSYNC10 10 | |||||
1055 | #define UC_SETTAGS11 11 | |||||
1056 | #define UC_SETDEBUG12 12 | |||||
1057 | #define UC_SETORDER13 13 | |||||
1058 | #define UC_SETWIDE14 14 | |||||
1059 | #define UC_SETFLAG15 15 | |||||
1060 | #define UC_CLEARPROF16 16 | |||||
1061 | ||||||
1062 | #ifdef SCSI_NCR_DEBUG_ERROR_RECOVERY_SUPPORT | |||||
1063 | #define UC_DEBUG_ERROR_RECOVERY 17 | |||||
1064 | #endif | |||||
1065 | ||||||
1066 | #define UF_TRACE(0x01) (0x01) | |||||
1067 | #define UF_NODISC(0x02) (0x02) | |||||
1068 | #define UF_NOSCAN(0x04) (0x04) | |||||
1069 | ||||||
1070 | /*--------------------------------------- | |||||
1071 | ** | |||||
1072 | ** Timestamps for profiling | |||||
1073 | ** | |||||
1074 | **--------------------------------------- | |||||
1075 | */ | |||||
1076 | ||||||
1077 | struct tstamp { | |||||
1078 | u_longunsigned long start; | |||||
1079 | u_longunsigned long end; | |||||
1080 | u_longunsigned long select; | |||||
1081 | u_longunsigned long command; | |||||
1082 | u_longunsigned long status; | |||||
1083 | u_longunsigned long disconnect; | |||||
1084 | u_longunsigned long reselect; | |||||
1085 | }; | |||||
1086 | ||||||
1087 | /* | |||||
1088 | ** profiling data (per device) | |||||
1089 | */ | |||||
1090 | ||||||
1091 | struct profile { | |||||
1092 | u_longunsigned long num_trans; | |||||
1093 | u_longunsigned long num_kbytes; | |||||
1094 | u_longunsigned long rest_bytes; | |||||
1095 | u_longunsigned long num_disc; | |||||
1096 | u_longunsigned long num_break; | |||||
1097 | u_longunsigned long num_int; | |||||
1098 | u_longunsigned long num_fly; | |||||
1099 | u_longunsigned long ms_setup; | |||||
1100 | u_longunsigned long ms_data; | |||||
1101 | u_longunsigned long ms_disc; | |||||
1102 | u_longunsigned long ms_post; | |||||
1103 | }; | |||||
1104 | ||||||
1105 | /*========================================================== | |||||
1106 | ** | |||||
1107 | ** Declaration of structs: target control block | |||||
1108 | ** | |||||
1109 | **========================================================== | |||||
1110 | */ | |||||
1111 | ||||||
1112 | struct tcb { | |||||
1113 | /* | |||||
1114 | ** during reselection the ncr jumps to this point | |||||
1115 | ** with SFBR set to the encoded target number | |||||
1116 | ** with bit 7 set. | |||||
1117 | ** if it's not this target, jump to the next. | |||||
1118 | ** | |||||
1119 | ** JUMP IF (SFBR != #target#) | |||||
1120 | ** @(next tcb) | |||||
1121 | */ | |||||
1122 | ||||||
1123 | struct link jump_tcb; | |||||
1124 | ||||||
1125 | /* | |||||
1126 | ** load the actual values for the sxfer and the scntl3 | |||||
1127 | ** register (sync/wide mode). | |||||
1128 | ** | |||||
1129 | ** SCR_COPY (1); | |||||
1130 | ** @(sval field of this tcb) | |||||
1131 | ** @(sxfer register) | |||||
1132 | ** SCR_COPY (1); | |||||
1133 | ** @(wval field of this tcb) | |||||
1134 | ** @(scntl3 register) | |||||
1135 | */ | |||||
1136 | ||||||
1137 | ncrcmd getscr[6]; | |||||
1138 | ||||||
1139 | /* | |||||
1140 | ** if next message is "identify" | |||||
1141 | ** then load the message to SFBR, | |||||
1142 | ** else load 0 to SFBR. | |||||
1143 | ** | |||||
1144 | ** CALL | |||||
1145 | ** <RESEL_LUN> | |||||
1146 | */ | |||||
1147 | ||||||
1148 | struct link call_lun; | |||||
1149 | ||||||
1150 | /* | |||||
1151 | ** now look for the right lun. | |||||
1152 | ** | |||||
1153 | ** JUMP | |||||
1154 | ** @(first ccb of this lun) | |||||
1155 | */ | |||||
1156 | ||||||
1157 | struct link jump_lcb; | |||||
1158 | ||||||
1159 | /* | |||||
1160 | ** pointer to interrupted getcc ccb | |||||
1161 | */ | |||||
1162 | ||||||
1163 | ccb_p hold_cp; | |||||
1164 | ||||||
1165 | /* | |||||
1166 | ** pointer to ccb used for negotiating. | |||||
1167 | ** Avoid to start a nego for all queued commands | |||||
1168 | ** when tagged command queuing is enabled. | |||||
1169 | */ | |||||
1170 | ||||||
1171 | ccb_p nego_cp; | |||||
1172 | ||||||
1173 | /* | |||||
1174 | ** statistical data | |||||
1175 | */ | |||||
1176 | ||||||
1177 | u_longunsigned long transfers; | |||||
1178 | u_longunsigned long bytes; | |||||
1179 | ||||||
1180 | /* | |||||
1181 | ** user settable limits for sync transfer | |||||
1182 | ** and tagged commands. | |||||
1183 | ** These limits are read from the NVRAM if present. | |||||
1184 | */ | |||||
1185 | ||||||
1186 | u_charunsigned char usrsync; | |||||
1187 | u_charunsigned char usrwide; | |||||
1188 | u_charunsigned char usrtags; | |||||
1189 | u_charunsigned char usrflag; | |||||
1190 | ||||||
1191 | u_charunsigned char numtags; | |||||
1192 | u_charunsigned char maxtags; | |||||
1193 | u_shortunsigned short num_good; | |||||
1194 | ||||||
1195 | /* | |||||
1196 | ** negotiation of wide and synch transfer. | |||||
1197 | ** device quirks. | |||||
1198 | */ | |||||
1199 | ||||||
1200 | /*0*/ u_charunsigned char minsync; | |||||
1201 | /*1*/ u_charunsigned char sval; | |||||
1202 | /*2*/ u_shortunsigned short period; | |||||
1203 | /*0*/ u_charunsigned char maxoffs; | |||||
1204 | ||||||
1205 | /*1*/ u_charunsigned char quirks; | |||||
1206 | ||||||
1207 | /*2*/ u_charunsigned char widedone; | |||||
1208 | /*3*/ u_charunsigned char wval; | |||||
1209 | /* | |||||
1210 | ** inquire data | |||||
1211 | */ | |||||
1212 | #define MAX_INQUIRE36 36 | |||||
1213 | u_charunsigned char inqdata[MAX_INQUIRE36]; | |||||
1214 | ||||||
1215 | /* | |||||
1216 | ** the lcb's of this tcb | |||||
1217 | */ | |||||
1218 | ||||||
1219 | lcb_p lp[MAX_LUN(8)]; | |||||
1220 | }; | |||||
1221 | ||||||
1222 | /*========================================================== | |||||
1223 | ** | |||||
1224 | ** Declaration of structs: lun control block | |||||
1225 | ** | |||||
1226 | **========================================================== | |||||
1227 | */ | |||||
1228 | ||||||
1229 | struct lcb { | |||||
1230 | /* | |||||
1231 | ** during reselection the ncr jumps to this point | |||||
1232 | ** with SFBR set to the "Identify" message. | |||||
1233 | ** if it's not this lun, jump to the next. | |||||
1234 | ** | |||||
1235 | ** JUMP IF (SFBR != #lun#) | |||||
1236 | ** @(next lcb of this target) | |||||
1237 | */ | |||||
1238 | ||||||
1239 | struct link jump_lcb; | |||||
1240 | ||||||
1241 | /* | |||||
1242 | ** if next message is "simple tag", | |||||
1243 | ** then load the tag to SFBR, | |||||
1244 | ** else load 0 to SFBR. | |||||
1245 | ** | |||||
1246 | ** CALL | |||||
1247 | ** <RESEL_TAG> | |||||
1248 | */ | |||||
1249 | ||||||
1250 | struct link call_tag; | |||||
1251 | ||||||
1252 | /* | |||||
1253 | ** now look for the right ccb. | |||||
1254 | ** | |||||
1255 | ** JUMP | |||||
1256 | ** @(first ccb of this lun) | |||||
1257 | */ | |||||
1258 | ||||||
1259 | struct link jump_ccb; | |||||
1260 | ||||||
1261 | /* | |||||
1262 | ** start of the ccb chain | |||||
1263 | */ | |||||
1264 | ||||||
1265 | ccb_p next_ccb; | |||||
1266 | ||||||
1267 | /* | |||||
1268 | ** Control of tagged queueing | |||||
1269 | */ | |||||
1270 | ||||||
1271 | u_charunsigned char reqccbs; | |||||
1272 | u_charunsigned char actccbs; | |||||
1273 | u_charunsigned char reqlink; | |||||
1274 | u_charunsigned char actlink; | |||||
1275 | u_charunsigned char usetags; | |||||
1276 | u_charunsigned char lasttag; | |||||
1277 | ||||||
1278 | /* | |||||
1279 | ** Linux specific fields: | |||||
1280 | ** Number of active commands and current credit. | |||||
1281 | ** Should be managed by the generic scsi driver | |||||
1282 | */ | |||||
1283 | ||||||
1284 | u_charunsigned char active; | |||||
1285 | u_charunsigned char opennings; | |||||
1286 | ||||||
1287 | /*----------------------------------------------- | |||||
1288 | ** Flag to force M_ORDERED_TAG on next command | |||||
1289 | ** in order to avoid spurious timeout when | |||||
1290 | ** M_SIMPLE_TAG is used for all operations. | |||||
1291 | **----------------------------------------------- | |||||
1292 | */ | |||||
1293 | u_charunsigned char force_ordered_tag; | |||||
1294 | #define NCR_TIMEOUT_INCREASE(5*100) (5*HZ100) | |||||
1295 | }; | |||||
1296 | ||||||
1297 | /*========================================================== | |||||
1298 | ** | |||||
1299 | ** Declaration of structs: COMMAND control block | |||||
1300 | ** | |||||
1301 | **========================================================== | |||||
1302 | ** | |||||
1303 | ** This substructure is copied from the ccb to a | |||||
1304 | ** global address after selection (or reselection) | |||||
1305 | ** and copied back before disconnect. | |||||
1306 | ** | |||||
1307 | ** These fields are accessible to the script processor. | |||||
1308 | ** | |||||
1309 | **---------------------------------------------------------- | |||||
1310 | */ | |||||
1311 | ||||||
1312 | struct head { | |||||
1313 | /* | |||||
1314 | ** Execution of a ccb starts at this point. | |||||
1315 | ** It's a jump to the "SELECT" label | |||||
1316 | ** of the script. | |||||
1317 | ** | |||||
1318 | ** After successful selection the script | |||||
1319 | ** processor overwrites it with a jump to | |||||
1320 | ** the IDLE label of the script. | |||||
1321 | */ | |||||
1322 | ||||||
1323 | struct link launch; | |||||
1324 | ||||||
1325 | /* | |||||
1326 | ** Saved data pointer. | |||||
1327 | ** Points to the position in the script | |||||
1328 | ** responsible for the actual transfer | |||||
1329 | ** of data. | |||||
1330 | ** It's written after reception of a | |||||
1331 | ** "SAVE_DATA_POINTER" message. | |||||
1332 | ** The goalpointer points after | |||||
1333 | ** the last transfer command. | |||||
1334 | */ | |||||
1335 | ||||||
1336 | u_int32 savep; | |||||
1337 | u_int32 lastp; | |||||
1338 | u_int32 goalp; | |||||
1339 | ||||||
1340 | /* | |||||
1341 | ** The virtual address of the ccb | |||||
1342 | ** containing this header. | |||||
1343 | */ | |||||
1344 | ||||||
1345 | ccb_p cp; | |||||
1346 | ||||||
1347 | /* | |||||
1348 | ** space for some timestamps to gather | |||||
1349 | ** profiling data about devices and this driver. | |||||
1350 | */ | |||||
1351 | ||||||
1352 | struct tstamp stamp; | |||||
1353 | ||||||
1354 | /* | |||||
1355 | ** status fields. | |||||
1356 | */ | |||||
1357 | ||||||
1358 | u_charunsigned char scr_st[4]; /* script status */ | |||||
1359 | u_charunsigned char status[4]; /* host status. Must be the last */ | |||||
1360 | /* DWORD of the CCB header */ | |||||
1361 | }; | |||||
1362 | ||||||
1363 | /* | |||||
1364 | ** The status bytes are used by the host and the script processor. | |||||
1365 | ** | |||||
1366 | ** The byte corresponding to the host_status must be stored in the | |||||
1367 | ** last DWORD of the CCB header since it is used for command | |||||
1368 | ** completion (ncr_wakeup()). Doing so, we are sure that the header | |||||
1369 | ** has been entirely copied back to the CCB when the host_status is | |||||
1370 | ** seen complete by the CPU. | |||||
1371 | ** | |||||
1372 | ** The last four bytes (status[4]) are copied to the scratchb register | |||||
1373 | ** (declared as scr0..scr3 in ncr_reg.h) just after the select/reselect, | |||||
1374 | ** and copied back just after disconnecting. | |||||
1375 | ** Inside the script the XX_REG are used. | |||||
1376 | ** | |||||
1377 | ** The first four bytes (scr_st[4]) are used inside the script by | |||||
1378 | ** "COPY" commands. | |||||
1379 | ** Because source and destination must have the same alignment | |||||
1380 | ** in a DWORD, the fields HAVE to be at the choosen offsets. | |||||
1381 | ** xerr_st 0 (0x34) scratcha | |||||
1382 | ** sync_st 1 (0x05) sxfer | |||||
1383 | ** wide_st 3 (0x03) scntl3 | |||||
1384 | */ | |||||
1385 | ||||||
1386 | /* | |||||
1387 | ** Last four bytes (script) | |||||
1388 | */ | |||||
1389 | #define QU_REGscr0 scr0 | |||||
1390 | #define HS_REGscr1 scr1 | |||||
1391 | #define HS_PRTnc_scr1 nc_scr1 | |||||
1392 | #define SS_REGscr2 scr2 | |||||
1393 | #define PS_REGscr3 scr3 | |||||
1394 | ||||||
1395 | /* | |||||
1396 | ** Last four bytes (host) | |||||
1397 | */ | |||||
1398 | #define actualquirksphys.header.status[0] phys.header.status[0] | |||||
1399 | #define host_statusphys.header.status[1] phys.header.status[1] | |||||
1400 | #define scsi_statusphys.header.status[2] phys.header.status[2] | |||||
1401 | #define parity_statusphys.header.status[3] phys.header.status[3] | |||||
1402 | ||||||
1403 | /* | |||||
1404 | ** First four bytes (script) | |||||
1405 | */ | |||||
1406 | #define xerr_stheader.scr_st[0] header.scr_st[0] | |||||
1407 | #define sync_stheader.scr_st[1] header.scr_st[1] | |||||
1408 | #define nego_stheader.scr_st[2] header.scr_st[2] | |||||
1409 | #define wide_stheader.scr_st[3] header.scr_st[3] | |||||
1410 | ||||||
1411 | /* | |||||
1412 | ** First four bytes (host) | |||||
1413 | */ | |||||
1414 | #define xerr_statusphys.header.scr_st[0] phys.xerr_stheader.scr_st[0] | |||||
1415 | #define sync_statusphys.header.scr_st[1] phys.sync_stheader.scr_st[1] | |||||
1416 | #define nego_statusphys.header.scr_st[2] phys.nego_stheader.scr_st[2] | |||||
1417 | #define wide_statusphys.header.scr_st[3] phys.wide_stheader.scr_st[3] | |||||
1418 | ||||||
1419 | /*========================================================== | |||||
1420 | ** | |||||
1421 | ** Declaration of structs: Data structure block | |||||
1422 | ** | |||||
1423 | **========================================================== | |||||
1424 | ** | |||||
1425 | ** During execution of a ccb by the script processor, | |||||
1426 | ** the DSA (data structure address) register points | |||||
1427 | ** to this substructure of the ccb. | |||||
1428 | ** This substructure contains the header with | |||||
1429 | ** the script-processor-changable data and | |||||
1430 | ** data blocks for the indirect move commands. | |||||
1431 | ** | |||||
1432 | **---------------------------------------------------------- | |||||
1433 | */ | |||||
1434 | ||||||
1435 | struct dsb { | |||||
1436 | ||||||
1437 | /* | |||||
1438 | ** Header. | |||||
1439 | ** Has to be the first entry, | |||||
1440 | ** because it's jumped to by the | |||||
1441 | ** script processor | |||||
1442 | */ | |||||
1443 | ||||||
1444 | struct head header; | |||||
1445 | ||||||
1446 | /* | |||||
1447 | ** Table data for Script | |||||
1448 | */ | |||||
1449 | ||||||
1450 | struct scr_tblsel select; | |||||
1451 | struct scr_tblmove smsg ; | |||||
1452 | struct scr_tblmove smsg2 ; | |||||
1453 | struct scr_tblmove cmd ; | |||||
1454 | struct scr_tblmove scmd ; | |||||
1455 | struct scr_tblmove sense ; | |||||
1456 | struct scr_tblmove data [MAX_SCATTER((127))]; | |||||
1457 | }; | |||||
1458 | ||||||
1459 | /*========================================================== | |||||
1460 | ** | |||||
1461 | ** Declaration of structs: Command control block. | |||||
1462 | ** | |||||
1463 | **========================================================== | |||||
1464 | ** | |||||
1465 | ** During execution of a ccb by the script processor, | |||||
1466 | ** the DSA (data structure address) register points | |||||
1467 | ** to this substructure of the ccb. | |||||
1468 | ** This substructure contains the header with | |||||
1469 | ** the script-processor-changable data and then | |||||
1470 | ** data blocks for the indirect move commands. | |||||
1471 | ** | |||||
1472 | **---------------------------------------------------------- | |||||
1473 | */ | |||||
1474 | ||||||
1475 | ||||||
1476 | struct ccb { | |||||
1477 | /* | |||||
1478 | ** This field forces 32 bytes alignement for phys.header, | |||||
1479 | ** in order to use cache line bursting when copying it | |||||
1480 | ** to the ncb. | |||||
1481 | */ | |||||
1482 | ||||||
1483 | struct link filler[2]; | |||||
1484 | ||||||
1485 | /* | |||||
1486 | ** during reselection the ncr jumps to this point. | |||||
1487 | ** If a "SIMPLE_TAG" message was received, | |||||
1488 | ** then SFBR is set to the tag. | |||||
1489 | ** else SFBR is set to 0 | |||||
1490 | ** If looking for another tag, jump to the next ccb. | |||||
1491 | ** | |||||
1492 | ** JUMP IF (SFBR != #TAG#) | |||||
1493 | ** @(next ccb of this lun) | |||||
1494 | */ | |||||
1495 | ||||||
1496 | struct link jump_ccb; | |||||
1497 | ||||||
1498 | /* | |||||
1499 | ** After execution of this call, the return address | |||||
1500 | ** (in the TEMP register) points to the following | |||||
1501 | ** data structure block. | |||||
1502 | ** So copy it to the DSA register, and start | |||||
1503 | ** processing of this data structure. | |||||
1504 | ** | |||||
1505 | ** CALL | |||||
1506 | ** <RESEL_TMP> | |||||
1507 | */ | |||||
1508 | ||||||
1509 | struct link call_tmp; | |||||
1510 | ||||||
1511 | /* | |||||
1512 | ** This is the data structure which is | |||||
1513 | ** to be executed by the script processor. | |||||
1514 | */ | |||||
1515 | ||||||
1516 | struct dsb phys; | |||||
1517 | ||||||
1518 | /* | |||||
1519 | ** If a data transfer phase is terminated too early | |||||
1520 | ** (after reception of a message (i.e. DISCONNECT)), | |||||
1521 | ** we have to prepare a mini script to transfer | |||||
1522 | ** the rest of the data. | |||||
1523 | */ | |||||
1524 | ||||||
1525 | ncrcmd patch[8]; | |||||
1526 | ||||||
1527 | /* | |||||
1528 | ** The general SCSI driver provides a | |||||
1529 | ** pointer to a control block. | |||||
1530 | */ | |||||
1531 | ||||||
1532 | Scsi_Cmnd *cmd; | |||||
1533 | int data_len; | |||||
1534 | ||||||
1535 | /* | |||||
1536 | ** We prepare a message to be sent after selection, | |||||
1537 | ** and a second one to be sent after getcc selection. | |||||
1538 | ** Contents are IDENTIFY and SIMPLE_TAG. | |||||
1539 | ** While negotiating sync or wide transfer, | |||||
1540 | ** a SDTM or WDTM message is appended. | |||||
1541 | */ | |||||
1542 | ||||||
1543 | u_charunsigned char scsi_smsg [8]; | |||||
1544 | u_charunsigned char scsi_smsg2[8]; | |||||
1545 | ||||||
1546 | /* | |||||
1547 | ** Lock this ccb. | |||||
1548 | ** Flag is used while looking for a free ccb. | |||||
1549 | */ | |||||
1550 | ||||||
1551 | u_longunsigned long magic; | |||||
1552 | ||||||
1553 | /* | |||||
1554 | ** Physical address of this instance of ccb | |||||
1555 | */ | |||||
1556 | ||||||
1557 | u_longunsigned long p_ccb; | |||||
1558 | ||||||
1559 | /* | |||||
1560 | ** Completion time out for this job. | |||||
1561 | ** It's set to time of start + allowed number of seconds. | |||||
1562 | */ | |||||
1563 | ||||||
1564 | u_longunsigned long tlimit; | |||||
1565 | ||||||
1566 | /* | |||||
1567 | ** All ccbs of one hostadapter are chained. | |||||
1568 | */ | |||||
1569 | ||||||
1570 | ccb_p link_ccb; | |||||
1571 | ||||||
1572 | /* | |||||
1573 | ** All ccbs of one target/lun are chained. | |||||
1574 | */ | |||||
1575 | ||||||
1576 | ccb_p next_ccb; | |||||
1577 | ||||||
1578 | /* | |||||
1579 | ** Sense command | |||||
1580 | */ | |||||
1581 | ||||||
1582 | u_charunsigned char sensecmd[6]; | |||||
1583 | ||||||
1584 | /* | |||||
1585 | ** Tag for this transfer. | |||||
1586 | ** It's patched into jump_ccb. | |||||
1587 | ** If it's not zero, a SIMPLE_TAG | |||||
1588 | ** message is included in smsg. | |||||
1589 | */ | |||||
1590 | ||||||
1591 | u_charunsigned char tag; | |||||
1592 | ||||||
1593 | /* | |||||
1594 | ** Number of segments of the scatter list. | |||||
1595 | ** Used for recalculation of savep/goalp/lastp on | |||||
1596 | ** SIR_DATA_IO_IS_OUT interrupt. | |||||
1597 | */ | |||||
1598 | ||||||
1599 | u_charunsigned char segments; | |||||
1600 | }; | |||||
1601 | ||||||
1602 | #define CCB_PHYS(cp,lbl)(cp->p_ccb + ((size_t) (&((struct ccb *)0)->lbl))) (cp->p_ccb + offsetof(struct ccb, lbl)((size_t) (&((struct ccb *)0)->lbl))) | |||||
1603 | ||||||
1604 | /*========================================================== | |||||
1605 | ** | |||||
1606 | ** Declaration of structs: NCR device descriptor | |||||
1607 | ** | |||||
1608 | **========================================================== | |||||
1609 | */ | |||||
1610 | ||||||
1611 | struct ncb { | |||||
1612 | /* | |||||
1613 | ** The global header. | |||||
1614 | ** Accessible to both the host and the | |||||
1615 | ** script-processor. | |||||
1616 | ** Is 32 bytes aligned since ncb is, in order to | |||||
1617 | ** allow cache line bursting when copying it from or | |||||
1618 | ** to ccbs. | |||||
1619 | */ | |||||
1620 | struct head header; | |||||
1621 | ||||||
1622 | /*----------------------------------------------- | |||||
1623 | ** Specific Linux fields | |||||
1624 | **----------------------------------------------- | |||||
1625 | */ | |||||
1626 | int unit; /* Unit number */ | |||||
1627 | char chip_name[8]; /* Chip name */ | |||||
1628 | char inst_name[16]; /* Instance name */ | |||||
1629 | struct timer_list timer; /* Timer link header */ | |||||
1630 | int ncr_cache; /* Cache test variable */ | |||||
1631 | Scsi_Cmnd *waiting_list; /* Waiting list header for commands */ | |||||
1632 | /* that we can't put into the squeue */ | |||||
1633 | u_longunsigned long settle_time; /* Reset in progess */ | |||||
1634 | u_charunsigned char release_stage; /* Synchronisation stage on release */ | |||||
1635 | u_charunsigned char verbose; /* Boot verbosity for this controller*/ | |||||
1636 | #ifdef SCSI_NCR_DEBUG_ERROR_RECOVERY_SUPPORT | |||||
1637 | u_charunsigned char debug_error_recovery; | |||||
1638 | u_charunsigned char stalling; | |||||
1639 | u_charunsigned char assert_atn; | |||||
1640 | #endif | |||||
1641 | ||||||
1642 | /*----------------------------------------------- | |||||
1643 | ** Added field to support differences | |||||
1644 | ** between ncr chips. | |||||
1645 | ** sv_xxx are some io register bit value at start-up and | |||||
1646 | ** so assumed to have been set by the sdms bios. | |||||
1647 | ** rv_xxx are the bit fields of io register that will keep | |||||
1648 | ** the features used by the driver. | |||||
1649 | **----------------------------------------------- | |||||
1650 | */ | |||||
1651 | u_shortunsigned short device_id; | |||||
1652 | u_charunsigned char revision_id; | |||||
1653 | ||||||
1654 | u_charunsigned char sv_scntl0; | |||||
1655 | u_charunsigned char sv_scntl3; | |||||
1656 | u_charunsigned char sv_dmode; | |||||
1657 | u_charunsigned char sv_dcntl; | |||||
1658 | u_charunsigned char sv_ctest3; | |||||
1659 | u_charunsigned char sv_ctest4; | |||||
1660 | u_charunsigned char sv_ctest5; | |||||
1661 | u_charunsigned char sv_gpcntl; | |||||
1662 | u_charunsigned char sv_stest2; | |||||
1663 | u_charunsigned char sv_stest4; | |||||
1664 | ||||||
1665 | u_charunsigned char rv_scntl0; | |||||
1666 | u_charunsigned char rv_scntl3; | |||||
1667 | u_charunsigned char rv_dmode; | |||||
1668 | u_charunsigned char rv_dcntl; | |||||
1669 | u_charunsigned char rv_ctest3; | |||||
1670 | u_charunsigned char rv_ctest4; | |||||
1671 | u_charunsigned char rv_ctest5; | |||||
1672 | u_charunsigned char rv_stest2; | |||||
1673 | ||||||
1674 | u_charunsigned char scsi_mode; | |||||
1675 | ||||||
1676 | /*----------------------------------------------- | |||||
1677 | ** Scripts .. | |||||
1678 | **----------------------------------------------- | |||||
1679 | ** | |||||
1680 | ** During reselection the ncr jumps to this point. | |||||
1681 | ** The SFBR register is loaded with the encoded target id. | |||||
1682 | ** | |||||
1683 | ** Jump to the first target. | |||||
1684 | ** | |||||
1685 | ** JUMP | |||||
1686 | ** @(next tcb) | |||||
1687 | */ | |||||
1688 | struct link jump_tcb; | |||||
1689 | ||||||
1690 | /*----------------------------------------------- | |||||
1691 | ** Configuration .. | |||||
1692 | **----------------------------------------------- | |||||
1693 | ** | |||||
1694 | ** virtual and physical addresses | |||||
1695 | ** of the 53c810 chip. | |||||
1696 | */ | |||||
1697 | vm_offset_t vaddr; | |||||
1698 | vm_offset_t paddr; | |||||
1699 | ||||||
1700 | vm_offset_t vaddr2; | |||||
1701 | vm_offset_t paddr2; | |||||
1702 | ||||||
1703 | /* | |||||
1704 | ** pointer to the chip's registers. | |||||
1705 | */ | |||||
1706 | volatile | |||||
1707 | struct ncr_reg* reg; | |||||
1708 | ||||||
1709 | /* | |||||
1710 | ** A copy of the scripts, relocated for this ncb. | |||||
1711 | */ | |||||
1712 | struct script *script0; | |||||
1713 | struct scripth *scripth0; | |||||
1714 | ||||||
1715 | /* | |||||
1716 | ** Scripts instance virtual address. | |||||
1717 | */ | |||||
1718 | struct script *script; | |||||
1719 | struct scripth *scripth; | |||||
1720 | ||||||
1721 | /* | |||||
1722 | ** Scripts instance physical address. | |||||
1723 | */ | |||||
1724 | u_longunsigned long p_script; | |||||
1725 | u_longunsigned long p_scripth; | |||||
1726 | ||||||
1727 | /* | |||||
1728 | ** The SCSI address of the host adapter. | |||||
1729 | */ | |||||
1730 | u_charunsigned char myaddr; | |||||
1731 | ||||||
1732 | /* | |||||
1733 | ** Max dwords burst supported by the adapter. | |||||
1734 | */ | |||||
1735 | u_charunsigned char maxburst; /* log base 2 of dwords burst */ | |||||
1736 | ||||||
1737 | /* | |||||
1738 | ** timing parameters | |||||
1739 | */ | |||||
1740 | u_charunsigned char minsync; /* Minimum sync period factor */ | |||||
1741 | u_charunsigned char maxsync; /* Maximum sync period factor */ | |||||
1742 | u_charunsigned char maxoffs; /* Max scsi offset */ | |||||
1743 | u_charunsigned char multiplier; /* Clock multiplier (1,2,4) */ | |||||
1744 | u_charunsigned char clock_divn; /* Number of clock divisors */ | |||||
1745 | u_longunsigned long clock_khz; /* SCSI clock frequency in KHz */ | |||||
1746 | u_intunsigned int features; /* Chip features map */ | |||||
1747 | ||||||
1748 | ||||||
1749 | /*----------------------------------------------- | |||||
1750 | ** Link to the generic SCSI driver | |||||
1751 | **----------------------------------------------- | |||||
1752 | */ | |||||
1753 | ||||||
1754 | /* struct scsi_link sc_link; */ | |||||
1755 | ||||||
1756 | /*----------------------------------------------- | |||||
1757 | ** Job control | |||||
1758 | **----------------------------------------------- | |||||
1759 | ** | |||||
1760 | ** Commands from user | |||||
1761 | */ | |||||
1762 | struct usrcmd user; | |||||
1763 | u_charunsigned char order; | |||||
1764 | ||||||
1765 | /* | |||||
1766 | ** Target data | |||||
1767 | */ | |||||
1768 | struct tcb target[MAX_TARGET((16))]; | |||||
1769 | ||||||
1770 | /* | |||||
1771 | ** Start queue. | |||||
1772 | */ | |||||
1773 | u_int32 squeue [MAX_START((7*(4)) + 4)]; | |||||
1774 | u_shortunsigned short squeueput; | |||||
1775 | u_shortunsigned short actccbs; | |||||
1776 | ||||||
1777 | /* | |||||
1778 | ** Timeout handler | |||||
1779 | */ | |||||
1780 | #if 0 | |||||
1781 | u_longunsigned long heartbeat; | |||||
1782 | u_shortunsigned short ticks; | |||||
1783 | u_shortunsigned short latetime; | |||||
1784 | #endif | |||||
1785 | u_longunsigned long lasttime; | |||||
1786 | ||||||
1787 | /*----------------------------------------------- | |||||
1788 | ** Debug and profiling | |||||
1789 | **----------------------------------------------- | |||||
1790 | ** | |||||
1791 | ** register dump | |||||
1792 | */ | |||||
1793 | struct ncr_reg regdump; | |||||
1794 | u_longunsigned long regtime; | |||||
1795 | ||||||
1796 | /* | |||||
1797 | ** Profiling data | |||||
1798 | */ | |||||
1799 | struct profile profile; | |||||
1800 | u_longunsigned long disc_phys; | |||||
1801 | u_longunsigned long disc_ref; | |||||
1802 | ||||||
1803 | /* | |||||
1804 | ** The global control block. | |||||
1805 | ** It's used only during the configuration phase. | |||||
1806 | ** A target control block will be created | |||||
1807 | ** after the first successful transfer. | |||||
1808 | */ | |||||
1809 | struct ccb *ccb; | |||||
1810 | ||||||
1811 | /* | |||||
1812 | ** message buffers. | |||||
1813 | ** Should be longword aligned, | |||||
1814 | ** because they're written with a | |||||
1815 | ** COPY script command. | |||||
1816 | */ | |||||
1817 | u_charunsigned char msgout[8]; | |||||
1818 | u_charunsigned char msgin [8]; | |||||
1819 | u_int32 lastmsg; | |||||
1820 | ||||||
1821 | /* | |||||
1822 | ** Buffer for STATUS_IN phase. | |||||
1823 | */ | |||||
1824 | u_charunsigned char scratch; | |||||
1825 | ||||||
1826 | /* | |||||
1827 | ** controller chip dependent maximal transfer width. | |||||
1828 | */ | |||||
1829 | u_charunsigned char maxwide; | |||||
1830 | ||||||
1831 | /* | |||||
1832 | ** option for M_IDENTIFY message: enables disconnecting | |||||
1833 | */ | |||||
1834 | u_charunsigned char disc; | |||||
1835 | ||||||
1836 | /* | |||||
1837 | ** address of the ncr control registers in io space | |||||
1838 | */ | |||||
1839 | u_intunsigned int port; | |||||
1840 | ||||||
1841 | /* | |||||
1842 | ** irq level | |||||
1843 | */ | |||||
1844 | u_shortunsigned short irq; | |||||
1845 | }; | |||||
1846 | ||||||
1847 | #define NCB_SCRIPT_PHYS(np,lbl)(np->p_script + ((size_t) (&((struct script *)0)->lbl ))) (np->p_script + offsetof (struct script, lbl)((size_t) (&((struct script *)0)->lbl))) | |||||
1848 | #define NCB_SCRIPTH_PHYS(np,lbl)(np->p_scripth + ((size_t) (&((struct scripth *)0)-> lbl))) (np->p_scripth + offsetof (struct scripth, lbl)((size_t) (&((struct scripth *)0)->lbl))) | |||||
1849 | ||||||
1850 | /*========================================================== | |||||
1851 | ** | |||||
1852 | ** | |||||
1853 | ** Script for NCR-Processor. | |||||
1854 | ** | |||||
1855 | ** Use ncr_script_fill() to create the variable parts. | |||||
1856 | ** Use ncr_script_copy_and_bind() to make a copy and | |||||
1857 | ** bind to physical addresses. | |||||
1858 | ** | |||||
1859 | ** | |||||
1860 | **========================================================== | |||||
1861 | ** | |||||
1862 | ** We have to know the offsets of all labels before | |||||
1863 | ** we reach them (for forward jumps). | |||||
1864 | ** Therefore we declare a struct here. | |||||
1865 | ** If you make changes inside the script, | |||||
1866 | ** DON'T FORGET TO CHANGE THE LENGTHS HERE! | |||||
1867 | ** | |||||
1868 | **---------------------------------------------------------- | |||||
1869 | */ | |||||
1870 | ||||||
1871 | /* | |||||
1872 | ** Script fragments which are loaded into the on-board RAM | |||||
1873 | ** of 825A, 875 and 895 chips. | |||||
1874 | */ | |||||
1875 | struct script { | |||||
1876 | ncrcmd start [ 4]; | |||||
1877 | ncrcmd start0 [ 2]; | |||||
1878 | ncrcmd start1 [ 3]; | |||||
1879 | ncrcmd startpos [ 1]; | |||||
1880 | ncrcmd trysel [ 8]; | |||||
1881 | ncrcmd skip [ 8]; | |||||
1882 | ncrcmd skip2 [ 3]; | |||||
1883 | ncrcmd idle [ 2]; | |||||
1884 | ncrcmd select [ 22]; | |||||
1885 | ncrcmd prepare [ 4]; | |||||
1886 | ncrcmd loadpos [ 14]; | |||||
1887 | ncrcmd prepare2 [ 24]; | |||||
1888 | ncrcmd setmsg [ 5]; | |||||
1889 | ncrcmd clrack [ 2]; | |||||
1890 | ncrcmd dispatch [ 38]; | |||||
1891 | ncrcmd no_data [ 17]; | |||||
1892 | ncrcmd checkatn [ 10]; | |||||
1893 | ncrcmd command [ 15]; | |||||
1894 | ncrcmd status [ 27]; | |||||
1895 | ncrcmd msg_in [ 26]; | |||||
1896 | ncrcmd msg_bad [ 6]; | |||||
1897 | ncrcmd complete [ 13]; | |||||
1898 | ncrcmd cleanup [ 12]; | |||||
1899 | ncrcmd cleanup0 [ 11]; | |||||
1900 | ncrcmd signal [ 10]; | |||||
1901 | ncrcmd save_dp [ 5]; | |||||
1902 | ncrcmd restore_dp [ 5]; | |||||
1903 | ncrcmd disconnect [ 12]; | |||||
1904 | ncrcmd disconnect0 [ 5]; | |||||
1905 | ncrcmd disconnect1 [ 23]; | |||||
1906 | ncrcmd msg_out [ 9]; | |||||
1907 | ncrcmd msg_out_done [ 7]; | |||||
1908 | ncrcmd badgetcc [ 6]; | |||||
1909 | ncrcmd reselect [ 8]; | |||||
1910 | ncrcmd reselect1 [ 8]; | |||||
1911 | ncrcmd reselect2 [ 8]; | |||||
1912 | ncrcmd resel_tmp [ 5]; | |||||
1913 | ncrcmd resel_lun [ 18]; | |||||
1914 | ncrcmd resel_tag [ 24]; | |||||
1915 | ncrcmd data_io [ 6]; | |||||
1916 | ncrcmd data_in [MAX_SCATTER((127)) * 4 + 4]; | |||||
1917 | }; | |||||
1918 | ||||||
1919 | /* | |||||
1920 | ** Script fragments which stay in main memory for all chips. | |||||
1921 | */ | |||||
1922 | struct scripth { | |||||
1923 | ncrcmd tryloop [MAX_START((7*(4)) + 4)*5+2]; | |||||
1924 | ncrcmd msg_parity [ 6]; | |||||
1925 | ncrcmd msg_reject [ 8]; | |||||
1926 | ncrcmd msg_ign_residue [ 32]; | |||||
1927 | ncrcmd msg_extended [ 18]; | |||||
1928 | ncrcmd msg_ext_2 [ 18]; | |||||
1929 | ncrcmd msg_wdtr [ 27]; | |||||
1930 | ncrcmd msg_ext_3 [ 18]; | |||||
1931 | ncrcmd msg_sdtr [ 27]; | |||||
1932 | ncrcmd msg_out_abort [ 10]; | |||||
1933 | ncrcmd getcc [ 4]; | |||||
1934 | ncrcmd getcc1 [ 5]; | |||||
1935 | #ifdef NCR_GETCC_WITHMSG | |||||
1936 | ncrcmd getcc2 [ 33]; | |||||
1937 | #else | |||||
1938 | ncrcmd getcc2 [ 14]; | |||||
1939 | #endif | |||||
1940 | ncrcmd getcc3 [ 10]; | |||||
1941 | ncrcmd data_out [MAX_SCATTER((127)) * 4 + 4]; | |||||
1942 | ncrcmd aborttag [ 4]; | |||||
1943 | ncrcmd abort [ 22]; | |||||
1944 | ncrcmd snooptest [ 9]; | |||||
1945 | ncrcmd snoopend [ 2]; | |||||
1946 | }; | |||||
1947 | ||||||
1948 | /*========================================================== | |||||
1949 | ** | |||||
1950 | ** | |||||
1951 | ** Function headers. | |||||
1952 | ** | |||||
1953 | ** | |||||
1954 | **========================================================== | |||||
1955 | */ | |||||
1956 | ||||||
1957 | static void ncr_alloc_ccb (ncb_p np, u_longunsigned long t, u_longunsigned long l); | |||||
1958 | static void ncr_complete (ncb_p np, ccb_p cp); | |||||
1959 | static void ncr_exception (ncb_p np); | |||||
1960 | static void ncr_free_ccb (ncb_p np, ccb_p cp, u_longunsigned long t, u_longunsigned long l); | |||||
1961 | static void ncr_getclock (ncb_p np, int mult); | |||||
1962 | static void ncr_selectclock (ncb_p np, u_charunsigned char scntl3); | |||||
1963 | static ccb_p ncr_get_ccb (ncb_p np, u_longunsigned long t,u_longunsigned long l); | |||||
1964 | static void ncr_init (ncb_p np, int reset, char * msg, u_longunsigned long code); | |||||
1965 | static int ncr_int_sbmc (ncb_p np); | |||||
1966 | static int ncr_int_par (ncb_p np); | |||||
1967 | static void ncr_int_ma (ncb_p np); | |||||
1968 | static void ncr_int_sir (ncb_p np); | |||||
1969 | static void ncr_int_sto (ncb_p np); | |||||
1970 | static u_longunsigned long ncr_lookup (char* id); | |||||
1971 | static void ncr_negotiate (struct ncb* np, struct tcb* tp); | |||||
1972 | static void ncr_opennings (ncb_p np, lcb_p lp, Scsi_Cmnd * xp); | |||||
1973 | ||||||
1974 | #ifdef SCSI_NCR_PROFILE_SUPPORT | |||||
1975 | static void ncb_profile (ncb_p np, ccb_p cp); | |||||
1976 | #endif | |||||
1977 | ||||||
1978 | static void ncr_script_copy_and_bind | |||||
1979 | (ncb_p np, ncrcmd *src, ncrcmd *dst, int len); | |||||
1980 | static void ncr_script_fill (struct script * scr, struct scripth * scripth); | |||||
1981 | static int ncr_scatter (ccb_p cp, Scsi_Cmnd *cmd); | |||||
1982 | static void ncr_setmaxtags (ncb_p np, tcb_p tp, u_longunsigned long numtags); | |||||
1983 | static void ncr_getsync (ncb_p np, u_charunsigned char sfac, u_charunsigned char *fakp, u_charunsigned char *scntl3p); | |||||
1984 | static void ncr_setsync (ncb_p np, ccb_p cp, u_charunsigned char scntl3, u_charunsigned char sxfer); | |||||
1985 | static void ncr_settags (tcb_p tp, lcb_p lp); | |||||
1986 | static void ncr_setwide (ncb_p np, ccb_p cp, u_charunsigned char wide, u_charunsigned char ack); | |||||
1987 | static int ncr_show_msg (u_charunsigned char * msg); | |||||
1988 | static int ncr_snooptest (ncb_p np); | |||||
1989 | static void ncr_timeout (ncb_p np); | |||||
1990 | static void ncr_wakeup (ncb_p np, u_longunsigned long code); | |||||
1991 | static void ncr_start_reset (ncb_p np, int settle_delay); | |||||
1992 | static int ncr_reset_scsi_bus (ncb_p np, int enab_int, int settle_delay); | |||||
1993 | ||||||
1994 | #ifdef SCSI_NCR_USER_COMMAND_SUPPORT | |||||
1995 | static void ncr_usercmd (ncb_p np); | |||||
1996 | #endif | |||||
1997 | ||||||
1998 | static int ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device); | |||||
1999 | ||||||
2000 | static void insert_into_waiting_list(ncb_p np, Scsi_Cmnd *cmd); | |||||
2001 | static Scsi_Cmnd *retrieve_from_waiting_list(int to_remove, ncb_p np, Scsi_Cmnd *cmd); | |||||
2002 | static void process_waiting_list(ncb_p np, int sts); | |||||
2003 | ||||||
2004 | #define remove_from_waiting_list(np, cmd)retrieve_from_waiting_list(1, (np), (cmd)) \ | |||||
2005 | retrieve_from_waiting_list(1, (np), (cmd)) | |||||
2006 | #define requeue_waiting_list(np)process_waiting_list((np), 0x00) process_waiting_list((np), DID_OK0x00) | |||||
2007 | #define reset_waiting_list(np)process_waiting_list((np), 0x08) process_waiting_list((np), DID_RESET0x08) | |||||
2008 | ||||||
2009 | #ifdef SCSI_NCR_NVRAM_SUPPORT | |||||
2010 | static int ncr_get_Symbios_nvram (ncr_slot *np, Symbios_nvram *nvram); | |||||
2011 | static int ncr_get_Tekram_nvram (ncr_slot *np, Tekram_nvram *nvram); | |||||
2012 | #endif | |||||
2013 | ||||||
2014 | /*========================================================== | |||||
2015 | ** | |||||
2016 | ** | |||||
2017 | ** Global static data. | |||||
2018 | ** | |||||
2019 | ** | |||||
2020 | **========================================================== | |||||
2021 | */ | |||||
2022 | ||||||
2023 | #ifdef SCSI_NCR_DEBUG_INFO_SUPPORT | |||||
2024 | static int ncr_debug = SCSI_NCR_DEBUG_FLAGS(0); | |||||
2025 | #endif | |||||
2026 | ||||||
2027 | static inlineinline __attribute__((always_inline)) char *ncr_name (ncb_p np) | |||||
2028 | { | |||||
2029 | return np->inst_name; | |||||
2030 | } | |||||
2031 | ||||||
2032 | ||||||
2033 | /*========================================================== | |||||
2034 | ** | |||||
2035 | ** | |||||
2036 | ** Scripts for NCR-Processor. | |||||
2037 | ** | |||||
2038 | ** Use ncr_script_bind for binding to physical addresses. | |||||
2039 | ** | |||||
2040 | ** | |||||
2041 | **========================================================== | |||||
2042 | ** | |||||
2043 | ** NADDR generates a reference to a field of the controller data. | |||||
2044 | ** PADDR generates a reference to another part of the script. | |||||
2045 | ** RADDR generates a reference to a script processor register. | |||||
2046 | ** FADDR generates a reference to a script processor register | |||||
2047 | ** with offset. | |||||
2048 | ** | |||||
2049 | **---------------------------------------------------------- | |||||
2050 | */ | |||||
2051 | ||||||
2052 | #define RELOC_SOFTC0x40000000 0x40000000 | |||||
2053 | #define RELOC_LABEL0x50000000 0x50000000 | |||||
2054 | #define RELOC_REGISTER0x60000000 0x60000000 | |||||
2055 | #define RELOC_KVAR0x70000000 0x70000000 | |||||
2056 | #define RELOC_LABELH0x80000000 0x80000000 | |||||
2057 | #define RELOC_MASK0xf0000000 0xf0000000 | |||||
2058 | ||||||
2059 | #define NADDR(label)(0x40000000 | ((size_t) (&((struct ncb *)0)->label))) (RELOC_SOFTC0x40000000 | offsetof(struct ncb, label)((size_t) (&((struct ncb *)0)->label))) | |||||
2060 | #define PADDR(label)(0x50000000 | ((size_t) (&((struct script *)0)->label) )) (RELOC_LABEL0x50000000 | offsetof(struct script, label)((size_t) (&((struct script *)0)->label))) | |||||
2061 | #define PADDRH(label)(0x80000000 | ((size_t) (&((struct scripth *)0)->label ))) (RELOC_LABELH0x80000000 | offsetof(struct scripth, label)((size_t) (&((struct scripth *)0)->label))) | |||||
2062 | #define RADDR(label)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_label )))) (RELOC_REGISTER0x60000000 | REG(label)(((size_t) (&((struct ncr_reg *)0)->nc_label)))) | |||||
2063 | #define FADDR(label,ofs)(0x60000000 | (((((size_t) (&((struct ncr_reg *)0)->nc_label ))))+(ofs)))(RELOC_REGISTER0x60000000 | ((REG(label)(((size_t) (&((struct ncr_reg *)0)->nc_label))))+(ofs))) | |||||
2064 | #define KVAR(which)(0x70000000 | (which)) (RELOC_KVAR0x70000000 | (which)) | |||||
2065 | ||||||
2066 | #define SCRIPT_KVAR_JIFFIES(0) (0) | |||||
2067 | ||||||
2068 | #define SCRIPT_KVAR_FIRST(0) SCRIPT_KVAR_JIFFIES(0) | |||||
2069 | #define SCRIPT_KVAR_LAST(0) SCRIPT_KVAR_JIFFIES(0) | |||||
2070 | ||||||
2071 | /* | |||||
2072 | * Kernel variables referenced in the scripts. | |||||
2073 | * THESE MUST ALL BE ALIGNED TO A 4-BYTE BOUNDARY. | |||||
2074 | */ | |||||
2075 | static void *script_kvars[] __initdata = | |||||
2076 | { (void *)&jiffies }; | |||||
2077 | ||||||
2078 | static struct script script0 __initdata = { | |||||
2079 | /*--------------------------< START >-----------------------*/ { | |||||
2080 | #if 0 | |||||
2081 | /* | |||||
2082 | ** Claim to be still alive ... | |||||
2083 | */ | |||||
2084 | SCR_COPY (sizeof (((struct ncb *)0)->heartbeat))(0xc0000000 | 0x01000000 | (sizeof (((struct ncb *)0)->heartbeat ))), | |||||
2085 | KVAR(SCRIPT_KVAR_JIFFIES)(0x70000000 | ((0))), | |||||
2086 | NADDR (heartbeat)(0x40000000 | ((size_t) (&((struct ncb *)0)->heartbeat ))), | |||||
2087 | #endif | |||||
2088 | /* | |||||
2089 | ** Make data structure address invalid. | |||||
2090 | ** clear SIGP. | |||||
2091 | */ | |||||
2092 | SCR_LOAD_REG (dsa, 0xff)(0x78000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_dsa )))) << 16ul)) | (0x00000000) | ((0xff)<<8ul)), | |||||
2093 | 0, | |||||
2094 | SCR_FROM_REG (ctest2)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_ctest2 )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
2095 | 0, | |||||
2096 | }/*-------------------------< START0 >----------------------*/,{ | |||||
2097 | /* | |||||
2098 | ** Hook for interrupted GetConditionCode. | |||||
2099 | ** Will be patched to ... IFTRUE by | |||||
2100 | ** the interrupt handler. | |||||
2101 | */ | |||||
2102 | SCR_INT0x98080000 ^ IFFALSE (0)(0x00080000 | (0)), | |||||
2103 | SIR_SENSE_RESTART(1), | |||||
2104 | ||||||
2105 | }/*-------------------------< START1 >----------------------*/,{ | |||||
2106 | /* | |||||
2107 | ** Hook for stalled start queue. | |||||
2108 | ** Will be patched to IFTRUE by the interrupt handler. | |||||
2109 | */ | |||||
2110 | SCR_INT0x98080000 ^ IFFALSE (0)(0x00080000 | (0)), | |||||
2111 | SIR_STALL_RESTART(3), | |||||
2112 | /* | |||||
2113 | ** Then jump to a certain point in tryloop. | |||||
2114 | ** Due to the lack of indirect addressing the code | |||||
2115 | ** is self modifying here. | |||||
2116 | */ | |||||
2117 | SCR_JUMP0x80080000, | |||||
2118 | }/*-------------------------< STARTPOS >--------------------*/,{ | |||||
2119 | PADDRH(tryloop)(0x80000000 | ((size_t) (&((struct scripth *)0)->tryloop ))), | |||||
2120 | }/*-------------------------< TRYSEL >----------------------*/,{ | |||||
2121 | /* | |||||
2122 | ** Now: | |||||
2123 | ** DSA: Address of a Data Structure | |||||
2124 | ** or Address of the IDLE-Label. | |||||
2125 | ** | |||||
2126 | ** TEMP: Address of a script, which tries to | |||||
2127 | ** start the NEXT entry. | |||||
2128 | ** | |||||
2129 | ** Save the TEMP register into the SCRATCHA register. | |||||
2130 | ** Then copy the DSA to TEMP and RETURN. | |||||
2131 | ** This is kind of an indirect jump. | |||||
2132 | ** (The script processor has NO stack, so the | |||||
2133 | ** CALL is actually a jump and link, and the | |||||
2134 | ** RETURN is an indirect jump.) | |||||
2135 | ** | |||||
2136 | ** If the slot was empty, DSA contains the address | |||||
2137 | ** of the IDLE part of this script. The processor | |||||
2138 | ** jumps to IDLE and waits for a reselect. | |||||
2139 | ** It will wake up and try the same slot again | |||||
2140 | ** after the SIGP bit becomes set by the host. | |||||
2141 | ** | |||||
2142 | ** If the slot was not empty, DSA contains | |||||
2143 | ** the address of the phys-part of a ccb. | |||||
2144 | ** The processor jumps to this address. | |||||
2145 | ** phys starts with head, | |||||
2146 | ** head starts with launch, | |||||
2147 | ** so actually the processor jumps to | |||||
2148 | ** the lauch part. | |||||
2149 | ** If the entry is scheduled for execution, | |||||
2150 | ** then launch contains a jump to SELECT. | |||||
2151 | ** If it's not scheduled, it contains a jump to IDLE. | |||||
2152 | */ | |||||
2153 | SCR_COPY (4)(0xc0000000 | 0x01000000 | (4)), | |||||
2154 | RADDR (temp)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_temp )))), | |||||
2155 | RADDR (scratcha)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))), | |||||
2156 | SCR_COPY (4)(0xc0000000 | 0x01000000 | (4)), | |||||
2157 | RADDR (dsa)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_dsa )))), | |||||
2158 | RADDR (temp)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_temp )))), | |||||
2159 | SCR_RETURN0x90080000, | |||||
2160 | 0 | |||||
2161 | ||||||
2162 | }/*-------------------------< SKIP >------------------------*/,{ | |||||
2163 | /* | |||||
2164 | ** This entry has been canceled. | |||||
2165 | ** Next time use the next slot. | |||||
2166 | */ | |||||
2167 | SCR_COPY (4)(0xc0000000 | 0x01000000 | (4)), | |||||
2168 | RADDR (scratcha)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))), | |||||
2169 | PADDR (startpos)(0x50000000 | ((size_t) (&((struct script *)0)->startpos ))), | |||||
2170 | /* | |||||
2171 | ** patch the launch field. | |||||
2172 | ** should look like an idle process. | |||||
2173 | */ | |||||
2174 | SCR_COPY_F (4)(0xc0000000 | (4)), | |||||
2175 | RADDR (dsa)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_dsa )))), | |||||
2176 | PADDR (skip2)(0x50000000 | ((size_t) (&((struct script *)0)->skip2) )), | |||||
2177 | SCR_COPY (8)(0xc0000000 | 0x01000000 | (8)), | |||||
2178 | PADDR (idle)(0x50000000 | ((size_t) (&((struct script *)0)->idle)) ), | |||||
2179 | }/*-------------------------< SKIP2 >-----------------------*/,{ | |||||
2180 | 0, | |||||
2181 | SCR_JUMP0x80080000, | |||||
2182 | PADDR(start)(0x50000000 | ((size_t) (&((struct script *)0)->start) )), | |||||
2183 | }/*-------------------------< IDLE >------------------------*/,{ | |||||
2184 | /* | |||||
2185 | ** Nothing to do? | |||||
2186 | ** Wait for reselect. | |||||
2187 | */ | |||||
2188 | SCR_JUMP0x80080000, | |||||
2189 | PADDR(reselect)(0x50000000 | ((size_t) (&((struct script *)0)->reselect ))), | |||||
2190 | ||||||
2191 | }/*-------------------------< SELECT >----------------------*/,{ | |||||
2192 | /* | |||||
2193 | ** DSA contains the address of a scheduled | |||||
2194 | ** data structure. | |||||
2195 | ** | |||||
2196 | ** SCRATCHA contains the address of the script, | |||||
2197 | ** which starts the next entry. | |||||
2198 | ** | |||||
2199 | ** Set Initiator mode. | |||||
2200 | ** | |||||
2201 | ** (Target mode is left as an exercise for the reader) | |||||
2202 | */ | |||||
2203 | ||||||
2204 | SCR_CLR (SCR_TRG)(0x60000000 | (0x00000200)), | |||||
2205 | 0, | |||||
2206 | SCR_LOAD_REG (HS_REG, 0xff)(0x78000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scr1 )))) << 16ul)) | (0x00000000) | ((0xff)<<8ul)), | |||||
2207 | 0, | |||||
2208 | ||||||
2209 | /* | |||||
2210 | ** And try to select this target. | |||||
2211 | */ | |||||
2212 | SCR_SEL_TBL_ATN0x43000000 ^ offsetof (struct dsb, select)((size_t) (&((struct dsb *)0)->select)), | |||||
2213 | PADDR (reselect)(0x50000000 | ((size_t) (&((struct script *)0)->reselect ))), | |||||
2214 | ||||||
2215 | /* | |||||
2216 | ** Now there are 4 possibilities: | |||||
2217 | ** | |||||
2218 | ** (1) The ncr looses arbitration. | |||||
2219 | ** This is ok, because it will try again, | |||||
2220 | ** when the bus becomes idle. | |||||
2221 | ** (But beware of the timeout function!) | |||||
2222 | ** | |||||
2223 | ** (2) The ncr is reselected. | |||||
2224 | ** Then the script processor takes the jump | |||||
2225 | ** to the RESELECT label. | |||||
2226 | ** | |||||
2227 | ** (3) The ncr completes the selection. | |||||
2228 | ** Then it will execute the next statement. | |||||
2229 | ** | |||||
2230 | ** (4) There is a selection timeout. | |||||
2231 | ** Then the ncr should interrupt the host and stop. | |||||
2232 | ** Unfortunately, it seems to continue execution | |||||
2233 | ** of the script. But it will fail with an | |||||
2234 | ** IID-interrupt on the next WHEN. | |||||
2235 | */ | |||||
2236 | ||||||
2237 | SCR_JUMPR0x80880000 ^ IFTRUE (WHEN (SCR_MSG_IN))(0x00000000 | ((0x00030000 | (0x07000000)))), | |||||
2238 | 0, | |||||
2239 | ||||||
2240 | /* | |||||
2241 | ** Save target id to ctest0 register | |||||
2242 | */ | |||||
2243 | ||||||
2244 | SCR_FROM_REG (sdid)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_sdid )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
2245 | 0, | |||||
2246 | SCR_TO_REG (ctest0)(0x68000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_ctest0 )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
2247 | 0, | |||||
2248 | /* | |||||
2249 | ** Send the IDENTIFY and SIMPLE_TAG messages | |||||
2250 | ** (and the M_X_SYNC_REQ message) | |||||
2251 | */ | |||||
2252 | SCR_MOVE_TBL(0x18000000 ^ (0 << 1ul)) ^ SCR_MSG_OUT0x06000000, | |||||
2253 | offsetof (struct dsb, smsg)((size_t) (&((struct dsb *)0)->smsg)), | |||||
2254 | #ifdef undef /* XXX better fail than try to deal with this ... */ | |||||
2255 | SCR_JUMPR0x80880000 ^ IFTRUE (WHEN (SCR_MSG_OUT))(0x00000000 | ((0x00030000 | (0x06000000)))), | |||||
2256 | -16, | |||||
2257 | #endif | |||||
2258 | SCR_CLR (SCR_ATN)(0x60000000 | (0x00000008)), | |||||
2259 | 0, | |||||
2260 | SCR_COPY (1)(0xc0000000 | 0x01000000 | (1)), | |||||
2261 | RADDR (sfbr)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_sfbr )))), | |||||
2262 | NADDR (lastmsg)(0x40000000 | ((size_t) (&((struct ncb *)0)->lastmsg)) ), | |||||
2263 | /* | |||||
2264 | ** Selection complete. | |||||
2265 | ** Next time use the next slot. | |||||
2266 | */ | |||||
2267 | SCR_COPY (4)(0xc0000000 | 0x01000000 | (4)), | |||||
2268 | RADDR (scratcha)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))), | |||||
2269 | PADDR (startpos)(0x50000000 | ((size_t) (&((struct script *)0)->startpos ))), | |||||
2270 | }/*-------------------------< PREPARE >----------------------*/,{ | |||||
2271 | /* | |||||
2272 | ** The ncr doesn't have an indirect load | |||||
2273 | ** or store command. So we have to | |||||
2274 | ** copy part of the control block to a | |||||
2275 | ** fixed place, where we can access it. | |||||
2276 | ** | |||||
2277 | ** We patch the address part of a | |||||
2278 | ** COPY command with the DSA-register. | |||||
2279 | */ | |||||
2280 | SCR_COPY_F (4)(0xc0000000 | (4)), | |||||
2281 | RADDR (dsa)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_dsa )))), | |||||
2282 | PADDR (loadpos)(0x50000000 | ((size_t) (&((struct script *)0)->loadpos ))), | |||||
2283 | /* | |||||
2284 | ** then we do the actual copy. | |||||
2285 | */ | |||||
2286 | SCR_COPY (sizeof (struct head))(0xc0000000 | 0x01000000 | (sizeof (struct head))), | |||||
2287 | /* | |||||
2288 | ** continued after the next label ... | |||||
2289 | */ | |||||
2290 | ||||||
2291 | }/*-------------------------< LOADPOS >---------------------*/,{ | |||||
2292 | 0, | |||||
2293 | NADDR (header)(0x40000000 | ((size_t) (&((struct ncb *)0)->header))), | |||||
2294 | /* | |||||
2295 | ** Mark this ccb as not scheduled. | |||||
2296 | */ | |||||
2297 | SCR_COPY (8)(0xc0000000 | 0x01000000 | (8)), | |||||
2298 | PADDR (idle)(0x50000000 | ((size_t) (&((struct script *)0)->idle)) ), | |||||
2299 | NADDR (header.launch)(0x40000000 | ((size_t) (&((struct ncb *)0)->header.launch ))), | |||||
2300 | /* | |||||
2301 | ** Set a time stamp for this selection | |||||
2302 | */ | |||||
2303 | SCR_COPY (sizeof (u_long))(0xc0000000 | 0x01000000 | (sizeof (unsigned long))), | |||||
2304 | KVAR(SCRIPT_KVAR_JIFFIES)(0x70000000 | ((0))), | |||||
2305 | NADDR (header.stamp.select)(0x40000000 | ((size_t) (&((struct ncb *)0)->header.stamp .select))), | |||||
2306 | /* | |||||
2307 | ** load the savep (saved pointer) into | |||||
2308 | ** the TEMP register (actual pointer) | |||||
2309 | */ | |||||
2310 | SCR_COPY (4)(0xc0000000 | 0x01000000 | (4)), | |||||
2311 | NADDR (header.savep)(0x40000000 | ((size_t) (&((struct ncb *)0)->header.savep ))), | |||||
2312 | RADDR (temp)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_temp )))), | |||||
2313 | /* | |||||
2314 | ** Initialize the status registers | |||||
2315 | */ | |||||
2316 | SCR_COPY (4)(0xc0000000 | 0x01000000 | (4)), | |||||
2317 | NADDR (header.status)(0x40000000 | ((size_t) (&((struct ncb *)0)->header.status ))), | |||||
2318 | RADDR (scr0)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_scr0 )))), | |||||
2319 | ||||||
2320 | }/*-------------------------< PREPARE2 >---------------------*/,{ | |||||
2321 | /* | |||||
2322 | ** Load the synchronous mode register | |||||
2323 | */ | |||||
2324 | SCR_COPY (1)(0xc0000000 | 0x01000000 | (1)), | |||||
2325 | NADDR (sync_st)(0x40000000 | ((size_t) (&((struct ncb *)0)->header.scr_st [1]))), | |||||
2326 | RADDR (sxfer)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_sxfer )))), | |||||
2327 | /* | |||||
2328 | ** Load the wide mode and timing register | |||||
2329 | */ | |||||
2330 | SCR_COPY (1)(0xc0000000 | 0x01000000 | (1)), | |||||
2331 | NADDR (wide_st)(0x40000000 | ((size_t) (&((struct ncb *)0)->header.scr_st [3]))), | |||||
2332 | RADDR (scntl3)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_scntl3 )))), | |||||
2333 | /* | |||||
2334 | ** Initialize the msgout buffer with a NOOP message. | |||||
2335 | */ | |||||
2336 | SCR_LOAD_REG (scratcha, M_NOOP)(0x78000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))) << 16ul)) | (0x00000000) | (((0x08))<<8ul)), | |||||
2337 | 0, | |||||
2338 | SCR_COPY (1)(0xc0000000 | 0x01000000 | (1)), | |||||
2339 | RADDR (scratcha)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))), | |||||
2340 | NADDR (msgout)(0x40000000 | ((size_t) (&((struct ncb *)0)->msgout))), | |||||
2341 | SCR_COPY (1)(0xc0000000 | 0x01000000 | (1)), | |||||
2342 | RADDR (scratcha)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))), | |||||
2343 | NADDR (msgin)(0x40000000 | ((size_t) (&((struct ncb *)0)->msgin))), | |||||
2344 | /* | |||||
2345 | ** Message in phase ? | |||||
2346 | */ | |||||
2347 | SCR_JUMP0x80080000 ^ IFFALSE (WHEN (SCR_MSG_IN))(0x00080000 | ((0x00030000 | (0x07000000)))), | |||||
2348 | PADDR (dispatch)(0x50000000 | ((size_t) (&((struct script *)0)->dispatch ))), | |||||
2349 | /* | |||||
2350 | ** Extended or reject message ? | |||||
2351 | */ | |||||
2352 | SCR_FROM_REG (sbdl)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_sbdl )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
2353 | 0, | |||||
2354 | SCR_JUMP0x80080000 ^ IFTRUE (DATA (M_EXTENDED))(0x00000000 | ((0x00040000 | (((0x01)) & 0xff)))), | |||||
2355 | PADDR (msg_in)(0x50000000 | ((size_t) (&((struct script *)0)->msg_in ))), | |||||
2356 | SCR_JUMP0x80080000 ^ IFTRUE (DATA (M_REJECT))(0x00000000 | ((0x00040000 | (((0x07)) & 0xff)))), | |||||
2357 | PADDRH (msg_reject)(0x80000000 | ((size_t) (&((struct scripth *)0)->msg_reject ))), | |||||
2358 | /* | |||||
2359 | ** normal processing | |||||
2360 | */ | |||||
2361 | SCR_JUMP0x80080000, | |||||
2362 | PADDR (dispatch)(0x50000000 | ((size_t) (&((struct script *)0)->dispatch ))), | |||||
2363 | }/*-------------------------< SETMSG >----------------------*/,{ | |||||
2364 | SCR_COPY (1)(0xc0000000 | 0x01000000 | (1)), | |||||
2365 | RADDR (scratcha)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))), | |||||
2366 | NADDR (msgout)(0x40000000 | ((size_t) (&((struct ncb *)0)->msgout))), | |||||
2367 | SCR_SET (SCR_ATN)(0x58000000 | (0x00000008)), | |||||
2368 | 0, | |||||
2369 | }/*-------------------------< CLRACK >----------------------*/,{ | |||||
2370 | /* | |||||
2371 | ** Terminate possible pending message phase. | |||||
2372 | */ | |||||
2373 | SCR_CLR (SCR_ACK)(0x60000000 | (0x00000040)), | |||||
2374 | 0, | |||||
2375 | ||||||
2376 | }/*-----------------------< DISPATCH >----------------------*/,{ | |||||
2377 | SCR_FROM_REG (HS_REG)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scr1 )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
2378 | 0, | |||||
2379 | SCR_INT0x98080000 ^ IFTRUE (DATA (HS_NEGOTIATE))(0x00000000 | ((0x00040000 | (((2)) & 0xff)))), | |||||
2380 | SIR_NEGO_FAILED(7), | |||||
2381 | /* | |||||
2382 | ** remove bogus output signals | |||||
2383 | */ | |||||
2384 | SCR_REG_REG (socl, SCR_AND, CACK|CATN)(0x78000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_socl )))) << 16ul)) | (0x04000000) | ((0x40|0x08)<<8ul )), | |||||
2385 | 0, | |||||
2386 | SCR_RETURN0x90080000 ^ IFTRUE (WHEN (SCR_DATA_OUT))(0x00000000 | ((0x00030000 | (0x00000000)))), | |||||
2387 | 0, | |||||
2388 | /* | |||||
2389 | ** DEL 397 - 53C875 Rev 3 - Part Number 609-0392410 - ITEM 4. | |||||
2390 | ** Possible data corruption during Memory Write and Invalidate. | |||||
2391 | ** This work-around resets the addressing logic prior to the | |||||
2392 | ** start of the first MOVE of a DATA IN phase. | |||||
2393 | ** (See README.ncr53c8xx for more information) | |||||
2394 | */ | |||||
2395 | SCR_JUMPR0x80880000 ^ IFFALSE (IF (SCR_DATA_IN))(0x00080000 | ((0x00020000 | (0x01000000)))), | |||||
2396 | 20, | |||||
2397 | SCR_COPY (4)(0xc0000000 | 0x01000000 | (4)), | |||||
2398 | RADDR (scratcha)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))), | |||||
2399 | RADDR (scratcha)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))), | |||||
2400 | SCR_RETURN0x90080000, | |||||
2401 | 0, | |||||
2402 | ||||||
2403 | SCR_JUMP0x80080000 ^ IFTRUE (IF (SCR_MSG_OUT))(0x00000000 | ((0x00020000 | (0x06000000)))), | |||||
2404 | PADDR (msg_out)(0x50000000 | ((size_t) (&((struct script *)0)->msg_out ))), | |||||
2405 | SCR_JUMP0x80080000 ^ IFTRUE (IF (SCR_MSG_IN))(0x00000000 | ((0x00020000 | (0x07000000)))), | |||||
2406 | PADDR (msg_in)(0x50000000 | ((size_t) (&((struct script *)0)->msg_in ))), | |||||
2407 | SCR_JUMP0x80080000 ^ IFTRUE (IF (SCR_COMMAND))(0x00000000 | ((0x00020000 | (0x02000000)))), | |||||
2408 | PADDR (command)(0x50000000 | ((size_t) (&((struct script *)0)->command ))), | |||||
2409 | SCR_JUMP0x80080000 ^ IFTRUE (IF (SCR_STATUS))(0x00000000 | ((0x00020000 | (0x03000000)))), | |||||
2410 | PADDR (status)(0x50000000 | ((size_t) (&((struct script *)0)->status ))), | |||||
2411 | /* | |||||
2412 | ** Discard one illegal phase byte, if required. | |||||
2413 | */ | |||||
2414 | SCR_LOAD_REG (scratcha, XE_BAD_PHASE)(0x78000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))) << 16ul)) | (0x00000000) | (((2))<<8ul)), | |||||
2415 | 0, | |||||
2416 | SCR_COPY (1)(0xc0000000 | 0x01000000 | (1)), | |||||
2417 | RADDR (scratcha)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))), | |||||
2418 | NADDR (xerr_st)(0x40000000 | ((size_t) (&((struct ncb *)0)->header.scr_st [0]))), | |||||
2419 | SCR_JUMPR0x80880000 ^ IFFALSE (IF (SCR_ILG_OUT))(0x00080000 | ((0x00020000 | (0x04000000)))), | |||||
2420 | 8, | |||||
2421 | SCR_MOVE_ABS (1)((0x08000000 ^ (0 << 1ul)) | (1)) ^ SCR_ILG_OUT0x04000000, | |||||
2422 | NADDR (scratch)(0x40000000 | ((size_t) (&((struct ncb *)0)->scratch)) ), | |||||
2423 | SCR_JUMPR0x80880000 ^ IFFALSE (IF (SCR_ILG_IN))(0x00080000 | ((0x00020000 | (0x05000000)))), | |||||
2424 | 8, | |||||
2425 | SCR_MOVE_ABS (1)((0x08000000 ^ (0 << 1ul)) | (1)) ^ SCR_ILG_IN0x05000000, | |||||
2426 | NADDR (scratch)(0x40000000 | ((size_t) (&((struct ncb *)0)->scratch)) ), | |||||
2427 | SCR_JUMP0x80080000, | |||||
2428 | PADDR (dispatch)(0x50000000 | ((size_t) (&((struct script *)0)->dispatch ))), | |||||
2429 | ||||||
2430 | }/*-------------------------< NO_DATA >--------------------*/,{ | |||||
2431 | /* | |||||
2432 | ** The target wants to tranfer too much data | |||||
2433 | ** or in the wrong direction. | |||||
2434 | ** Remember that in extended error. | |||||
2435 | */ | |||||
2436 | SCR_LOAD_REG (scratcha, XE_EXTRA_DATA)(0x78000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))) << 16ul)) | (0x00000000) | (((1))<<8ul)), | |||||
2437 | 0, | |||||
2438 | SCR_COPY (1)(0xc0000000 | 0x01000000 | (1)), | |||||
2439 | RADDR (scratcha)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))), | |||||
2440 | NADDR (xerr_st)(0x40000000 | ((size_t) (&((struct ncb *)0)->header.scr_st [0]))), | |||||
2441 | /* | |||||
2442 | ** Discard one data byte, if required. | |||||
2443 | */ | |||||
2444 | SCR_JUMPR0x80880000 ^ IFFALSE (WHEN (SCR_DATA_OUT))(0x00080000 | ((0x00030000 | (0x00000000)))), | |||||
2445 | 8, | |||||
2446 | SCR_MOVE_ABS (1)((0x08000000 ^ (0 << 1ul)) | (1)) ^ SCR_DATA_OUT0x00000000, | |||||
2447 | NADDR (scratch)(0x40000000 | ((size_t) (&((struct ncb *)0)->scratch)) ), | |||||
2448 | SCR_JUMPR0x80880000 ^ IFFALSE (IF (SCR_DATA_IN))(0x00080000 | ((0x00020000 | (0x01000000)))), | |||||
2449 | 8, | |||||
2450 | SCR_MOVE_ABS (1)((0x08000000 ^ (0 << 1ul)) | (1)) ^ SCR_DATA_IN0x01000000, | |||||
2451 | NADDR (scratch)(0x40000000 | ((size_t) (&((struct ncb *)0)->scratch)) ), | |||||
2452 | /* | |||||
2453 | ** .. and repeat as required. | |||||
2454 | */ | |||||
2455 | SCR_CALL0x88080000, | |||||
2456 | PADDR (dispatch)(0x50000000 | ((size_t) (&((struct script *)0)->dispatch ))), | |||||
2457 | SCR_JUMP0x80080000, | |||||
2458 | PADDR (no_data)(0x50000000 | ((size_t) (&((struct script *)0)->no_data ))), | |||||
2459 | }/*-------------------------< CHECKATN >--------------------*/,{ | |||||
2460 | /* | |||||
2461 | ** If AAP (bit 1 of scntl0 register) is set | |||||
2462 | ** and a parity error is detected, | |||||
2463 | ** the script processor asserts ATN. | |||||
2464 | ** | |||||
2465 | ** The target should switch to a MSG_OUT phase | |||||
2466 | ** to get the message. | |||||
2467 | */ | |||||
2468 | SCR_FROM_REG (socl)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_socl )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
2469 | 0, | |||||
2470 | SCR_JUMP0x80080000 ^ IFFALSE (MASK (CATN, CATN))(0x00080000 | ((0x00040000 | (((0x08 ^ 0xff) & 0xff) << 8ul)|((0x08) & 0xff)))), | |||||
2471 | PADDR (dispatch)(0x50000000 | ((size_t) (&((struct script *)0)->dispatch ))), | |||||
2472 | /* | |||||
2473 | ** count it | |||||
2474 | */ | |||||
2475 | SCR_REG_REG (PS_REG, SCR_ADD, 1)(0x78000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scr3 )))) << 16ul)) | (0x06000000) | ((1)<<8ul)), | |||||
2476 | 0, | |||||
2477 | /* | |||||
2478 | ** Prepare a M_ID_ERROR message | |||||
2479 | ** (initiator detected error). | |||||
2480 | ** The target should retry the transfer. | |||||
2481 | */ | |||||
2482 | SCR_LOAD_REG (scratcha, M_ID_ERROR)(0x78000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))) << 16ul)) | (0x00000000) | (((0x05))<<8ul)), | |||||
2483 | 0, | |||||
2484 | SCR_JUMP0x80080000, | |||||
2485 | PADDR (setmsg)(0x50000000 | ((size_t) (&((struct script *)0)->setmsg ))), | |||||
2486 | ||||||
2487 | }/*-------------------------< COMMAND >--------------------*/,{ | |||||
2488 | /* | |||||
2489 | ** If this is not a GETCC transfer ... | |||||
2490 | */ | |||||
2491 | SCR_FROM_REG (SS_REG)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scr2 )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
2492 | 0, | |||||
2493 | /*<<<*/ SCR_JUMPR0x80880000 ^ IFTRUE (DATA (S_CHECK_COND))(0x00000000 | ((0x00040000 | (((0x02)) & 0xff)))), | |||||
2494 | 28, | |||||
2495 | /* | |||||
2496 | ** ... set a timestamp ... | |||||
2497 | */ | |||||
2498 | SCR_COPY (sizeof (u_long))(0xc0000000 | 0x01000000 | (sizeof (unsigned long))), | |||||
2499 | KVAR(SCRIPT_KVAR_JIFFIES)(0x70000000 | ((0))), | |||||
2500 | NADDR (header.stamp.command)(0x40000000 | ((size_t) (&((struct ncb *)0)->header.stamp .command))), | |||||
2501 | /* | |||||
2502 | ** ... and send the command | |||||
2503 | */ | |||||
2504 | SCR_MOVE_TBL(0x18000000 ^ (0 << 1ul)) ^ SCR_COMMAND0x02000000, | |||||
2505 | offsetof (struct dsb, cmd)((size_t) (&((struct dsb *)0)->cmd)), | |||||
2506 | SCR_JUMP0x80080000, | |||||
2507 | PADDR (dispatch)(0x50000000 | ((size_t) (&((struct script *)0)->dispatch ))), | |||||
2508 | /* | |||||
2509 | ** Send the GETCC command | |||||
2510 | */ | |||||
2511 | /*>>>*/ SCR_MOVE_TBL(0x18000000 ^ (0 << 1ul)) ^ SCR_COMMAND0x02000000, | |||||
2512 | offsetof (struct dsb, scmd)((size_t) (&((struct dsb *)0)->scmd)), | |||||
2513 | SCR_JUMP0x80080000, | |||||
2514 | PADDR (dispatch)(0x50000000 | ((size_t) (&((struct script *)0)->dispatch ))), | |||||
2515 | ||||||
2516 | }/*-------------------------< STATUS >--------------------*/,{ | |||||
2517 | /* | |||||
2518 | ** set the timestamp. | |||||
2519 | */ | |||||
2520 | SCR_COPY (sizeof (u_long))(0xc0000000 | 0x01000000 | (sizeof (unsigned long))), | |||||
2521 | KVAR(SCRIPT_KVAR_JIFFIES)(0x70000000 | ((0))), | |||||
2522 | NADDR (header.stamp.status)(0x40000000 | ((size_t) (&((struct ncb *)0)->header.stamp .status))), | |||||
2523 | /* | |||||
2524 | ** If this is a GETCC transfer, | |||||
2525 | */ | |||||
2526 | SCR_FROM_REG (SS_REG)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scr2 )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
2527 | 0, | |||||
2528 | /*<<<*/ SCR_JUMPR0x80880000 ^ IFFALSE (DATA (S_CHECK_COND))(0x00080000 | ((0x00040000 | (((0x02)) & 0xff)))), | |||||
2529 | 40, | |||||
2530 | /* | |||||
2531 | ** get the status | |||||
2532 | */ | |||||
2533 | SCR_MOVE_ABS (1)((0x08000000 ^ (0 << 1ul)) | (1)) ^ SCR_STATUS0x03000000, | |||||
2534 | NADDR (scratch)(0x40000000 | ((size_t) (&((struct ncb *)0)->scratch)) ), | |||||
2535 | /* | |||||
2536 | ** Save status to scsi_status. | |||||
2537 | ** Mark as complete. | |||||
2538 | ** And wait for disconnect. | |||||
2539 | */ | |||||
2540 | SCR_TO_REG (SS_REG)(0x68000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scr2 )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
2541 | 0, | |||||
2542 | SCR_REG_REG (SS_REG, SCR_OR, S_SENSE)(0x78000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scr2 )))) << 16ul)) | (0x02000000) | (((0x80))<<8ul)), | |||||
2543 | 0, | |||||
2544 | SCR_LOAD_REG (HS_REG, HS_COMPLETE)(0x78000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scr1 )))) << 16ul)) | (0x00000000) | (((4))<<8ul)), | |||||
2545 | 0, | |||||
2546 | SCR_JUMP0x80080000, | |||||
2547 | PADDR (checkatn)(0x50000000 | ((size_t) (&((struct script *)0)->checkatn ))), | |||||
2548 | /* | |||||
2549 | ** If it was no GETCC transfer, | |||||
2550 | ** save the status to scsi_status. | |||||
2551 | */ | |||||
2552 | /*>>>*/ SCR_MOVE_ABS (1)((0x08000000 ^ (0 << 1ul)) | (1)) ^ SCR_STATUS0x03000000, | |||||
2553 | NADDR (scratch)(0x40000000 | ((size_t) (&((struct ncb *)0)->scratch)) ), | |||||
2554 | SCR_TO_REG (SS_REG)(0x68000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scr2 )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
2555 | 0, | |||||
2556 | /* | |||||
2557 | ** if it was no check condition ... | |||||
2558 | */ | |||||
2559 | SCR_JUMP0x80080000 ^ IFTRUE (DATA (S_CHECK_COND))(0x00000000 | ((0x00040000 | (((0x02)) & 0xff)))), | |||||
2560 | PADDR (checkatn)(0x50000000 | ((size_t) (&((struct script *)0)->checkatn ))), | |||||
2561 | /* | |||||
2562 | ** ... mark as complete. | |||||
2563 | */ | |||||
2564 | SCR_LOAD_REG (HS_REG, HS_COMPLETE)(0x78000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scr1 )))) << 16ul)) | (0x00000000) | (((4))<<8ul)), | |||||
2565 | 0, | |||||
2566 | SCR_JUMP0x80080000, | |||||
2567 | PADDR (checkatn)(0x50000000 | ((size_t) (&((struct script *)0)->checkatn ))), | |||||
2568 | ||||||
2569 | }/*-------------------------< MSG_IN >--------------------*/,{ | |||||
2570 | /* | |||||
2571 | ** Get the first byte of the message | |||||
2572 | ** and save it to SCRATCHA. | |||||
2573 | ** | |||||
2574 | ** The script processor doesn't negate the | |||||
2575 | ** ACK signal after this transfer. | |||||
2576 | */ | |||||
2577 | SCR_MOVE_ABS (1)((0x08000000 ^ (0 << 1ul)) | (1)) ^ SCR_MSG_IN0x07000000, | |||||
2578 | NADDR (msgin[0])(0x40000000 | ((size_t) (&((struct ncb *)0)->msgin[0]) )), | |||||
2579 | /* | |||||
2580 | ** Check for message parity error. | |||||
2581 | */ | |||||
2582 | SCR_TO_REG (scratcha)(0x68000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
2583 | 0, | |||||
2584 | SCR_FROM_REG (socl)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_socl )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
2585 | 0, | |||||
2586 | SCR_JUMP0x80080000 ^ IFTRUE (MASK (CATN, CATN))(0x00000000 | ((0x00040000 | (((0x08 ^ 0xff) & 0xff) << 8ul)|((0x08) & 0xff)))), | |||||
2587 | PADDRH (msg_parity)(0x80000000 | ((size_t) (&((struct scripth *)0)->msg_parity ))), | |||||
2588 | SCR_FROM_REG (scratcha)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
2589 | 0, | |||||
2590 | /* | |||||
2591 | ** Parity was ok, handle this message. | |||||
2592 | */ | |||||
2593 | SCR_JUMP0x80080000 ^ IFTRUE (DATA (M_COMPLETE))(0x00000000 | ((0x00040000 | (((0x00)) & 0xff)))), | |||||
2594 | PADDR (complete)(0x50000000 | ((size_t) (&((struct script *)0)->complete ))), | |||||
2595 | SCR_JUMP0x80080000 ^ IFTRUE (DATA (M_SAVE_DP))(0x00000000 | ((0x00040000 | (((0x02)) & 0xff)))), | |||||
2596 | PADDR (save_dp)(0x50000000 | ((size_t) (&((struct script *)0)->save_dp ))), | |||||
2597 | SCR_JUMP0x80080000 ^ IFTRUE (DATA (M_RESTORE_DP))(0x00000000 | ((0x00040000 | (((0x03)) & 0xff)))), | |||||
2598 | PADDR (restore_dp)(0x50000000 | ((size_t) (&((struct script *)0)->restore_dp ))), | |||||
2599 | SCR_JUMP0x80080000 ^ IFTRUE (DATA (M_DISCONNECT))(0x00000000 | ((0x00040000 | (((0x04)) & 0xff)))), | |||||
2600 | PADDR (disconnect)(0x50000000 | ((size_t) (&((struct script *)0)->disconnect ))), | |||||
2601 | SCR_JUMP0x80080000 ^ IFTRUE (DATA (M_EXTENDED))(0x00000000 | ((0x00040000 | (((0x01)) & 0xff)))), | |||||
2602 | PADDRH (msg_extended)(0x80000000 | ((size_t) (&((struct scripth *)0)->msg_extended ))), | |||||
2603 | SCR_JUMP0x80080000 ^ IFTRUE (DATA (M_NOOP))(0x00000000 | ((0x00040000 | (((0x08)) & 0xff)))), | |||||
2604 | PADDR (clrack)(0x50000000 | ((size_t) (&((struct script *)0)->clrack ))), | |||||
2605 | SCR_JUMP0x80080000 ^ IFTRUE (DATA (M_REJECT))(0x00000000 | ((0x00040000 | (((0x07)) & 0xff)))), | |||||
2606 | PADDRH (msg_reject)(0x80000000 | ((size_t) (&((struct scripth *)0)->msg_reject ))), | |||||
2607 | SCR_JUMP0x80080000 ^ IFTRUE (DATA (M_IGN_RESIDUE))(0x00000000 | ((0x00040000 | (((0x23)) & 0xff)))), | |||||
2608 | PADDRH (msg_ign_residue)(0x80000000 | ((size_t) (&((struct scripth *)0)->msg_ign_residue ))), | |||||
2609 | /* | |||||
2610 | ** Rest of the messages left as | |||||
2611 | ** an exercise ... | |||||
2612 | ** | |||||
2613 | ** Unimplemented messages: | |||||
2614 | ** fall through to MSG_BAD. | |||||
2615 | */ | |||||
2616 | }/*-------------------------< MSG_BAD >------------------*/,{ | |||||
2617 | /* | |||||
2618 | ** unimplemented message - reject it. | |||||
2619 | */ | |||||
2620 | SCR_INT0x98080000, | |||||
2621 | SIR_REJECT_SENT(10), | |||||
2622 | SCR_LOAD_REG (scratcha, M_REJECT)(0x78000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))) << 16ul)) | (0x00000000) | (((0x07))<<8ul)), | |||||
2623 | 0, | |||||
2624 | SCR_JUMP0x80080000, | |||||
2625 | PADDR (setmsg)(0x50000000 | ((size_t) (&((struct script *)0)->setmsg ))), | |||||
2626 | ||||||
2627 | }/*-------------------------< COMPLETE >-----------------*/,{ | |||||
2628 | /* | |||||
2629 | ** Complete message. | |||||
2630 | ** | |||||
2631 | ** If it's not the get condition code, | |||||
2632 | ** copy TEMP register to LASTP in header. | |||||
2633 | */ | |||||
2634 | SCR_FROM_REG (SS_REG)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scr2 )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
2635 | 0, | |||||
2636 | /*<<<*/ SCR_JUMPR0x80880000 ^ IFTRUE (MASK (S_SENSE, S_SENSE))(0x00000000 | ((0x00040000 | ((((0x80) ^ 0xff) & 0xff) << 8ul)|(((0x80)) & 0xff)))), | |||||
2637 | 12, | |||||
2638 | SCR_COPY (4)(0xc0000000 | 0x01000000 | (4)), | |||||
2639 | RADDR (temp)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_temp )))), | |||||
2640 | NADDR (header.lastp)(0x40000000 | ((size_t) (&((struct ncb *)0)->header.lastp ))), | |||||
2641 | /*>>>*/ /* | |||||
2642 | ** When we terminate the cycle by clearing ACK, | |||||
2643 | ** the target may disconnect immediately. | |||||
2644 | ** | |||||
2645 | ** We don't want to be told of an | |||||
2646 | ** "unexpected disconnect", | |||||
2647 | ** so we disable this feature. | |||||
2648 | */ | |||||
2649 | SCR_REG_REG (scntl2, SCR_AND, 0x7f)(0x78000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scntl2 )))) << 16ul)) | (0x04000000) | ((0x7f)<<8ul)), | |||||
2650 | 0, | |||||
2651 | /* | |||||
2652 | ** Terminate cycle ... | |||||
2653 | */ | |||||
2654 | SCR_CLR (SCR_ACK|SCR_ATN)(0x60000000 | (0x00000040|0x00000008)), | |||||
2655 | 0, | |||||
2656 | /* | |||||
2657 | ** ... and wait for the disconnect. | |||||
2658 | */ | |||||
2659 | SCR_WAIT_DISC0x48000000, | |||||
2660 | 0, | |||||
2661 | }/*-------------------------< CLEANUP >-------------------*/,{ | |||||
2662 | /* | |||||
2663 | ** dsa: Pointer to ccb | |||||
2664 | ** or xxxxxxFF (no ccb) | |||||
2665 | ** | |||||
2666 | ** HS_REG: Host-Status (<>0!) | |||||
2667 | */ | |||||
2668 | SCR_FROM_REG (dsa)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_dsa )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
2669 | 0, | |||||
2670 | SCR_JUMP0x80080000 ^ IFTRUE (DATA (0xff))(0x00000000 | ((0x00040000 | ((0xff) & 0xff)))), | |||||
2671 | PADDR (signal)(0x50000000 | ((size_t) (&((struct script *)0)->signal ))), | |||||
2672 | /* | |||||
2673 | ** dsa is valid. | |||||
2674 | ** save the status registers | |||||
2675 | */ | |||||
2676 | SCR_COPY (4)(0xc0000000 | 0x01000000 | (4)), | |||||
2677 | RADDR (scr0)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_scr0 )))), | |||||
2678 | NADDR (header.status)(0x40000000 | ((size_t) (&((struct ncb *)0)->header.status ))), | |||||
2679 | /* | |||||
2680 | ** and copy back the header to the ccb. | |||||
2681 | */ | |||||
2682 | SCR_COPY_F (4)(0xc0000000 | (4)), | |||||
2683 | RADDR (dsa)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_dsa )))), | |||||
2684 | PADDR (cleanup0)(0x50000000 | ((size_t) (&((struct script *)0)->cleanup0 ))), | |||||
2685 | SCR_COPY (sizeof (struct head))(0xc0000000 | 0x01000000 | (sizeof (struct head))), | |||||
2686 | NADDR (header)(0x40000000 | ((size_t) (&((struct ncb *)0)->header))), | |||||
2687 | }/*-------------------------< CLEANUP0 >--------------------*/,{ | |||||
2688 | 0, | |||||
2689 | ||||||
2690 | /* | |||||
2691 | ** If command resulted in "check condition" | |||||
2692 | ** status and is not yet completed, | |||||
2693 | ** try to get the condition code. | |||||
2694 | */ | |||||
2695 | SCR_FROM_REG (HS_REG)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scr1 )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
2696 | 0, | |||||
2697 | /*<<<*/ SCR_JUMPR0x80880000 ^ IFFALSE (MASK (0, HS_DONEMASK))(0x00080000 | ((0x00040000 | ((((0xfc) ^ 0xff) & 0xff) << 8ul)|((0) & 0xff)))), | |||||
2698 | 16, | |||||
2699 | SCR_FROM_REG (SS_REG)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scr2 )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
2700 | 0, | |||||
2701 | SCR_JUMP0x80080000 ^ IFTRUE (DATA (S_CHECK_COND))(0x00000000 | ((0x00040000 | (((0x02)) & 0xff)))), | |||||
2702 | PADDRH(getcc2)(0x80000000 | ((size_t) (&((struct scripth *)0)->getcc2 ))), | |||||
2703 | /* | |||||
2704 | ** And make the DSA register invalid. | |||||
2705 | */ | |||||
2706 | /*>>>*/ SCR_LOAD_REG (dsa, 0xff)(0x78000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_dsa )))) << 16ul)) | (0x00000000) | ((0xff)<<8ul)), /* invalid */ | |||||
2707 | 0, | |||||
2708 | }/*-------------------------< SIGNAL >----------------------*/,{ | |||||
2709 | /* | |||||
2710 | ** if status = queue full, | |||||
2711 | ** reinsert in startqueue and stall queue. | |||||
2712 | */ | |||||
2713 | SCR_FROM_REG (SS_REG)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scr2 )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
2714 | 0, | |||||
2715 | SCR_INT0x98080000 ^ IFTRUE (DATA (S_QUEUE_FULL))(0x00000000 | ((0x00040000 | (((0x28)) & 0xff)))), | |||||
2716 | SIR_STALL_QUEUE(4), | |||||
2717 | /* | |||||
2718 | ** if job completed ... | |||||
2719 | */ | |||||
2720 | SCR_FROM_REG (HS_REG)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scr1 )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
2721 | 0, | |||||
2722 | /* | |||||
2723 | ** ... signal completion to the host | |||||
2724 | */ | |||||
2725 | SCR_INT_FLY0x98180000 ^ IFFALSE (MASK (0, HS_DONEMASK))(0x00080000 | ((0x00040000 | ((((0xfc) ^ 0xff) & 0xff) << 8ul)|((0) & 0xff)))), | |||||
2726 | 0, | |||||
2727 | /* | |||||
2728 | ** Auf zu neuen Schandtaten! | |||||
2729 | */ | |||||
2730 | SCR_JUMP0x80080000, | |||||
2731 | PADDR(start)(0x50000000 | ((size_t) (&((struct script *)0)->start) )), | |||||
2732 | ||||||
2733 | }/*-------------------------< SAVE_DP >------------------*/,{ | |||||
2734 | /* | |||||
2735 | ** SAVE_DP message: | |||||
2736 | ** Copy TEMP register to SAVEP in header. | |||||
2737 | */ | |||||
2738 | SCR_COPY (4)(0xc0000000 | 0x01000000 | (4)), | |||||
2739 | RADDR (temp)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_temp )))), | |||||
2740 | NADDR (header.savep)(0x40000000 | ((size_t) (&((struct ncb *)0)->header.savep ))), | |||||
2741 | SCR_JUMP0x80080000, | |||||
2742 | PADDR (clrack)(0x50000000 | ((size_t) (&((struct script *)0)->clrack ))), | |||||
2743 | }/*-------------------------< RESTORE_DP >---------------*/,{ | |||||
2744 | /* | |||||
2745 | ** RESTORE_DP message: | |||||
2746 | ** Copy SAVEP in header to TEMP register. | |||||
2747 | */ | |||||
2748 | SCR_COPY (4)(0xc0000000 | 0x01000000 | (4)), | |||||
2749 | NADDR (header.savep)(0x40000000 | ((size_t) (&((struct ncb *)0)->header.savep ))), | |||||
2750 | RADDR (temp)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_temp )))), | |||||
2751 | SCR_JUMP0x80080000, | |||||
2752 | PADDR (clrack)(0x50000000 | ((size_t) (&((struct script *)0)->clrack ))), | |||||
2753 | ||||||
2754 | }/*-------------------------< DISCONNECT >---------------*/,{ | |||||
2755 | /* | |||||
2756 | ** If QUIRK_AUTOSAVE is set, | |||||
2757 | ** do an "save pointer" operation. | |||||
2758 | */ | |||||
2759 | SCR_FROM_REG (QU_REG)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scr0 )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
2760 | 0, | |||||
2761 | /*<<<*/ SCR_JUMPR0x80880000 ^ IFFALSE (MASK (QUIRK_AUTOSAVE, QUIRK_AUTOSAVE))(0x00080000 | ((0x00040000 | ((((0x01) ^ 0xff) & 0xff) << 8ul)|(((0x01)) & 0xff)))), | |||||
2762 | 12, | |||||
2763 | /* | |||||
2764 | ** like SAVE_DP message: | |||||
2765 | ** Copy TEMP register to SAVEP in header. | |||||
2766 | */ | |||||
2767 | SCR_COPY (4)(0xc0000000 | 0x01000000 | (4)), | |||||
2768 | RADDR (temp)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_temp )))), | |||||
2769 | NADDR (header.savep)(0x40000000 | ((size_t) (&((struct ncb *)0)->header.savep ))), | |||||
2770 | /*>>>*/ /* | |||||
2771 | ** Check if temp==savep or temp==goalp: | |||||
2772 | ** if not, log a missing save pointer message. | |||||
2773 | ** In fact, it's a comparison mod 256. | |||||
2774 | ** | |||||
2775 | ** Hmmm, I hadn't thought that I would be urged to | |||||
2776 | ** write this kind of ugly self modifying code. | |||||
2777 | ** | |||||
2778 | ** It's unbelievable, but the ncr53c8xx isn't able | |||||
2779 | ** to subtract one register from another. | |||||
2780 | */ | |||||
2781 | SCR_FROM_REG (temp)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_temp )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
2782 | 0, | |||||
2783 | /* | |||||
2784 | ** You are not expected to understand this .. | |||||
2785 | ** | |||||
2786 | ** CAUTION: only little endian architectures supported! XXX | |||||
2787 | */ | |||||
2788 | SCR_COPY_F (1)(0xc0000000 | (1)), | |||||
2789 | NADDR (header.savep)(0x40000000 | ((size_t) (&((struct ncb *)0)->header.savep ))), | |||||
2790 | PADDR (disconnect0)(0x50000000 | ((size_t) (&((struct script *)0)->disconnect0 ))), | |||||
2791 | }/*-------------------------< DISCONNECT0 >--------------*/,{ | |||||
2792 | /*<<<*/ SCR_JUMPR0x80880000 ^ IFTRUE (DATA (1))(0x00000000 | ((0x00040000 | ((1) & 0xff)))), | |||||
2793 | 20, | |||||
2794 | /* | |||||
2795 | ** neither this | |||||
2796 | */ | |||||
2797 | SCR_COPY_F (1)(0xc0000000 | (1)), | |||||
2798 | NADDR (header.goalp)(0x40000000 | ((size_t) (&((struct ncb *)0)->header.goalp ))), | |||||
2799 | PADDR (disconnect1)(0x50000000 | ((size_t) (&((struct script *)0)->disconnect1 ))), | |||||
2800 | }/*-------------------------< DISCONNECT1 >--------------*/,{ | |||||
2801 | SCR_INT0x98080000 ^ IFFALSE (DATA (1))(0x00080000 | ((0x00040000 | ((1) & 0xff)))), | |||||
2802 | SIR_MISSING_SAVE(12), | |||||
2803 | /*>>>*/ | |||||
2804 | ||||||
2805 | /* | |||||
2806 | ** DISCONNECTing ... | |||||
2807 | ** | |||||
2808 | ** disable the "unexpected disconnect" feature, | |||||
2809 | ** and remove the ACK signal. | |||||
2810 | */ | |||||
2811 | SCR_REG_REG (scntl2, SCR_AND, 0x7f)(0x78000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scntl2 )))) << 16ul)) | (0x04000000) | ((0x7f)<<8ul)), | |||||
2812 | 0, | |||||
2813 | SCR_CLR (SCR_ACK|SCR_ATN)(0x60000000 | (0x00000040|0x00000008)), | |||||
2814 | 0, | |||||
2815 | /* | |||||
2816 | ** Wait for the disconnect. | |||||
2817 | */ | |||||
2818 | SCR_WAIT_DISC0x48000000, | |||||
2819 | 0, | |||||
2820 | /* | |||||
2821 | ** Profiling: | |||||
2822 | ** Set a time stamp, | |||||
2823 | ** and count the disconnects. | |||||
2824 | */ | |||||
2825 | SCR_COPY (sizeof (u_long))(0xc0000000 | 0x01000000 | (sizeof (unsigned long))), | |||||
2826 | KVAR(SCRIPT_KVAR_JIFFIES)(0x70000000 | ((0))), | |||||
2827 | NADDR (header.stamp.disconnect)(0x40000000 | ((size_t) (&((struct ncb *)0)->header.stamp .disconnect))), | |||||
2828 | SCR_COPY (4)(0xc0000000 | 0x01000000 | (4)), | |||||
2829 | NADDR (disc_phys)(0x40000000 | ((size_t) (&((struct ncb *)0)->disc_phys ))), | |||||
2830 | RADDR (temp)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_temp )))), | |||||
2831 | SCR_REG_REG (temp, SCR_ADD, 0x01)(0x78000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_temp )))) << 16ul)) | (0x06000000) | ((0x01)<<8ul)), | |||||
2832 | 0, | |||||
2833 | SCR_COPY (4)(0xc0000000 | 0x01000000 | (4)), | |||||
2834 | RADDR (temp)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_temp )))), | |||||
2835 | NADDR (disc_phys)(0x40000000 | ((size_t) (&((struct ncb *)0)->disc_phys ))), | |||||
2836 | /* | |||||
2837 | ** Status is: DISCONNECTED. | |||||
2838 | */ | |||||
2839 | SCR_LOAD_REG (HS_REG, HS_DISCONNECT)(0x78000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scr1 )))) << 16ul)) | (0x00000000) | (((3))<<8ul)), | |||||
2840 | 0, | |||||
2841 | SCR_JUMP0x80080000, | |||||
2842 | PADDR (cleanup)(0x50000000 | ((size_t) (&((struct script *)0)->cleanup ))), | |||||
2843 | ||||||
2844 | }/*-------------------------< MSG_OUT >-------------------*/,{ | |||||
2845 | /* | |||||
2846 | ** The target requests a message. | |||||
2847 | */ | |||||
2848 | SCR_MOVE_ABS (1)((0x08000000 ^ (0 << 1ul)) | (1)) ^ SCR_MSG_OUT0x06000000, | |||||
2849 | NADDR (msgout)(0x40000000 | ((size_t) (&((struct ncb *)0)->msgout))), | |||||
2850 | SCR_COPY (1)(0xc0000000 | 0x01000000 | (1)), | |||||
2851 | RADDR (sfbr)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_sfbr )))), | |||||
2852 | NADDR (lastmsg)(0x40000000 | ((size_t) (&((struct ncb *)0)->lastmsg)) ), | |||||
2853 | /* | |||||
2854 | ** If it was no ABORT message ... | |||||
2855 | */ | |||||
2856 | SCR_JUMP0x80080000 ^ IFTRUE (DATA (M_ABORT))(0x00000000 | ((0x00040000 | (((0x06)) & 0xff)))), | |||||
2857 | PADDRH (msg_out_abort)(0x80000000 | ((size_t) (&((struct scripth *)0)->msg_out_abort ))), | |||||
2858 | /* | |||||
2859 | ** ... wait for the next phase | |||||
2860 | ** if it's a message out, send it again, ... | |||||
2861 | */ | |||||
2862 | SCR_JUMP0x80080000 ^ IFTRUE (WHEN (SCR_MSG_OUT))(0x00000000 | ((0x00030000 | (0x06000000)))), | |||||
2863 | PADDR (msg_out)(0x50000000 | ((size_t) (&((struct script *)0)->msg_out ))), | |||||
2864 | }/*-------------------------< MSG_OUT_DONE >--------------*/,{ | |||||
2865 | /* | |||||
2866 | ** ... else clear the message ... | |||||
2867 | */ | |||||
2868 | SCR_LOAD_REG (scratcha, M_NOOP)(0x78000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))) << 16ul)) | (0x00000000) | (((0x08))<<8ul)), | |||||
2869 | 0, | |||||
2870 | SCR_COPY (4)(0xc0000000 | 0x01000000 | (4)), | |||||
2871 | RADDR (scratcha)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))), | |||||
2872 | NADDR (msgout)(0x40000000 | ((size_t) (&((struct ncb *)0)->msgout))), | |||||
2873 | /* | |||||
2874 | ** ... and process the next phase | |||||
2875 | */ | |||||
2876 | SCR_JUMP0x80080000, | |||||
2877 | PADDR (dispatch)(0x50000000 | ((size_t) (&((struct script *)0)->dispatch ))), | |||||
2878 | }/*------------------------< BADGETCC >---------------------*/,{ | |||||
2879 | /* | |||||
2880 | ** If SIGP was set, clear it and try again. | |||||
2881 | */ | |||||
2882 | SCR_FROM_REG (ctest2)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_ctest2 )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
2883 | 0, | |||||
2884 | SCR_JUMP0x80080000 ^ IFTRUE (MASK (CSIGP,CSIGP))(0x00000000 | ((0x00040000 | (((0x40 ^ 0xff) & 0xff) << 8ul)|((0x40) & 0xff)))), | |||||
2885 | PADDRH (getcc2)(0x80000000 | ((size_t) (&((struct scripth *)0)->getcc2 ))), | |||||
2886 | SCR_INT0x98080000, | |||||
2887 | SIR_SENSE_FAILED(2), | |||||
2888 | }/*-------------------------< RESELECT >--------------------*/,{ | |||||
2889 | /* | |||||
2890 | ** This NOP will be patched with LED OFF | |||||
2891 | ** SCR_REG_REG (gpreg, SCR_OR, 0x01) | |||||
2892 | */ | |||||
2893 | SCR_NO_OP0x80000000, | |||||
2894 | 0, | |||||
2895 | /* | |||||
2896 | ** make the DSA invalid. | |||||
2897 | */ | |||||
2898 | SCR_LOAD_REG (dsa, 0xff)(0x78000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_dsa )))) << 16ul)) | (0x00000000) | ((0xff)<<8ul)), | |||||
2899 | 0, | |||||
2900 | SCR_CLR (SCR_TRG)(0x60000000 | (0x00000200)), | |||||
2901 | 0, | |||||
2902 | /* | |||||
2903 | ** Sleep waiting for a reselection. | |||||
2904 | ** If SIGP is set, special treatment. | |||||
2905 | ** | |||||
2906 | ** Zu allem bereit .. | |||||
2907 | */ | |||||
2908 | SCR_WAIT_RESEL0x50000000, | |||||
2909 | PADDR(reselect2)(0x50000000 | ((size_t) (&((struct script *)0)->reselect2 ))), | |||||
2910 | }/*-------------------------< RESELECT1 >--------------------*/,{ | |||||
2911 | /* | |||||
2912 | ** This NOP will be patched with LED ON | |||||
2913 | ** SCR_REG_REG (gpreg, SCR_AND, 0xfe) | |||||
2914 | */ | |||||
2915 | SCR_NO_OP0x80000000, | |||||
2916 | 0, | |||||
2917 | /* | |||||
2918 | ** ... zu nichts zu gebrauchen ? | |||||
2919 | ** | |||||
2920 | ** load the target id into the SFBR | |||||
2921 | ** and jump to the control block. | |||||
2922 | ** | |||||
2923 | ** Look at the declarations of | |||||
2924 | ** - struct ncb | |||||
2925 | ** - struct tcb | |||||
2926 | ** - struct lcb | |||||
2927 | ** - struct ccb | |||||
2928 | ** to understand what's going on. | |||||
2929 | */ | |||||
2930 | SCR_REG_SFBR (ssid, SCR_AND, 0x8F)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_ssid )))) << 16ul)) | (0x04000000) | ((0x8F)<<8ul)), | |||||
2931 | 0, | |||||
2932 | SCR_TO_REG (ctest0)(0x68000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_ctest0 )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
2933 | 0, | |||||
2934 | SCR_JUMP0x80080000, | |||||
2935 | NADDR (jump_tcb)(0x40000000 | ((size_t) (&((struct ncb *)0)->jump_tcb) )), | |||||
2936 | }/*-------------------------< RESELECT2 >-------------------*/,{ | |||||
2937 | /* | |||||
2938 | ** This NOP will be patched with LED ON | |||||
2939 | ** SCR_REG_REG (gpreg, SCR_AND, 0xfe) | |||||
2940 | */ | |||||
2941 | SCR_NO_OP0x80000000, | |||||
2942 | 0, | |||||
2943 | /* | |||||
2944 | ** If it's not connected :( | |||||
2945 | ** -> interrupted by SIGP bit. | |||||
2946 | ** Jump to start. | |||||
2947 | */ | |||||
2948 | SCR_FROM_REG (ctest2)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_ctest2 )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
2949 | 0, | |||||
2950 | SCR_JUMP0x80080000 ^ IFTRUE (MASK (CSIGP,CSIGP))(0x00000000 | ((0x00040000 | (((0x40 ^ 0xff) & 0xff) << 8ul)|((0x40) & 0xff)))), | |||||
2951 | PADDR (start)(0x50000000 | ((size_t) (&((struct script *)0)->start) )), | |||||
2952 | SCR_JUMP0x80080000, | |||||
2953 | PADDR (reselect)(0x50000000 | ((size_t) (&((struct script *)0)->reselect ))), | |||||
2954 | ||||||
2955 | }/*-------------------------< RESEL_TMP >-------------------*/,{ | |||||
2956 | /* | |||||
2957 | ** The return address in TEMP | |||||
2958 | ** is in fact the data structure address, | |||||
2959 | ** so copy it to the DSA register. | |||||
2960 | */ | |||||
2961 | SCR_COPY (4)(0xc0000000 | 0x01000000 | (4)), | |||||
2962 | RADDR (temp)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_temp )))), | |||||
2963 | RADDR (dsa)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_dsa )))), | |||||
2964 | SCR_JUMP0x80080000, | |||||
2965 | PADDR (prepare)(0x50000000 | ((size_t) (&((struct script *)0)->prepare ))), | |||||
2966 | ||||||
2967 | }/*-------------------------< RESEL_LUN >-------------------*/,{ | |||||
2968 | /* | |||||
2969 | ** come back to this point | |||||
2970 | ** to get an IDENTIFY message | |||||
2971 | ** Wait for a msg_in phase. | |||||
2972 | */ | |||||
2973 | /*<<<*/ SCR_JUMPR0x80880000 ^ IFFALSE (WHEN (SCR_MSG_IN))(0x00080000 | ((0x00030000 | (0x07000000)))), | |||||
2974 | 48, | |||||
2975 | /* | |||||
2976 | ** message phase | |||||
2977 | ** It's not a sony, it's a trick: | |||||
2978 | ** read the data without acknowledging it. | |||||
2979 | */ | |||||
2980 | SCR_FROM_REG (sbdl)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_sbdl )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
2981 | 0, | |||||
2982 | /*<<<*/ SCR_JUMPR0x80880000 ^ IFFALSE (MASK (M_IDENTIFY, 0x98))(0x00080000 | ((0x00040000 | (((0x98 ^ 0xff) & 0xff) << 8ul)|(((0x80)) & 0xff)))), | |||||
2983 | 32, | |||||
2984 | /* | |||||
2985 | ** It WAS an Identify message. | |||||
2986 | ** get it and ack it! | |||||
2987 | */ | |||||
2988 | SCR_MOVE_ABS (1)((0x08000000 ^ (0 << 1ul)) | (1)) ^ SCR_MSG_IN0x07000000, | |||||
2989 | NADDR (msgin)(0x40000000 | ((size_t) (&((struct ncb *)0)->msgin))), | |||||
2990 | SCR_CLR (SCR_ACK)(0x60000000 | (0x00000040)), | |||||
2991 | 0, | |||||
2992 | /* | |||||
2993 | ** Mask out the lun. | |||||
2994 | */ | |||||
2995 | SCR_REG_REG (sfbr, SCR_AND, 0x07)(0x78000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_sfbr )))) << 16ul)) | (0x04000000) | ((0x07)<<8ul)), | |||||
2996 | 0, | |||||
2997 | SCR_RETURN0x90080000, | |||||
2998 | 0, | |||||
2999 | /* | |||||
3000 | ** No message phase or no IDENTIFY message: | |||||
3001 | ** return 0. | |||||
3002 | */ | |||||
3003 | /*>>>*/ SCR_LOAD_SFBR (0)((0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)-> nc_gpreg)))) << 16ul)) | (0x00000000) | ((0)<<8ul ))), | |||||
3004 | 0, | |||||
3005 | SCR_RETURN0x90080000, | |||||
3006 | 0, | |||||
3007 | ||||||
3008 | }/*-------------------------< RESEL_TAG >-------------------*/,{ | |||||
3009 | /* | |||||
3010 | ** come back to this point | |||||
3011 | ** to get a SIMPLE_TAG message | |||||
3012 | ** Wait for a MSG_IN phase. | |||||
3013 | */ | |||||
3014 | /*<<<*/ SCR_JUMPR0x80880000 ^ IFFALSE (WHEN (SCR_MSG_IN))(0x00080000 | ((0x00030000 | (0x07000000)))), | |||||
3015 | 64, | |||||
3016 | /* | |||||
3017 | ** message phase | |||||
3018 | ** It's a trick - read the data | |||||
3019 | ** without acknowledging it. | |||||
3020 | */ | |||||
3021 | SCR_FROM_REG (sbdl)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_sbdl )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
3022 | 0, | |||||
3023 | /*<<<*/ SCR_JUMPR0x80880000 ^ IFFALSE (DATA (M_SIMPLE_TAG))(0x00080000 | ((0x00040000 | (((0x20)) & 0xff)))), | |||||
3024 | 48, | |||||
3025 | /* | |||||
3026 | ** It WAS a SIMPLE_TAG message. | |||||
3027 | ** get it and ack it! | |||||
3028 | */ | |||||
3029 | SCR_MOVE_ABS (1)((0x08000000 ^ (0 << 1ul)) | (1)) ^ SCR_MSG_IN0x07000000, | |||||
3030 | NADDR (msgin)(0x40000000 | ((size_t) (&((struct ncb *)0)->msgin))), | |||||
3031 | SCR_CLR (SCR_ACK)(0x60000000 | (0x00000040)), | |||||
3032 | 0, | |||||
3033 | /* | |||||
3034 | ** Wait for the second byte (the tag) | |||||
3035 | */ | |||||
3036 | /*<<<*/ SCR_JUMPR0x80880000 ^ IFFALSE (WHEN (SCR_MSG_IN))(0x00080000 | ((0x00030000 | (0x07000000)))), | |||||
3037 | 24, | |||||
3038 | /* | |||||
3039 | ** Get it and ack it! | |||||
3040 | */ | |||||
3041 | SCR_MOVE_ABS (1)((0x08000000 ^ (0 << 1ul)) | (1)) ^ SCR_MSG_IN0x07000000, | |||||
3042 | NADDR (msgin)(0x40000000 | ((size_t) (&((struct ncb *)0)->msgin))), | |||||
3043 | SCR_CLR (SCR_ACK|SCR_CARRY)(0x60000000 | (0x00000040|0x00000400)), | |||||
3044 | 0, | |||||
3045 | SCR_RETURN0x90080000, | |||||
3046 | 0, | |||||
3047 | /* | |||||
3048 | ** No message phase or no SIMPLE_TAG message | |||||
3049 | ** or no second byte: return 0. | |||||
3050 | */ | |||||
3051 | /*>>>*/ SCR_LOAD_SFBR (0)((0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)-> nc_gpreg)))) << 16ul)) | (0x00000000) | ((0)<<8ul ))), | |||||
3052 | 0, | |||||
3053 | SCR_SET (SCR_CARRY)(0x58000000 | (0x00000400)), | |||||
3054 | 0, | |||||
3055 | SCR_RETURN0x90080000, | |||||
3056 | 0, | |||||
3057 | ||||||
3058 | }/*-------------------------< DATA_IO >--------------------*/,{ | |||||
3059 | /* | |||||
3060 | ** Because Linux does not provide xfer data direction | |||||
3061 | ** to low-level scsi drivers, we must trust the target | |||||
3062 | ** for actual data direction when we cannot guess it. | |||||
3063 | ** The programmed interrupt patches savep, lastp, goalp, | |||||
3064 | ** etc.., and restarts the scsi script at data_out/in. | |||||
3065 | */ | |||||
3066 | SCR_INT0x98080000 ^ IFTRUE (WHEN (SCR_DATA_OUT))(0x00000000 | ((0x00030000 | (0x00000000)))), | |||||
3067 | SIR_DATA_IO_IS_OUT(13), | |||||
3068 | SCR_INT0x98080000 ^ IFTRUE (WHEN (SCR_DATA_IN))(0x00000000 | ((0x00030000 | (0x01000000)))), | |||||
3069 | SIR_DATA_IO_IS_IN(14), | |||||
3070 | SCR_JUMP0x80080000, | |||||
3071 | PADDR (no_data)(0x50000000 | ((size_t) (&((struct script *)0)->no_data ))), | |||||
3072 | ||||||
3073 | }/*-------------------------< DATA_IN >--------------------*/,{ | |||||
3074 | /* | |||||
3075 | ** Because the size depends on the | |||||
3076 | ** #define MAX_SCATTER parameter, | |||||
3077 | ** it is filled in at runtime. | |||||
3078 | ** | |||||
3079 | ** ##===========< i=0; i<MAX_SCATTER >========= | |||||
3080 | ** || SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_IN)), | |||||
3081 | ** || PADDR (checkatn), | |||||
3082 | ** || SCR_MOVE_TBL ^ SCR_DATA_IN, | |||||
3083 | ** || offsetof (struct dsb, data[ i]), | |||||
3084 | ** ##========================================== | |||||
3085 | ** | |||||
3086 | ** SCR_CALL, | |||||
3087 | ** PADDR (checkatn), | |||||
3088 | ** SCR_JUMP, | |||||
3089 | ** PADDR (no_data), | |||||
3090 | */ | |||||
3091 | 0 | |||||
3092 | }/*--------------------------------------------------------*/ | |||||
3093 | }; | |||||
3094 | ||||||
3095 | static struct scripth scripth0 __initdata = { | |||||
3096 | /*-------------------------< TRYLOOP >---------------------*/{ | |||||
3097 | /* | |||||
3098 | ** Load an entry of the start queue into dsa | |||||
3099 | ** and try to start it by jumping to TRYSEL. | |||||
3100 | ** | |||||
3101 | ** Because the size depends on the | |||||
3102 | ** #define MAX_START parameter, it is filled | |||||
3103 | ** in at runtime. | |||||
3104 | ** | |||||
3105 | **----------------------------------------------------------- | |||||
3106 | ** | |||||
3107 | ** ##===========< I=0; i<MAX_START >=========== | |||||
3108 | ** || SCR_COPY (4), | |||||
3109 | ** || NADDR (squeue[i]), | |||||
3110 | ** || RADDR (dsa), | |||||
3111 | ** || SCR_CALL, | |||||
3112 | ** || PADDR (trysel), | |||||
3113 | ** ##========================================== | |||||
3114 | ** | |||||
3115 | ** SCR_JUMP, | |||||
3116 | ** PADDRH(tryloop), | |||||
3117 | ** | |||||
3118 | **----------------------------------------------------------- | |||||
3119 | */ | |||||
3120 | 0 | |||||
3121 | },/*-------------------------< MSG_PARITY >---------------*/{ | |||||
3122 | /* | |||||
3123 | ** count it | |||||
3124 | */ | |||||
3125 | SCR_REG_REG (PS_REG, SCR_ADD, 0x01)(0x78000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scr3 )))) << 16ul)) | (0x06000000) | ((0x01)<<8ul)), | |||||
3126 | 0, | |||||
3127 | /* | |||||
3128 | ** send a "message parity error" message. | |||||
3129 | */ | |||||
3130 | SCR_LOAD_REG (scratcha, M_PARITY)(0x78000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))) << 16ul)) | (0x00000000) | (((0x09))<<8ul)), | |||||
3131 | 0, | |||||
3132 | SCR_JUMP0x80080000, | |||||
3133 | PADDR (setmsg)(0x50000000 | ((size_t) (&((struct script *)0)->setmsg ))), | |||||
3134 | }/*-------------------------< MSG_REJECT >---------------*/,{ | |||||
3135 | /* | |||||
3136 | ** If a negotiation was in progress, | |||||
3137 | ** negotiation failed. | |||||
3138 | */ | |||||
3139 | SCR_FROM_REG (HS_REG)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scr1 )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
3140 | 0, | |||||
3141 | SCR_INT0x98080000 ^ IFTRUE (DATA (HS_NEGOTIATE))(0x00000000 | ((0x00040000 | (((2)) & 0xff)))), | |||||
3142 | SIR_NEGO_FAILED(7), | |||||
3143 | /* | |||||
3144 | ** else make host log this message | |||||
3145 | */ | |||||
3146 | SCR_INT0x98080000 ^ IFFALSE (DATA (HS_NEGOTIATE))(0x00080000 | ((0x00040000 | (((2)) & 0xff)))), | |||||
3147 | SIR_REJECT_RECEIVED(9), | |||||
3148 | SCR_JUMP0x80080000, | |||||
3149 | PADDR (clrack)(0x50000000 | ((size_t) (&((struct script *)0)->clrack ))), | |||||
3150 | ||||||
3151 | }/*-------------------------< MSG_IGN_RESIDUE >----------*/,{ | |||||
3152 | /* | |||||
3153 | ** Terminate cycle | |||||
3154 | */ | |||||
3155 | SCR_CLR (SCR_ACK)(0x60000000 | (0x00000040)), | |||||
3156 | 0, | |||||
3157 | SCR_JUMP0x80080000 ^ IFFALSE (WHEN (SCR_MSG_IN))(0x00080000 | ((0x00030000 | (0x07000000)))), | |||||
3158 | PADDR (dispatch)(0x50000000 | ((size_t) (&((struct script *)0)->dispatch ))), | |||||
3159 | /* | |||||
3160 | ** get residue size. | |||||
3161 | */ | |||||
3162 | SCR_MOVE_ABS (1)((0x08000000 ^ (0 << 1ul)) | (1)) ^ SCR_MSG_IN0x07000000, | |||||
3163 | NADDR (msgin[1])(0x40000000 | ((size_t) (&((struct ncb *)0)->msgin[1]) )), | |||||
3164 | /* | |||||
3165 | ** Check for message parity error. | |||||
3166 | */ | |||||
3167 | SCR_TO_REG (scratcha)(0x68000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
3168 | 0, | |||||
3169 | SCR_FROM_REG (socl)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_socl )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
3170 | 0, | |||||
3171 | SCR_JUMP0x80080000 ^ IFTRUE (MASK (CATN, CATN))(0x00000000 | ((0x00040000 | (((0x08 ^ 0xff) & 0xff) << 8ul)|((0x08) & 0xff)))), | |||||
3172 | PADDRH (msg_parity)(0x80000000 | ((size_t) (&((struct scripth *)0)->msg_parity ))), | |||||
3173 | SCR_FROM_REG (scratcha)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
3174 | 0, | |||||
3175 | /* | |||||
3176 | ** Size is 0 .. ignore message. | |||||
3177 | */ | |||||
3178 | SCR_JUMP0x80080000 ^ IFTRUE (DATA (0))(0x00000000 | ((0x00040000 | ((0) & 0xff)))), | |||||
3179 | PADDR (clrack)(0x50000000 | ((size_t) (&((struct script *)0)->clrack ))), | |||||
3180 | /* | |||||
3181 | ** Size is not 1 .. have to interrupt. | |||||
3182 | */ | |||||
3183 | /*<<<*/ SCR_JUMPR0x80880000 ^ IFFALSE (DATA (1))(0x00080000 | ((0x00040000 | ((1) & 0xff)))), | |||||
3184 | 40, | |||||
3185 | /* | |||||
3186 | ** Check for residue byte in swide register | |||||
3187 | */ | |||||
3188 | SCR_FROM_REG (scntl2)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scntl2 )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
3189 | 0, | |||||
3190 | /*<<<*/ SCR_JUMPR0x80880000 ^ IFFALSE (MASK (WSR, WSR))(0x00080000 | ((0x00040000 | (((0x01 ^ 0xff) & 0xff) << 8ul)|((0x01) & 0xff)))), | |||||
3191 | 16, | |||||
3192 | /* | |||||
3193 | ** There IS data in the swide register. | |||||
3194 | ** Discard it. | |||||
3195 | */ | |||||
3196 | SCR_REG_REG (scntl2, SCR_OR, WSR)(0x78000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scntl2 )))) << 16ul)) | (0x02000000) | ((0x01)<<8ul)), | |||||
3197 | 0, | |||||
3198 | SCR_JUMP0x80080000, | |||||
3199 | PADDR (clrack)(0x50000000 | ((size_t) (&((struct script *)0)->clrack ))), | |||||
3200 | /* | |||||
3201 | ** Load again the size to the sfbr register. | |||||
3202 | */ | |||||
3203 | /*>>>*/ SCR_FROM_REG (scratcha)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
3204 | 0, | |||||
3205 | /*>>>*/ SCR_INT0x98080000, | |||||
3206 | SIR_IGN_RESIDUE(11), | |||||
3207 | SCR_JUMP0x80080000, | |||||
3208 | PADDR (clrack)(0x50000000 | ((size_t) (&((struct script *)0)->clrack ))), | |||||
3209 | ||||||
3210 | }/*-------------------------< MSG_EXTENDED >-------------*/,{ | |||||
3211 | /* | |||||
3212 | ** Terminate cycle | |||||
3213 | */ | |||||
3214 | SCR_CLR (SCR_ACK)(0x60000000 | (0x00000040)), | |||||
3215 | 0, | |||||
3216 | SCR_JUMP0x80080000 ^ IFFALSE (WHEN (SCR_MSG_IN))(0x00080000 | ((0x00030000 | (0x07000000)))), | |||||
3217 | PADDR (dispatch)(0x50000000 | ((size_t) (&((struct script *)0)->dispatch ))), | |||||
3218 | /* | |||||
3219 | ** get length. | |||||
3220 | */ | |||||
3221 | SCR_MOVE_ABS (1)((0x08000000 ^ (0 << 1ul)) | (1)) ^ SCR_MSG_IN0x07000000, | |||||
3222 | NADDR (msgin[1])(0x40000000 | ((size_t) (&((struct ncb *)0)->msgin[1]) )), | |||||
3223 | /* | |||||
3224 | ** Check for message parity error. | |||||
3225 | */ | |||||
3226 | SCR_TO_REG (scratcha)(0x68000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
3227 | 0, | |||||
3228 | SCR_FROM_REG (socl)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_socl )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
3229 | 0, | |||||
3230 | SCR_JUMP0x80080000 ^ IFTRUE (MASK (CATN, CATN))(0x00000000 | ((0x00040000 | (((0x08 ^ 0xff) & 0xff) << 8ul)|((0x08) & 0xff)))), | |||||
3231 | PADDRH (msg_parity)(0x80000000 | ((size_t) (&((struct scripth *)0)->msg_parity ))), | |||||
3232 | SCR_FROM_REG (scratcha)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
3233 | 0, | |||||
3234 | /* | |||||
3235 | */ | |||||
3236 | SCR_JUMP0x80080000 ^ IFTRUE (DATA (3))(0x00000000 | ((0x00040000 | ((3) & 0xff)))), | |||||
3237 | PADDRH (msg_ext_3)(0x80000000 | ((size_t) (&((struct scripth *)0)->msg_ext_3 ))), | |||||
3238 | SCR_JUMP0x80080000 ^ IFFALSE (DATA (2))(0x00080000 | ((0x00040000 | ((2) & 0xff)))), | |||||
3239 | PADDR (msg_bad)(0x50000000 | ((size_t) (&((struct script *)0)->msg_bad ))), | |||||
3240 | }/*-------------------------< MSG_EXT_2 >----------------*/,{ | |||||
3241 | SCR_CLR (SCR_ACK)(0x60000000 | (0x00000040)), | |||||
3242 | 0, | |||||
3243 | SCR_JUMP0x80080000 ^ IFFALSE (WHEN (SCR_MSG_IN))(0x00080000 | ((0x00030000 | (0x07000000)))), | |||||
3244 | PADDR (dispatch)(0x50000000 | ((size_t) (&((struct script *)0)->dispatch ))), | |||||
3245 | /* | |||||
3246 | ** get extended message code. | |||||
3247 | */ | |||||
3248 | SCR_MOVE_ABS (1)((0x08000000 ^ (0 << 1ul)) | (1)) ^ SCR_MSG_IN0x07000000, | |||||
3249 | NADDR (msgin[2])(0x40000000 | ((size_t) (&((struct ncb *)0)->msgin[2]) )), | |||||
3250 | /* | |||||
3251 | ** Check for message parity error. | |||||
3252 | */ | |||||
3253 | SCR_TO_REG (scratcha)(0x68000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
3254 | 0, | |||||
3255 | SCR_FROM_REG (socl)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_socl )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
3256 | 0, | |||||
3257 | SCR_JUMP0x80080000 ^ IFTRUE (MASK (CATN, CATN))(0x00000000 | ((0x00040000 | (((0x08 ^ 0xff) & 0xff) << 8ul)|((0x08) & 0xff)))), | |||||
3258 | PADDRH (msg_parity)(0x80000000 | ((size_t) (&((struct scripth *)0)->msg_parity ))), | |||||
3259 | SCR_FROM_REG (scratcha)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
3260 | 0, | |||||
3261 | SCR_JUMP0x80080000 ^ IFTRUE (DATA (M_X_WIDE_REQ))(0x00000000 | ((0x00040000 | (((0x03)) & 0xff)))), | |||||
3262 | PADDRH (msg_wdtr)(0x80000000 | ((size_t) (&((struct scripth *)0)->msg_wdtr ))), | |||||
3263 | /* | |||||
3264 | ** unknown extended message | |||||
3265 | */ | |||||
3266 | SCR_JUMP0x80080000, | |||||
3267 | PADDR (msg_bad)(0x50000000 | ((size_t) (&((struct script *)0)->msg_bad ))) | |||||
3268 | }/*-------------------------< MSG_WDTR >-----------------*/,{ | |||||
3269 | SCR_CLR (SCR_ACK)(0x60000000 | (0x00000040)), | |||||
3270 | 0, | |||||
3271 | SCR_JUMP0x80080000 ^ IFFALSE (WHEN (SCR_MSG_IN))(0x00080000 | ((0x00030000 | (0x07000000)))), | |||||
3272 | PADDR (dispatch)(0x50000000 | ((size_t) (&((struct script *)0)->dispatch ))), | |||||
3273 | /* | |||||
3274 | ** get data bus width | |||||
3275 | */ | |||||
3276 | SCR_MOVE_ABS (1)((0x08000000 ^ (0 << 1ul)) | (1)) ^ SCR_MSG_IN0x07000000, | |||||
3277 | NADDR (msgin[3])(0x40000000 | ((size_t) (&((struct ncb *)0)->msgin[3]) )), | |||||
3278 | SCR_FROM_REG (socl)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_socl )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
3279 | 0, | |||||
3280 | SCR_JUMP0x80080000 ^ IFTRUE (MASK (CATN, CATN))(0x00000000 | ((0x00040000 | (((0x08 ^ 0xff) & 0xff) << 8ul)|((0x08) & 0xff)))), | |||||
3281 | PADDRH (msg_parity)(0x80000000 | ((size_t) (&((struct scripth *)0)->msg_parity ))), | |||||
3282 | /* | |||||
3283 | ** let the host do the real work. | |||||
3284 | */ | |||||
3285 | SCR_INT0x98080000, | |||||
3286 | SIR_NEGO_WIDE(6), | |||||
3287 | /* | |||||
3288 | ** let the target fetch our answer. | |||||
3289 | */ | |||||
3290 | SCR_SET (SCR_ATN)(0x58000000 | (0x00000008)), | |||||
3291 | 0, | |||||
3292 | SCR_CLR (SCR_ACK)(0x60000000 | (0x00000040)), | |||||
3293 | 0, | |||||
3294 | ||||||
3295 | SCR_INT0x98080000 ^ IFFALSE (WHEN (SCR_MSG_OUT))(0x00080000 | ((0x00030000 | (0x06000000)))), | |||||
3296 | SIR_NEGO_PROTO(8), | |||||
3297 | /* | |||||
3298 | ** Send the M_X_WIDE_REQ | |||||
3299 | */ | |||||
3300 | SCR_MOVE_ABS (4)((0x08000000 ^ (0 << 1ul)) | (4)) ^ SCR_MSG_OUT0x06000000, | |||||
3301 | NADDR (msgout)(0x40000000 | ((size_t) (&((struct ncb *)0)->msgout))), | |||||
3302 | SCR_CLR (SCR_ATN)(0x60000000 | (0x00000008)), | |||||
3303 | 0, | |||||
3304 | SCR_COPY (1)(0xc0000000 | 0x01000000 | (1)), | |||||
3305 | RADDR (sfbr)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_sfbr )))), | |||||
3306 | NADDR (lastmsg)(0x40000000 | ((size_t) (&((struct ncb *)0)->lastmsg)) ), | |||||
3307 | SCR_JUMP0x80080000, | |||||
3308 | PADDR (msg_out_done)(0x50000000 | ((size_t) (&((struct script *)0)->msg_out_done ))), | |||||
3309 | ||||||
3310 | }/*-------------------------< MSG_EXT_3 >----------------*/,{ | |||||
3311 | SCR_CLR (SCR_ACK)(0x60000000 | (0x00000040)), | |||||
3312 | 0, | |||||
3313 | SCR_JUMP0x80080000 ^ IFFALSE (WHEN (SCR_MSG_IN))(0x00080000 | ((0x00030000 | (0x07000000)))), | |||||
3314 | PADDR (dispatch)(0x50000000 | ((size_t) (&((struct script *)0)->dispatch ))), | |||||
3315 | /* | |||||
3316 | ** get extended message code. | |||||
3317 | */ | |||||
3318 | SCR_MOVE_ABS (1)((0x08000000 ^ (0 << 1ul)) | (1)) ^ SCR_MSG_IN0x07000000, | |||||
3319 | NADDR (msgin[2])(0x40000000 | ((size_t) (&((struct ncb *)0)->msgin[2]) )), | |||||
3320 | /* | |||||
3321 | ** Check for message parity error. | |||||
3322 | */ | |||||
3323 | SCR_TO_REG (scratcha)(0x68000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
3324 | 0, | |||||
3325 | SCR_FROM_REG (socl)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_socl )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
3326 | 0, | |||||
3327 | SCR_JUMP0x80080000 ^ IFTRUE (MASK (CATN, CATN))(0x00000000 | ((0x00040000 | (((0x08 ^ 0xff) & 0xff) << 8ul)|((0x08) & 0xff)))), | |||||
3328 | PADDRH (msg_parity)(0x80000000 | ((size_t) (&((struct scripth *)0)->msg_parity ))), | |||||
3329 | SCR_FROM_REG (scratcha)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
3330 | 0, | |||||
3331 | SCR_JUMP0x80080000 ^ IFTRUE (DATA (M_X_SYNC_REQ))(0x00000000 | ((0x00040000 | (((0x01)) & 0xff)))), | |||||
3332 | PADDRH (msg_sdtr)(0x80000000 | ((size_t) (&((struct scripth *)0)->msg_sdtr ))), | |||||
3333 | /* | |||||
3334 | ** unknown extended message | |||||
3335 | */ | |||||
3336 | SCR_JUMP0x80080000, | |||||
3337 | PADDR (msg_bad)(0x50000000 | ((size_t) (&((struct script *)0)->msg_bad ))) | |||||
3338 | ||||||
3339 | }/*-------------------------< MSG_SDTR >-----------------*/,{ | |||||
3340 | SCR_CLR (SCR_ACK)(0x60000000 | (0x00000040)), | |||||
3341 | 0, | |||||
3342 | SCR_JUMP0x80080000 ^ IFFALSE (WHEN (SCR_MSG_IN))(0x00080000 | ((0x00030000 | (0x07000000)))), | |||||
3343 | PADDR (dispatch)(0x50000000 | ((size_t) (&((struct script *)0)->dispatch ))), | |||||
3344 | /* | |||||
3345 | ** get period and offset | |||||
3346 | */ | |||||
3347 | SCR_MOVE_ABS (2)((0x08000000 ^ (0 << 1ul)) | (2)) ^ SCR_MSG_IN0x07000000, | |||||
3348 | NADDR (msgin[3])(0x40000000 | ((size_t) (&((struct ncb *)0)->msgin[3]) )), | |||||
3349 | SCR_FROM_REG (socl)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_socl )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
3350 | 0, | |||||
3351 | SCR_JUMP0x80080000 ^ IFTRUE (MASK (CATN, CATN))(0x00000000 | ((0x00040000 | (((0x08 ^ 0xff) & 0xff) << 8ul)|((0x08) & 0xff)))), | |||||
3352 | PADDRH (msg_parity)(0x80000000 | ((size_t) (&((struct scripth *)0)->msg_parity ))), | |||||
3353 | /* | |||||
3354 | ** let the host do the real work. | |||||
3355 | */ | |||||
3356 | SCR_INT0x98080000, | |||||
3357 | SIR_NEGO_SYNC(5), | |||||
3358 | /* | |||||
3359 | ** let the target fetch our answer. | |||||
3360 | */ | |||||
3361 | SCR_SET (SCR_ATN)(0x58000000 | (0x00000008)), | |||||
3362 | 0, | |||||
3363 | SCR_CLR (SCR_ACK)(0x60000000 | (0x00000040)), | |||||
3364 | 0, | |||||
3365 | ||||||
3366 | SCR_INT0x98080000 ^ IFFALSE (WHEN (SCR_MSG_OUT))(0x00080000 | ((0x00030000 | (0x06000000)))), | |||||
3367 | SIR_NEGO_PROTO(8), | |||||
3368 | /* | |||||
3369 | ** Send the M_X_SYNC_REQ | |||||
3370 | */ | |||||
3371 | SCR_MOVE_ABS (5)((0x08000000 ^ (0 << 1ul)) | (5)) ^ SCR_MSG_OUT0x06000000, | |||||
3372 | NADDR (msgout)(0x40000000 | ((size_t) (&((struct ncb *)0)->msgout))), | |||||
3373 | SCR_CLR (SCR_ATN)(0x60000000 | (0x00000008)), | |||||
3374 | 0, | |||||
3375 | SCR_COPY (1)(0xc0000000 | 0x01000000 | (1)), | |||||
3376 | RADDR (sfbr)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_sfbr )))), | |||||
3377 | NADDR (lastmsg)(0x40000000 | ((size_t) (&((struct ncb *)0)->lastmsg)) ), | |||||
3378 | SCR_JUMP0x80080000, | |||||
3379 | PADDR (msg_out_done)(0x50000000 | ((size_t) (&((struct script *)0)->msg_out_done ))), | |||||
3380 | ||||||
3381 | }/*-------------------------< MSG_OUT_ABORT >-------------*/,{ | |||||
3382 | /* | |||||
3383 | ** After ABORT message, | |||||
3384 | ** | |||||
3385 | ** expect an immediate disconnect, ... | |||||
3386 | */ | |||||
3387 | SCR_REG_REG (scntl2, SCR_AND, 0x7f)(0x78000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scntl2 )))) << 16ul)) | (0x04000000) | ((0x7f)<<8ul)), | |||||
3388 | 0, | |||||
3389 | SCR_CLR (SCR_ACK|SCR_ATN)(0x60000000 | (0x00000040|0x00000008)), | |||||
3390 | 0, | |||||
3391 | SCR_WAIT_DISC0x48000000, | |||||
3392 | 0, | |||||
3393 | /* | |||||
3394 | ** ... and set the status to "ABORTED" | |||||
3395 | */ | |||||
3396 | SCR_LOAD_REG (HS_REG, HS_ABORTED)(0x78000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scr1 )))) << 16ul)) | (0x00000000) | (((7))<<8ul)), | |||||
3397 | 0, | |||||
3398 | SCR_JUMP0x80080000, | |||||
3399 | PADDR (cleanup)(0x50000000 | ((size_t) (&((struct script *)0)->cleanup ))), | |||||
3400 | ||||||
3401 | }/*-------------------------< GETCC >-----------------------*/,{ | |||||
3402 | /* | |||||
3403 | ** The ncr doesn't have an indirect load | |||||
3404 | ** or store command. So we have to | |||||
3405 | ** copy part of the control block to a | |||||
3406 | ** fixed place, where we can modify it. | |||||
3407 | ** | |||||
3408 | ** We patch the address part of a COPY command | |||||
3409 | ** with the address of the dsa register ... | |||||
3410 | */ | |||||
3411 | SCR_COPY_F (4)(0xc0000000 | (4)), | |||||
3412 | RADDR (dsa)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_dsa )))), | |||||
3413 | PADDRH (getcc1)(0x80000000 | ((size_t) (&((struct scripth *)0)->getcc1 ))), | |||||
3414 | /* | |||||
3415 | ** ... then we do the actual copy. | |||||
3416 | */ | |||||
3417 | SCR_COPY (sizeof (struct head))(0xc0000000 | 0x01000000 | (sizeof (struct head))), | |||||
3418 | }/*-------------------------< GETCC1 >----------------------*/,{ | |||||
3419 | 0, | |||||
3420 | NADDR (header)(0x40000000 | ((size_t) (&((struct ncb *)0)->header))), | |||||
3421 | /* | |||||
3422 | ** Initialize the status registers | |||||
3423 | */ | |||||
3424 | SCR_COPY (4)(0xc0000000 | 0x01000000 | (4)), | |||||
3425 | NADDR (header.status)(0x40000000 | ((size_t) (&((struct ncb *)0)->header.status ))), | |||||
3426 | RADDR (scr0)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_scr0 )))), | |||||
3427 | }/*-------------------------< GETCC2 >----------------------*/,{ | |||||
3428 | /* | |||||
3429 | ** Get the condition code from a target. | |||||
3430 | ** | |||||
3431 | ** DSA points to a data structure. | |||||
3432 | ** Set TEMP to the script location | |||||
3433 | ** that receives the condition code. | |||||
3434 | ** | |||||
3435 | ** Because there is no script command | |||||
3436 | ** to load a longword into a register, | |||||
3437 | ** we use a CALL command. | |||||
3438 | */ | |||||
3439 | /*<<<*/ SCR_CALLR0x88880000, | |||||
3440 | 24, | |||||
3441 | /* | |||||
3442 | ** Get the condition code. | |||||
3443 | */ | |||||
3444 | SCR_MOVE_TBL(0x18000000 ^ (0 << 1ul)) ^ SCR_DATA_IN0x01000000, | |||||
3445 | offsetof (struct dsb, sense)((size_t) (&((struct dsb *)0)->sense)), | |||||
3446 | /* | |||||
3447 | ** No data phase may follow! | |||||
3448 | */ | |||||
3449 | SCR_CALL0x88080000, | |||||
3450 | PADDR (checkatn)(0x50000000 | ((size_t) (&((struct script *)0)->checkatn ))), | |||||
3451 | SCR_JUMP0x80080000, | |||||
3452 | PADDR (no_data)(0x50000000 | ((size_t) (&((struct script *)0)->no_data ))), | |||||
3453 | /*>>>*/ | |||||
3454 | ||||||
3455 | /* | |||||
3456 | ** The CALL jumps to this point. | |||||
3457 | ** Prepare for a RESTORE_POINTER message. | |||||
3458 | ** Save the TEMP register into the saved pointer. | |||||
3459 | */ | |||||
3460 | SCR_COPY (4)(0xc0000000 | 0x01000000 | (4)), | |||||
3461 | RADDR (temp)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_temp )))), | |||||
3462 | NADDR (header.savep)(0x40000000 | ((size_t) (&((struct ncb *)0)->header.savep ))), | |||||
3463 | /* | |||||
3464 | ** Load scratcha, because in case of a selection timeout, | |||||
3465 | ** the host will expect a new value for startpos in | |||||
3466 | ** the scratcha register. | |||||
3467 | */ | |||||
3468 | SCR_COPY (4)(0xc0000000 | 0x01000000 | (4)), | |||||
3469 | PADDR (startpos)(0x50000000 | ((size_t) (&((struct script *)0)->startpos ))), | |||||
3470 | RADDR (scratcha)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))), | |||||
3471 | #ifdef NCR_GETCC_WITHMSG | |||||
3472 | /* | |||||
3473 | ** If QUIRK_NOMSG is set, select without ATN. | |||||
3474 | ** and don't send a message. | |||||
3475 | */ | |||||
3476 | SCR_FROM_REG (QU_REG)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scr0 )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
3477 | 0, | |||||
3478 | SCR_JUMP0x80080000 ^ IFTRUE (MASK (QUIRK_NOMSG, QUIRK_NOMSG))(0x00000000 | ((0x00040000 | ((((0x02) ^ 0xff) & 0xff) << 8ul)|(((0x02)) & 0xff)))), | |||||
3479 | PADDRH(getcc3)(0x80000000 | ((size_t) (&((struct scripth *)0)->getcc3 ))), | |||||
3480 | /* | |||||
3481 | ** Then try to connect to the target. | |||||
3482 | ** If we are reselected, special treatment | |||||
3483 | ** of the current job is required before | |||||
3484 | ** accepting the reselection. | |||||
3485 | */ | |||||
3486 | SCR_SEL_TBL_ATN0x43000000 ^ offsetof (struct dsb, select)((size_t) (&((struct dsb *)0)->select)), | |||||
3487 | PADDR(badgetcc)(0x50000000 | ((size_t) (&((struct script *)0)->badgetcc ))), | |||||
3488 | /* | |||||
3489 | ** save target id. | |||||
3490 | */ | |||||
3491 | SCR_FROM_REG (sdid)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_sdid )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
3492 | 0, | |||||
3493 | SCR_TO_REG (ctest0)(0x68000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_ctest0 )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
3494 | 0, | |||||
3495 | /* | |||||
3496 | ** Send the IDENTIFY message. | |||||
3497 | ** In case of short transfer, remove ATN. | |||||
3498 | */ | |||||
3499 | SCR_MOVE_TBL(0x18000000 ^ (0 << 1ul)) ^ SCR_MSG_OUT0x06000000, | |||||
3500 | offsetof (struct dsb, smsg2)((size_t) (&((struct dsb *)0)->smsg2)), | |||||
3501 | SCR_CLR (SCR_ATN)(0x60000000 | (0x00000008)), | |||||
3502 | 0, | |||||
3503 | /* | |||||
3504 | ** save the first byte of the message. | |||||
3505 | */ | |||||
3506 | SCR_COPY (1)(0xc0000000 | 0x01000000 | (1)), | |||||
3507 | RADDR (sfbr)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_sfbr )))), | |||||
3508 | NADDR (lastmsg)(0x40000000 | ((size_t) (&((struct ncb *)0)->lastmsg)) ), | |||||
3509 | SCR_JUMP0x80080000, | |||||
3510 | PADDR (prepare2)(0x50000000 | ((size_t) (&((struct script *)0)->prepare2 ))), | |||||
3511 | ||||||
3512 | #endif | |||||
3513 | }/*-------------------------< GETCC3 >----------------------*/,{ | |||||
3514 | /* | |||||
3515 | ** Try to connect to the target. | |||||
3516 | ** If we are reselected, special treatment | |||||
3517 | ** of the current job is required before | |||||
3518 | ** accepting the reselection. | |||||
3519 | ** | |||||
3520 | ** Silly target won't accept a message. | |||||
3521 | ** Select without ATN. | |||||
3522 | */ | |||||
3523 | SCR_SEL_TBL0x42000000 ^ offsetof (struct dsb, select)((size_t) (&((struct dsb *)0)->select)), | |||||
3524 | PADDR(badgetcc)(0x50000000 | ((size_t) (&((struct script *)0)->badgetcc ))), | |||||
3525 | /* | |||||
3526 | ** save target id. | |||||
3527 | */ | |||||
3528 | SCR_FROM_REG (sdid)(0x70000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_sdid )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
3529 | 0, | |||||
3530 | SCR_TO_REG (ctest0)(0x68000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_ctest0 )))) << 16ul)) | (0x02000000) | ((0)<<8ul)), | |||||
3531 | 0, | |||||
3532 | /* | |||||
3533 | ** Force error if selection timeout | |||||
3534 | */ | |||||
3535 | SCR_JUMPR0x80880000 ^ IFTRUE (WHEN (SCR_MSG_IN))(0x00000000 | ((0x00030000 | (0x07000000)))), | |||||
3536 | 0, | |||||
3537 | /* | |||||
3538 | ** don't negotiate. | |||||
3539 | */ | |||||
3540 | SCR_JUMP0x80080000, | |||||
3541 | PADDR (prepare2)(0x50000000 | ((size_t) (&((struct script *)0)->prepare2 ))), | |||||
3542 | ||||||
3543 | }/*-------------------------< DATA_OUT >-------------------*/,{ | |||||
3544 | /* | |||||
3545 | ** Because the size depends on the | |||||
3546 | ** #define MAX_SCATTER parameter, | |||||
3547 | ** it is filled in at runtime. | |||||
3548 | ** | |||||
3549 | ** ##===========< i=0; i<MAX_SCATTER >========= | |||||
3550 | ** || SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_OUT)), | |||||
3551 | ** || PADDR (dispatch), | |||||
3552 | ** || SCR_MOVE_TBL ^ SCR_DATA_OUT, | |||||
3553 | ** || offsetof (struct dsb, data[ i]), | |||||
3554 | ** ##========================================== | |||||
3555 | ** | |||||
3556 | ** SCR_CALL, | |||||
3557 | ** PADDR (dispatch), | |||||
3558 | ** SCR_JUMP, | |||||
3559 | ** PADDR (no_data), | |||||
3560 | ** | |||||
3561 | **--------------------------------------------------------- | |||||
3562 | */ | |||||
3563 | 0 | |||||
3564 | }/*-------------------------< ABORTTAG >-------------------*/,{ | |||||
3565 | /* | |||||
3566 | ** Abort a bad reselection. | |||||
3567 | ** Set the message to ABORT vs. ABORT_TAG | |||||
3568 | */ | |||||
3569 | SCR_LOAD_REG (scratcha, M_ABORT_TAG)(0x78000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))) << 16ul)) | (0x00000000) | (((0x0d))<<8ul)), | |||||
3570 | 0, | |||||
3571 | SCR_JUMPR0x80880000 ^ IFFALSE (CARRYSET)(0x00080000 | ((0x00200000))), | |||||
3572 | 8, | |||||
3573 | }/*-------------------------< ABORT >----------------------*/,{ | |||||
3574 | SCR_LOAD_REG (scratcha, M_ABORT)(0x78000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))) << 16ul)) | (0x00000000) | (((0x06))<<8ul)), | |||||
3575 | 0, | |||||
3576 | SCR_COPY (1)(0xc0000000 | 0x01000000 | (1)), | |||||
3577 | RADDR (scratcha)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))), | |||||
3578 | NADDR (msgout)(0x40000000 | ((size_t) (&((struct ncb *)0)->msgout))), | |||||
3579 | SCR_SET (SCR_ATN)(0x58000000 | (0x00000008)), | |||||
3580 | 0, | |||||
3581 | SCR_CLR (SCR_ACK)(0x60000000 | (0x00000040)), | |||||
3582 | 0, | |||||
3583 | /* | |||||
3584 | ** and send it. | |||||
3585 | ** we expect an immediate disconnect | |||||
3586 | */ | |||||
3587 | SCR_REG_REG (scntl2, SCR_AND, 0x7f)(0x78000000 | ((((((size_t) (&((struct ncr_reg *)0)->nc_scntl2 )))) << 16ul)) | (0x04000000) | ((0x7f)<<8ul)), | |||||
3588 | 0, | |||||
3589 | SCR_MOVE_ABS (1)((0x08000000 ^ (0 << 1ul)) | (1)) ^ SCR_MSG_OUT0x06000000, | |||||
3590 | NADDR (msgout)(0x40000000 | ((size_t) (&((struct ncb *)0)->msgout))), | |||||
3591 | SCR_COPY (1)(0xc0000000 | 0x01000000 | (1)), | |||||
3592 | RADDR (sfbr)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_sfbr )))), | |||||
3593 | NADDR (lastmsg)(0x40000000 | ((size_t) (&((struct ncb *)0)->lastmsg)) ), | |||||
3594 | SCR_CLR (SCR_ACK|SCR_ATN)(0x60000000 | (0x00000040|0x00000008)), | |||||
3595 | 0, | |||||
3596 | SCR_WAIT_DISC0x48000000, | |||||
3597 | 0, | |||||
3598 | SCR_JUMP0x80080000, | |||||
3599 | PADDR (start)(0x50000000 | ((size_t) (&((struct script *)0)->start) )), | |||||
3600 | }/*-------------------------< SNOOPTEST >-------------------*/,{ | |||||
3601 | /* | |||||
3602 | ** Read the variable. | |||||
3603 | */ | |||||
3604 | SCR_COPY (4)(0xc0000000 | 0x01000000 | (4)), | |||||
3605 | NADDR(ncr_cache)(0x40000000 | ((size_t) (&((struct ncb *)0)->ncr_cache ))), | |||||
3606 | RADDR (scratcha)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_scratcha )))), | |||||
3607 | /* | |||||
3608 | ** Write the variable. | |||||
3609 | */ | |||||
3610 | SCR_COPY (4)(0xc0000000 | 0x01000000 | (4)), | |||||
3611 | RADDR (temp)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_temp )))), | |||||
3612 | NADDR(ncr_cache)(0x40000000 | ((size_t) (&((struct ncb *)0)->ncr_cache ))), | |||||
3613 | /* | |||||
3614 | ** Read back the variable. | |||||
3615 | */ | |||||
3616 | SCR_COPY (4)(0xc0000000 | 0x01000000 | (4)), | |||||
3617 | NADDR(ncr_cache)(0x40000000 | ((size_t) (&((struct ncb *)0)->ncr_cache ))), | |||||
3618 | RADDR (temp)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_temp )))), | |||||
3619 | }/*-------------------------< SNOOPEND >-------------------*/,{ | |||||
3620 | /* | |||||
3621 | ** And stop. | |||||
3622 | */ | |||||
3623 | SCR_INT0x98080000, | |||||
3624 | 99, | |||||
3625 | }/*--------------------------------------------------------*/ | |||||
3626 | }; | |||||
3627 | ||||||
3628 | /*========================================================== | |||||
3629 | ** | |||||
3630 | ** | |||||
3631 | ** Fill in #define dependent parts of the script | |||||
3632 | ** | |||||
3633 | ** | |||||
3634 | **========================================================== | |||||
3635 | */ | |||||
3636 | ||||||
3637 | __initfunc(void ncr_script_fill (struct script * scr, struct scripth * scrh ) | |||||
3638 | void ncr_script_fill (struct script * scr, struct scripth * scrh)void ncr_script_fill (struct script * scr, struct scripth * scrh ) | |||||
3639 | )void ncr_script_fill (struct script * scr, struct scripth * scrh ) | |||||
3640 | { | |||||
3641 | int i; | |||||
3642 | ncrcmd *p; | |||||
3643 | ||||||
3644 | p = scrh->tryloop; | |||||
3645 | for (i=0; i<MAX_START((7*(4)) + 4); i++) { | |||||
3646 | *p++ =SCR_COPY (4)(0xc0000000 | 0x01000000 | (4)); | |||||
3647 | *p++ =NADDR (squeue[i])(0x40000000 | ((size_t) (&((struct ncb *)0)->squeue[i] ))); | |||||
3648 | *p++ =RADDR (dsa)(0x60000000 | (((size_t) (&((struct ncr_reg *)0)->nc_dsa )))); | |||||
3649 | *p++ =SCR_CALL0x88080000; | |||||
3650 | *p++ =PADDR (trysel)(0x50000000 | ((size_t) (&((struct script *)0)->trysel ))); | |||||
3651 | }; | |||||
3652 | *p++ =SCR_JUMP0x80080000; | |||||
3653 | *p++ =PADDRH(tryloop)(0x80000000 | ((size_t) (&((struct scripth *)0)->tryloop ))); | |||||
3654 | ||||||
3655 | assert ((u_long)p == (u_long)&scrh->tryloop + sizeof (scrh->tryloop)){ if (!((unsigned long)p == (unsigned long)&scrh->tryloop + sizeof (scrh->tryloop))) { (void)printk( "assertion \"%s\" failed: file \"%s\", line %d\n" , "(u_long)p == (u_long)&scrh->tryloop + sizeof (scrh->tryloop)" , "../linux/src/drivers/scsi/ncr53c8xx.c", 3655); } }; | |||||
3656 | ||||||
3657 | p = scr->data_in; | |||||
3658 | ||||||
3659 | for (i=0; i<MAX_SCATTER((127)); i++) { | |||||
3660 | *p++ =SCR_CALL0x88080000 ^ IFFALSE (WHEN (SCR_DATA_IN))(0x00080000 | ((0x00030000 | (0x01000000)))); | |||||
3661 | *p++ =PADDR (checkatn)(0x50000000 | ((size_t) (&((struct script *)0)->checkatn ))); | |||||
3662 | *p++ =SCR_MOVE_TBL(0x18000000 ^ (0 << 1ul)) ^ SCR_DATA_IN0x01000000; | |||||
3663 | *p++ =offsetof (struct dsb, data[i])((size_t) (&((struct dsb *)0)->data[i])); | |||||
3664 | }; | |||||
3665 | ||||||
3666 | *p++ =SCR_CALL0x88080000; | |||||
3667 | *p++ =PADDR (checkatn)(0x50000000 | ((size_t) (&((struct script *)0)->checkatn ))); | |||||
3668 | *p++ =SCR_JUMP0x80080000; | |||||
3669 | *p++ =PADDR (no_data)(0x50000000 | ((size_t) (&((struct script *)0)->no_data ))); | |||||
3670 | ||||||
3671 | assert ((u_long)p == (u_long)&scr->data_in + sizeof (scr->data_in)){ if (!((unsigned long)p == (unsigned long)&scr->data_in + sizeof (scr->data_in))) { (void)printk( "assertion \"%s\" failed: file \"%s\", line %d\n" , "(u_long)p == (u_long)&scr->data_in + sizeof (scr->data_in)" , "../linux/src/drivers/scsi/ncr53c8xx.c", 3671); } }; | |||||
3672 | ||||||
3673 | p = scrh->data_out; | |||||
3674 | ||||||
3675 | for (i=0; i<MAX_SCATTER((127)); i++) { | |||||
3676 | *p++ =SCR_CALL0x88080000 ^ IFFALSE (WHEN (SCR_DATA_OUT))(0x00080000 | ((0x00030000 | (0x00000000)))); | |||||
3677 | *p++ =PADDR (dispatch)(0x50000000 | ((size_t) (&((struct script *)0)->dispatch ))); | |||||
3678 | *p++ =SCR_MOVE_TBL(0x18000000 ^ (0 << 1ul)) ^ SCR_DATA_OUT0x00000000; | |||||
3679 | *p++ =offsetof (struct dsb, data[i])((size_t) (&((struct dsb *)0)->data[i])); | |||||
3680 | }; | |||||
3681 | ||||||
3682 | *p++ =SCR_CALL0x88080000; | |||||
3683 | *p++ =PADDR (dispatch)(0x50000000 | ((size_t) (&((struct script *)0)->dispatch ))); | |||||
3684 | *p++ =SCR_JUMP0x80080000; | |||||
3685 | *p++ =PADDR (no_data)(0x50000000 | ((size_t) (&((struct script *)0)->no_data ))); | |||||
3686 | ||||||
3687 | assert ((u_long)p == (u_long)&scrh->data_out + sizeof (scrh->data_out)){ if (!((unsigned long)p == (unsigned long)&scrh->data_out + sizeof (scrh->data_out))) { (void)printk( "assertion \"%s\" failed: file \"%s\", line %d\n" , "(u_long)p == (u_long)&scrh->data_out + sizeof (scrh->data_out)" , "../linux/src/drivers/scsi/ncr53c8xx.c", 3687); } }; | |||||
3688 | } | |||||
3689 | ||||||
3690 | /*========================================================== | |||||
3691 | ** | |||||
3692 | ** | |||||
3693 | ** Copy and rebind a script. | |||||
3694 | ** | |||||
3695 | ** | |||||
3696 | **========================================================== | |||||
3697 | */ | |||||
3698 | ||||||
3699 | __initfunc(static void ncr_script_copy_and_bind (ncb_p np, ncrcmd *src, ncrcmd *dst, int len) | |||||
3700 | static void ncr_script_copy_and_bind (ncb_p np, ncrcmd *src, ncrcmd *dst, int len)static void ncr_script_copy_and_bind (ncb_p np, ncrcmd *src, ncrcmd *dst, int len) | |||||
3701 | )static void ncr_script_copy_and_bind (ncb_p np, ncrcmd *src, ncrcmd *dst, int len) | |||||
3702 | { | |||||
3703 | ncrcmd opcode, new, old, tmp1, tmp2; | |||||
3704 | ncrcmd *start, *end; | |||||
3705 | int relocs; | |||||
3706 | int opchanged = 0; | |||||
3707 | ||||||
3708 | start = src; | |||||
3709 | end = src + len/4; | |||||
3710 | ||||||
3711 | while (src < end) { | |||||
3712 | ||||||
3713 | opcode = *src++; | |||||
3714 | *dst++ = cpu_to_scr(opcode)(opcode); | |||||
3715 | ||||||
3716 | /* | |||||
3717 | ** If we forget to change the length | |||||
3718 | ** in struct script, a field will be | |||||
3719 | ** padded with 0. This is an illegal | |||||
3720 | ** command. | |||||
3721 | */ | |||||
3722 | ||||||
3723 | if (opcode == 0) { | |||||
3724 | printfprintk ("%s: ERROR0 IN SCRIPT at %d.\n", | |||||
3725 | ncr_name(np), (int) (src-start-1)); | |||||
3726 | DELAY (1000000); | |||||
3727 | }; | |||||
3728 | ||||||
3729 | if (DEBUG_FLAGSncr_debug & DEBUG_SCRIPT(0x0040)) | |||||
3730 | printfprintk ("%p: <%x>\n", | |||||
3731 | (src-1), (unsigned)opcode); | |||||
3732 | ||||||
3733 | /* | |||||
3734 | ** We don't have to decode ALL commands | |||||
3735 | */ | |||||
3736 | switch (opcode >> 28) { | |||||
3737 | ||||||
3738 | case 0xc: | |||||
3739 | /* | |||||
3740 | ** COPY has TWO arguments. | |||||
3741 | */ | |||||
3742 | relocs = 2; | |||||
3743 | tmp1 = src[0]; | |||||
3744 | if ((tmp1 & RELOC_MASK0xf0000000) == RELOC_KVAR0x70000000) | |||||
3745 | tmp1 = 0; | |||||
3746 | tmp2 = src[1]; | |||||
3747 | if ((tmp2 & RELOC_MASK0xf0000000) == RELOC_KVAR0x70000000) | |||||
3748 | tmp2 = 0; | |||||
3749 | if ((tmp1 ^ tmp2) & 3) { | |||||
3750 | printfprintk ("%s: ERROR1 IN SCRIPT at %d.\n", | |||||
3751 | ncr_name(np), (int) (src-start-1)); | |||||
3752 | DELAY (1000000); | |||||
3753 | } | |||||
3754 | /* | |||||
3755 | ** If PREFETCH feature not enabled, remove | |||||
3756 | ** the NO FLUSH bit if present. | |||||
3757 | */ | |||||
3758 | if ((opcode & SCR_NO_FLUSH0x01000000) && !(np->features & FE_PFEN(1<<12))) { | |||||
3759 | dst[-1] = cpu_to_scr(opcode & ~SCR_NO_FLUSH)(opcode & ~0x01000000); | |||||
3760 | ++opchanged; | |||||
3761 | } | |||||
3762 | break; | |||||
3763 | ||||||
3764 | case 0x0: | |||||
3765 | /* | |||||
3766 | ** MOVE (absolute address) | |||||
3767 | */ | |||||
3768 | relocs = 1; | |||||
3769 | break; | |||||
3770 | ||||||
3771 | case 0x8: | |||||
3772 | /* | |||||
3773 | ** JUMP / CALL | |||||
3774 | ** don't relocate if relative :-) | |||||
3775 | */ | |||||
3776 | if (opcode & 0x00800000) | |||||
3777 | relocs = 0; | |||||
3778 | else | |||||
3779 | relocs = 1; | |||||
3780 | break; | |||||
3781 | ||||||
3782 | case 0x4: | |||||
3783 | case 0x5: | |||||
3784 | case 0x6: | |||||
3785 | case 0x7: | |||||
3786 | relocs = 1; | |||||
3787 | break; | |||||
3788 | ||||||
3789 | default: | |||||
3790 | relocs = 0; | |||||
3791 | break; | |||||
3792 | }; | |||||
3793 | ||||||
3794 | if (relocs) { | |||||
3795 | while (relocs--) { | |||||
3796 | old = *src++; | |||||
3797 | ||||||
3798 | switch (old & RELOC_MASK0xf0000000) { | |||||
3799 | case RELOC_REGISTER0x60000000: | |||||
3800 | new = (old & ~RELOC_MASK0xf0000000) + np->paddr; | |||||
3801 | break; | |||||
3802 | case RELOC_LABEL0x50000000: | |||||
3803 | new = (old & ~RELOC_MASK0xf0000000) + np->p_script; | |||||
3804 | break; | |||||
3805 | case RELOC_LABELH0x80000000: | |||||
3806 | new = (old & ~RELOC_MASK0xf0000000) + np->p_scripth; | |||||
3807 | break; | |||||
3808 | case RELOC_SOFTC0x40000000: | |||||
3809 | new = (old & ~RELOC_MASK0xf0000000) + vtophys(np)virt_to_phys(np); | |||||
3810 | break; | |||||
3811 | case RELOC_KVAR0x70000000: | |||||
3812 | if (((old & ~RELOC_MASK0xf0000000) < | |||||
3813 | SCRIPT_KVAR_FIRST(0)) || | |||||
3814 | ((old & ~RELOC_MASK0xf0000000) > | |||||
3815 | SCRIPT_KVAR_LAST(0))) | |||||
3816 | panic("ncr KVAR out of range"); | |||||
3817 | new = vtophys(script_kvars[old &virt_to_phys(script_kvars[old & ~0xf0000000]) | |||||
3818 | ~RELOC_MASK])virt_to_phys(script_kvars[old & ~0xf0000000]); | |||||
3819 | break; | |||||
3820 | case 0: | |||||
3821 | /* Don't relocate a 0 address. */ | |||||
3822 | if (old == 0) { | |||||
3823 | new = old; | |||||
3824 | break; | |||||
3825 | } | |||||
3826 | /* fall through */ | |||||
3827 | default: | |||||
3828 | panic("ncr_script_copy_and_bind: weird relocation %x\n", old); | |||||
3829 | break; | |||||
3830 | } | |||||
3831 | ||||||
3832 | *dst++ = cpu_to_scr(new)(new); | |||||
3833 | } | |||||
3834 | } else | |||||
3835 | *dst++ = cpu_to_scr(*src++)(*src++); | |||||
3836 | ||||||
3837 | }; | |||||
3838 | if (bootverbose(np->verbose) > 1 && opchanged) | |||||
3839 | printfprintk("%s: NO FLUSH bit removed from %d script instructions\n", | |||||
3840 | ncr_name(np), opchanged); | |||||
3841 | } | |||||
3842 | ||||||
3843 | /*========================================================== | |||||
3844 | ** | |||||
3845 | ** | |||||
3846 | ** Auto configuration: attach and init a host adapter. | |||||
3847 | ** | |||||
3848 | ** | |||||
3849 | **========================================================== | |||||
3850 | */ | |||||
3851 | ||||||
3852 | /* | |||||
3853 | ** Linux host data structure | |||||
3854 | ** | |||||
3855 | ** The script area is allocated in the host data structure | |||||
3856 | ** because kmalloc() returns NULL during scsi initialisations | |||||
3857 | ** with Linux 1.2.X | |||||
3858 | */ | |||||
3859 | ||||||
3860 | struct host_data { | |||||
3861 | struct ncb *ncb; | |||||
3862 | ||||||
3863 | char ncb_align[NCB_ALIGN_SIZE(1UL << 5)-1]; /* Filler for alignment */ | |||||
3864 | struct ncb _ncb_data; | |||||
3865 | ||||||
3866 | char ccb_align[CCB_ALIGN_SIZE(1UL << 5)-1]; /* Filler for alignment */ | |||||
3867 | struct ccb _ccb_data; | |||||
3868 | ||||||
3869 | char scr_align[SCR_ALIGN_SIZE(1UL << 5)-1]; /* Filler for alignment */ | |||||
3870 | struct script script_data; | |||||
3871 | ||||||
3872 | struct scripth scripth_data; | |||||
3873 | }; | |||||
3874 | ||||||
3875 | /* | |||||
3876 | ** Print something which allow to retrieve the controler type, unit, | |||||
3877 | ** target, lun concerned by a kernel message. | |||||
3878 | */ | |||||
3879 | ||||||
3880 | #define PRINT_LUN(np, target, lun)printk("<6>" "%s-<%d,%d>: ", ncr_name(np), (int) ( target), (int) (lun)) \printk | |||||
3881 | printfprintk(KERN_INFO"<6>" "%s-<%d,%d>: ", ncr_name(np), (int) (target), (int) (lun)) | |||||
3882 | ||||||
3883 | static void PRINT_ADDR(Scsi_Cmnd *cmd) | |||||
3884 | { | |||||
3885 | struct host_data *host_data = (struct host_data *) cmd->host->hostdata; | |||||
3886 | ncb_p np = host_data->ncb; | |||||
3887 | if (np) PRINT_LUN(np, cmd->target, cmd->lun)printk("<6>" "%s-<%d,%d>: ", ncr_name(np), (int) ( cmd->target), (int) (cmd->lun)); | |||||
3888 | } | |||||
3889 | ||||||
3890 | /*========================================================== | |||||
3891 | ** | |||||
3892 | ** NCR chip clock divisor table. | |||||
3893 | ** Divisors are multiplied by 10,000,000 in order to make | |||||
3894 | ** calculations more simple. | |||||
3895 | ** | |||||
3896 | **========================================================== | |||||
3897 | */ | |||||
3898 | ||||||
3899 | #define _5M5000000 5000000 | |||||
3900 | static u_longunsigned long div_10M[] = | |||||
3901 | {2*_5M5000000, 3*_5M5000000, 4*_5M5000000, 6*_5M5000000, 8*_5M5000000, 12*_5M5000000, 16*_5M5000000}; | |||||
3902 | ||||||
3903 | ||||||
3904 | /*=============================================================== | |||||
3905 | ** | |||||
3906 | ** Prepare io register values used by ncr_init() according | |||||
3907 | ** to selected and supported features. | |||||
3908 | ** | |||||
3909 | ** NCR chips allow burst lengths of 2, 4, 8, 16, 32, 64, 128 | |||||
3910 | ** transfers. 32,64,128 are only supported by 875 and 895 chips. | |||||
3911 | ** We use log base 2 (burst length) as internal code, with | |||||
3912 | ** value 0 meaning "burst disabled". | |||||
3913 | ** | |||||
3914 | **=============================================================== | |||||
3915 | */ | |||||
3916 | ||||||
3917 | /* | |||||
3918 | * Burst length from burst code. | |||||
3919 | */ | |||||
3920 | #define burst_length(bc)(!(bc))? 0 : 1 << (bc) (!(bc))? 0 : 1 << (bc) | |||||
3921 | ||||||
3922 | /* | |||||
3923 | * Burst code from io register bits. | |||||
3924 | */ | |||||
3925 | #define burst_code(dmode, ctest4, ctest5)(ctest4) & 0x80? 0 : (((dmode) & 0xc0) >> 6) + ( (ctest5) & 0x04) + 1 \ | |||||
3926 | (ctest4) & 0x80? 0 : (((dmode) & 0xc0) >> 6) + ((ctest5) & 0x04) + 1 | |||||
3927 | ||||||
3928 | /* | |||||
3929 | * Set initial io register bits from burst code. | |||||
3930 | */ | |||||
3931 | static inlineinline __attribute__((always_inline)) void ncr_init_burst(ncb_p np, u_charunsigned char bc) | |||||
3932 | { | |||||
3933 | np->rv_ctest4 &= ~0x80; | |||||
3934 | np->rv_dmode &= ~(0x3 << 6); | |||||
3935 | np->rv_ctest5 &= ~0x4; | |||||
3936 | ||||||
3937 | if (!bc) { | |||||
3938 | np->rv_ctest4 |= 0x80; | |||||
3939 | } | |||||
3940 | else { | |||||
3941 | --bc; | |||||
3942 | np->rv_dmode |= ((bc & 0x3) << 6); | |||||
3943 | np->rv_ctest5 |= (bc & 0x4); | |||||
3944 | } | |||||
3945 | } | |||||
3946 | ||||||
3947 | #ifdef SCSI_NCR_NVRAM_SUPPORT | |||||
3948 | ||||||
3949 | /* | |||||
3950 | ** Get target set-up from Symbios format NVRAM. | |||||
3951 | */ | |||||
3952 | ||||||
3953 | __initfunc(static void ncr_Symbios_setup_target(ncb_p np, int target, Symbios_nvram *nvram) | |||||
3954 | static voidstatic void ncr_Symbios_setup_target(ncb_p np, int target, Symbios_nvram *nvram) | |||||
3955 | ncr_Symbios_setup_target(ncb_p np, int target, Symbios_nvram *nvram)static void ncr_Symbios_setup_target(ncb_p np, int target, Symbios_nvram *nvram) | |||||
3956 | )static void ncr_Symbios_setup_target(ncb_p np, int target, Symbios_nvram *nvram) | |||||
3957 | { | |||||
3958 | tcb_p tp = &np->target[target]; | |||||
3959 | Symbios_target *tn = &nvram->target[target]; | |||||
3960 | ||||||
3961 | tp->usrsync = tn->sync_period ? (tn->sync_period + 3) / 4 : 255; | |||||
3962 | tp->usrwide = tn->bus_width == 0x10 ? 1 : 0; | |||||
3963 | tp->usrtags = | |||||
3964 | (tn->flags & SYMBIOS_QUEUE_TAGS_ENABLED)? SCSI_NCR_MAX_TAGS(4) : 0; | |||||
3965 | ||||||
3966 | if (!(tn->flags & SYMBIOS_DISCONNECT_ENABLE)) | |||||
3967 | tp->usrflag |= UF_NODISC(0x02); | |||||
3968 | if (!(tn->flags & SYMBIOS_SCAN_AT_BOOT_TIME)) | |||||
3969 | tp->usrflag |= UF_NOSCAN(0x04); | |||||
3970 | } | |||||
3971 | ||||||
3972 | /* | |||||
3973 | ** Get target set-up from Tekram format NVRAM. | |||||
3974 | */ | |||||
3975 | ||||||
3976 | __initfunc(static void ncr_Tekram_setup_target(ncb_p np, int target, Tekram_nvram *nvram) | |||||
3977 | static voidstatic void ncr_Tekram_setup_target(ncb_p np, int target, Tekram_nvram *nvram) | |||||
3978 | ncr_Tekram_setup_target(ncb_p np, int target, Tekram_nvram *nvram)static void ncr_Tekram_setup_target(ncb_p np, int target, Tekram_nvram *nvram) | |||||
3979 | )static void ncr_Tekram_setup_target(ncb_p np, int target, Tekram_nvram *nvram) | |||||
3980 | { | |||||
3981 | tcb_p tp = &np->target[target]; | |||||
3982 | struct Tekram_target *tn = &nvram->target[target]; | |||||
3983 | int i; | |||||
3984 | ||||||
3985 | if (tn->flags & TEKRAM_SYNC_NEGO) { | |||||
3986 | i = tn->sync_index & 0xf; | |||||
3987 | tp->usrsync = i < 12 ? Tekram_sync[i] : 255; | |||||
3988 | } | |||||
3989 | ||||||
3990 | tp->usrwide = (tn->flags & TEKRAM_WIDE_NEGO) ? 1 : 0; | |||||
3991 | ||||||
3992 | if (tn->flags & TEKRAM_TAGGED_COMMANDS) { | |||||
3993 | tp->usrtags = 2 << nvram->max_tags_index; | |||||
3994 | if (tp->usrtags > SCSI_NCR_MAX_TAGS(4)) | |||||
3995 | tp->usrtags = SCSI_NCR_MAX_TAGS(4); | |||||
3996 | } | |||||
3997 | ||||||
3998 | if (!(tn->flags & TEKRAM_DISCONNECT_ENABLE)) | |||||
3999 | tp->usrflag = UF_NODISC(0x02); | |||||
4000 | ||||||
4001 | /* If any device does not support parity, we will not use this option */ | |||||
4002 | if (!(tn->flags & TEKRAM_PARITY_CHECK)) | |||||
4003 | np->rv_scntl0 &= ~0x0a; /* SCSI parity checking disabled */ | |||||
4004 | } | |||||
4005 | #endif /* SCSI_NCR_NVRAM_SUPPORT */ | |||||
4006 | ||||||
4007 | __initfunc(static int ncr_prepare_setting(ncb_p np, ncr_nvram *nvram) | |||||
4008 | static int ncr_prepare_setting(ncb_p np, ncr_nvram *nvram)static int ncr_prepare_setting(ncb_p np, ncr_nvram *nvram) | |||||
4009 | )static int ncr_prepare_setting(ncb_p np, ncr_nvram *nvram) | |||||
4010 | { | |||||
4011 | u_charunsigned char burst_max; | |||||
4012 | u_longunsigned long period; | |||||
4013 | int i; | |||||
4014 | ||||||
4015 | /* | |||||
4016 | ** Save assumed BIOS setting | |||||
4017 | */ | |||||
4018 | ||||||
4019 | np->sv_scntl0 = INB(nc_scntl0)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_scntl0))))) & 0x0a; | |||||
4020 | np->sv_scntl3 = INB(nc_scntl3)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_scntl3))))) & 0x07; | |||||
4021 | np->sv_dmode = INB(nc_dmode)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_dmode))))) & 0xce; | |||||
4022 | np->sv_dcntl = INB(nc_dcntl)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_dcntl))))) & 0xa8; | |||||
4023 | np->sv_ctest3 = INB(nc_ctest3)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_ctest3))))) & 0x01; | |||||
4024 | np->sv_ctest4 = INB(nc_ctest4)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_ctest4))))) & 0x80; | |||||
4025 | np->sv_ctest5 = INB(nc_ctest5)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_ctest5))))) & 0x24; | |||||
4026 | np->sv_gpcntl = INB(nc_gpcntl)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_gpcntl))))); | |||||
4027 | np->sv_stest2 = INB(nc_stest2)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_stest2))))) & 0x20; | |||||
4028 | np->sv_stest4 = INB(nc_stest4)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_stest4))))); | |||||
4029 | ||||||
4030 | /* | |||||
4031 | ** Wide ? | |||||
4032 | */ | |||||
4033 | ||||||
4034 | np->maxwide = (np->features & FE_WIDE(1<<1))? 1 : 0; | |||||
4035 | ||||||
4036 | /* | |||||
4037 | ** Get the frequency of the chip's clock. | |||||
4038 | ** Find the right value for scntl3. | |||||
4039 | */ | |||||
4040 | ||||||
4041 | if (np->features & FE_QUAD(1<<5)) | |||||
4042 | np->multiplier = 4; | |||||
4043 | else if (np->features & FE_DBLR(1<<4)) | |||||
4044 | np->multiplier = 2; | |||||
4045 | else | |||||
4046 | np->multiplier = 1; | |||||
4047 | ||||||
4048 | np->clock_khz = (np->features & FE_CLK80(1<<15))? 80000 : 40000; | |||||
4049 | np->clock_khz *= np->multiplier; | |||||
4050 | ||||||
4051 | if (np->clock_khz != 40000) | |||||
4052 | ncr_getclock(np, np->multiplier); | |||||
4053 | ||||||
4054 | /* | |||||
4055 | * Divisor to be used for async (timer pre-scaler). | |||||
4056 | */ | |||||
4057 | i = np->clock_divn - 1; | |||||
4058 | while (i >= 0) { | |||||
4059 | --i; | |||||
4060 | if (10ul * SCSI_NCR_MIN_ASYNC(40) * np->clock_khz > div_10M[i]) { | |||||
4061 | ++i; | |||||
4062 | break; | |||||
4063 | } | |||||
4064 | } | |||||
4065 | np->rv_scntl3 = i+1; | |||||
4066 | ||||||
4067 | /* | |||||
4068 | * Minimum synchronous period factor supported by the chip. | |||||
4069 | * Btw, 'period' is in tenths of nanoseconds. | |||||
4070 | */ | |||||
4071 | ||||||
4072 | period = (4 * div_10M[0] + np->clock_khz - 1) / np->clock_khz; | |||||
4073 | if (period <= 250) np->minsync = 10; | |||||
4074 | else if (period <= 303) np->minsync = 11; | |||||
4075 | else if (period <= 500) np->minsync = 12; | |||||
4076 | else np->minsync = (period + 40 - 1) / 40; | |||||
4077 | ||||||
4078 | /* | |||||
4079 | * Check against chip SCSI standard support (SCSI-2,ULTRA,ULTRA2). | |||||
4080 | */ | |||||
4081 | ||||||
4082 | if (np->minsync < 25 && !(np->features & (FE_ULTRA(1<<2)|FE_ULTRA2(1<<3)))) | |||||
4083 | np->minsync = 25; | |||||
4084 | else if (np->minsync < 12 && !(np->features & FE_ULTRA2(1<<3))) | |||||
4085 | np->minsync = 12; | |||||
4086 | ||||||
4087 | /* | |||||
4088 | * Maximum synchronous period factor supported by the chip. | |||||
4089 | */ | |||||
4090 | ||||||
4091 | period = (11 * div_10M[np->clock_divn - 1]) / (4 * np->clock_khz); | |||||
4092 | np->maxsync = period > 2540 ? 254 : period / 10; | |||||
4093 | ||||||
4094 | /* | |||||
4095 | ** Prepare initial value of other IO registers | |||||
4096 | */ | |||||
4097 | #if defined SCSI_NCR_TRUST_BIOS_SETTING | |||||
4098 | np->rv_scntl0 = np->sv_scntl0; | |||||
4099 | np->rv_dmode = np->sv_dmode; | |||||
4100 | np->rv_dcntl = np->sv_dcntl; | |||||
4101 | np->rv_ctest3 = np->sv_ctest3; | |||||
4102 | np->rv_ctest4 = np->sv_ctest4; | |||||
4103 | np->rv_ctest5 = np->sv_ctest5; | |||||
4104 | burst_max = burst_code(np->sv_dmode, np->sv_ctest4, np->sv_ctest5)(np->sv_ctest4) & 0x80? 0 : (((np->sv_dmode) & 0xc0 ) >> 6) + ((np->sv_ctest5) & 0x04) + 1; | |||||
4105 | #else | |||||
4106 | ||||||
4107 | /* | |||||
4108 | ** Select burst length (dwords) | |||||
4109 | */ | |||||
4110 | burst_max = driver_setup.burst_max; | |||||
4111 | if (burst_max == 255) | |||||
4112 | burst_max = burst_code(np->sv_dmode, np->sv_ctest4, np->sv_ctest5)(np->sv_ctest4) & 0x80? 0 : (((np->sv_dmode) & 0xc0 ) >> 6) + ((np->sv_ctest5) & 0x04) + 1; | |||||
4113 | if (burst_max > 7) | |||||
4114 | burst_max = 7; | |||||
4115 | if (burst_max > np->maxburst) | |||||
4116 | burst_max = np->maxburst; | |||||
4117 | ||||||
4118 | /* | |||||
4119 | ** Select all supported special features | |||||
4120 | */ | |||||
4121 | if (np->features & FE_ERL(1<<6)) | |||||
4122 | np->rv_dmode |= ERL0x08; /* Enable Read Line */ | |||||
4123 | if (np->features & FE_BOF(1<<10)) | |||||
4124 | np->rv_dmode |= BOF0x02; /* Burst Opcode Fetch */ | |||||
4125 | if (np->features & FE_ERMP(1<<9)) | |||||
4126 | np->rv_dmode |= ERMP0x04; /* Enable Read Multiple */ | |||||
4127 | if (np->features & FE_PFEN(1<<12)) | |||||
4128 | np->rv_dcntl |= PFEN0x20; /* Prefetch Enable */ | |||||
4129 | if (np->features & FE_CLSE(1<<7)) | |||||
4130 | np->rv_dcntl |= CLSE0x80; /* Cache Line Size Enable */ | |||||
4131 | if (np->features & FE_WRIE(1<<8)) | |||||
4132 | np->rv_ctest3 |= WRIE0x01; /* Write and Invalidate */ | |||||
4133 | if (np->features & FE_DFS(1<<11)) | |||||
4134 | np->rv_ctest5 |= DFS0x20; /* Dma Fifo Size */ | |||||
4135 | ||||||
4136 | /* | |||||
4137 | ** Select some other | |||||
4138 | */ | |||||
4139 | if (driver_setup.master_parity) | |||||
4140 | np->rv_ctest4 |= MPEE0x08; /* Master parity checking */ | |||||
4141 | if (driver_setup.scsi_parity) | |||||
4142 | np->rv_scntl0 |= 0x0a; /* full arb., ena parity, par->ATN */ | |||||
4143 | ||||||
4144 | #ifdef SCSI_NCR_NVRAM_SUPPORT | |||||
4145 | /* | |||||
4146 | ** Get parity checking, host ID and verbose mode from NVRAM | |||||
4147 | **/ | |||||
4148 | if (nvram) { | |||||
4149 | switch(nvram->type) { | |||||
4150 | case SCSI_NCR_TEKRAM_NVRAM(2): | |||||
4151 | np->myaddr = nvram->data.Tekram.host_id & 0x0f; | |||||
4152 | break; | |||||
4153 | case SCSI_NCR_SYMBIOS_NVRAM(1): | |||||
4154 | if (!(nvram->data.Symbios.flags & SYMBIOS_PARITY_ENABLE)) | |||||
4155 | np->rv_scntl0 &= ~0x0a; | |||||
4156 | np->myaddr = nvram->data.Symbios.host_id & 0x0f; | |||||
4157 | if (nvram->data.Symbios.flags & SYMBIOS_VERBOSE_MSGS) | |||||
4158 | np->verbose += 1; | |||||
4159 | break; | |||||
4160 | } | |||||
4161 | } | |||||
4162 | #endif | |||||
4163 | /* | |||||
4164 | ** Get SCSI addr of host adapter (set by bios?). | |||||
4165 | */ | |||||
4166 | if (!np->myaddr) np->myaddr = INB(nc_scid)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_scid))))) & 0x07; | |||||
4167 | if (!np->myaddr) np->myaddr = SCSI_NCR_MYADDR(7); | |||||
4168 | ||||||
4169 | ||||||
4170 | #endif /* SCSI_NCR_TRUST_BIOS_SETTING */ | |||||
4171 | ||||||
4172 | /* | |||||
4173 | * Prepare initial io register bits for burst length | |||||
4174 | */ | |||||
4175 | ncr_init_burst(np, burst_max); | |||||
4176 | ||||||
4177 | /* | |||||
4178 | ** Set differential mode and LED support. | |||||
4179 | ** Ignore these features for boards known to use a | |||||
4180 | ** specific GPIO wiring (Tekram only for now). | |||||
4181 | ** Probe initial setting of GPREG and GPCNTL for | |||||
4182 | ** other ones. | |||||
4183 | */ | |||||
4184 | if (!nvram || nvram->type != SCSI_NCR_TEKRAM_NVRAM(2)) { | |||||
4185 | switch(driver_setup.diff_support) { | |||||
4186 | case 3: | |||||
4187 | if (INB(nc_gpreg)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_gpreg))))) & 0x08) | |||||
4188 | break; | |||||
4189 | case 2: | |||||
4190 | np->rv_stest2 |= 0x20; | |||||
4191 | break; | |||||
4192 | case 1: | |||||
4193 | np->rv_stest2 |= (np->sv_stest2 & 0x20); | |||||
4194 | break; | |||||
4195 | default: | |||||
4196 | break; | |||||
4197 | } | |||||
4198 | } | |||||
4199 | if ((driver_setup.led_pin || | |||||
4200 | (nvram && nvram->type == SCSI_NCR_SYMBIOS_NVRAM(1))) && | |||||
4201 | !(np->sv_gpcntl & 0x01)) | |||||
4202 | np->features |= FE_LED0(1<<0); | |||||
4203 | ||||||
4204 | /* | |||||
4205 | ** Set irq mode. | |||||
4206 | */ | |||||
4207 | switch(driver_setup.irqm) { | |||||
4208 | case 2: | |||||
4209 | np->rv_dcntl |= IRQM0x08; | |||||
4210 | break; | |||||
4211 | case 1: | |||||
4212 | np->rv_dcntl |= (np->sv_dcntl & IRQM0x08); | |||||
4213 | break; | |||||
4214 | default: | |||||
4215 | break; | |||||
4216 | } | |||||
4217 | ||||||
4218 | /* | |||||
4219 | ** Configure targets according to driver setup. | |||||
4220 | ** If NVRAM present get targets setup from NVRAM. | |||||
4221 | ** Allow to override sync, wide and NOSCAN from | |||||
4222 | ** boot command line. | |||||
4223 | */ | |||||
4224 | for (i = 0 ; i < MAX_TARGET((16)) ; i++) { | |||||
4225 | tcb_p tp = &np->target[i]; | |||||
4226 | ||||||
4227 | tp->usrsync = 255; | |||||
4228 | #ifdef SCSI_NCR_NVRAM_SUPPORT | |||||
4229 | if (nvram) { | |||||
4230 | switch(nvram->type) { | |||||
4231 | case SCSI_NCR_TEKRAM_NVRAM(2): | |||||
4232 | ncr_Tekram_setup_target(np, i, &nvram->data.Tekram); | |||||
4233 | break; | |||||
4234 | case SCSI_NCR_SYMBIOS_NVRAM(1): | |||||
4235 | ncr_Symbios_setup_target(np, i, &nvram->data.Symbios); | |||||
4236 | break; | |||||
4237 | } | |||||
4238 | if (driver_setup.use_nvram & 0x2) | |||||
4239 | tp->usrsync = driver_setup.default_sync; | |||||
4240 | if (driver_setup.use_nvram & 0x4) | |||||
4241 | tp->usrwide = driver_setup.max_wide; | |||||
4242 | if (driver_setup.use_nvram & 0x8) | |||||
4243 | tp->usrflag &= ~UF_NOSCAN(0x04); | |||||
4244 | } | |||||
4245 | else { | |||||
4246 | #else | |||||
4247 | if (1) { | |||||
4248 | #endif | |||||
4249 | tp->usrsync = driver_setup.default_sync; | |||||
4250 | tp->usrwide = driver_setup.max_wide; | |||||
4251 | tp->usrtags = driver_setup.default_tags; | |||||
4252 | if (!driver_setup.disconnection) | |||||
4253 | np->target[i].usrflag = UF_NODISC(0x02); | |||||
4254 | } | |||||
4255 | } | |||||
4256 | ||||||
4257 | /* | |||||
4258 | ** Announce all that stuff to user. | |||||
4259 | */ | |||||
4260 | ||||||
4261 | i = nvram ? nvram->type : 0; | |||||
4262 | printfprintk(KERN_INFO"<6>" "%s: %sID %d, Fast-%d%s%s\n", ncr_name(np), | |||||
4263 | i == SCSI_NCR_SYMBIOS_NVRAM(1) ? "Symbios format NVRAM, " : | |||||
4264 | (i == SCSI_NCR_TEKRAM_NVRAM(2) ? "Tekram format NVRAM, " : ""), | |||||
4265 | np->myaddr, | |||||
4266 | np->minsync < 12 ? 40 : (np->minsync < 25 ? 20 : 10), | |||||
4267 | (np->rv_scntl0 & 0xa) ? ", Parity Checking" : ", NO Parity", | |||||
4268 | (np->rv_stest2 & 0x20) ? ", Differential" : ""); | |||||
4269 | ||||||
4270 | if (bootverbose(np->verbose) > 1) { | |||||
4271 | printfprintk ("%s: initial SCNTL3/DMODE/DCNTL/CTEST3/4/5 = " | |||||
4272 | "(hex) %02x/%02x/%02x/%02x/%02x/%02x\n", | |||||
4273 | ncr_name(np), np->sv_scntl3, np->sv_dmode, np->sv_dcntl, | |||||
4274 | np->sv_ctest3, np->sv_ctest4, np->sv_ctest5); | |||||
4275 | ||||||
4276 | printfprintk ("%s: final SCNTL3/DMODE/DCNTL/CTEST3/4/5 = " | |||||
4277 | "(hex) %02x/%02x/%02x/%02x/%02x/%02x\n", | |||||
4278 | ncr_name(np), np->rv_scntl3, np->rv_dmode, np->rv_dcntl, | |||||
4279 | np->rv_ctest3, np->rv_ctest4, np->rv_ctest5); | |||||
4280 | } | |||||
4281 | ||||||
4282 | if (bootverbose(np->verbose) && np->paddr2) | |||||
4283 | printfprintk (KERN_INFO"<6>" "%s: on-board RAM at 0x%lx\n", | |||||
4284 | ncr_name(np), np->paddr2); | |||||
4285 | ||||||
4286 | return 0; | |||||
4287 | } | |||||
4288 | ||||||
4289 | ||||||
4290 | #ifdef SCSI_NCR_DEBUG_NVRAM | |||||
4291 | ||||||
4292 | __initfunc(void ncr_display_Symbios_nvram(ncb_p np, Symbios_nvram *nvram ) | |||||
4293 | void ncr_display_Symbios_nvram(ncb_p np, Symbios_nvram *nvram)void ncr_display_Symbios_nvram(ncb_p np, Symbios_nvram *nvram ) | |||||
4294 | )void ncr_display_Symbios_nvram(ncb_p np, Symbios_nvram *nvram ) | |||||
4295 | { | |||||
4296 | int i; | |||||
4297 | ||||||
4298 | /* display Symbios nvram host data */ | |||||
4299 | printfprintk("%s: HOST ID=%d%s%s%s%s\n", | |||||
4300 | ncr_name(np), nvram->host_id & 0x0f, | |||||
4301 | (nvram->flags & SYMBIOS_SCAM_ENABLE) ? " SCAM" :"", | |||||
4302 | (nvram->flags & SYMBIOS_PARITY_ENABLE) ? " PARITY" :"", | |||||
4303 | (nvram->flags & SYMBIOS_VERBOSE_MSGS) ? " VERSBOSE" :"", | |||||
4304 | (nvram->flags1 & SYMBIOS_SCAN_HI_LO) ? " HI_LO" :""); | |||||
4305 | ||||||
4306 | /* display Symbios nvram drive data */ | |||||
4307 | for (i = 0 ; i < 15 ; i++) { | |||||
4308 | struct Symbios_target *tn = &nvram->target[i]; | |||||
4309 | printfprintk("%s-%d:%s%s%s%s WIDTH=%d SYNC=%d TMO=%d\n", | |||||
4310 | ncr_name(np), i, | |||||
4311 | (tn->flags & SYMBIOS_DISCONNECT_ENABLE) ? " DISC" : "", | |||||
4312 | (tn->flags & SYMBIOS_SCAN_AT_BOOT_TIME) ? " SCAN_BOOT" : "", | |||||
4313 | (tn->flags & SYMBIOS_SCAN_LUNS) ? " SCAN_LUNS" : "", | |||||
4314 | (tn->flags & SYMBIOS_QUEUE_TAGS_ENABLED)? " TCQ" : "", | |||||
4315 | tn->bus_width, | |||||
4316 | tn->sync_period / 4, | |||||
4317 | tn->timeout); | |||||
4318 | } | |||||
4319 | } | |||||
4320 | ||||||
4321 | static u_charunsigned char Tekram_boot_delay[7] __initdata = {3, 5, 10, 20, 30, 60, 120}; | |||||
4322 | ||||||
4323 | __initfunc(void ncr_display_Tekram_nvram(ncb_p np, Tekram_nvram *nvram) | |||||
4324 | void ncr_display_Tekram_nvram(ncb_p np, Tekram_nvram *nvram)void ncr_display_Tekram_nvram(ncb_p np, Tekram_nvram *nvram) | |||||
4325 | )void ncr_display_Tekram_nvram(ncb_p np, Tekram_nvram *nvram) | |||||
4326 | { | |||||
4327 | int i, tags, boot_delay; | |||||
4328 | char *rem; | |||||
4329 | ||||||
4330 | /* display Tekram nvram host data */ | |||||
4331 | tags = 2 << nvram->max_tags_index; | |||||
4332 | boot_delay = 0; | |||||
4333 | if (nvram->boot_delay_index < 6) | |||||
4334 | boot_delay = Tekram_boot_delay[nvram->boot_delay_index]; | |||||
4335 | switch((nvram->flags & TEKRAM_REMOVABLE_FLAGS) >> 6) { | |||||
4336 | default: | |||||
4337 | case 0: rem = ""; break; | |||||
4338 | case 1: rem = " REMOVABLE=boot device"; break; | |||||
4339 | case 2: rem = " REMOVABLE=all"; break; | |||||
4340 | } | |||||
4341 | ||||||
4342 | printfprintk("%s: HOST ID=%d%s%s%s%s%s%s%s%s%s BOOT DELAY=%d tags=%d\n", | |||||
4343 | ncr_name(np), nvram->host_id & 0x0f, | |||||
4344 | (nvram->flags1 & SYMBIOS_SCAM_ENABLE) ? " SCAM" :"", | |||||
4345 | (nvram->flags & TEKRAM_MORE_THAN_2_DRIVES) ? " >2DRIVES" :"", | |||||
4346 | (nvram->flags & TEKRAM_DRIVES_SUP_1GB) ? " >1GB" :"", | |||||
4347 | (nvram->flags & TEKRAM_RESET_ON_POWER_ON) ? " RESET" :"", | |||||
4348 | (nvram->flags & TEKRAM_ACTIVE_NEGATION) ? " ACT_NEG" :"", | |||||
4349 | (nvram->flags & TEKRAM_IMMEDIATE_SEEK) ? " IMM_SEEK" :"", | |||||
4350 | (nvram->flags & TEKRAM_SCAN_LUNS) ? " SCAN_LUNS" :"", | |||||
4351 | (nvram->flags1 & TEKRAM_F2_F6_ENABLED) ? " F2_F6" :"", | |||||
4352 | rem, boot_delay, tags); | |||||
4353 | ||||||
4354 | /* display Tekram nvram drive data */ | |||||
4355 | for (i = 0; i <= 15; i++) { | |||||
4356 | int sync, j; | |||||
4357 | struct Tekram_target *tn = &nvram->target[i]; | |||||
4358 | j = tn->sync_index & 0xf; | |||||
4359 | sync = j < 12 ? Tekram_sync[j] : 255; | |||||
4360 | printfprintk("%s-%d:%s%s%s%s%s%s PERIOD=%d\n", | |||||
4361 | ncr_name(np), i, | |||||
4362 | (tn->flags & TEKRAM_PARITY_CHECK) ? " PARITY" : "", | |||||
4363 | (tn->flags & TEKRAM_SYNC_NEGO) ? " SYNC" : "", | |||||
4364 | (tn->flags & TEKRAM_DISCONNECT_ENABLE) ? " DISC" : "", | |||||
4365 | (tn->flags & TEKRAM_START_CMD) ? " START" : "", | |||||
4366 | (tn->flags & TEKRAM_TAGGED_COMMANDS) ? " TCQ" : "", | |||||
4367 | (tn->flags & TEKRAM_WIDE_NEGO) ? " WIDE" : "", | |||||
4368 | sync); | |||||
4369 | } | |||||
4370 | } | |||||
4371 | #endif /* SCSI_NCR_DEBUG_NVRAM */ | |||||
4372 | ||||||
4373 | /* | |||||
4374 | ** Host attach and initialisations. | |||||
4375 | ** | |||||
4376 | ** Allocate host data and ncb structure. | |||||
4377 | ** Request IO region and remap MMIO region. | |||||
4378 | ** Do chip initialization. | |||||
4379 | ** If all is OK, install interrupt handling and | |||||
4380 | ** start the timer daemon. | |||||
4381 | */ | |||||
4382 | ||||||
4383 | __initfunc(static int ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device) | |||||
4384 | static int ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device)static int ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device) | |||||
4385 | )static int ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device) | |||||
4386 | { | |||||
4387 | struct host_data *host_data; | |||||
4388 | ncb_p np; | |||||
4389 | struct Scsi_Host *instance = 0; | |||||
4390 | u_longunsigned long flags = 0; | |||||
4391 | ncr_nvram *nvram = device->nvram; | |||||
4392 | ||||||
4393 | printfprintk(KERN_INFO"<6>" "ncr53c%s-%d: rev=0x%02x, base=0x%x, io_port=0x%x, irq=%d\n", | |||||
4394 | device->chip.name, unit, device->chip.revision_id, device->slot.base, | |||||
4395 | device->slot.io_port, device->slot.irq); | |||||
4396 | ||||||
4397 | /* | |||||
4398 | ** Allocate host_data structure | |||||
4399 | */ | |||||
4400 | if (!(instance = scsi_register(tpnt, sizeof(*host_data)))) | |||||
4401 | goto attach_error; | |||||
4402 | ||||||
4403 | /* | |||||
4404 | ** Initialize structure. | |||||
4405 | */ | |||||
4406 | host_data = (struct host_data *) instance->hostdata; | |||||
4407 | ||||||
4408 | /* | |||||
4409 | ** Align np and first ccb to 32 boundary for cache line | |||||
4410 | ** bursting when copying the global header. | |||||
4411 | */ | |||||
4412 | np = (ncb_p) (((u_longunsigned long) &host_data->_ncb_data) & NCB_ALIGN_MASK(~((1UL << 5)-1))); | |||||
4413 | host_data->ncb = np; | |||||
4414 | bzero (np, sizeof (*np))(__builtin_constant_p(0) ? (__builtin_constant_p(((sizeof (*np )))) ? __constant_c_and_count_memset((((np))),((0x01010101UL* (unsigned char)(0))),(((sizeof (*np))))) : __constant_c_memset ((((np))),((0x01010101UL*(unsigned char)(0))),(((sizeof (*np) ))))) : (__builtin_constant_p(((sizeof (*np)))) ? __memset_generic (((((np)))),(((0))),((((sizeof (*np)))))) : __memset_generic( (((np))),((0)),(((sizeof (*np))))))); | |||||
4415 | ||||||
4416 | np->ccb = (ccb_p) (((u_longunsigned long) &host_data->_ccb_data) & CCB_ALIGN_MASK(~((1UL << 5)-1))); | |||||
4417 | bzero (np->ccb, sizeof (*np->ccb))(__builtin_constant_p(0) ? (__builtin_constant_p(((sizeof (*np ->ccb)))) ? __constant_c_and_count_memset((((np->ccb))) ,((0x01010101UL*(unsigned char)(0))),(((sizeof (*np->ccb)) ))) : __constant_c_memset((((np->ccb))),((0x01010101UL*(unsigned char)(0))),(((sizeof (*np->ccb)))))) : (__builtin_constant_p (((sizeof (*np->ccb)))) ? __memset_generic(((((np->ccb) ))),(((0))),((((sizeof (*np->ccb)))))) : __memset_generic( (((np->ccb))),((0)),(((sizeof (*np->ccb))))))); | |||||
4418 | ||||||
4419 | /* | |||||
4420 | ** Store input informations in the host data structure. | |||||
4421 | */ | |||||
4422 | strncpy(np->chip_name, device->chip.name, sizeof(np->chip_name) - 1); | |||||
4423 | np->unit = unit; | |||||
4424 | np->verbose = driver_setup.verbose; | |||||
4425 | sprintflinux_sprintf(np->inst_name, "ncr53c%s-%d", np->chip_name, np->unit); | |||||
4426 | np->device_id = device->chip.device_id; | |||||
4427 | np->revision_id = device->chip.revision_id; | |||||
4428 | np->features = device->chip.features; | |||||
4429 | np->clock_divn = device->chip.nr_divisor; | |||||
4430 | np->maxoffs = device->chip.offset_max; | |||||
4431 | np->maxburst = device->chip.burst_max; | |||||
4432 | ||||||
4433 | np->script0 = | |||||
4434 | (struct script *) (((u_longunsigned long) &host_data->script_data) & SCR_ALIGN_MASK(~((1UL << 5)-1))); | |||||
4435 | np->scripth0 = &host_data->scripth_data; | |||||
4436 | ||||||
4437 | /* | |||||
4438 | ** Initialize timer structure | |||||
4439 | ** | |||||
4440 | */ | |||||
4441 | init_timer(&np->timer); | |||||
4442 | np->timer.data = (unsigned long) np; | |||||
4443 | np->timer.function = ncr53c8xx_timeout; | |||||
4444 | ||||||
4445 | /* | |||||
4446 | ** Try to map the controller chip to | |||||
4447 | ** virtual and physical memory. | |||||
4448 | */ | |||||
4449 | ||||||
4450 | np->paddr = device->slot.base; | |||||
4451 | np->paddr2 = (np->features & FE_RAM(1<<14))? device->slot.base_2 : 0; | |||||
4452 | ||||||
4453 | #ifndef NCR_IOMAPPED | |||||
4454 | np->vaddr = remap_pci_mem((u_longunsigned long) np->paddr, (u_longunsigned long) 128); | |||||
4455 | if (!np->vaddr) { | |||||
4456 | printfprintk("%s: can't map memory mapped IO region\n", ncr_name(np)); | |||||
4457 | goto attach_error; | |||||
4458 | } | |||||
4459 | else | |||||
4460 | if (bootverbose(np->verbose) > 1) | |||||
4461 | printfprintk("%s: using memory mapped IO at virtual address 0x%lx\n", ncr_name(np), (u_longunsigned long) np->vaddr); | |||||
4462 | ||||||
4463 | /* | |||||
4464 | ** Make the controller's registers available. | |||||
4465 | ** Now the INB INW INL OUTB OUTW OUTL macros | |||||
4466 | ** can be used safely. | |||||
4467 | */ | |||||
4468 | ||||||
4469 | np->reg = (struct ncr_reg*) np->vaddr; | |||||
4470 | ||||||
4471 | #endif /* !defined NCR_IOMAPPED */ | |||||
4472 | ||||||
4473 | /* | |||||
4474 | ** Try to map the controller chip into iospace. | |||||
4475 | */ | |||||
4476 | ||||||
4477 | request_region(device->slot.io_port, 128, "ncr53c8xx"); | |||||
4478 | np->port = device->slot.io_port; | |||||
4479 | ||||||
4480 | #ifdef SCSI_NCR_NVRAM_SUPPORT | |||||
4481 | if (nvram) { | |||||
4482 | switch(nvram->type) { | |||||
4483 | case SCSI_NCR_SYMBIOS_NVRAM(1): | |||||
4484 | #ifdef SCSI_NCR_DEBUG_NVRAM | |||||
4485 | ncr_display_Symbios_nvram(np, &nvram->data.Symbios); | |||||
4486 | #endif | |||||
4487 | break; | |||||
4488 | case SCSI_NCR_TEKRAM_NVRAM(2): | |||||
4489 | #ifdef SCSI_NCR_DEBUG_NVRAM | |||||
4490 | ncr_display_Tekram_nvram(np, &nvram->data.Tekram); | |||||
4491 | #endif | |||||
4492 | break; | |||||
4493 | default: | |||||
4494 | nvram = 0; | |||||
4495 | #ifdef SCSI_NCR_DEBUG_NVRAM | |||||
4496 | printfprintk("%s: NVRAM: None or invalid data.\n", ncr_name(np)); | |||||
4497 | #endif | |||||
4498 | } | |||||
4499 | } | |||||
4500 | #endif | |||||
4501 | ||||||
4502 | /* | |||||
4503 | ** Do chip dependent initialization. | |||||
4504 | */ | |||||
4505 | (void)ncr_prepare_setting(np, nvram); | |||||
4506 | ||||||
4507 | #ifndef NCR_IOMAPPED | |||||
4508 | if (np->paddr2 && sizeof(struct script) <= 4096) { | |||||
4509 | np->vaddr2 = remap_pci_mem((u_longunsigned long) np->paddr2, (u_longunsigned long) 4096); | |||||
4510 | if (!np->vaddr2) { | |||||
4511 | printfprintk("%s: can't map memory mapped IO region\n", ncr_name(np)); | |||||
4512 | goto attach_error; | |||||
4513 | } | |||||
4514 | else | |||||
4515 | if (bootverbose(np->verbose) > 1) | |||||
4516 | printfprintk("%s: on-board ram mapped at virtual address 0x%lx\n", ncr_name(np), (u_longunsigned long) np->vaddr2); | |||||
4517 | } | |||||
4518 | #endif /* !defined NCR_IOMAPPED */ | |||||
4519 | ||||||
4520 | /* | |||||
4521 | ** Fill Linux host instance structure | |||||
4522 | */ | |||||
4523 | #if LINUX_VERSION_CODE131108 >= LinuxVersionCode(1,3,0)(((1)<<16)+((3)<<8)+(0)) | |||||
4524 | instance->max_channel = 0; | |||||
4525 | instance->max_id = np->maxwide ? 16 : 8; | |||||
4526 | instance->max_lun = SCSI_NCR_MAX_LUN(8); | |||||
4527 | #endif | |||||
4528 | #ifndef NCR_IOMAPPED | |||||
4529 | instance->base = (char *) np->reg; | |||||
4530 | #endif | |||||
4531 | instance->irq = device->slot.irq; | |||||
4532 | instance->io_port = device->slot.io_port; | |||||
4533 | instance->n_io_port = 128; | |||||
4534 | instance->dma_channel = 0; | |||||
4535 | #if LINUX_VERSION_CODE131108 >= LinuxVersionCode(2,0,0)(((2)<<16)+((0)<<8)+(0)) | |||||
4536 | instance->select_queue_depths = ncr53c8xx_select_queue_depths; | |||||
4537 | #endif | |||||
4538 | ||||||
4539 | /* | |||||
4540 | ** Patch script to physical addresses | |||||
4541 | */ | |||||
4542 | ncr_script_fill (&script0, &scripth0); | |||||
4543 | ||||||
4544 | np->scripth = np->scripth0; | |||||
4545 | np->p_scripth = vtophys(np->scripth)virt_to_phys(np->scripth); | |||||
4546 | ||||||
4547 | np->script = (np->vaddr2) ? (struct script *) np->vaddr2 : np->script0; | |||||
4548 | np->p_script = (np->vaddr2) ? np->paddr2 : vtophys(np->script0)virt_to_phys(np->script0); | |||||
4549 | ||||||
4550 | ncr_script_copy_and_bind (np, (ncrcmd *) &script0, (ncrcmd *) np->script0, sizeof(struct script)); | |||||
4551 | ncr_script_copy_and_bind (np, (ncrcmd *) &scripth0, (ncrcmd *) np->scripth0, sizeof(struct scripth)); | |||||
4552 | np->ccb->p_ccb = vtophys (np->ccb)virt_to_phys(np->ccb); | |||||
4553 | ||||||
4554 | /* | |||||
4555 | ** Patch the script for LED support. | |||||
4556 | */ | |||||
4557 | ||||||
4558 | if (np->features & FE_LED0(1<<0)) { | |||||
4559 | np->script0->reselect[0] = | |||||
4560 | cpu_to_scr(SCR_REG_REG(gpreg, SCR_OR, 0x01))((0x78000000 | ((((((size_t) (&((struct ncr_reg *)0)-> nc_gpreg)))) << 16ul)) | (0x02000000) | ((0x01)<< 8ul))); | |||||
4561 | np->script0->reselect1[0] = | |||||
4562 | cpu_to_scr(SCR_REG_REG(gpreg, SCR_AND, 0xfe))((0x78000000 | ((((((size_t) (&((struct ncr_reg *)0)-> nc_gpreg)))) << 16ul)) | (0x04000000) | ((0xfe)<< 8ul))); | |||||
4563 | np->script0->reselect2[0] = | |||||
4564 | cpu_to_scr(SCR_REG_REG(gpreg, SCR_AND, 0xfe))((0x78000000 | ((((((size_t) (&((struct ncr_reg *)0)-> nc_gpreg)))) << 16ul)) | (0x04000000) | ((0xfe)<< 8ul))); | |||||
4565 | } | |||||
4566 | ||||||
4567 | /* | |||||
4568 | ** init data structure | |||||
4569 | */ | |||||
4570 | ||||||
4571 | np->jump_tcb.l_cmd = cpu_to_scr(SCR_JUMP)(0x80080000); | |||||
4572 | np->jump_tcb.l_paddr = cpu_to_scr(NCB_SCRIPTH_PHYS (np, abort))((np->p_scripth + ((size_t) (&((struct scripth *)0)-> abort)))); | |||||
4573 | ||||||
4574 | /* | |||||
4575 | ** Reset chip. | |||||
4576 | */ | |||||
4577 | ||||||
4578 | OUTB (nc_istat, SRST)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_istat))))) = (((0x40)))); | |||||
4579 | DELAY (1000); | |||||
4580 | OUTB (nc_istat, 0 )((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_istat))))) = (((0)))); | |||||
4581 | ||||||
4582 | /* | |||||
4583 | ** Now check the cache handling of the pci chipset. | |||||
4584 | */ | |||||
4585 | ||||||
4586 | if (ncr_snooptest (np)) { | |||||
4587 | printfprintk ("CACHE INCORRECTLY CONFIGURED.\n"); | |||||
4588 | goto attach_error; | |||||
4589 | }; | |||||
4590 | ||||||
4591 | /* | |||||
4592 | ** Install the interrupt handler. | |||||
4593 | */ | |||||
4594 | #if LINUX_VERSION_CODE131108 >= LinuxVersionCode(1,3,70)(((1)<<16)+((3)<<8)+(70)) | |||||
4595 | #ifdef SCSI_NCR_SHARE_IRQ | |||||
4596 | if (bootverbose(np->verbose) > 1) | |||||
4597 | printfprintk("%s: requesting shared irq %d (dev_id=0x%lx)\n", | |||||
4598 | ncr_name(np), device->slot.irq, (u_longunsigned long) np); | |||||
4599 | if (request_irq(device->slot.irq, ncr53c8xx_intr, | |||||
4600 | SA_INTERRUPT0x20000000|SA_SHIRQ0x04000000, "ncr53c8xx", np)) { | |||||
4601 | #else | |||||
4602 | if (request_irq(device->slot.irq, ncr53c8xx_intr, | |||||
4603 | SA_INTERRUPT0x20000000, "ncr53c8xx", np)) { | |||||
4604 | #endif | |||||
4605 | #else | |||||
4606 | if (request_irq(device->slot.irq, ncr53c8xx_intr, | |||||
4607 | SA_INTERRUPT0x20000000, "ncr53c8xx")) { | |||||
4608 | #endif | |||||
4609 | printfprintk("%s: request irq %d failure\n", ncr_name(np), device->slot.irq); | |||||
4610 | goto attach_error; | |||||
4611 | } | |||||
4612 | np->irq = device->slot.irq; | |||||
4613 | ||||||
4614 | /* | |||||
4615 | ** After SCSI devices have been opened, we cannot | |||||
4616 | ** reset the bus safely, so we do it here. | |||||
4617 | ** Interrupt handler does the real work. | |||||
4618 | ** Process the reset exception, | |||||
4619 | ** if interrupts are not enabled yet. | |||||
4620 | ** Then enable disconnects. | |||||
4621 | */ | |||||
4622 | save_flags(flags)__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); cli()__asm__ __volatile__ ("cli": : :"memory"); | |||||
4623 | if (ncr_reset_scsi_bus(np, 0, driver_setup.settle_delay) != 0) { | |||||
4624 | printfprintk("%s: FATAL ERROR: CHECK SCSI BUS - CABLES, TERMINATION, DEVICE POWER etc.!\n", ncr_name(np)); | |||||
4625 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||||
4626 | goto attach_error; | |||||
4627 | } | |||||
4628 | ncr_exception (np); | |||||
4629 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||||
4630 | ||||||
4631 | np->disc = 1; | |||||
4632 | ||||||
4633 | /* | |||||
4634 | ** The middle-level SCSI driver does not | |||||
4635 | ** wait devices to settle. | |||||
4636 | ** Wait synchronously if more than 2 seconds. | |||||
4637 | */ | |||||
4638 | if (driver_setup.settle_delay > 2) { | |||||
4639 | printfprintk("%s: waiting %d seconds for scsi devices to settle...\n", | |||||
4640 | ncr_name(np), driver_setup.settle_delay); | |||||
4641 | DELAY(1000000UL * driver_setup.settle_delay); | |||||
4642 | } | |||||
4643 | ||||||
4644 | /* | |||||
4645 | ** Now let the generic SCSI driver | |||||
4646 | ** look for the SCSI devices on the bus .. | |||||
4647 | */ | |||||
4648 | ||||||
4649 | /* | |||||
4650 | ** start the timeout daemon | |||||
4651 | */ | |||||
4652 | np->lasttime=0; | |||||
4653 | ncr_timeout (np); | |||||
4654 | ||||||
4655 | /* | |||||
4656 | ** use SIMPLE TAG messages by default | |||||
4657 | */ | |||||
4658 | #ifdef SCSI_NCR_ALWAYS_SIMPLE_TAG | |||||
4659 | np->order = M_SIMPLE_TAG(0x20); | |||||
4660 | #endif | |||||
4661 | ||||||
4662 | /* | |||||
4663 | ** Done. | |||||
4664 | */ | |||||
4665 | if (!the_template) { | |||||
4666 | the_template = instance->hostt; | |||||
4667 | first_host = instance; | |||||
4668 | } | |||||
4669 | ||||||
4670 | return 0; | |||||
4671 | ||||||
4672 | attach_error: | |||||
4673 | if (!instance) return -1; | |||||
4674 | printfprintk("%s: detaching...\n", ncr_name(np)); | |||||
4675 | #ifndef NCR_IOMAPPED | |||||
4676 | if (np->vaddr) { | |||||
4677 | #ifdef DEBUG_NCR53C8XX | |||||
4678 | printfprintk("%s: releasing memory mapped IO region %lx[%d]\n", ncr_name(np), (u_longunsigned long) np->vaddr, 128); | |||||
4679 | #endif | |||||
4680 | unmap_pci_mem((vm_offset_t) np->vaddr, (u_longunsigned long) 128); | |||||
4681 | } | |||||
4682 | if (np->vaddr2) { | |||||
4683 | #ifdef DEBUG_NCR53C8XX | |||||
4684 | printfprintk("%s: releasing memory mapped IO region %lx[%d]\n", ncr_name(np), (u_longunsigned long) np->vaddr2, 4096); | |||||
4685 | #endif | |||||
4686 | unmap_pci_mem((vm_offset_t) np->vaddr2, (u_longunsigned long) 4096); | |||||
4687 | } | |||||
4688 | #endif | |||||
4689 | if (np->port) { | |||||
4690 | #ifdef DEBUG_NCR53C8XX | |||||
4691 | printfprintk("%s: releasing IO region %x[%d]\n", ncr_name(np), np->port, 128); | |||||
4692 | #endif | |||||
4693 | release_region(np->port, 128); | |||||
4694 | } | |||||
4695 | if (np->irq) { | |||||
4696 | #ifdef DEBUG_NCR53C8XX | |||||
4697 | printfprintk("%s: freeing irq %d\n", ncr_name(np), np->irq); | |||||
4698 | #endif | |||||
4699 | #if LINUX_VERSION_CODE131108 >= LinuxVersionCode(1,3,70)(((1)<<16)+((3)<<8)+(70)) | |||||
4700 | free_irq(np->irq, np); | |||||
4701 | #else | |||||
4702 | free_irq(np->irq); | |||||
4703 | #endif | |||||
4704 | } | |||||
4705 | scsi_unregister(instance); | |||||
4706 | ||||||
4707 | return -1; | |||||
4708 | } | |||||
4709 | ||||||
4710 | /*========================================================== | |||||
4711 | ** | |||||
4712 | ** | |||||
4713 | ** Start execution of a SCSI command. | |||||
4714 | ** This is called from the generic SCSI driver. | |||||
4715 | ** | |||||
4716 | ** | |||||
4717 | **========================================================== | |||||
4718 | */ | |||||
4719 | int ncr_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) | |||||
4720 | { | |||||
4721 | struct Scsi_Host *host = cmd->host; | |||||
4722 | /* Scsi_Device *device = cmd->device; */ | |||||
4723 | struct host_data *host_data = (struct host_data *) host->hostdata; | |||||
4724 | ncb_p np = host_data->ncb; | |||||
4725 | tcb_p tp = &np->target[cmd->target]; | |||||
4726 | ||||||
4727 | ccb_p cp; | |||||
4728 | lcb_p lp; | |||||
4729 | ||||||
4730 | int segments; | |||||
4731 | u_charunsigned char qidx, nego, idmsg, *msgptr; | |||||
4732 | u_intunsigned int msglen, msglen2; | |||||
4733 | u_longunsigned long flags; | |||||
4734 | int xfer_direction; | |||||
4735 | ||||||
4736 | cmd->scsi_done = done; | |||||
4737 | cmd->host_scribble = NULL((void *) 0); | |||||
4738 | cmd->SCp.ptr = NULL((void *) 0); | |||||
4739 | cmd->SCp.buffer = NULL((void *) 0); | |||||
4740 | ||||||
4741 | /*--------------------------------------------- | |||||
4742 | ** | |||||
4743 | ** Some shortcuts ... | |||||
4744 | ** | |||||
4745 | **--------------------------------------------- | |||||
4746 | */ | |||||
4747 | if ((cmd->target == np->myaddr ) || | |||||
4748 | (cmd->target >= MAX_TARGET((16))) || | |||||
4749 | (cmd->lun >= MAX_LUN(8) )) { | |||||
4750 | return(DID_BAD_TARGET0x04); | |||||
4751 | } | |||||
4752 | ||||||
4753 | /*--------------------------------------------- | |||||
4754 | ** | |||||
4755 | ** Complete the 1st TEST UNIT READY command | |||||
4756 | ** with error condition if the device is | |||||
4757 | ** flagged NOSCAN, in order to speed up | |||||
4758 | ** the boot. | |||||
4759 | ** | |||||
4760 | **--------------------------------------------- | |||||
4761 | */ | |||||
4762 | if (cmd->cmnd[0] == 0 && (tp->usrflag & UF_NOSCAN(0x04))) { | |||||
4763 | tp->usrflag &= ~UF_NOSCAN(0x04); | |||||
4764 | return DID_BAD_TARGET0x04; | |||||
4765 | } | |||||
4766 | ||||||
4767 | if (DEBUG_FLAGSncr_debug & DEBUG_TINY(0x0080)) { | |||||
4768 | PRINT_ADDR(cmd); | |||||
4769 | printfprintk ("CMD=%x ", cmd->cmnd[0]); | |||||
4770 | } | |||||
4771 | ||||||
4772 | /*--------------------------------------------------- | |||||
4773 | ** | |||||
4774 | ** Assign a ccb / bind cmd. | |||||
4775 | ** If resetting, shorten settle_time if necessary | |||||
4776 | ** in order to avoid spurious timeouts. | |||||
4777 | ** If resetting or no free ccb, | |||||
4778 | ** insert cmd into the waiting list. | |||||
4779 | ** | |||||
4780 | **---------------------------------------------------- | |||||
4781 | */ | |||||
4782 | save_flags(flags)__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); cli()__asm__ __volatile__ ("cli": : :"memory"); | |||||
4783 | ||||||
4784 | if (np->settle_time && cmd->timeout_per_command >= HZ100 && | |||||
4785 | np->settle_time > jiffies + cmd->timeout_per_command - HZ100) { | |||||
4786 | np->settle_time = jiffies + cmd->timeout_per_command - HZ100; | |||||
4787 | } | |||||
4788 | ||||||
4789 | if (np->settle_time || !(cp=ncr_get_ccb (np, cmd->target, cmd->lun))) { | |||||
4790 | insert_into_waiting_list(np, cmd); | |||||
4791 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||||
4792 | return(DID_OK0x00); | |||||
4793 | } | |||||
4794 | cp->cmd = cmd; | |||||
4795 | ||||||
4796 | /*--------------------------------------------------- | |||||
4797 | ** | |||||
4798 | ** Enable tagged queue if asked by scsi ioctl | |||||
4799 | ** | |||||
4800 | **---------------------------------------------------- | |||||
4801 | */ | |||||
4802 | if (!tp->usrtags && cmd->device && cmd->device->tagged_queue) { | |||||
4803 | tp->usrtags = SCSI_NCR_MAX_TAGS(4); | |||||
4804 | ncr_setmaxtags (np, tp, SCSI_NCR_MAX_TAGS(4)); | |||||
4805 | } | |||||
4806 | ||||||
4807 | /*--------------------------------------------------- | |||||
4808 | ** | |||||
4809 | ** timestamp | |||||
4810 | ** | |||||
4811 | **---------------------------------------------------- | |||||
4812 | */ | |||||
4813 | #ifdef SCSI_NCR_PROFILE_SUPPORT | |||||
4814 | bzero (&cp->phys.header.stamp, sizeof (struct tstamp))(__builtin_constant_p(0) ? (__builtin_constant_p(((sizeof (struct tstamp)))) ? __constant_c_and_count_memset((((&cp->phys .header.stamp))),((0x01010101UL*(unsigned char)(0))),(((sizeof (struct tstamp))))) : __constant_c_memset((((&cp->phys .header.stamp))),((0x01010101UL*(unsigned char)(0))),(((sizeof (struct tstamp)))))) : (__builtin_constant_p(((sizeof (struct tstamp)))) ? __memset_generic(((((&cp->phys.header.stamp )))),(((0))),((((sizeof (struct tstamp)))))) : __memset_generic ((((&cp->phys.header.stamp))),((0)),(((sizeof (struct tstamp ))))))); | |||||
4815 | cp->phys.header.stamp.start = jiffies; | |||||
4816 | #endif | |||||
4817 | ||||||
4818 | /*---------------------------------------------------- | |||||
4819 | ** | |||||
4820 | ** Get device quirks from a speciality table. | |||||
4821 | ** | |||||
4822 | ** @GENSCSI@ | |||||
4823 | ** This should be a part of the device table | |||||
4824 | ** in "scsi_conf.c". | |||||
4825 | ** | |||||
4826 | **---------------------------------------------------- | |||||
4827 | */ | |||||
4828 | if (tp->quirks & QUIRK_UPDATE(0x80)) { | |||||
4829 | tp->quirks = ncr_lookup ((char*) &tp->inqdata[0]); | |||||
4830 | #ifndef NCR_GETCC_WITHMSG | |||||
4831 | if (tp->quirks) { | |||||
4832 | PRINT_ADDR(cmd); | |||||
4833 | printfprintk ("quirks=%x.\n", tp->quirks); | |||||
4834 | } | |||||
4835 | #endif | |||||
4836 | } | |||||
4837 | ||||||
4838 | /*--------------------------------------------------- | |||||
4839 | ** | |||||
4840 | ** negotiation required? | |||||
4841 | ** | |||||
4842 | ** Only SCSI-II devices. | |||||
4843 | ** To negotiate with SCSI-I devices is dangerous, since | |||||
4844 | ** Synchronous Negotiation protocol is optional, and | |||||
4845 | ** INQUIRY data do not contains capabilities in byte 7. | |||||
4846 | **---------------------------------------------------- | |||||
4847 | */ | |||||
4848 | ||||||
4849 | nego = 0; | |||||
4850 | ||||||
4851 | if (cmd->lun == 0 && !tp->nego_cp && | |||||
4852 | (tp->inqdata[2] & 0x7) >= 2 && tp->inqdata[7]) { | |||||
4853 | /* | |||||
4854 | ** negotiate wide transfers ? | |||||
4855 | */ | |||||
4856 | ||||||
4857 | if (!tp->widedone) { | |||||
4858 | if (tp->inqdata[7] & INQ7_WIDE16(0x20)) { | |||||
4859 | nego = NS_WIDE(2); | |||||
4860 | } else | |||||
4861 | tp->widedone=1; | |||||
4862 | }; | |||||
4863 | ||||||
4864 | /* | |||||
4865 | ** negotiate synchronous transfers? | |||||
4866 | */ | |||||
4867 | ||||||
4868 | if (!nego && !tp->period) { | |||||
4869 | if ( 1 | |||||
4870 | #if defined (CDROM_ASYNC) | |||||
4871 | && ((tp->inqdata[0] & 0x1f) != 5) | |||||
4872 | #endif | |||||
4873 | && (tp->inqdata[7] & INQ7_SYNC(0x10))) { | |||||
4874 | nego = NS_SYNC(1); | |||||
4875 | } else { | |||||
4876 | tp->period =0xffff; | |||||
4877 | tp->sval = 0xe0; | |||||
4878 | PRINT_ADDR(cmd); | |||||
4879 | printfprintk ("asynchronous.\n"); | |||||
4880 | }; | |||||
4881 | }; | |||||
4882 | ||||||
4883 | /* | |||||
4884 | ** remember nego is pending for the target. | |||||
4885 | ** Avoid to start a nego for all queued commands | |||||
4886 | ** when tagged command queuing is enabled. | |||||
4887 | */ | |||||
4888 | ||||||
4889 | if (nego) | |||||
4890 | tp->nego_cp = cp; | |||||
4891 | }; | |||||
4892 | ||||||
4893 | /*--------------------------------------------------- | |||||
4894 | ** | |||||
4895 | ** choose a new tag ... | |||||
4896 | ** | |||||
4897 | **---------------------------------------------------- | |||||
4898 | */ | |||||
4899 | ||||||
4900 | if ((lp = tp->lp[cmd->lun]) && (lp->usetags)) { | |||||
4901 | /* | |||||
4902 | ** assign a tag to this ccb! | |||||
4903 | */ | |||||
4904 | while (!cp->tag) { | |||||
4905 | ccb_p cp2 = lp->next_ccb; | |||||
4906 | lp->lasttag = lp->lasttag % 255 + 1; | |||||
4907 | while (cp2 && cp2->tag != lp->lasttag) | |||||
4908 | cp2 = cp2->next_ccb; | |||||
4909 | if (cp2) continue; | |||||
4910 | cp->tag=lp->lasttag; | |||||
4911 | if (DEBUG_FLAGSncr_debug & DEBUG_TAGS(0x0400)) { | |||||
4912 | PRINT_ADDR(cmd); | |||||
4913 | printfprintk ("using tag #%d.\n", cp->tag); | |||||
4914 | } | |||||
4915 | } | |||||
4916 | } else { | |||||
4917 | cp->tag=0; | |||||
4918 | } | |||||
4919 | ||||||
4920 | /*---------------------------------------------------- | |||||
4921 | ** | |||||
4922 | ** Build the identify / tag / sdtr message | |||||
4923 | ** | |||||
4924 | **---------------------------------------------------- | |||||
4925 | */ | |||||
4926 | ||||||
4927 | idmsg = M_IDENTIFY(0x80) | cmd->lun; | |||||
4928 | ||||||
4929 | if (cp != np->ccb && ((np->disc && !(tp->usrflag & UF_NODISC(0x02))) || cp->tag)) | |||||
4930 | idmsg |= 0x40; | |||||
4931 | ||||||
4932 | msgptr = cp->scsi_smsg; | |||||
4933 | msglen = 0; | |||||
4934 | msgptr[msglen++] = idmsg; | |||||
4935 | ||||||
4936 | if (cp->tag) { | |||||
4937 | char tag; | |||||
4938 | ||||||
4939 | tag = np->order; | |||||
4940 | if (tag == 0) { | |||||
4941 | /* | |||||
4942 | ** Ordered write ops, unordered read ops. | |||||
4943 | */ | |||||
4944 | switch (cmd->cmnd[0]) { | |||||
4945 | case 0x08: /* READ_SMALL (6) */ | |||||
4946 | case 0x28: /* READ_BIG (10) */ | |||||
4947 | case 0xa8: /* READ_HUGE (12) */ | |||||
4948 | tag = M_SIMPLE_TAG(0x20); | |||||
4949 | break; | |||||
4950 | default: | |||||
4951 | tag = M_ORDERED_TAG(0x22); | |||||
4952 | } | |||||
4953 | } | |||||
4954 | /* | |||||
4955 | ** Have to force ordered tag to avoid timeouts | |||||
4956 | */ | |||||
4957 | if ((lp = tp->lp[cmd->lun]) && (lp->force_ordered_tag)) { | |||||
4958 | tag = M_ORDERED_TAG(0x22); | |||||
4959 | lp->force_ordered_tag = 0; | |||||
4960 | if (DEBUG_FLAGSncr_debug & DEBUG_TAGS(0x0400)) { | |||||
4961 | PRINT_ADDR(cmd); | |||||
4962 | printfprintk ("Ordered Queue Tag forced\n"); | |||||
4963 | } | |||||
4964 | } | |||||
4965 | msgptr[msglen++] = tag; | |||||
4966 | msgptr[msglen++] = cp -> tag; | |||||
4967 | } | |||||
4968 | ||||||
4969 | switch (nego) { | |||||
4970 | case NS_SYNC(1): | |||||
4971 | msgptr[msglen++] = M_EXTENDED(0x01); | |||||
4972 | msgptr[msglen++] = 3; | |||||
4973 | msgptr[msglen++] = M_X_SYNC_REQ(0x01); | |||||
4974 | msgptr[msglen++] = tp->maxoffs ? tp->minsync : 0; | |||||
4975 | msgptr[msglen++] = tp->maxoffs; | |||||
4976 | if (DEBUG_FLAGSncr_debug & DEBUG_NEGO(0x0200)) { | |||||
4977 | PRINT_ADDR(cp->cmd); | |||||
4978 | printfprintk ("sync msgout: "); | |||||
4979 | ncr_show_msg (&cp->scsi_smsg [msglen-5]); | |||||
4980 | printfprintk (".\n"); | |||||
4981 | }; | |||||
4982 | break; | |||||
4983 | case NS_WIDE(2): | |||||
4984 | msgptr[msglen++] = M_EXTENDED(0x01); | |||||
4985 | msgptr[msglen++] = 2; | |||||
4986 | msgptr[msglen++] = M_X_WIDE_REQ(0x03); | |||||
4987 | msgptr[msglen++] = tp->usrwide; | |||||
4988 | if (DEBUG_FLAGSncr_debug & DEBUG_NEGO(0x0200)) { | |||||
4989 | PRINT_ADDR(cp->cmd); | |||||
4990 | printfprintk ("wide msgout: "); | |||||
4991 | ncr_show_msg (&cp->scsi_smsg [msglen-4]); | |||||
4992 | printfprintk (".\n"); | |||||
4993 | }; | |||||
4994 | break; | |||||
4995 | }; | |||||
4996 | ||||||
4997 | /*---------------------------------------------------- | |||||
4998 | ** | |||||
4999 | ** Build the identify message for getcc. | |||||
5000 | ** | |||||
5001 | **---------------------------------------------------- | |||||
5002 | */ | |||||
5003 | ||||||
5004 | cp -> scsi_smsg2 [0] = idmsg; | |||||
5005 | msglen2 = 1; | |||||
5006 | ||||||
5007 | /*---------------------------------------------------- | |||||
5008 | ** | |||||
5009 | ** Build the data descriptors | |||||
5010 | ** | |||||
5011 | **---------------------------------------------------- | |||||
5012 | */ | |||||
5013 | ||||||
5014 | segments = ncr_scatter (cp, cp->cmd); | |||||
5015 | ||||||
5016 | if (segments < 0) { | |||||
5017 | ncr_free_ccb(np, cp, cmd->target, cmd->lun); | |||||
5018 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||||
5019 | return(DID_ERROR0x07); | |||||
5020 | } | |||||
5021 | ||||||
5022 | /*---------------------------------------------------- | |||||
5023 | ** | |||||
5024 | ** Guess xfer direction. | |||||
5025 | ** Spare some CPU by testing here frequently opcode. | |||||
5026 | ** | |||||
5027 | **---------------------------------------------------- | |||||
5028 | */ | |||||
5029 | switch((int) cmd->cmnd[0]) { | |||||
5030 | case 0x08: /* READ(6) 08 */ | |||||
5031 | case 0x28: /* READ(10) 28 */ | |||||
5032 | case 0xA8: /* READ(12) A8 */ | |||||
5033 | xfer_direction = XferIn1; | |||||
5034 | break; | |||||
5035 | case 0x0A: /* WRITE(6) 0A */ | |||||
5036 | case 0x2A: /* WRITE(10) 2A */ | |||||
5037 | case 0xAA: /* WRITE(12) AA */ | |||||
5038 | xfer_direction = XferOut2; | |||||
5039 | break; | |||||
5040 | default: | |||||
5041 | xfer_direction = guess_xfer_direction((int) cmd->cmnd[0]); | |||||
5042 | break; | |||||
5043 | } | |||||
5044 | ||||||
5045 | /*---------------------------------------------------- | |||||
5046 | ** | |||||
5047 | ** Set the SAVED_POINTER. | |||||
5048 | ** | |||||
5049 | **---------------------------------------------------- | |||||
5050 | */ | |||||
5051 | ||||||
5052 | cp->segments = segments; | |||||
5053 | if (!cp->data_len) | |||||
5054 | xfer_direction = XferNone0; | |||||
5055 | ||||||
5056 | switch (xfer_direction) { | |||||
5057 | u_longunsigned long endp; | |||||
5058 | default: | |||||
5059 | case XferBoth3: | |||||
5060 | cp->phys.header.savep = | |||||
5061 | cpu_to_scr(NCB_SCRIPT_PHYS (np, data_io))((np->p_script + ((size_t) (&((struct script *)0)-> data_io)))); | |||||
5062 | cp->phys.header.goalp = cp->phys.header.savep; | |||||
5063 | break; | |||||
5064 | case XferIn1: | |||||
5065 | endp = NCB_SCRIPT_PHYS (np, data_in)(np->p_script + ((size_t) (&((struct script *)0)->data_in ))) + MAX_SCATTER((127))*16; | |||||
5066 | cp->phys.header.goalp = cpu_to_scr(endp + 8)(endp + 8); | |||||
5067 | cp->phys.header.savep = cpu_to_scr(endp - segments*16)(endp - segments*16); | |||||
5068 | break; | |||||
5069 | case XferOut2: | |||||
5070 | endp = NCB_SCRIPTH_PHYS (np, data_out)(np->p_scripth + ((size_t) (&((struct scripth *)0)-> data_out))) + MAX_SCATTER((127))*16; | |||||
5071 | cp->phys.header.goalp = cpu_to_scr(endp + 8)(endp + 8); | |||||
5072 | cp->phys.header.savep = cpu_to_scr(endp - segments*16)(endp - segments*16); | |||||
5073 | break; | |||||
5074 | case XferNone0: | |||||
5075 | cp->phys.header.savep = | |||||
5076 | cpu_to_scr(NCB_SCRIPT_PHYS (np, no_data))((np->p_script + ((size_t) (&((struct script *)0)-> no_data)))); | |||||
5077 | cp->phys.header.goalp = cp->phys.header.savep; | |||||
5078 | break; | |||||
5079 | } | |||||
5080 | ||||||
5081 | cp->phys.header.lastp = cp->phys.header.savep; | |||||
5082 | ||||||
5083 | /*---------------------------------------------------- | |||||
5084 | ** | |||||
5085 | ** fill in ccb | |||||
5086 | ** | |||||
5087 | **---------------------------------------------------- | |||||
5088 | ** | |||||
5089 | ** | |||||
5090 | ** physical -> virtual backlink | |||||
5091 | ** Generic SCSI command | |||||
5092 | */ | |||||
5093 | cp->phys.header.cp = cp; | |||||
5094 | /* | |||||
5095 | ** Startqueue | |||||
5096 | */ | |||||
5097 | cp->phys.header.launch.l_paddr = | |||||
5098 | cpu_to_scr(NCB_SCRIPT_PHYS (np, select))((np->p_script + ((size_t) (&((struct script *)0)-> select)))); | |||||
5099 | cp->phys.header.launch.l_cmd = cpu_to_scr(SCR_JUMP)(0x80080000); | |||||
5100 | /* | |||||
5101 | ** select | |||||
5102 | */ | |||||
5103 | cp->phys.select.sel_id = cmd->target; | |||||
5104 | cp->phys.select.sel_scntl3 = tp->wval; | |||||
5105 | cp->phys.select.sel_sxfer = tp->sval; | |||||
5106 | /* | |||||
5107 | ** message | |||||
5108 | */ | |||||
5109 | cp->phys.smsg.addr = cpu_to_scr(CCB_PHYS (cp, scsi_smsg))((cp->p_ccb + ((size_t) (&((struct ccb *)0)->scsi_smsg )))); | |||||
5110 | cp->phys.smsg.size = cpu_to_scr(msglen)(msglen); | |||||
5111 | ||||||
5112 | cp->phys.smsg2.addr = cpu_to_scr(CCB_PHYS (cp, scsi_smsg2))((cp->p_ccb + ((size_t) (&((struct ccb *)0)->scsi_smsg2 )))); | |||||
5113 | cp->phys.smsg2.size = cpu_to_scr(msglen2)(msglen2); | |||||
5114 | /* | |||||
5115 | ** command | |||||
5116 | */ | |||||
5117 | cp->phys.cmd.addr = cpu_to_scr(vtophys (&cmd->cmnd[0]))(virt_to_phys(&cmd->cmnd[0])); | |||||
5118 | cp->phys.cmd.size = cpu_to_scr(cmd->cmd_len)(cmd->cmd_len); | |||||
5119 | /* | |||||
5120 | ** sense command | |||||
5121 | */ | |||||
5122 | cp->phys.scmd.addr = cpu_to_scr(CCB_PHYS (cp, sensecmd))((cp->p_ccb + ((size_t) (&((struct ccb *)0)->sensecmd )))); | |||||
5123 | cp->phys.scmd.size = cpu_to_scr(6)(6); | |||||
5124 | /* | |||||
5125 | ** patch requested size into sense command | |||||
5126 | */ | |||||
5127 | cp->sensecmd[0] = 0x03; | |||||
5128 | cp->sensecmd[1] = cmd->lun << 5; | |||||
5129 | cp->sensecmd[4] = sizeof(cmd->sense_buffer); | |||||
5130 | /* | |||||
5131 | ** sense data | |||||
5132 | */ | |||||
5133 | cp->phys.sense.addr = | |||||
5134 | cpu_to_scr(vtophys (&cmd->sense_buffer[0]))(virt_to_phys(&cmd->sense_buffer[0])); | |||||
5135 | cp->phys.sense.size = cpu_to_scr(sizeof(cmd->sense_buffer))(sizeof(cmd->sense_buffer)); | |||||
5136 | /* | |||||
5137 | ** status | |||||
5138 | */ | |||||
5139 | cp->actualquirksphys.header.status[0] = tp->quirks; | |||||
5140 | cp->host_statusphys.header.status[1] = nego ? HS_NEGOTIATE(2) : HS_BUSY(1); | |||||
5141 | cp->scsi_statusphys.header.status[2] = S_ILLEGAL(0xff); | |||||
5142 | cp->parity_statusphys.header.status[3] = 0; | |||||
5143 | ||||||
5144 | cp->xerr_statusphys.header.scr_st[0] = XE_OK(0); | |||||
5145 | cp->sync_statusphys.header.scr_st[1] = tp->sval; | |||||
5146 | cp->nego_statusphys.header.scr_st[2] = nego; | |||||
5147 | cp->wide_statusphys.header.scr_st[3] = tp->wval; | |||||
5148 | ||||||
5149 | /*---------------------------------------------------- | |||||
5150 | ** | |||||
5151 | ** Critical region: start this job. | |||||
5152 | ** | |||||
5153 | **---------------------------------------------------- | |||||
5154 | */ | |||||
5155 | ||||||
5156 | /* | |||||
5157 | ** reselect pattern and activate this job. | |||||
5158 | */ | |||||
5159 | ||||||
5160 | cp->jump_ccb.l_cmd = | |||||
5161 | cpu_to_scr((SCR_JUMP ^ IFFALSE (DATA (cp->tag))))((0x80080000 ^ (0x00080000 | ((0x00040000 | ((cp->tag) & 0xff)))))); | |||||
5162 | ||||||
5163 | /* Compute a time limit greater than the middle-level driver one */ | |||||
5164 | if (cmd->timeout_per_command > 0) | |||||
5165 | cp->tlimit = jiffies + cmd->timeout_per_command + NCR_TIMEOUT_INCREASE(5*100); | |||||
5166 | else | |||||
5167 | cp->tlimit = jiffies + 3600 * HZ100; /* No timeout=one hour */ | |||||
5168 | cp->magic = CCB_MAGIC(0xf2691ad2); | |||||
5169 | ||||||
5170 | /* | |||||
5171 | ** insert into start queue. | |||||
5172 | */ | |||||
5173 | ||||||
5174 | qidx = np->squeueput + 1; | |||||
5175 | if (qidx >= MAX_START((7*(4)) + 4)) qidx=0; | |||||
5176 | np->squeue [qidx ] = cpu_to_scr(NCB_SCRIPT_PHYS (np, idle))((np->p_script + ((size_t) (&((struct script *)0)-> idle)))); | |||||
5177 | np->squeue [np->squeueput] = cpu_to_scr(CCB_PHYS (cp, phys))((cp->p_ccb + ((size_t) (&((struct ccb *)0)->phys)) )); | |||||
5178 | np->squeueput = qidx; | |||||
5179 | ||||||
5180 | if(DEBUG_FLAGSncr_debug & DEBUG_QUEUE(0x0008)) | |||||
5181 | printfprintk ("%s: queuepos=%d tryoffset=%d.\n", ncr_name (np), | |||||
5182 | np->squeueput, | |||||
5183 | (unsigned)(scr_to_cpu(np->script->startpos[0])(np->script->startpos[0]) - | |||||
5184 | (NCB_SCRIPTH_PHYS (np, tryloop)(np->p_scripth + ((size_t) (&((struct scripth *)0)-> tryloop)))))); | |||||
5185 | ||||||
5186 | /* | |||||
5187 | ** Script processor may be waiting for reselect. | |||||
5188 | ** Wake it up. | |||||
5189 | */ | |||||
5190 | #ifdef SCSI_NCR_DEBUG_ERROR_RECOVERY_SUPPORT | |||||
5191 | if (!np->stalling) | |||||
5192 | #endif | |||||
5193 | OUTB (nc_istat, SIGP)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_istat))))) = (((0x20)))); | |||||
5194 | ||||||
5195 | /* | |||||
5196 | ** and reenable interrupts | |||||
5197 | */ | |||||
5198 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||||
5199 | ||||||
5200 | /* | |||||
5201 | ** Command is successfully queued. | |||||
5202 | */ | |||||
5203 | ||||||
5204 | return(DID_OK0x00); | |||||
5205 | } | |||||
5206 | ||||||
5207 | /*========================================================== | |||||
5208 | ** | |||||
5209 | ** | |||||
5210 | ** Start reset process. | |||||
5211 | ** If reset in progress do nothing. | |||||
5212 | ** The interrupt handler will reinitialize the chip. | |||||
5213 | ** The timeout handler will wait for settle_time before | |||||
5214 | ** clearing it and so resuming command processing. | |||||
5215 | ** | |||||
5216 | ** | |||||
5217 | **========================================================== | |||||
5218 | */ | |||||
5219 | static void ncr_start_reset(ncb_p np, int settle_delay) | |||||
5220 | { | |||||
5221 | u_longunsigned long flags; | |||||
5222 | ||||||
5223 | save_flags(flags)__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); cli()__asm__ __volatile__ ("cli": : :"memory"); | |||||
5224 | ||||||
5225 | if (!np->settle_time) { | |||||
5226 | (void) ncr_reset_scsi_bus(np, 1, settle_delay); | |||||
5227 | } | |||||
5228 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||||
5229 | } | |||||
5230 | ||||||
5231 | static int ncr_reset_scsi_bus(ncb_p np, int enab_int, int settle_delay) | |||||
5232 | { | |||||
5233 | u_int32 term; | |||||
5234 | int retv = 0; | |||||
5235 | ||||||
5236 | np->settle_time = jiffies + settle_delay * HZ100; | |||||
5237 | ||||||
5238 | if (bootverbose(np->verbose) > 1) | |||||
5239 | printfprintk("%s: resetting, " | |||||
5240 | "command processing suspended for %d seconds\n", | |||||
5241 | ncr_name(np), settle_delay); | |||||
5242 | ||||||
5243 | OUTB (nc_istat, SRST)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_istat))))) = (((0x40)))); | |||||
5244 | DELAY (1000); | |||||
5245 | OUTB (nc_istat, 0)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_istat))))) = (((0)))); | |||||
5246 | if (enab_int) | |||||
5247 | OUTW (nc_sien, RST)((*(volatile unsigned short *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_sien))))) = (((0x02)))); | |||||
5248 | /* | |||||
5249 | ** Enable Tolerant, reset IRQD if present and | |||||
5250 | ** properly set IRQ mode, prior to resetting the bus. | |||||
5251 | */ | |||||
5252 | OUTB (nc_stest3, TE)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_stest3))))) = (((0x80))) ); | |||||
5253 | OUTB (nc_dcntl, (np->rv_dcntl & IRQM))((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_dcntl))))) = ((((np-> rv_dcntl & 0x08))))); | |||||
5254 | OUTB (nc_scntl1, CRST)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_scntl1))))) = (((0x08))) ); | |||||
5255 | DELAY (100); | |||||
5256 | ||||||
5257 | if (!driver_setup.bus_check) | |||||
5258 | goto out; | |||||
5259 | /* | |||||
5260 | ** Check for no terminators or SCSI bus shorts to ground. | |||||
5261 | ** Read SCSI data bus, data parity bits and control signals. | |||||
5262 | ** We are expecting RESET to be TRUE and other signals to be | |||||
5263 | ** FALSE. | |||||
5264 | */ | |||||
5265 | term = INB(nc_sstat0)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_sstat0))))); /* rst, sdp0 */ | |||||
5266 | term = ((term & 2) << 7) + ((term & 1) << 16); | |||||
5267 | term |= ((INB(nc_sstat2)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_sstat2))))) & 0x01) << 25) | /* sdp1 */ | |||||
5268 | (INW(nc_sbdl)(*(volatile unsigned short *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_sbdl))))) << 9) | /* d15-0 */ | |||||
5269 | INB(nc_sbcl)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_sbcl))))); /* req, ack, bsy, sel, atn, msg, cd, io */ | |||||
5270 | ||||||
5271 | if (!(np->features & FE_WIDE(1<<1))) | |||||
5272 | term &= 0x3ffff; | |||||
5273 | ||||||
5274 | if (term != (2<<7)) { | |||||
5275 | printfprintk("%s: suspicious SCSI data while resetting the BUS.\n", | |||||
5276 | ncr_name(np)); | |||||
5277 | printfprintk("%s: %sdp0,d7-0,rst,req,ack,bsy,sel,atn,msg,c/d,i/o = " | |||||
5278 | "0x%lx, expecting 0x%lx\n", | |||||
5279 | ncr_name(np), | |||||
5280 | (np->features & FE_WIDE(1<<1)) ? "dp1,d15-8," : "", | |||||
5281 | (u_longunsigned long)term, (u_longunsigned long)(2<<7)); | |||||
5282 | if (driver_setup.bus_check == 1) | |||||
5283 | retv = 1; | |||||
5284 | } | |||||
5285 | out: | |||||
5286 | OUTB (nc_scntl1, 0)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_scntl1))))) = (((0)))); | |||||
5287 | return retv; | |||||
5288 | } | |||||
5289 | ||||||
5290 | /*========================================================== | |||||
5291 | ** | |||||
5292 | ** | |||||
5293 | ** Reset the SCSI BUS. | |||||
5294 | ** This is called from the generic SCSI driver. | |||||
5295 | ** | |||||
5296 | ** | |||||
5297 | **========================================================== | |||||
5298 | */ | |||||
5299 | int ncr_reset_bus (Scsi_Cmnd *cmd, int sync_reset) | |||||
5300 | { | |||||
5301 | struct Scsi_Host *host = cmd->host; | |||||
5302 | /* Scsi_Device *device = cmd->device; */ | |||||
5303 | struct host_data *host_data = (struct host_data *) host->hostdata; | |||||
5304 | ncb_p np = host_data->ncb; | |||||
5305 | ccb_p cp; | |||||
5306 | u_longunsigned long flags; | |||||
5307 | int found; | |||||
5308 | ||||||
5309 | #ifdef SCSI_NCR_DEBUG_ERROR_RECOVERY_SUPPORT | |||||
5310 | if (np->stalling) | |||||
5311 | np->stalling = 0; | |||||
5312 | #endif | |||||
5313 | ||||||
5314 | save_flags(flags)__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); cli()__asm__ __volatile__ ("cli": : :"memory"); | |||||
5315 | /* | |||||
5316 | * Return immediately if reset is in progress. | |||||
5317 | */ | |||||
5318 | if (np->settle_time) { | |||||
5319 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||||
5320 | return SCSI_RESET_PUNT1; | |||||
5321 | } | |||||
5322 | /* | |||||
5323 | * Start the reset process. | |||||
5324 | * The script processor is then assumed to be stopped. | |||||
5325 | * Commands will now be queued in the waiting list until a settle | |||||
5326 | * delay of 2 seconds will be completed. | |||||
5327 | */ | |||||
5328 | ncr_start_reset(np, driver_setup.settle_delay); | |||||
5329 | /* | |||||
5330 | * First, look in the wakeup list | |||||
5331 | */ | |||||
5332 | for (found=0, cp=np->ccb; cp; cp=cp->link_ccb) { | |||||
5333 | /* | |||||
5334 | ** look for the ccb of this command. | |||||
5335 | */ | |||||
5336 | if (cp->host_statusphys.header.status[1] == HS_IDLE(0)) continue; | |||||
5337 | if (cp->cmd == cmd) { | |||||
5338 | found = 1; | |||||
5339 | break; | |||||
5340 | } | |||||
5341 | } | |||||
5342 | /* | |||||
5343 | * Then, look in the waiting list | |||||
5344 | */ | |||||
5345 | if (!found && retrieve_from_waiting_list(0, np, cmd)) | |||||
5346 | found = 1; | |||||
5347 | /* | |||||
5348 | * Wake-up all awaiting commands with DID_RESET. | |||||
5349 | */ | |||||
5350 | reset_waiting_list(np)process_waiting_list((np), 0x08); | |||||
5351 | /* | |||||
5352 | * Wake-up all pending commands with HS_RESET -> DID_RESET. | |||||
5353 | */ | |||||
5354 | ncr_wakeup(np, HS_RESET(6)); | |||||
5355 | /* | |||||
5356 | * If the involved command was not in a driver queue, and the | |||||
5357 | * scsi driver told us reset is synchronous, and the command is not | |||||
5358 | * currently in the waiting list, complete it with DID_RESET status, | |||||
5359 | * in order to keep it alive. | |||||
5360 | */ | |||||
5361 | if (!found && sync_reset && !retrieve_from_waiting_list(0, np, cmd)) { | |||||
5362 | cmd->result = ScsiResult(DID_RESET, 0)(((0x08) << 16) + ((0) & 0x7f)); | |||||
5363 | cmd->scsi_done(cmd); | |||||
5364 | } | |||||
5365 | ||||||
5366 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||||
5367 | ||||||
5368 | return SCSI_RESET_SUCCESS2; | |||||
5369 | } | |||||
5370 | ||||||
5371 | /*========================================================== | |||||
5372 | ** | |||||
5373 | ** | |||||
5374 | ** Abort an SCSI command. | |||||
5375 | ** This is called from the generic SCSI driver. | |||||
5376 | ** | |||||
5377 | ** | |||||
5378 | **========================================================== | |||||
5379 | */ | |||||
5380 | static int ncr_abort_command (Scsi_Cmnd *cmd) | |||||
5381 | { | |||||
5382 | struct Scsi_Host *host = cmd->host; | |||||
5383 | /* Scsi_Device *device = cmd->device; */ | |||||
5384 | struct host_data *host_data = (struct host_data *) host->hostdata; | |||||
5385 | ncb_p np = host_data->ncb; | |||||
5386 | ccb_p cp; | |||||
5387 | u_longunsigned long flags; | |||||
5388 | int found; | |||||
5389 | int retv; | |||||
5390 | ||||||
5391 | #ifdef SCSI_NCR_DEBUG_ERROR_RECOVERY_SUPPORT | |||||
5392 | if (np->stalling == 2) | |||||
5393 | np->stalling = 0; | |||||
5394 | #endif | |||||
5395 | ||||||
5396 | save_flags(flags)__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); cli()__asm__ __volatile__ ("cli": : :"memory"); | |||||
5397 | /* | |||||
5398 | * First, look for the scsi command in the waiting list | |||||
5399 | */ | |||||
5400 | if (remove_from_waiting_list(np, cmd)retrieve_from_waiting_list(1, (np), (cmd))) { | |||||
5401 | cmd->result = ScsiResult(DID_ABORT, 0)(((0x05) << 16) + ((0) & 0x7f)); | |||||
5402 | cmd->scsi_done(cmd); | |||||
5403 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||||
5404 | return SCSI_ABORT_SUCCESS1; | |||||
5405 | } | |||||
5406 | ||||||
5407 | /* | |||||
5408 | * Then, look in the wakeup list | |||||
5409 | */ | |||||
5410 | for (found=0, cp=np->ccb; cp; cp=cp->link_ccb) { | |||||
5411 | /* | |||||
5412 | ** look for the ccb of this command. | |||||
5413 | */ | |||||
5414 | if (cp->host_statusphys.header.status[1] == HS_IDLE(0)) continue; | |||||
5415 | if (cp->cmd == cmd) { | |||||
5416 | found = 1; | |||||
5417 | break; | |||||
5418 | } | |||||
5419 | } | |||||
5420 | ||||||
5421 | if (!found) { | |||||
5422 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||||
5423 | return SCSI_ABORT_NOT_RUNNING4; | |||||
5424 | } | |||||
5425 | ||||||
5426 | if (np->settle_time) { | |||||
5427 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||||
5428 | return SCSI_ABORT_SNOOZE0; | |||||
5429 | } | |||||
5430 | ||||||
5431 | /* | |||||
5432 | ** Disable reselect. | |||||
5433 | ** Remove it from startqueue. | |||||
5434 | ** Set cp->tlimit to 0. The ncr_timeout() handler will use | |||||
5435 | ** this condition in order to complete the canceled command | |||||
5436 | ** after the script skipped the ccb, if necessary. | |||||
5437 | */ | |||||
5438 | cp->jump_ccb.l_cmd = cpu_to_scr(SCR_JUMP)(0x80080000); | |||||
5439 | if (cp->phys.header.launch.l_paddr == | |||||
5440 | cpu_to_scr(NCB_SCRIPT_PHYS (np, select))((np->p_script + ((size_t) (&((struct script *)0)-> select))))) { | |||||
5441 | printfprintk ("%s: abort ccb=%p (skip)\n", ncr_name (np), cp); | |||||
5442 | cp->phys.header.launch.l_paddr = | |||||
5443 | cpu_to_scr(NCB_SCRIPT_PHYS (np, skip))((np->p_script + ((size_t) (&((struct script *)0)-> skip)))); | |||||
5444 | } | |||||
5445 | ||||||
5446 | cp->tlimit = 0; | |||||
5447 | retv = SCSI_ABORT_PENDING2; | |||||
5448 | ||||||
5449 | /* | |||||
5450 | ** If there are no requests, the script | |||||
5451 | ** processor will sleep on SEL_WAIT_RESEL. | |||||
5452 | ** Let's wake it up, since it may have to work. | |||||
5453 | */ | |||||
5454 | #ifdef SCSI_NCR_DEBUG_ERROR_RECOVERY_SUPPORT | |||||
5455 | if (!np->stalling) | |||||
5456 | #endif | |||||
5457 | OUTB (nc_istat, SIGP)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_istat))))) = (((0x20)))); | |||||
5458 | ||||||
5459 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||||
5460 | ||||||
5461 | return retv; | |||||
5462 | } | |||||
5463 | ||||||
5464 | /*========================================================== | |||||
5465 | ** | |||||
5466 | ** Linux release module stuff. | |||||
5467 | ** | |||||
5468 | ** Called before unloading the module | |||||
5469 | ** Detach the host. | |||||
5470 | ** We have to free resources and halt the NCR chip | |||||
5471 | ** | |||||
5472 | **========================================================== | |||||
5473 | */ | |||||
5474 | ||||||
5475 | #ifdef MODULE | |||||
5476 | static int ncr_detach(ncb_p np) | |||||
5477 | { | |||||
5478 | ccb_p cp; | |||||
5479 | tcb_p tp; | |||||
5480 | lcb_p lp; | |||||
5481 | int target, lun; | |||||
5482 | int i; | |||||
5483 | ||||||
5484 | printfprintk("%s: releasing host resources\n", ncr_name(np)); | |||||
5485 | ||||||
5486 | /* | |||||
5487 | ** Stop the ncr_timeout process | |||||
5488 | ** Set release_stage to 1 and wait that ncr_timeout() set it to 2. | |||||
5489 | */ | |||||
5490 | ||||||
5491 | #ifdef DEBUG_NCR53C8XX | |||||
5492 | printfprintk("%s: stopping the timer\n", ncr_name(np)); | |||||
5493 | #endif | |||||
5494 | np->release_stage = 1; | |||||
5495 | for (i = 50 ; i && np->release_stage != 2 ; i--) DELAY(100000); | |||||
5496 | if (np->release_stage != 2) | |||||
5497 | printfprintk("%s: the timer seems to be already stopped\n", ncr_name(np)); | |||||
5498 | else np->release_stage = 2; | |||||
5499 | ||||||
5500 | /* | |||||
5501 | ** Disable chip interrupts | |||||
5502 | */ | |||||
5503 | ||||||
5504 | #ifdef DEBUG_NCR53C8XX | |||||
5505 | printfprintk("%s: disabling chip interrupts\n", ncr_name(np)); | |||||
5506 | #endif | |||||
5507 | OUTW (nc_sien , 0)((*(volatile unsigned short *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_sien))))) = (((0)))); | |||||
5508 | OUTB (nc_dien , 0)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_dien))))) = (((0)))); | |||||
5509 | ||||||
5510 | /* | |||||
5511 | ** Free irq | |||||
5512 | */ | |||||
5513 | ||||||
5514 | #ifdef DEBUG_NCR53C8XX | |||||
5515 | printfprintk("%s: freeing irq %d\n", ncr_name(np), np->irq); | |||||
5516 | #endif | |||||
5517 | #if LINUX_VERSION_CODE131108 >= LinuxVersionCode(1,3,70)(((1)<<16)+((3)<<8)+(70)) | |||||
5518 | free_irq(np->irq, np); | |||||
5519 | #else | |||||
5520 | free_irq(np->irq); | |||||
5521 | #endif | |||||
5522 | ||||||
5523 | /* | |||||
5524 | ** Reset NCR chip | |||||
5525 | ** Restore bios setting for automatic clock detection. | |||||
5526 | */ | |||||
5527 | ||||||
5528 | printfprintk("%s: resetting chip\n", ncr_name(np)); | |||||
5529 | OUTB (nc_istat, SRST)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_istat))))) = (((0x40)))); | |||||
5530 | DELAY (1000); | |||||
5531 | OUTB (nc_istat, 0 )((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_istat))))) = (((0)))); | |||||
5532 | ||||||
5533 | OUTB(nc_dmode, np->sv_dmode)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_dmode))))) = (((np->sv_dmode )))); | |||||
5534 | OUTB(nc_dcntl, np->sv_dcntl)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_dcntl))))) = (((np->sv_dcntl )))); | |||||
5535 | OUTB(nc_ctest3, np->sv_ctest3)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_ctest3))))) = (((np-> sv_ctest3)))); | |||||
5536 | OUTB(nc_ctest4, np->sv_ctest4)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_ctest4))))) = (((np-> sv_ctest4)))); | |||||
5537 | OUTB(nc_ctest5, np->sv_ctest5)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_ctest5))))) = (((np-> sv_ctest5)))); | |||||
5538 | OUTB(nc_gpcntl, np->sv_gpcntl)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_gpcntl))))) = (((np-> sv_gpcntl)))); | |||||
5539 | OUTB(nc_stest2, np->sv_stest2)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_stest2))))) = (((np-> sv_stest2)))); | |||||
5540 | ||||||
5541 | ncr_selectclock(np, np->sv_scntl3); | |||||
5542 | ||||||
5543 | /* | |||||
5544 | ** Release Memory mapped IO region and IO mapped region | |||||
5545 | */ | |||||
5546 | ||||||
5547 | #ifndef NCR_IOMAPPED | |||||
5548 | #ifdef DEBUG_NCR53C8XX | |||||
5549 | printfprintk("%s: releasing memory mapped IO region %lx[%d]\n", ncr_name(np), (u_longunsigned long) np->vaddr, 128); | |||||
5550 | #endif | |||||
5551 | unmap_pci_mem((vm_offset_t) np->vaddr, (u_longunsigned long) 128); | |||||
5552 | #ifdef DEBUG_NCR53C8XX | |||||
5553 | printfprintk("%s: releasing memory mapped IO region %lx[%d]\n", ncr_name(np), (u_longunsigned long) np->vaddr2, 4096); | |||||
5554 | #endif | |||||
5555 | unmap_pci_mem((vm_offset_t) np->vaddr2, (u_longunsigned long) 4096); | |||||
5556 | #endif | |||||
5557 | ||||||
5558 | #ifdef DEBUG_NCR53C8XX | |||||
5559 | printfprintk("%s: releasing IO region %x[%d]\n", ncr_name(np), np->port, 128); | |||||
5560 | #endif | |||||
5561 | release_region(np->port, 128); | |||||
5562 | ||||||
5563 | /* | |||||
5564 | ** Free allocated ccb(s) | |||||
5565 | */ | |||||
5566 | ||||||
5567 | while ((cp=np->ccb->link_ccb) != NULL((void *) 0)) { | |||||
5568 | np->ccb->link_ccb = cp->link_ccb; | |||||
5569 | if (cp->host_statusphys.header.status[1]) { | |||||
5570 | printfprintk("%s: shall free an active ccb (host_status=%d)\n", | |||||
5571 | ncr_name(np), cp->host_statusphys.header.status[1]); | |||||
5572 | } | |||||
5573 | #ifdef DEBUG_NCR53C8XX | |||||
5574 | printfprintk("%s: freeing ccb (%lx)\n", ncr_name(np), (u_longunsigned long) cp); | |||||
5575 | #endif | |||||
5576 | m_free(cp, sizeof(*cp)); | |||||
5577 | } | |||||
5578 | ||||||
5579 | /* | |||||
5580 | ** Free allocated tp(s) | |||||
5581 | */ | |||||
5582 | ||||||
5583 | for (target = 0; target < MAX_TARGET((16)) ; target++) { | |||||
5584 | tp=&np->target[target]; | |||||
5585 | for (lun = 0 ; lun < MAX_LUN(8) ; lun++) { | |||||
5586 | lp = tp->lp[lun]; | |||||
5587 | if (lp) { | |||||
5588 | #ifdef DEBUG_NCR53C8XX | |||||
5589 | printfprintk("%s: freeing lp (%lx)\n", ncr_name(np), (u_longunsigned long) lp); | |||||
5590 | #endif | |||||
5591 | m_free(lp, sizeof(*lp)); | |||||
5592 | } | |||||
5593 | } | |||||
5594 | } | |||||
5595 | ||||||
5596 | printfprintk("%s: host resources successfully released\n", ncr_name(np)); | |||||
5597 | ||||||
5598 | return 1; | |||||
5599 | } | |||||
5600 | #endif | |||||
5601 | ||||||
5602 | /*========================================================== | |||||
5603 | ** | |||||
5604 | ** | |||||
5605 | ** Complete execution of a SCSI command. | |||||
5606 | ** Signal completion to the generic SCSI driver. | |||||
5607 | ** | |||||
5608 | ** | |||||
5609 | **========================================================== | |||||
5610 | */ | |||||
5611 | ||||||
5612 | void ncr_complete (ncb_p np, ccb_p cp) | |||||
5613 | { | |||||
5614 | Scsi_Cmnd *cmd; | |||||
5615 | tcb_p tp; | |||||
5616 | lcb_p lp; | |||||
5617 | ||||||
5618 | /* | |||||
5619 | ** Sanity check | |||||
5620 | */ | |||||
5621 | ||||||
5622 | if (!cp || (cp->magic!=CCB_MAGIC(0xf2691ad2)) || !cp->cmd) return; | |||||
5623 | cp->magic = 1; | |||||
5624 | cp->tlimit= 0; | |||||
5625 | cmd = cp->cmd; | |||||
5626 | ||||||
5627 | /* | |||||
5628 | ** No Reselect anymore. | |||||
5629 | */ | |||||
5630 | cp->jump_ccb.l_cmd = cpu_to_scr(SCR_JUMP)(0x80080000); | |||||
5631 | ||||||
5632 | /* | |||||
5633 | ** No starting. | |||||
5634 | */ | |||||
5635 | cp->phys.header.launch.l_paddr = cpu_to_scr(NCB_SCRIPT_PHYS (np, idle))((np->p_script + ((size_t) (&((struct script *)0)-> idle)))); | |||||
5636 | ||||||
5637 | /* | |||||
5638 | ** timestamp | |||||
5639 | ** Optional, spare some CPU time | |||||
5640 | */ | |||||
5641 | #ifdef SCSI_NCR_PROFILE_SUPPORT | |||||
5642 | ncb_profile (np, cp); | |||||
5643 | #endif | |||||
5644 | ||||||
5645 | if (DEBUG_FLAGSncr_debug & DEBUG_TINY(0x0080)) | |||||
5646 | printfprintk ("CCB=%lx STAT=%x/%x\n", (unsigned long)cp & 0xfff, | |||||
5647 | cp->host_statusphys.header.status[1],cp->scsi_statusphys.header.status[2]); | |||||
5648 | ||||||
5649 | cmd = cp->cmd; | |||||
5650 | cp->cmd = NULL((void *) 0); | |||||
5651 | tp = &np->target[cmd->target]; | |||||
5652 | lp = tp->lp[cmd->lun]; | |||||
5653 | ||||||
5654 | /* | |||||
5655 | ** We donnot queue more than 1 ccb per target | |||||
5656 | ** with negotiation at any time. If this ccb was | |||||
5657 | ** used for negotiation, clear this info in the tcb. | |||||
5658 | */ | |||||
5659 | ||||||
5660 | if (cp == tp->nego_cp) | |||||
5661 | tp->nego_cp = 0; | |||||
5662 | ||||||
5663 | /* | |||||
5664 | ** Check for parity errors. | |||||
5665 | */ | |||||
5666 | ||||||
5667 | if (cp->parity_statusphys.header.status[3]) { | |||||
5668 | PRINT_ADDR(cmd); | |||||
5669 | printfprintk ("%d parity error(s), fallback.\n", cp->parity_statusphys.header.status[3]); | |||||
5670 | /* | |||||
5671 | ** fallback to asynch transfer. | |||||
5672 | */ | |||||
5673 | tp->usrsync=255; | |||||
5674 | tp->period = 0; | |||||
5675 | } | |||||
5676 | ||||||
5677 | /* | |||||
5678 | ** Check for extended errors. | |||||
5679 | */ | |||||
5680 | ||||||
5681 | if (cp->xerr_statusphys.header.scr_st[0] != XE_OK(0)) { | |||||
5682 | PRINT_ADDR(cmd); | |||||
5683 | switch (cp->xerr_statusphys.header.scr_st[0]) { | |||||
5684 | case XE_EXTRA_DATA(1): | |||||
5685 | printfprintk ("extraneous data discarded.\n"); | |||||
5686 | break; | |||||
5687 | case XE_BAD_PHASE(2): | |||||
5688 | printfprintk ("illegal scsi phase (4/5).\n"); | |||||
5689 | break; | |||||
5690 | default: | |||||
5691 | printfprintk ("extended error %d.\n", cp->xerr_statusphys.header.scr_st[0]); | |||||
5692 | break; | |||||
5693 | } | |||||
5694 | if (cp->host_statusphys.header.status[1]==HS_COMPLETE(4)) | |||||
5695 | cp->host_statusphys.header.status[1] = HS_FAIL(9); | |||||
5696 | } | |||||
5697 | ||||||
5698 | /* | |||||
5699 | ** Check the status. | |||||
5700 | */ | |||||
5701 | if ( (cp->host_statusphys.header.status[1] == HS_COMPLETE(4)) | |||||
5702 | && (cp->scsi_statusphys.header.status[2] == S_GOOD(0x00) || | |||||
5703 | cp->scsi_statusphys.header.status[2] == S_COND_MET(0x04))) { | |||||
5704 | /* | |||||
5705 | ** All went well (GOOD status). | |||||
5706 | ** CONDITION MET status is returned on | |||||
5707 | ** `Pre-Fetch' or `Search data' success. | |||||
5708 | */ | |||||
5709 | cmd->result = ScsiResult(DID_OK, cp->scsi_status)(((0x00) << 16) + ((cp->phys.header.status[2]) & 0x7f)); | |||||
5710 | ||||||
5711 | /* | |||||
5712 | ** if (cp->phys.header.lastp != cp->phys.header.goalp)... | |||||
5713 | ** | |||||
5714 | ** @RESID@ | |||||
5715 | ** Could dig out the correct value for resid, | |||||
5716 | ** but it would be quite complicated. | |||||
5717 | ** | |||||
5718 | ** The ah1542.c driver sets it to 0 too ... | |||||
5719 | */ | |||||
5720 | ||||||
5721 | /* | |||||
5722 | ** Try to assign a ccb to this nexus | |||||
5723 | */ | |||||
5724 | ncr_alloc_ccb (np, cmd->target, cmd->lun); | |||||
5725 | ||||||
5726 | /* | |||||
5727 | ** On inquire cmd (0x12) save some data. | |||||
5728 | ** Clear questionnable capacities. | |||||
5729 | */ | |||||
5730 | if (cmd->lun == 0 && cmd->cmnd[0] == 0x12) { | |||||
5731 | if (np->unit < SCSI_NCR_MAX_HOST(2)) { | |||||
5732 | if (driver_setup.force_sync_nego) | |||||
5733 | ((char *) cmd->request_buffer)[7] |= INQ7_SYNC(0x10); | |||||
5734 | else | |||||
5735 | ((char *) cmd->request_buffer)[7] &= | |||||
5736 | (target_capabilities[np->unit].and_map[cmd->target]); | |||||
5737 | } | |||||
5738 | bcopy ( cmd->request_buffer,(__builtin_constant_p((sizeof (tp->inqdata))) ? __constant_memcpy (((&tp->inqdata)),((cmd->request_buffer)),((sizeof ( tp->inqdata)))) : __memcpy(((&tp->inqdata)),((cmd-> request_buffer)),((sizeof (tp->inqdata))))) | |||||
5739 | &tp->inqdata,(__builtin_constant_p((sizeof (tp->inqdata))) ? __constant_memcpy (((&tp->inqdata)),((cmd->request_buffer)),((sizeof ( tp->inqdata)))) : __memcpy(((&tp->inqdata)),((cmd-> request_buffer)),((sizeof (tp->inqdata))))) | |||||
5740 | sizeof (tp->inqdata))(__builtin_constant_p((sizeof (tp->inqdata))) ? __constant_memcpy (((&tp->inqdata)),((cmd->request_buffer)),((sizeof ( tp->inqdata)))) : __memcpy(((&tp->inqdata)),((cmd-> request_buffer)),((sizeof (tp->inqdata))))); | |||||
5741 | ||||||
5742 | /* | |||||
5743 | ** set number of tags | |||||
5744 | */ | |||||
5745 | ncr_setmaxtags (np, tp, driver_setup.default_tags); | |||||
5746 | /* | |||||
5747 | ** prepare negotiation of synch and wide. | |||||
5748 | */ | |||||
5749 | ncr_negotiate (np, tp); | |||||
5750 | ||||||
5751 | /* | |||||
5752 | ** force quirks update before next command start | |||||
5753 | */ | |||||
5754 | tp->quirks |= QUIRK_UPDATE(0x80); | |||||
5755 | } | |||||
5756 | ||||||
5757 | /* | |||||
5758 | ** Announce changes to the generic driver. | |||||
5759 | */ | |||||
5760 | if (lp) { | |||||
5761 | ncr_settags (tp, lp); | |||||
5762 | if (lp->reqlink != lp->actlink) | |||||
5763 | ncr_opennings (np, lp, cmd); | |||||
5764 | }; | |||||
5765 | ||||||
5766 | tp->bytes += cp->data_len; | |||||
5767 | tp->transfers ++; | |||||
5768 | ||||||
5769 | /* | |||||
5770 | ** If tags was reduced due to queue full, | |||||
5771 | ** increase tags if 100 good status received. | |||||
5772 | */ | |||||
5773 | if (tp->numtags < tp->maxtags) { | |||||
5774 | ++tp->num_good; | |||||
5775 | if (tp->num_good >= 100) { | |||||
5776 | tp->num_good = 0; | |||||
5777 | ++tp->numtags; | |||||
5778 | if (tp->numtags == 1) { | |||||
5779 | PRINT_ADDR(cmd); | |||||
5780 | printfprintk("tagged command queueing resumed\n"); | |||||
5781 | } | |||||
5782 | } | |||||
5783 | } | |||||
5784 | } else if ((cp->host_statusphys.header.status[1] == HS_COMPLETE(4)) | |||||
5785 | && (cp->scsi_statusphys.header.status[2] == (S_SENSE(0x80)|S_GOOD(0x00)) || | |||||
5786 | cp->scsi_statusphys.header.status[2] == (S_SENSE(0x80)|S_CHECK_COND(0x02)))) { | |||||
5787 | ||||||
5788 | /* | |||||
5789 | ** Check condition code | |||||
5790 | */ | |||||
5791 | cmd->result = ScsiResult(DID_OK, S_CHECK_COND)(((0x00) << 16) + (((0x02)) & 0x7f)); | |||||
5792 | ||||||
5793 | if (DEBUG_FLAGSncr_debug & (DEBUG_RESULT(0x0010)|DEBUG_TINY(0x0080))) { | |||||
5794 | u_charunsigned char * p = (u_charunsigned char*) & cmd->sense_buffer; | |||||
5795 | int i; | |||||
5796 | printfprintk ("\n%s: sense data:", ncr_name (np)); | |||||
5797 | for (i=0; i<14; i++) printfprintk (" %x", *p++); | |||||
5798 | printfprintk (".\n"); | |||||
5799 | } | |||||
5800 | ||||||
5801 | } else if ((cp->host_statusphys.header.status[1] == HS_COMPLETE(4)) | |||||
5802 | && (cp->scsi_statusphys.header.status[2] == S_BUSY(0x08) || | |||||
5803 | cp->scsi_statusphys.header.status[2] == S_CONFLICT(0x18))) { | |||||
5804 | ||||||
5805 | /* | |||||
5806 | ** Target is busy. | |||||
5807 | */ | |||||
5808 | cmd->result = ScsiResult(DID_OK, cp->scsi_status)(((0x00) << 16) + ((cp->phys.header.status[2]) & 0x7f)); | |||||
5809 | ||||||
5810 | } else if ((cp->host_statusphys.header.status[1] == HS_COMPLETE(4)) | |||||
5811 | && (cp->scsi_statusphys.header.status[2] == S_QUEUE_FULL(0x28))) { | |||||
5812 | ||||||
5813 | /* | |||||
5814 | ** Target is stuffed. | |||||
5815 | */ | |||||
5816 | cmd->result = ScsiResult(DID_OK, cp->scsi_status)(((0x00) << 16) + ((cp->phys.header.status[2]) & 0x7f)); | |||||
5817 | ||||||
5818 | /* | |||||
5819 | ** Suspend tagged queuing and start good status counter. | |||||
5820 | ** Announce changes to the generic driver. | |||||
5821 | */ | |||||
5822 | if (tp->numtags) { | |||||
5823 | PRINT_ADDR(cmd); | |||||
5824 | printfprintk("QUEUE FULL! suspending tagged command queueing\n"); | |||||
5825 | tp->numtags = 0; | |||||
5826 | tp->num_good = 0; | |||||
5827 | if (lp) { | |||||
5828 | ncr_settags (tp, lp); | |||||
5829 | if (lp->reqlink != lp->actlink) | |||||
5830 | ncr_opennings (np, lp, cmd); | |||||
5831 | }; | |||||
5832 | } | |||||
5833 | } else if ((cp->host_statusphys.header.status[1] == HS_SEL_TIMEOUT(5)) | |||||
5834 | || (cp->host_statusphys.header.status[1] == HS_TIMEOUT(8))) { | |||||
5835 | ||||||
5836 | /* | |||||
5837 | ** No response | |||||
5838 | */ | |||||
5839 | cmd->result = ScsiResult(DID_TIME_OUT, cp->scsi_status)(((0x03) << 16) + ((cp->phys.header.status[2]) & 0x7f)); | |||||
5840 | ||||||
5841 | } else if (cp->host_statusphys.header.status[1] == HS_RESET(6)) { | |||||
5842 | ||||||
5843 | /* | |||||
5844 | ** SCSI bus reset | |||||
5845 | */ | |||||
5846 | cmd->result = ScsiResult(DID_RESET, cp->scsi_status)(((0x08) << 16) + ((cp->phys.header.status[2]) & 0x7f)); | |||||
5847 | ||||||
5848 | } else if (cp->host_statusphys.header.status[1] == HS_ABORTED(7)) { | |||||
5849 | ||||||
5850 | /* | |||||
5851 | ** Transfer aborted | |||||
5852 | */ | |||||
5853 | cmd->result = ScsiResult(DID_ABORT, cp->scsi_status)(((0x05) << 16) + ((cp->phys.header.status[2]) & 0x7f)); | |||||
5854 | ||||||
5855 | } else { | |||||
5856 | ||||||
5857 | /* | |||||
5858 | ** Other protocol messes | |||||
5859 | */ | |||||
5860 | PRINT_ADDR(cmd); | |||||
5861 | printfprintk ("COMMAND FAILED (%x %x) @%p.\n", | |||||
5862 | cp->host_statusphys.header.status[1], cp->scsi_statusphys.header.status[2], cp); | |||||
5863 | ||||||
5864 | cmd->result = ScsiResult(DID_ERROR, cp->scsi_status)(((0x07) << 16) + ((cp->phys.header.status[2]) & 0x7f)); | |||||
5865 | } | |||||
5866 | ||||||
5867 | /* | |||||
5868 | ** trace output | |||||
5869 | */ | |||||
5870 | ||||||
5871 | if (tp->usrflag & UF_TRACE(0x01)) { | |||||
5872 | u_charunsigned char * p; | |||||
5873 | int i; | |||||
5874 | PRINT_ADDR(cmd); | |||||
5875 | printfprintk (" CMD:"); | |||||
5876 | p = (u_charunsigned char*) &cmd->cmnd[0]; | |||||
5877 | for (i=0; i<cmd->cmd_len; i++) printfprintk (" %x", *p++); | |||||
5878 | ||||||
5879 | if (cp->host_statusphys.header.status[1]==HS_COMPLETE(4)) { | |||||
5880 | switch (cp->scsi_statusphys.header.status[2]) { | |||||
5881 | case S_GOOD(0x00): | |||||
5882 | printfprintk (" GOOD"); | |||||
5883 | break; | |||||
5884 | case S_CHECK_COND(0x02): | |||||
5885 | printfprintk (" SENSE:"); | |||||
5886 | p = (u_charunsigned char*) &cmd->sense_buffer; | |||||
5887 | for (i=0; i<14; i++) | |||||
5888 | printfprintk (" %x", *p++); | |||||
5889 | break; | |||||
5890 | default: | |||||
5891 | printfprintk (" STAT: %x\n", cp->scsi_statusphys.header.status[2]); | |||||
5892 | break; | |||||
5893 | } | |||||
5894 | } else printfprintk (" HOSTERROR: %x", cp->host_statusphys.header.status[1]); | |||||
5895 | printfprintk ("\n"); | |||||
5896 | } | |||||
5897 | ||||||
5898 | /* | |||||
5899 | ** Free this ccb | |||||
5900 | */ | |||||
5901 | ncr_free_ccb (np, cp, cmd->target, cmd->lun); | |||||
5902 | ||||||
5903 | /* | |||||
5904 | ** requeue awaiting scsi commands | |||||
5905 | */ | |||||
5906 | if (np->waiting_list) requeue_waiting_list(np)process_waiting_list((np), 0x00); | |||||
5907 | ||||||
5908 | /* | |||||
5909 | ** signal completion to generic driver. | |||||
5910 | */ | |||||
5911 | cmd->scsi_done (cmd); | |||||
5912 | } | |||||
5913 | ||||||
5914 | /*========================================================== | |||||
5915 | ** | |||||
5916 | ** | |||||
5917 | ** Signal all (or one) control block done. | |||||
5918 | ** | |||||
5919 | ** | |||||
5920 | **========================================================== | |||||
5921 | */ | |||||
5922 | ||||||
5923 | void ncr_wakeup (ncb_p np, u_longunsigned long code) | |||||
5924 | { | |||||
5925 | /* | |||||
5926 | ** Starting at the default ccb and following | |||||
5927 | ** the links, complete all jobs with a | |||||
5928 | ** host_status greater than "disconnect". | |||||
5929 | ** | |||||
5930 | ** If the "code" parameter is not zero, | |||||
5931 | ** complete all jobs that are not IDLE. | |||||
5932 | */ | |||||
5933 | ||||||
5934 | ccb_p cp = np->ccb; | |||||
5935 | while (cp) { | |||||
5936 | switch (cp->host_statusphys.header.status[1]) { | |||||
5937 | ||||||
5938 | case HS_IDLE(0): | |||||
5939 | break; | |||||
5940 | ||||||
5941 | case HS_DISCONNECT(3): | |||||
5942 | if(DEBUG_FLAGSncr_debug & DEBUG_TINY(0x0080)) printfprintk ("D"); | |||||
5943 | /* fall through */ | |||||
5944 | ||||||
5945 | case HS_BUSY(1): | |||||
5946 | case HS_NEGOTIATE(2): | |||||
5947 | if (!code) break; | |||||
5948 | cp->host_statusphys.header.status[1] = code; | |||||
5949 | ||||||
5950 | /* fall through */ | |||||
5951 | ||||||
5952 | default: | |||||
5953 | ncr_complete (np, cp); | |||||
5954 | break; | |||||
5955 | }; | |||||
5956 | cp = cp -> link_ccb; | |||||
5957 | }; | |||||
5958 | } | |||||
5959 | ||||||
5960 | /*========================================================== | |||||
5961 | ** | |||||
5962 | ** | |||||
5963 | ** Start NCR chip. | |||||
5964 | ** | |||||
5965 | ** | |||||
5966 | **========================================================== | |||||
5967 | */ | |||||
5968 | ||||||
5969 | void ncr_init (ncb_p np, int reset, char * msg, u_longunsigned long code) | |||||
5970 | { | |||||
5971 | int i; | |||||
5972 | ||||||
5973 | /* | |||||
5974 | ** Reset chip if asked, otherwise just clear fifos. | |||||
5975 | */ | |||||
5976 | if (reset) { | |||||
5977 | OUTB (nc_istat, SRST)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_istat))))) = (((0x40)))); | |||||
5978 | DELAY (10000); | |||||
5979 | } | |||||
5980 | else { | |||||
5981 | OUTB (nc_stest3, TE|CSF)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_stest3))))) = (((0x80|0x02 )))); | |||||
5982 | OUTONB (nc_ctest3, CLF)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_ctest3))))) = ((((*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_ctest3))))) | (0x04))))); | |||||
5983 | } | |||||
5984 | ||||||
5985 | /* | |||||
5986 | ** Message. | |||||
5987 | */ | |||||
5988 | ||||||
5989 | if (msg) printfprintk (KERN_INFO"<6>" "%s: restart (%s).\n", ncr_name (np), msg); | |||||
5990 | ||||||
5991 | /* | |||||
5992 | ** Clear Start Queue | |||||
5993 | */ | |||||
5994 | for (i=0;i<MAX_START((7*(4)) + 4);i++) | |||||
5995 | np -> squeue [i] = cpu_to_scr(NCB_SCRIPT_PHYS (np, idle))((np->p_script + ((size_t) (&((struct script *)0)-> idle)))); | |||||
5996 | ||||||
5997 | /* | |||||
5998 | ** Start at first entry. | |||||
5999 | */ | |||||
6000 | np->squeueput = 0; | |||||
6001 | np->script0->startpos[0] = cpu_to_scr(NCB_SCRIPTH_PHYS (np, tryloop))((np->p_scripth + ((size_t) (&((struct scripth *)0)-> tryloop)))); | |||||
6002 | np->script0->start0 [0] = cpu_to_scr(SCR_INT ^ IFFALSE (0))(0x98080000 ^ (0x00080000 | (0))); | |||||
6003 | ||||||
6004 | /* | |||||
6005 | ** Wakeup all pending jobs. | |||||
6006 | */ | |||||
6007 | ncr_wakeup (np, code); | |||||
6008 | ||||||
6009 | /* | |||||
6010 | ** Init chip. | |||||
6011 | */ | |||||
6012 | ||||||
6013 | OUTB (nc_istat, 0x00 )((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_istat))))) = (((0x00)))); /* Remove Reset, abort */ | |||||
6014 | OUTB (nc_scntl0, np->rv_scntl0 | 0xc0)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_scntl0))))) = (((np-> rv_scntl0 | 0xc0)))); | |||||
6015 | /* full arb., ena parity, par->ATN */ | |||||
6016 | OUTB (nc_scntl1, 0x00)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_scntl1))))) = (((0x00))) ); /* odd parity, and remove CRST!! */ | |||||
6017 | ||||||
6018 | ncr_selectclock(np, np->rv_scntl3); /* Select SCSI clock */ | |||||
6019 | ||||||
6020 | OUTB (nc_scid , RRE|np->myaddr)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_scid))))) = (((0x40|np-> myaddr)))); /* Adapter SCSI address */ | |||||
6021 | OUTW (nc_respid, 1ul<<np->myaddr)((*(volatile unsigned short *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_respid))))) = (((1ul<< np->myaddr)))); /* Id to respond to */ | |||||
6022 | OUTB (nc_istat , SIGP )((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_istat))))) = (((0x20)))); /* Signal Process */ | |||||
6023 | OUTB (nc_dmode , np->rv_dmode)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_dmode))))) = (((np->rv_dmode )))); /* Burst length, dma mode */ | |||||
6024 | OUTB (nc_ctest5, np->rv_ctest5)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_ctest5))))) = (((np-> rv_ctest5)))); /* Large fifo + large burst */ | |||||
6025 | ||||||
6026 | OUTB (nc_dcntl , NOCOM|np->rv_dcntl)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_dcntl))))) = (((0x01|np-> rv_dcntl)))); /* Protect SFBR */ | |||||
6027 | OUTB (nc_ctest3, np->rv_ctest3)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_ctest3))))) = (((np-> rv_ctest3)))); /* Write and invalidate */ | |||||
6028 | OUTB (nc_ctest4, np->rv_ctest4)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_ctest4))))) = (((np-> rv_ctest4)))); /* Master parity checking */ | |||||
6029 | ||||||
6030 | OUTB (nc_stest2, EXT|np->rv_stest2)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_stest2))))) = (((0x02|np ->rv_stest2)))); /* Extended Sreq/Sack filtering */ | |||||
6031 | OUTB (nc_stest3, TE)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_stest3))))) = (((0x80))) ); /* TolerANT enable */ | |||||
6032 | OUTB (nc_stime0, 0x0d )((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_stime0))))) = (((0x0d))) ); /* HTH disabled STO 0.4 sec. */ | |||||
6033 | ||||||
6034 | /* | |||||
6035 | ** Disable disconnects. | |||||
6036 | */ | |||||
6037 | ||||||
6038 | np->disc = 0; | |||||
6039 | ||||||
6040 | /* | |||||
6041 | ** Enable GPIO0 pin for writing if LED support. | |||||
6042 | */ | |||||
6043 | ||||||
6044 | if (np->features & FE_LED0(1<<0)) { | |||||
6045 | OUTOFFB (nc_gpcntl, 0x01)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_gpcntl))))) = ((((*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_gpcntl))))) & ~(0x01))))); | |||||
6046 | } | |||||
6047 | ||||||
6048 | /* | |||||
6049 | ** Upload the script into on-board RAM | |||||
6050 | */ | |||||
6051 | if (np->vaddr2) { | |||||
6052 | if (bootverbose(np->verbose)) | |||||
6053 | printfprintk ("%s: copying script fragments into the on-board RAM ...\n", ncr_name(np)); | |||||
6054 | #if LINUX_VERSION_CODE131108 >= LinuxVersionCode(2,0,0)(((2)<<16)+((0)<<8)+(0)) | |||||
6055 | memcpy_toio(np->script, np->script0, sizeof(struct script))(__builtin_constant_p((sizeof(struct script))) ? __constant_memcpy (((void *)(np->script)),((np->script0)),((sizeof(struct script)))) : __memcpy(((void *)(np->script)),((np->script0 )),((sizeof(struct script))))); | |||||
6056 | #else | |||||
6057 | memcpy(np->script, np->script0, sizeof(struct script))(__builtin_constant_p(sizeof(struct script)) ? __constant_memcpy ((np->script),(np->script0),(sizeof(struct script))) : __memcpy ((np->script),(np->script0),(sizeof(struct script)))); | |||||
6058 | #endif | |||||
6059 | } | |||||
6060 | ||||||
6061 | /* | |||||
6062 | ** enable ints | |||||
6063 | */ | |||||
6064 | ||||||
6065 | OUTW (nc_sien , STO|HTH|MA|SGE|UDC|RST)((*(volatile unsigned short *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_sien))))) = (((0x0400|0x0100 |0x80|0x08|0x04|0x02)))); | |||||
6066 | OUTB (nc_dien , MDPE|BF|ABRT|SSI|SIR|IID)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_dien))))) = (((0x40|0x20 |0x10|0x08|0x04|0x01)))); | |||||
6067 | ||||||
6068 | /* | |||||
6069 | ** For 895/6 enable SBMC interrupt and save current SCSI bus mode. | |||||
6070 | */ | |||||
6071 | if (np->features & FE_ULTRA2(1<<3)) { | |||||
6072 | OUTONW (nc_sien, SBMC)((*(volatile unsigned short *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_sien))))) = ((((*(volatile unsigned short *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_sien))))) | (0x1000))))); | |||||
6073 | np->scsi_mode = INB (nc_stest4)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_stest4))))) & SMODE0xc0; | |||||
6074 | } | |||||
6075 | ||||||
6076 | /* | |||||
6077 | ** Fill in target structure. | |||||
6078 | ** Reinitialize usrsync. | |||||
6079 | ** Reinitialize usrwide. | |||||
6080 | ** Prepare sync negotiation according to actual SCSI bus mode. | |||||
6081 | */ | |||||
6082 | ||||||
6083 | for (i=0;i<MAX_TARGET((16));i++) { | |||||
6084 | tcb_p tp = &np->target[i]; | |||||
6085 | ||||||
6086 | tp->sval = 0; | |||||
6087 | tp->wval = np->rv_scntl3; | |||||
6088 | ||||||
6089 | if (tp->usrsync != 255) { | |||||
6090 | if (tp->usrsync <= np->maxsync) { | |||||
6091 | if (tp->usrsync < np->minsync) { | |||||
6092 | tp->usrsync = np->minsync; | |||||
6093 | } | |||||
6094 | } | |||||
6095 | else | |||||
6096 | tp->usrsync = 255; | |||||
6097 | }; | |||||
6098 | ||||||
6099 | if (tp->usrwide > np->maxwide) | |||||
6100 | tp->usrwide = np->maxwide; | |||||
6101 | ||||||
6102 | ncr_negotiate (np, tp); | |||||
6103 | } | |||||
6104 | ||||||
6105 | /* | |||||
6106 | ** Start script processor. | |||||
6107 | */ | |||||
6108 | ||||||
6109 | OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, start))((*(volatile unsigned int *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_dsp))))) = ((((np->p_script + ((size_t) (&((struct script *)0)->start))))))); | |||||
6110 | } | |||||
6111 | ||||||
6112 | /*========================================================== | |||||
6113 | ** | |||||
6114 | ** Prepare the negotiation values for wide and | |||||
6115 | ** synchronous transfers. | |||||
6116 | ** | |||||
6117 | **========================================================== | |||||
6118 | */ | |||||
6119 | ||||||
6120 | static void ncr_negotiate (struct ncb* np, struct tcb* tp) | |||||
6121 | { | |||||
6122 | /* | |||||
6123 | ** minsync unit is 4ns ! | |||||
6124 | */ | |||||
6125 | ||||||
6126 | u_longunsigned long minsync = tp->usrsync; | |||||
6127 | ||||||
6128 | /* | |||||
6129 | ** SCSI bus mode limit | |||||
6130 | */ | |||||
6131 | ||||||
6132 | if (np->scsi_mode && np->scsi_mode == SMODE_SE0x80) { | |||||
6133 | if (minsync < 12) minsync = 12; | |||||
6134 | } | |||||
6135 | ||||||
6136 | /* | |||||
6137 | ** if not scsi 2 | |||||
6138 | ** don't believe FAST! | |||||
6139 | */ | |||||
6140 | ||||||
6141 | if ((minsync < 50) && (tp->inqdata[2] & 0x0f) < 2) | |||||
6142 | minsync=50; | |||||
6143 | ||||||
6144 | /* | |||||
6145 | ** our limit .. | |||||
6146 | */ | |||||
6147 | ||||||
6148 | if (minsync < np->minsync) | |||||
6149 | minsync = np->minsync; | |||||
6150 | ||||||
6151 | /* | |||||
6152 | ** divider limit | |||||
6153 | */ | |||||
6154 | ||||||
6155 | if (minsync > np->maxsync) | |||||
6156 | minsync = 255; | |||||
6157 | ||||||
6158 | tp->minsync = minsync; | |||||
6159 | tp->maxoffs = (minsync<255 ? np->maxoffs : 0); | |||||
6160 | ||||||
6161 | /* | |||||
6162 | ** period=0: has to negotiate sync transfer | |||||
6163 | */ | |||||
6164 | ||||||
6165 | tp->period=0; | |||||
6166 | ||||||
6167 | /* | |||||
6168 | ** widedone=0: has to negotiate wide transfer | |||||
6169 | */ | |||||
6170 | tp->widedone=0; | |||||
6171 | } | |||||
6172 | ||||||
6173 | /*========================================================== | |||||
6174 | ** | |||||
6175 | ** Get clock factor and sync divisor for a given | |||||
6176 | ** synchronous factor period. | |||||
6177 | ** Returns the clock factor (in sxfer) and scntl3 | |||||
6178 | ** synchronous divisor field. | |||||
6179 | ** | |||||
6180 | **========================================================== | |||||
6181 | */ | |||||
6182 | ||||||
6183 | static void ncr_getsync(ncb_p np, u_charunsigned char sfac, u_charunsigned char *fakp, u_charunsigned char *scntl3p) | |||||
6184 | { | |||||
6185 | u_longunsigned long clk = np->clock_khz; /* SCSI clock frequency in kHz */ | |||||
6186 | int div = np->clock_divn; /* Number of divisors supported */ | |||||
6187 | u_longunsigned long fak; /* Sync factor in sxfer */ | |||||
6188 | u_longunsigned long per; /* Period in tenths of ns */ | |||||
6189 | u_longunsigned long kpc; /* (per * clk) */ | |||||
6190 | ||||||
6191 | /* | |||||
6192 | ** Compute the synchronous period in tenths of nano-seconds | |||||
6193 | */ | |||||
6194 | if (sfac <= 10) per = 250; | |||||
6195 | else if (sfac == 11) per = 303; | |||||
6196 | else if (sfac == 12) per = 500; | |||||
6197 | else per = 40 * sfac; | |||||
6198 | ||||||
6199 | /* | |||||
6200 | ** Look for the greatest clock divisor that allows an | |||||
6201 | ** input speed faster than the period. | |||||
6202 | */ | |||||
6203 | kpc = per * clk; | |||||
6204 | while (--div >= 0) | |||||
6205 | if (kpc >= (div_10M[div] << 2)) break; | |||||
6206 | ||||||
6207 | /* | |||||
6208 | ** Calculate the lowest clock factor that allows an output | |||||
6209 | ** speed not faster than the period. | |||||
6210 | */ | |||||
6211 | fak = (kpc - 1) / div_10M[div] + 1; | |||||
6212 | ||||||
6213 | #if 0 /* This optimization does not seem very usefull */ | |||||
6214 | ||||||
6215 | per = (fak * div_10M[div]) / clk; | |||||
6216 | ||||||
6217 | /* | |||||
6218 | ** Why not to try the immediate lower divisor and to choose | |||||
6219 | ** the one that allows the fastest output speed ? | |||||
6220 | ** We don't want input speed too much greater than output speed. | |||||
6221 | */ | |||||
6222 | if (div >= 1 && fak < 8) { | |||||
6223 | u_longunsigned long fak2, per2; | |||||
6224 | fak2 = (kpc - 1) / div_10M[div-1] + 1; | |||||
6225 | per2 = (fak2 * div_10M[div-1]) / clk; | |||||
6226 | if (per2 < per && fak2 <= 8) { | |||||
6227 | fak = fak2; | |||||
6228 | per = per2; | |||||
6229 | --div; | |||||
6230 | } | |||||
6231 | } | |||||
6232 | #endif | |||||
6233 | ||||||
6234 | if (fak < 4) fak = 4; /* Should never happen, too bad ... */ | |||||
6235 | ||||||
6236 | /* | |||||
6237 | ** Compute and return sync parameters for the ncr | |||||
6238 | */ | |||||
6239 | *fakp = fak - 4; | |||||
6240 | *scntl3p = ((div+1) << 4) + (sfac < 25 ? 0x80 : 0); | |||||
6241 | } | |||||
6242 | ||||||
6243 | ||||||
6244 | /*========================================================== | |||||
6245 | ** | |||||
6246 | ** Set actual values, sync status and patch all ccbs of | |||||
6247 | ** a target according to new sync/wide agreement. | |||||
6248 | ** | |||||
6249 | **========================================================== | |||||
6250 | */ | |||||
6251 | ||||||
6252 | static void ncr_set_sync_wide_status (ncb_p np, u_charunsigned char target) | |||||
6253 | { | |||||
6254 | ccb_p cp; | |||||
6255 | tcb_p tp = &np->target[target]; | |||||
6256 | ||||||
6257 | /* | |||||
6258 | ** set actual value and sync_status | |||||
6259 | */ | |||||
6260 | OUTB (nc_sxfer, tp->sval)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_sxfer))))) = (((tp->sval )))); | |||||
6261 | np->sync_stheader.scr_st[1] = tp->sval; | |||||
6262 | OUTB (nc_scntl3, tp->wval)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_scntl3))))) = (((tp-> wval)))); | |||||
6263 | np->wide_stheader.scr_st[3] = tp->wval; | |||||
6264 | ||||||
6265 | /* | |||||
6266 | ** patch ALL ccbs of this target. | |||||
6267 | */ | |||||
6268 | for (cp = np->ccb; cp; cp = cp->link_ccb) { | |||||
6269 | if (!cp->cmd) continue; | |||||
6270 | if (cp->cmd->target != target) continue; | |||||
6271 | cp->sync_statusphys.header.scr_st[1] = tp->sval; | |||||
6272 | cp->wide_statusphys.header.scr_st[3] = tp->wval; | |||||
6273 | }; | |||||
6274 | } | |||||
6275 | ||||||
6276 | /*========================================================== | |||||
6277 | ** | |||||
6278 | ** Switch sync mode for current job and it's target | |||||
6279 | ** | |||||
6280 | **========================================================== | |||||
6281 | */ | |||||
6282 | ||||||
6283 | static void ncr_setsync (ncb_p np, ccb_p cp, u_charunsigned char scntl3, u_charunsigned char sxfer) | |||||
6284 | { | |||||
6285 | Scsi_Cmnd *cmd; | |||||
6286 | tcb_p tp; | |||||
6287 | u_charunsigned char target = INB (nc_ctest0)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_ctest0))))) & 0x0f; | |||||
6288 | u_charunsigned char idiv; | |||||
6289 | ||||||
6290 | assert (cp){ if (!(cp)) { (void)printk( "assertion \"%s\" failed: file \"%s\", line %d\n" , "cp", "../linux/src/drivers/scsi/ncr53c8xx.c", 6290); } }; | |||||
6291 | if (!cp) return; | |||||
6292 | ||||||
6293 | cmd = cp->cmd; | |||||
6294 | assert (cmd){ if (!(cmd)) { (void)printk( "assertion \"%s\" failed: file \"%s\", line %d\n" , "cmd", "../linux/src/drivers/scsi/ncr53c8xx.c", 6294); } }; | |||||
6295 | if (!cmd) return; | |||||
6296 | assert (target == (cmd->target & 0xf)){ if (!(target == (cmd->target & 0xf))) { (void)printk ( "assertion \"%s\" failed: file \"%s\", line %d\n", "target == (cmd->target & 0xf)" , "../linux/src/drivers/scsi/ncr53c8xx.c", 6296); } }; | |||||
6297 | ||||||
6298 | tp = &np->target[target]; | |||||
6299 | ||||||
6300 | if (!scntl3 || !(sxfer & 0x1f)) | |||||
6301 | scntl3 = np->rv_scntl3; | |||||
6302 | scntl3 = (scntl3 & 0xf0) | (tp->wval & EWS0x08) | (np->rv_scntl3 & 0x07); | |||||
6303 | ||||||
6304 | /* | |||||
6305 | ** Deduce the value of controller sync period from scntl3. | |||||
6306 | ** period is in tenths of nano-seconds. | |||||
6307 | */ | |||||
6308 | ||||||
6309 | idiv = ((scntl3 >> 4) & 0x7); | |||||
6310 | if ((sxfer & 0x1f) && idiv) | |||||
6311 | tp->period = (((sxfer>>5)+4)*div_10M[idiv-1])/np->clock_khz; | |||||
6312 | else | |||||
6313 | tp->period = 0xffff; | |||||
6314 | ||||||
6315 | /* | |||||
6316 | ** Stop there if sync parameters are unchanged | |||||
6317 | */ | |||||
6318 | if (tp->sval == sxfer && tp->wval == scntl3) return; | |||||
6319 | tp->sval = sxfer; | |||||
6320 | tp->wval = scntl3; | |||||
6321 | ||||||
6322 | /* | |||||
6323 | ** Bells and whistles ;-) | |||||
6324 | */ | |||||
6325 | PRINT_ADDR(cmd); | |||||
6326 | if (sxfer & 0x01f) { | |||||
6327 | unsigned f10 = 100000 << (tp->widedone ? tp->widedone -1 : 0); | |||||
6328 | unsigned mb10 = (f10 + tp->period/2) / tp->period; | |||||
6329 | char *scsi; | |||||
6330 | ||||||
6331 | /* | |||||
6332 | ** Disable extended Sreq/Sack filtering | |||||
6333 | */ | |||||
6334 | if (tp->period <= 2000) OUTOFFB (nc_stest2, EXT)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_stest2))))) = ((((*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_stest2))))) & ~(0x02))))); | |||||
6335 | ||||||
6336 | /* | |||||
6337 | ** Bells and whistles ;-) | |||||
6338 | */ | |||||
6339 | if (tp->period < 500) scsi = "FAST-40"; | |||||
6340 | else if (tp->period < 1000) scsi = "FAST-20"; | |||||
6341 | else if (tp->period < 2000) scsi = "FAST-10"; | |||||
6342 | else scsi = "FAST-5"; | |||||
6343 | ||||||
6344 | printfprintk ("%s %sSCSI %d.%d MB/s (%d ns, offset %d)\n", scsi, | |||||
6345 | tp->widedone > 1 ? "WIDE " : "", | |||||
6346 | mb10 / 10, mb10 % 10, tp->period / 10, sxfer & 0x1f); | |||||
6347 | } else | |||||
6348 | printfprintk ("%sasynchronous.\n", tp->widedone > 1 ? "wide " : ""); | |||||
6349 | ||||||
6350 | /* | |||||
6351 | ** set actual value and sync_status | |||||
6352 | ** patch ALL ccbs of this target. | |||||
6353 | */ | |||||
6354 | ncr_set_sync_wide_status(np, target); | |||||
6355 | } | |||||
6356 | ||||||
6357 | /*========================================================== | |||||
6358 | ** | |||||
6359 | ** Switch wide mode for current job and it's target | |||||
6360 | ** SCSI specs say: a SCSI device that accepts a WDTR | |||||
6361 | ** message shall reset the synchronous agreement to | |||||
6362 | ** asynchronous mode. | |||||
6363 | ** | |||||
6364 | **========================================================== | |||||
6365 | */ | |||||
6366 | ||||||
6367 | static void ncr_setwide (ncb_p np, ccb_p cp, u_charunsigned char wide, u_charunsigned char ack) | |||||
6368 | { | |||||
6369 | Scsi_Cmnd *cmd; | |||||
6370 | u_shortunsigned short target = INB (nc_ctest0)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_ctest0))))) & 0x0f; | |||||
6371 | tcb_p tp; | |||||
6372 | u_charunsigned char scntl3; | |||||
6373 | u_charunsigned char sxfer; | |||||
6374 | ||||||
6375 | assert (cp){ if (!(cp)) { (void)printk( "assertion \"%s\" failed: file \"%s\", line %d\n" , "cp", "../linux/src/drivers/scsi/ncr53c8xx.c", 6375); } }; | |||||
6376 | if (!cp) return; | |||||
6377 | ||||||
6378 | cmd = cp->cmd; | |||||
6379 | assert (cmd){ if (!(cmd)) { (void)printk( "assertion \"%s\" failed: file \"%s\", line %d\n" , "cmd", "../linux/src/drivers/scsi/ncr53c8xx.c", 6379); } }; | |||||
6380 | if (!cmd) return; | |||||
6381 | assert (target == (cmd->target & 0xf)){ if (!(target == (cmd->target & 0xf))) { (void)printk ( "assertion \"%s\" failed: file \"%s\", line %d\n", "target == (cmd->target & 0xf)" , "../linux/src/drivers/scsi/ncr53c8xx.c", 6381); } }; | |||||
6382 | ||||||
6383 | tp = &np->target[target]; | |||||
6384 | tp->widedone = wide+1; | |||||
6385 | scntl3 = (tp->wval & (~EWS0x08)) | (wide ? EWS0x08 : 0); | |||||
6386 | ||||||
6387 | sxfer = ack ? 0 : tp->sval; | |||||
6388 | ||||||
6389 | /* | |||||
6390 | ** Stop there if sync/wide parameters are unchanged | |||||
6391 | */ | |||||
6392 | if (tp->sval == sxfer && tp->wval == scntl3) return; | |||||
6393 | tp->sval = sxfer; | |||||
6394 | tp->wval = scntl3; | |||||
6395 | ||||||
6396 | /* | |||||
6397 | ** Bells and whistles ;-) | |||||
6398 | */ | |||||
6399 | if (bootverbose(np->verbose) >= 2) { | |||||
6400 | PRINT_ADDR(cmd); | |||||
6401 | if (scntl3 & EWS0x08) | |||||
6402 | printfprintk ("WIDE SCSI (16 bit) enabled.\n"); | |||||
6403 | else | |||||
6404 | printfprintk ("WIDE SCSI disabled.\n"); | |||||
6405 | } | |||||
6406 | ||||||
6407 | /* | |||||
6408 | ** set actual value and sync_status | |||||
6409 | ** patch ALL ccbs of this target. | |||||
6410 | */ | |||||
6411 | ncr_set_sync_wide_status(np, target); | |||||
6412 | } | |||||
6413 | ||||||
6414 | /*========================================================== | |||||
6415 | ** | |||||
6416 | ** Switch tagged mode for a target. | |||||
6417 | ** | |||||
6418 | **========================================================== | |||||
6419 | */ | |||||
6420 | ||||||
6421 | static void ncr_setmaxtags (ncb_p np, tcb_p tp, u_longunsigned long numtags) | |||||
6422 | { | |||||
6423 | int l; | |||||
6424 | if (numtags > tp->usrtags) | |||||
6425 | numtags = tp->usrtags; | |||||
6426 | tp->numtags = numtags; | |||||
6427 | tp->maxtags = numtags; | |||||
6428 | ||||||
6429 | for (l=0; l<MAX_LUN(8); l++) { | |||||
6430 | lcb_p lp; | |||||
6431 | u_charunsigned char wastags; | |||||
6432 | ||||||
6433 | if (!tp) break; | |||||
6434 | lp=tp->lp[l]; | |||||
6435 | if (!lp) continue; | |||||
6436 | ||||||
6437 | wastags = lp->usetags; | |||||
6438 | ncr_settags (tp, lp); | |||||
6439 | ||||||
6440 | if (numtags > 1 && lp->reqccbs > 1) { | |||||
6441 | PRINT_LUN(np, tp - np->target, l)printk("<6>" "%s-<%d,%d>: ", ncr_name(np), (int) ( tp - np->target), (int) (l)); | |||||
6442 | printfprintk("using tagged command queueing, up to %ld cmds/lun\n", numtags); | |||||
6443 | } | |||||
6444 | else if (numtags <= 1 && wastags) { | |||||
6445 | PRINT_LUN(np, tp - np->target, l)printk("<6>" "%s-<%d,%d>: ", ncr_name(np), (int) ( tp - np->target), (int) (l)); | |||||
6446 | printfprintk("disabling tagged command queueing\n"); | |||||
6447 | } | |||||
6448 | }; | |||||
6449 | } | |||||
6450 | ||||||
6451 | static void ncr_settags (tcb_p tp, lcb_p lp) | |||||
6452 | { | |||||
6453 | u_charunsigned char reqtags, tmp; | |||||
6454 | ||||||
6455 | if ((!tp) || (!lp)) return; | |||||
6456 | ||||||
6457 | /* | |||||
6458 | ** only devices conformant to ANSI Version >= 2 | |||||
6459 | ** only devices capable of tagges commands | |||||
6460 | ** only disk devices | |||||
6461 | ** only if enabled by user .. | |||||
6462 | */ | |||||
6463 | if (( tp->inqdata[2] & 0x7) >= 2 && | |||||
6464 | ( tp->inqdata[7] & INQ7_QUEUE(0x02)) && ((tp->inqdata[0] & 0x1f)==0x00) | |||||
6465 | && tp->numtags > 1) { | |||||
6466 | reqtags = tp->numtags; | |||||
6467 | if (lp->actlink <= 1) | |||||
6468 | lp->usetags=reqtags; | |||||
6469 | } else { | |||||
6470 | reqtags = 1; | |||||
6471 | if (lp->actlink <= 1) | |||||
6472 | lp->usetags=0; | |||||
6473 | }; | |||||
6474 | ||||||
6475 | /* | |||||
6476 | ** don't announce more than available. | |||||
6477 | */ | |||||
6478 | tmp = lp->actccbs; | |||||
6479 | if (tmp > reqtags) tmp = reqtags; | |||||
6480 | lp->reqlink = tmp; | |||||
6481 | ||||||
6482 | /* | |||||
6483 | ** don't discard if announced. | |||||
6484 | */ | |||||
6485 | tmp = lp->actlink; | |||||
6486 | if (tmp < reqtags) tmp = reqtags; | |||||
6487 | lp->reqccbs = tmp; | |||||
6488 | } | |||||
6489 | ||||||
6490 | /*---------------------------------------------------- | |||||
6491 | ** | |||||
6492 | ** handle user commands | |||||
6493 | ** | |||||
6494 | **---------------------------------------------------- | |||||
6495 | */ | |||||
6496 | ||||||
6497 | #ifdef SCSI_NCR_USER_COMMAND_SUPPORT | |||||
6498 | ||||||
6499 | static void ncr_usercmd (ncb_p np) | |||||
6500 | { | |||||
6501 | u_charunsigned char t; | |||||
6502 | tcb_p tp; | |||||
6503 | ||||||
6504 | switch (np->user.cmd) { | |||||
6505 | ||||||
6506 | case 0: return; | |||||
6507 | ||||||
6508 | case UC_SETSYNC10: | |||||
6509 | for (t=0; t<MAX_TARGET((16)); t++) { | |||||
6510 | if (!((np->user.target>>t)&1)) continue; | |||||
6511 | tp = &np->target[t]; | |||||
6512 | tp->usrsync = np->user.data; | |||||
6513 | ncr_negotiate (np, tp); | |||||
6514 | }; | |||||
6515 | break; | |||||
6516 | ||||||
6517 | case UC_SETTAGS11: | |||||
6518 | if (np->user.data > SCSI_NCR_MAX_TAGS(4)) | |||||
6519 | np->user.data = SCSI_NCR_MAX_TAGS(4); | |||||
6520 | for (t=0; t<MAX_TARGET((16)); t++) { | |||||
6521 | if (!((np->user.target>>t)&1)) continue; | |||||
6522 | np->target[t].usrtags = np->user.data; | |||||
6523 | ncr_setmaxtags (np, &np->target[t], np->user.data); | |||||
6524 | }; | |||||
6525 | break; | |||||
6526 | ||||||
6527 | case UC_SETDEBUG12: | |||||
6528 | #ifdef SCSI_NCR_DEBUG_INFO_SUPPORT | |||||
6529 | ncr_debug = np->user.data; | |||||
6530 | #endif | |||||
6531 | break; | |||||
6532 | ||||||
6533 | case UC_SETORDER13: | |||||
6534 | np->order = np->user.data; | |||||
6535 | break; | |||||
6536 | ||||||
6537 | case UC_SETWIDE14: | |||||
6538 | for (t=0; t<MAX_TARGET((16)); t++) { | |||||
6539 | u_longunsigned long size; | |||||
6540 | if (!((np->user.target>>t)&1)) continue; | |||||
6541 | tp = &np->target[t]; | |||||
6542 | size = np->user.data; | |||||
6543 | if (size > np->maxwide) size=np->maxwide; | |||||
6544 | tp->usrwide = size; | |||||
6545 | ncr_negotiate (np, tp); | |||||
6546 | }; | |||||
6547 | break; | |||||
6548 | ||||||
6549 | case UC_SETFLAG15: | |||||
6550 | for (t=0; t<MAX_TARGET((16)); t++) { | |||||
6551 | if (!((np->user.target>>t)&1)) continue; | |||||
6552 | tp = &np->target[t]; | |||||
6553 | tp->usrflag = np->user.data; | |||||
6554 | }; | |||||
6555 | break; | |||||
6556 | ||||||
6557 | case UC_CLEARPROF16: | |||||
6558 | bzero(&np->profile, sizeof(np->profile))(__builtin_constant_p(0) ? (__builtin_constant_p(((sizeof(np-> profile)))) ? __constant_c_and_count_memset((((&np->profile ))),((0x01010101UL*(unsigned char)(0))),(((sizeof(np->profile ))))) : __constant_c_memset((((&np->profile))),((0x01010101UL *(unsigned char)(0))),(((sizeof(np->profile)))))) : (__builtin_constant_p (((sizeof(np->profile)))) ? __memset_generic(((((&np-> profile)))),(((0))),((((sizeof(np->profile)))))) : __memset_generic ((((&np->profile))),((0)),(((sizeof(np->profile)))) ))); | |||||
6559 | break; | |||||
6560 | #ifdef UC_DEBUG_ERROR_RECOVERY | |||||
6561 | case UC_DEBUG_ERROR_RECOVERY: | |||||
6562 | np->debug_error_recovery = np->user.data; | |||||
6563 | break; | |||||
6564 | #endif | |||||
6565 | } | |||||
6566 | np->user.cmd=0; | |||||
6567 | } | |||||
6568 | #endif | |||||
6569 | ||||||
6570 | ||||||
6571 | /*===================================================================== | |||||
6572 | ** | |||||
6573 | ** Embedded error recovery debugging code. | |||||
6574 | ** | |||||
6575 | **===================================================================== | |||||
6576 | ** | |||||
6577 | ** This code is conditionned by SCSI_NCR_DEBUG_ERROR_RECOVERY_SUPPORT. | |||||
6578 | ** It only can be enabled after boot-up with a control command. | |||||
6579 | ** | |||||
6580 | ** Every 30 seconds the timer handler of the driver decides to | |||||
6581 | ** change the behaviour of the driver in order to trigger errors. | |||||
6582 | ** | |||||
6583 | ** If last command was "debug_error_recovery sge", the driver | |||||
6584 | ** sets sync offset of all targets that use sync transfers to 2, | |||||
6585 | ** and so hopes a SCSI gross error at the next read operation. | |||||
6586 | ** | |||||
6587 | ** If last command was "debug_error_recovery abort", the driver | |||||
6588 | ** does not signal new scsi commands to the script processor, until | |||||
6589 | ** it is asked to abort or reset a command by the mid-level driver. | |||||
6590 | ** | |||||
6591 | ** If last command was "debug_error_recovery reset", the driver | |||||
6592 | ** does not signal new scsi commands to the script processor, until | |||||
6593 | ** it is asked to reset a command by the mid-level driver. | |||||
6594 | ** | |||||
6595 | ** If last command was "debug_error_recovery parity", the driver | |||||
6596 | ** will assert ATN on the next DATA IN phase mismatch, and so will | |||||
6597 | ** behave as if a parity error had been detected. | |||||
6598 | ** | |||||
6599 | ** The command "debug_error_recovery none" makes the driver behave | |||||
6600 | ** normaly. | |||||
6601 | ** | |||||
6602 | **===================================================================== | |||||
6603 | */ | |||||
6604 | ||||||
6605 | #ifdef SCSI_NCR_DEBUG_ERROR_RECOVERY_SUPPORT | |||||
6606 | static void ncr_trigger_errors (ncb_p np) | |||||
6607 | { | |||||
6608 | /* | |||||
6609 | ** If np->debug_error_recovery is not zero, we want to | |||||
6610 | ** simulate common errors in order to test error recovery. | |||||
6611 | */ | |||||
6612 | do { | |||||
6613 | static u_longunsigned long last = 0l; | |||||
6614 | ||||||
6615 | if (!np->debug_error_recovery) | |||||
6616 | break; | |||||
6617 | if (!last) | |||||
6618 | last = jiffies; | |||||
6619 | else if (jiffies < last + 30*HZ100) | |||||
6620 | break; | |||||
6621 | last = jiffies; | |||||
6622 | /* | |||||
6623 | * This one triggers SCSI gross errors. | |||||
6624 | */ | |||||
6625 | if (np->debug_error_recovery == 1) { | |||||
6626 | int i; | |||||
6627 | printfprintk("%s: testing error recovery from SCSI gross error...\n", ncr_name(np)); | |||||
6628 | for (i = 0 ; i < MAX_TARGET((16)) ; i++) { | |||||
6629 | if (np->target[i].sval & 0x1f) { | |||||
6630 | np->target[i].sval &= ~0x1f; | |||||
6631 | np->target[i].sval += 2; | |||||
6632 | } | |||||
6633 | } | |||||
6634 | } | |||||
6635 | /* | |||||
6636 | * This one triggers abort from the mid-level driver. | |||||
6637 | */ | |||||
6638 | else if (np->debug_error_recovery == 2) { | |||||
6639 | printfprintk("%s: testing error recovery from mid-level driver abort()...\n", ncr_name(np)); | |||||
6640 | np->stalling = 2; | |||||
6641 | } | |||||
6642 | /* | |||||
6643 | * This one triggers reset from the mid-level driver. | |||||
6644 | */ | |||||
6645 | else if (np->debug_error_recovery == 3) { | |||||
6646 | printfprintk("%s: testing error recovery from mid-level driver reset()...\n", ncr_name(np)); | |||||
6647 | np->stalling = 3; | |||||
6648 | } | |||||
6649 | /* | |||||
6650 | * This one set ATN on phase mismatch in DATA IN phase and so | |||||
6651 | * will behave as on scsi parity error detected. | |||||
6652 | */ | |||||
6653 | else if (np->debug_error_recovery == 4) { | |||||
6654 | printfprintk("%s: testing data in parity error...\n", ncr_name(np)); | |||||
6655 | np->assert_atn = 1; | |||||
6656 | } | |||||
6657 | } while (0); | |||||
6658 | } | |||||
6659 | #endif | |||||
6660 | ||||||
6661 | /*========================================================== | |||||
6662 | ** | |||||
6663 | ** | |||||
6664 | ** ncr timeout handler. | |||||
6665 | ** | |||||
6666 | ** | |||||
6667 | **========================================================== | |||||
6668 | ** | |||||
6669 | ** Misused to keep the driver running when | |||||
6670 | ** interrupts are not configured correctly. | |||||
6671 | ** | |||||
6672 | **---------------------------------------------------------- | |||||
6673 | */ | |||||
6674 | ||||||
6675 | static void ncr_timeout (ncb_p np) | |||||
6676 | { | |||||
6677 | u_longunsigned long thistime = jiffies; | |||||
6678 | u_longunsigned long count = 0; | |||||
6679 | ccb_p cp; | |||||
6680 | u_longunsigned long flags; | |||||
6681 | ||||||
6682 | /* | |||||
6683 | ** If release process in progress, let's go | |||||
6684 | ** Set the release stage from 1 to 2 to synchronize | |||||
6685 | ** with the release process. | |||||
6686 | */ | |||||
6687 | ||||||
6688 | if (np->release_stage) { | |||||
6689 | if (np->release_stage == 1) np->release_stage = 2; | |||||
6690 | return; | |||||
6691 | } | |||||
6692 | ||||||
6693 | np->timer.expires = | |||||
6694 | #if LINUX_VERSION_CODE131108 >= LinuxVersionCode(1,3,0)(((1)<<16)+((3)<<8)+(0)) | |||||
6695 | jiffies + | |||||
6696 | #endif | |||||
6697 | SCSI_NCR_TIMER_INTERVAL((100 +5 -1)/5); | |||||
6698 | ||||||
6699 | add_timer(&np->timer); | |||||
6700 | ||||||
6701 | #ifdef SCSI_NCR_DEBUG_ERROR_RECOVERY_SUPPORT | |||||
6702 | ncr_trigger_errors (np); | |||||
6703 | #endif | |||||
6704 | ||||||
6705 | /* | |||||
6706 | ** If we are resetting the ncr, wait for settle_time before | |||||
6707 | ** clearing it. Then command processing will be resumed. | |||||
6708 | */ | |||||
6709 | if (np->settle_time) { | |||||
6710 | if (np->settle_time <= thistime) { | |||||
6711 | if (bootverbose(np->verbose) > 1) | |||||
6712 | printfprintk("%s: command processing resumed\n", ncr_name(np)); | |||||
6713 | save_flags(flags)__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); cli()__asm__ __volatile__ ("cli": : :"memory"); | |||||
6714 | np->settle_time = 0; | |||||
6715 | np->disc = 1; | |||||
6716 | requeue_waiting_list(np)process_waiting_list((np), 0x00); | |||||
6717 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||||
6718 | } | |||||
6719 | return; | |||||
6720 | } | |||||
6721 | ||||||
6722 | /* | |||||
6723 | ** Since the generic scsi driver only allows us 0.5 second | |||||
6724 | ** to perform abort of a command, we must look at ccbs about | |||||
6725 | ** every 0.25 second. | |||||
6726 | */ | |||||
6727 | if (np->lasttime + (HZ100>>2) <= thistime) { | |||||
6728 | /* | |||||
6729 | ** block ncr interrupts | |||||
6730 | */ | |||||
6731 | save_flags(flags)__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); cli()__asm__ __volatile__ ("cli": : :"memory"); | |||||
6732 | ||||||
6733 | np->lasttime = thistime; | |||||
6734 | ||||||
6735 | /* | |||||
6736 | ** Reset profile data to avoid ugly overflow | |||||
6737 | ** (Limited to 1024 GB for 32 bit architecture) | |||||
6738 | */ | |||||
6739 | if (np->profile.num_kbytes > (~0UL >> 2)) | |||||
6740 | bzero(&np->profile, sizeof(np->profile))(__builtin_constant_p(0) ? (__builtin_constant_p(((sizeof(np-> profile)))) ? __constant_c_and_count_memset((((&np->profile ))),((0x01010101UL*(unsigned char)(0))),(((sizeof(np->profile ))))) : __constant_c_memset((((&np->profile))),((0x01010101UL *(unsigned char)(0))),(((sizeof(np->profile)))))) : (__builtin_constant_p (((sizeof(np->profile)))) ? __memset_generic(((((&np-> profile)))),(((0))),((((sizeof(np->profile)))))) : __memset_generic ((((&np->profile))),((0)),(((sizeof(np->profile)))) ))); | |||||
6741 | ||||||
6742 | /*---------------------------------------------------- | |||||
6743 | ** | |||||
6744 | ** handle ncr chip timeouts | |||||
6745 | ** | |||||
6746 | ** Assumption: | |||||
6747 | ** We have a chance to arbitrate for the | |||||
6748 | ** SCSI bus at least every 10 seconds. | |||||
6749 | ** | |||||
6750 | **---------------------------------------------------- | |||||
6751 | */ | |||||
6752 | #if 0 | |||||
6753 | if (thistime < np->heartbeat + HZ100 + HZ100) | |||||
6754 | np->latetime = 0; | |||||
6755 | else | |||||
6756 | np->latetime++; | |||||
6757 | #endif | |||||
6758 | ||||||
6759 | /*---------------------------------------------------- | |||||
6760 | ** | |||||
6761 | ** handle ccb timeouts | |||||
6762 | ** | |||||
6763 | **---------------------------------------------------- | |||||
6764 | */ | |||||
6765 | ||||||
6766 | for (cp=np->ccb; cp; cp=cp->link_ccb) { | |||||
6767 | /* | |||||
6768 | ** look for timed out ccbs. | |||||
6769 | */ | |||||
6770 | if (!cp->host_statusphys.header.status[1]) continue; | |||||
6771 | count++; | |||||
6772 | /* | |||||
6773 | ** Have to force ordered tag to avoid timeouts | |||||
6774 | */ | |||||
6775 | if (cp->cmd && cp->tlimit && cp->tlimit <= | |||||
6776 | thistime + NCR_TIMEOUT_INCREASE(5*100) + SCSI_NCR_TIMEOUT_ALERT(3*100)) { | |||||
6777 | lcb_p lp; | |||||
6778 | lp = np->target[cp->cmd->target].lp[cp->cmd->lun]; | |||||
6779 | if (lp && !lp->force_ordered_tag) { | |||||
6780 | lp->force_ordered_tag = 1; | |||||
6781 | } | |||||
6782 | } | |||||
6783 | /* | |||||
6784 | ** ncr_abort_command() cannot complete canceled | |||||
6785 | ** commands immediately. It sets tlimit to zero | |||||
6786 | ** and ask the script to skip the scsi process if | |||||
6787 | ** necessary. We have to complete this work here. | |||||
6788 | */ | |||||
6789 | ||||||
6790 | if (cp->tlimit) continue; | |||||
6791 | ||||||
6792 | switch (cp->host_statusphys.header.status[1]) { | |||||
6793 | ||||||
6794 | case HS_BUSY(1): | |||||
6795 | case HS_NEGOTIATE(2): | |||||
6796 | /* | |||||
6797 | ** still in start queue ? | |||||
6798 | */ | |||||
6799 | if (cp->phys.header.launch.l_paddr == | |||||
6800 | cpu_to_scr(NCB_SCRIPT_PHYS (np, skip))((np->p_script + ((size_t) (&((struct script *)0)-> skip))))) | |||||
6801 | continue; | |||||
6802 | ||||||
6803 | /* fall through */ | |||||
6804 | case HS_DISCONNECT(3): | |||||
6805 | cp->host_statusphys.header.status[1]=HS_ABORTED(7); | |||||
6806 | }; | |||||
6807 | cp->tag = 0; | |||||
6808 | ||||||
6809 | /* | |||||
6810 | ** wakeup this ccb. | |||||
6811 | */ | |||||
6812 | ncr_complete (np, cp); | |||||
6813 | ||||||
6814 | #ifdef SCSI_NCR_DEBUG_ERROR_RECOVERY_SUPPORT | |||||
6815 | if (!np->stalling) | |||||
6816 | #endif | |||||
6817 | OUTB (nc_istat, SIGP)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_istat))))) = (((0x20)))); | |||||
6818 | } | |||||
6819 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||||
6820 | } | |||||
6821 | ||||||
6822 | #ifdef SCSI_NCR_BROKEN_INTR | |||||
6823 | if (INB(nc_istat)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_istat))))) & (INTF0x04|SIP0x02|DIP0x01)) { | |||||
6824 | ||||||
6825 | /* | |||||
6826 | ** Process pending interrupts. | |||||
6827 | */ | |||||
6828 | save_flags(flags)__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); cli()__asm__ __volatile__ ("cli": : :"memory"); | |||||
6829 | if (DEBUG_FLAGSncr_debug & DEBUG_TINY(0x0080)) printfprintk ("{"); | |||||
6830 | ncr_exception (np); | |||||
6831 | if (DEBUG_FLAGSncr_debug & DEBUG_TINY(0x0080)) printfprintk ("}"); | |||||
6832 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||||
6833 | } | |||||
6834 | #endif /* SCSI_NCR_BROKEN_INTR */ | |||||
6835 | } | |||||
6836 | ||||||
6837 | /*========================================================== | |||||
6838 | ** | |||||
6839 | ** log message for real hard errors | |||||
6840 | ** | |||||
6841 | ** "ncr0 targ 0?: ERROR (ds:si) (so-si-sd) (sxfer/scntl3) @ name (dsp:dbc)." | |||||
6842 | ** " reg: r0 r1 r2 r3 r4 r5 r6 ..... rf." | |||||
6843 | ** | |||||
6844 | ** exception register: | |||||
6845 | ** ds: dstat | |||||
6846 | ** si: sist | |||||
6847 | ** | |||||
6848 | ** SCSI bus lines: | |||||
6849 | ** so: control lines as driver by NCR. | |||||
6850 | ** si: control lines as seen by NCR. | |||||
6851 | ** sd: scsi data lines as seen by NCR. | |||||
6852 | ** | |||||
6853 | ** wide/fastmode: | |||||
6854 | ** sxfer: (see the manual) | |||||
6855 | ** scntl3: (see the manual) | |||||
6856 | ** | |||||
6857 | ** current script command: | |||||
6858 | ** dsp: script adress (relative to start of script). | |||||
6859 | ** dbc: first word of script command. | |||||
6860 | ** | |||||
6861 | ** First 16 register of the chip: | |||||
6862 | ** r0..rf | |||||
6863 | ** | |||||
6864 | **========================================================== | |||||
6865 | */ | |||||
6866 | ||||||
6867 | static void ncr_log_hard_error(ncb_p np, u_shortunsigned short sist, u_charunsigned char dstat) | |||||
6868 | { | |||||
6869 | u_int32 dsp; | |||||
6870 | int script_ofs; | |||||
6871 | int script_size; | |||||
6872 | char *script_name; | |||||
6873 | u_charunsigned char *script_base; | |||||
6874 | int i; | |||||
6875 | ||||||
6876 | dsp = INL (nc_dsp)(*(volatile unsigned int *) ((char *)np->reg + (((size_t) ( &((struct ncr_reg *)0)->nc_dsp))))); | |||||
6877 | ||||||
6878 | if (dsp > np->p_script && dsp <= np->p_script + sizeof(struct script)) { | |||||
6879 | script_ofs = dsp - np->p_script; | |||||
6880 | script_size = sizeof(struct script); | |||||
6881 | script_base = (u_charunsigned char *) np->script; | |||||
6882 | script_name = "script"; | |||||
6883 | } | |||||
6884 | else if (np->p_scripth < dsp && | |||||
6885 | dsp <= np->p_scripth + sizeof(struct scripth)) { | |||||
6886 | script_ofs = dsp - np->p_scripth; | |||||
6887 | script_size = sizeof(struct scripth); | |||||
6888 | script_base = (u_charunsigned char *) np->scripth; | |||||
6889 | script_name = "scripth"; | |||||
6890 | } else { | |||||
6891 | script_ofs = dsp; | |||||
6892 | script_size = 0; | |||||
6893 | script_base = 0; | |||||
6894 | script_name = "mem"; | |||||
6895 | } | |||||
6896 | ||||||
6897 | printfprintk ("%s:%d: ERROR (%x:%x) (%x-%x-%x) (%x/%x) @ (%s %x:%08x).\n", | |||||
6898 | ncr_name (np), (unsigned)INB (nc_ctest0)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_ctest0)))))&0x0f, dstat, sist, | |||||
6899 | (unsigned)INB (nc_socl)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_socl))))), (unsigned)INB (nc_sbcl)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_sbcl))))), (unsigned)INB (nc_sbdl)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_sbdl))))), | |||||
6900 | (unsigned)INB (nc_sxfer)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_sxfer))))),(unsigned)INB (nc_scntl3)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_scntl3))))), script_name, script_ofs, | |||||
6901 | (unsigned)INL (nc_dbc)(*(volatile unsigned int *) ((char *)np->reg + (((size_t) ( &((struct ncr_reg *)0)->nc_dbc)))))); | |||||
6902 | ||||||
6903 | if (((script_ofs & 3) == 0) && | |||||
6904 | (unsigned)script_ofs < script_size) { | |||||
6905 | printfprintk ("%s: script cmd = %08x\n", ncr_name(np), | |||||
6906 | (int) *(ncrcmd *)(script_base + script_ofs)); | |||||
6907 | } | |||||
6908 | ||||||
6909 | printfprintk ("%s: regdump:", ncr_name(np)); | |||||
6910 | for (i=0; i<16;i++) | |||||
6911 | printfprintk (" %02x", (unsigned)INB_OFF(i)(*(volatile unsigned char *) ((char *)np->reg + (i)))); | |||||
6912 | printfprintk (".\n"); | |||||
6913 | } | |||||
6914 | ||||||
6915 | /*============================================================ | |||||
6916 | ** | |||||
6917 | ** ncr chip exception handler. | |||||
6918 | ** | |||||
6919 | **============================================================ | |||||
6920 | ** | |||||
6921 | ** In normal cases, interrupt conditions occur one at a | |||||
6922 | ** time. The ncr is able to stack in some extra registers | |||||
6923 | ** other interrupts that will occurs after the first one. | |||||
6924 | ** But severall interrupts may occur at the same time. | |||||
6925 | ** | |||||
6926 | ** We probably should only try to deal with the normal | |||||
6927 | ** case, but it seems that multiple interrupts occur in | |||||
6928 | ** some cases that are not abnormal at all. | |||||
6929 | ** | |||||
6930 | ** The most frequent interrupt condition is Phase Mismatch. | |||||
6931 | ** We should want to service this interrupt quickly. | |||||
6932 | ** A SCSI parity error may be delivered at the same time. | |||||
6933 | ** The SIR interrupt is not very frequent in this driver, | |||||
6934 | ** since the INTFLY is likely used for command completion | |||||
6935 | ** signaling. | |||||
6936 | ** The Selection Timeout interrupt may be triggered with | |||||
6937 | ** IID and/or UDC. | |||||
6938 | ** The SBMC interrupt (SCSI Bus Mode Change) may probably | |||||
6939 | ** occur at any time. | |||||
6940 | ** | |||||
6941 | ** This handler try to deal as cleverly as possible with all | |||||
6942 | ** the above. | |||||
6943 | ** | |||||
6944 | **============================================================ | |||||
6945 | */ | |||||
6946 | ||||||
6947 | void ncr_exception (ncb_p np) | |||||
6948 | { | |||||
6949 | u_charunsigned char istat, dstat; | |||||
6950 | u_shortunsigned short sist; | |||||
6951 | int i; | |||||
6952 | ||||||
6953 | /* | |||||
6954 | ** interrupt on the fly ? | |||||
6955 | ** Since the global header may be copied back to a CCB | |||||
6956 | ** using a posted PCI memory write, the last operation on | |||||
6957 | ** the istat register is a READ in order to flush posted | |||||
6958 | ** PCI commands (Btw, the 'do' loop is probably useless). | |||||
6959 | */ | |||||
6960 | istat = INB (nc_istat)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_istat))))); | |||||
6961 | if (istat & INTF0x04) { | |||||
6962 | do { | |||||
6963 | OUTB (nc_istat, (istat & SIGP) | INTF)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_istat))))) = ((((istat & 0x20) | 0x04)))); | |||||
6964 | istat = INB (nc_istat)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_istat))))); | |||||
6965 | } while (istat & INTF0x04); | |||||
6966 | if (DEBUG_FLAGSncr_debug & DEBUG_TINY(0x0080)) printfprintk ("F "); | |||||
6967 | np->profile.num_fly++; | |||||
6968 | ncr_wakeup (np, 0); | |||||
6969 | }; | |||||
6970 | ||||||
6971 | if (!(istat & (SIP0x02|DIP0x01))) | |||||
6972 | return; | |||||
6973 | ||||||
6974 | np->profile.num_int++; | |||||
6975 | ||||||
6976 | if (istat & CABRT0x80) | |||||
6977 | OUTB (nc_istat, CABRT)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_istat))))) = (((0x80)))); | |||||
6978 | ||||||
6979 | /* | |||||
6980 | ** Steinbach's Guideline for Systems Programming: | |||||
6981 | ** Never test for an error condition you don't know how to handle. | |||||
6982 | */ | |||||
6983 | ||||||
6984 | sist = (istat & SIP0x02) ? INW (nc_sist)(*(volatile unsigned short *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_sist))))) : 0; | |||||
6985 | dstat = (istat & DIP0x01) ? INB (nc_dstat)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_dstat))))) : 0; | |||||
6986 | ||||||
6987 | if (DEBUG_FLAGSncr_debug & DEBUG_TINY(0x0080)) | |||||
6988 | printfprintk ("<%d|%x:%x|%x:%x>", | |||||
6989 | (int)INB(nc_scr0)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_scr0))))), | |||||
6990 | dstat,sist, | |||||
6991 | (unsigned)INL(nc_dsp)(*(volatile unsigned int *) ((char *)np->reg + (((size_t) ( &((struct ncr_reg *)0)->nc_dsp))))), | |||||
6992 | (unsigned)INL(nc_dbc)(*(volatile unsigned int *) ((char *)np->reg + (((size_t) ( &((struct ncr_reg *)0)->nc_dbc)))))); | |||||
6993 | ||||||
6994 | /*======================================================== | |||||
6995 | ** First, interrupts we want to service cleanly. | |||||
6996 | ** | |||||
6997 | ** Phase mismatch is the most frequent interrupt, and | |||||
6998 | ** so we have to service it as quickly and as cleanly | |||||
6999 | ** as possible. | |||||
7000 | ** Programmed interrupts are rarely used in this driver, | |||||
7001 | ** but we must handle them cleanly anyway. | |||||
7002 | ** We try to deal with PAR and SBMC combined with | |||||
7003 | ** some other interrupt(s). | |||||
7004 | **========================================================= | |||||
7005 | */ | |||||
7006 | ||||||
7007 | if (!(sist & (STO0x0400|GEN0x0200|HTH0x0100|SGE0x08|UDC0x04|RST0x02)) && | |||||
7008 | !(dstat & (MDPE0x40|BF0x20|ABRT0x10|IID0x01))) { | |||||
7009 | if ((sist & SBMC0x1000) && ncr_int_sbmc (np)) | |||||
7010 | return; | |||||
7011 | if ((sist & PAR0x01) && ncr_int_par (np)) | |||||
7012 | return; | |||||
7013 | if (sist & MA0x80) { | |||||
7014 | ncr_int_ma (np); | |||||
7015 | return; | |||||
7016 | } | |||||
7017 | if (dstat & SIR0x04) { | |||||
7018 | ncr_int_sir (np); | |||||
7019 | return; | |||||
7020 | } | |||||
7021 | /* | |||||
7022 | ** DEL 397 - 53C875 Rev 3 - Part Number 609-0392410 - ITEM 2. | |||||
7023 | */ | |||||
7024 | if (!(sist & (SBMC0x1000|PAR0x01)) && !(dstat & SSI0x08)) { | |||||
7025 | printfprintk( "%s: unknown interrupt(s) ignored, " | |||||
7026 | "ISTAT=%x DSTAT=%x SIST=%x\n", | |||||
7027 | ncr_name(np), istat, dstat, sist); | |||||
7028 | return; | |||||
7029 | } | |||||
7030 | ||||||
7031 | OUTONB (nc_dcntl, (STD|NOCOM))((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_dcntl))))) = ((((*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_dcntl))))) | ((0x04|0x01)))))); | |||||
7032 | return; | |||||
7033 | }; | |||||
7034 | ||||||
7035 | /*======================================================== | |||||
7036 | ** Now, interrupts that need some fixing up. | |||||
7037 | ** Order and multiple interrupts is so less important. | |||||
7038 | ** | |||||
7039 | ** If SRST has been asserted, we just reset the chip. | |||||
7040 | ** | |||||
7041 | ** Selection is intirely handled by the chip. If the | |||||
7042 | ** chip says STO, we trust it. Seems some other | |||||
7043 | ** interrupts may occur at the same time (UDC, IID), so | |||||
7044 | ** we ignore them. In any case we do enough fix-up | |||||
7045 | ** in the service routine. | |||||
7046 | ** We just exclude some fatal dma errors. | |||||
7047 | **========================================================= | |||||
7048 | */ | |||||
7049 | ||||||
7050 | if (sist & RST0x02) { | |||||
7051 | ncr_init (np, 1, bootverbose(np->verbose) ? "scsi reset" : NULL((void *) 0), HS_RESET(6)); | |||||
7052 | return; | |||||
7053 | }; | |||||
7054 | ||||||
7055 | if ((sist & STO0x0400) && | |||||
7056 | !(dstat & (MDPE0x40|BF0x20|ABRT0x10))) { | |||||
7057 | /* | |||||
7058 | ** DEL 397 - 53C875 Rev 3 - Part Number 609-0392410 - ITEM 1. | |||||
7059 | */ | |||||
7060 | OUTONB (nc_ctest3, CLF)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_ctest3))))) = ((((*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_ctest3))))) | (0x04))))); | |||||
7061 | ||||||
7062 | ncr_int_sto (np); | |||||
7063 | return; | |||||
7064 | }; | |||||
7065 | ||||||
7066 | /*========================================================= | |||||
7067 | ** Now, interrupts we are not able to recover cleanly. | |||||
7068 | ** (At least for the moment). | |||||
7069 | ** | |||||
7070 | ** Do the register dump. | |||||
7071 | ** Log message for real hard errors. | |||||
7072 | ** Clear all fifos. | |||||
7073 | ** For MDPE, BF, ABORT, IID, SGE and HTH we reset the | |||||
7074 | ** BUS and the chip. | |||||
7075 | ** We are more soft for UDC. | |||||
7076 | **========================================================= | |||||
7077 | */ | |||||
7078 | if (jiffies - np->regtime > 10*HZ100) { | |||||
7079 | np->regtime = jiffies; | |||||
7080 | for (i = 0; i<sizeof(np->regdump); i++) | |||||
7081 | ((char*)&np->regdump)[i] = INB_OFF(i)(*(volatile unsigned char *) ((char *)np->reg + (i))); | |||||
7082 | np->regdump.nc_dstat = dstat; | |||||
7083 | np->regdump.nc_sist = sist; | |||||
7084 | }; | |||||
7085 | ||||||
7086 | ncr_log_hard_error(np, sist, dstat); | |||||
7087 | ||||||
7088 | printfprintk ("%s: have to clear fifos.\n", ncr_name (np)); | |||||
7089 | OUTB (nc_stest3, TE|CSF)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_stest3))))) = (((0x80|0x02 )))); | |||||
7090 | OUTONB (nc_ctest3, CLF)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_ctest3))))) = ((((*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_ctest3))))) | (0x04))))); | |||||
7091 | ||||||
7092 | if ((sist & (SGE0x08)) || | |||||
7093 | (dstat & (MDPE0x40|BF0x20|ABORT0x06|IID0x01))) { | |||||
7094 | ncr_start_reset(np, driver_setup.settle_delay); | |||||
7095 | return; | |||||
7096 | }; | |||||
7097 | ||||||
7098 | if (sist & HTH0x0100) { | |||||
7099 | printfprintk ("%s: handshake timeout\n", ncr_name(np)); | |||||
7100 | ncr_start_reset(np, driver_setup.settle_delay); | |||||
7101 | return; | |||||
7102 | }; | |||||
7103 | ||||||
7104 | if (sist & UDC0x04) { | |||||
7105 | printfprintk ("%s: unexpected disconnect\n", ncr_name(np)); | |||||
7106 | if (INB (nc_scr1)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_scr1))))) != 0xff) { | |||||
7107 | OUTB (nc_scr1, HS_UNEXPECTED)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_scr1))))) = ((((10))))); | |||||
7108 | OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, cleanup))((*(volatile unsigned int *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_dsp))))) = ((((np->p_script + ((size_t) (&((struct script *)0)->cleanup))))))); | |||||
7109 | }; | |||||
7110 | ncr_start_reset(np, driver_setup.settle_delay); | |||||
7111 | return; | |||||
7112 | }; | |||||
7113 | ||||||
7114 | /*========================================================= | |||||
7115 | ** We just miss the cause of the interrupt. :( | |||||
7116 | ** Print a message. The timeout will do the real work. | |||||
7117 | **========================================================= | |||||
7118 | */ | |||||
7119 | printfprintk ("%s: unknown interrupt\n", ncr_name(np)); | |||||
7120 | } | |||||
7121 | ||||||
7122 | /*========================================================== | |||||
7123 | ** | |||||
7124 | ** ncr chip exception handler for selection timeout | |||||
7125 | ** | |||||
7126 | **========================================================== | |||||
7127 | ** | |||||
7128 | ** There seems to be a bug in the 53c810. | |||||
7129 | ** Although a STO-Interrupt is pending, | |||||
7130 | ** it continues executing script commands. | |||||
7131 | ** But it will fail and interrupt (IID) on | |||||
7132 | ** the next instruction where it's looking | |||||
7133 | ** for a valid phase. | |||||
7134 | ** | |||||
7135 | **---------------------------------------------------------- | |||||
7136 | */ | |||||
7137 | ||||||
7138 | void ncr_int_sto (ncb_p np) | |||||
7139 | { | |||||
7140 | u_longunsigned long dsa, scratcha, diff; | |||||
7141 | ccb_p cp; | |||||
7142 | if (DEBUG_FLAGSncr_debug & DEBUG_TINY(0x0080)) printfprintk ("T"); | |||||
7143 | ||||||
7144 | /* | |||||
7145 | ** look for ccb and set the status. | |||||
7146 | */ | |||||
7147 | ||||||
7148 | dsa = INL (nc_dsa)(*(volatile unsigned int *) ((char *)np->reg + (((size_t) ( &((struct ncr_reg *)0)->nc_dsa))))); | |||||
7149 | cp = np->ccb; | |||||
7150 | while (cp && (CCB_PHYS (cp, phys)(cp->p_ccb + ((size_t) (&((struct ccb *)0)->phys))) != dsa)) | |||||
7151 | cp = cp->link_ccb; | |||||
7152 | ||||||
7153 | if (cp) { | |||||
7154 | cp-> host_statusphys.header.status[1] = HS_SEL_TIMEOUT(5); | |||||
7155 | ncr_complete (np, cp); | |||||
7156 | }; | |||||
7157 | ||||||
7158 | /* | |||||
7159 | ** repair start queue | |||||
7160 | */ | |||||
7161 | ||||||
7162 | scratcha = INL (nc_scratcha)(*(volatile unsigned int *) ((char *)np->reg + (((size_t) ( &((struct ncr_reg *)0)->nc_scratcha))))); | |||||
7163 | diff = scratcha - NCB_SCRIPTH_PHYS (np, tryloop)(np->p_scripth + ((size_t) (&((struct scripth *)0)-> tryloop))); | |||||
7164 | ||||||
7165 | /* assert ((diff <= MAX_START * 20) && !(diff % 20));*/ | |||||
7166 | ||||||
7167 | if ((diff <= MAX_START((7*(4)) + 4) * 20) && !(diff % 20)) { | |||||
7168 | np->script->startpos[0] = cpu_to_scr(scratcha)(scratcha); | |||||
7169 | OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, start))((*(volatile unsigned int *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_dsp))))) = ((((np->p_script + ((size_t) (&((struct script *)0)->start))))))); | |||||
7170 | return; | |||||
7171 | }; | |||||
7172 | ncr_init (np, 1, "selection timeout", HS_FAIL(9)); | |||||
7173 | np->disc = 1; | |||||
7174 | } | |||||
7175 | ||||||
7176 | /*========================================================== | |||||
7177 | ** | |||||
7178 | ** ncr chip exception handler for SCSI bus mode change | |||||
7179 | ** | |||||
7180 | **========================================================== | |||||
7181 | ** | |||||
7182 | ** spi2-r12 11.2.3 says a transceiver mode change must | |||||
7183 | ** generate a reset event and a device that detects a reset | |||||
7184 | ** event shall initiate a hard reset. It says also that a | |||||
7185 | ** device that detects a mode change shall set data transfer | |||||
7186 | ** mode to eight bit asynchronous, etc... | |||||
7187 | ** So, just resetting should be enough. | |||||
7188 | ** | |||||
7189 | ** | |||||
7190 | **---------------------------------------------------------- | |||||
7191 | */ | |||||
7192 | ||||||
7193 | static int ncr_int_sbmc (ncb_p np) | |||||
7194 | { | |||||
7195 | u_charunsigned char scsi_mode = INB (nc_stest4)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_stest4))))) & SMODE0xc0; | |||||
7196 | ||||||
7197 | printfprintk("%s: SCSI bus mode change from %x to %x.\n", | |||||
7198 | ncr_name(np), np->scsi_mode, scsi_mode); | |||||
7199 | ||||||
7200 | np->scsi_mode = scsi_mode; | |||||
7201 | ||||||
7202 | /* | |||||
7203 | ** Suspend command processing for 1 second and | |||||
7204 | ** reinitialize all except the chip. | |||||
7205 | */ | |||||
7206 | np->settle_time = jiffies + HZ100; | |||||
7207 | ncr_init (np, 0, bootverbose(np->verbose) ? "scsi mode change" : NULL((void *) 0), HS_RESET(6)); | |||||
7208 | ||||||
7209 | return 1; | |||||
7210 | } | |||||
7211 | ||||||
7212 | /*========================================================== | |||||
7213 | ** | |||||
7214 | ** ncr chip exception handler for SCSI parity error. | |||||
7215 | ** | |||||
7216 | **========================================================== | |||||
7217 | ** | |||||
7218 | ** SCSI parity errors are handled by the SCSI script. | |||||
7219 | ** So, we just print some message. | |||||
7220 | ** | |||||
7221 | **---------------------------------------------------------- | |||||
7222 | */ | |||||
7223 | ||||||
7224 | static int ncr_int_par (ncb_p np) | |||||
7225 | { | |||||
7226 | printfprintk("%s: SCSI parity error detected\n", ncr_name(np)); | |||||
7227 | return 0; | |||||
7228 | } | |||||
7229 | ||||||
7230 | /*========================================================== | |||||
7231 | ** | |||||
7232 | ** | |||||
7233 | ** ncr chip exception handler for phase errors. | |||||
7234 | ** | |||||
7235 | ** | |||||
7236 | **========================================================== | |||||
7237 | ** | |||||
7238 | ** We have to construct a new transfer descriptor, | |||||
7239 | ** to transfer the rest of the current block. | |||||
7240 | ** | |||||
7241 | **---------------------------------------------------------- | |||||
7242 | */ | |||||
7243 | ||||||
7244 | static void ncr_int_ma (ncb_p np) | |||||
7245 | { | |||||
7246 | u_int32 dbc; | |||||
7247 | u_int32 rest; | |||||
7248 | u_int32 dsp; | |||||
7249 | u_int32 dsa; | |||||
7250 | u_int32 nxtdsp; | |||||
7251 | u_int32 *vdsp; | |||||
7252 | u_int32 oadr, olen; | |||||
7253 | u_int32 *tblp; | |||||
7254 | ncrcmd *newcmd; | |||||
7255 | u_charunsigned char cmd, sbcl; | |||||
7256 | ccb_p cp; | |||||
7257 | ||||||
7258 | dsp = INL (nc_dsp)(*(volatile unsigned int *) ((char *)np->reg + (((size_t) ( &((struct ncr_reg *)0)->nc_dsp))))); | |||||
7259 | dbc = INL (nc_dbc)(*(volatile unsigned int *) ((char *)np->reg + (((size_t) ( &((struct ncr_reg *)0)->nc_dbc))))); | |||||
7260 | sbcl = INB (nc_sbcl)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_sbcl))))); | |||||
7261 | ||||||
7262 | cmd = dbc >> 24; | |||||
7263 | rest = dbc & 0xffffff; | |||||
7264 | ||||||
7265 | /* | |||||
7266 | ** Take into account dma fifo and various buffers and latches, | |||||
7267 | ** only if the interrupted phase is an OUTPUT phase. | |||||
7268 | */ | |||||
7269 | ||||||
7270 | if ((cmd & 1) == 0) { | |||||
7271 | u_charunsigned char ctest5, ss0, ss2; | |||||
7272 | u_shortunsigned short delta; | |||||
7273 | ||||||
7274 | ctest5 = (np->rv_ctest5 & DFS0x20) ? INB (nc_ctest5)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_ctest5))))) : 0; | |||||
7275 | if (ctest5 & DFS0x20) | |||||
7276 | delta=(((ctest5 << 8) | (INB (nc_dfifo)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_dfifo))))) & 0xff)) - rest) & 0x3ff; | |||||
7277 | else | |||||
7278 | delta=(INB (nc_dfifo)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_dfifo))))) - rest) & 0x7f; | |||||
7279 | ||||||
7280 | /* | |||||
7281 | ** The data in the dma fifo has not been transfered to | |||||
7282 | ** the target -> add the amount to the rest | |||||
7283 | ** and clear the data. | |||||
7284 | ** Check the sstat2 register in case of wide transfer. | |||||
7285 | */ | |||||
7286 | ||||||
7287 | rest += delta; | |||||
7288 | ss0 = INB (nc_sstat0)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_sstat0))))); | |||||
7289 | if (ss0 & OLF0x20) rest++; | |||||
7290 | if (ss0 & ORF0x40) rest++; | |||||
7291 | if (INB(nc_scntl3)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_scntl3))))) & EWS0x08) { | |||||
7292 | ss2 = INB (nc_sstat2)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_sstat2))))); | |||||
7293 | if (ss2 & OLF10x20) rest++; | |||||
7294 | if (ss2 & ORF10x40) rest++; | |||||
7295 | }; | |||||
7296 | ||||||
7297 | OUTONB (nc_ctest3, CLF )((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_ctest3))))) = ((((*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_ctest3))))) | (0x04))))); /* clear dma fifo */ | |||||
7298 | OUTB (nc_stest3, TE|CSF)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_stest3))))) = (((0x80|0x02 )))); /* clear scsi fifo */ | |||||
7299 | ||||||
7300 | if (DEBUG_FLAGSncr_debug & (DEBUG_TINY(0x0080)|DEBUG_PHASE(0x0002))) | |||||
7301 | printfprintk ("P%x%x RL=%d D=%d SS0=%x ", cmd&7, sbcl&7, | |||||
7302 | (unsigned) rest, (unsigned) delta, ss0); | |||||
7303 | ||||||
7304 | } else { | |||||
7305 | if (DEBUG_FLAGSncr_debug & (DEBUG_TINY(0x0080)|DEBUG_PHASE(0x0002))) | |||||
7306 | printfprintk ("P%x%x RL=%d ", cmd&7, sbcl&7, rest); | |||||
7307 | if ((cmd & 7) != 1) { | |||||
7308 | OUTONB (nc_ctest3, CLF )((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_ctest3))))) = ((((*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_ctest3))))) | (0x04))))); | |||||
7309 | OUTB (nc_stest3, TE|CSF)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_stest3))))) = (((0x80|0x02 )))); | |||||
7310 | } | |||||
7311 | } | |||||
7312 | ||||||
7313 | /* | |||||
7314 | ** locate matching cp | |||||
7315 | */ | |||||
7316 | dsa = INL (nc_dsa)(*(volatile unsigned int *) ((char *)np->reg + (((size_t) ( &((struct ncr_reg *)0)->nc_dsa))))); | |||||
7317 | cp = np->ccb; | |||||
7318 | while (cp && (CCB_PHYS (cp, phys)(cp->p_ccb + ((size_t) (&((struct ccb *)0)->phys))) != dsa)) | |||||
7319 | cp = cp->link_ccb; | |||||
7320 | ||||||
7321 | if (!cp) { | |||||
7322 | printfprintk ("%s: SCSI phase error fixup: CCB already dequeued (0x%08lx)\n", | |||||
7323 | ncr_name (np), (u_longunsigned long) np->header.cp); | |||||
7324 | return; | |||||
7325 | } | |||||
7326 | if (cp != np->header.cp) { | |||||
7327 | printfprintk ("%s: SCSI phase error fixup: CCB address mismatch (0x%08lx != 0x%08lx)\n", | |||||
7328 | ncr_name (np), (u_longunsigned long) cp, (u_longunsigned long) np->header.cp); | |||||
7329 | /* return;*/ | |||||
7330 | } | |||||
7331 | ||||||
7332 | /* | |||||
7333 | ** find the interrupted script command, | |||||
7334 | ** and the address at which to continue. | |||||
7335 | */ | |||||
7336 | ||||||
7337 | if (dsp == vtophys (&cp->patch[2])virt_to_phys(&cp->patch[2])) { | |||||
7338 | vdsp = &cp->patch[0]; | |||||
7339 | nxtdsp = vdsp[3]; | |||||
7340 | } else if (dsp == vtophys (&cp->patch[6])virt_to_phys(&cp->patch[6])) { | |||||
7341 | vdsp = &cp->patch[4]; | |||||
7342 | nxtdsp = vdsp[3]; | |||||
7343 | } else if (dsp > np->p_script && dsp <= np->p_script + sizeof(struct script)) { | |||||
7344 | vdsp = (u_int32 *) ((char*)np->script - np->p_script + dsp -8); | |||||
7345 | nxtdsp = dsp; | |||||
7346 | } else { | |||||
7347 | vdsp = (u_int32 *) ((char*)np->scripth - np->p_scripth + dsp -8); | |||||
7348 | nxtdsp = dsp; | |||||
7349 | }; | |||||
7350 | ||||||
7351 | /* | |||||
7352 | ** log the information | |||||
7353 | */ | |||||
7354 | ||||||
7355 | if (DEBUG_FLAGSncr_debug & DEBUG_PHASE(0x0002)) { | |||||
7356 | printfprintk ("\nCP=%p CP2=%p DSP=%x NXT=%x VDSP=%p CMD=%x ", | |||||
7357 | cp, np->header.cp, | |||||
7358 | (unsigned)dsp, | |||||
7359 | (unsigned)nxtdsp, vdsp, cmd); | |||||
7360 | }; | |||||
7361 | ||||||
7362 | /* | |||||
7363 | ** get old startaddress and old length. | |||||
7364 | */ | |||||
7365 | ||||||
7366 | oadr = scr_to_cpu(vdsp[1])(vdsp[1]); | |||||
7367 | ||||||
7368 | if (cmd & 0x10) { /* Table indirect */ | |||||
7369 | tblp = (u_int32 *) ((char*) &cp->phys + oadr); | |||||
7370 | olen = scr_to_cpu(tblp[0])(tblp[0]); | |||||
7371 | oadr = scr_to_cpu(tblp[1])(tblp[1]); | |||||
7372 | } else { | |||||
7373 | tblp = (u_int32 *) 0; | |||||
7374 | olen = scr_to_cpu(vdsp[0])(vdsp[0]) & 0xffffff; | |||||
7375 | }; | |||||
7376 | ||||||
7377 | if (DEBUG_FLAGSncr_debug & DEBUG_PHASE(0x0002)) { | |||||
7378 | printfprintk ("OCMD=%x\nTBLP=%p OLEN=%x OADR=%x\n", | |||||
7379 | (unsigned) (scr_to_cpu(vdsp[0])(vdsp[0]) >> 24), | |||||
7380 | tblp, | |||||
7381 | (unsigned) olen, | |||||
7382 | (unsigned) oadr); | |||||
7383 | }; | |||||
7384 | ||||||
7385 | /* | |||||
7386 | ** check cmd against assumed interrupted script command. | |||||
7387 | */ | |||||
7388 | ||||||
7389 | if (cmd != (scr_to_cpu(vdsp[0])(vdsp[0]) >> 24)) { | |||||
7390 | PRINT_ADDR(cp->cmd); | |||||
7391 | printfprintk ("internal error: cmd=%02x != %02x=(vdsp[0] >> 24)\n", | |||||
7392 | (unsigned)cmd, (unsigned)scr_to_cpu(vdsp[0])(vdsp[0]) >> 24); | |||||
7393 | ||||||
7394 | return; | |||||
7395 | } | |||||
7396 | ||||||
7397 | #ifdef SCSI_NCR_DEBUG_ERROR_RECOVERY_SUPPORT | |||||
7398 | if ((cmd & 7) == 1 && np->assert_atn) { | |||||
7399 | np->assert_atn = 0; | |||||
7400 | OUTONB(nc_socl, CATN)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_socl))))) = ((((*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_socl))))) | (0x08))))); | |||||
7401 | } | |||||
7402 | #endif | |||||
7403 | ||||||
7404 | /* | |||||
7405 | ** if old phase not dataphase, leave here. | |||||
7406 | */ | |||||
7407 | ||||||
7408 | if (cmd & 0x06) { | |||||
7409 | PRINT_ADDR(cp->cmd); | |||||
7410 | printfprintk ("phase change %x-%x %d@%08x resid=%d.\n", | |||||
7411 | cmd&7, sbcl&7, (unsigned)olen, | |||||
7412 | (unsigned)oadr, (unsigned)rest); | |||||
7413 | ||||||
7414 | OUTONB (nc_dcntl, (STD|NOCOM))((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_dcntl))))) = ((((*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_dcntl))))) | ((0x04|0x01)))))); | |||||
7415 | return; | |||||
7416 | }; | |||||
7417 | ||||||
7418 | /* | |||||
7419 | ** choose the correct patch area. | |||||
7420 | ** if savep points to one, choose the other. | |||||
7421 | */ | |||||
7422 | ||||||
7423 | newcmd = cp->patch; | |||||
7424 | if (cp->phys.header.savep == cpu_to_scr(vtophys (newcmd))(virt_to_phys(newcmd))) newcmd+=4; | |||||
7425 | ||||||
7426 | /* | |||||
7427 | ** fillin the commands | |||||
7428 | */ | |||||
7429 | ||||||
7430 | newcmd[0] = cpu_to_scr(((cmd & 0x0f) << 24) | rest)(((cmd & 0x0f) << 24) | rest); | |||||
7431 | newcmd[1] = cpu_to_scr(oadr + olen - rest)(oadr + olen - rest); | |||||
7432 | newcmd[2] = cpu_to_scr(SCR_JUMP)(0x80080000); | |||||
7433 | newcmd[3] = cpu_to_scr(nxtdsp)(nxtdsp); | |||||
7434 | ||||||
7435 | if (DEBUG_FLAGSncr_debug & DEBUG_PHASE(0x0002)) { | |||||
7436 | PRINT_ADDR(cp->cmd); | |||||
7437 | printfprintk ("newcmd[%d] %x %x %x %x.\n", | |||||
7438 | (int) (newcmd - cp->patch), | |||||
7439 | (unsigned)scr_to_cpu(newcmd[0])(newcmd[0]), | |||||
7440 | (unsigned)scr_to_cpu(newcmd[1])(newcmd[1]), | |||||
7441 | (unsigned)scr_to_cpu(newcmd[2])(newcmd[2]), | |||||
7442 | (unsigned)scr_to_cpu(newcmd[3])(newcmd[3])); | |||||
7443 | } | |||||
7444 | /* | |||||
7445 | ** fake the return address (to the patch). | |||||
7446 | ** and restart script processor at dispatcher. | |||||
7447 | */ | |||||
7448 | np->profile.num_break++; | |||||
7449 | OUTL (nc_temp, vtophys (newcmd))((*(volatile unsigned int *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_temp))))) = (((virt_to_phys (newcmd))))); | |||||
7450 | if ((cmd & 7) == 0) | |||||
7451 | OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, dispatch))((*(volatile unsigned int *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_dsp))))) = ((((np->p_script + ((size_t) (&((struct script *)0)->dispatch))))))); | |||||
7452 | else | |||||
7453 | OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, checkatn))((*(volatile unsigned int *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_dsp))))) = ((((np->p_script + ((size_t) (&((struct script *)0)->checkatn))))))); | |||||
7454 | } | |||||
7455 | ||||||
7456 | /*========================================================== | |||||
7457 | ** | |||||
7458 | ** | |||||
7459 | ** ncr chip exception handler for programmed interrupts. | |||||
7460 | ** | |||||
7461 | ** | |||||
7462 | **========================================================== | |||||
7463 | */ | |||||
7464 | ||||||
7465 | static int ncr_show_msg (u_charunsigned char * msg) | |||||
7466 | { | |||||
7467 | u_charunsigned char i; | |||||
7468 | printfprintk ("%x",*msg); | |||||
7469 | if (*msg==M_EXTENDED(0x01)) { | |||||
7470 | for (i=1;i<8;i++) { | |||||
7471 | if (i-1>msg[1]) break; | |||||
7472 | printfprintk ("-%x",msg[i]); | |||||
7473 | }; | |||||
7474 | return (i+1); | |||||
7475 | } else if ((*msg & 0xf0) == 0x20) { | |||||
7476 | printfprintk ("-%x",msg[1]); | |||||
7477 | return (2); | |||||
7478 | }; | |||||
7479 | return (1); | |||||
7480 | } | |||||
7481 | ||||||
7482 | void ncr_int_sir (ncb_p np) | |||||
7483 | { | |||||
7484 | u_charunsigned char scntl3; | |||||
7485 | u_charunsigned char chg, ofs, per, fak, wide; | |||||
7486 | u_charunsigned char num = INB (nc_dsps)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_dsps))))); | |||||
7487 | ccb_p cp=0; | |||||
7488 | u_longunsigned long dsa; | |||||
7489 | u_charunsigned char target = INB (nc_ctest0)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_ctest0))))) & 0x0f; | |||||
7490 | tcb_p tp = &np->target[target]; | |||||
7491 | int i; | |||||
7492 | if (DEBUG_FLAGSncr_debug & DEBUG_TINY(0x0080)) printfprintk ("I#%d", num); | |||||
7493 | ||||||
7494 | switch (num) { | |||||
7495 | case SIR_SENSE_RESTART(1): | |||||
7496 | case SIR_STALL_RESTART(3): | |||||
7497 | break; | |||||
7498 | case SIR_STALL_QUEUE(4): /* Ignore, just restart the script */ | |||||
7499 | goto out; | |||||
7500 | ||||||
7501 | default: | |||||
7502 | /* | |||||
7503 | ** lookup the ccb | |||||
7504 | */ | |||||
7505 | dsa = INL (nc_dsa)(*(volatile unsigned int *) ((char *)np->reg + (((size_t) ( &((struct ncr_reg *)0)->nc_dsa))))); | |||||
7506 | cp = np->ccb; | |||||
7507 | while (cp && (CCB_PHYS (cp, phys)(cp->p_ccb + ((size_t) (&((struct ccb *)0)->phys))) != dsa)) | |||||
7508 | cp = cp->link_ccb; | |||||
7509 | ||||||
7510 | assert (cp){ if (!(cp)) { (void)printk( "assertion \"%s\" failed: file \"%s\", line %d\n" , "cp", "../linux/src/drivers/scsi/ncr53c8xx.c", 7510); } }; | |||||
7511 | if (!cp) | |||||
7512 | goto out; | |||||
7513 | assert (cp == np->header.cp){ if (!(cp == np->header.cp)) { (void)printk( "assertion \"%s\" failed: file \"%s\", line %d\n" , "cp == np->header.cp", "../linux/src/drivers/scsi/ncr53c8xx.c" , 7513); } }; | |||||
7514 | if (cp != np->header.cp) | |||||
7515 | goto out; | |||||
7516 | } | |||||
7517 | ||||||
7518 | switch (num) { | |||||
7519 | u_longunsigned long endp; | |||||
7520 | case SIR_DATA_IO_IS_OUT(13): | |||||
7521 | case SIR_DATA_IO_IS_IN(14): | |||||
7522 | /* | |||||
7523 | ** We did not guess the direction of transfer. We have to wait for | |||||
7524 | ** actual data direction driven by the target before setting | |||||
7525 | ** pointers. We must patch the global header too. | |||||
7526 | */ | |||||
7527 | if (num == SIR_DATA_IO_IS_OUT(13)) { | |||||
7528 | endp = NCB_SCRIPTH_PHYS (np, data_out)(np->p_scripth + ((size_t) (&((struct scripth *)0)-> data_out))) + MAX_SCATTER((127))*16; | |||||
7529 | cp->phys.header.goalp = cpu_to_scr(endp + 8)(endp + 8); | |||||
7530 | cp->phys.header.savep = | |||||
7531 | cpu_to_scr(endp - cp->segments*16)(endp - cp->segments*16); | |||||
7532 | } else { | |||||
7533 | endp = NCB_SCRIPT_PHYS (np, data_in)(np->p_script + ((size_t) (&((struct script *)0)->data_in ))) + MAX_SCATTER((127))*16; | |||||
7534 | cp->phys.header.goalp = cpu_to_scr(endp + 8)(endp + 8); | |||||
7535 | cp->phys.header.savep = | |||||
7536 | cpu_to_scr(endp - cp->segments*16)(endp - cp->segments*16); | |||||
7537 | } | |||||
7538 | ||||||
7539 | cp->phys.header.lastp = cp->phys.header.savep; | |||||
7540 | np->header.savep = cp->phys.header.savep; | |||||
7541 | np->header.goalp = cp->phys.header.goalp; | |||||
7542 | np->header.lastp = cp->phys.header.lastp; | |||||
7543 | ||||||
7544 | OUTL (nc_temp, scr_to_cpu(np->header.savep))((*(volatile unsigned int *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_temp))))) = ((((np->header .savep))))); | |||||
7545 | OUTL (nc_dsp, scr_to_cpu(np->header.savep))((*(volatile unsigned int *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_dsp))))) = ((((np->header .savep))))); | |||||
7546 | return; | |||||
7547 | /* break; */ | |||||
7548 | ||||||
7549 | /*-------------------------------------------------------------------- | |||||
7550 | ** | |||||
7551 | ** Processing of interrupted getcc selects | |||||
7552 | ** | |||||
7553 | **-------------------------------------------------------------------- | |||||
7554 | */ | |||||
7555 | ||||||
7556 | case SIR_SENSE_RESTART(1): | |||||
7557 | /*------------------------------------------ | |||||
7558 | ** Script processor is idle. | |||||
7559 | ** Look for interrupted "check cond" | |||||
7560 | **------------------------------------------ | |||||
7561 | */ | |||||
7562 | ||||||
7563 | if (DEBUG_FLAGSncr_debug & DEBUG_RESTART(0x1000)) | |||||
7564 | printfprintk ("%s: int#%d",ncr_name (np),num); | |||||
7565 | cp = (ccb_p) 0; | |||||
7566 | for (i=0; i<MAX_TARGET((16)); i++) { | |||||
7567 | if (DEBUG_FLAGSncr_debug & DEBUG_RESTART(0x1000)) printfprintk (" t%d", i); | |||||
7568 | tp = &np->target[i]; | |||||
7569 | if (DEBUG_FLAGSncr_debug & DEBUG_RESTART(0x1000)) printfprintk ("+"); | |||||
7570 | cp = tp->hold_cp; | |||||
7571 | if (!cp) continue; | |||||
7572 | if (DEBUG_FLAGSncr_debug & DEBUG_RESTART(0x1000)) printfprintk ("+"); | |||||
7573 | if ((cp->host_statusphys.header.status[1]==HS_BUSY(1)) && | |||||
7574 | (cp->scsi_statusphys.header.status[2]==S_CHECK_COND(0x02))) | |||||
7575 | break; | |||||
7576 | if (DEBUG_FLAGSncr_debug & DEBUG_RESTART(0x1000)) printfprintk ("- (remove)"); | |||||
7577 | tp->hold_cp = cp = (ccb_p) 0; | |||||
7578 | }; | |||||
7579 | ||||||
7580 | if (cp) { | |||||
7581 | if (DEBUG_FLAGSncr_debug & DEBUG_RESTART(0x1000)) | |||||
7582 | printfprintk ("+ restart job ..\n"); | |||||
7583 | OUTL (nc_dsa, CCB_PHYS (cp, phys))((*(volatile unsigned int *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_dsa))))) = ((((cp->p_ccb + ((size_t) (&((struct ccb *)0)->phys))))))); | |||||
7584 | OUTL (nc_dsp, NCB_SCRIPTH_PHYS (np, getcc))((*(volatile unsigned int *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_dsp))))) = ((((np->p_scripth + ((size_t) (&((struct scripth *)0)->getcc))))))); | |||||
7585 | return; | |||||
7586 | }; | |||||
7587 | ||||||
7588 | /* | |||||
7589 | ** no job, resume normal processing | |||||
7590 | */ | |||||
7591 | if (DEBUG_FLAGSncr_debug & DEBUG_RESTART(0x1000)) printfprintk (" -- remove trap\n"); | |||||
7592 | np->script->start0[0] = cpu_to_scr(SCR_INT ^ IFFALSE (0))(0x98080000 ^ (0x00080000 | (0))); | |||||
7593 | break; | |||||
7594 | ||||||
7595 | case SIR_SENSE_FAILED(2): | |||||
7596 | /*------------------------------------------- | |||||
7597 | ** While trying to select for | |||||
7598 | ** getting the condition code, | |||||
7599 | ** a target reselected us. | |||||
7600 | **------------------------------------------- | |||||
7601 | */ | |||||
7602 | if (DEBUG_FLAGSncr_debug & DEBUG_RESTART(0x1000)) { | |||||
7603 | PRINT_ADDR(cp->cmd); | |||||
7604 | printfprintk ("in getcc reselect by t%d.\n", | |||||
7605 | (int)INB(nc_ssid)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_ssid))))) & 0x0f); | |||||
7606 | } | |||||
7607 | ||||||
7608 | /* | |||||
7609 | ** Mark this job | |||||
7610 | */ | |||||
7611 | cp->host_statusphys.header.status[1] = HS_BUSY(1); | |||||
7612 | cp->scsi_statusphys.header.status[2] = S_CHECK_COND(0x02); | |||||
7613 | np->target[cp->cmd->target].hold_cp = cp; | |||||
7614 | ||||||
7615 | /* | |||||
7616 | ** And patch code to restart it. | |||||
7617 | */ | |||||
7618 | np->script->start0[0] = cpu_to_scr(SCR_INT)(0x98080000); | |||||
7619 | break; | |||||
7620 | ||||||
7621 | /*----------------------------------------------------------------------------- | |||||
7622 | ** | |||||
7623 | ** Was Sie schon immer ueber transfermode negotiation wissen wollten ... | |||||
7624 | ** | |||||
7625 | ** We try to negotiate sync and wide transfer only after | |||||
7626 | ** a successfull inquire command. We look at byte 7 of the | |||||
7627 | ** inquire data to determine the capabilities of the target. | |||||
7628 | ** | |||||
7629 | ** When we try to negotiate, we append the negotiation message | |||||
7630 | ** to the identify and (maybe) simple tag message. | |||||
7631 | ** The host status field is set to HS_NEGOTIATE to mark this | |||||
7632 | ** situation. | |||||
7633 | ** | |||||
7634 | ** If the target doesn't answer this message immidiately | |||||
7635 | ** (as required by the standard), the SIR_NEGO_FAIL interrupt | |||||
7636 | ** will be raised eventually. | |||||
7637 | ** The handler removes the HS_NEGOTIATE status, and sets the | |||||
7638 | ** negotiated value to the default (async / nowide). | |||||
7639 | ** | |||||
7640 | ** If we receive a matching answer immediately, we check it | |||||
7641 | ** for validity, and set the values. | |||||
7642 | ** | |||||
7643 | ** If we receive a Reject message immediately, we assume the | |||||
7644 | ** negotiation has failed, and fall back to standard values. | |||||
7645 | ** | |||||
7646 | ** If we receive a negotiation message while not in HS_NEGOTIATE | |||||
7647 | ** state, it's a target initiated negotiation. We prepare a | |||||
7648 | ** (hopefully) valid answer, set our parameters, and send back | |||||
7649 | ** this answer to the target. | |||||
7650 | ** | |||||
7651 | ** If the target doesn't fetch the answer (no message out phase), | |||||
7652 | ** we assume the negotiation has failed, and fall back to default | |||||
7653 | ** settings. | |||||
7654 | ** | |||||
7655 | ** When we set the values, we adjust them in all ccbs belonging | |||||
7656 | ** to this target, in the controller's register, and in the "phys" | |||||
7657 | ** field of the controller's struct ncb. | |||||
7658 | ** | |||||
7659 | ** Possible cases: hs sir msg_in value send goto | |||||
7660 | ** We try to negotiate: | |||||
7661 | ** -> target doesnt't msgin NEG FAIL noop defa. - dispatch | |||||
7662 | ** -> target rejected our msg NEG FAIL reject defa. - dispatch | |||||
7663 | ** -> target answered (ok) NEG SYNC sdtr set - clrack | |||||
7664 | ** -> target answered (!ok) NEG SYNC sdtr defa. REJ--->msg_bad | |||||
7665 | ** -> target answered (ok) NEG WIDE wdtr set - clrack | |||||
7666 | ** -> target answered (!ok) NEG WIDE wdtr defa. REJ--->msg_bad | |||||
7667 | ** -> any other msgin NEG FAIL noop defa. - dispatch | |||||
7668 | ** | |||||
7669 | ** Target tries to negotiate: | |||||
7670 | ** -> incoming message --- SYNC sdtr set SDTR - | |||||
7671 | ** -> incoming message --- WIDE wdtr set WDTR - | |||||
7672 | ** We sent our answer: | |||||
7673 | ** -> target doesn't msgout --- PROTO ? defa. - dispatch | |||||
7674 | ** | |||||
7675 | **----------------------------------------------------------------------------- | |||||
7676 | */ | |||||
7677 | ||||||
7678 | case SIR_NEGO_FAILED(7): | |||||
7679 | /*------------------------------------------------------- | |||||
7680 | ** | |||||
7681 | ** Negotiation failed. | |||||
7682 | ** Target doesn't send an answer message, | |||||
7683 | ** or target rejected our message. | |||||
7684 | ** | |||||
7685 | ** Remove negotiation request. | |||||
7686 | ** | |||||
7687 | **------------------------------------------------------- | |||||
7688 | */ | |||||
7689 | OUTB (HS_PRT, HS_BUSY)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_scr1))))) = ((((1))))); | |||||
7690 | ||||||
7691 | /* fall through */ | |||||
7692 | ||||||
7693 | case SIR_NEGO_PROTO(8): | |||||
7694 | /*------------------------------------------------------- | |||||
7695 | ** | |||||
7696 | ** Negotiation failed. | |||||
7697 | ** Target doesn't fetch the answer message. | |||||
7698 | ** | |||||
7699 | **------------------------------------------------------- | |||||
7700 | */ | |||||
7701 | ||||||
7702 | if (DEBUG_FLAGSncr_debug & DEBUG_NEGO(0x0200)) { | |||||
7703 | PRINT_ADDR(cp->cmd); | |||||
7704 | printfprintk ("negotiation failed sir=%x status=%x.\n", | |||||
7705 | num, cp->nego_statusphys.header.scr_st[2]); | |||||
7706 | }; | |||||
7707 | ||||||
7708 | /* | |||||
7709 | ** any error in negotiation: | |||||
7710 | ** fall back to default mode. | |||||
7711 | */ | |||||
7712 | switch (cp->nego_statusphys.header.scr_st[2]) { | |||||
7713 | ||||||
7714 | case NS_SYNC(1): | |||||
7715 | ncr_setsync (np, cp, 0, 0xe0); | |||||
7716 | break; | |||||
7717 | ||||||
7718 | case NS_WIDE(2): | |||||
7719 | ncr_setwide (np, cp, 0, 0); | |||||
7720 | break; | |||||
7721 | ||||||
7722 | }; | |||||
7723 | np->msgin [0] = M_NOOP(0x08); | |||||
7724 | np->msgout[0] = M_NOOP(0x08); | |||||
7725 | cp->nego_statusphys.header.scr_st[2] = 0; | |||||
7726 | OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, dispatch))((*(volatile unsigned int *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_dsp))))) = ((((np->p_script + ((size_t) (&((struct script *)0)->dispatch))))))); | |||||
7727 | break; | |||||
7728 | ||||||
7729 | case SIR_NEGO_SYNC(5): | |||||
7730 | /* | |||||
7731 | ** Synchronous request message received. | |||||
7732 | */ | |||||
7733 | ||||||
7734 | if (DEBUG_FLAGSncr_debug & DEBUG_NEGO(0x0200)) { | |||||
7735 | PRINT_ADDR(cp->cmd); | |||||
7736 | printfprintk ("sync msgin: "); | |||||
7737 | (void) ncr_show_msg (np->msgin); | |||||
7738 | printfprintk (".\n"); | |||||
7739 | }; | |||||
7740 | ||||||
7741 | /* | |||||
7742 | ** get requested values. | |||||
7743 | */ | |||||
7744 | ||||||
7745 | chg = 0; | |||||
7746 | per = np->msgin[3]; | |||||
7747 | ofs = np->msgin[4]; | |||||
7748 | if (ofs==0) per=255; | |||||
7749 | ||||||
7750 | /* | |||||
7751 | ** if target sends SDTR message, | |||||
7752 | ** it CAN transfer synch. | |||||
7753 | */ | |||||
7754 | ||||||
7755 | if (ofs) | |||||
7756 | tp->inqdata[7] |= INQ7_SYNC(0x10); | |||||
7757 | ||||||
7758 | /* | |||||
7759 | ** check values against driver limits. | |||||
7760 | */ | |||||
7761 | ||||||
7762 | if (per < np->minsync) | |||||
7763 | {chg = 1; per = np->minsync;} | |||||
7764 | if (per < tp->minsync) | |||||
7765 | {chg = 1; per = tp->minsync;} | |||||
7766 | if (ofs > tp->maxoffs) | |||||
7767 | {chg = 1; ofs = tp->maxoffs;} | |||||
7768 | ||||||
7769 | /* | |||||
7770 | ** Check against controller limits. | |||||
7771 | */ | |||||
7772 | fak = 7; | |||||
7773 | scntl3 = 0; | |||||
7774 | if (ofs != 0) { | |||||
7775 | ncr_getsync(np, per, &fak, &scntl3); | |||||
7776 | if (fak > 7) { | |||||
7777 | chg = 1; | |||||
7778 | ofs = 0; | |||||
7779 | } | |||||
7780 | } | |||||
7781 | if (ofs == 0) { | |||||
7782 | fak = 7; | |||||
7783 | per = 0; | |||||
7784 | scntl3 = 0; | |||||
7785 | tp->minsync = 0; | |||||
7786 | } | |||||
7787 | ||||||
7788 | if (DEBUG_FLAGSncr_debug & DEBUG_NEGO(0x0200)) { | |||||
7789 | PRINT_ADDR(cp->cmd); | |||||
7790 | printfprintk ("sync: per=%d scntl3=0x%x ofs=%d fak=%d chg=%d.\n", | |||||
7791 | per, scntl3, ofs, fak, chg); | |||||
7792 | } | |||||
7793 | ||||||
7794 | if (INB (HS_PRT)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_scr1))))) == HS_NEGOTIATE(2)) { | |||||
7795 | OUTB (HS_PRT, HS_BUSY)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_scr1))))) = ((((1))))); | |||||
7796 | switch (cp->nego_statusphys.header.scr_st[2]) { | |||||
7797 | ||||||
7798 | case NS_SYNC(1): | |||||
7799 | /* | |||||
7800 | ** This was an answer message | |||||
7801 | */ | |||||
7802 | if (chg) { | |||||
7803 | /* | |||||
7804 | ** Answer wasn't acceptable. | |||||
7805 | */ | |||||
7806 | ncr_setsync (np, cp, 0, 0xe0); | |||||
7807 | OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, msg_bad))((*(volatile unsigned int *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_dsp))))) = ((((np->p_script + ((size_t) (&((struct script *)0)->msg_bad))))))); | |||||
7808 | } else { | |||||
7809 | /* | |||||
7810 | ** Answer is ok. | |||||
7811 | */ | |||||
7812 | ncr_setsync (np, cp, scntl3, (fak<<5)|ofs); | |||||
7813 | OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, clrack))((*(volatile unsigned int *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_dsp))))) = ((((np->p_script + ((size_t) (&((struct script *)0)->clrack))))))); | |||||
7814 | }; | |||||
7815 | return; | |||||
7816 | ||||||
7817 | case NS_WIDE(2): | |||||
7818 | ncr_setwide (np, cp, 0, 0); | |||||
7819 | break; | |||||
7820 | }; | |||||
7821 | }; | |||||
7822 | ||||||
7823 | /* | |||||
7824 | ** It was a request. | |||||
7825 | ** Check against the table of target capabilities. | |||||
7826 | ** If target not capable force M_REJECT and asynchronous. | |||||
7827 | */ | |||||
7828 | if (np->unit < SCSI_NCR_MAX_HOST(2)) { | |||||
7829 | tp->inqdata[7] &= | |||||
7830 | (target_capabilities[np->unit].and_map[target]); | |||||
7831 | if (!(tp->inqdata[7] & INQ7_SYNC(0x10))) { | |||||
7832 | ofs = 0; | |||||
7833 | fak = 7; | |||||
7834 | } | |||||
7835 | } | |||||
7836 | ||||||
7837 | /* | |||||
7838 | ** It was a request. Set value and | |||||
7839 | ** prepare an answer message | |||||
7840 | */ | |||||
7841 | ||||||
7842 | ncr_setsync (np, cp, scntl3, (fak<<5)|ofs); | |||||
7843 | ||||||
7844 | np->msgout[0] = M_EXTENDED(0x01); | |||||
7845 | np->msgout[1] = 3; | |||||
7846 | np->msgout[2] = M_X_SYNC_REQ(0x01); | |||||
7847 | np->msgout[3] = per; | |||||
7848 | np->msgout[4] = ofs; | |||||
7849 | ||||||
7850 | cp->nego_statusphys.header.scr_st[2] = NS_SYNC(1); | |||||
7851 | ||||||
7852 | if (DEBUG_FLAGSncr_debug & DEBUG_NEGO(0x0200)) { | |||||
7853 | PRINT_ADDR(cp->cmd); | |||||
7854 | printfprintk ("sync msgout: "); | |||||
7855 | (void) ncr_show_msg (np->msgout); | |||||
7856 | printfprintk (".\n"); | |||||
7857 | } | |||||
7858 | ||||||
7859 | if (!ofs) { | |||||
7860 | OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, msg_bad))((*(volatile unsigned int *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_dsp))))) = ((((np->p_script + ((size_t) (&((struct script *)0)->msg_bad))))))); | |||||
7861 | return; | |||||
7862 | } | |||||
7863 | np->msgin [0] = M_NOOP(0x08); | |||||
7864 | ||||||
7865 | break; | |||||
7866 | ||||||
7867 | case SIR_NEGO_WIDE(6): | |||||
7868 | /* | |||||
7869 | ** Wide request message received. | |||||
7870 | */ | |||||
7871 | if (DEBUG_FLAGSncr_debug & DEBUG_NEGO(0x0200)) { | |||||
7872 | PRINT_ADDR(cp->cmd); | |||||
7873 | printfprintk ("wide msgin: "); | |||||
7874 | (void) ncr_show_msg (np->msgin); | |||||
7875 | printfprintk (".\n"); | |||||
7876 | }; | |||||
7877 | ||||||
7878 | /* | |||||
7879 | ** get requested values. | |||||
7880 | */ | |||||
7881 | ||||||
7882 | chg = 0; | |||||
7883 | wide = np->msgin[3]; | |||||
7884 | ||||||
7885 | /* | |||||
7886 | ** if target sends WDTR message, | |||||
7887 | ** it CAN transfer wide. | |||||
7888 | */ | |||||
7889 | ||||||
7890 | if (wide) | |||||
7891 | tp->inqdata[7] |= INQ7_WIDE16(0x20); | |||||
7892 | ||||||
7893 | /* | |||||
7894 | ** check values against driver limits. | |||||
7895 | */ | |||||
7896 | ||||||
7897 | if (wide > tp->usrwide) | |||||
7898 | {chg = 1; wide = tp->usrwide;} | |||||
7899 | ||||||
7900 | if (DEBUG_FLAGSncr_debug & DEBUG_NEGO(0x0200)) { | |||||
7901 | PRINT_ADDR(cp->cmd); | |||||
7902 | printfprintk ("wide: wide=%d chg=%d.\n", wide, chg); | |||||
7903 | } | |||||
7904 | ||||||
7905 | if (INB (HS_PRT)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_scr1))))) == HS_NEGOTIATE(2)) { | |||||
7906 | OUTB (HS_PRT, HS_BUSY)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_scr1))))) = ((((1))))); | |||||
7907 | switch (cp->nego_statusphys.header.scr_st[2]) { | |||||
7908 | ||||||
7909 | case NS_WIDE(2): | |||||
7910 | /* | |||||
7911 | ** This was an answer message | |||||
7912 | */ | |||||
7913 | if (chg) { | |||||
7914 | /* | |||||
7915 | ** Answer wasn't acceptable. | |||||
7916 | */ | |||||
7917 | ncr_setwide (np, cp, 0, 1); | |||||
7918 | OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, msg_bad))((*(volatile unsigned int *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_dsp))))) = ((((np->p_script + ((size_t) (&((struct script *)0)->msg_bad))))))); | |||||
7919 | } else { | |||||
7920 | /* | |||||
7921 | ** Answer is ok. | |||||
7922 | */ | |||||
7923 | ncr_setwide (np, cp, wide, 1); | |||||
7924 | OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, clrack))((*(volatile unsigned int *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_dsp))))) = ((((np->p_script + ((size_t) (&((struct script *)0)->clrack))))))); | |||||
7925 | }; | |||||
7926 | return; | |||||
7927 | ||||||
7928 | case NS_SYNC(1): | |||||
7929 | ncr_setsync (np, cp, 0, 0xe0); | |||||
7930 | break; | |||||
7931 | }; | |||||
7932 | }; | |||||
7933 | ||||||
7934 | /* | |||||
7935 | ** It was a request, set value and | |||||
7936 | ** prepare an answer message | |||||
7937 | */ | |||||
7938 | ||||||
7939 | ncr_setwide (np, cp, wide, 1); | |||||
7940 | ||||||
7941 | np->msgout[0] = M_EXTENDED(0x01); | |||||
7942 | np->msgout[1] = 2; | |||||
7943 | np->msgout[2] = M_X_WIDE_REQ(0x03); | |||||
7944 | np->msgout[3] = wide; | |||||
7945 | ||||||
7946 | np->msgin [0] = M_NOOP(0x08); | |||||
7947 | ||||||
7948 | cp->nego_statusphys.header.scr_st[2] = NS_WIDE(2); | |||||
7949 | ||||||
7950 | if (DEBUG_FLAGSncr_debug & DEBUG_NEGO(0x0200)) { | |||||
7951 | PRINT_ADDR(cp->cmd); | |||||
7952 | printfprintk ("wide msgout: "); | |||||
7953 | (void) ncr_show_msg (np->msgin); | |||||
7954 | printfprintk (".\n"); | |||||
7955 | } | |||||
7956 | break; | |||||
7957 | ||||||
7958 | /*-------------------------------------------------------------------- | |||||
7959 | ** | |||||
7960 | ** Processing of special messages | |||||
7961 | ** | |||||
7962 | **-------------------------------------------------------------------- | |||||
7963 | */ | |||||
7964 | ||||||
7965 | case SIR_REJECT_RECEIVED(9): | |||||
7966 | /*----------------------------------------------- | |||||
7967 | ** | |||||
7968 | ** We received a M_REJECT message. | |||||
7969 | ** | |||||
7970 | **----------------------------------------------- | |||||
7971 | */ | |||||
7972 | ||||||
7973 | PRINT_ADDR(cp->cmd); | |||||
7974 | printfprintk ("M_REJECT received (%x:%x).\n", | |||||
7975 | (unsigned)scr_to_cpu(np->lastmsg)(np->lastmsg), np->msgout[0]); | |||||
7976 | break; | |||||
7977 | ||||||
7978 | case SIR_REJECT_SENT(10): | |||||
7979 | /*----------------------------------------------- | |||||
7980 | ** | |||||
7981 | ** We received an unknown message | |||||
7982 | ** | |||||
7983 | **----------------------------------------------- | |||||
7984 | */ | |||||
7985 | ||||||
7986 | PRINT_ADDR(cp->cmd); | |||||
7987 | printfprintk ("M_REJECT sent for "); | |||||
7988 | (void) ncr_show_msg (np->msgin); | |||||
7989 | printfprintk (".\n"); | |||||
7990 | break; | |||||
7991 | ||||||
7992 | /*-------------------------------------------------------------------- | |||||
7993 | ** | |||||
7994 | ** Processing of special messages | |||||
7995 | ** | |||||
7996 | **-------------------------------------------------------------------- | |||||
7997 | */ | |||||
7998 | ||||||
7999 | case SIR_IGN_RESIDUE(11): | |||||
8000 | /*----------------------------------------------- | |||||
8001 | ** | |||||
8002 | ** We received an IGNORE RESIDUE message, | |||||
8003 | ** which couldn't be handled by the script. | |||||
8004 | ** | |||||
8005 | **----------------------------------------------- | |||||
8006 | */ | |||||
8007 | ||||||
8008 | PRINT_ADDR(cp->cmd); | |||||
8009 | printfprintk ("M_IGN_RESIDUE received, but not yet implemented.\n"); | |||||
8010 | break; | |||||
8011 | ||||||
8012 | case SIR_MISSING_SAVE(12): | |||||
8013 | /*----------------------------------------------- | |||||
8014 | ** | |||||
8015 | ** We received an DISCONNECT message, | |||||
8016 | ** but the datapointer wasn't saved before. | |||||
8017 | ** | |||||
8018 | **----------------------------------------------- | |||||
8019 | */ | |||||
8020 | ||||||
8021 | PRINT_ADDR(cp->cmd); | |||||
8022 | printfprintk ("M_DISCONNECT received, but datapointer not saved: " | |||||
8023 | "data=%x save=%x goal=%x.\n", | |||||
8024 | (unsigned) INL (nc_temp)(*(volatile unsigned int *) ((char *)np->reg + (((size_t) ( &((struct ncr_reg *)0)->nc_temp))))), | |||||
8025 | (unsigned) scr_to_cpu(np->header.savep)(np->header.savep), | |||||
8026 | (unsigned) scr_to_cpu(np->header.goalp)(np->header.goalp)); | |||||
8027 | break; | |||||
8028 | ||||||
8029 | #if 0 /* This stuff does not work */ | |||||
8030 | /*-------------------------------------------------------------------- | |||||
8031 | ** | |||||
8032 | ** Processing of a "S_QUEUE_FULL" status. | |||||
8033 | ** | |||||
8034 | ** The current command has been rejected, | |||||
8035 | ** because there are too many in the command queue. | |||||
8036 | ** We have started too many commands for that target. | |||||
8037 | ** | |||||
8038 | ** If possible, reinsert at head of queue. | |||||
8039 | ** Stall queue until there are no disconnected jobs | |||||
8040 | ** (ncr is REALLY idle). Then restart processing. | |||||
8041 | ** | |||||
8042 | ** We should restart the current job after the controller | |||||
8043 | ** has become idle. But this is not yet implemented. | |||||
8044 | ** | |||||
8045 | **-------------------------------------------------------------------- | |||||
8046 | */ | |||||
8047 | case SIR_STALL_QUEUE(4): | |||||
8048 | /*----------------------------------------------- | |||||
8049 | ** | |||||
8050 | ** Stall the start queue. | |||||
8051 | ** | |||||
8052 | **----------------------------------------------- | |||||
8053 | */ | |||||
8054 | PRINT_ADDR(cp->cmd); | |||||
8055 | printfprintk ("queue full.\n"); | |||||
8056 | ||||||
8057 | np->script->start1[0] = cpu_to_scr(SCR_INT)(0x98080000); | |||||
8058 | ||||||
8059 | /* | |||||
8060 | ** Try to disable tagged transfers. | |||||
8061 | */ | |||||
8062 | ncr_setmaxtags (np, &np->target[target], 0); | |||||
8063 | ||||||
8064 | /* | |||||
8065 | ** @QUEUE@ | |||||
8066 | ** | |||||
8067 | ** Should update the launch field of the | |||||
8068 | ** current job to be able to restart it. | |||||
8069 | ** Then prepend it to the start queue. | |||||
8070 | */ | |||||
8071 | ||||||
8072 | /* fall through */ | |||||
8073 | ||||||
8074 | case SIR_STALL_RESTART(3): | |||||
8075 | /*----------------------------------------------- | |||||
8076 | ** | |||||
8077 | ** Enable selecting again, | |||||
8078 | ** if NO disconnected jobs. | |||||
8079 | ** | |||||
8080 | **----------------------------------------------- | |||||
8081 | */ | |||||
8082 | /* | |||||
8083 | ** Look for a disconnected job. | |||||
8084 | */ | |||||
8085 | cp = np->ccb; | |||||
8086 | while (cp && cp->host_statusphys.header.status[1] != HS_DISCONNECT(3)) | |||||
8087 | cp = cp->link_ccb; | |||||
8088 | ||||||
8089 | /* | |||||
8090 | ** if there is one, ... | |||||
8091 | */ | |||||
8092 | if (cp) { | |||||
8093 | /* | |||||
8094 | ** wait for reselection | |||||
8095 | */ | |||||
8096 | OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, reselect))((*(volatile unsigned int *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_dsp))))) = ((((np->p_script + ((size_t) (&((struct script *)0)->reselect))))))); | |||||
8097 | return; | |||||
8098 | }; | |||||
8099 | ||||||
8100 | /* | |||||
8101 | ** else remove the interrupt. | |||||
8102 | */ | |||||
8103 | ||||||
8104 | printfprintk ("%s: queue empty.\n", ncr_name (np)); | |||||
8105 | np->script->start1[0] = cpu_to_scr(SCR_INT ^ IFFALSE (0))(0x98080000 ^ (0x00080000 | (0))); | |||||
8106 | break; | |||||
8107 | #endif /* This stuff does not work */ | |||||
8108 | }; | |||||
8109 | ||||||
8110 | out: | |||||
8111 | OUTONB (nc_dcntl, (STD|NOCOM))((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_dcntl))))) = ((((*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_dcntl))))) | ((0x04|0x01)))))); | |||||
8112 | } | |||||
8113 | ||||||
8114 | /*========================================================== | |||||
8115 | ** | |||||
8116 | ** | |||||
8117 | ** Aquire a control block | |||||
8118 | ** | |||||
8119 | ** | |||||
8120 | **========================================================== | |||||
8121 | */ | |||||
8122 | ||||||
8123 | static ccb_p ncr_get_ccb | |||||
8124 | (ncb_p np, u_longunsigned long target, u_longunsigned long lun) | |||||
8125 | { | |||||
8126 | lcb_p lp; | |||||
8127 | ccb_p cp = (ccb_p) 0; | |||||
8128 | ||||||
8129 | /* | |||||
8130 | ** Lun structure available ? | |||||
8131 | */ | |||||
8132 | ||||||
8133 | lp = np->target[target].lp[lun]; | |||||
8134 | ||||||
8135 | if (lp && lp->opennings && (!lp->active || lp->active < lp->reqlink)) { | |||||
8136 | ||||||
8137 | cp = lp->next_ccb; | |||||
8138 | ||||||
8139 | /* | |||||
8140 | ** Look for free CCB | |||||
8141 | */ | |||||
8142 | ||||||
8143 | while (cp && cp->magic) cp = cp->next_ccb; | |||||
8144 | ||||||
8145 | /* | |||||
8146 | ** Increment active commands and decrement credit. | |||||
8147 | */ | |||||
8148 | ||||||
8149 | if (cp) { | |||||
8150 | ++lp->active; | |||||
8151 | --lp->opennings; | |||||
8152 | } | |||||
8153 | } | |||||
8154 | ||||||
8155 | /* | |||||
8156 | ** if nothing available, take the default. | |||||
8157 | ** DANGEROUS, because this ccb is not suitable for | |||||
8158 | ** reselection. | |||||
8159 | ** If lp->actccbs > 0 wait for a suitable ccb to be free. | |||||
8160 | */ | |||||
8161 | if ((!cp) && lp && lp->actccbs > 0) | |||||
8162 | return ((ccb_p) 0); | |||||
8163 | ||||||
8164 | if (!cp) cp = np->ccb; | |||||
8165 | ||||||
8166 | /* | |||||
8167 | ** Wait until available. | |||||
8168 | */ | |||||
8169 | #if 0 | |||||
8170 | while (cp->magic) { | |||||
8171 | if (flags & SCSI_NOSLEEP) break; | |||||
8172 | if (tsleep ((caddr_t)cp, PRIBIO|PCATCH, "ncr", 0)) | |||||
8173 | break; | |||||
8174 | }; | |||||
8175 | #endif | |||||
8176 | ||||||
8177 | if (cp->magic) | |||||
8178 | return ((ccb_p) 0); | |||||
8179 | ||||||
8180 | cp->magic = 1; | |||||
8181 | return (cp); | |||||
8182 | } | |||||
8183 | ||||||
8184 | /*========================================================== | |||||
8185 | ** | |||||
8186 | ** | |||||
8187 | ** Release one control block | |||||
8188 | ** | |||||
8189 | ** | |||||
8190 | **========================================================== | |||||
8191 | */ | |||||
8192 | ||||||
8193 | void ncr_free_ccb (ncb_p np, ccb_p cp, u_longunsigned long target, u_longunsigned long lun) | |||||
8194 | { | |||||
8195 | lcb_p lp; | |||||
8196 | ||||||
8197 | /* | |||||
8198 | ** sanity | |||||
8199 | */ | |||||
8200 | ||||||
8201 | assert (cp != NULL){ if (!(cp != ((void *) 0))) { (void)printk( "assertion \"%s\" failed: file \"%s\", line %d\n" , "cp != NULL", "../linux/src/drivers/scsi/ncr53c8xx.c", 8201 ); } }; | |||||
8202 | ||||||
8203 | /* | |||||
8204 | ** Decrement active commands and increment credit. | |||||
8205 | */ | |||||
8206 | ||||||
8207 | lp = np->target[target].lp[lun]; | |||||
8208 | if (lp) { | |||||
8209 | --lp->active; | |||||
8210 | ++lp->opennings; | |||||
8211 | } | |||||
8212 | ||||||
8213 | cp -> host_statusphys.header.status[1] = HS_IDLE(0); | |||||
8214 | cp -> magic = 0; | |||||
8215 | #if 0 | |||||
8216 | if (cp == np->ccb) | |||||
8217 | wakeup ((caddr_t) cp); | |||||
8218 | #endif | |||||
8219 | } | |||||
8220 | ||||||
8221 | /*========================================================== | |||||
8222 | ** | |||||
8223 | ** | |||||
8224 | ** Allocation of resources for Targets/Luns/Tags. | |||||
8225 | ** | |||||
8226 | ** | |||||
8227 | **========================================================== | |||||
8228 | */ | |||||
8229 | ||||||
8230 | static void ncr_alloc_ccb (ncb_p np, u_longunsigned long target, u_longunsigned long lun) | |||||
8231 | { | |||||
8232 | tcb_p tp; | |||||
8233 | lcb_p lp; | |||||
8234 | ccb_p cp; | |||||
8235 | ||||||
8236 | assert (np != NULL){ if (!(np != ((void *) 0))) { (void)printk( "assertion \"%s\" failed: file \"%s\", line %d\n" , "np != NULL", "../linux/src/drivers/scsi/ncr53c8xx.c", 8236 ); } }; | |||||
8237 | ||||||
8238 | if (target>=MAX_TARGET((16))) return; | |||||
8239 | if (lun >=MAX_LUN(8) ) return; | |||||
8240 | ||||||
8241 | tp=&np->target[target]; | |||||
8242 | ||||||
8243 | if (!tp->jump_tcb.l_cmd) { | |||||
8244 | /* | |||||
8245 | ** initialize it. | |||||
8246 | */ | |||||
8247 | tp->jump_tcb.l_cmd = | |||||
8248 | cpu_to_scr((SCR_JUMP^IFFALSE (DATA (0x80 + target))))((0x80080000^(0x00080000 | ((0x00040000 | ((0x80 + target) & 0xff)))))); | |||||
8249 | tp->jump_tcb.l_paddr = np->jump_tcb.l_paddr; | |||||
8250 | ||||||
8251 | tp->getscr[0] = (np->features & FE_PFEN(1<<12)) ? | |||||
8252 | cpu_to_scr(SCR_COPY(1))((0xc0000000 | 0x01000000 | (1))):cpu_to_scr(SCR_COPY_F(1))((0xc0000000 | (1))); | |||||
8253 | tp->getscr[1] = cpu_to_scr(vtophys (&tp->sval))(virt_to_phys(&tp->sval)); | |||||
8254 | tp->getscr[2] = | |||||
8255 | cpu_to_scr(np->paddr + offsetof (struct ncr_reg, nc_sxfer))(np->paddr + ((size_t) (&((struct ncr_reg *)0)->nc_sxfer ))); | |||||
8256 | ||||||
8257 | tp->getscr[3] = (np->features & FE_PFEN(1<<12)) ? | |||||
8258 | cpu_to_scr(SCR_COPY(1))((0xc0000000 | 0x01000000 | (1))):cpu_to_scr(SCR_COPY_F(1))((0xc0000000 | (1))); | |||||
8259 | tp->getscr[4] = cpu_to_scr(vtophys (&tp->wval))(virt_to_phys(&tp->wval)); | |||||
8260 | tp->getscr[5] = | |||||
8261 | cpu_to_scr(np->paddr + offsetof (struct ncr_reg, nc_scntl3))(np->paddr + ((size_t) (&((struct ncr_reg *)0)->nc_scntl3 ))); | |||||
8262 | ||||||
8263 | assert (( (offsetof(struct ncr_reg, nc_sxfer) ^{ if (!(( (((size_t) (&((struct ncr_reg *)0)->nc_sxfer )) ^ ((size_t) (&((struct tcb *)0)->sval))) &3) == 0)) { (void)printk( "assertion \"%s\" failed: file \"%s\", line %d\n" , "( (offsetof(struct ncr_reg, nc_sxfer) ^ offsetof(struct tcb , sval )) &3) == 0" , "../linux/src/drivers/scsi/ncr53c8xx.c", 8264); } } | |||||
8264 | offsetof(struct tcb , sval )) &3) == 0){ if (!(( (((size_t) (&((struct ncr_reg *)0)->nc_sxfer )) ^ ((size_t) (&((struct tcb *)0)->sval))) &3) == 0)) { (void)printk( "assertion \"%s\" failed: file \"%s\", line %d\n" , "( (offsetof(struct ncr_reg, nc_sxfer) ^ offsetof(struct tcb , sval )) &3) == 0" , "../linux/src/drivers/scsi/ncr53c8xx.c", 8264); } }; | |||||
8265 | assert (( (offsetof(struct ncr_reg, nc_scntl3) ^{ if (!(( (((size_t) (&((struct ncr_reg *)0)->nc_scntl3 )) ^ ((size_t) (&((struct tcb *)0)->wval))) &3) == 0)) { (void)printk( "assertion \"%s\" failed: file \"%s\", line %d\n" , "( (offsetof(struct ncr_reg, nc_scntl3) ^ offsetof(struct tcb , wval )) &3) == 0" , "../linux/src/drivers/scsi/ncr53c8xx.c", 8266); } } | |||||
8266 | offsetof(struct tcb , wval )) &3) == 0){ if (!(( (((size_t) (&((struct ncr_reg *)0)->nc_scntl3 )) ^ ((size_t) (&((struct tcb *)0)->wval))) &3) == 0)) { (void)printk( "assertion \"%s\" failed: file \"%s\", line %d\n" , "( (offsetof(struct ncr_reg, nc_scntl3) ^ offsetof(struct tcb , wval )) &3) == 0" , "../linux/src/drivers/scsi/ncr53c8xx.c", 8266); } }; | |||||
8267 | ||||||
8268 | tp->call_lun.l_cmd = cpu_to_scr(SCR_CALL)(0x88080000); | |||||
8269 | tp->call_lun.l_paddr = | |||||
8270 | cpu_to_scr(NCB_SCRIPT_PHYS (np, resel_lun))((np->p_script + ((size_t) (&((struct script *)0)-> resel_lun)))); | |||||
8271 | ||||||
8272 | tp->jump_lcb.l_cmd = cpu_to_scr(SCR_JUMP)(0x80080000); | |||||
8273 | tp->jump_lcb.l_paddr = cpu_to_scr(NCB_SCRIPTH_PHYS (np, abort))((np->p_scripth + ((size_t) (&((struct scripth *)0)-> abort)))); | |||||
8274 | np->jump_tcb.l_paddr = cpu_to_scr(vtophys (&tp->jump_tcb))(virt_to_phys(&tp->jump_tcb)); | |||||
8275 | } | |||||
8276 | ||||||
8277 | /* | |||||
8278 | ** Logic unit control block | |||||
8279 | */ | |||||
8280 | lp = tp->lp[lun]; | |||||
8281 | if (!lp) { | |||||
8282 | /* | |||||
8283 | ** Allocate a lcb | |||||
8284 | */ | |||||
8285 | lp = (lcb_p) m_alloc (sizeof (struct lcb), LCB_ALIGN_SHIFT5); | |||||
8286 | if (!lp) return; | |||||
8287 | ||||||
8288 | if (DEBUG_FLAGSncr_debug & DEBUG_ALLOC(0x0001)) { | |||||
8289 | PRINT_LUN(np, target, lun)printk("<6>" "%s-<%d,%d>: ", ncr_name(np), (int) ( target), (int) (lun)); | |||||
8290 | printfprintk ("new lcb @%p.\n", lp); | |||||
8291 | } | |||||
8292 | ||||||
8293 | /* | |||||
8294 | ** Initialize it | |||||
8295 | */ | |||||
8296 | bzero (lp, sizeof (*lp))(__builtin_constant_p(0) ? (__builtin_constant_p(((sizeof (*lp )))) ? __constant_c_and_count_memset((((lp))),((0x01010101UL* (unsigned char)(0))),(((sizeof (*lp))))) : __constant_c_memset ((((lp))),((0x01010101UL*(unsigned char)(0))),(((sizeof (*lp) ))))) : (__builtin_constant_p(((sizeof (*lp)))) ? __memset_generic (((((lp)))),(((0))),((((sizeof (*lp)))))) : __memset_generic( (((lp))),((0)),(((sizeof (*lp))))))); | |||||
8297 | lp->jump_lcb.l_cmd = | |||||
8298 | cpu_to_scr(SCR_JUMP ^ IFFALSE (DATA (lun)))(0x80080000 ^ (0x00080000 | ((0x00040000 | ((lun) & 0xff) )))); | |||||
8299 | lp->jump_lcb.l_paddr = tp->jump_lcb.l_paddr; | |||||
8300 | ||||||
8301 | lp->call_tag.l_cmd = cpu_to_scr(SCR_CALL)(0x88080000); | |||||
8302 | lp->call_tag.l_paddr = | |||||
8303 | cpu_to_scr(NCB_SCRIPT_PHYS (np, resel_tag))((np->p_script + ((size_t) (&((struct script *)0)-> resel_tag)))); | |||||
8304 | ||||||
8305 | lp->jump_ccb.l_cmd = cpu_to_scr(SCR_JUMP)(0x80080000); | |||||
8306 | lp->jump_ccb.l_paddr = | |||||
8307 | cpu_to_scr(NCB_SCRIPTH_PHYS (np, aborttag))((np->p_scripth + ((size_t) (&((struct scripth *)0)-> aborttag)))); | |||||
8308 | ||||||
8309 | lp->actlink = 1; | |||||
8310 | ||||||
8311 | lp->active = 1; | |||||
8312 | ||||||
8313 | /* | |||||
8314 | ** Chain into LUN list | |||||
8315 | */ | |||||
8316 | tp->jump_lcb.l_paddr = cpu_to_scr(vtophys (&lp->jump_lcb))(virt_to_phys(&lp->jump_lcb)); | |||||
8317 | tp->lp[lun] = lp; | |||||
8318 | ||||||
8319 | ncr_setmaxtags (np, tp, driver_setup.default_tags); | |||||
8320 | } | |||||
8321 | ||||||
8322 | /* | |||||
8323 | ** Allocate ccbs up to lp->reqccbs. | |||||
8324 | */ | |||||
8325 | ||||||
8326 | /* | |||||
8327 | ** Limit possible number of ccbs. | |||||
8328 | ** | |||||
8329 | ** If tagged command queueing is enabled, | |||||
8330 | ** can use more than one ccb. | |||||
8331 | */ | |||||
8332 | if (np->actccbs >= MAX_START((7*(4)) + 4)-2) return; | |||||
8333 | if (lp->actccbs && (lp->actccbs >= lp->reqccbs)) | |||||
8334 | return; | |||||
8335 | ||||||
8336 | /* | |||||
8337 | ** Allocate a ccb | |||||
8338 | */ | |||||
8339 | cp = (ccb_p) m_alloc (sizeof (struct ccb), CCB_ALIGN_SHIFT5); | |||||
8340 | if (!cp) | |||||
8341 | return; | |||||
8342 | ||||||
8343 | if (DEBUG_FLAGSncr_debug & DEBUG_ALLOC(0x0001)) { | |||||
8344 | PRINT_LUN(np, target, lun)printk("<6>" "%s-<%d,%d>: ", ncr_name(np), (int) ( target), (int) (lun)); | |||||
8345 | printfprintk ("new ccb @%p.\n", cp); | |||||
8346 | } | |||||
8347 | ||||||
8348 | /* | |||||
8349 | ** Count it | |||||
8350 | */ | |||||
8351 | lp->actccbs++; | |||||
8352 | np->actccbs++; | |||||
8353 | ||||||
8354 | /* | |||||
8355 | ** Initialize it | |||||
8356 | */ | |||||
8357 | bzero (cp, sizeof (*cp))(__builtin_constant_p(0) ? (__builtin_constant_p(((sizeof (*cp )))) ? __constant_c_and_count_memset((((cp))),((0x01010101UL* (unsigned char)(0))),(((sizeof (*cp))))) : __constant_c_memset ((((cp))),((0x01010101UL*(unsigned char)(0))),(((sizeof (*cp) ))))) : (__builtin_constant_p(((sizeof (*cp)))) ? __memset_generic (((((cp)))),(((0))),((((sizeof (*cp)))))) : __memset_generic( (((cp))),((0)),(((sizeof (*cp))))))); | |||||
8358 | ||||||
8359 | /* | |||||
8360 | ** Fill in physical addresses | |||||
8361 | */ | |||||
8362 | ||||||
8363 | cp->p_ccb = vtophys (cp)virt_to_phys(cp); | |||||
8364 | ||||||
8365 | /* | |||||
8366 | ** Chain into reselect list | |||||
8367 | */ | |||||
8368 | cp->jump_ccb.l_cmd = cpu_to_scr(SCR_JUMP)(0x80080000); | |||||
8369 | cp->jump_ccb.l_paddr = lp->jump_ccb.l_paddr; | |||||
8370 | lp->jump_ccb.l_paddr = cpu_to_scr(CCB_PHYS (cp, jump_ccb))((cp->p_ccb + ((size_t) (&((struct ccb *)0)->jump_ccb )))); | |||||
8371 | cp->call_tmp.l_cmd = cpu_to_scr(SCR_CALL)(0x88080000); | |||||
8372 | cp->call_tmp.l_paddr = cpu_to_scr(NCB_SCRIPT_PHYS (np, resel_tmp))((np->p_script + ((size_t) (&((struct script *)0)-> resel_tmp)))); | |||||
8373 | ||||||
8374 | /* | |||||
8375 | ** Chain into wakeup list | |||||
8376 | */ | |||||
8377 | cp->link_ccb = np->ccb->link_ccb; | |||||
8378 | np->ccb->link_ccb = cp; | |||||
8379 | ||||||
8380 | /* | |||||
8381 | ** Chain into CCB list | |||||
8382 | */ | |||||
8383 | cp->next_ccb = lp->next_ccb; | |||||
8384 | lp->next_ccb = cp; | |||||
8385 | } | |||||
8386 | ||||||
8387 | /*========================================================== | |||||
8388 | ** | |||||
8389 | ** | |||||
8390 | ** Announce the number of ccbs/tags to the scsi driver. | |||||
8391 | ** | |||||
8392 | ** | |||||
8393 | **========================================================== | |||||
8394 | */ | |||||
8395 | ||||||
8396 | static void ncr_opennings (ncb_p np, lcb_p lp, Scsi_Cmnd * cmd) | |||||
8397 | { | |||||
8398 | /* | |||||
8399 | ** want to reduce the number ... | |||||
8400 | */ | |||||
8401 | if (lp->actlink > lp->reqlink) { | |||||
8402 | ||||||
8403 | /* | |||||
8404 | ** Try to reduce the count. | |||||
8405 | ** We assume to run at splbio .. | |||||
8406 | */ | |||||
8407 | u_charunsigned char diff = lp->actlink - lp->reqlink; | |||||
8408 | ||||||
8409 | if (!diff) return; | |||||
8410 | ||||||
8411 | if (diff > lp->opennings) | |||||
8412 | diff = lp->opennings; | |||||
8413 | ||||||
8414 | lp->opennings -= diff; | |||||
8415 | ||||||
8416 | lp->actlink -= diff; | |||||
8417 | if (DEBUG_FLAGSncr_debug & DEBUG_TAGS(0x0400)) | |||||
8418 | printfprintk ("%s: actlink: diff=%d, new=%d, req=%d\n", | |||||
8419 | ncr_name(np), diff, lp->actlink, lp->reqlink); | |||||
8420 | return; | |||||
8421 | }; | |||||
8422 | ||||||
8423 | /* | |||||
8424 | ** want to increase the number ? | |||||
8425 | */ | |||||
8426 | if (lp->reqlink > lp->actlink) { | |||||
8427 | u_charunsigned char diff = lp->reqlink - lp->actlink; | |||||
8428 | ||||||
8429 | lp->opennings += diff; | |||||
8430 | ||||||
8431 | lp->actlink += diff; | |||||
8432 | #if 0 | |||||
8433 | wakeup ((caddr_t) xp->sc_link); | |||||
8434 | #endif | |||||
8435 | if (DEBUG_FLAGSncr_debug & DEBUG_TAGS(0x0400)) | |||||
8436 | printfprintk ("%s: actlink: diff=%d, new=%d, req=%d\n", | |||||
8437 | ncr_name(np), diff, lp->actlink, lp->reqlink); | |||||
8438 | }; | |||||
8439 | } | |||||
8440 | ||||||
8441 | /*========================================================== | |||||
8442 | ** | |||||
8443 | ** | |||||
8444 | ** Build Scatter Gather Block | |||||
8445 | ** | |||||
8446 | ** | |||||
8447 | **========================================================== | |||||
8448 | ** | |||||
8449 | ** The transfer area may be scattered among | |||||
8450 | ** several non adjacent physical pages. | |||||
8451 | ** | |||||
8452 | ** We may use MAX_SCATTER blocks. | |||||
8453 | ** | |||||
8454 | **---------------------------------------------------------- | |||||
8455 | */ | |||||
8456 | ||||||
8457 | /* | |||||
8458 | ** We try to reduce the number of interrupts caused | |||||
8459 | ** by unexpected phase changes due to disconnects. | |||||
8460 | ** A typical harddisk may disconnect before ANY block. | |||||
8461 | ** If we wanted to avoid unexpected phase changes at all | |||||
8462 | ** we had to use a break point every 512 bytes. | |||||
8463 | ** Of course the number of scatter/gather blocks is | |||||
8464 | ** limited. | |||||
8465 | ** Under Linux, the scatter/gatter blocks are provided by | |||||
8466 | ** the generic driver. We just have to copy addresses and | |||||
8467 | ** sizes to the data segment array. | |||||
8468 | */ | |||||
8469 | ||||||
8470 | static int ncr_scatter(ccb_p cp, Scsi_Cmnd *cmd) | |||||
8471 | { | |||||
8472 | struct scr_tblmove *data; | |||||
8473 | int segment = 0; | |||||
8474 | int use_sg = (int) cmd->use_sg; | |||||
8475 | ||||||
8476 | #if 0 | |||||
8477 | bzero (cp->phys.data, sizeof (cp->phys.data))(__builtin_constant_p(0) ? (__builtin_constant_p(((sizeof (cp ->phys.data)))) ? __constant_c_and_count_memset((((cp-> phys.data))),((0x01010101UL*(unsigned char)(0))),(((sizeof (cp ->phys.data))))) : __constant_c_memset((((cp->phys.data ))),((0x01010101UL*(unsigned char)(0))),(((sizeof (cp->phys .data)))))) : (__builtin_constant_p(((sizeof (cp->phys.data )))) ? __memset_generic(((((cp->phys.data)))),(((0))),(((( sizeof (cp->phys.data)))))) : __memset_generic((((cp->phys .data))),((0)),(((sizeof (cp->phys.data))))))); | |||||
8478 | #endif | |||||
8479 | data = cp->phys.data; | |||||
8480 | cp->data_len = 0; | |||||
8481 | ||||||
8482 | if (!use_sg) { | |||||
8483 | if (cmd->request_bufflen) { | |||||
8484 | data = &data[MAX_SCATTER((127)) - 1]; | |||||
8485 | data[0].addr = cpu_to_scr(vtophys(cmd->request_buffer))(virt_to_phys(cmd->request_buffer)); | |||||
8486 | data[0].size = cpu_to_scr(cmd->request_bufflen)(cmd->request_bufflen); | |||||
8487 | cp->data_len = cmd->request_bufflen; | |||||
8488 | segment = 1; | |||||
8489 | } | |||||
8490 | } | |||||
8491 | else if (use_sg <= MAX_SCATTER((127))) { | |||||
8492 | struct scatterlist *scatter = (struct scatterlist *)cmd->buffer; | |||||
8493 | ||||||
8494 | data = &data[MAX_SCATTER((127)) - use_sg]; | |||||
8495 | while (segment < use_sg) { | |||||
8496 | data[segment].addr = | |||||
8497 | cpu_to_scr(vtophys(scatter[segment].address))(virt_to_phys(scatter[segment].address)); | |||||
8498 | data[segment].size = | |||||
8499 | cpu_to_scr(scatter[segment].length)(scatter[segment].length); | |||||
8500 | cp->data_len += scatter[segment].length; | |||||
8501 | ++segment; | |||||
8502 | } | |||||
8503 | } | |||||
8504 | else { | |||||
8505 | return -1; | |||||
8506 | } | |||||
8507 | ||||||
8508 | return segment; | |||||
8509 | } | |||||
8510 | ||||||
8511 | /*========================================================== | |||||
8512 | ** | |||||
8513 | ** | |||||
8514 | ** Test the pci bus snoop logic :-( | |||||
8515 | ** | |||||
8516 | ** Has to be called with interrupts disabled. | |||||
8517 | ** | |||||
8518 | ** | |||||
8519 | **========================================================== | |||||
8520 | */ | |||||
8521 | ||||||
8522 | #ifndef NCR_IOMAPPED | |||||
8523 | __initfunc(static int ncr_regtest (struct ncb* np) | |||||
8524 | static int ncr_regtest (struct ncb* np)static int ncr_regtest (struct ncb* np) | |||||
8525 | )static int ncr_regtest (struct ncb* np) | |||||
8526 | { | |||||
8527 | register volatile u_longunsigned long data; | |||||
8528 | /* | |||||
8529 | ** ncr registers may NOT be cached. | |||||
8530 | ** write 0xffffffff to a read only register area, | |||||
8531 | ** and try to read it back. | |||||
8532 | */ | |||||
8533 | data = 0xffffffff; | |||||
8534 | OUTL_OFF(offsetof(struct ncr_reg, nc_dstat), data)((*(volatile unsigned int *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_dstat))))) = ((data))); | |||||
8535 | data = INL_OFF(offsetof(struct ncr_reg, nc_dstat))(*(volatile unsigned int *) ((char *)np->reg + (((size_t) ( &((struct ncr_reg *)0)->nc_dstat))))); | |||||
8536 | #if 1 | |||||
8537 | if (data == 0xffffffff) { | |||||
8538 | #else | |||||
8539 | if ((data & 0xe2f0fffd) != 0x02000080) { | |||||
8540 | #endif | |||||
8541 | printfprintk ("CACHE TEST FAILED: reg dstat-sstat2 readback %x.\n", | |||||
8542 | (unsigned) data); | |||||
8543 | return (0x10); | |||||
8544 | }; | |||||
8545 | return (0); | |||||
8546 | } | |||||
8547 | #endif | |||||
8548 | ||||||
8549 | __initfunc(static int ncr_snooptest (struct ncb* np) | |||||
8550 | static int ncr_snooptest (struct ncb* np)static int ncr_snooptest (struct ncb* np) | |||||
8551 | )static int ncr_snooptest (struct ncb* np) | |||||
8552 | { | |||||
8553 | u_longunsigned long ncr_rd, ncr_wr, ncr_bk, host_rd, host_wr, pc, err=0; | |||||
8554 | int i; | |||||
8555 | #ifndef NCR_IOMAPPED | |||||
8556 | if (np->reg) { | |||||
| ||||||
8557 | err |= ncr_regtest (np); | |||||
8558 | if (err) return (err); | |||||
8559 | } | |||||
8560 | #endif | |||||
8561 | /* | |||||
8562 | ** init | |||||
8563 | */ | |||||
8564 | pc = NCB_SCRIPTH_PHYS (np, snooptest)(np->p_scripth + ((size_t) (&((struct scripth *)0)-> snooptest))); | |||||
8565 | host_wr = 1; | |||||
8566 | ncr_wr = 2; | |||||
8567 | /* | |||||
8568 | ** Set memory and register. | |||||
8569 | */ | |||||
8570 | np->ncr_cache = cpu_to_scr(host_wr)(host_wr); | |||||
8571 | OUTL (nc_temp, ncr_wr)((*(volatile unsigned int *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_temp))))) = (((ncr_wr)))); | |||||
| ||||||
8572 | /* | |||||
8573 | ** Start script (exchange values) | |||||
8574 | */ | |||||
8575 | OUTL (nc_dsp, pc)((*(volatile unsigned int *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_dsp))))) = (((pc)))); | |||||
8576 | /* | |||||
8577 | ** Wait 'til done (with timeout) | |||||
8578 | */ | |||||
8579 | for (i=0; i<NCR_SNOOP_TIMEOUT(1000000); i++) | |||||
8580 | if (INB(nc_istat)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_istat))))) & (INTF0x04|SIP0x02|DIP0x01)) | |||||
8581 | break; | |||||
8582 | /* | |||||
8583 | ** Save termination position. | |||||
8584 | */ | |||||
8585 | pc = INL (nc_dsp)(*(volatile unsigned int *) ((char *)np->reg + (((size_t) ( &((struct ncr_reg *)0)->nc_dsp))))); | |||||
8586 | /* | |||||
8587 | ** Read memory and register. | |||||
8588 | */ | |||||
8589 | host_rd = scr_to_cpu(np->ncr_cache)(np->ncr_cache); | |||||
8590 | ncr_rd = INL (nc_scratcha)(*(volatile unsigned int *) ((char *)np->reg + (((size_t) ( &((struct ncr_reg *)0)->nc_scratcha))))); | |||||
8591 | ncr_bk = INL (nc_temp)(*(volatile unsigned int *) ((char *)np->reg + (((size_t) ( &((struct ncr_reg *)0)->nc_temp))))); | |||||
8592 | /* | |||||
8593 | ** Reset ncr chip | |||||
8594 | */ | |||||
8595 | OUTB (nc_istat, SRST)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_istat))))) = (((0x40)))); | |||||
8596 | DELAY (1000); | |||||
8597 | OUTB (nc_istat, 0 )((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_istat))))) = (((0)))); | |||||
8598 | /* | |||||
8599 | ** check for timeout | |||||
8600 | */ | |||||
8601 | if (i>=NCR_SNOOP_TIMEOUT(1000000)) { | |||||
8602 | printfprintk ("CACHE TEST FAILED: timeout.\n"); | |||||
8603 | return (0x20); | |||||
8604 | }; | |||||
8605 | /* | |||||
8606 | ** Check termination position. | |||||
8607 | */ | |||||
8608 | if (pc != NCB_SCRIPTH_PHYS (np, snoopend)(np->p_scripth + ((size_t) (&((struct scripth *)0)-> snoopend)))+8) { | |||||
8609 | printfprintk ("CACHE TEST FAILED: script execution failed.\n"); | |||||
8610 | printfprintk ("start=%08lx, pc=%08lx, end=%08lx\n", | |||||
8611 | (u_longunsigned long) NCB_SCRIPTH_PHYS (np, snooptest)(np->p_scripth + ((size_t) (&((struct scripth *)0)-> snooptest))), pc, | |||||
8612 | (u_longunsigned long) NCB_SCRIPTH_PHYS (np, snoopend)(np->p_scripth + ((size_t) (&((struct scripth *)0)-> snoopend))) +8); | |||||
8613 | return (0x40); | |||||
8614 | }; | |||||
8615 | /* | |||||
8616 | ** Show results. | |||||
8617 | */ | |||||
8618 | if (host_wr != ncr_rd) { | |||||
8619 | printfprintk ("CACHE TEST FAILED: host wrote %d, ncr read %d.\n", | |||||
8620 | (int) host_wr, (int) ncr_rd); | |||||
8621 | err |= 1; | |||||
8622 | }; | |||||
8623 | if (host_rd != ncr_wr) { | |||||
8624 | printfprintk ("CACHE TEST FAILED: ncr wrote %d, host read %d.\n", | |||||
8625 | (int) ncr_wr, (int) host_rd); | |||||
8626 | err |= 2; | |||||
8627 | }; | |||||
8628 | if (ncr_bk != ncr_wr) { | |||||
8629 | printfprintk ("CACHE TEST FAILED: ncr wrote %d, read back %d.\n", | |||||
8630 | (int) ncr_wr, (int) ncr_bk); | |||||
8631 | err |= 4; | |||||
8632 | }; | |||||
8633 | return (err); | |||||
8634 | } | |||||
8635 | ||||||
8636 | /*========================================================== | |||||
8637 | ** | |||||
8638 | ** | |||||
8639 | ** Profiling the drivers and targets performance. | |||||
8640 | ** | |||||
8641 | ** | |||||
8642 | **========================================================== | |||||
8643 | */ | |||||
8644 | ||||||
8645 | #ifdef SCSI_NCR_PROFILE_SUPPORT | |||||
8646 | ||||||
8647 | /* | |||||
8648 | ** Compute the difference in jiffies ticks. | |||||
8649 | */ | |||||
8650 | ||||||
8651 | #define ncr_delta(from, to) \ | |||||
8652 | ( ((to) && (from))? (to) - (from) : -1 ) | |||||
8653 | ||||||
8654 | #define PROFILE cp->phys.header.stamp | |||||
8655 | static void ncb_profile (ncb_p np, ccb_p cp) | |||||
8656 | { | |||||
8657 | int co, st, en, di, se, post,work,disc; | |||||
8658 | u_longunsigned long diff; | |||||
8659 | ||||||
8660 | PROFILE.end = jiffies; | |||||
8661 | ||||||
8662 | st = ncr_delta (PROFILE.start,PROFILE.status); | |||||
8663 | if (st<0) return; /* status not reached */ | |||||
8664 | ||||||
8665 | co = ncr_delta (PROFILE.start,PROFILE.command); | |||||
8666 | if (co<0) return; /* command not executed */ | |||||
8667 | ||||||
8668 | en = ncr_delta (PROFILE.start,PROFILE.end), | |||||
8669 | di = ncr_delta (PROFILE.start,PROFILE.disconnect), | |||||
8670 | se = ncr_delta (PROFILE.start,PROFILE.select); | |||||
8671 | post = en - st; | |||||
8672 | ||||||
8673 | /* | |||||
8674 | ** @PROFILE@ Disconnect time invalid if multiple disconnects | |||||
8675 | */ | |||||
8676 | ||||||
8677 | if (di>=0) disc = se-di; else disc = 0; | |||||
8678 | ||||||
8679 | work = (st - co) - disc; | |||||
8680 | ||||||
8681 | diff = (np->disc_phys - np->disc_ref) & 0xff; | |||||
8682 | np->disc_ref += diff; | |||||
8683 | ||||||
8684 | np->profile.num_trans += 1; | |||||
8685 | if (cp->cmd) { | |||||
8686 | np->profile.num_kbytes += (cp->cmd->request_bufflen >> 10); | |||||
8687 | np->profile.rest_bytes += (cp->cmd->request_bufflen & (0x400-1)); | |||||
8688 | if (np->profile.rest_bytes >= 0x400) { | |||||
8689 | ++np->profile.num_kbytes; | |||||
8690 | np->profile.rest_bytes -= 0x400; | |||||
8691 | } | |||||
8692 | } | |||||
8693 | np->profile.num_disc += diff; | |||||
8694 | np->profile.ms_setup += co; | |||||
8695 | np->profile.ms_data += work; | |||||
8696 | np->profile.ms_disc += disc; | |||||
8697 | np->profile.ms_post += post; | |||||
8698 | } | |||||
8699 | #undef PROFILE | |||||
8700 | ||||||
8701 | #endif /* SCSI_NCR_PROFILE_SUPPORT */ | |||||
8702 | ||||||
8703 | /*========================================================== | |||||
8704 | ** | |||||
8705 | ** | |||||
8706 | ** Device lookup. | |||||
8707 | ** | |||||
8708 | ** @GENSCSI@ should be integrated to scsiconf.c | |||||
8709 | ** | |||||
8710 | ** | |||||
8711 | **========================================================== | |||||
8712 | */ | |||||
8713 | ||||||
8714 | struct table_entry { | |||||
8715 | char * manufacturer; | |||||
8716 | char * model; | |||||
8717 | char * version; | |||||
8718 | u_longunsigned long info; | |||||
8719 | }; | |||||
8720 | ||||||
8721 | static struct table_entry device_tab[] = | |||||
8722 | { | |||||
8723 | #ifdef NCR_GETCC_WITHMSG | |||||
8724 | {"", "", "", QUIRK_NOMSG(0x02)}, | |||||
8725 | {"SONY", "SDT-5000", "3.17", QUIRK_NOMSG(0x02)}, | |||||
8726 | {"WangDAT", "Model 2600", "01.7", QUIRK_NOMSG(0x02)}, | |||||
8727 | {"WangDAT", "Model 3200", "02.2", QUIRK_NOMSG(0x02)}, | |||||
8728 | {"WangDAT", "Model 1300", "02.4", QUIRK_NOMSG(0x02)}, | |||||
8729 | #endif | |||||
8730 | {"", "", "", 0} /* catch all: must be last entry. */ | |||||
8731 | }; | |||||
8732 | ||||||
8733 | static u_longunsigned long ncr_lookup(char * id) | |||||
8734 | { | |||||
8735 | struct table_entry * p = device_tab; | |||||
8736 | char *d, *r, c; | |||||
8737 | ||||||
8738 | for (;;p++) { | |||||
8739 | ||||||
8740 | d = id+8; | |||||
8741 | r = p->manufacturer; | |||||
8742 | while ((c=*r++)) if (c!=*d++) break; | |||||
8743 | if (c) continue; | |||||
8744 | ||||||
8745 | d = id+16; | |||||
8746 | r = p->model; | |||||
8747 | while ((c=*r++)) if (c!=*d++) break; | |||||
8748 | if (c) continue; | |||||
8749 | ||||||
8750 | d = id+32; | |||||
8751 | r = p->version; | |||||
8752 | while ((c=*r++)) if (c!=*d++) break; | |||||
8753 | if (c) continue; | |||||
8754 | ||||||
8755 | return (p->info); | |||||
8756 | } | |||||
8757 | } | |||||
8758 | ||||||
8759 | /*========================================================== | |||||
8760 | ** | |||||
8761 | ** Determine the ncr's clock frequency. | |||||
8762 | ** This is essential for the negotiation | |||||
8763 | ** of the synchronous transfer rate. | |||||
8764 | ** | |||||
8765 | **========================================================== | |||||
8766 | ** | |||||
8767 | ** Note: we have to return the correct value. | |||||
8768 | ** THERE IS NO SAVE DEFAULT VALUE. | |||||
8769 | ** | |||||
8770 | ** Most NCR/SYMBIOS boards are delivered with a 40 Mhz clock. | |||||
8771 | ** 53C860 and 53C875 rev. 1 support fast20 transfers but | |||||
8772 | ** do not have a clock doubler and so are provided with a | |||||
8773 | ** 80 MHz clock. All other fast20 boards incorporate a doubler | |||||
8774 | ** and so should be delivered with a 40 MHz clock. | |||||
8775 | ** The future fast40 chips (895/895) use a 40 Mhz base clock | |||||
8776 | ** and provide a clock quadrupler (160 Mhz). The code below | |||||
8777 | ** tries to deal as cleverly as possible with all this stuff. | |||||
8778 | ** | |||||
8779 | **---------------------------------------------------------- | |||||
8780 | */ | |||||
8781 | ||||||
8782 | /* | |||||
8783 | * Select NCR SCSI clock frequency | |||||
8784 | */ | |||||
8785 | static void ncr_selectclock(ncb_p np, u_charunsigned char scntl3) | |||||
8786 | { | |||||
8787 | if (np->multiplier < 2) { | |||||
8788 | OUTB(nc_scntl3, scntl3)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_scntl3))))) = (((scntl3) ))); | |||||
8789 | return; | |||||
8790 | } | |||||
8791 | ||||||
8792 | if (bootverbose(np->verbose) >= 2) | |||||
8793 | printfprintk ("%s: enabling clock multiplier\n", ncr_name(np)); | |||||
8794 | ||||||
8795 | OUTB(nc_stest1, DBLEN)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_stest1))))) = (((0x08))) ); /* Enable clock multiplier */ | |||||
8796 | if (np->multiplier > 2) { /* Poll bit 5 of stest4 for quadrupler */ | |||||
8797 | int i = 20; | |||||
8798 | while (!(INB(nc_stest4)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_stest4))))) & LCKFRQ0x20) && --i > 0) | |||||
8799 | DELAY(20); | |||||
8800 | if (!i) | |||||
8801 | printfprintk("%s: the chip cannot lock the frequency\n", ncr_name(np)); | |||||
8802 | } else /* Wait 20 micro-seconds for doubler */ | |||||
8803 | DELAY(20); | |||||
8804 | OUTB(nc_stest3, HSC)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_stest3))))) = (((0x20))) ); /* Halt the scsi clock */ | |||||
8805 | OUTB(nc_scntl3, scntl3)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_scntl3))))) = (((scntl3) ))); | |||||
8806 | OUTB(nc_stest1, (DBLEN|DBLSEL))((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_stest1))))) = ((((0x08|0x04 )))));/* Select clock multiplier */ | |||||
8807 | OUTB(nc_stest3, 0x00|TE)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_stest3))))) = (((0x00|0x80 )))); /* Restart scsi clock */ | |||||
8808 | } | |||||
8809 | ||||||
8810 | ||||||
8811 | /* | |||||
8812 | * calculate NCR SCSI clock frequency (in KHz) | |||||
8813 | */ | |||||
8814 | __initfunc(static unsigned ncrgetfreq (ncb_p np, int gen) | |||||
8815 | static unsigned ncrgetfreq (ncb_p np, int gen)static unsigned ncrgetfreq (ncb_p np, int gen) | |||||
8816 | )static unsigned ncrgetfreq (ncb_p np, int gen) | |||||
8817 | { | |||||
8818 | unsigned ms = 0; | |||||
8819 | ||||||
8820 | /* | |||||
8821 | * Measure GEN timer delay in order | |||||
8822 | * to calculate SCSI clock frequency | |||||
8823 | * | |||||
8824 | * This code will never execute too | |||||
8825 | * many loop iterations (if DELAY is | |||||
8826 | * reasonably correct). It could get | |||||
8827 | * too low a delay (too high a freq.) | |||||
8828 | * if the CPU is slow executing the | |||||
8829 | * loop for some reason (an NMI, for | |||||
8830 | * example). For this reason we will | |||||
8831 | * if multiple measurements are to be | |||||
8832 | * performed trust the higher delay | |||||
8833 | * (lower frequency returned). | |||||
8834 | */ | |||||
8835 | OUTB (nc_stest1, 0)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_stest1))))) = (((0)))); /* make sure clock doubler is OFF */ | |||||
8836 | OUTW (nc_sien , 0)((*(volatile unsigned short *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_sien))))) = (((0)))); /* mask all scsi interrupts */ | |||||
8837 | (void) INW (nc_sist)(*(volatile unsigned short *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_sist))))); /* clear pending scsi interrupt */ | |||||
8838 | OUTB (nc_dien , 0)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_dien))))) = (((0)))); /* mask all dma interrupts */ | |||||
8839 | (void) INW (nc_sist)(*(volatile unsigned short *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_sist))))); /* another one, just to be sure :) */ | |||||
8840 | OUTB (nc_scntl3, 4)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_scntl3))))) = (((4)))); /* set pre-scaler to divide by 3 */ | |||||
8841 | OUTB (nc_stime1, 0)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_stime1))))) = (((0)))); /* disable general purpose timer */ | |||||
8842 | OUTB (nc_stime1, gen)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_stime1))))) = (((gen)))); /* set to nominal delay of 1<<gen * 125us */ | |||||
8843 | while (!(INW(nc_sist)(*(volatile unsigned short *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_sist))))) & GEN0x0200) && ms++ < 100000) | |||||
8844 | DELAY(1000); /* count ms */ | |||||
8845 | OUTB (nc_stime1, 0)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_stime1))))) = (((0)))); /* disable general purpose timer */ | |||||
8846 | /* | |||||
8847 | * set prescaler to divide by whatever 0 means | |||||
8848 | * 0 ought to choose divide by 2, but appears | |||||
8849 | * to set divide by 3.5 mode in my 53c810 ... | |||||
8850 | */ | |||||
8851 | OUTB (nc_scntl3, 0)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_scntl3))))) = (((0)))); | |||||
8852 | ||||||
8853 | if (bootverbose(np->verbose) >= 2) | |||||
8854 | printfprintk ("%s: Delay (GEN=%d): %u msec\n", ncr_name(np), gen, ms); | |||||
8855 | /* | |||||
8856 | * adjust for prescaler, and convert into KHz | |||||
8857 | */ | |||||
8858 | return ms ? ((1 << gen) * 4340) / ms : 0; | |||||
8859 | } | |||||
8860 | ||||||
8861 | /* | |||||
8862 | * Get/probe NCR SCSI clock frequency | |||||
8863 | */ | |||||
8864 | __initfunc(static void ncr_getclock (ncb_p np, int mult) | |||||
8865 | static void ncr_getclock (ncb_p np, int mult)static void ncr_getclock (ncb_p np, int mult) | |||||
8866 | )static void ncr_getclock (ncb_p np, int mult) | |||||
8867 | { | |||||
8868 | unsigned char scntl3 = INB(nc_scntl3)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_scntl3))))); | |||||
8869 | unsigned char stest1 = INB(nc_stest1)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_stest1))))); | |||||
8870 | unsigned f1; | |||||
8871 | ||||||
8872 | np->multiplier = 1; | |||||
8873 | f1 = 40000; | |||||
8874 | ||||||
8875 | /* | |||||
8876 | ** True with 875 or 895 with clock multiplier selected | |||||
8877 | */ | |||||
8878 | if (mult > 1 && (stest1 & (DBLEN0x08+DBLSEL0x04)) == DBLEN0x08+DBLSEL0x04) { | |||||
8879 | if (bootverbose(np->verbose) >= 2) | |||||
8880 | printfprintk ("%s: clock multiplier found\n", ncr_name(np)); | |||||
8881 | np->multiplier = mult; | |||||
8882 | } | |||||
8883 | ||||||
8884 | /* | |||||
8885 | ** If multiplier not found or scntl3 not 7,5,3, | |||||
8886 | ** reset chip and get frequency from general purpose timer. | |||||
8887 | ** Otherwise trust scntl3 BIOS setting. | |||||
8888 | */ | |||||
8889 | if (np->multiplier != mult || (scntl3 & 7) < 3 || !(scntl3 & 1)) { | |||||
8890 | unsigned f2; | |||||
8891 | ||||||
8892 | OUTB(nc_istat, SRST)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_istat))))) = (((0x40)))); DELAY(5); OUTB(nc_istat, 0)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_istat))))) = (((0)))); | |||||
8893 | ||||||
8894 | (void) ncrgetfreq (np, 11); /* throw away first result */ | |||||
8895 | f1 = ncrgetfreq (np, 11); | |||||
8896 | f2 = ncrgetfreq (np, 11); | |||||
8897 | ||||||
8898 | if (bootverbose(np->verbose)) | |||||
8899 | printfprintk ("%s: NCR clock is %uKHz, %uKHz\n", ncr_name(np), f1, f2); | |||||
8900 | ||||||
8901 | if (f1 > f2) f1 = f2; /* trust lower result */ | |||||
8902 | ||||||
8903 | if (f1 < 45000) f1 = 40000; | |||||
8904 | else if (f1 < 55000) f1 = 50000; | |||||
8905 | else f1 = 80000; | |||||
8906 | ||||||
8907 | if (f1 < 80000 && mult > 1) { | |||||
8908 | if (bootverbose(np->verbose) >= 2) | |||||
8909 | printfprintk ("%s: clock multiplier assumed\n", ncr_name(np)); | |||||
8910 | np->multiplier = mult; | |||||
8911 | } | |||||
8912 | } else { | |||||
8913 | if ((scntl3 & 7) == 3) f1 = 40000; | |||||
8914 | else if ((scntl3 & 7) == 5) f1 = 80000; | |||||
8915 | else f1 = 160000; | |||||
8916 | ||||||
8917 | f1 /= np->multiplier; | |||||
8918 | } | |||||
8919 | ||||||
8920 | /* | |||||
8921 | ** Compute controller synchronous parameters. | |||||
8922 | */ | |||||
8923 | f1 *= np->multiplier; | |||||
8924 | np->clock_khz = f1; | |||||
8925 | } | |||||
8926 | ||||||
8927 | /*===================== LINUX ENTRY POINTS SECTION ==========================*/ | |||||
8928 | ||||||
8929 | #ifndef ucharunsigned char | |||||
8930 | #define ucharunsigned char unsigned char | |||||
8931 | #endif | |||||
8932 | ||||||
8933 | #ifndef ushortunsigned short | |||||
8934 | #define ushortunsigned short unsigned short | |||||
8935 | #endif | |||||
8936 | ||||||
8937 | #ifndef ulongunsigned long | |||||
8938 | #define ulongunsigned long unsigned long | |||||
8939 | #endif | |||||
8940 | ||||||
8941 | /* --------------------------------------------------------------------- | |||||
8942 | ** | |||||
8943 | ** Driver setup from the boot command line | |||||
8944 | ** | |||||
8945 | ** --------------------------------------------------------------------- | |||||
8946 | */ | |||||
8947 | ||||||
8948 | __initfunc(void ncr53c8xx_setup(char *str, int *ints) | |||||
8949 | void ncr53c8xx_setup(char *str, int *ints)void ncr53c8xx_setup(char *str, int *ints) | |||||
8950 | )void ncr53c8xx_setup(char *str, int *ints) | |||||
8951 | { | |||||
8952 | #ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT | |||||
8953 | char *cur = str; | |||||
8954 | char *pc, *pv; | |||||
8955 | int val; | |||||
8956 | int base; | |||||
8957 | int c; | |||||
8958 | ||||||
8959 | while (cur != NULL((void *) 0) && (pc = strchr(cur, ':')) != NULL((void *) 0)) { | |||||
8960 | val = 0; | |||||
8961 | pv = pc; | |||||
8962 | c = *++pv; | |||||
8963 | if (c == 'n') | |||||
8964 | val = 0; | |||||
8965 | else if (c == 'y') | |||||
8966 | val = 1; | |||||
8967 | else { | |||||
8968 | base = 0; | |||||
8969 | #if 0 | |||||
8970 | if (c == '0') { | |||||
8971 | c = *pv++; | |||||
8972 | base = 8; | |||||
8973 | } | |||||
8974 | if (c == 'x') { | |||||
8975 | ++pv; | |||||
8976 | base = 16; | |||||
8977 | } | |||||
8978 | else if (c >= '0' && c <= '9') | |||||
8979 | base = 10; | |||||
8980 | else | |||||
8981 | break; | |||||
8982 | #endif | |||||
8983 | val = (int) simple_strtoul(pv, NULL((void *) 0), base); | |||||
8984 | } | |||||
8985 | ||||||
8986 | if (!strncmp(cur, "mpar:", 5)) | |||||
8987 | driver_setup.master_parity = val; | |||||
8988 | else if (!strncmp(cur, "spar:", 5)) | |||||
8989 | driver_setup.scsi_parity = val; | |||||
8990 | else if (!strncmp(cur, "disc:", 5)) | |||||
8991 | driver_setup.disconnection = val; | |||||
8992 | else if (!strncmp(cur, "specf:", 6)) | |||||
8993 | driver_setup.special_features = val; | |||||
8994 | else if (!strncmp(cur, "ultra:", 6)) | |||||
8995 | driver_setup.ultra_scsi = val; | |||||
8996 | else if (!strncmp(cur, "fsn:", 4)) | |||||
8997 | driver_setup.force_sync_nego = val; | |||||
8998 | else if (!strncmp(cur, "revprob:", 8)) | |||||
8999 | driver_setup.reverse_probe = val; | |||||
9000 | else if (!strncmp(cur, "tags:", 5)) { | |||||
9001 | if (val > SCSI_NCR_MAX_TAGS(4)) | |||||
9002 | val = SCSI_NCR_MAX_TAGS(4); | |||||
9003 | driver_setup.default_tags = val; | |||||
9004 | } | |||||
9005 | else if (!strncmp(cur, "sync:", 5)) | |||||
9006 | driver_setup.default_sync = val; | |||||
9007 | else if (!strncmp(cur, "verb:", 5)) | |||||
9008 | driver_setup.verbose = val; | |||||
9009 | else if (!strncmp(cur, "debug:", 6)) | |||||
9010 | driver_setup.debug = val; | |||||
9011 | else if (!strncmp(cur, "burst:", 6)) | |||||
9012 | driver_setup.burst_max = val; | |||||
9013 | else if (!strncmp(cur, "led:", 4)) | |||||
9014 | driver_setup.led_pin = val; | |||||
9015 | else if (!strncmp(cur, "wide:", 5)) | |||||
9016 | driver_setup.max_wide = val? 1:0; | |||||
9017 | else if (!strncmp(cur, "settle:", 7)) | |||||
9018 | driver_setup.settle_delay= val; | |||||
9019 | else if (!strncmp(cur, "diff:", 5)) | |||||
9020 | driver_setup.diff_support= val; | |||||
9021 | else if (!strncmp(cur, "irqm:", 5)) | |||||
9022 | driver_setup.irqm = val; | |||||
9023 | else if (!strncmp(cur, "pcifix:", 7)) | |||||
9024 | driver_setup.pci_fix_up = val; | |||||
9025 | else if (!strncmp(cur, "buschk:", 7)) | |||||
9026 | driver_setup.bus_check = val; | |||||
9027 | #ifdef SCSI_NCR_NVRAM_SUPPORT | |||||
9028 | else if (!strncmp(cur, "nvram:", 6)) | |||||
9029 | driver_setup.use_nvram = val; | |||||
9030 | #endif | |||||
9031 | ||||||
9032 | else if (!strncmp(cur, "safe:", 5) && val) | |||||
9033 | memcpy(&driver_setup, &driver_safe_setup, sizeof(driver_setup))(__builtin_constant_p(sizeof(driver_setup)) ? __constant_memcpy ((&driver_setup),(&driver_safe_setup),(sizeof(driver_setup ))) : __memcpy((&driver_setup),(&driver_safe_setup),( sizeof(driver_setup)))); | |||||
9034 | else | |||||
9035 | printfprintk("ncr53c8xx_setup: unexpected boot option '%.*s' ignored\n", (int)(pc-cur+1), cur); | |||||
9036 | ||||||
9037 | #ifdef MODULE | |||||
9038 | if ((cur = strchr(cur, ' ')) != NULL((void *) 0)) | |||||
9039 | #else | |||||
9040 | if ((cur = strchr(cur, ',')) != NULL((void *) 0)) | |||||
9041 | #endif | |||||
9042 | ++cur; | |||||
9043 | } | |||||
9044 | #endif /* SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT */ | |||||
9045 | } | |||||
9046 | ||||||
9047 | static int ncr53c8xx_pci_init(Scsi_Host_Template *tpnt, | |||||
9048 | ucharunsigned char bus, ucharunsigned char device_fn, ncr_device *device); | |||||
9049 | ||||||
9050 | /* | |||||
9051 | ** Linux entry point for NCR53C8XX devices detection routine. | |||||
9052 | ** | |||||
9053 | ** Called by the middle-level scsi drivers at initialization time, | |||||
9054 | ** or at module installation. | |||||
9055 | ** | |||||
9056 | ** Read the PCI configuration and try to attach each | |||||
9057 | ** detected NCR board. | |||||
9058 | ** | |||||
9059 | ** If NVRAM is present, try to attach boards according to | |||||
9060 | ** the used defined boot order. | |||||
9061 | ** | |||||
9062 | ** Returns the number of boards successfully attached. | |||||
9063 | */ | |||||
9064 | ||||||
9065 | __initfunc(static void ncr_print_driver_setup(void) | |||||
9066 | static void ncr_print_driver_setup(void)static void ncr_print_driver_setup(void) | |||||
9067 | )static void ncr_print_driver_setup(void) | |||||
9068 | { | |||||
9069 | #define YesNo(y) y ? 'y' : 'n' | |||||
9070 | printk("ncr53c8xx: setup=disc:%c,specf:%d,ultra:%c,tags:%d,sync:%d,burst:%d,wide:%c,diff:%d\n", | |||||
9071 | YesNo(driver_setup.disconnection), | |||||
9072 | driver_setup.special_features, | |||||
9073 | YesNo(driver_setup.ultra_scsi), | |||||
9074 | driver_setup.default_tags, | |||||
9075 | driver_setup.default_sync, | |||||
9076 | driver_setup.burst_max, | |||||
9077 | YesNo(driver_setup.max_wide), | |||||
9078 | driver_setup.diff_support); | |||||
9079 | printk("ncr53c8xx: setup=mpar:%c,spar:%c,fsn=%c,verb:%d,debug:0x%x,led:%c,settle:%d,irqm:%d\n", | |||||
9080 | YesNo(driver_setup.master_parity), | |||||
9081 | YesNo(driver_setup.scsi_parity), | |||||
9082 | YesNo(driver_setup.force_sync_nego), | |||||
9083 | driver_setup.verbose, | |||||
9084 | driver_setup.debug, | |||||
9085 | YesNo(driver_setup.led_pin), | |||||
9086 | driver_setup.settle_delay, | |||||
9087 | driver_setup.irqm); | |||||
9088 | #undef YesNo | |||||
9089 | } | |||||
9090 | ||||||
9091 | /* | |||||
9092 | ** NCR53C8XX devices description table and chip ids list. | |||||
9093 | */ | |||||
9094 | ||||||
9095 | static ncr_chip ncr_chip_table[] __initdata = SCSI_NCR_CHIP_TABLE{ {0x0001, 0x0f, "810", 4, 8, 4, (1<<6)} , {0x0001, 0xff , "810a", 4, 8, 4, ((1<<6)|(1<<7)|(1<<8)|(1 <<9))|(1<<13)|(1<<12)|(1<<10)} , {0x0004 , 0xff, "815", 4, 8, 4, (1<<6)|(1<<10)} , {0x0002 , 0xff, "820", 4, 8, 4, (1<<1)|(1<<6)} , {0x0003, 0x0f, "825", 4, 8, 4, (1<<1)|(1<<6)|(1<<10 )} , {0x0003, 0xff, "825a", 6, 8, 4, (1<<1)|(((1<< 6)|(1<<7)|(1<<8)|(1<<9)) & ~(1<<6 ))|(1<<10)|(1<<11)|(1<<13)|(1<<12)|(1 <<14)} , {0x0006, 0xff, "860", 4, 8, 5, (1<<2)|(1 <<15)|((1<<6)|(1<<7)|(1<<8)|(1<< 9))|(1<<10)|(1<<13)|(1<<12)} , {0x000f, 0x01 , "875", 6, 16, 5, (1<<1)|(1<<2)|(1<<15)|(( (1<<6)|(1<<7)|(1<<8)|(1<<9)) & ~( 1<<6))|(1<<10)|(1<<11)|(1<<13)|(1<< 12)|(1<<14)} , {0x000f, 0xff, "875", 6, 16, 5, (1<< 1)|(1<<2)|(1<<4)|(((1<<6)|(1<<7)|(1<< 8)|(1<<9)) & ~(1<<6))|(1<<10)|(1<< 11)|(1<<13)|(1<<12)|(1<<14)} , {0x008f,0xff , "875J", 6, 16, 5, (1<<1)|(1<<2)|(1<<4)|(( (1<<6)|(1<<7)|(1<<8)|(1<<9)) & ~( 1<<6))|(1<<10)|(1<<11)|(1<<13)|(1<< 12)|(1<<14)} , {0x000d, 0xff, "885", 6, 16, 5, (1<< 1)|(1<<2)|(1<<4)|(((1<<6)|(1<<7)|(1<< 8)|(1<<9)) & ~(1<<6))|(1<<10)|(1<< 11)|(1<<13)|(1<<12)|(1<<14)} , {0x000c, 0xff , "895", 7, 31, 7, (1<<1)|(1<<3)|(1<<5)|((1 <<6)|(1<<7)|(1<<8)|(1<<9))|(1<< 10)|(1<<11)|(1<<13)|(1<<12)|(1<<14)} , {0x000b, 0xff, "896", 7, 31, 7, (1<<1)|(1<<3)|(1 <<5)|((1<<6)|(1<<7)|(1<<8)|(1<< 9))|(1<<10)|(1<<11)|(1<<13)|(1<<12)|( 1<<14)}}; | |||||
9096 | static ushortunsigned short ncr_chip_ids[] __initdata = SCSI_NCR_CHIP_IDS{ 0x0001, 0x0004, 0x0002, 0x0003, 0x0006, 0x000f, 0x008f, 0x000d , 0x000c, 0x000b }; | |||||
9097 | ||||||
9098 | #ifdef SCSI_NCR_NVRAM_SUPPORT | |||||
9099 | __initfunc(static int ncr_attach_using_nvram(Scsi_Host_Template *tpnt, int nvram_index, int count, ncr_device device[]) | |||||
9100 | static intstatic int ncr_attach_using_nvram(Scsi_Host_Template *tpnt, int nvram_index, int count, ncr_device device[]) | |||||
9101 | ncr_attach_using_nvram(Scsi_Host_Template *tpnt, int nvram_index, int count, ncr_device device[])static int ncr_attach_using_nvram(Scsi_Host_Template *tpnt, int nvram_index, int count, ncr_device device[]) | |||||
9102 | )static int ncr_attach_using_nvram(Scsi_Host_Template *tpnt, int nvram_index, int count, ncr_device device[]) | |||||
9103 | { | |||||
9104 | int i, j; | |||||
9105 | int attach_count = 0; | |||||
9106 | ncr_nvram *nvram; | |||||
9107 | ncr_device *devp; | |||||
9108 | ||||||
9109 | if (!nvram_index) | |||||
9110 | return 0; | |||||
9111 | ||||||
9112 | /* find first Symbios NVRAM if there is one as we need to check it for host boot order */ | |||||
9113 | for (i = 0, nvram_index = -1; i < count; i++) { | |||||
9114 | devp = &device[i]; | |||||
9115 | nvram = devp->nvram; | |||||
9116 | if (!nvram) | |||||
9117 | continue; | |||||
9118 | if (nvram->type == SCSI_NCR_SYMBIOS_NVRAM(1)) { | |||||
9119 | if (nvram_index == -1) | |||||
9120 | nvram_index = i; | |||||
9121 | #ifdef SCSI_NCR_DEBUG_NVRAM | |||||
9122 | printfprintk("ncr53c8xx: NVRAM: Symbios format Boot Block, 53c%s, PCI bus %d, device %d, function %d\n", | |||||
9123 | devp->chip.name, devp->slot.bus, | |||||
9124 | (int) (devp->slot.device_fn & 0xf8) >> 3, | |||||
9125 | (int) devp->slot.device_fn & 7); | |||||
9126 | for (j = 0 ; j < 4 ; j++) { | |||||
9127 | Symbios_host *h = &nvram->data.Symbios.host[j]; | |||||
9128 | printfprintk("ncr53c8xx: BOOT[%d] device_id=%04x vendor_id=%04x device_fn=%02x io_port=%04x %s\n", | |||||
9129 | j, h->device_id, h->vendor_id, | |||||
9130 | h->device_fn, h->io_port, | |||||
9131 | (h->flags & SYMBIOS_INIT_SCAN_AT_BOOT) ? "SCAN AT BOOT" : ""); | |||||
9132 | } | |||||
9133 | } | |||||
9134 | else if (nvram->type == SCSI_NCR_TEKRAM_NVRAM(2)) { | |||||
9135 | /* display Tekram nvram data */ | |||||
9136 | printfprintk("ncr53c8xx: NVRAM: Tekram format data, 53c%s, PCI bus %d, device %d, function %d\n", | |||||
9137 | devp->chip.name, devp->slot.bus, | |||||
9138 | (int) (devp->slot.device_fn & 0xf8) >> 3, | |||||
9139 | (int) devp->slot.device_fn & 7); | |||||
9140 | #endif | |||||
9141 | } | |||||
9142 | } | |||||
9143 | ||||||
9144 | if (nvram_index >= 0 && nvram_index < count) | |||||
9145 | nvram = device[nvram_index].nvram; | |||||
9146 | else | |||||
9147 | nvram = 0; | |||||
9148 | ||||||
9149 | if (!nvram) | |||||
9150 | goto out; | |||||
9151 | ||||||
9152 | /* | |||||
9153 | ** check devices in the boot record against devices detected. | |||||
9154 | ** attach devices if we find a match. boot table records that | |||||
9155 | ** do not match any detected devices will be ignored. | |||||
9156 | ** devices that do not match any boot table will not be attached | |||||
9157 | ** here but will attempt to be attached during the device table | |||||
9158 | ** rescan. | |||||
9159 | */ | |||||
9160 | for (i = 0; i < 4; i++) { | |||||
9161 | Symbios_host *h = &nvram->data.Symbios.host[i]; | |||||
9162 | for (j = 0 ; j < count ; j++) { | |||||
9163 | devp = &device[j]; | |||||
9164 | if (h->device_fn == devp->slot.device_fn && | |||||
9165 | #if 0 /* bus number location in nvram ? */ | |||||
9166 | h->bus == devp->slot.bus && | |||||
9167 | #endif | |||||
9168 | h->device_id == devp->chip.device_id) | |||||
9169 | break; | |||||
9170 | } | |||||
9171 | if (j < count && !devp->attach_done) { | |||||
9172 | if (!ncr_attach (tpnt, attach_count, devp)) | |||||
9173 | attach_count++; | |||||
9174 | devp->attach_done = 1; | |||||
9175 | } | |||||
9176 | } | |||||
9177 | ||||||
9178 | out: | |||||
9179 | return attach_count; | |||||
9180 | } | |||||
9181 | #endif /* SCSI_NCR_NVRAM_SUPPORT */ | |||||
9182 | ||||||
9183 | __initfunc(int ncr53c8xx_detect(Scsi_Host_Template *tpnt) | |||||
9184 | int ncr53c8xx_detect(Scsi_Host_Template *tpnt)int ncr53c8xx_detect(Scsi_Host_Template *tpnt) | |||||
9185 | )int ncr53c8xx_detect(Scsi_Host_Template *tpnt) | |||||
9186 | { | |||||
9187 | int i, j; | |||||
9188 | int chips; | |||||
9189 | int count = 0; | |||||
9190 | ucharunsigned char bus, device_fn; | |||||
9191 | short index; | |||||
9192 | int attach_count = 0; | |||||
9193 | ncr_device device[8]; | |||||
9194 | #ifdef SCSI_NCR_NVRAM_SUPPORT | |||||
9195 | ncr_nvram nvram[4]; | |||||
9196 | int k, nvrams; | |||||
9197 | #endif | |||||
9198 | int hosts; | |||||
9199 | ||||||
9200 | #ifdef SCSI_NCR_NVRAM_SUPPORT | |||||
9201 | int nvram_index = 0; | |||||
9202 | #endif | |||||
9203 | if (initverbose(driver_setup.verbose) >= 2) | |||||
9204 | ncr_print_driver_setup(); | |||||
9205 | ||||||
9206 | #ifdef SCSI_NCR_DEBUG_INFO_SUPPORT | |||||
9207 | ncr_debug = driver_setup.debug; | |||||
9208 | #endif | |||||
9209 | ||||||
9210 | #if LINUX_VERSION_CODE131108 >= LinuxVersionCode(1,3,0)(((1)<<16)+((3)<<8)+(0)) | |||||
9211 | tpnt->proc_dir = &proc_scsi_ncr53c8xx; | |||||
9212 | # ifdef SCSI_NCR_PROC_INFO_SUPPORT | |||||
9213 | tpnt->proc_info = ncr53c8xx_proc_info; | |||||
9214 | # endif | |||||
9215 | #endif | |||||
9216 | ||||||
9217 | #if defined(SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT) && defined(MODULE) | |||||
9218 | if (ncr53c8xx) | |||||
9219 | ncr53c8xx_setup(ncr53c8xx, (int *) 0); | |||||
9220 | #endif | |||||
9221 | ||||||
9222 | /* | |||||
9223 | ** Detect all 53c8xx hosts and then attach them. | |||||
9224 | ** | |||||
9225 | ** If we are using NVRAM, once all hosts are detected, we need to check | |||||
9226 | ** any NVRAM for boot order in case detect and boot order differ and | |||||
9227 | ** attach them using the order in the NVRAM. | |||||
9228 | ** | |||||
9229 | ** If no NVRAM is found or data appears invalid attach boards in the | |||||
9230 | ** the order they are detected. | |||||
9231 | */ | |||||
9232 | ||||||
9233 | if (!pcibios_present()) | |||||
9234 | return 0; | |||||
9235 | ||||||
9236 | chips = sizeof(ncr_chip_ids) / sizeof(ncr_chip_ids[0]); | |||||
9237 | hosts = sizeof(device) / sizeof(device[0]); | |||||
9238 | #ifdef SCSI_NCR_NVRAM_SUPPORT | |||||
9239 | k = 0; | |||||
9240 | if (driver_setup.use_nvram & 0x1) | |||||
9241 | nvrams = sizeof(nvram) / sizeof(nvram[0]); | |||||
9242 | else | |||||
9243 | nvrams = 0; | |||||
9244 | #endif | |||||
9245 | ||||||
9246 | for (j = 0; j < chips ; ++j) { | |||||
9247 | i = driver_setup.reverse_probe ? chips-1 - j : j; | |||||
9248 | for (index = 0; ; index++) { | |||||
9249 | char *msg = ""; | |||||
9250 | if ((pcibios_find_device(PCI_VENDOR_ID_NCR0x1000, ncr_chip_ids[i], | |||||
9251 | index, &bus, &device_fn)) || | |||||
9252 | (count == hosts)) | |||||
9253 | break; | |||||
9254 | #ifdef SCSI_NCR_NVRAM_SUPPORT | |||||
9255 | device[count].nvram = k < nvrams ? &nvram[k] : 0; | |||||
9256 | #else | |||||
9257 | device[count].nvram = 0; | |||||
9258 | #endif | |||||
9259 | if (ncr53c8xx_pci_init(tpnt, bus, device_fn, &device[count])) { | |||||
9260 | device[count].nvram = 0; | |||||
9261 | continue; | |||||
9262 | } | |||||
9263 | #ifdef SCSI_NCR_NVRAM_SUPPORT | |||||
9264 | if (device[count].nvram) { | |||||
9265 | ++k; | |||||
9266 | nvram_index |= device[count].nvram->type; | |||||
9267 | switch (device[count].nvram->type) { | |||||
9268 | case SCSI_NCR_TEKRAM_NVRAM(2): | |||||
9269 | msg = "with Tekram NVRAM"; | |||||
9270 | break; | |||||
9271 | case SCSI_NCR_SYMBIOS_NVRAM(1): | |||||
9272 | msg = "with Symbios NVRAM"; | |||||
9273 | break; | |||||
9274 | default: | |||||
9275 | msg = ""; | |||||
9276 | device[count].nvram = 0; | |||||
9277 | --k; | |||||
9278 | } | |||||
9279 | } | |||||
9280 | #endif | |||||
9281 | printfprintk(KERN_INFO"<6>" "ncr53c8xx: 53c%s detected %s\n", | |||||
9282 | device[count].chip.name, msg); | |||||
9283 | ++count; | |||||
9284 | } | |||||
9285 | } | |||||
9286 | #ifdef SCSI_NCR_NVRAM_SUPPORT | |||||
9287 | attach_count = ncr_attach_using_nvram(tpnt, nvram_index, count, device); | |||||
9288 | #endif | |||||
9289 | /* | |||||
9290 | ** rescan device list to make sure all boards attached. | |||||
9291 | ** devices without boot records will not be attached yet | |||||
9292 | ** so try to attach them here. | |||||
9293 | */ | |||||
9294 | for (i= 0; i < count; i++) { | |||||
9295 | if (!device[i].attach_done && | |||||
9296 | !ncr_attach (tpnt, attach_count, &device[i])) { | |||||
9297 | attach_count++; | |||||
9298 | } | |||||
9299 | } | |||||
9300 | ||||||
9301 | return attach_count; | |||||
9302 | } | |||||
9303 | ||||||
9304 | /* | |||||
9305 | ** Read and check the PCI configuration for any detected NCR | |||||
9306 | ** boards and save data for attaching after all boards have | |||||
9307 | ** been detected. | |||||
9308 | */ | |||||
9309 | ||||||
9310 | __initfunc(static int ncr53c8xx_pci_init(Scsi_Host_Template *tpnt, unsigned char bus, unsigned char device_fn, ncr_device *device) | |||||
9311 | static int ncr53c8xx_pci_init(Scsi_Host_Template *tpnt,static int ncr53c8xx_pci_init(Scsi_Host_Template *tpnt, unsigned char bus, unsigned char device_fn, ncr_device *device) | |||||
9312 | uchar bus, uchar device_fn, ncr_device *device)static int ncr53c8xx_pci_init(Scsi_Host_Template *tpnt, unsigned char bus, unsigned char device_fn, ncr_device *device) | |||||
9313 | )static int ncr53c8xx_pci_init(Scsi_Host_Template *tpnt, unsigned char bus, unsigned char device_fn, ncr_device *device) | |||||
9314 | { | |||||
9315 | ushortunsigned short vendor_id, device_id, command; | |||||
9316 | ucharunsigned char cache_line_size, latency_timer; | |||||
9317 | ucharunsigned char irq, revision; | |||||
9318 | #if LINUX_VERSION_CODE131108 >= LinuxVersionCode(1,3,0)(((1)<<16)+((3)<<8)+(0)) | |||||
9319 | uint base, base_2, io_port; | |||||
9320 | #else | |||||
9321 | ulongunsigned long base, base_2; | |||||
9322 | #endif | |||||
9323 | int i; | |||||
9324 | ||||||
9325 | #ifdef SCSI_NCR_NVRAM_SUPPORT | |||||
9326 | ncr_nvram *nvram = device->nvram; | |||||
9327 | #endif | |||||
9328 | ncr_chip *chip; | |||||
9329 | ||||||
9330 | printk(KERN_INFO"<6>" "ncr53c8xx: at PCI bus %d, device %d, function %d\n", | |||||
9331 | bus, (int) (device_fn & 0xf8) >> 3, (int) device_fn & 7); | |||||
9332 | /* | |||||
9333 | * Read info from the PCI config space. | |||||
9334 | * pcibios_read_config_xxx() functions are assumed to be used for | |||||
9335 | * successfully detected PCI devices. | |||||
9336 | * Expecting error conditions from them is just paranoia, | |||||
9337 | * thus void cast. | |||||
9338 | */ | |||||
9339 | (void) pcibios_read_config_word(bus, device_fn, | |||||
9340 | PCI_VENDOR_ID0x00, &vendor_id); | |||||
9341 | (void) pcibios_read_config_word(bus, device_fn, | |||||
9342 | PCI_DEVICE_ID0x02, &device_id); | |||||
9343 | (void) pcibios_read_config_word(bus, device_fn, | |||||
9344 | PCI_COMMAND0x04, &command); | |||||
9345 | (void) pcibios_read_config_dword(bus, device_fn, | |||||
9346 | PCI_BASE_ADDRESS_00x10, &io_port); | |||||
9347 | (void) pcibios_read_config_dword(bus, device_fn, | |||||
9348 | PCI_BASE_ADDRESS_10x14, &base); | |||||
9349 | (void) pcibios_read_config_dword(bus, device_fn, | |||||
9350 | PCI_BASE_ADDRESS_20x18, &base_2); | |||||
9351 | (void) pcibios_read_config_byte(bus, device_fn, | |||||
9352 | PCI_CLASS_REVISION0x08,&revision); | |||||
9353 | (void) pcibios_read_config_byte(bus, device_fn, | |||||
9354 | PCI_INTERRUPT_LINE0x3c, &irq); | |||||
9355 | (void) pcibios_read_config_byte(bus, device_fn, | |||||
9356 | PCI_CACHE_LINE_SIZE0x0c, &cache_line_size); | |||||
9357 | (void) pcibios_read_config_byte(bus, device_fn, | |||||
9358 | PCI_LATENCY_TIMER0x0d, &latency_timer); | |||||
9359 | ||||||
9360 | /* | |||||
9361 | * Check if the chip is supported | |||||
9362 | */ | |||||
9363 | chip = 0; | |||||
9364 | for (i = 0; i < sizeof(ncr_chip_table)/sizeof(ncr_chip_table[0]); i++) { | |||||
9365 | if (device_id != ncr_chip_table[i].device_id) | |||||
9366 | continue; | |||||
9367 | if (revision > ncr_chip_table[i].revision_id) | |||||
9368 | continue; | |||||
9369 | chip = &device->chip; | |||||
9370 | memcpy(chip, &ncr_chip_table[i], sizeof(*chip))(__builtin_constant_p(sizeof(*chip)) ? __constant_memcpy((chip ),(&ncr_chip_table[i]),(sizeof(*chip))) : __memcpy((chip) ,(&ncr_chip_table[i]),(sizeof(*chip)))); | |||||
9371 | chip->revision_id = revision; | |||||
9372 | break; | |||||
9373 | } | |||||
9374 | if (!chip) { | |||||
9375 | printk("ncr53c8xx: not initializing, device not supported\n"); | |||||
9376 | return -1; | |||||
9377 | } | |||||
9378 | ||||||
9379 | #ifdef __powerpc__ | |||||
9380 | /* | |||||
9381 | * Severall fix-up for power/pc. | |||||
9382 | * Should not be performed by the driver. | |||||
9383 | */ | |||||
9384 | if ((command & | |||||
9385 | (PCI_COMMAND_MASTER0x4|PCI_COMMAND_IO0x1|PCI_COMMAND_MEMORY0x2)) != | |||||
9386 | (PCI_COMMAND_MASTER0x4|PCI_COMMAND_IO0x1|PCI_COMMAND_MEMORY0x2)) { | |||||
9387 | printk("ncr53c8xx : setting PCI master/io/command bit\n"); | |||||
9388 | command |= PCI_COMMAND_MASTER0x4|PCI_COMMAND_IO0x1|PCI_COMMAND_MEMORY0x2; | |||||
9389 | pcibios_write_config_word(bus, device_fn, PCI_COMMAND0x04, command); | |||||
9390 | } | |||||
9391 | if (io_port >= 0x10000000) { | |||||
9392 | io_port = (io_port & 0x00FFFFFF) | 0x01000000; | |||||
9393 | pcibios_write_config_dword(bus, device_fn, PCI_BASE_ADDRESS_00x10, io_port); | |||||
9394 | } | |||||
9395 | if (base >= 0x10000000) { | |||||
9396 | base = (base & 0x00FFFFFF) | 0x01000000; | |||||
9397 | pcibios_write_config_dword(bus, device_fn, PCI_BASE_ADDRESS_10x14, base); | |||||
9398 | } | |||||
9399 | #endif | |||||
9400 | ||||||
9401 | /* | |||||
9402 | * Check availability of IO space, memory space and master capability. | |||||
9403 | */ | |||||
9404 | if (command & PCI_COMMAND_IO0x1) { | |||||
9405 | if ((io_port & 3) != 1) { | |||||
9406 | printk("ncr53c8xx: disabling I/O mapping since base address 0 (0x%x)\n" | |||||
9407 | " bits 0..1 indicate a non-IO mapping\n", (int) io_port); | |||||
9408 | io_port = 0; | |||||
9409 | } | |||||
9410 | else | |||||
9411 | io_port &= PCI_BASE_ADDRESS_IO_MASK(~0x03); | |||||
9412 | } | |||||
9413 | else | |||||
9414 | io_port = 0; | |||||
9415 | ||||||
9416 | if (command & PCI_COMMAND_MEMORY0x2) { | |||||
9417 | if ((base & PCI_BASE_ADDRESS_SPACE0x01) != PCI_BASE_ADDRESS_SPACE_MEMORY0x00) { | |||||
9418 | printk("ncr53c8xx: disabling memory mapping since base address 1\n" | |||||
9419 | " contains a non-memory mapping\n"); | |||||
9420 | base = 0; | |||||
9421 | } | |||||
9422 | else | |||||
9423 | base &= PCI_BASE_ADDRESS_MEM_MASK(~0x0f); | |||||
9424 | } | |||||
9425 | else | |||||
9426 | base = 0; | |||||
9427 | ||||||
9428 | if (!io_port && !base) { | |||||
9429 | printk("ncr53c8xx: not initializing, both I/O and memory mappings disabled\n"); | |||||
9430 | return -1; | |||||
9431 | } | |||||
9432 | ||||||
9433 | base_2 &= PCI_BASE_ADDRESS_MEM_MASK(~0x0f); | |||||
9434 | ||||||
9435 | if (io_port && check_region (io_port, 128)) { | |||||
9436 | printk("ncr53c8xx: IO region 0x%x to 0x%x is in use\n", | |||||
9437 | (int) io_port, (int) (io_port + 127)); | |||||
9438 | return -1; | |||||
9439 | } | |||||
9440 | ||||||
9441 | if (!(command & PCI_COMMAND_MASTER0x4)) { | |||||
9442 | printk("ncr53c8xx: not initializing, BUS MASTERING was disabled\n"); | |||||
9443 | return -1; | |||||
9444 | } | |||||
9445 | ||||||
9446 | /* | |||||
9447 | * Fix some features according to driver setup. | |||||
9448 | */ | |||||
9449 | if (!(driver_setup.special_features & 1)) | |||||
9450 | chip->features &= ~FE_SPECIAL_SET(((1<<6)|(1<<7)|(1<<8)|(1<<9))|(1<< 10)|(1<<11)|(1<<13)|(1<<12)|(1<<14)); | |||||
9451 | else { | |||||
9452 | if (driver_setup.special_features & 2) | |||||
9453 | chip->features &= ~FE_WRIE(1<<8); | |||||
9454 | } | |||||
9455 | if (driver_setup.ultra_scsi < 2 && (chip->features & FE_ULTRA2(1<<3))) { | |||||
9456 | chip->features |= FE_ULTRA(1<<2); | |||||
9457 | chip->features &= ~FE_ULTRA2(1<<3); | |||||
9458 | } | |||||
9459 | if (driver_setup.ultra_scsi < 1) | |||||
9460 | chip->features &= ~FE_ULTRA(1<<2); | |||||
9461 | if (!driver_setup.max_wide) | |||||
9462 | chip->features &= ~FE_WIDE(1<<1); | |||||
9463 | ||||||
9464 | ||||||
9465 | #ifdef SCSI_NCR_PCI_FIX_UP_SUPPORT | |||||
9466 | ||||||
9467 | /* | |||||
9468 | * Try to fix up PCI config according to wished features. | |||||
9469 | */ | |||||
9470 | #if defined(__i3861) && !defined(MODULE) | |||||
9471 | if ((driver_setup.pci_fix_up & 1) && | |||||
9472 | (chip->features & FE_CLSE(1<<7)) && cache_line_size == 0) { | |||||
9473 | #if LINUX_VERSION_CODE131108 < LinuxVersionCode(2,1,75)(((2)<<16)+((1)<<8)+(75)) | |||||
9474 | extern char x86; | |||||
9475 | switch(x86) { | |||||
9476 | #else | |||||
9477 | switch(boot_cpu_data.x86) { | |||||
9478 | #endif | |||||
9479 | case 4: cache_line_size = 4; break; | |||||
9480 | case 5: cache_line_size = 8; break; | |||||
9481 | } | |||||
9482 | if (cache_line_size) | |||||
9483 | (void) pcibios_write_config_byte(bus, device_fn, | |||||
9484 | PCI_CACHE_LINE_SIZE0x0c, cache_line_size); | |||||
9485 | if (initverbose(driver_setup.verbose)) | |||||
9486 | printk("ncr53c8xx: setting PCI_CACHE_LINE_SIZE to %d (fix-up).\n", cache_line_size); | |||||
9487 | } | |||||
9488 | ||||||
9489 | if ((driver_setup.pci_fix_up & 2) && cache_line_size && | |||||
9490 | (chip->features & FE_WRIE(1<<8)) && !(command & PCI_COMMAND_INVALIDATE0x10)) { | |||||
9491 | command |= PCI_COMMAND_INVALIDATE0x10; | |||||
9492 | (void) pcibios_write_config_word(bus, device_fn, | |||||
9493 | PCI_COMMAND0x04, command); | |||||
9494 | if (initverbose(driver_setup.verbose)) | |||||
9495 | printk("ncr53c8xx: setting PCI_COMMAND_INVALIDATE bit (fix-up).\n"); | |||||
9496 | } | |||||
9497 | #endif | |||||
9498 | /* | |||||
9499 | * Fix up for old chips that support READ LINE but not CACHE LINE SIZE. | |||||
9500 | * - If CACHE LINE SIZE is unknown, set burst max to 32 bytes = 8 dwords | |||||
9501 | * and donnot enable READ LINE. | |||||
9502 | * - Otherwise set it to the CACHE LINE SIZE (power of 2 assumed). | |||||
9503 | */ | |||||
9504 | ||||||
9505 | if (!(chip->features & FE_CLSE(1<<7))) { | |||||
9506 | int burst_max = chip->burst_max; | |||||
9507 | if (cache_line_size == 0) { | |||||
9508 | chip->features &= ~FE_ERL(1<<6); | |||||
9509 | if (burst_max > 3) | |||||
9510 | burst_max = 3; | |||||
9511 | } | |||||
9512 | else { | |||||
9513 | while (cache_line_size < (1 << burst_max)) | |||||
9514 | --burst_max; | |||||
9515 | } | |||||
9516 | chip->burst_max = burst_max; | |||||
9517 | } | |||||
9518 | ||||||
9519 | /* | |||||
9520 | * Tune PCI LATENCY TIMER according to burst max length transfer. | |||||
9521 | * (latency timer >= burst length + 6, we add 10 to be quite sure) | |||||
9522 | * If current value is zero, the device has probably been configured | |||||
9523 | * for no bursting due to some broken hardware. | |||||
9524 | */ | |||||
9525 | ||||||
9526 | if (latency_timer == 0 && chip->burst_max) | |||||
9527 | printk("ncr53c8xx: PCI_LATENCY_TIMER=0, bursting should'nt be allowed.\n"); | |||||
9528 | ||||||
9529 | if ((driver_setup.pci_fix_up & 4) && chip->burst_max) { | |||||
9530 | ucharunsigned char lt = (1 << chip->burst_max) + 6 + 10; | |||||
9531 | if (latency_timer < lt) { | |||||
9532 | latency_timer = lt; | |||||
9533 | if (initverbose(driver_setup.verbose)) | |||||
9534 | printk("ncr53c8xx: setting PCI_LATENCY_TIMER to %d bus clocks (fix-up).\n", latency_timer); | |||||
9535 | (void) pcibios_write_config_byte(bus, device_fn, | |||||
9536 | PCI_LATENCY_TIMER0x0d, latency_timer); | |||||
9537 | } | |||||
9538 | } | |||||
9539 | ||||||
9540 | /* | |||||
9541 | * Fix up for recent chips that support CACHE LINE SIZE. | |||||
9542 | * If PCI config space is not OK, remove features that shall not be | |||||
9543 | * used by the chip. No need to trigger possible chip bugs. | |||||
9544 | */ | |||||
9545 | ||||||
9546 | if ((chip->features & FE_CLSE(1<<7)) && cache_line_size == 0) { | |||||
9547 | chip->features &= ~FE_CACHE_SET((1<<6)|(1<<7)|(1<<8)|(1<<9)); | |||||
9548 | printk("ncr53c8xx: PCI_CACHE_LINE_SIZE not set, features based on CACHE LINE SIZE not used.\n"); | |||||
9549 | } | |||||
9550 | ||||||
9551 | if ((chip->features & FE_WRIE(1<<8)) && !(command & PCI_COMMAND_INVALIDATE0x10)) { | |||||
9552 | chip->features &= ~FE_WRIE(1<<8); | |||||
9553 | printk("ncr53c8xx: PCI_COMMAND_INVALIDATE not set, WRITE AND INVALIDATE not used\n"); | |||||
9554 | } | |||||
9555 | ||||||
9556 | #endif /* SCSI_NCR_PCI_FIX_UP_SUPPORT */ | |||||
9557 | ||||||
9558 | /* initialise ncr_device structure with items required by ncr_attach */ | |||||
9559 | device->slot.bus = bus; | |||||
9560 | device->slot.device_fn = device_fn; | |||||
9561 | device->slot.base = base; | |||||
9562 | device->slot.base_2 = base_2; | |||||
9563 | device->slot.io_port = io_port; | |||||
9564 | device->slot.irq = irq; | |||||
9565 | device->attach_done = 0; | |||||
9566 | #ifdef SCSI_NCR_NVRAM_SUPPORT | |||||
9567 | if (!nvram) | |||||
9568 | goto out; | |||||
9569 | ||||||
9570 | /* | |||||
9571 | ** Get access to chip IO registers | |||||
9572 | */ | |||||
9573 | #ifdef NCR_IOMAPPED | |||||
9574 | request_region(io_port, 128, "ncr53c8xx"); | |||||
9575 | device->slot.port = io_port; | |||||
9576 | #else | |||||
9577 | device->slot.reg = (struct ncr_reg *) remap_pci_mem((ulongunsigned long) base, 128); | |||||
9578 | if (!device->slot.reg) | |||||
9579 | goto out; | |||||
9580 | #endif | |||||
9581 | ||||||
9582 | /* | |||||
9583 | ** Try to read SYMBIOS nvram. | |||||
9584 | ** Data can be used to order booting of boards. | |||||
9585 | ** | |||||
9586 | ** Data is saved in ncr_device structure if NVRAM found. This | |||||
9587 | ** is then used to find drive boot order for ncr_attach(). | |||||
9588 | ** | |||||
9589 | ** NVRAM data is passed to Scsi_Host_Template later during ncr_attach() | |||||
9590 | ** for any device set up. | |||||
9591 | ** | |||||
9592 | ** Try to read TEKRAM nvram if Symbios nvram not found. | |||||
9593 | */ | |||||
9594 | ||||||
9595 | if (!ncr_get_Symbios_nvram(&device->slot, &nvram->data.Symbios)) | |||||
9596 | nvram->type = SCSI_NCR_SYMBIOS_NVRAM(1); | |||||
9597 | else if (!ncr_get_Tekram_nvram(&device->slot, &nvram->data.Tekram)) | |||||
9598 | nvram->type = SCSI_NCR_TEKRAM_NVRAM(2); | |||||
9599 | else | |||||
9600 | nvram->type = 0; | |||||
9601 | out: | |||||
9602 | /* | |||||
9603 | ** Release access to chip IO registers | |||||
9604 | */ | |||||
9605 | #ifdef NCR_IOMAPPED | |||||
9606 | release_region(device->slot.port, 128); | |||||
9607 | #else | |||||
9608 | unmap_pci_mem((vm_offset_t) device->slot.reg, (u_longunsigned long) 128); | |||||
9609 | #endif | |||||
9610 | ||||||
9611 | #endif /* SCSI_NCR_NVRAM_SUPPORT */ | |||||
9612 | return 0; | |||||
9613 | } | |||||
9614 | ||||||
9615 | #if LINUX_VERSION_CODE131108 >= LinuxVersionCode(2,0,0)(((2)<<16)+((0)<<8)+(0)) | |||||
9616 | /* | |||||
9617 | ** Linux select queue depths function | |||||
9618 | */ | |||||
9619 | static void ncr53c8xx_select_queue_depths(struct Scsi_Host *host, struct scsi_device *devlist) | |||||
9620 | { | |||||
9621 | struct scsi_device *device; | |||||
9622 | ||||||
9623 | for (device = devlist; device; device = device->next) { | |||||
9624 | if (device->host == host) { | |||||
9625 | #if SCSI_NCR_MAX_TAGS(4) > 1 | |||||
9626 | if (device->tagged_supported) { | |||||
9627 | device->queue_depth = SCSI_NCR_MAX_TAGS(4); | |||||
9628 | } | |||||
9629 | else { | |||||
9630 | device->queue_depth = 2; | |||||
9631 | } | |||||
9632 | #else | |||||
9633 | device->queue_depth = 1; | |||||
9634 | #endif | |||||
9635 | ||||||
9636 | #ifdef DEBUG_NCR53C8XX | |||||
9637 | printk("ncr53c8xx_select_queue_depth: id=%d, lun=%d, queue_depth=%d\n", | |||||
9638 | device->id, device->lun, device->queue_depth); | |||||
9639 | #endif | |||||
9640 | } | |||||
9641 | } | |||||
9642 | } | |||||
9643 | #endif | |||||
9644 | ||||||
9645 | /* | |||||
9646 | ** Linux entry point of queuecommand() function | |||||
9647 | */ | |||||
9648 | ||||||
9649 | int ncr53c8xx_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) | |||||
9650 | { | |||||
9651 | int sts; | |||||
9652 | #ifdef DEBUG_NCR53C8XX | |||||
9653 | printk("ncr53c8xx_queue_command\n"); | |||||
9654 | #endif | |||||
9655 | ||||||
9656 | if ((sts = ncr_queue_command(cmd, done)) != DID_OK0x00) { | |||||
9657 | cmd->result = ScsiResult(sts, 0)(((sts) << 16) + ((0) & 0x7f)); | |||||
9658 | done(cmd); | |||||
9659 | #ifdef DEBUG_NCR53C8XX | |||||
9660 | printk("ncr53c8xx : command not queued - result=%d\n", sts); | |||||
9661 | #endif | |||||
9662 | return sts; | |||||
9663 | } | |||||
9664 | #ifdef DEBUG_NCR53C8XX | |||||
9665 | printk("ncr53c8xx : command successfully queued\n"); | |||||
9666 | #endif | |||||
9667 | return sts; | |||||
9668 | } | |||||
9669 | ||||||
9670 | /* | |||||
9671 | ** Linux entry point of the interrupt handler. | |||||
9672 | ** Fort linux versions > 1.3.70, we trust the kernel for | |||||
9673 | ** passing the internal host descriptor as 'dev_id'. | |||||
9674 | ** Otherwise, we scan the host list and call the interrupt | |||||
9675 | ** routine for each host that uses this IRQ. | |||||
9676 | */ | |||||
9677 | ||||||
9678 | #if LINUX_VERSION_CODE131108 >= LinuxVersionCode(1,3,70)(((1)<<16)+((3)<<8)+(70)) | |||||
9679 | static void ncr53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs) | |||||
9680 | { | |||||
9681 | #ifdef DEBUG_NCR53C8XX | |||||
9682 | printk("ncr53c8xx : interrupt received\n"); | |||||
9683 | #endif | |||||
9684 | ||||||
9685 | if (DEBUG_FLAGSncr_debug & DEBUG_TINY(0x0080)) printfprintk ("["); | |||||
9686 | ncr_exception((ncb_p) dev_id); | |||||
9687 | if (DEBUG_FLAGSncr_debug & DEBUG_TINY(0x0080)) printfprintk ("]\n"); | |||||
9688 | } | |||||
9689 | ||||||
9690 | #else | |||||
9691 | static void ncr53c8xx_intr(int irq, struct pt_regs * regs) | |||||
9692 | { | |||||
9693 | struct Scsi_Host *host; | |||||
9694 | struct host_data *host_data; | |||||
9695 | ||||||
9696 | for (host = first_host; host; host = host->next) { | |||||
9697 | if (host->hostt == the_template && host->irq == irq) { | |||||
9698 | host_data = (struct host_data *) host->hostdata; | |||||
9699 | if (DEBUG_FLAGSncr_debug & DEBUG_TINY(0x0080)) printfprintk ("["); | |||||
9700 | ncr_exception(host_data->ncb); | |||||
9701 | if (DEBUG_FLAGSncr_debug & DEBUG_TINY(0x0080)) printfprintk ("]\n"); | |||||
9702 | } | |||||
9703 | } | |||||
9704 | } | |||||
9705 | #endif | |||||
9706 | ||||||
9707 | /* | |||||
9708 | ** Linux entry point of the timer handler | |||||
9709 | */ | |||||
9710 | ||||||
9711 | static void ncr53c8xx_timeout(unsigned long np) | |||||
9712 | { | |||||
9713 | ncr_timeout((ncb_p) np); | |||||
9714 | } | |||||
9715 | ||||||
9716 | /* | |||||
9717 | ** Linux entry point of reset() function | |||||
9718 | */ | |||||
9719 | ||||||
9720 | #if defined SCSI_RESET_SYNCHRONOUS0x01 && defined SCSI_RESET_ASYNCHRONOUS0x02 | |||||
9721 | ||||||
9722 | int ncr53c8xx_reset(Scsi_Cmnd *cmd, unsigned int reset_flags) | |||||
9723 | { | |||||
9724 | int sts; | |||||
9725 | unsigned long flags; | |||||
9726 | ||||||
9727 | printk("ncr53c8xx_reset: pid=%lu reset_flags=%x serial_number=%ld serial_number_at_timeout=%ld\n", | |||||
9728 | cmd->pid, reset_flags, cmd->serial_number, cmd->serial_number_at_timeout); | |||||
9729 | ||||||
9730 | save_flags(flags)__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); cli()__asm__ __volatile__ ("cli": : :"memory"); | |||||
9731 | ||||||
9732 | /* | |||||
9733 | * We have to just ignore reset requests in some situations. | |||||
9734 | */ | |||||
9735 | #if defined SCSI_RESET_NOT_RUNNING5 | |||||
9736 | if (cmd->serial_number != cmd->serial_number_at_timeout) { | |||||
9737 | sts = SCSI_RESET_NOT_RUNNING5; | |||||
9738 | goto out; | |||||
9739 | } | |||||
9740 | #endif | |||||
9741 | /* | |||||
9742 | * If the mid-level driver told us reset is synchronous, it seems | |||||
9743 | * that we must call the done() callback for the involved command, | |||||
9744 | * even if this command was not queued to the low-level driver, | |||||
9745 | * before returning SCSI_RESET_SUCCESS. | |||||
9746 | */ | |||||
9747 | ||||||
9748 | sts = ncr_reset_bus(cmd, | |||||
9749 | (reset_flags & (SCSI_RESET_SYNCHRONOUS0x01 | SCSI_RESET_ASYNCHRONOUS0x02)) == SCSI_RESET_SYNCHRONOUS0x01); | |||||
9750 | /* | |||||
9751 | * Since we always reset the controller, when we return success, | |||||
9752 | * we add this information to the return code. | |||||
9753 | */ | |||||
9754 | #if defined SCSI_RESET_HOST_RESET0x200 | |||||
9755 | if (sts == SCSI_RESET_SUCCESS2) | |||||
9756 | sts |= SCSI_RESET_HOST_RESET0x200; | |||||
9757 | #endif | |||||
9758 | ||||||
9759 | out: | |||||
9760 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||||
9761 | return sts; | |||||
9762 | } | |||||
9763 | #else | |||||
9764 | int ncr53c8xx_reset(Scsi_Cmnd *cmd) | |||||
9765 | { | |||||
9766 | printk("ncr53c8xx_reset: command pid %lu\n", cmd->pid); | |||||
9767 | return ncr_reset_bus(cmd, 1); | |||||
9768 | } | |||||
9769 | #endif | |||||
9770 | ||||||
9771 | /* | |||||
9772 | ** Linux entry point of abort() function | |||||
9773 | */ | |||||
9774 | ||||||
9775 | #if defined SCSI_RESET_SYNCHRONOUS0x01 && defined SCSI_RESET_ASYNCHRONOUS0x02 | |||||
9776 | ||||||
9777 | int ncr53c8xx_abort(Scsi_Cmnd *cmd) | |||||
9778 | { | |||||
9779 | int sts; | |||||
9780 | unsigned long flags; | |||||
9781 | ||||||
9782 | printk("ncr53c8xx_abort: pid=%lu serial_number=%ld serial_number_at_timeout=%ld\n", | |||||
9783 | cmd->pid, cmd->serial_number, cmd->serial_number_at_timeout); | |||||
9784 | ||||||
9785 | save_flags(flags)__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); cli()__asm__ __volatile__ ("cli": : :"memory"); | |||||
9786 | ||||||
9787 | /* | |||||
9788 | * We have to just ignore abort requests in some situations. | |||||
9789 | */ | |||||
9790 | if (cmd->serial_number != cmd->serial_number_at_timeout) { | |||||
9791 | sts = SCSI_ABORT_NOT_RUNNING4; | |||||
9792 | goto out; | |||||
9793 | } | |||||
9794 | ||||||
9795 | sts = ncr_abort_command(cmd); | |||||
9796 | out: | |||||
9797 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||||
9798 | return sts; | |||||
9799 | } | |||||
9800 | #else | |||||
9801 | int ncr53c8xx_abort(Scsi_Cmnd *cmd) | |||||
9802 | { | |||||
9803 | printk("ncr53c8xx_abort: command pid %lu\n", cmd->pid); | |||||
9804 | return ncr_abort_command(cmd); | |||||
9805 | } | |||||
9806 | #endif | |||||
9807 | ||||||
9808 | #ifdef MODULE | |||||
9809 | int ncr53c8xx_release(struct Scsi_Host *host) | |||||
9810 | { | |||||
9811 | #ifdef DEBUG_NCR53C8XX | |||||
9812 | printk("ncr53c8xx : release\n"); | |||||
9813 | #endif | |||||
9814 | ncr_detach(((struct host_data *) host->hostdata)->ncb); | |||||
9815 | ||||||
9816 | return 1; | |||||
9817 | } | |||||
9818 | #endif | |||||
9819 | ||||||
9820 | ||||||
9821 | /* | |||||
9822 | ** Scsi command waiting list management. | |||||
9823 | ** | |||||
9824 | ** It may happen that we cannot insert a scsi command into the start queue, | |||||
9825 | ** in the following circumstances. | |||||
9826 | ** Too few preallocated ccb(s), | |||||
9827 | ** maxtags < cmd_per_lun of the Linux host control block, | |||||
9828 | ** etc... | |||||
9829 | ** Such scsi commands are inserted into a waiting list. | |||||
9830 | ** When a scsi command complete, we try to requeue the commands of the | |||||
9831 | ** waiting list. | |||||
9832 | */ | |||||
9833 | ||||||
9834 | #define next_wcmd host_scribble | |||||
9835 | ||||||
9836 | static void insert_into_waiting_list(ncb_p np, Scsi_Cmnd *cmd) | |||||
9837 | { | |||||
9838 | Scsi_Cmnd *wcmd; | |||||
9839 | ||||||
9840 | #ifdef DEBUG_WAITING_LIST | |||||
9841 | printfprintk("%s: cmd %lx inserted into waiting list\n", ncr_name(np), (u_longunsigned long) cmd); | |||||
9842 | #endif | |||||
9843 | cmd->next_wcmd = 0; | |||||
9844 | if (!(wcmd = np->waiting_list)) np->waiting_list = cmd; | |||||
9845 | else { | |||||
9846 | while ((wcmd->next_wcmd) != 0) | |||||
9847 | wcmd = (Scsi_Cmnd *) wcmd->next_wcmd; | |||||
9848 | wcmd->next_wcmd = (char *) cmd; | |||||
9849 | } | |||||
9850 | } | |||||
9851 | ||||||
9852 | static Scsi_Cmnd *retrieve_from_waiting_list(int to_remove, ncb_p np, Scsi_Cmnd *cmd) | |||||
9853 | { | |||||
9854 | Scsi_Cmnd *wcmd; | |||||
9855 | ||||||
9856 | if (!(wcmd = np->waiting_list)) return 0; | |||||
9857 | while (wcmd->next_wcmd) { | |||||
9858 | if (cmd == (Scsi_Cmnd *) wcmd->next_wcmd) { | |||||
9859 | if (to_remove) { | |||||
9860 | wcmd->next_wcmd = cmd->next_wcmd; | |||||
9861 | cmd->next_wcmd = 0; | |||||
9862 | } | |||||
9863 | #ifdef DEBUG_WAITING_LIST | |||||
9864 | printfprintk("%s: cmd %lx retrieved from waiting list\n", ncr_name(np), (u_longunsigned long) cmd); | |||||
9865 | #endif | |||||
9866 | return cmd; | |||||
9867 | } | |||||
9868 | } | |||||
9869 | return 0; | |||||
9870 | } | |||||
9871 | ||||||
9872 | static void process_waiting_list(ncb_p np, int sts) | |||||
9873 | { | |||||
9874 | Scsi_Cmnd *waiting_list, *wcmd; | |||||
9875 | ||||||
9876 | waiting_list = np->waiting_list; | |||||
9877 | np->waiting_list = 0; | |||||
9878 | ||||||
9879 | #ifdef DEBUG_WAITING_LIST | |||||
9880 | if (waiting_list) printfprintk("%s: waiting_list=%lx processing sts=%d\n", ncr_name(np), (u_longunsigned long) waiting_list, sts); | |||||
9881 | #endif | |||||
9882 | while ((wcmd = waiting_list) != 0) { | |||||
9883 | waiting_list = (Scsi_Cmnd *) wcmd->next_wcmd; | |||||
9884 | wcmd->next_wcmd = 0; | |||||
9885 | if (sts == DID_OK0x00) { | |||||
9886 | #ifdef DEBUG_WAITING_LIST | |||||
9887 | printfprintk("%s: cmd %lx trying to requeue\n", ncr_name(np), (u_longunsigned long) wcmd); | |||||
9888 | #endif | |||||
9889 | sts = ncr_queue_command(wcmd, wcmd->scsi_done); | |||||
9890 | } | |||||
9891 | if (sts != DID_OK0x00) { | |||||
9892 | #ifdef DEBUG_WAITING_LIST | |||||
9893 | printfprintk("%s: cmd %lx done forced sts=%d\n", ncr_name(np), (u_longunsigned long) wcmd, sts); | |||||
9894 | #endif | |||||
9895 | wcmd->result = ScsiResult(sts, 0)(((sts) << 16) + ((0) & 0x7f)); | |||||
9896 | wcmd->scsi_done(wcmd); | |||||
9897 | } | |||||
9898 | } | |||||
9899 | } | |||||
9900 | ||||||
9901 | #undef next_wcmd | |||||
9902 | ||||||
9903 | /* | |||||
9904 | ** Returns data transfer direction for common op-codes. | |||||
9905 | */ | |||||
9906 | ||||||
9907 | static int guess_xfer_direction(int opcode) | |||||
9908 | { | |||||
9909 | int d; | |||||
9910 | ||||||
9911 | switch(opcode) { | |||||
9912 | case 0x12: /* INQUIRY 12 */ | |||||
9913 | case 0x4D: /* LOG SENSE 4D */ | |||||
9914 | case 0x5A: /* MODE SENSE(10) 5A */ | |||||
9915 | case 0x1A: /* MODE SENSE(6) 1A */ | |||||
9916 | case 0x3C: /* READ BUFFER 3C */ | |||||
9917 | case 0x1C: /* RECEIVE DIAGNOSTIC RESULTS 1C */ | |||||
9918 | case 0x03: /* REQUEST SENSE 03 */ | |||||
9919 | d = XferIn1; | |||||
9920 | break; | |||||
9921 | case 0x39: /* COMPARE 39 */ | |||||
9922 | case 0x3A: /* COPY AND VERIFY 3A */ | |||||
9923 | case 0x18: /* COPY 18 */ | |||||
9924 | case 0x4C: /* LOG SELECT 4C */ | |||||
9925 | case 0x55: /* MODE SELECT(10) 55 */ | |||||
9926 | case 0x3B: /* WRITE BUFFER 3B */ | |||||
9927 | case 0x1D: /* SEND DIAGNOSTIC 1D */ | |||||
9928 | case 0x40: /* CHANGE DEFINITION 40 */ | |||||
9929 | case 0x15: /* MODE SELECT(6) 15 */ | |||||
9930 | d = XferOut2; | |||||
9931 | break; | |||||
9932 | case 0x00: /* TEST UNIT READY 00 */ | |||||
9933 | d = XferNone0; | |||||
9934 | break; | |||||
9935 | default: | |||||
9936 | d = XferBoth3; | |||||
9937 | break; | |||||
9938 | } | |||||
9939 | ||||||
9940 | return d; | |||||
9941 | } | |||||
9942 | ||||||
9943 | ||||||
9944 | #ifdef SCSI_NCR_PROC_INFO_SUPPORT | |||||
9945 | ||||||
9946 | /*========================================================================= | |||||
9947 | ** Proc file system stuff | |||||
9948 | ** | |||||
9949 | ** A read operation returns profile information. | |||||
9950 | ** A write operation is a control command. | |||||
9951 | ** The string is parsed in the driver code and the command is passed | |||||
9952 | ** to the ncr_usercmd() function. | |||||
9953 | **========================================================================= | |||||
9954 | */ | |||||
9955 | ||||||
9956 | #ifdef SCSI_NCR_USER_COMMAND_SUPPORT | |||||
9957 | ||||||
9958 | #define is_digit(c) ((c) >= '0' && (c) <= '9') | |||||
9959 | #define digit_to_bin(c) ((c) - '0') | |||||
9960 | #define is_space(c) ((c) == ' ' || (c) == '\t') | |||||
9961 | ||||||
9962 | static int skip_spaces(char *ptr, int len) | |||||
9963 | { | |||||
9964 | int cnt, c; | |||||
9965 | ||||||
9966 | for (cnt = len; cnt > 0 && (c = *ptr++) && is_space(c); cnt--); | |||||
9967 | ||||||
9968 | return (len - cnt); | |||||
9969 | } | |||||
9970 | ||||||
9971 | static int get_int_arg(char *ptr, int len, u_longunsigned long *pv) | |||||
9972 | { | |||||
9973 | int cnt, c; | |||||
9974 | u_longunsigned long v; | |||||
9975 | ||||||
9976 | for (v = 0, cnt = len; cnt > 0 && (c = *ptr++) && is_digit(c); cnt--) { | |||||
9977 | v = (v * 10) + digit_to_bin(c); | |||||
9978 | } | |||||
9979 | ||||||
9980 | if (pv) | |||||
9981 | *pv = v; | |||||
9982 | ||||||
9983 | return (len - cnt); | |||||
9984 | } | |||||
9985 | ||||||
9986 | static int is_keyword(char *ptr, int len, char *verb) | |||||
9987 | { | |||||
9988 | int verb_len = strlen(verb); | |||||
9989 | ||||||
9990 | if (len >= strlen(verb) && !memcmp__builtin_memcmp(verb, ptr, verb_len)) | |||||
9991 | return verb_len; | |||||
9992 | else | |||||
9993 | return 0; | |||||
9994 | ||||||
9995 | } | |||||
9996 | ||||||
9997 | #define SKIP_SPACES(min_spaces) \ | |||||
9998 | if ((arg_len = skip_spaces(ptr, len)) < (min_spaces)) \ | |||||
9999 | return -EINVAL22; \ | |||||
10000 | ptr += arg_len; len -= arg_len; | |||||
10001 | ||||||
10002 | #define GET_INT_ARG(v) \ | |||||
10003 | if (!(arg_len = get_int_arg(ptr, len, &(v)))) \ | |||||
10004 | return -EINVAL22; \ | |||||
10005 | ptr += arg_len; len -= arg_len; | |||||
10006 | ||||||
10007 | ||||||
10008 | /* | |||||
10009 | ** Parse a control command | |||||
10010 | */ | |||||
10011 | ||||||
10012 | static int ncr_user_command(ncb_p np, char *buffer, int length) | |||||
10013 | { | |||||
10014 | char *ptr = buffer; | |||||
10015 | int len = length; | |||||
10016 | struct usrcmd *uc = &np->user; | |||||
10017 | int arg_len; | |||||
10018 | u_longunsigned long target; | |||||
10019 | ||||||
10020 | bzero(uc, sizeof(*uc))(__builtin_constant_p(0) ? (__builtin_constant_p(((sizeof(*uc )))) ? __constant_c_and_count_memset((((uc))),((0x01010101UL* (unsigned char)(0))),(((sizeof(*uc))))) : __constant_c_memset ((((uc))),((0x01010101UL*(unsigned char)(0))),(((sizeof(*uc)) )))) : (__builtin_constant_p(((sizeof(*uc)))) ? __memset_generic (((((uc)))),(((0))),((((sizeof(*uc)))))) : __memset_generic(( ((uc))),((0)),(((sizeof(*uc))))))); | |||||
10021 | ||||||
10022 | if (len > 0 && ptr[len-1] == '\n') | |||||
10023 | --len; | |||||
10024 | ||||||
10025 | if ((arg_len = is_keyword(ptr, len, "setsync")) != 0) | |||||
10026 | uc->cmd = UC_SETSYNC10; | |||||
10027 | else if ((arg_len = is_keyword(ptr, len, "settags")) != 0) | |||||
10028 | uc->cmd = UC_SETTAGS11; | |||||
10029 | else if ((arg_len = is_keyword(ptr, len, "setorder")) != 0) | |||||
10030 | uc->cmd = UC_SETORDER13; | |||||
10031 | else if ((arg_len = is_keyword(ptr, len, "setwide")) != 0) | |||||
10032 | uc->cmd = UC_SETWIDE14; | |||||
10033 | else if ((arg_len = is_keyword(ptr, len, "setdebug")) != 0) | |||||
10034 | uc->cmd = UC_SETDEBUG12; | |||||
10035 | else if ((arg_len = is_keyword(ptr, len, "setflag")) != 0) | |||||
10036 | uc->cmd = UC_SETFLAG15; | |||||
10037 | else if ((arg_len = is_keyword(ptr, len, "clearprof")) != 0) | |||||
10038 | uc->cmd = UC_CLEARPROF16; | |||||
10039 | #ifdef UC_DEBUG_ERROR_RECOVERY | |||||
10040 | else if ((arg_len = is_keyword(ptr, len, "debug_error_recovery")) != 0) | |||||
10041 | uc->cmd = UC_DEBUG_ERROR_RECOVERY; | |||||
10042 | #endif | |||||
10043 | else | |||||
10044 | arg_len = 0; | |||||
10045 | ||||||
10046 | #ifdef DEBUG_PROC_INFO | |||||
10047 | printfprintk("ncr_user_command: arg_len=%d, cmd=%ld\n", arg_len, uc->cmd); | |||||
10048 | #endif | |||||
10049 | ||||||
10050 | if (!arg_len) | |||||
10051 | return -EINVAL22; | |||||
10052 | ptr += arg_len; len -= arg_len; | |||||
10053 | ||||||
10054 | switch(uc->cmd) { | |||||
10055 | case UC_SETSYNC10: | |||||
10056 | case UC_SETTAGS11: | |||||
10057 | case UC_SETWIDE14: | |||||
10058 | case UC_SETFLAG15: | |||||
10059 | SKIP_SPACES(1); | |||||
10060 | if ((arg_len = is_keyword(ptr, len, "all")) != 0) { | |||||
10061 | ptr += arg_len; len -= arg_len; | |||||
10062 | uc->target = ~0; | |||||
10063 | } else { | |||||
10064 | GET_INT_ARG(target); | |||||
10065 | uc->target = (1<<target); | |||||
10066 | #ifdef DEBUG_PROC_INFO | |||||
10067 | printfprintk("ncr_user_command: target=%ld\n", target); | |||||
10068 | #endif | |||||
10069 | } | |||||
10070 | break; | |||||
10071 | } | |||||
10072 | ||||||
10073 | switch(uc->cmd) { | |||||
10074 | case UC_SETSYNC10: | |||||
10075 | case UC_SETTAGS11: | |||||
10076 | case UC_SETWIDE14: | |||||
10077 | SKIP_SPACES(1); | |||||
10078 | GET_INT_ARG(uc->data); | |||||
10079 | #ifdef DEBUG_PROC_INFO | |||||
10080 | printfprintk("ncr_user_command: data=%ld\n", uc->data); | |||||
10081 | #endif | |||||
10082 | break; | |||||
10083 | case UC_SETORDER13: | |||||
10084 | SKIP_SPACES(1); | |||||
10085 | if ((arg_len = is_keyword(ptr, len, "simple"))) | |||||
10086 | uc->data = M_SIMPLE_TAG(0x20); | |||||
10087 | else if ((arg_len = is_keyword(ptr, len, "ordered"))) | |||||
10088 | uc->data = M_ORDERED_TAG(0x22); | |||||
10089 | else if ((arg_len = is_keyword(ptr, len, "default"))) | |||||
10090 | uc->data = 0; | |||||
10091 | else | |||||
10092 | return -EINVAL22; | |||||
10093 | break; | |||||
10094 | case UC_SETDEBUG12: | |||||
10095 | while (len > 0) { | |||||
10096 | SKIP_SPACES(1); | |||||
10097 | if ((arg_len = is_keyword(ptr, len, "alloc"))) | |||||
10098 | uc->data |= DEBUG_ALLOC(0x0001); | |||||
10099 | else if ((arg_len = is_keyword(ptr, len, "phase"))) | |||||
10100 | uc->data |= DEBUG_PHASE(0x0002); | |||||
10101 | else if ((arg_len = is_keyword(ptr, len, "poll"))) | |||||
10102 | uc->data |= DEBUG_POLL(0x0004); | |||||
10103 | else if ((arg_len = is_keyword(ptr, len, "queue"))) | |||||
10104 | uc->data |= DEBUG_QUEUE(0x0008); | |||||
10105 | else if ((arg_len = is_keyword(ptr, len, "result"))) | |||||
10106 | uc->data |= DEBUG_RESULT(0x0010); | |||||
10107 | else if ((arg_len = is_keyword(ptr, len, "scatter"))) | |||||
10108 | uc->data |= DEBUG_SCATTER(0x0020); | |||||
10109 | else if ((arg_len = is_keyword(ptr, len, "script"))) | |||||
10110 | uc->data |= DEBUG_SCRIPT(0x0040); | |||||
10111 | else if ((arg_len = is_keyword(ptr, len, "tiny"))) | |||||
10112 | uc->data |= DEBUG_TINY(0x0080); | |||||
10113 | else if ((arg_len = is_keyword(ptr, len, "timing"))) | |||||
10114 | uc->data |= DEBUG_TIMING(0x0100); | |||||
10115 | else if ((arg_len = is_keyword(ptr, len, "nego"))) | |||||
10116 | uc->data |= DEBUG_NEGO(0x0200); | |||||
10117 | else if ((arg_len = is_keyword(ptr, len, "tags"))) | |||||
10118 | uc->data |= DEBUG_TAGS(0x0400); | |||||
10119 | else if ((arg_len = is_keyword(ptr, len, "freeze"))) | |||||
10120 | uc->data |= DEBUG_FREEZE(0x0800); | |||||
10121 | else if ((arg_len = is_keyword(ptr, len, "restart"))) | |||||
10122 | uc->data |= DEBUG_RESTART(0x1000); | |||||
10123 | else | |||||
10124 | return -EINVAL22; | |||||
10125 | ptr += arg_len; len -= arg_len; | |||||
10126 | } | |||||
10127 | #ifdef DEBUG_PROC_INFO | |||||
10128 | printfprintk("ncr_user_command: data=%ld\n", uc->data); | |||||
10129 | #endif | |||||
10130 | break; | |||||
10131 | case UC_SETFLAG15: | |||||
10132 | while (len > 0) { | |||||
10133 | SKIP_SPACES(1); | |||||
10134 | if ((arg_len = is_keyword(ptr, len, "trace"))) | |||||
10135 | uc->data |= UF_TRACE(0x01); | |||||
10136 | else if ((arg_len = is_keyword(ptr, len, "no_disc"))) | |||||
10137 | uc->data |= UF_NODISC(0x02); | |||||
10138 | else | |||||
10139 | return -EINVAL22; | |||||
10140 | ptr += arg_len; len -= arg_len; | |||||
10141 | } | |||||
10142 | break; | |||||
10143 | #ifdef UC_DEBUG_ERROR_RECOVERY | |||||
10144 | case UC_DEBUG_ERROR_RECOVERY: | |||||
10145 | SKIP_SPACES(1); | |||||
10146 | if ((arg_len = is_keyword(ptr, len, "sge"))) | |||||
10147 | uc->data = 1; | |||||
10148 | else if ((arg_len = is_keyword(ptr, len, "abort"))) | |||||
10149 | uc->data = 2; | |||||
10150 | else if ((arg_len = is_keyword(ptr, len, "reset"))) | |||||
10151 | uc->data = 3; | |||||
10152 | else if ((arg_len = is_keyword(ptr, len, "parity"))) | |||||
10153 | uc->data = 4; | |||||
10154 | else if ((arg_len = is_keyword(ptr, len, "none"))) | |||||
10155 | uc->data = 0; | |||||
10156 | else | |||||
10157 | return -EINVAL22; | |||||
10158 | ptr += arg_len; len -= arg_len; | |||||
10159 | break; | |||||
10160 | #endif | |||||
10161 | default: | |||||
10162 | break; | |||||
10163 | } | |||||
10164 | ||||||
10165 | if (len) | |||||
10166 | return -EINVAL22; | |||||
10167 | else { | |||||
10168 | long flags; | |||||
10169 | ||||||
10170 | save_flags(flags)__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); cli()__asm__ __volatile__ ("cli": : :"memory"); | |||||
10171 | ncr_usercmd (np); | |||||
10172 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); | |||||
10173 | } | |||||
10174 | return length; | |||||
10175 | } | |||||
10176 | ||||||
10177 | #endif /* SCSI_NCR_USER_COMMAND_SUPPORT */ | |||||
10178 | ||||||
10179 | #ifdef SCSI_NCR_USER_INFO_SUPPORT | |||||
10180 | ||||||
10181 | struct info_str | |||||
10182 | { | |||||
10183 | char *buffer; | |||||
10184 | int length; | |||||
10185 | int offset; | |||||
10186 | int pos; | |||||
10187 | }; | |||||
10188 | ||||||
10189 | static void copy_mem_info(struct info_str *info, char *data, int len) | |||||
10190 | { | |||||
10191 | if (info->pos + len > info->length) | |||||
10192 | len = info->length - info->pos; | |||||
10193 | ||||||
10194 | if (info->pos + len < info->offset) { | |||||
10195 | info->pos += len; | |||||
10196 | return; | |||||
10197 | } | |||||
10198 | if (info->pos < info->offset) { | |||||
10199 | data += (info->offset - info->pos); | |||||
10200 | len -= (info->offset - info->pos); | |||||
10201 | } | |||||
10202 | ||||||
10203 | if (len > 0) { | |||||
10204 | memcpy(info->buffer + info->pos, data, len)(__builtin_constant_p(len) ? __constant_memcpy((info->buffer + info->pos),(data),(len)) : __memcpy((info->buffer + info ->pos),(data),(len))); | |||||
10205 | info->pos += len; | |||||
10206 | } | |||||
10207 | } | |||||
10208 | ||||||
10209 | static int copy_info(struct info_str *info, char *fmt, ...) | |||||
10210 | { | |||||
10211 | va_list args; | |||||
10212 | char buf[81]; | |||||
10213 | int len; | |||||
10214 | ||||||
10215 | va_start(args, fmt)__builtin_va_start(args,fmt); | |||||
10216 | len = vsprintflinux_vsprintf(buf, fmt, args); | |||||
10217 | va_end(args)__builtin_va_end(args); | |||||
10218 | ||||||
10219 | copy_mem_info(info, buf, len); | |||||
10220 | return len; | |||||
10221 | } | |||||
10222 | ||||||
10223 | /* | |||||
10224 | ** Copy formatted profile information into the input buffer. | |||||
10225 | */ | |||||
10226 | ||||||
10227 | #define to_ms(t) ((t) * 1000 / HZ100) | |||||
10228 | ||||||
10229 | static int ncr_host_info(ncb_p np, char *ptr, off_t offset, int len) | |||||
10230 | { | |||||
10231 | struct info_str info; | |||||
10232 | ||||||
10233 | info.buffer = ptr; | |||||
10234 | info.length = len; | |||||
10235 | info.offset = offset; | |||||
10236 | info.pos = 0; | |||||
10237 | ||||||
10238 | copy_info(&info, "General information:\n"); | |||||
10239 | copy_info(&info, " Chip NCR53C%s, ", np->chip_name); | |||||
10240 | copy_info(&info, "device id 0x%x, ", np->device_id); | |||||
10241 | copy_info(&info, "revision id 0x%x\n", np->revision_id); | |||||
10242 | ||||||
10243 | copy_info(&info, " IO port address 0x%lx, ", (u_longunsigned long) np->port); | |||||
10244 | copy_info(&info, "IRQ number %d\n", (int) np->irq); | |||||
10245 | ||||||
10246 | #ifndef NCR_IOMAPPED | |||||
10247 | if (np->reg) | |||||
10248 | copy_info(&info, " Using memory mapped IO at virtual address 0x%lx\n", | |||||
10249 | (u_longunsigned long) np->reg); | |||||
10250 | #endif | |||||
10251 | copy_info(&info, " Synchronous period factor %d, ", (int) np->minsync); | |||||
10252 | copy_info(&info, "max commands per lun %d\n", SCSI_NCR_MAX_TAGS(4)); | |||||
10253 | ||||||
10254 | if (driver_setup.debug || driver_setup.verbose > 1) { | |||||
10255 | copy_info(&info, " Debug flags 0x%x, ", driver_setup.debug); | |||||
10256 | copy_info(&info, "verbosity level %d\n", driver_setup.verbose); | |||||
10257 | } | |||||
10258 | ||||||
10259 | #ifdef SCSI_NCR_PROFILE_SUPPORT | |||||
10260 | copy_info(&info, "Profiling information:\n"); | |||||
10261 | copy_info(&info, " %-12s = %lu\n", "num_trans",np->profile.num_trans); | |||||
10262 | copy_info(&info, " %-12s = %lu\n", "num_kbytes",np->profile.num_kbytes); | |||||
10263 | copy_info(&info, " %-12s = %lu\n", "num_disc", np->profile.num_disc); | |||||
10264 | copy_info(&info, " %-12s = %lu\n", "num_break",np->profile.num_break); | |||||
10265 | copy_info(&info, " %-12s = %lu\n", "num_int", np->profile.num_int); | |||||
10266 | copy_info(&info, " %-12s = %lu\n", "num_fly", np->profile.num_fly); | |||||
10267 | copy_info(&info, " %-12s = %lu\n", "ms_setup", to_ms(np->profile.ms_setup)); | |||||
10268 | copy_info(&info, " %-12s = %lu\n", "ms_data", to_ms(np->profile.ms_data)); | |||||
10269 | copy_info(&info, " %-12s = %lu\n", "ms_disc", to_ms(np->profile.ms_disc)); | |||||
10270 | copy_info(&info, " %-12s = %lu\n", "ms_post", to_ms(np->profile.ms_post)); | |||||
10271 | #endif | |||||
10272 | ||||||
10273 | return info.pos > info.offset? info.pos - info.offset : 0; | |||||
10274 | } | |||||
10275 | ||||||
10276 | #endif /* SCSI_NCR_USER_INFO_SUPPORT */ | |||||
10277 | ||||||
10278 | /* | |||||
10279 | ** Entry point of the scsi proc fs of the driver. | |||||
10280 | ** - func = 0 means read (returns profile data) | |||||
10281 | ** - func = 1 means write (parse user control command) | |||||
10282 | */ | |||||
10283 | ||||||
10284 | int ncr53c8xx_proc_info(char *buffer, char **start, off_t offset, | |||||
10285 | int length, int hostno, int func) | |||||
10286 | { | |||||
10287 | struct Scsi_Host *host; | |||||
10288 | struct host_data *host_data; | |||||
10289 | ncb_p ncb = 0; | |||||
10290 | int retv; | |||||
10291 | ||||||
10292 | #ifdef DEBUG_PROC_INFO | |||||
10293 | printfprintk("ncr53c8xx_proc_info: hostno=%d, func=%d\n", hostno, func); | |||||
10294 | #endif | |||||
10295 | ||||||
10296 | for (host = first_host; host; host = host->next) { | |||||
10297 | if (host->hostt == the_template && host->host_no == hostno) { | |||||
10298 | host_data = (struct host_data *) host->hostdata; | |||||
10299 | ncb = host_data->ncb; | |||||
10300 | break; | |||||
10301 | } | |||||
10302 | } | |||||
10303 | ||||||
10304 | if (!ncb) | |||||
10305 | return -EINVAL22; | |||||
10306 | ||||||
10307 | if (func) { | |||||
10308 | #ifdef SCSI_NCR_USER_COMMAND_SUPPORT | |||||
10309 | retv = ncr_user_command(ncb, buffer, length); | |||||
10310 | #else | |||||
10311 | retv = -EINVAL22; | |||||
10312 | #endif | |||||
10313 | } | |||||
10314 | else { | |||||
10315 | if (start) | |||||
10316 | *start = buffer; | |||||
10317 | #ifdef SCSI_NCR_USER_INFO_SUPPORT | |||||
10318 | retv = ncr_host_info(ncb, buffer, offset, length); | |||||
10319 | #else | |||||
10320 | retv = -EINVAL22; | |||||
10321 | #endif | |||||
10322 | } | |||||
10323 | ||||||
10324 | return retv; | |||||
10325 | } | |||||
10326 | ||||||
10327 | ||||||
10328 | /*========================================================================= | |||||
10329 | ** End of proc file system stuff | |||||
10330 | **========================================================================= | |||||
10331 | */ | |||||
10332 | #endif | |||||
10333 | ||||||
10334 | ||||||
10335 | #ifdef SCSI_NCR_NVRAM_SUPPORT | |||||
10336 | ||||||
10337 | /* --------------------------------------------------------------------- | |||||
10338 | ** | |||||
10339 | ** Try reading Symbios format nvram | |||||
10340 | ** | |||||
10341 | ** --------------------------------------------------------------------- | |||||
10342 | ** | |||||
10343 | ** GPOI0 - data in/data out | |||||
10344 | ** GPIO1 - clock | |||||
10345 | ** | |||||
10346 | ** return 0 if NVRAM data OK, 1 if NVRAM data not OK | |||||
10347 | ** --------------------------------------------------------------------- | |||||
10348 | */ | |||||
10349 | ||||||
10350 | #define SET_BIT 0 | |||||
10351 | #define CLR_BIT 1 | |||||
10352 | #define SET_CLK 2 | |||||
10353 | #define CLR_CLK 3 | |||||
10354 | ||||||
10355 | static u_shortunsigned short nvram_read_data(ncr_slot *np, u_charunsigned char *data, int len, u_charunsigned char *gpreg, u_charunsigned char *gpcntl); | |||||
10356 | static void nvram_start(ncr_slot *np, u_charunsigned char *gpreg); | |||||
10357 | static void nvram_write_byte(ncr_slot *np, u_charunsigned char *ack_data, u_charunsigned char write_data, u_charunsigned char *gpreg, u_charunsigned char *gpcntl); | |||||
10358 | static void nvram_read_byte(ncr_slot *np, u_charunsigned char *read_data, u_charunsigned char ack_data, u_charunsigned char *gpreg, u_charunsigned char *gpcntl); | |||||
10359 | static void nvram_readAck(ncr_slot *np, u_charunsigned char *read_bit, u_charunsigned char *gpreg, u_charunsigned char *gpcntl); | |||||
10360 | static void nvram_writeAck(ncr_slot *np, u_charunsigned char write_bit, u_charunsigned char *gpreg, u_charunsigned char *gpcntl); | |||||
10361 | static void nvram_doBit(ncr_slot *np, u_charunsigned char *read_bit, u_charunsigned char write_bit, u_charunsigned char *gpreg); | |||||
10362 | static void nvram_stop(ncr_slot *np, u_charunsigned char *gpreg); | |||||
10363 | static void nvram_setBit(ncr_slot *np, u_charunsigned char write_bit, u_charunsigned char *gpreg, int bit_mode); | |||||
10364 | ||||||
10365 | __initfunc(static int ncr_get_Symbios_nvram (ncr_slot *np, Symbios_nvram *nvram) | |||||
10366 | static int ncr_get_Symbios_nvram (ncr_slot *np, Symbios_nvram *nvram)static int ncr_get_Symbios_nvram (ncr_slot *np, Symbios_nvram *nvram) | |||||
10367 | )static int ncr_get_Symbios_nvram (ncr_slot *np, Symbios_nvram *nvram) | |||||
10368 | { | |||||
10369 | static u_charunsigned char Symbios_trailer[6] = {0xfe, 0xfe, 0, 0, 0, 0}; | |||||
10370 | u_charunsigned char gpcntl, gpreg; | |||||
10371 | u_charunsigned char old_gpcntl, old_gpreg; | |||||
10372 | u_shortunsigned short csum; | |||||
10373 | u_charunsigned char ack_data; | |||||
10374 | int retv = 1; | |||||
10375 | ||||||
10376 | /* save current state of GPCNTL and GPREG */ | |||||
10377 | old_gpreg = INB (nc_gpreg)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_gpreg))))); | |||||
10378 | old_gpcntl = INB (nc_gpcntl)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_gpcntl))))); | |||||
10379 | gpcntl = old_gpcntl & 0xfc; | |||||
10380 | ||||||
10381 | /* set up GPREG & GPCNTL to set GPIO0 and GPIO1 in to known state */ | |||||
10382 | OUTB (nc_gpreg, old_gpreg)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_gpreg))))) = (((old_gpreg )))); | |||||
10383 | OUTB (nc_gpcntl, gpcntl)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_gpcntl))))) = (((gpcntl) ))); | |||||
10384 | ||||||
10385 | /* this is to set NVRAM into a known state with GPIO0/1 both low */ | |||||
10386 | gpreg = old_gpreg; | |||||
10387 | nvram_setBit(np, 0, &gpreg, CLR_CLK); | |||||
10388 | nvram_setBit(np, 0, &gpreg, CLR_BIT); | |||||
10389 | ||||||
10390 | /* now set NVRAM inactive with GPIO0/1 both high */ | |||||
10391 | nvram_stop(np, &gpreg); | |||||
10392 | ||||||
10393 | /* activate NVRAM */ | |||||
10394 | nvram_start(np, &gpreg); | |||||
10395 | ||||||
10396 | /* write device code and random address MSB */ | |||||
10397 | nvram_write_byte(np, &ack_data, | |||||
10398 | 0xa0 | ((SYMBIOS_NVRAM_ADDRESS >> 7) & 0x0e), &gpreg, &gpcntl); | |||||
10399 | if (ack_data & 0x01) | |||||
10400 | goto out; | |||||
10401 | ||||||
10402 | /* write random address LSB */ | |||||
10403 | nvram_write_byte(np, &ack_data, | |||||
10404 | (SYMBIOS_NVRAM_ADDRESS & 0x7f) << 1, &gpreg, &gpcntl); | |||||
10405 | if (ack_data & 0x01) | |||||
10406 | goto out; | |||||
10407 | ||||||
10408 | /* regenerate START state to set up for reading */ | |||||
10409 | nvram_start(np, &gpreg); | |||||
10410 | ||||||
10411 | /* rewrite device code and address MSB with read bit set (lsb = 0x01) */ | |||||
10412 | nvram_write_byte(np, &ack_data, | |||||
10413 | 0xa1 | ((SYMBIOS_NVRAM_ADDRESS >> 7) & 0x0e), &gpreg, &gpcntl); | |||||
10414 | if (ack_data & 0x01) | |||||
10415 | goto out; | |||||
10416 | ||||||
10417 | /* now set up GPIO0 for inputting data */ | |||||
10418 | gpcntl |= 0x01; | |||||
10419 | OUTB (nc_gpcntl, gpcntl)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_gpcntl))))) = (((gpcntl) ))); | |||||
10420 | ||||||
10421 | /* input all active data - only part of total NVRAM */ | |||||
10422 | csum = nvram_read_data(np, | |||||
10423 | (u_charunsigned char *) nvram, sizeof(*nvram), &gpreg, &gpcntl); | |||||
10424 | ||||||
10425 | /* finally put NVRAM back in inactive mode */ | |||||
10426 | gpcntl &= 0xfe; | |||||
10427 | OUTB (nc_gpcntl, gpcntl)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_gpcntl))))) = (((gpcntl) ))); | |||||
10428 | nvram_stop(np, &gpreg); | |||||
10429 | ||||||
10430 | #ifdef SCSI_NCR_DEBUG_NVRAM | |||||
10431 | printfprintk("ncr53c8xx: NvRAM marker=%x trailer=%x %x %x %x %x %x byte_count=%d/%d checksum=%x/%x\n", | |||||
10432 | nvram->start_marker, | |||||
10433 | nvram->trailer[0], nvram->trailer[1], nvram->trailer[2], | |||||
10434 | nvram->trailer[3], nvram->trailer[4], nvram->trailer[5], | |||||
10435 | nvram->byte_count, sizeof(*nvram) - 12, | |||||
10436 | nvram->checksum, csum); | |||||
10437 | #endif | |||||
10438 | ||||||
10439 | /* check valid NVRAM signature, verify byte count and checksum */ | |||||
10440 | if (nvram->start_marker == 0 && | |||||
10441 | !memcmp__builtin_memcmp(nvram->trailer, Symbios_trailer, 6) && | |||||
10442 | nvram->byte_count == sizeof(*nvram) - 12 && | |||||
10443 | csum == nvram->checksum) | |||||
10444 | retv = 0; | |||||
10445 | out: | |||||
10446 | /* return GPIO0/1 to original states after having accessed NVRAM */ | |||||
10447 | OUTB (nc_gpcntl, old_gpcntl)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_gpcntl))))) = (((old_gpcntl )))); | |||||
10448 | OUTB (nc_gpreg, old_gpreg)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_gpreg))))) = (((old_gpreg )))); | |||||
10449 | ||||||
10450 | return retv; | |||||
10451 | } | |||||
10452 | ||||||
10453 | /* | |||||
10454 | * Read Symbios NvRAM data and compute checksum. | |||||
10455 | */ | |||||
10456 | __initfunc(static unsigned short nvram_read_data(ncr_slot *np, unsigned char *data, int len, unsigned char *gpreg, unsigned char *gpcntl) | |||||
10457 | static u_short nvram_read_data(ncr_slot *np, u_char *data, int len, u_char *gpreg, u_char *gpcntl)static unsigned short nvram_read_data(ncr_slot *np, unsigned char *data, int len, unsigned char *gpreg, unsigned char *gpcntl) | |||||
10458 | )static unsigned short nvram_read_data(ncr_slot *np, unsigned char *data, int len, unsigned char *gpreg, unsigned char *gpcntl) | |||||
10459 | { | |||||
10460 | int x; | |||||
10461 | u_shortunsigned short csum; | |||||
10462 | ||||||
10463 | for (x = 0; x < len; x++) | |||||
10464 | nvram_read_byte(np, &data[x], (x == (len - 1)), gpreg, gpcntl); | |||||
10465 | ||||||
10466 | for (x = 6, csum = 0; x < len - 6; x++) | |||||
10467 | csum += data[x]; | |||||
10468 | ||||||
10469 | return csum; | |||||
10470 | } | |||||
10471 | ||||||
10472 | /* | |||||
10473 | * Send START condition to NVRAM to wake it up. | |||||
10474 | */ | |||||
10475 | __initfunc(static void nvram_start(ncr_slot *np, unsigned char *gpreg) | |||||
10476 | static void nvram_start(ncr_slot *np, u_char *gpreg)static void nvram_start(ncr_slot *np, unsigned char *gpreg) | |||||
10477 | )static void nvram_start(ncr_slot *np, unsigned char *gpreg) | |||||
10478 | { | |||||
10479 | nvram_setBit(np, 1, gpreg, SET_BIT); | |||||
10480 | nvram_setBit(np, 0, gpreg, SET_CLK); | |||||
10481 | nvram_setBit(np, 0, gpreg, CLR_BIT); | |||||
10482 | nvram_setBit(np, 0, gpreg, CLR_CLK); | |||||
10483 | } | |||||
10484 | ||||||
10485 | /* | |||||
10486 | * WRITE a byte to the NVRAM and then get an ACK to see it was accepted OK, | |||||
10487 | * GPIO0 must already be set as an output | |||||
10488 | */ | |||||
10489 | __initfunc(static void nvram_write_byte(ncr_slot *np, unsigned char *ack_data , unsigned char write_data, unsigned char *gpreg, unsigned char *gpcntl) | |||||
10490 | static void nvram_write_byte(ncr_slot *np, u_char *ack_data, u_char write_data, u_char *gpreg, u_char *gpcntl)static void nvram_write_byte(ncr_slot *np, unsigned char *ack_data , unsigned char write_data, unsigned char *gpreg, unsigned char *gpcntl) | |||||
10491 | )static void nvram_write_byte(ncr_slot *np, unsigned char *ack_data , unsigned char write_data, unsigned char *gpreg, unsigned char *gpcntl) | |||||
10492 | { | |||||
10493 | int x; | |||||
10494 | ||||||
10495 | for (x = 0; x < 8; x++) | |||||
10496 | nvram_doBit(np, 0, (write_data >> (7 - x)) & 0x01, gpreg); | |||||
10497 | ||||||
10498 | nvram_readAck(np, ack_data, gpreg, gpcntl); | |||||
10499 | } | |||||
10500 | ||||||
10501 | /* | |||||
10502 | * READ a byte from the NVRAM and then send an ACK to say we have got it, | |||||
10503 | * GPIO0 must already be set as an input | |||||
10504 | */ | |||||
10505 | __initfunc(static void nvram_read_byte(ncr_slot *np, unsigned char *read_data , unsigned char ack_data, unsigned char *gpreg, unsigned char *gpcntl) | |||||
10506 | static void nvram_read_byte(ncr_slot *np, u_char *read_data, u_char ack_data, u_char *gpreg, u_char *gpcntl)static void nvram_read_byte(ncr_slot *np, unsigned char *read_data , unsigned char ack_data, unsigned char *gpreg, unsigned char *gpcntl) | |||||
10507 | )static void nvram_read_byte(ncr_slot *np, unsigned char *read_data , unsigned char ack_data, unsigned char *gpreg, unsigned char *gpcntl) | |||||
10508 | { | |||||
10509 | int x; | |||||
10510 | u_charunsigned char read_bit; | |||||
10511 | ||||||
10512 | *read_data = 0; | |||||
10513 | for (x = 0; x < 8; x++) { | |||||
10514 | nvram_doBit(np, &read_bit, 1, gpreg); | |||||
10515 | *read_data |= ((read_bit & 0x01) << (7 - x)); | |||||
10516 | } | |||||
10517 | ||||||
10518 | nvram_writeAck(np, ack_data, gpreg, gpcntl); | |||||
10519 | } | |||||
10520 | ||||||
10521 | /* | |||||
10522 | * Output an ACK to the NVRAM after reading, | |||||
10523 | * change GPIO0 to output and when done back to an input | |||||
10524 | */ | |||||
10525 | __initfunc(static void nvram_writeAck(ncr_slot *np, unsigned char write_bit , unsigned char *gpreg, unsigned char *gpcntl) | |||||
10526 | static void nvram_writeAck(ncr_slot *np, u_char write_bit, u_char *gpreg, u_char *gpcntl)static void nvram_writeAck(ncr_slot *np, unsigned char write_bit , unsigned char *gpreg, unsigned char *gpcntl) | |||||
10527 | )static void nvram_writeAck(ncr_slot *np, unsigned char write_bit , unsigned char *gpreg, unsigned char *gpcntl) | |||||
10528 | { | |||||
10529 | OUTB (nc_gpcntl, *gpcntl & 0xfe)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_gpcntl))))) = (((*gpcntl & 0xfe)))); | |||||
10530 | nvram_doBit(np, 0, write_bit, gpreg); | |||||
10531 | OUTB (nc_gpcntl, *gpcntl)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_gpcntl))))) = (((*gpcntl )))); | |||||
10532 | } | |||||
10533 | ||||||
10534 | /* | |||||
10535 | * Input an ACK from NVRAM after writing, | |||||
10536 | * change GPIO0 to input and when done back to an output | |||||
10537 | */ | |||||
10538 | __initfunc(static void nvram_readAck(ncr_slot *np, unsigned char *read_bit , unsigned char *gpreg, unsigned char *gpcntl) | |||||
10539 | static void nvram_readAck(ncr_slot *np, u_char *read_bit, u_char *gpreg, u_char *gpcntl)static void nvram_readAck(ncr_slot *np, unsigned char *read_bit , unsigned char *gpreg, unsigned char *gpcntl) | |||||
10540 | )static void nvram_readAck(ncr_slot *np, unsigned char *read_bit , unsigned char *gpreg, unsigned char *gpcntl) | |||||
10541 | { | |||||
10542 | OUTB (nc_gpcntl, *gpcntl | 0x01)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_gpcntl))))) = (((*gpcntl | 0x01)))); | |||||
10543 | nvram_doBit(np, read_bit, 1, gpreg); | |||||
10544 | OUTB (nc_gpcntl, *gpcntl)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_gpcntl))))) = (((*gpcntl )))); | |||||
10545 | } | |||||
10546 | ||||||
10547 | /* | |||||
10548 | * Read or write a bit to the NVRAM, | |||||
10549 | * read if GPIO0 input else write if GPIO0 output | |||||
10550 | */ | |||||
10551 | __initfunc(static void nvram_doBit(ncr_slot *np, unsigned char *read_bit , unsigned char write_bit, unsigned char *gpreg) | |||||
10552 | static void nvram_doBit(ncr_slot *np, u_char *read_bit, u_char write_bit, u_char *gpreg)static void nvram_doBit(ncr_slot *np, unsigned char *read_bit , unsigned char write_bit, unsigned char *gpreg) | |||||
10553 | )static void nvram_doBit(ncr_slot *np, unsigned char *read_bit , unsigned char write_bit, unsigned char *gpreg) | |||||
10554 | { | |||||
10555 | nvram_setBit(np, write_bit, gpreg, SET_BIT); | |||||
10556 | nvram_setBit(np, 0, gpreg, SET_CLK); | |||||
10557 | if (read_bit) | |||||
10558 | *read_bit = INB (nc_gpreg)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_gpreg))))); | |||||
10559 | nvram_setBit(np, 0, gpreg, CLR_CLK); | |||||
10560 | nvram_setBit(np, 0, gpreg, CLR_BIT); | |||||
10561 | } | |||||
10562 | ||||||
10563 | /* | |||||
10564 | * Send STOP condition to NVRAM - puts NVRAM to sleep... ZZzzzz!! | |||||
10565 | */ | |||||
10566 | __initfunc(static void nvram_stop(ncr_slot *np, unsigned char *gpreg) | |||||
10567 | static void nvram_stop(ncr_slot *np, u_char *gpreg)static void nvram_stop(ncr_slot *np, unsigned char *gpreg) | |||||
10568 | )static void nvram_stop(ncr_slot *np, unsigned char *gpreg) | |||||
10569 | { | |||||
10570 | nvram_setBit(np, 0, gpreg, SET_CLK); | |||||
10571 | nvram_setBit(np, 1, gpreg, SET_BIT); | |||||
10572 | } | |||||
10573 | ||||||
10574 | /* | |||||
10575 | * Set/clear data/clock bit in GPIO0 | |||||
10576 | */ | |||||
10577 | __initfunc(static void nvram_setBit(ncr_slot *np, unsigned char write_bit , unsigned char *gpreg, int bit_mode) | |||||
10578 | static void nvram_setBit(ncr_slot *np, u_char write_bit, u_char *gpreg, int bit_mode)static void nvram_setBit(ncr_slot *np, unsigned char write_bit , unsigned char *gpreg, int bit_mode) | |||||
10579 | )static void nvram_setBit(ncr_slot *np, unsigned char write_bit , unsigned char *gpreg, int bit_mode) | |||||
10580 | { | |||||
10581 | DELAY(5); | |||||
10582 | switch (bit_mode){ | |||||
10583 | case SET_BIT: | |||||
10584 | *gpreg |= write_bit; | |||||
10585 | break; | |||||
10586 | case CLR_BIT: | |||||
10587 | *gpreg &= 0xfe; | |||||
10588 | break; | |||||
10589 | case SET_CLK: | |||||
10590 | *gpreg |= 0x02; | |||||
10591 | break; | |||||
10592 | case CLR_CLK: | |||||
10593 | *gpreg &= 0xfd; | |||||
10594 | break; | |||||
10595 | ||||||
10596 | } | |||||
10597 | OUTB (nc_gpreg, *gpreg)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_gpreg))))) = (((*gpreg)) )); | |||||
10598 | DELAY(5); | |||||
10599 | } | |||||
10600 | ||||||
10601 | #undef SET_BIT 0 | |||||
10602 | #undef CLR_BIT 1 | |||||
10603 | #undef SET_CLK 2 | |||||
10604 | #undef CLR_CLK 3 | |||||
10605 | ||||||
10606 | ||||||
10607 | /* --------------------------------------------------------------------- | |||||
10608 | ** | |||||
10609 | ** Try reading Tekram format nvram | |||||
10610 | ** | |||||
10611 | ** --------------------------------------------------------------------- | |||||
10612 | ** | |||||
10613 | ** GPOI0 - data in | |||||
10614 | ** GPIO1 - data out | |||||
10615 | ** GPIO2 - clock | |||||
10616 | ** GPIO4 - chip select | |||||
10617 | ** | |||||
10618 | ** return 0 if NVRAM data OK, 1 if NVRAM data not OK | |||||
10619 | ** --------------------------------------------------------------------- | |||||
10620 | */ | |||||
10621 | ||||||
10622 | static u_shortunsigned short Tnvram_read_data(ncr_slot *np, u_shortunsigned short *data, int len, u_charunsigned char *gpreg); | |||||
10623 | static void Tnvram_Send_Command(ncr_slot *np, u_shortunsigned short write_data, u_charunsigned char *read_bit, u_charunsigned char *gpreg); | |||||
10624 | static void Tnvram_Read_Word(ncr_slot *np, u_shortunsigned short *nvram_data, u_charunsigned char *gpreg); | |||||
10625 | static void Tnvram_Read_Bit(ncr_slot *np, u_charunsigned char *read_bit, u_charunsigned char *gpreg); | |||||
10626 | static void Tnvram_Write_Bit(ncr_slot *np, u_charunsigned char write_bit, u_charunsigned char *gpreg); | |||||
10627 | static void Tnvram_Stop(ncr_slot *np, u_charunsigned char *gpreg); | |||||
10628 | static void Tnvram_Clk(ncr_slot *np, u_charunsigned char *gpreg); | |||||
10629 | ||||||
10630 | __initfunc(static int ncr_get_Tekram_nvram (ncr_slot *np, Tekram_nvram * nvram) | |||||
10631 | static int ncr_get_Tekram_nvram (ncr_slot *np, Tekram_nvram *nvram)static int ncr_get_Tekram_nvram (ncr_slot *np, Tekram_nvram * nvram) | |||||
10632 | )static int ncr_get_Tekram_nvram (ncr_slot *np, Tekram_nvram * nvram) | |||||
10633 | { | |||||
10634 | u_charunsigned char gpcntl, gpreg; | |||||
10635 | u_charunsigned char old_gpcntl, old_gpreg; | |||||
10636 | u_shortunsigned short csum; | |||||
10637 | ||||||
10638 | /* save current state of GPCNTL and GPREG */ | |||||
10639 | old_gpreg = INB (nc_gpreg)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_gpreg))))); | |||||
10640 | old_gpcntl = INB (nc_gpcntl)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_gpcntl))))); | |||||
10641 | ||||||
10642 | /* set up GPREG & GPCNTL to set GPIO0/1/2/4 in to known state, 0 in, | |||||
10643 | 1/2/4 out */ | |||||
10644 | gpreg = old_gpreg & 0xe9; | |||||
10645 | OUTB (nc_gpreg, gpreg)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_gpreg))))) = (((gpreg))) ); | |||||
10646 | gpcntl = (old_gpcntl & 0xe9) | 0x09; | |||||
10647 | OUTB (nc_gpcntl, gpcntl)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_gpcntl))))) = (((gpcntl) ))); | |||||
10648 | ||||||
10649 | /* input all of NVRAM, 64 words */ | |||||
10650 | csum = Tnvram_read_data(np, (u_shortunsigned short *) nvram, | |||||
10651 | sizeof(*nvram) / sizeof(short), &gpreg); | |||||
10652 | ||||||
10653 | /* return GPIO0/1/2/4 to original states after having accessed NVRAM */ | |||||
10654 | OUTB (nc_gpcntl, old_gpcntl)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_gpcntl))))) = (((old_gpcntl )))); | |||||
10655 | OUTB (nc_gpreg, old_gpreg)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_gpreg))))) = (((old_gpreg )))); | |||||
10656 | ||||||
10657 | /* check data valid */ | |||||
10658 | if (csum != 0x1234) | |||||
10659 | return 1; | |||||
10660 | ||||||
10661 | return 0; | |||||
10662 | } | |||||
10663 | ||||||
10664 | /* | |||||
10665 | * Read Tekram NvRAM data and compute checksum. | |||||
10666 | */ | |||||
10667 | __initfunc(static unsigned short Tnvram_read_data(ncr_slot *np, unsigned short *data, int len, unsigned char *gpreg) | |||||
10668 | static u_short Tnvram_read_data(ncr_slot *np, u_short *data, int len, u_char *gpreg)static unsigned short Tnvram_read_data(ncr_slot *np, unsigned short *data, int len, unsigned char *gpreg) | |||||
10669 | )static unsigned short Tnvram_read_data(ncr_slot *np, unsigned short *data, int len, unsigned char *gpreg) | |||||
10670 | { | |||||
10671 | u_charunsigned char read_bit; | |||||
10672 | u_shortunsigned short csum; | |||||
10673 | int x; | |||||
10674 | ||||||
10675 | for (x = 0, csum = 0; x < len; x++) { | |||||
10676 | ||||||
10677 | /* output read command and address */ | |||||
10678 | Tnvram_Send_Command(np, 0x180 | x, &read_bit, gpreg); | |||||
10679 | if (read_bit & 0x01) | |||||
10680 | return 0; /* Force bad checksum */ | |||||
10681 | ||||||
10682 | Tnvram_Read_Word(np, &data[x], gpreg); | |||||
10683 | csum += data[x]; | |||||
10684 | ||||||
10685 | Tnvram_Stop(np, gpreg); | |||||
10686 | } | |||||
10687 | ||||||
10688 | return csum; | |||||
10689 | } | |||||
10690 | ||||||
10691 | /* | |||||
10692 | * Send read command and address to NVRAM | |||||
10693 | */ | |||||
10694 | __initfunc(static void Tnvram_Send_Command(ncr_slot *np, unsigned short write_data , unsigned char *read_bit, unsigned char *gpreg) | |||||
10695 | static void Tnvram_Send_Command(ncr_slot *np, u_short write_data, u_char *read_bit, u_char *gpreg)static void Tnvram_Send_Command(ncr_slot *np, unsigned short write_data , unsigned char *read_bit, unsigned char *gpreg) | |||||
10696 | )static void Tnvram_Send_Command(ncr_slot *np, unsigned short write_data , unsigned char *read_bit, unsigned char *gpreg) | |||||
10697 | { | |||||
10698 | int x; | |||||
10699 | ||||||
10700 | /* send 9 bits, start bit (1), command (2), address (6) */ | |||||
10701 | for (x = 0; x < 9; x++) | |||||
10702 | Tnvram_Write_Bit(np, (u_charunsigned char) (write_data >> (8 - x)), gpreg); | |||||
10703 | ||||||
10704 | *read_bit = INB (nc_gpreg)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_gpreg))))); | |||||
10705 | } | |||||
10706 | ||||||
10707 | /* | |||||
10708 | * READ a byte from the NVRAM | |||||
10709 | */ | |||||
10710 | __initfunc(static void Tnvram_Read_Word(ncr_slot *np, unsigned short *nvram_data , unsigned char *gpreg) | |||||
10711 | static void Tnvram_Read_Word(ncr_slot *np, u_short *nvram_data, u_char *gpreg)static void Tnvram_Read_Word(ncr_slot *np, unsigned short *nvram_data , unsigned char *gpreg) | |||||
10712 | )static void Tnvram_Read_Word(ncr_slot *np, unsigned short *nvram_data , unsigned char *gpreg) | |||||
10713 | { | |||||
10714 | int x; | |||||
10715 | u_charunsigned char read_bit; | |||||
10716 | ||||||
10717 | *nvram_data = 0; | |||||
10718 | for (x = 0; x < 16; x++) { | |||||
10719 | Tnvram_Read_Bit(np, &read_bit, gpreg); | |||||
10720 | ||||||
10721 | if (read_bit & 0x01) | |||||
10722 | *nvram_data |= (0x01 << (15 - x)); | |||||
10723 | else | |||||
10724 | *nvram_data &= ~(0x01 << (15 - x)); | |||||
10725 | } | |||||
10726 | } | |||||
10727 | ||||||
10728 | /* | |||||
10729 | * Read bit from NVRAM | |||||
10730 | */ | |||||
10731 | __initfunc(static void Tnvram_Read_Bit(ncr_slot *np, unsigned char *read_bit , unsigned char *gpreg) | |||||
10732 | static void Tnvram_Read_Bit(ncr_slot *np, u_char *read_bit, u_char *gpreg)static void Tnvram_Read_Bit(ncr_slot *np, unsigned char *read_bit , unsigned char *gpreg) | |||||
10733 | )static void Tnvram_Read_Bit(ncr_slot *np, unsigned char *read_bit , unsigned char *gpreg) | |||||
10734 | { | |||||
10735 | DELAY(2); | |||||
10736 | Tnvram_Clk(np, gpreg); | |||||
10737 | *read_bit = INB (nc_gpreg)(*(volatile unsigned char *) ((char *)np->reg + (((size_t) (&((struct ncr_reg *)0)->nc_gpreg))))); | |||||
10738 | } | |||||
10739 | ||||||
10740 | /* | |||||
10741 | * Write bit to GPIO0 | |||||
10742 | */ | |||||
10743 | __initfunc(static void Tnvram_Write_Bit(ncr_slot *np, unsigned char write_bit , unsigned char *gpreg) | |||||
10744 | static void Tnvram_Write_Bit(ncr_slot *np, u_char write_bit, u_char *gpreg)static void Tnvram_Write_Bit(ncr_slot *np, unsigned char write_bit , unsigned char *gpreg) | |||||
10745 | )static void Tnvram_Write_Bit(ncr_slot *np, unsigned char write_bit , unsigned char *gpreg) | |||||
10746 | { | |||||
10747 | if (write_bit & 0x01) | |||||
10748 | *gpreg |= 0x02; | |||||
10749 | else | |||||
10750 | *gpreg &= 0xfd; | |||||
10751 | ||||||
10752 | *gpreg |= 0x10; | |||||
10753 | ||||||
10754 | OUTB (nc_gpreg, *gpreg)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_gpreg))))) = (((*gpreg)) )); | |||||
10755 | DELAY(2); | |||||
10756 | ||||||
10757 | Tnvram_Clk(np, gpreg); | |||||
10758 | } | |||||
10759 | ||||||
10760 | /* | |||||
10761 | * Send STOP condition to NVRAM - puts NVRAM to sleep... ZZZzzz!! | |||||
10762 | */ | |||||
10763 | __initfunc(static void Tnvram_Stop(ncr_slot *np, unsigned char *gpreg) | |||||
10764 | static void Tnvram_Stop(ncr_slot *np, u_char *gpreg)static void Tnvram_Stop(ncr_slot *np, unsigned char *gpreg) | |||||
10765 | )static void Tnvram_Stop(ncr_slot *np, unsigned char *gpreg) | |||||
10766 | { | |||||
10767 | *gpreg &= 0xef; | |||||
10768 | OUTB (nc_gpreg, *gpreg)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_gpreg))))) = (((*gpreg)) )); | |||||
10769 | DELAY(2); | |||||
10770 | ||||||
10771 | Tnvram_Clk(np, gpreg); | |||||
10772 | } | |||||
10773 | ||||||
10774 | /* | |||||
10775 | * Pulse clock bit in GPIO0 | |||||
10776 | */ | |||||
10777 | __initfunc(static void Tnvram_Clk(ncr_slot *np, unsigned char *gpreg) | |||||
10778 | static void Tnvram_Clk(ncr_slot *np, u_char *gpreg)static void Tnvram_Clk(ncr_slot *np, unsigned char *gpreg) | |||||
10779 | )static void Tnvram_Clk(ncr_slot *np, unsigned char *gpreg) | |||||
10780 | { | |||||
10781 | OUTB (nc_gpreg, *gpreg | 0x04)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_gpreg))))) = (((*gpreg | 0x04)))); | |||||
10782 | DELAY(2); | |||||
10783 | OUTB (nc_gpreg, *gpreg)((*(volatile unsigned char *) ((char *)np->reg + (((size_t ) (&((struct ncr_reg *)0)->nc_gpreg))))) = (((*gpreg)) )); | |||||
10784 | } | |||||
10785 | ||||||
10786 | #endif /* SCSI_NCR_NVRAM_SUPPORT */ | |||||
10787 | ||||||
10788 | /* | |||||
10789 | ** Module stuff | |||||
10790 | */ | |||||
10791 | ||||||
10792 | #ifdef MODULE | |||||
10793 | Scsi_Host_Template driver_template = NCR53C8XX; | |||||
10794 | #include "scsi_module.c" | |||||
10795 | #endif |