File: | obj-scan-build/../linux/src/drivers/scsi/ncr53c8xx.c |
Location: | line 5625, column 2 |
Description: | Value stored to 'cmd' is never read |
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; |
Value stored to 'cmd' is never read | |
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 |