File: | obj-scan-build/../linux/src/drivers/scsi/ncr53c8xx.c |
Location: | line 3885, column 53 |
Description: | Access to field 'host' results in a dereference of a null pointer (loaded from variable 'cmd') |
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 |