|
|
1.1 root 1: /************************************************************************
2: * GDT ISA/EISA/PCI Disk Array Controller driver for Linux *
3: * *
4: * gdth.c *
5: * Copyright (C) 1995-98 ICP vortex Computersysteme GmbH, Achim Leubner *
6: * *
7: * <[email protected]> *
8: * *
9: * This program is free software; you can redistribute it and/or modify *
10: * it under the terms of the GNU General Public License as published *
11: * by the Free Software Foundation; either version 2 of the License, *
12: * or (at your option) any later version. *
13: * *
14: * This program is distributed in the hope that it will be useful, *
15: * but WITHOUT ANY WARRANTY; without even the implied warranty of *
16: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
17: * GNU General Public License for more details. *
18: * *
19: * You should have received a copy of the GNU General Public License *
20: * along with this kernel; if not, write to the Free Software *
21: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
22: * *
23: * Tested with Linux 1.2.13, ..., 2.1.103 *
24: * *
25: * $Log: gdth.c,v $
26: * Revision 1.1 1999/04/26 05:54:35 tb
27: * 1998-11-30 OKUJI Yoshinori <[email protected]>
28: *
29: * Clean up linux emulation code to make it architecture-independent
30: * as much as possible.
31: *
32: * * linux: Renamed from linuxdev.
33: * * Makefile.in (objfiles): Add linux.o instead of linuxdev.o.
34: * (MAKE): New variable. Used for the linux.o target.
35: * * configure.in: Add AC_CHECK_TOOL(MAKE, make).
36: * * i386/i386/spl.h: Include <i386/ipl.h>, for compatibility with
37: * OSF Mach 3.0. Suggested by Elgin Lee <[email protected]>.
38: * * linux/src: Renamed from linux/linux.
39: * * linux/dev: Renamed from linux/mach.
40: * * linux/Drivers.in (AC_INIT): Use dev/include/linux/autoconf.h,
41: * instead of mach/include/linux/autoconf.h.
42: * * Makefile.in (all): Target ../linux.o instead of ../linuxdev.o.
43: * * linux/dev/drivers/block/genhd.c: Include <machine/spl.h> instead
44: * of <i386/ipl.h>.
45: * * linux/dev/drivers/net/auto_irq.c: Remove unneeded header files,
46: * <i386/ipl.h> and <i386/pic.h>.
47: * * linux/dev/init/main.c: Many i386-dependent codes moved to ...
48: * * linux/dev/arch/i386/irq.c: ... here.
49: * * linux/dev/arch/i386/setup.c: New file.
50: * * linux/dev/arch/i386/linux_emul.h: Likewise.
51: * * linux/dev/arch/i386/glue/timer.c: Merged into sched.c.
52: * * linux/dev/arch/i386/glue/sched.c: Include <machine/spl.h> instead
53: * of <i386/ipl.h>, and moved to ...
54: * * linux/dev/kernel/sched.c: ... here.
55: * * linux/dev/arch/i386/glue/block.c: Include <machine/spl.h> and
56: * <linux_emul.h>, instead of i386-dependent header files, and
57: * moved to ...
58: * * linux/dev/glue/blocl.c: ... here.
59: * * linux/dev/arch/i386/glue/net.c: Include <machine/spl.h> and
60: * <linux_emul.h>, instead of i386-dependent header files, and
61: * moved to ...
62: * * linux/dev/glue/net.c: ... here.
63: * * linux/dev/arch/i386/glue/misc.c: Remove `x86' and moved to ...
64: * * linux/dev/glue/misc.c: ... here.
65: * * linux/dev/arch/i386/glue/kmem.c: Moved to ...
66: * * linux/dev/glue/kmem.c: ... here.
67: *
68: * Revision 1.16 1998/09/28 16:08:46 achim
69: * GDT_PCIMPR: DPMEM remapping, if required
70: * mdelay() added
71: *
72: * Revision 1.15 1998/06/03 14:54:06 achim
73: * gdth_delay(), gdth_flush() implemented
74: * Bugfix: gdth_release() changed
75: *
76: * Revision 1.14 1998/05/22 10:01:17 achim
77: * mj: pcibios_strerror() removed
78: * Improved SMP support (if version >= 2.1.95)
79: * gdth_halt(): halt_called flag added (if version < 2.1)
80: *
81: * Revision 1.13 1998/04/16 09:14:57 achim
82: * Reserve drives (for raw service) implemented
83: * New error handling code enabled
84: * Get controller name from board_info() IOCTL
85: * Final round of PCI device driver patches by Martin Mares
86: *
87: * Revision 1.12 1998/03/03 09:32:37 achim
88: * Fibre channel controller support added
89: *
90: * Revision 1.11 1998/01/27 16:19:14 achim
91: * SA_SHIRQ added
92: * add_timer()/del_timer() instead of GDTH_TIMER
93: * scsi_add_timer()/scsi_del_timer() instead of SCSI_TIMER
94: * New error handling included
95: *
96: * Revision 1.10 1997/10/31 12:29:57 achim
97: * Read heads/sectors from host drive
98: *
99: * Revision 1.9 1997/09/04 10:07:25 achim
100: * IO-mapping with virt_to_bus(), readb(), writeb(), ...
101: * register_reboot_notifier() to get a notify on shutdown used
102: *
103: * Revision 1.8 1997/04/02 12:14:30 achim
104: * Version 1.00 (see gdth.h), tested with kernel 2.0.29
105: *
106: * Revision 1.7 1997/03/12 13:33:37 achim
107: * gdth_reset() changed, new async. events
108: *
109: * Revision 1.6 1997/03/04 14:01:11 achim
110: * Shutdown routine gdth_halt() implemented
111: *
112: * Revision 1.5 1997/02/21 09:08:36 achim
113: * New controller included (RP, RP1, RP2 series)
114: * IOCTL interface implemented
115: *
116: * Revision 1.4 1996/07/05 12:48:55 achim
117: * Function gdth_bios_param() implemented
118: * New constant GDTH_MAXC_P_L inserted
119: * GDT_WRITE_THR, GDT_EXT_INFO implemented
120: * Function gdth_reset() changed
121: *
122: * Revision 1.3 1996/05/10 09:04:41 achim
123: * Small changes for Linux 1.2.13
124: *
125: * Revision 1.2 1996/05/09 12:45:27 achim
126: * Loadable module support implemented
127: * /proc support corrections made
128: *
129: * Revision 1.1 1996/04/11 07:35:57 achim
130: * Initial revision
131: *
132: *
133: * $Id: gdth.c,v 1.1 1999/04/26 05:54:35 tb Exp $
134: ************************************************************************/
135:
136: #ifdef MODULE
137: #include <linux/module.h>
138: #endif
139:
140: #include <linux/version.h>
141: #include <linux/kernel.h>
142: #include <linux/head.h>
143: #include <linux/types.h>
144: #include <linux/pci.h>
145: #include <linux/string.h>
146: #include <linux/ioport.h>
147: #include <linux/delay.h>
148: #include <linux/sched.h>
149: #include <linux/in.h>
150: #include <linux/proc_fs.h>
151: #include <linux/time.h>
152: #include <linux/timer.h>
153: #if LINUX_VERSION_CODE >= 0x020100
154: #include <linux/reboot.h>
155: #else
156: #include <linux/bios32.h>
157: #endif
158:
159: #include <asm/dma.h>
160: #include <asm/system.h>
161: #include <asm/io.h>
162: #if LINUX_VERSION_CODE >= 0x02015F
163: #include <asm/spinlock.h>
164: #endif
165:
166: #if LINUX_VERSION_CODE >= 0x010300
167: #include <linux/blk.h>
168: #else
169: #include "../block/blk.h"
170: #endif
171: #include "scsi.h"
172: #include "hosts.h"
173: #include "sd.h"
174:
175: #include "gdth.h"
176:
177: /****************************************************************************/
178:
179: /* LILO params: gdth=<IRQ>
180: *
181: * Where: <IRQ> is any of the valid IRQs for EISA controllers (10,11,12,14)
182: * Sets the IRQ of the GDT3000/3020 EISA controller to this value,
183: * if the IRQ can not automat. detect (controller BIOS disabled)
184: * See gdth_init_eisa()
185: *
186: * You can use the command line gdth=0 to disable the driver
187: */
188: static unchar irqs[MAXHA] = {0xff};
189: static unchar disable_gdth_scan = FALSE;
190:
191: /* Reserve drives for raw service: Fill the following structure with the
192: * appropriate values: Controller number, Channel, Target ID
193: */
194: static gdth_reserve_str reserve_list[] = {
195: /* { 0, 1, 4 }, Example: Controller 0, Channel B, ID 4 */
196: { 0xff, 0xff, 0xff } /* end of list */
197: };
198:
199: /****************************************************************************/
200:
201: #if LINUX_VERSION_CODE >= 0x02015F
202: static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs);
203: static void do_gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs);
204: #elif LINUX_VERSION_CODE >= 0x010346
205: static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs);
206: #else
207: static void gdth_interrupt(int irq,struct pt_regs *regs);
208: #endif
209: static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp);
210: static int gdth_async_event(int hanum,int service);
211:
212: static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority);
213: static void gdth_next(int hanum);
214: static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b);
215: static int gdth_special_cmd(int hanum,Scsi_Cmnd *scp,unchar b);
216: static gdth_evt_str *gdth_store_event(ushort source, ushort idx,
217: gdth_evt_data *evt);
218: static int gdth_read_event(int handle, gdth_evt_str *estr);
219: static void gdth_readapp_event(unchar application, gdth_evt_str *estr);
220: static void gdth_clear_events(void);
221:
222: static void gdth_copy_internal_data(Scsi_Cmnd *scp,char *buffer,ushort count);
223: static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp,
224: unchar b,ulong *flags);
225: static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive);
226:
227: static int gdth_search_eisa(ushort eisa_adr);
228: static int gdth_search_isa(ulong bios_adr);
229: static int gdth_search_pci(ushort device_id,ushort index,gdth_pci_str *pcistr);
230: static int gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha);
231: static int gdth_init_isa(ulong bios_adr,gdth_ha_str *ha);
232: static int gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha);
233:
234: static void gdth_enable_int(int hanum);
235: static int gdth_get_status(unchar *pIStatus,int irq);
236: static int gdth_test_busy(int hanum);
237: static int gdth_get_cmd_index(int hanum);
238: static void gdth_release_event(int hanum);
239: static int gdth_wait(int hanum,int index,ulong time);
240: static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong p1,
241: ulong p2,ulong p3);
242: static int gdth_search_drives(int hanum);
243:
244: static void *gdth_mmap(ulong paddr, ulong size);
245: static void gdth_munmap(void *addr);
246:
247: static const char *gdth_ctr_name(int hanum);
248:
249: static void gdth_flush(int hanum);
250: #if LINUX_VERSION_CODE >= 0x020100
251: static int gdth_halt(struct notifier_block *nb, ulong event, void *buf);
252: #else
253: static int halt_called = FALSE;
254: void gdth_halt(void);
255: #endif
256:
257: #ifdef DEBUG_GDTH
258: static unchar DebugState = DEBUG_GDTH;
259: extern int sys_syslog(int,char*,int);
260: #define LOGEN sys_syslog(7,NULL,0)
261:
262: #ifdef __SERIAL__
263: #define MAX_SERBUF 160
264: static void ser_init(void);
265: static void ser_puts(char *str);
266: static void ser_putc(char c);
267: static int ser_printk(const char *fmt, ...);
268: static char strbuf[MAX_SERBUF+1];
269: #ifdef __COM2__
270: #define COM_BASE 0x2f8
271: #else
272: #define COM_BASE 0x3f8
273: #endif
274: static void ser_init()
275: {
276: unsigned port=COM_BASE;
277:
278: outb(0x80,port+3);
279: outb(0,port+1);
280: /* 19200 Baud, if 9600: outb(12,port) */
281: outb(6, port);
282: outb(3,port+3);
283: outb(0,port+1);
284: /*
285: ser_putc('I');
286: ser_putc(' ');
287: */
288: }
289:
290: static void ser_puts(char *str)
291: {
292: char *ptr;
293:
294: ser_init();
295: for (ptr=str;*ptr;++ptr)
296: ser_putc(*ptr);
297: }
298:
299: static void ser_putc(char c)
300: {
301: unsigned port=COM_BASE;
302:
303: while ((inb(port+5) & 0x20)==0);
304: outb(c,port);
305: if (c==0x0a)
306: {
307: while ((inb(port+5) & 0x20)==0);
308: outb(0x0d,port);
309: }
310: }
311:
312: static int ser_printk(const char *fmt, ...)
313: {
314: va_list args;
315: int i;
316:
317: va_start(args,fmt);
318: i = vsprintf(strbuf,fmt,args);
319: ser_puts(strbuf);
320: va_end(args);
321: return i;
322: }
323:
324: #define TRACE(a) {if (DebugState==1) {ser_printk a;}}
325: #define TRACE2(a) {if (DebugState==1 || DebugState==2) {ser_printk a;}}
326: #define TRACE3(a) {if (DebugState!=0) {ser_printk a;}}
327:
328: #else /* !__SERIAL__ */
329: #define TRACE(a) {if (DebugState==1) {LOGEN;printk a;}}
330: #define TRACE2(a) {if (DebugState==1 || DebugState==2) {LOGEN;printk a;}}
331: #define TRACE3(a) {if (DebugState!=0) {LOGEN;printk a;}}
332: #endif
333:
334: #else /* !DEBUG */
335: #define TRACE(a)
336: #define TRACE2(a)
337: #define TRACE3(a)
338: #endif
339:
340: #ifdef GDTH_STATISTICS
341: static ulong max_rq=0, max_index=0, max_sg=0;
342: static ulong act_ints=0, act_ios=0, act_stats=0, act_rq=0;
343: static struct timer_list gdth_timer;
344: #endif
345:
346: #define PTR2USHORT(a) (ushort)(ulong)(a)
347: #define GDTOFFSOF(a,b) (size_t)&(((a*)0)->b)
348: #define INDEX_OK(i,t) ((i)<sizeof(t)/sizeof((t)[0]))
349:
350: #define NUMDATA(a) ( (gdth_num_str *)((a)->hostdata))
351: #define HADATA(a) (&((gdth_ext_str *)((a)->hostdata))->haext)
352: #define CMDDATA(a) (&((gdth_ext_str *)((a)->hostdata))->cmdext)
353: #define DMADATA(a) (&((gdth_ext_str *)((a)->hostdata))->dmaext)
354:
355:
356: #if LINUX_VERSION_CODE < 0x010300
357: static void *gdth_mmap(ulong paddr, ulong size)
358: {
359: if (paddr >= high_memory)
360: return NULL;
361: else
362: return (void *)paddr;
363: }
364: static void gdth_munmap(void *addr)
365: {
366: }
367: inline ulong virt_to_phys(volatile void *addr)
368: {
369: return (ulong)addr;
370: }
371: inline void *phys_to_virt(ulong addr)
372: {
373: return (void *)addr;
374: }
375: #define virt_to_bus virt_to_phys
376: #define bus_to_virt phys_to_virt
377: #define readb(addr) (*(volatile unchar *)(addr))
378: #define readw(addr) (*(volatile ushort *)(addr))
379: #define readl(addr) (*(volatile ulong *)(addr))
380: #define writeb(b,addr) (*(volatile unchar *)(addr) = (b))
381: #define writew(b,addr) (*(volatile ushort *)(addr) = (b))
382: #define writel(b,addr) (*(volatile ulong *)(addr) = (b))
383: #define memset_io(a,b,c) memset((void *)(a),(b),(c))
384: #define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c))
385: #define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c))
386:
387: #elif LINUX_VERSION_CODE < 0x020100
388: static int remapped = FALSE;
389: static void *gdth_mmap(ulong paddr, ulong size)
390: {
391: if ( paddr >= high_memory) {
392: remapped = TRUE;
393: return vremap(paddr, size);
394: } else {
395: return (void *)paddr;
396: }
397: }
398: static void gdth_munmap(void *addr)
399: {
400: if (remapped)
401: vfree(addr);
402: remapped = FALSE;
403: }
404: #else
405: static void *gdth_mmap(ulong paddr, ulong size)
406: {
407: return ioremap(paddr, size);
408: }
409: static void gdth_munmap(void *addr)
410: {
411: return iounmap(addr);
412: }
413: #endif
414:
415:
416: static unchar gdth_drq_tab[4] = {5,6,7,7}; /* DRQ table */
417: static unchar gdth_irq_tab[6] = {0,10,11,12,14,0}; /* IRQ table */
418: static unchar gdth_polling; /* polling if TRUE */
419: static unchar gdth_from_wait = FALSE; /* gdth_wait() */
420: static int wait_index,wait_hanum; /* gdth_wait() */
421: static int gdth_ctr_count = 0; /* controller count */
422: static int gdth_ctr_vcount = 0; /* virt. ctr. count */
423: static int gdth_ctr_released = 0; /* gdth_release() */
424: static struct Scsi_Host *gdth_ctr_tab[MAXHA]; /* controller table */
425: static struct Scsi_Host *gdth_ctr_vtab[MAXHA*MAXBUS]; /* virt. ctr. table */
426: static unchar gdth_write_through = FALSE; /* write through */
427: static char *gdth_ioctl_tab[4][MAXHA]; /* ioctl buffer */
428: static gdth_evt_str ebuffer[MAX_EVENTS]; /* event buffer */
429: static int elastidx;
430: static int eoldidx;
431:
432: static struct {
433: Scsi_Cmnd *cmnd; /* pending request */
434: ushort service; /* service */
435: } gdth_cmd_tab[GDTH_MAXCMDS][MAXHA]; /* table of pend. requests */
436:
437: #define DIN 1 /* IN data direction */
438: #define DOU 2 /* OUT data direction */
439: #define DNO DIN /* no data transfer */
440: #define DUN DIN /* unknown data direction */
441: static unchar gdth_direction_tab[0x100] = {
442: DNO,DNO,DIN,DIN,DOU,DIN,DIN,DOU,DIN,DUN,DOU,DOU,DUN,DUN,DUN,DIN,
443: DNO,DIN,DIN,DOU,DIN,DOU,DNO,DNO,DOU,DNO,DIN,DNO,DIN,DOU,DNO,DUN,
444: DIN,DUN,DIN,DUN,DOU,DIN,DUN,DUN,DIN,DIN,DIN,DUN,DUN,DIN,DIN,DIN,
445: DIN,DIN,DIN,DNO,DIN,DNO,DNO,DIN,DIN,DIN,DIN,DIN,DIN,DIN,DIN,DIN,
446: DIN,DIN,DIN,DIN,DIN,DNO,DUN,DNO,DNO,DNO,DUN,DNO,DIN,DIN,DUN,DUN,
447: DUN,DUN,DUN,DUN,DUN,DIN,DUN,DUN,DUN,DUN,DIN,DUN,DUN,DUN,DUN,DUN,
448: DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
449: DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
450: DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
451: DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
452: DUN,DUN,DUN,DUN,DUN,DNO,DNO,DUN,DIN,DNO,DIN,DUN,DNO,DUN,DIN,DIN,
453: DIN,DIN,DIN,DNO,DUN,DIN,DIN,DIN,DIN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
454: DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
455: DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
456: DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DOU,DUN,DUN,DUN,DUN,DUN,
457: DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN
458: };
459:
460: /* __initfunc, __initdata macros */
461: #if LINUX_VERSION_CODE >= 0x020126
462: #include <linux/init.h>
463: #else
464: #define __initfunc(A) A
465: #define __initdata
466: #define __init
467: #endif
468:
469: /* /proc support */
470: #if LINUX_VERSION_CODE >= 0x010300
471: #include <linux/stat.h>
472: struct proc_dir_entry proc_scsi_gdth = {
473: PROC_SCSI_GDTH, 4, "gdth",
474: S_IFDIR | S_IRUGO | S_IXUGO, 2
475: };
476: #include "gdth_proc.h"
477: #include "gdth_proc.c"
478: #endif
479:
480: #if LINUX_VERSION_CODE >= 0x020100
481: /* notifier block to get a notify on system shutdown/halt/reboot */
482: static struct notifier_block gdth_notifier = {
483: gdth_halt, NULL, 0
484: };
485: #endif
486:
487: static void gdth_delay(int milliseconds)
488: {
489: if (milliseconds == 0) {
490: udelay(1);
491: } else {
492: #if LINUX_VERSION_CODE >= 0x020168
493: mdelay(milliseconds);
494: #else
495: int i;
496: for (i = 0; i < milliseconds; ++i)
497: udelay(1000);
498: #endif
499: }
500: }
501:
502: /* controller search and initialization functions */
503:
504: __initfunc (static int gdth_search_eisa(ushort eisa_adr))
505: {
506: ulong id;
507:
508: TRACE(("gdth_search_eisa() adr. %x\n",eisa_adr));
509: id = inl(eisa_adr+ID0REG);
510: if (id == GDT3A_ID || id == GDT3B_ID) { /* GDT3000A or GDT3000B */
511: if ((inb(eisa_adr+EISAREG) & 8) == 0)
512: return 0; /* not EISA configured */
513: return 1;
514: }
515: if (id == GDT3_ID) /* GDT3000 */
516: return 1;
517:
518: return 0;
519: }
520:
521:
522: __initfunc (static int gdth_search_isa(ulong bios_adr))
523: {
524: void *addr;
525: ulong id;
526:
527: TRACE(("gdth_search_isa() bios adr. %lx\n",bios_adr));
528: if ((addr = gdth_mmap(bios_adr+BIOS_ID_OFFS, sizeof(ulong))) != NULL) {
529: id = readl(addr);
530: gdth_munmap(addr);
531: if (id == GDT2_ID) /* GDT2000 */
532: return 1;
533: }
534: return 0;
535: }
536:
537:
538: __initfunc (static int gdth_search_pci(ushort device_id,ushort index,gdth_pci_str *pcistr))
539: {
540: int error;
541: ulong base0,base1,base2;
542:
543: TRACE(("gdth_search_pci() device_id %d, index %d\n",
544: device_id,index));
545:
546: #if LINUX_VERSION_CODE >= 0x20155
547: if (!pci_present())
548: return 0;
549: #else
550: if (!pcibios_present())
551: return 0;
552: #endif
553:
554: if (pcibios_find_device(PCI_VENDOR_ID_VORTEX,device_id,index,
555: &pcistr->bus,&pcistr->device_fn))
556: return 0;
557:
558: /* GDT PCI controller found, now read resources from config space */
559: #if LINUX_VERSION_CODE >= 0x20155
560: {
561: struct pci_dev *pdev = pci_find_slot(pcistr->bus, pcistr->device_fn);
562: base0 = pdev->base_address[0];
563: base1 = pdev->base_address[1];
564: base2 = pdev->base_address[2];
565: if ((error = pcibios_read_config_dword(pcistr->bus,pcistr->device_fn,
566: PCI_ROM_ADDRESS,
567: (int *) &pcistr->bios))) {
568: printk("GDT-PCI: error %d reading configuration space", error);
569: return -1;
570: }
571: pcistr->irq = pdev->irq;
572: }
573: #else
574: #if LINUX_VERSION_CODE >= 0x010300
575: #define GDTH_BASEP (int *)
576: #else
577: #define GDTH_BASEP
578: #endif
579: if ((error = pcibios_read_config_dword(pcistr->bus,pcistr->device_fn,
580: PCI_BASE_ADDRESS_0,
581: GDTH_BASEP&base0)) ||
582: (error = pcibios_read_config_dword(pcistr->bus,pcistr->device_fn,
583: PCI_BASE_ADDRESS_1,
584: GDTH_BASEP&base1)) ||
585: (error = pcibios_read_config_dword(pcistr->bus,pcistr->device_fn,
586: PCI_BASE_ADDRESS_2,
587: GDTH_BASEP&base2)) ||
588: (error = pcibios_read_config_dword(pcistr->bus,pcistr->device_fn,
589: PCI_ROM_ADDRESS,
590: GDTH_BASEP&pcistr->bios)) ||
591: (error = pcibios_read_config_byte(pcistr->bus,pcistr->device_fn,
592: PCI_INTERRUPT_LINE,&pcistr->irq))) {
593: printk("GDT-PCI: error %d reading configuration space", error);
594: return -1;
595: }
596: #endif
597:
598: pcistr->device_id = device_id;
599: if (device_id <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000 or GDT6000B */
600: device_id >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) { /* MPR */
601: if ((base0 & PCI_BASE_ADDRESS_SPACE)!=PCI_BASE_ADDRESS_SPACE_MEMORY)
602: return -1;
603: pcistr->dpmem = base0 & PCI_BASE_ADDRESS_MEM_MASK;
604: } else { /* GDT6110, GDT6120, .. */
605: if ((base0 & PCI_BASE_ADDRESS_SPACE)!=PCI_BASE_ADDRESS_SPACE_MEMORY ||
606: (base2 & PCI_BASE_ADDRESS_SPACE)!=PCI_BASE_ADDRESS_SPACE_MEMORY ||
607: (base1 & PCI_BASE_ADDRESS_SPACE)!=PCI_BASE_ADDRESS_SPACE_IO)
608: return -1;
609: pcistr->dpmem = base2 & PCI_BASE_ADDRESS_MEM_MASK;
610: pcistr->io_mm = base0 & PCI_BASE_ADDRESS_MEM_MASK;
611: pcistr->io = base1 & PCI_BASE_ADDRESS_IO_MASK;
612: }
613: return 1;
614: }
615:
616:
617: __initfunc (static int gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha))
618: {
619: ulong retries,id;
620: unchar prot_ver,eisacf,i,irq_found;
621:
622: TRACE(("gdth_init_eisa() adr. %x\n",eisa_adr));
623:
624: /* disable board interrupts, deinitialize services */
625: outb(0xff,eisa_adr+EDOORREG);
626: outb(0x00,eisa_adr+EDENABREG);
627: outb(0x00,eisa_adr+EINTENABREG);
628:
629: outb(0xff,eisa_adr+LDOORREG);
630: retries = INIT_RETRIES;
631: gdth_delay(20);
632: while (inb(eisa_adr+EDOORREG) != 0xff) {
633: if (--retries == 0) {
634: printk("GDT-EISA: Initialization error (DEINIT failed)\n");
635: return 0;
636: }
637: gdth_delay(1);
638: TRACE2(("wait for DEINIT: retries=%ld\n",retries));
639: }
640: prot_ver = inb(eisa_adr+MAILBOXREG);
641: outb(0xff,eisa_adr+EDOORREG);
642: if (prot_ver != PROTOCOL_VERSION) {
643: printk("GDT-EISA: Illegal protocol version\n");
644: return 0;
645: }
646: ha->bmic = eisa_adr;
647: ha->brd_phys = (ulong)eisa_adr >> 12;
648:
649: outl(0,eisa_adr+MAILBOXREG);
650: outl(0,eisa_adr+MAILBOXREG+4);
651: outl(0,eisa_adr+MAILBOXREG+8);
652: outl(0,eisa_adr+MAILBOXREG+12);
653:
654: /* detect IRQ */
655: if ((id = inl(eisa_adr+ID0REG)) == GDT3_ID) {
656: ha->type = GDT_EISA;
657: ha->stype = id;
658: outl(1,eisa_adr+MAILBOXREG+8);
659: outb(0xfe,eisa_adr+LDOORREG);
660: retries = INIT_RETRIES;
661: gdth_delay(20);
662: while (inb(eisa_adr+EDOORREG) != 0xfe) {
663: if (--retries == 0) {
664: printk("GDT-EISA: Initialization error (get IRQ failed)\n");
665: return 0;
666: }
667: gdth_delay(1);
668: }
669: ha->irq = inb(eisa_adr+MAILBOXREG);
670: outb(0xff,eisa_adr+EDOORREG);
671: TRACE2(("GDT3000/3020: IRQ=%d\n",ha->irq));
672: /* check the result */
673: if (ha->irq == 0) {
674: TRACE2(("Unknown IRQ, check IRQ table from cmd line !\n"));
675: for (i=0,irq_found=FALSE; i<MAXHA && irqs[i]!=0xff; ++i) {
676: if (irqs[i]!=0) {
677: irq_found=TRUE;
678: break;
679: }
680: }
681: if (irq_found) {
682: ha->irq = irqs[i];
683: irqs[i] = 0;
684: printk("GDT-EISA: Can not detect controller IRQ,\n");
685: printk("Use IRQ setting from command line (IRQ = %d)\n",
686: ha->irq);
687: } else {
688: printk("GDT-EISA: Initialization error (unknown IRQ), Enable\n");
689: printk("the controller BIOS or use command line parameters\n");
690: return 0;
691: }
692: }
693: } else {
694: eisacf = inb(eisa_adr+EISAREG) & 7;
695: if (eisacf > 4) /* level triggered */
696: eisacf -= 4;
697: ha->irq = gdth_irq_tab[eisacf];
698: ha->type = GDT_EISA;
699: ha->stype= id;
700: }
701: return 1;
702: }
703:
704:
705: __initfunc (static int gdth_init_isa(ulong bios_adr,gdth_ha_str *ha))
706: {
707: register gdt2_dpram_str *dp2_ptr;
708: int i;
709: unchar irq_drq,prot_ver;
710: ulong retries;
711:
712: TRACE(("gdth_init_isa() bios adr. %lx\n",bios_adr));
713:
714: ha->brd = gdth_mmap(bios_adr, sizeof(gdt2_dpram_str));
715: if (ha->brd == NULL) {
716: printk("GDT-ISA: Initialization error (DPMEM remap error)\n");
717: return 0;
718: }
719: dp2_ptr = (gdt2_dpram_str *)ha->brd;
720: writeb(1, &dp2_ptr->io.memlock); /* switch off write protection */
721: /* reset interface area */
722: memset_io((char *)&dp2_ptr->u,0,sizeof(dp2_ptr->u));
723: if (readl(&dp2_ptr->u) != 0) {
724: printk("GDT-PCI: Initialization error (DPMEM write error)\n");
725: gdth_munmap(ha->brd);
726: return 0;
727: }
728:
729: /* disable board interrupts, read DRQ and IRQ */
730: writeb(0xff, &dp2_ptr->io.irqdel);
731: writeb(0x00, &dp2_ptr->io.irqen);
732: writeb(0x00, &dp2_ptr->u.ic.S_Status);
733: writeb(0x00, &dp2_ptr->u.ic.Cmd_Index);
734:
735: irq_drq = readb(&dp2_ptr->io.rq);
736: for (i=0; i<3; ++i) {
737: if ((irq_drq & 1)==0)
738: break;
739: irq_drq >>= 1;
740: }
741: ha->drq = gdth_drq_tab[i];
742:
743: irq_drq = readb(&dp2_ptr->io.rq) >> 3;
744: for (i=1; i<5; ++i) {
745: if ((irq_drq & 1)==0)
746: break;
747: irq_drq >>= 1;
748: }
749: ha->irq = gdth_irq_tab[i];
750:
751: /* deinitialize services */
752: writel(bios_adr, &dp2_ptr->u.ic.S_Info[0]);
753: writeb(0xff, &dp2_ptr->u.ic.S_Cmd_Indx);
754: writeb(0, &dp2_ptr->io.event);
755: retries = INIT_RETRIES;
756: gdth_delay(20);
757: while (readb(&dp2_ptr->u.ic.S_Status) != 0xff) {
758: if (--retries == 0) {
759: printk("GDT-ISA: Initialization error (DEINIT failed)\n");
760: gdth_munmap(ha->brd);
761: return 0;
762: }
763: gdth_delay(1);
764: }
765: prot_ver = (unchar)readl(&dp2_ptr->u.ic.S_Info[0]);
766: writeb(0, &dp2_ptr->u.ic.Status);
767: writeb(0xff, &dp2_ptr->io.irqdel);
768: if (prot_ver != PROTOCOL_VERSION) {
769: printk("GDT-ISA: Illegal protocol version\n");
770: gdth_munmap(ha->brd);
771: return 0;
772: }
773:
774: ha->type = GDT_ISA;
775: ha->ic_all_size = sizeof(dp2_ptr->u);
776: ha->stype= GDT2_ID;
777: ha->brd_phys = bios_adr >> 4;
778:
779: /* special request to controller BIOS */
780: writel(0x00, &dp2_ptr->u.ic.S_Info[0]);
781: writel(0x00, &dp2_ptr->u.ic.S_Info[1]);
782: writel(0x01, &dp2_ptr->u.ic.S_Info[2]);
783: writel(0x00, &dp2_ptr->u.ic.S_Info[3]);
784: writeb(0xfe, &dp2_ptr->u.ic.S_Cmd_Indx);
785: writeb(0, &dp2_ptr->io.event);
786: retries = INIT_RETRIES;
787: gdth_delay(20);
788: while (readb(&dp2_ptr->u.ic.S_Status) != 0xfe) {
789: if (--retries == 0) {
790: printk("GDT-ISA: Initialization error\n");
791: gdth_munmap(ha->brd);
792: return 0;
793: }
794: gdth_delay(1);
795: }
796: writeb(0, &dp2_ptr->u.ic.Status);
797: writeb(0xff, &dp2_ptr->io.irqdel);
798: return 1;
799: }
800:
801:
802: __initfunc (static int gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha))
803: {
804: register gdt6_dpram_str *dp6_ptr;
805: register gdt6c_dpram_str *dp6c_ptr;
806: register gdt6m_dpram_str *dp6m_ptr;
807: ulong retries;
808: unchar prot_ver;
809: int i, found = FALSE;
810:
811: TRACE(("gdth_init_pci()\n"));
812:
813: ha->brd_phys = (pcistr->bus << 8) | (pcistr->device_fn & 0xf8);
814: ha->stype = (ulong)pcistr->device_id;
815: ha->irq = pcistr->irq;
816:
817: if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6000B) { /* GDT6000 or GDT6000B */
818: TRACE2(("init_pci() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq));
819: ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6_dpram_str));
820: if (ha->brd == NULL) {
821: printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
822: return 0;
823: }
824: dp6_ptr = (gdt6_dpram_str *)ha->brd;
825: /* reset interface area */
826: memset_io((char *)&dp6_ptr->u,0,sizeof(dp6_ptr->u));
827: if (readl(&dp6_ptr->u) != 0) {
828: printk("GDT-PCI: Initialization error (DPMEM write error)\n");
829: gdth_munmap(ha->brd);
830: return 0;
831: }
832:
833: /* disable board interrupts, deinit services */
834: writeb(0xff, &dp6_ptr->io.irqdel);
835: writeb(0x00, &dp6_ptr->io.irqen);;
836: writeb(0x00, &dp6_ptr->u.ic.S_Status);
837: writeb(0x00, &dp6_ptr->u.ic.Cmd_Index);
838:
839: writel(pcistr->dpmem, &dp6_ptr->u.ic.S_Info[0]);
840: writeb(0xff, &dp6_ptr->u.ic.S_Cmd_Indx);
841: writeb(0, &dp6_ptr->io.event);
842: retries = INIT_RETRIES;
843: gdth_delay(20);
844: while (readb(&dp6_ptr->u.ic.S_Status) != 0xff) {
845: if (--retries == 0) {
846: printk("GDT-PCI: Initialization error (DEINIT failed)\n");
847: gdth_munmap(ha->brd);
848: return 0;
849: }
850: gdth_delay(1);
851: }
852: prot_ver = (unchar)readl(&dp6_ptr->u.ic.S_Info[0]);
853: writeb(0, &dp6_ptr->u.ic.S_Status);
854: writeb(0xff, &dp6_ptr->io.irqdel);
855: if (prot_ver != PROTOCOL_VERSION) {
856: printk("GDT-PCI: Illegal protocol version\n");
857: gdth_munmap(ha->brd);
858: return 0;
859: }
860:
861: ha->type = GDT_PCI;
862: ha->ic_all_size = sizeof(dp6_ptr->u);
863:
864: /* special command to controller BIOS */
865: writel(0x00, &dp6_ptr->u.ic.S_Info[0]);
866: writel(0x00, &dp6_ptr->u.ic.S_Info[1]);
867: writel(0x01, &dp6_ptr->u.ic.S_Info[2]);
868: writel(0x00, &dp6_ptr->u.ic.S_Info[3]);
869: writeb(0xfe, &dp6_ptr->u.ic.S_Cmd_Indx);
870: writeb(0, &dp6_ptr->io.event);
871: retries = INIT_RETRIES;
872: gdth_delay(20);
873: while (readb(&dp6_ptr->u.ic.S_Status) != 0xfe) {
874: if (--retries == 0) {
875: printk("GDT-PCI: Initialization error\n");
876: gdth_munmap(ha->brd);
877: return 0;
878: }
879: gdth_delay(1);
880: }
881: writeb(0, &dp6_ptr->u.ic.S_Status);
882: writeb(0xff, &dp6_ptr->io.irqdel);
883:
884: } else if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6555) { /* GDT6110, GDT6120, .. */
885: ha->plx = (gdt6c_plx_regs *)pcistr->io;
886: TRACE2(("init_pci_new() dpmem %lx io %lx irq %d\n",
887: pcistr->dpmem,(ulong)ha->plx,ha->irq));
888: ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6c_dpram_str));
889: if (ha->brd == NULL) {
890: printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
891: gdth_munmap(ha->brd);
892: return 0;
893: }
894: dp6c_ptr = (gdt6c_dpram_str *)ha->brd;
895: /* reset interface area */
896: memset_io((char *)&dp6c_ptr->u,0,sizeof(dp6c_ptr->u));
897: if (readl(&dp6c_ptr->u) != 0) {
898: printk("GDT-PCI: Initialization error (DPMEM write error)\n");
899: gdth_munmap(ha->brd);
900: return 0;
901: }
902:
903: /* disable board interrupts, deinit services */
904: outb(0x00,PTR2USHORT(&ha->plx->control1));
905: outb(0xff,PTR2USHORT(&ha->plx->edoor_reg));
906:
907: writeb(0x00, &dp6c_ptr->u.ic.S_Status);
908: writeb(0x00, &dp6c_ptr->u.ic.Cmd_Index);
909:
910: writel(pcistr->dpmem, &dp6c_ptr->u.ic.S_Info[0]);
911: writeb(0xff, &dp6c_ptr->u.ic.S_Cmd_Indx);
912:
913: outb(1,PTR2USHORT(&ha->plx->ldoor_reg));
914:
915: retries = INIT_RETRIES;
916: gdth_delay(20);
917: while (readb(&dp6c_ptr->u.ic.S_Status) != 0xff) {
918: if (--retries == 0) {
919: printk("GDT-PCI: Initialization error (DEINIT failed)\n");
920: gdth_munmap(ha->brd);
921: return 0;
922: }
923: gdth_delay(1);
924: }
925: prot_ver = (unchar)readl(&dp6c_ptr->u.ic.S_Info[0]);
926: writeb(0, &dp6c_ptr->u.ic.Status);
927: if (prot_ver != PROTOCOL_VERSION) {
928: printk("GDT-PCI: Illegal protocol version\n");
929: gdth_munmap(ha->brd);
930: return 0;
931: }
932:
933: ha->type = GDT_PCINEW;
934: ha->ic_all_size = sizeof(dp6c_ptr->u);
935:
936: /* special command to controller BIOS */
937: writel(0x00, &dp6c_ptr->u.ic.S_Info[0]);
938: writel(0x00, &dp6c_ptr->u.ic.S_Info[1]);
939: writel(0x01, &dp6c_ptr->u.ic.S_Info[2]);
940: writel(0x00, &dp6c_ptr->u.ic.S_Info[3]);
941: writeb(0xfe, &dp6c_ptr->u.ic.S_Cmd_Indx);
942:
943: outb(1,PTR2USHORT(&ha->plx->ldoor_reg));
944:
945: retries = INIT_RETRIES;
946: gdth_delay(20);
947: while (readb(&dp6c_ptr->u.ic.S_Status) != 0xfe) {
948: if (--retries == 0) {
949: printk("GDT-PCI: Initialization error\n");
950: gdth_munmap(ha->brd);
951: return 0;
952: }
953: gdth_delay(1);
954: }
955: writeb(0, &dp6c_ptr->u.ic.S_Status);
956:
957: } else { /* MPR */
958: TRACE2(("init_pci_mpr() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq));
959: ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6m_dpram_str));
960: if (ha->brd == NULL) {
961: printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
962: return 0;
963: }
964:
965: /* check and reset interface area */
966: dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
967: writel(DPMEM_MAGIC, &dp6m_ptr->u);
968: if (readl(&dp6m_ptr->u) != DPMEM_MAGIC) {
969: printk("GDT-PCI: Cannot access DPMEM at 0x%x (shadowed?)\n",
970: (int)ha->brd);
971: found = FALSE;
972: for (i = 0xC8000; i < 0xE8000; i += 0x4000) {
973: pcibios_write_config_dword( pcistr->bus, pcistr->device_fn,
974: PCI_BASE_ADDRESS_0, i );
975: gdth_munmap( ha->brd );
976: ha->brd = gdth_mmap(i, sizeof(gdt6m_dpram_str));
977: if (ha->brd == NULL) {
978: printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
979: return 0;
980: }
981: dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
982: writel(DPMEM_MAGIC, &dp6m_ptr->u);
983: if (readl(&dp6m_ptr->u) == DPMEM_MAGIC) {
984: printk("GDT-PCI: Use free address at 0x%x\n",
985: (int)ha->brd);
986: found = TRUE;
987: break;
988: }
989: }
990: if (!found) {
991: printk("GDT-PCI: No free address found!\n");
992: gdth_munmap( ha->brd );
993: return 0;
994: }
995: }
996: memset_io((char *)&dp6m_ptr->u,0,sizeof(dp6m_ptr->u));
997:
998: /* disable board interrupts, deinit services */
999: writeb(readb(&dp6m_ptr->i960r.edoor_en_reg) | 4,
1000: &dp6m_ptr->i960r.edoor_en_reg);
1001: writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
1002: writeb(0x00, &dp6m_ptr->u.ic.S_Status);
1003: writeb(0x00, &dp6m_ptr->u.ic.Cmd_Index);
1004:
1005: writel(pcistr->dpmem, &dp6m_ptr->u.ic.S_Info[0]);
1006: writeb(0xff, &dp6m_ptr->u.ic.S_Cmd_Indx);
1007: writeb(1, &dp6m_ptr->i960r.ldoor_reg);
1008: retries = INIT_RETRIES;
1009: gdth_delay(20);
1010: while (readb(&dp6m_ptr->u.ic.S_Status) != 0xff) {
1011: if (--retries == 0) {
1012: printk("GDT-PCI: Initialization error (DEINIT failed)\n");
1013: gdth_munmap(ha->brd);
1014: return 0;
1015: }
1016: gdth_delay(1);
1017: }
1018: prot_ver = (unchar)readl(&dp6m_ptr->u.ic.S_Info[0]);
1019: writeb(0, &dp6m_ptr->u.ic.S_Status);
1020: if (prot_ver != PROTOCOL_VERSION) {
1021: printk("GDT-PCI: Illegal protocol version\n");
1022: gdth_munmap(ha->brd);
1023: return 0;
1024: }
1025:
1026: ha->type = GDT_PCIMPR;
1027: ha->ic_all_size = sizeof(dp6m_ptr->u);
1028:
1029: /* special command to controller BIOS */
1030: writel(0x00, &dp6m_ptr->u.ic.S_Info[0]);
1031: writel(0x00, &dp6m_ptr->u.ic.S_Info[1]);
1032: writel(0x01, &dp6m_ptr->u.ic.S_Info[2]);
1033: writel(0x00, &dp6m_ptr->u.ic.S_Info[3]);
1034: writeb(0xfe, &dp6m_ptr->u.ic.S_Cmd_Indx);
1035: writeb(1, &dp6m_ptr->i960r.ldoor_reg);
1036: retries = INIT_RETRIES;
1037: gdth_delay(20);
1038: while (readb(&dp6m_ptr->u.ic.S_Status) != 0xfe) {
1039: if (--retries == 0) {
1040: printk("GDT-PCI: Initialization error\n");
1041: gdth_munmap(ha->brd);
1042: return 0;
1043: }
1044: gdth_delay(1);
1045: }
1046: writeb(0, &dp6m_ptr->u.ic.S_Status);
1047: }
1048:
1049: return 1;
1050: }
1051:
1052:
1053: /* controller protocol functions */
1054:
1055: __initfunc (static void gdth_enable_int(int hanum))
1056: {
1057: gdth_ha_str *ha;
1058: ulong flags;
1059: gdt2_dpram_str *dp2_ptr;
1060: gdt6_dpram_str *dp6_ptr;
1061: gdt6m_dpram_str *dp6m_ptr;
1062:
1063: TRACE(("gdth_enable_int() hanum %d\n",hanum));
1064: ha = HADATA(gdth_ctr_tab[hanum]);
1065:
1066: save_flags(flags);
1067: cli();
1068:
1069: if (ha->type == GDT_EISA) {
1070: outb(0xff, ha->bmic + EDOORREG);
1071: outb(0xff, ha->bmic + EDENABREG);
1072: outb(0x01, ha->bmic + EINTENABREG);
1073: } else if (ha->type == GDT_ISA) {
1074: dp2_ptr = (gdt2_dpram_str *)ha->brd;
1075: writeb(1, &dp2_ptr->io.irqdel);
1076: writeb(0, &dp2_ptr->u.ic.Cmd_Index);
1077: writeb(1, &dp2_ptr->io.irqen);
1078: } else if (ha->type == GDT_PCI) {
1079: dp6_ptr = (gdt6_dpram_str *)ha->brd;
1080: writeb(1, &dp6_ptr->io.irqdel);
1081: writeb(0, &dp6_ptr->u.ic.Cmd_Index);
1082: writeb(1, &dp6_ptr->io.irqen);
1083: } else if (ha->type == GDT_PCINEW) {
1084: outb(0xff, PTR2USHORT(&ha->plx->edoor_reg));
1085: outb(0x03, PTR2USHORT(&ha->plx->control1));
1086: } else if (ha->type == GDT_PCIMPR) {
1087: dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
1088: writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
1089: writeb(readb(&dp6m_ptr->i960r.edoor_en_reg) & ~4,
1090: &dp6m_ptr->i960r.edoor_en_reg);
1091: }
1092: restore_flags(flags);
1093: }
1094:
1095:
1096: static int gdth_get_status(unchar *pIStatus,int irq)
1097: {
1098: register gdth_ha_str *ha;
1099: int i;
1100:
1101: TRACE(("gdth_get_status() irq %d ctr_count %d\n",
1102: irq,gdth_ctr_count));
1103:
1104: *pIStatus = 0;
1105: for (i=0; i<gdth_ctr_count; ++i) {
1106: ha = HADATA(gdth_ctr_tab[i]);
1107: if (ha->irq != (unchar)irq) /* check IRQ */
1108: continue;
1109: if (ha->type == GDT_EISA)
1110: *pIStatus = inb((ushort)ha->bmic + EDOORREG);
1111: else if (ha->type == GDT_ISA)
1112: *pIStatus = readb(&((gdt2_dpram_str *)ha->brd)->u.ic.Cmd_Index);
1113: else if (ha->type == GDT_PCI)
1114: *pIStatus = readb(&((gdt6_dpram_str *)ha->brd)->u.ic.Cmd_Index);
1115: else if (ha->type == GDT_PCINEW)
1116: *pIStatus = inb(PTR2USHORT(&ha->plx->edoor_reg));
1117: else if (ha->type == GDT_PCIMPR)
1118: *pIStatus = readb(&((gdt6m_dpram_str *)ha->brd)->i960r.edoor_reg);
1119:
1120: if (*pIStatus)
1121: return i; /* board found */
1122: }
1123: return -1;
1124: }
1125:
1126:
1127: static int gdth_test_busy(int hanum)
1128: {
1129: register gdth_ha_str *ha;
1130: register int gdtsema0 = 0;
1131:
1132: TRACE(("gdth_test_busy() hanum %d\n",hanum));
1133:
1134: ha = HADATA(gdth_ctr_tab[hanum]);
1135: if (ha->type == GDT_EISA)
1136: gdtsema0 = (int)inb(ha->bmic + SEMA0REG);
1137: else if (ha->type == GDT_ISA)
1138: gdtsema0 = (int)readb(&((gdt2_dpram_str *)ha->brd)->u.ic.Sema0);
1139: else if (ha->type == GDT_PCI)
1140: gdtsema0 = (int)readb(&((gdt6_dpram_str *)ha->brd)->u.ic.Sema0);
1141: else if (ha->type == GDT_PCINEW)
1142: gdtsema0 = (int)inb(PTR2USHORT(&ha->plx->sema0_reg));
1143: else if (ha->type == GDT_PCIMPR)
1144: gdtsema0 = (int)readb(&((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg);
1145:
1146: return (gdtsema0 & 1);
1147: }
1148:
1149:
1150: static int gdth_get_cmd_index(int hanum)
1151: {
1152: register gdth_ha_str *ha;
1153: int i;
1154:
1155: TRACE(("gdth_get_cmd_index() hanum %d\n",hanum));
1156:
1157: ha = HADATA(gdth_ctr_tab[hanum]);
1158: for (i=0; i<GDTH_MAXCMDS; ++i) {
1159: if (gdth_cmd_tab[i][hanum].cmnd == UNUSED_CMND) {
1160: gdth_cmd_tab[i][hanum].cmnd = ha->pccb->RequestBuffer;
1161: gdth_cmd_tab[i][hanum].service = ha->pccb->Service;
1162: ha->pccb->CommandIndex = (ulong)i+2;
1163: return (i+2);
1164: }
1165: }
1166: return 0;
1167: }
1168:
1169:
1170: static void gdth_set_sema0(int hanum)
1171: {
1172: register gdth_ha_str *ha;
1173:
1174: TRACE(("gdth_set_sema0() hanum %d\n",hanum));
1175:
1176: ha = HADATA(gdth_ctr_tab[hanum]);
1177: if (ha->type == GDT_EISA)
1178: outb(1, ha->bmic + SEMA0REG);
1179: else if (ha->type == GDT_ISA)
1180: writeb(1, &((gdt2_dpram_str *)ha->brd)->u.ic.Sema0);
1181: else if (ha->type == GDT_PCI)
1182: writeb(1, &((gdt6_dpram_str *)ha->brd)->u.ic.Sema0);
1183: else if (ha->type == GDT_PCINEW)
1184: outb(1, PTR2USHORT(&ha->plx->sema0_reg));
1185: else if (ha->type == GDT_PCIMPR)
1186: writeb(1, &((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg);
1187:
1188: }
1189:
1190:
1191: static void gdth_copy_command(int hanum)
1192: {
1193: register gdth_ha_str *ha;
1194: register gdth_cmd_str *cmd_ptr;
1195: register gdt6m_dpram_str *dp6m_ptr;
1196: register gdt6c_dpram_str *dp6c_ptr;
1197: gdt6_dpram_str *dp6_ptr;
1198: gdt2_dpram_str *dp2_ptr;
1199: ushort cp_count,dp_offset,cmd_no;
1200:
1201: TRACE(("gdth_copy_command() hanum %d\n",hanum));
1202:
1203: ha = HADATA(gdth_ctr_tab[hanum]);
1204: cp_count = ha->cmd_len;
1205: dp_offset= ha->cmd_offs_dpmem;
1206: cmd_no = ha->cmd_cnt;
1207: cmd_ptr = ha->pccb;
1208:
1209: ++ha->cmd_cnt;
1210: if (ha->type == GDT_EISA)
1211: return; /* no DPMEM, no copy */
1212:
1213: /* set cpcount dword aligned */
1214: if (cp_count & 3)
1215: cp_count += (4 - (cp_count & 3));
1216:
1217: ha->cmd_offs_dpmem += cp_count;
1218:
1219: /* set offset and service, copy command to DPMEM */
1220: if (ha->type == GDT_ISA) {
1221: dp2_ptr = (gdt2_dpram_str *)ha->brd;
1222: writew(dp_offset + DPMEM_COMMAND_OFFSET,
1223: &dp2_ptr->u.ic.comm_queue[cmd_no].offset);
1224: writew((ushort)cmd_ptr->Service,
1225: &dp2_ptr->u.ic.comm_queue[cmd_no].serv_id);
1226: memcpy_toio(&dp2_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
1227: } else if (ha->type == GDT_PCI) {
1228: dp6_ptr = (gdt6_dpram_str *)ha->brd;
1229: writew(dp_offset + DPMEM_COMMAND_OFFSET,
1230: &dp6_ptr->u.ic.comm_queue[cmd_no].offset);
1231: writew((ushort)cmd_ptr->Service,
1232: &dp6_ptr->u.ic.comm_queue[cmd_no].serv_id);
1233: memcpy_toio(&dp6_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
1234: } else if (ha->type == GDT_PCINEW) {
1235: dp6c_ptr = (gdt6c_dpram_str *)ha->brd;
1236: writew(dp_offset + DPMEM_COMMAND_OFFSET,
1237: &dp6c_ptr->u.ic.comm_queue[cmd_no].offset);
1238: writew((ushort)cmd_ptr->Service,
1239: &dp6c_ptr->u.ic.comm_queue[cmd_no].serv_id);
1240: memcpy_toio(&dp6c_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
1241: } else if (ha->type == GDT_PCIMPR) {
1242: dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
1243: writew(dp_offset + DPMEM_COMMAND_OFFSET,
1244: &dp6m_ptr->u.ic.comm_queue[cmd_no].offset);
1245: writew((ushort)cmd_ptr->Service,
1246: &dp6m_ptr->u.ic.comm_queue[cmd_no].serv_id);
1247: memcpy_toio(&dp6m_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
1248: }
1249: }
1250:
1251:
1252: static void gdth_release_event(int hanum)
1253: {
1254: register gdth_ha_str *ha;
1255:
1256: #ifdef GDTH_STATISTICS
1257: ulong i,j;
1258: for (i=0,j=0; j<GDTH_MAXCMDS; ++j) {
1259: if (gdth_cmd_tab[j][hanum].cmnd != UNUSED_CMND)
1260: ++i;
1261: }
1262: if (max_index < i) {
1263: max_index = i;
1264: TRACE3(("GDT: max_index = %d\n",(ushort)i));
1265: }
1266: #endif
1267:
1268: TRACE(("gdth_release_event() hanum %d\n",hanum));
1269: ha = HADATA(gdth_ctr_tab[hanum]);
1270:
1271: if (ha->pccb->OpCode == GDT_INIT)
1272: ha->pccb->Service |= 0x80;
1273:
1274: if (ha->type == GDT_EISA) {
1275: outb(ha->pccb->Service, ha->bmic + LDOORREG);
1276: if (ha->pccb->OpCode == GDT_INIT) /* store DMA buffer */
1277: outl((ulong)ha->pccb, ha->bmic + MAILBOXREG);
1278: } else if (ha->type == GDT_ISA)
1279: writeb(0, &((gdt2_dpram_str *)ha->brd)->io.event);
1280: else if (ha->type == GDT_PCI)
1281: writeb(0, &((gdt6_dpram_str *)ha->brd)->io.event);
1282: else if (ha->type == GDT_PCINEW)
1283: outb(1, PTR2USHORT(&ha->plx->ldoor_reg));
1284: else if (ha->type == GDT_PCIMPR)
1285: writeb(1, &((gdt6m_dpram_str *)ha->brd)->i960r.ldoor_reg);
1286: }
1287:
1288:
1289: static int gdth_wait(int hanum,int index,ulong time)
1290: {
1291: gdth_ha_str *ha;
1292: int answer_found = FALSE;
1293:
1294: TRACE(("gdth_wait() hanum %d index %d time %ld\n",hanum,index,time));
1295:
1296: ha = HADATA(gdth_ctr_tab[hanum]);
1297: if (index == 0)
1298: return 1; /* no wait required */
1299:
1300: gdth_from_wait = TRUE;
1301: do {
1302: #if LINUX_VERSION_CODE >= 0x010346
1303: gdth_interrupt((int)ha->irq,NULL,NULL);
1304: #else
1305: gdth_interrupt((int)ha->irq,NULL);
1306: #endif
1307: if (wait_hanum==hanum && wait_index==index) {
1308: answer_found = TRUE;
1309: break;
1310: }
1311: gdth_delay(1);
1312: } while (--time);
1313: gdth_from_wait = FALSE;
1314:
1315: while (gdth_test_busy(hanum))
1316: gdth_delay(0);
1317:
1318: return (answer_found);
1319: }
1320:
1321:
1322: static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong p1,
1323: ulong p2,ulong p3)
1324: {
1325: register gdth_ha_str *ha;
1326: register gdth_cmd_str *cmd_ptr;
1327: int retries,index;
1328:
1329: TRACE2(("gdth_internal_cmd() service %d opcode %d\n",service,opcode));
1330:
1331: ha = HADATA(gdth_ctr_tab[hanum]);
1332: cmd_ptr = ha->pccb;
1333: memset((char*)cmd_ptr,0,sizeof(gdth_cmd_str));
1334:
1335: /* make command */
1336: for (retries = INIT_RETRIES;;) {
1337: cmd_ptr->Service = service;
1338: cmd_ptr->RequestBuffer = INTERNAL_CMND;
1339: if (!(index=gdth_get_cmd_index(hanum))) {
1340: TRACE(("GDT: No free command index found\n"));
1341: return 0;
1342: }
1343: gdth_set_sema0(hanum);
1344: cmd_ptr->OpCode = opcode;
1345: cmd_ptr->BoardNode = LOCALBOARD;
1346: if (service == CACHESERVICE) {
1347: if (opcode == GDT_IOCTL) {
1348: cmd_ptr->u.ioctl.subfunc = p1;
1349: cmd_ptr->u.ioctl.channel = p2;
1350: cmd_ptr->u.ioctl.param_size = (ushort)p3;
1351: cmd_ptr->u.ioctl.p_param = virt_to_bus(ha->pscratch);
1352: } else {
1353: cmd_ptr->u.cache.DeviceNo = (ushort)p1;
1354: cmd_ptr->u.cache.BlockNo = p2;
1355: }
1356: } else if (service == SCSIRAWSERVICE) {
1357: cmd_ptr->u.raw.direction = p1;
1358: cmd_ptr->u.raw.bus = (unchar)p2;
1359: cmd_ptr->u.raw.target = (unchar)p3;
1360: cmd_ptr->u.raw.lun = 0;
1361: }
1362: ha->cmd_len = sizeof(gdth_cmd_str);
1363: ha->cmd_offs_dpmem = 0;
1364: ha->cmd_cnt = 0;
1365: gdth_copy_command(hanum);
1366: gdth_release_event(hanum);
1367: gdth_delay(20);
1368: if (!gdth_wait(hanum,index,INIT_TIMEOUT)) {
1369: printk("GDT: Initialization error (timeout service %d)\n",service);
1370: return 0;
1371: }
1372: if (ha->status != S_BSY || --retries == 0)
1373: break;
1374: gdth_delay(1);
1375: }
1376:
1377: return (ha->status != S_OK ? 0:1);
1378: }
1379:
1380:
1381: /* search for devices */
1382:
1383: __initfunc (static int gdth_search_drives(int hanum))
1384: {
1385: register gdth_ha_str *ha;
1386: ushort cdev_cnt,i;
1387: unchar b,t,pos_found;
1388: ulong drv_cyls, drv_hds, drv_secs;
1389: ulong bus_no;
1390: gdth_getch_str *chn;
1391: gdth_iochan_str *ioc;
1392:
1393: TRACE(("gdth_search_drives() hanum %d\n",hanum));
1394: ha = HADATA(gdth_ctr_tab[hanum]);
1395:
1396: /* initialize controller services, at first: screen service */
1397: if (!gdth_internal_cmd(hanum,SCREENSERVICE,GDT_INIT,0,0,0)) {
1398: printk("GDT: Initialization error screen service (code %d)\n",
1399: ha->status);
1400: return 0;
1401: }
1402: TRACE2(("gdth_search_drives(): SCREENSERVICE initialized\n"));
1403:
1404: /* initialize cache service */
1405: if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_INIT,LINUX_OS,0,0)) {
1406: printk("GDT: Initialization error cache service (code %d)\n",
1407: ha->status);
1408: return 0;
1409: }
1410: TRACE2(("gdth_search_drives(): CACHESERVICE initialized\n"));
1411: cdev_cnt = (ushort)ha->info;
1412:
1413: /* mount all cache devices */
1414: gdth_internal_cmd(hanum,CACHESERVICE,GDT_MOUNT,0xffff,1,0);
1415: TRACE2(("gdth_search_drives(): mountall CACHESERVICE OK\n"));
1416:
1417: /* initialize cache service after mountall */
1418: if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_INIT,LINUX_OS,0,0)) {
1419: printk("GDT: Initialization error cache service (code %d)\n",
1420: ha->status);
1421: return 0;
1422: }
1423: TRACE2(("gdth_search_drives() CACHES. init. after mountall\n"));
1424: cdev_cnt = (ushort)ha->info;
1425:
1426: /* detect number of SCSI buses - try new IOCTL */
1427: ioc = (gdth_iochan_str *)DMADATA(gdth_ctr_tab[hanum]);
1428: ioc->version = -1UL;
1429: ioc->list_entries = MAXBUS;
1430: ioc->first_chan = 0;
1431: ioc->last_chan = MAXBUS-1;
1432: ioc->list_offset = GDTOFFSOF(gdth_iochan_str, list[0]);
1433: if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,GET_IOCHAN_DESC,
1434: INVALID_CHANNEL,sizeof(gdth_iochan_str))) {
1435: TRACE2(("GET_IOCHAN_DESC supported!\n"));
1436: ha->bus_cnt = ioc->chan_count;
1437: for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no)
1438: if (ioc->list[bus_no].proc_id < MAXID)
1439: ha->id[bus_no][ioc->list[bus_no].proc_id].type = SIOP_DTYP;
1440: } else {
1441: /* old method */
1442: chn = (gdth_getch_str *)DMADATA(gdth_ctr_tab[hanum]);
1443: for (bus_no = 0; bus_no < MAXBUS; ++bus_no) {
1444: chn->channel_no = bus_no;
1445: if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
1446: SCSI_CHAN_CNT | L_CTRL_PATTERN,
1447: IO_CHANNEL | INVALID_CHANNEL,
1448: sizeof(gdth_getch_str))) {
1449: if (bus_no == 0) {
1450: printk("GDT: Error detecting SCSI channel count (0x%x)\n",
1451: ha->status);
1452: return 0;
1453: }
1454: break;
1455: }
1456: if (chn->siop_id < MAXID)
1457: ha->id[bus_no][chn->siop_id].type = SIOP_DTYP;
1458: }
1459: ha->bus_cnt = (unchar)bus_no;
1460: }
1461: TRACE2(("gdth_search_drives() %d SCSI channels\n",ha->bus_cnt));
1462:
1463: /* read cache configuration */
1464: if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,CACHE_INFO,
1465: INVALID_CHANNEL,sizeof(gdth_cinfo_str))) {
1466: printk("GDT: Initialization error cache service (code %d)\n",
1467: ha->status);
1468: return 0;
1469: }
1470: ha->cpar = ((gdth_cinfo_str *)DMADATA(gdth_ctr_tab[hanum]))->cpar;
1471: TRACE2(("gdth_search_drives() cinfo: vs %lx sta %d str %d dw %d b %d\n",
1472: ha->cpar.version,ha->cpar.state,ha->cpar.strategy,
1473: ha->cpar.write_back,ha->cpar.block_size));
1474:
1475: /* read board info, fill ctr_name[] */
1476: if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,BOARD_INFO,
1477: INVALID_CHANNEL,sizeof(gdth_binfo_str))) {
1478: TRACE2(("BOARD_INFO supported!\n"));
1479: strcpy(ha->ctr_name, ((gdth_binfo_str *)DMADATA(gdth_ctr_tab[hanum]))->type_string);
1480: } else {
1481: strcpy(ha->ctr_name, gdth_ctr_name(hanum));
1482: }
1483: TRACE2(("Controller name: %s\n",ha->ctr_name));
1484:
1485: /* initialize raw service */
1486: if (!gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_INIT,0,0,0)) {
1487: printk("GDT: Initialization error raw service (code %d)\n",
1488: ha->status);
1489: return 0;
1490: }
1491: TRACE2(("gdth_search_drives(): RAWSERVICE initialized\n"));
1492:
1493: /* set/get features raw service (scatter/gather) */
1494: ha->raw_feat = 0;
1495: if (gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_SET_FEAT,SCATTER_GATHER,
1496: 0,0)) {
1497: TRACE2(("gdth_search_drives(): set features RAWSERVICE OK\n"));
1498: if (gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_GET_FEAT,0,0,0)) {
1499: TRACE2(("gdth_search_dr(): get feat RAWSERVICE %ld\n",
1500: ha->info));
1501: ha->raw_feat = (ushort)ha->info;
1502: }
1503: }
1504:
1505: /* set/get features cache service (equal to raw service) */
1506: if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_SET_FEAT,0,
1507: SCATTER_GATHER,0)) {
1508: TRACE2(("gdth_search_drives(): set features CACHESERVICE OK\n"));
1509: if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_GET_FEAT,0,0,0)) {
1510: TRACE2(("gdth_search_dr(): get feat CACHESERV. %ld\n",
1511: ha->info));
1512: ha->cache_feat = (ushort)ha->info;
1513: }
1514: }
1515:
1516: /* reserve drives for raw service */
1517: for (i = 0; reserve_list[i].hanum != 0xff; ++i) {
1518: if (reserve_list[i].hanum < MAXHA && reserve_list[i].hanum == hanum &&
1519: reserve_list[i].bus < MAXBUS && reserve_list[i].id < MAXID) {
1520: TRACE2(("gdth_search_drives(): reserve ha %d bus %d id %d\n",
1521: reserve_list[i].hanum, reserve_list[i].bus,
1522: reserve_list[i].id));
1523: if (!gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_RESERVE,0,
1524: reserve_list[i].bus, reserve_list[i].id)) {
1525: printk("GDT: Error raw service (RESERVE, code %d)\n",
1526: ha->status);
1527: }
1528: }
1529: }
1530:
1531: /* scanning for raw devices */
1532: for (b=0; b<ha->bus_cnt; ++b) {
1533: for (t=0; t<MAXID; ++t) {
1534: TRACE(("gdth_search_drives() rawd. bus %d id %d\n",b,t));
1535: if (ha->id[b][t].type != SIOP_DTYP &&
1536: gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_INFO,0,b,t)) {
1537: ha->id[b][t].type = RAW_DTYP;
1538: }
1539: }
1540: }
1541:
1542: /* scanning for cache devices */
1543: for (i=0; i<cdev_cnt && i<MAX_HDRIVES; ++i) {
1544: TRACE(("gdth_search_drives() cachedev. %d\n",i));
1545: if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_INFO,i,0,0)) {
1546: /* dynamic relation between host drive number and Bus/ID */
1547: /* search free position */
1548: pos_found = FALSE;
1549: for (b=0,t=0; b<ha->bus_cnt; ++b) {
1550: for (t=0; t<MAXID; ++t) {
1551: if (ha->id[b][t].type == EMPTY_DTYP) {
1552: pos_found = TRUE;
1553: break;
1554: }
1555: }
1556: if (pos_found)
1557: break;
1558: }
1559: TRACE(("gdth_search_dr() drive %d free pos at bus/id %d/%d\n",
1560: i,b,t));
1561:
1562: ha->id[b][t].type = CACHE_DTYP;
1563: ha->id[b][t].devtype = 0;
1564: ha->id[b][t].size = ha->info;
1565: ha->id[b][t].hostdrive = i;
1566:
1567: /* evaluate mapping (sectors per head, heads per cylinder) */
1568: ha->id[b][t].size &= ~SECS32;
1569: if (ha->info2 == 0) {
1570: drv_cyls = ha->id[b][t].size /HEADS/SECS;
1571: if (drv_cyls <= MAXCYLS) {
1572: drv_hds = HEADS;
1573: drv_secs= SECS;
1574: } else { /* too high for 64*32 */
1575: drv_cyls = ha->id[b][t].size /MEDHEADS/MEDSECS;
1576: if (drv_cyls <= MAXCYLS) {
1577: drv_hds = MEDHEADS;
1578: drv_secs= MEDSECS;
1579: } else { /* too high for 127*63 */
1580: drv_cyls = ha->id[b][t].size /BIGHEADS/BIGSECS;
1581: drv_hds = BIGHEADS;
1582: drv_secs= BIGSECS;
1583: }
1584: }
1585: } else {
1586: drv_hds = ha->info2 & 0xff;
1587: drv_secs = (ha->info2 >> 8) & 0xff;
1588: drv_cyls = ha->id[b][t].size /drv_hds/drv_secs;
1589: }
1590: ha->id[b][t].heads = (unchar)drv_hds;
1591: ha->id[b][t].secs = (unchar)drv_secs;
1592: /* round size */
1593: ha->id[b][t].size = drv_cyls * drv_hds * drv_secs;
1594: TRACE2(("gdth_search_dr() cdr. %d size %ld hds %ld scs %ld\n",
1595: i,ha->id[b][t].size,drv_hds,drv_secs));
1596:
1597: /* get informations about device */
1598: if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_DEVTYPE,i,
1599: 0,0)) {
1600: TRACE(("gdth_search_dr() cache drive %d devtype %ld\n",
1601: i,ha->info));
1602: ha->id[b][t].devtype = (ushort)ha->info;
1603: }
1604: }
1605: }
1606:
1607: TRACE(("gdth_search_drives() OK\n"));
1608: return 1;
1609: }
1610:
1611:
1612: /* command queueing/sending functions */
1613:
1614: static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority)
1615: {
1616: register gdth_ha_str *ha;
1617: register Scsi_Cmnd *pscp;
1618: register Scsi_Cmnd *nscp;
1619: ulong flags;
1620: unchar b, t;
1621:
1622: TRACE(("gdth_putq() priority %d\n",priority));
1623: save_flags(flags);
1624: cli();
1625:
1626: ha = HADATA(gdth_ctr_tab[hanum]);
1627: scp->SCp.this_residual = (int)priority;
1628: gdth_update_timeout(hanum, scp, scp->timeout_per_command * 6);
1629: #if LINUX_VERSION_CODE >= 0x020000
1630: b = scp->channel;
1631: #else
1632: b = NUMDATA(nscp->host)->busnum;
1633: #endif
1634: t = scp->target;
1635: #if LINUX_VERSION_CODE >= 0x010300
1636: if (priority >= DEFAULT_PRI && ha->id[b][t].lock) {
1637: TRACE2(("gdth_putq(): locked IO -> update_timeout()\n"));
1638: scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0);
1639: }
1640: #endif
1641:
1642: if (ha->req_first==NULL) {
1643: ha->req_first = scp; /* queue was empty */
1644: scp->SCp.ptr = NULL;
1645: } else { /* queue not empty */
1646: pscp = ha->req_first;
1647: nscp = (Scsi_Cmnd *)pscp->SCp.ptr;
1648: /* priority: 0-highest,..,0xff-lowest */
1649: while (nscp && (unchar)nscp->SCp.this_residual <= priority) {
1650: pscp = nscp;
1651: nscp = (Scsi_Cmnd *)pscp->SCp.ptr;
1652: }
1653: pscp->SCp.ptr = (char *)scp;
1654: scp->SCp.ptr = (char *)nscp;
1655: }
1656: restore_flags(flags);
1657:
1658: #ifdef GDTH_STATISTICS
1659: flags = 0;
1660: for (nscp=ha->req_first; nscp; nscp=(Scsi_Cmnd*)nscp->SCp.ptr)
1661: ++flags;
1662: if (max_rq < flags) {
1663: max_rq = flags;
1664: TRACE3(("GDT: max_rq = %d\n",(ushort)max_rq));
1665: }
1666: #endif
1667: }
1668:
1669: static void gdth_next(int hanum)
1670: {
1671: register gdth_ha_str *ha;
1672: register Scsi_Cmnd *pscp;
1673: register Scsi_Cmnd *nscp;
1674: unchar b, t, next_cmd, firsttime;
1675: ushort hdrive;
1676: ulong flags;
1677: int cmd_index;
1678:
1679: TRACE(("gdth_next() hanum %d\n",hanum));
1680: save_flags(flags);
1681: cli();
1682:
1683: ha = HADATA(gdth_ctr_tab[hanum]);
1684: ha->cmd_cnt = ha->cmd_offs_dpmem = 0;
1685: next_cmd = firsttime = TRUE;
1686: cmd_index = 0;
1687:
1688: for (nscp = pscp = ha->req_first; nscp; nscp = (Scsi_Cmnd *)nscp->SCp.ptr) {
1689: if (nscp != pscp && nscp != (Scsi_Cmnd *)pscp->SCp.ptr)
1690: pscp = (Scsi_Cmnd *)pscp->SCp.ptr;
1691: #if LINUX_VERSION_CODE >= 0x020000
1692: b = nscp->channel;
1693: #else
1694: b = NUMDATA(nscp->host)->busnum;
1695: #endif
1696: t = nscp->target;
1697: if (nscp->SCp.this_residual < DEFAULT_PRI || !ha->id[b][t].lock) {
1698:
1699: if (firsttime) {
1700: if (gdth_test_busy(hanum)) { /* controller busy ? */
1701: TRACE(("gdth_next() controller %d busy !\n",hanum));
1702: if (!gdth_polling) {
1703: restore_flags(flags);
1704: return;
1705: }
1706: while (gdth_test_busy(hanum))
1707: gdth_delay(1);
1708: }
1709: firsttime = FALSE;
1710: }
1711:
1712: #if LINUX_VERSION_CODE >= 0x010300
1713: if (nscp->done == gdth_scsi_done) {
1714: if (!(cmd_index=gdth_special_cmd(hanum,nscp,b)))
1715: next_cmd = FALSE;
1716: } else
1717: #endif
1718: if (ha->id[b][t].type != CACHE_DTYP) {
1719: if (!(cmd_index=gdth_fill_raw_cmd(hanum,nscp,b)))
1720: next_cmd = FALSE;
1721: } else {
1722: hdrive = ha->id[b][t].hostdrive;
1723: switch (nscp->cmnd[0]) {
1724: case TEST_UNIT_READY:
1725: case INQUIRY:
1726: case REQUEST_SENSE:
1727: case READ_CAPACITY:
1728: case VERIFY:
1729: case START_STOP:
1730: case MODE_SENSE:
1731: TRACE2(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0],
1732: nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
1733: nscp->cmnd[4],nscp->cmnd[5]));
1734: gdth_internal_cache_cmd(hanum,nscp,b,&flags);
1735: break;
1736:
1737: case ALLOW_MEDIUM_REMOVAL:
1738: TRACE2(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0],
1739: nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
1740: nscp->cmnd[4],nscp->cmnd[5]));
1741: if ( (nscp->cmnd[4]&1) && !(ha->id[b][t].devtype&1) ) {
1742: TRACE2(("Prevent r. nonremov. drive->do nothing\n"));
1743: nscp->result = DID_OK << 16;
1744: restore_flags( flags );
1745: if (!nscp->SCp.have_data_in)
1746: nscp->SCp.have_data_in++;
1747: else
1748: nscp->scsi_done(nscp);
1749: save_flags( flags );
1750: cli();
1751: } else {
1752: nscp->cmnd[3] = (ha->id[b][t].devtype&1) ? 1:0;
1753: TRACE2(("Prevent/allow r. %d rem. drive %d\n",
1754: nscp->cmnd[4],nscp->cmnd[3]));
1755: if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,hdrive)))
1756: next_cmd = FALSE;
1757: }
1758: break;
1759:
1760: case READ_6:
1761: case WRITE_6:
1762: case READ_10:
1763: case WRITE_10:
1764: if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,hdrive)))
1765: next_cmd = FALSE;
1766: break;
1767:
1768: default:
1769: TRACE2(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0],
1770: nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
1771: nscp->cmnd[4],nscp->cmnd[5]));
1772: printk("GDT: Unknown SCSI command 0x%x to cache service !\n",
1773: nscp->cmnd[0]);
1774: nscp->result = DID_ABORT << 16;
1775: restore_flags( flags );
1776: if (!nscp->SCp.have_data_in)
1777: nscp->SCp.have_data_in++;
1778: else
1779: nscp->scsi_done(nscp);
1780: save_flags( flags );
1781: cli();
1782: break;
1783: }
1784: }
1785:
1786: if (!next_cmd)
1787: break;
1788: if (nscp == ha->req_first)
1789: ha->req_first = pscp = (Scsi_Cmnd *)nscp->SCp.ptr;
1790: else
1791: pscp->SCp.ptr = nscp->SCp.ptr;
1792: if (gdth_polling)
1793: break;
1794: }
1795: }
1796:
1797: if (ha->cmd_cnt > 0) {
1798: gdth_release_event(hanum);
1799: }
1800:
1801: restore_flags(flags);
1802:
1803: if (gdth_polling && ha->cmd_cnt > 0) {
1804: if (!gdth_wait(hanum,cmd_index,POLL_TIMEOUT))
1805: printk("GDT: Controller %d: Command %d timed out !\n",
1806: hanum,cmd_index);
1807: }
1808: }
1809:
1810: static void gdth_copy_internal_data(Scsi_Cmnd *scp,char *buffer,ushort count)
1811: {
1812: ushort cpcount,i;
1813: ushort cpsum,cpnow;
1814: struct scatterlist *sl;
1815:
1816: cpcount = count<=(ushort)scp->bufflen ? count:(ushort)scp->bufflen;
1817: if (scp->use_sg) {
1818: sl = (struct scatterlist *)scp->request_buffer;
1819: for (i=0,cpsum=0; i<scp->use_sg; ++i,++sl) {
1820: cpnow = (ushort)sl->length;
1821: TRACE(("copy_internal() now %d sum %d count %d %d\n",
1822: cpnow,cpsum,cpcount,(ushort)scp->bufflen));
1823: if (cpsum+cpnow > cpcount)
1824: cpnow = cpcount - cpsum;
1825: cpsum += cpnow;
1826: memcpy((char*)sl->address,buffer,cpnow);
1827: if (cpsum == cpcount)
1828: break;
1829: buffer += cpnow;
1830: }
1831: } else {
1832: TRACE(("copy_internal() count %d\n",cpcount));
1833: memcpy((char*)scp->request_buffer,buffer,cpcount);
1834: }
1835: }
1836:
1837: static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp,
1838: unchar b,ulong *flags)
1839: {
1840: register gdth_ha_str *ha;
1841: ushort hdrive;
1842: unchar t;
1843: gdth_inq_data inq;
1844: gdth_rdcap_data rdc;
1845: gdth_sense_data sd;
1846: gdth_modep_data mpd;
1847:
1848: ha = HADATA(gdth_ctr_tab[hanum]);
1849: t = scp->target;
1850: hdrive = ha->id[b][t].hostdrive;
1851: TRACE(("gdth_internal_cache_cmd() cmd 0x%x hdrive %d\n",
1852: scp->cmnd[0],hdrive));
1853:
1854: if (scp->lun !=0)
1855: scp->result = DID_BAD_TARGET << 16;
1856: else {
1857: switch (scp->cmnd[0]) {
1858: case TEST_UNIT_READY:
1859: case VERIFY:
1860: case START_STOP:
1861: TRACE2(("Test/Verify/Start hdrive %d\n",hdrive));
1862: break;
1863:
1864: case INQUIRY:
1865: TRACE2(("Inquiry hdrive %d devtype %d\n",
1866: hdrive,ha->id[b][t].devtype));
1867: inq.type_qual = (ha->id[b][t].devtype&4) ? TYPE_ROM:TYPE_DISK;
1868: /* you can here set all disks to removable, if you want to do
1869: a flush using the ALLOW_MEDIUM_REMOVAL command */
1870: inq.modif_rmb = ha->id[b][t].devtype&1 ? 0x80:0x00;
1871: inq.version = 2;
1872: inq.resp_aenc = 2;
1873: inq.add_length= 32;
1874: strcpy(inq.vendor,"ICP ");
1875: sprintf(inq.product,"Host Drive #%02d",hdrive);
1876: strcpy(inq.revision," ");
1877: gdth_copy_internal_data(scp,(char*)&inq,sizeof(gdth_inq_data));
1878: break;
1879:
1880: case REQUEST_SENSE:
1881: TRACE2(("Request sense hdrive %d\n",hdrive));
1882: sd.errorcode = 0x70;
1883: sd.segno = 0x00;
1884: sd.key = NO_SENSE;
1885: sd.info = 0;
1886: sd.add_length= 0;
1887: gdth_copy_internal_data(scp,(char*)&sd,sizeof(gdth_sense_data));
1888: break;
1889:
1890: case MODE_SENSE:
1891: TRACE2(("Mode sense hdrive %d\n",hdrive));
1892: memset((char*)&mpd,0,sizeof(gdth_modep_data));
1893: mpd.hd.data_length = sizeof(gdth_modep_data);
1894: mpd.hd.dev_par = (ha->id[b][t].devtype&2) ? 0x80:0;
1895: mpd.hd.bd_length = sizeof(mpd.bd);
1896: mpd.bd.block_length[0] = (SECTOR_SIZE & 0x00ff0000) >> 16;
1897: mpd.bd.block_length[1] = (SECTOR_SIZE & 0x0000ff00) >> 8;
1898: mpd.bd.block_length[2] = (SECTOR_SIZE & 0x000000ff);
1899: gdth_copy_internal_data(scp,(char*)&mpd,sizeof(gdth_modep_data));
1900: break;
1901:
1902: case READ_CAPACITY:
1903: TRACE2(("Read capacity hdrive %d\n",hdrive));
1904: rdc.last_block_no = ntohl(ha->id[b][t].size-1);
1905: rdc.block_length = ntohl(SECTOR_SIZE);
1906: gdth_copy_internal_data(scp,(char*)&rdc,sizeof(gdth_rdcap_data));
1907: break;
1908:
1909: default:
1910: TRACE2(("Internal cache cmd 0x%x unknown\n",scp->cmnd[0]));
1911: break;
1912: }
1913: scp->result = DID_OK << 16;
1914: }
1915:
1916: restore_flags(*flags);
1917: if (!scp->SCp.have_data_in)
1918: scp->SCp.have_data_in++;
1919: else
1920: scp->scsi_done(scp);
1921: save_flags(*flags);
1922: cli();
1923: return 1;
1924: }
1925:
1926: static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
1927: {
1928: register gdth_ha_str *ha;
1929: register gdth_cmd_str *cmdp;
1930: struct scatterlist *sl;
1931: ushort i;
1932: int cmd_index;
1933:
1934: ha = HADATA(gdth_ctr_tab[hanum]);
1935: cmdp = ha->pccb;
1936: TRACE(("gdth_fill_cache_cmd() cmd 0x%x cmdsize %d hdrive %d\n",
1937: scp->cmnd[0],scp->cmd_len,hdrive));
1938:
1939: if (ha->type==GDT_EISA && ha->cmd_cnt>0)
1940: return 0;
1941:
1942: cmdp->Service = CACHESERVICE;
1943: cmdp->RequestBuffer = scp;
1944: /* search free command index */
1945: if (!(cmd_index=gdth_get_cmd_index(hanum))) {
1946: TRACE(("GDT: No free command index found\n"));
1947: return 0;
1948: }
1949: /* if it's the first command, set command semaphore */
1950: if (ha->cmd_cnt == 0)
1951: gdth_set_sema0(hanum);
1952:
1953: /* fill command */
1954: if (scp->cmnd[0]==ALLOW_MEDIUM_REMOVAL) {
1955: if (scp->cmnd[4] & 1) /* prevent ? */
1956: cmdp->OpCode = GDT_MOUNT;
1957: else if (scp->cmnd[3] & 1) /* removable drive ? */
1958: cmdp->OpCode = GDT_UNMOUNT;
1959: else
1960: cmdp->OpCode = GDT_FLUSH;
1961: } else {
1962: if (scp->cmnd[0]==WRITE_6 || scp->cmnd[0]==WRITE_10) {
1963: if (gdth_write_through)
1964: cmdp->OpCode = GDT_WRITE_THR;
1965: else
1966: cmdp->OpCode = GDT_WRITE;
1967: } else {
1968: cmdp->OpCode = GDT_READ;
1969: }
1970: }
1971:
1972: cmdp->BoardNode = LOCALBOARD;
1973: cmdp->u.cache.DeviceNo = hdrive;
1974:
1975: if (scp->cmnd[0]==ALLOW_MEDIUM_REMOVAL) {
1976: cmdp->u.cache.BlockNo = 1;
1977: cmdp->u.cache.sg_canz = 0;
1978: } else {
1979: if (scp->cmd_len != 6) {
1980: cmdp->u.cache.BlockNo = ntohl(*(ulong*)&scp->cmnd[2]);
1981: cmdp->u.cache.BlockCnt= (ulong)ntohs(*(ushort*)&scp->cmnd[7]);
1982: } else {
1983: cmdp->u.cache.BlockNo = ntohl(*(ulong*)&scp->cmnd[0]) & 0x001fffffUL;
1984: cmdp->u.cache.BlockCnt= scp->cmnd[4]==0 ? 0x100 : scp->cmnd[4];
1985: }
1986:
1987: if (scp->use_sg) {
1988: cmdp->u.cache.DestAddr= -1UL;
1989: sl = (struct scatterlist *)scp->request_buffer;
1990: for (i=0; i<scp->use_sg; ++i,++sl) {
1991: cmdp->u.cache.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
1992: cmdp->u.cache.sg_lst[i].sg_len = (ulong)sl->length;
1993: }
1994: cmdp->u.cache.sg_canz = (ulong)i;
1995:
1996: #ifdef GDTH_STATISTICS
1997: if (max_sg < (ulong)i) {
1998: max_sg = (ulong)i;
1999: TRACE3(("GDT: max_sg = %d\n",i));
2000: }
2001: #endif
2002: if (i<GDTH_MAXSG)
2003: cmdp->u.cache.sg_lst[i].sg_len = 0;
2004: } else {
2005: if (ha->cache_feat & SCATTER_GATHER) {
2006: cmdp->u.cache.DestAddr = -1UL;
2007: cmdp->u.cache.sg_canz = 1;
2008: cmdp->u.cache.sg_lst[0].sg_ptr = virt_to_bus(scp->request_buffer);
2009: cmdp->u.cache.sg_lst[0].sg_len = scp->request_bufflen;
2010: cmdp->u.cache.sg_lst[1].sg_len = 0;
2011: } else {
2012: cmdp->u.cache.DestAddr = virt_to_bus(scp->request_buffer);
2013: cmdp->u.cache.sg_canz= 0;
2014: }
2015: }
2016: }
2017: TRACE(("cache cmd: addr. %lx sganz %lx sgptr0 %lx sglen0 %lx\n",
2018: cmdp->u.cache.DestAddr,cmdp->u.cache.sg_canz,
2019: cmdp->u.cache.sg_lst[0].sg_ptr,
2020: cmdp->u.cache.sg_lst[0].sg_len));
2021: TRACE(("cache cmd: cmd %d blockno. %ld, blockcnt %ld\n",
2022: cmdp->OpCode,cmdp->u.cache.BlockNo,cmdp->u.cache.BlockCnt));
2023:
2024: /* evaluate command size, check space */
2025: ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) +
2026: (ushort)cmdp->u.cache.sg_canz * sizeof(gdth_sg_str);
2027: if (ha->cmd_len & 3)
2028: ha->cmd_len += (4 - (ha->cmd_len & 3));
2029:
2030: if (ha->cmd_cnt > 0) {
2031: if ((ha->cmd_offs_dpmem + ha->cmd_len + DPMEM_COMMAND_OFFSET) >
2032: ha->ic_all_size) {
2033: TRACE2(("gdth_fill_cache() DPMEM overflow\n"));
2034: gdth_cmd_tab[cmd_index-2][hanum].cmnd = UNUSED_CMND;
2035: return 0;
2036: }
2037: }
2038:
2039: /* copy command */
2040: gdth_copy_command(hanum);
2041: return cmd_index;
2042: }
2043:
2044: static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
2045: {
2046: register gdth_ha_str *ha;
2047: register gdth_cmd_str *cmdp;
2048: struct scatterlist *sl;
2049: ushort i;
2050: int cmd_index;
2051: unchar t,l;
2052:
2053: ha = HADATA(gdth_ctr_tab[hanum]);
2054: t = scp->target;
2055: l = scp->lun;
2056: cmdp = ha->pccb;
2057: TRACE(("gdth_fill_raw_cmd() cmd 0x%x bus %d ID %d LUN %d\n",
2058: scp->cmnd[0],b,t,l));
2059:
2060: if (ha->type==GDT_EISA && ha->cmd_cnt>0)
2061: return 0;
2062:
2063: cmdp->Service = SCSIRAWSERVICE;
2064: cmdp->RequestBuffer = scp;
2065: /* search free command index */
2066: if (!(cmd_index=gdth_get_cmd_index(hanum))) {
2067: TRACE(("GDT: No free command index found\n"));
2068: return 0;
2069: }
2070: /* if it's the first command, set command semaphore */
2071: if (ha->cmd_cnt == 0)
2072: gdth_set_sema0(hanum);
2073:
2074: /* fill command */
2075: cmdp->OpCode = GDT_WRITE; /* always */
2076: cmdp->BoardNode = LOCALBOARD;
2077: cmdp->u.raw.reserved = 0;
2078: cmdp->u.raw.mdisc_time = 0;
2079: cmdp->u.raw.mcon_time = 0;
2080: cmdp->u.raw.clen = scp->cmd_len;
2081: cmdp->u.raw.target = t;
2082: cmdp->u.raw.lun = l;
2083: cmdp->u.raw.bus = b;
2084: cmdp->u.raw.priority = 0;
2085: cmdp->u.raw.link_p = NULL;
2086: cmdp->u.raw.sdlen = scp->request_bufflen;
2087: cmdp->u.raw.sense_len = 16;
2088: cmdp->u.raw.sense_data = virt_to_bus(scp->sense_buffer);
2089: cmdp->u.raw.direction =
2090: gdth_direction_tab[scp->cmnd[0]]==DOU ? DATA_OUT : DATA_IN;
2091: memcpy(cmdp->u.raw.cmd,scp->cmnd,12);
2092:
2093: if (scp->use_sg) {
2094: cmdp->u.raw.sdata = -1UL;
2095: sl = (struct scatterlist *)scp->request_buffer;
2096: for (i=0; i<scp->use_sg; ++i,++sl) {
2097: cmdp->u.raw.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
2098: cmdp->u.raw.sg_lst[i].sg_len = (ulong)sl->length;
2099: }
2100: cmdp->u.raw.sg_ranz = (ulong)i;
2101:
2102: #ifdef GDTH_STATISTICS
2103: if (max_sg < (ulong)i) {
2104: max_sg = (ulong)i;
2105: TRACE3(("GDT: max_sg = %d\n",i));
2106: }
2107: #endif
2108: if (i<GDTH_MAXSG)
2109: cmdp->u.raw.sg_lst[i].sg_len = 0;
2110: } else {
2111: if (ha->raw_feat & SCATTER_GATHER) {
2112: cmdp->u.raw.sdata = -1UL;
2113: cmdp->u.raw.sg_ranz= 1;
2114: cmdp->u.raw.sg_lst[0].sg_ptr = virt_to_bus(scp->request_buffer);
2115: cmdp->u.raw.sg_lst[0].sg_len = scp->request_bufflen;
2116: cmdp->u.raw.sg_lst[1].sg_len = 0;
2117: } else {
2118: cmdp->u.raw.sdata = virt_to_bus(scp->request_buffer);
2119: cmdp->u.raw.sg_ranz= 0;
2120: }
2121: }
2122: TRACE(("raw cmd: addr. %lx sganz %lx sgptr0 %lx sglen0 %lx\n",
2123: cmdp->u.raw.sdata,cmdp->u.raw.sg_ranz,
2124: cmdp->u.raw.sg_lst[0].sg_ptr,
2125: cmdp->u.raw.sg_lst[0].sg_len));
2126:
2127: /* evaluate command size, check space */
2128: ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) +
2129: (ushort)cmdp->u.raw.sg_ranz * sizeof(gdth_sg_str);
2130: if (ha->cmd_len & 3)
2131: ha->cmd_len += (4 - (ha->cmd_len & 3));
2132:
2133: if (ha->cmd_cnt > 0) {
2134: if ((ha->cmd_offs_dpmem + ha->cmd_len + DPMEM_COMMAND_OFFSET) >
2135: ha->ic_all_size) {
2136: TRACE2(("gdth_fill_raw() DPMEM overflow\n"));
2137: gdth_cmd_tab[cmd_index-2][hanum].cmnd = UNUSED_CMND;
2138: return 0;
2139: }
2140: }
2141:
2142: /* copy command */
2143: gdth_copy_command(hanum);
2144: return cmd_index;
2145: }
2146:
2147: static int gdth_special_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
2148: {
2149: register gdth_ha_str *ha;
2150: register gdth_cmd_str *cmdp;
2151: int cmd_index;
2152:
2153: ha = HADATA(gdth_ctr_tab[hanum]);
2154: cmdp= ha->pccb;
2155: TRACE2(("gdth_special_cmd(): "));
2156:
2157: if (ha->type==GDT_EISA && ha->cmd_cnt>0)
2158: return 0;
2159:
2160: memcpy( cmdp, scp->request_buffer, sizeof(gdth_cmd_str));
2161: cmdp->RequestBuffer = scp;
2162:
2163: /* search free command index */
2164: if (!(cmd_index=gdth_get_cmd_index(hanum))) {
2165: TRACE(("GDT: No free command index found\n"));
2166: return 0;
2167: }
2168:
2169: /* if it's the first command, set command semaphore */
2170: if (ha->cmd_cnt == 0)
2171: gdth_set_sema0(hanum);
2172:
2173: /* evaluate command size, check space */
2174: if (cmdp->OpCode == GDT_IOCTL) {
2175: TRACE2(("IOCTL\n"));
2176: ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.ioctl.p_param) + sizeof(ulong);
2177: } else if (cmdp->Service == CACHESERVICE) {
2178: TRACE2(("cache command %d\n",cmdp->OpCode));
2179: ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) + sizeof(gdth_sg_str);
2180: } else if (cmdp->Service == SCSIRAWSERVICE) {
2181: TRACE2(("raw command %d/%d\n",cmdp->OpCode,cmdp->u.raw.cmd[0]));
2182: ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) + sizeof(gdth_sg_str);
2183: }
2184:
2185: if (ha->cmd_len & 3)
2186: ha->cmd_len += (4 - (ha->cmd_len & 3));
2187:
2188: if (ha->cmd_cnt > 0) {
2189: if ((ha->cmd_offs_dpmem + ha->cmd_len + DPMEM_COMMAND_OFFSET) >
2190: ha->ic_all_size) {
2191: TRACE2(("gdth_special_cmd() DPMEM overflow\n"));
2192: gdth_cmd_tab[cmd_index-2][hanum].cmnd = UNUSED_CMND;
2193: return 0;
2194: }
2195: }
2196:
2197: /* copy command */
2198: gdth_copy_command(hanum);
2199: return cmd_index;
2200: }
2201:
2202:
2203: /* Controller event handling functions */
2204: static gdth_evt_str *gdth_store_event(ushort source, ushort idx,
2205: gdth_evt_data *evt)
2206: {
2207: gdth_evt_str *e;
2208: ulong flags;
2209: struct timeval tv;
2210:
2211: TRACE2(("gdth_store_event() source %d idx %d\n", source, idx));
2212: if (source == 0) /* no source -> no event */
2213: return 0;
2214:
2215: save_flags(flags);
2216: cli();
2217: if (ebuffer[elastidx].event_source == source &&
2218: ebuffer[elastidx].event_idx == idx &&
2219: !memcmp((char *)&ebuffer[elastidx].event_data.eu,
2220: (char *)&evt->eu, evt->size)) {
2221: e = &ebuffer[elastidx];
2222: do_gettimeofday(&tv);
2223: e->last_stamp = tv.tv_sec;
2224: ++e->same_count;
2225: } else {
2226: if (ebuffer[elastidx].event_source != 0) { /* entry not free ? */
2227: ++elastidx;
2228: if (elastidx == MAX_EVENTS)
2229: elastidx = 0;
2230: if (elastidx == eoldidx) { /* reached mark ? */
2231: ++eoldidx;
2232: if (eoldidx == MAX_EVENTS)
2233: eoldidx = 0;
2234: }
2235: }
2236: e = &ebuffer[elastidx];
2237: e->event_source = source;
2238: e->event_idx = idx;
2239: do_gettimeofday(&tv);
2240: e->first_stamp = e->last_stamp = tv.tv_sec;
2241: e->same_count = 1;
2242: e->event_data = *evt;
2243: }
2244: restore_flags(flags);
2245: return e;
2246: }
2247:
2248: static int gdth_read_event(int handle, gdth_evt_str *estr)
2249: {
2250: gdth_evt_str *e;
2251: int eindex;
2252: ulong flags;
2253:
2254: TRACE2(("gdth_read_event() handle %d\n", handle));
2255: save_flags(flags);
2256: cli();
2257: if (handle == -1)
2258: eindex = eoldidx;
2259: else
2260: eindex = handle;
2261: estr->event_source = 0;
2262:
2263: if (eindex >= MAX_EVENTS) {
2264: restore_flags(flags);
2265: return eindex;
2266: }
2267: e = &ebuffer[eindex];
2268: if (e->event_source != 0) {
2269: if (eindex != elastidx) {
2270: if (++eindex == MAX_EVENTS)
2271: eindex = 0;
2272: } else {
2273: eindex = -1;
2274: }
2275: memcpy(estr, e, sizeof(gdth_evt_str));
2276: }
2277: restore_flags(flags);
2278: return eindex;
2279: }
2280:
2281: static void gdth_readapp_event(unchar application, gdth_evt_str *estr)
2282: {
2283: gdth_evt_str *e;
2284: int eindex;
2285: ulong flags;
2286: unchar found = FALSE;
2287:
2288: TRACE2(("gdth_readapp_event() app. %d\n", application));
2289: save_flags(flags);
2290: cli();
2291: eindex = eoldidx;
2292: for (;;) {
2293: e = &ebuffer[eindex];
2294: if (e->event_source == 0)
2295: break;
2296: if ((e->application & application) == 0) {
2297: e->application |= application;
2298: found = TRUE;
2299: break;
2300: }
2301: if (eindex == elastidx)
2302: break;
2303: if (++eindex == MAX_EVENTS)
2304: eindex = 0;
2305: }
2306: if (found)
2307: memcpy(estr, e, sizeof(gdth_evt_str));
2308: else
2309: estr->event_source = 0;
2310: restore_flags(flags);
2311: }
2312:
2313: static void gdth_clear_events()
2314: {
2315: ulong flags;
2316:
2317: TRACE(("gdth_clear_events()"));
2318: save_flags(flags);
2319: cli();
2320:
2321: eoldidx = elastidx = 0;
2322: ebuffer[0].event_source = 0;
2323: restore_flags(flags);
2324: }
2325:
2326:
2327: /* SCSI interface functions */
2328:
2329: #if LINUX_VERSION_CODE >= 0x02015F
2330: static void do_gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
2331: {
2332: ulong flags;
2333:
2334: spin_lock_irqsave(&io_request_lock, flags);
2335: gdth_interrupt(irq, dev_id, regs);
2336: spin_unlock_irqrestore(&io_request_lock, flags);
2337: }
2338: #endif
2339:
2340: #if LINUX_VERSION_CODE >= 0x010346
2341: static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
2342: #else
2343: static void gdth_interrupt(int irq,struct pt_regs *regs)
2344: #endif
2345: {
2346: register gdth_ha_str *ha;
2347: gdt6m_dpram_str *dp6m_ptr;
2348: gdt6_dpram_str *dp6_ptr;
2349: gdt2_dpram_str *dp2_ptr;
2350: Scsi_Cmnd *scp;
2351: int hanum;
2352: unchar IStatus;
2353: ushort CmdStatus, Service = 0;
2354: ulong InfoBytes, InfoBytes2 = 0;
2355: gdth_evt_data dvr;
2356:
2357: TRACE(("gdth_interrupt() IRQ %d\n",irq));
2358:
2359: /* if polling and not from gdth_wait() -> return */
2360: if (gdth_polling) {
2361: if (!gdth_from_wait) {
2362: return;
2363: }
2364: }
2365:
2366: wait_index = 0;
2367:
2368: /* search controller */
2369: if ((hanum = gdth_get_status(&IStatus,irq)) == -1) {
2370: /*
2371: TRACE2(("gdth_interrupt(): Spurious interrupt received\n"));
2372: */
2373: return;
2374: }
2375:
2376: #ifdef GDTH_STATISTICS
2377: ++act_ints;
2378: #endif
2379:
2380: ha = HADATA(gdth_ctr_tab[hanum]);
2381: if (ha->type == GDT_EISA) {
2382: if (IStatus & 0x80) { /* error flag */
2383: IStatus &= ~0x80;
2384: CmdStatus = inw(ha->bmic + MAILBOXREG+8);
2385: TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,CmdStatus));
2386: if (IStatus == ASYNCINDEX) { /* async. event ? */
2387: Service = inw(ha->bmic + MAILBOXREG+10);
2388: InfoBytes2 = inl(ha->bmic + MAILBOXREG+4);
2389: }
2390: } else /* no error */
2391: CmdStatus = S_OK;
2392: InfoBytes = inl(ha->bmic + MAILBOXREG+12);
2393: if (gdth_polling) /* init. -> more info */
2394: InfoBytes2 = inl(ha->bmic + MAILBOXREG+4);
2395: outb(0xff, ha->bmic + EDOORREG); /* acknowledge interrupt */
2396: outb(0x00, ha->bmic + SEMA1REG); /* reset status semaphore */
2397: } else if (ha->type == GDT_ISA) {
2398: dp2_ptr = (gdt2_dpram_str *)ha->brd;
2399: if (IStatus & 0x80) { /* error flag */
2400: IStatus &= ~0x80;
2401: CmdStatus = readw(&dp2_ptr->u.ic.Status);
2402: TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,CmdStatus));
2403: if (IStatus == ASYNCINDEX) { /* async. event ? */
2404: Service = readw(&dp2_ptr->u.ic.Service);
2405: InfoBytes2 = readl(&dp2_ptr->u.ic.Info[1]);
2406: }
2407: } else /* no error */
2408: CmdStatus = S_OK;
2409: InfoBytes = readl(&dp2_ptr->u.ic.Info[0]);
2410: if (gdth_polling) /* init. -> more info */
2411: InfoBytes2 = readl(&dp2_ptr->u.ic.Info[1]);
2412: writeb(0xff, &dp2_ptr->io.irqdel); /* acknowledge interrupt */
2413: writeb(0, &dp2_ptr->u.ic.Cmd_Index); /* reset command index */
2414: writeb(0, &dp2_ptr->io.Sema1); /* reset status semaphore */
2415: } else if (ha->type == GDT_PCI) {
2416: dp6_ptr = (gdt6_dpram_str *)ha->brd;
2417: if (IStatus & 0x80) { /* error flag */
2418: IStatus &= ~0x80;
2419: CmdStatus = readw(&dp6_ptr->u.ic.Status);
2420: TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,CmdStatus));
2421: if (IStatus == ASYNCINDEX) { /* async. event ? */
2422: Service = readw(&dp6_ptr->u.ic.Service);
2423: InfoBytes2 = readl(&dp6_ptr->u.ic.Info[1]);
2424: }
2425: } else /* no error */
2426: CmdStatus = S_OK;
2427: InfoBytes = readl(&dp6_ptr->u.ic.Info[0]);
2428: if (gdth_polling) /* init. -> more info */
2429: InfoBytes2 = readl(&dp6_ptr->u.ic.Info[1]);
2430: writeb(0xff, &dp6_ptr->io.irqdel); /* acknowledge interrupt */
2431: writeb(0, &dp6_ptr->u.ic.Cmd_Index); /* reset command index */
2432: writeb(0, &dp6_ptr->io.Sema1); /* reset status semaphore */
2433: } else if (ha->type == GDT_PCINEW) {
2434: if (IStatus & 0x80) { /* error flag */
2435: IStatus &= ~0x80;
2436: CmdStatus = inw(PTR2USHORT(&ha->plx->status));
2437: TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,CmdStatus));
2438: if (IStatus == ASYNCINDEX) { /* async. event ? */
2439: Service = inw(PTR2USHORT(&ha->plx->service));
2440: InfoBytes2 = inl(PTR2USHORT(&ha->plx->info[1]));
2441: }
2442: } else
2443: CmdStatus = S_OK;
2444:
2445: InfoBytes = inl(PTR2USHORT(&ha->plx->info[0]));
2446: if (gdth_polling) /* init. -> more info */
2447: InfoBytes2 = inl(PTR2USHORT(&ha->plx->info[1]));
2448: outb(0xff, PTR2USHORT(&ha->plx->edoor_reg));
2449: outb(0x00, PTR2USHORT(&ha->plx->sema1_reg));
2450: } else if (ha->type == GDT_PCIMPR) {
2451: dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
2452: if (IStatus & 0x80) { /* error flag */
2453: IStatus &= ~0x80;
2454: CmdStatus = readw(&dp6m_ptr->i960r.status);
2455: TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,CmdStatus));
2456: if (IStatus == ASYNCINDEX) { /* async. event ? */
2457: Service = readw(&dp6m_ptr->i960r.service);
2458: InfoBytes2 = readl(&dp6m_ptr->i960r.info[1]);
2459: }
2460: } else /* no error */
2461: CmdStatus = S_OK;
2462: InfoBytes = readl(&dp6m_ptr->i960r.info[0]);
2463: if (gdth_polling) /* init. -> more info */
2464: InfoBytes2 = readl(&dp6m_ptr->i960r.info[1]);
2465: writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
2466: writeb(0, &dp6m_ptr->i960r.sema1_reg);
2467: } else {
2468: TRACE2(("gdth_interrupt() unknown controller type\n"));
2469: return;
2470: }
2471:
2472: TRACE(("gdth_interrupt() index %d stat %d info %ld\n",
2473: IStatus,CmdStatus,InfoBytes));
2474: ha->status = CmdStatus;
2475: ha->info = InfoBytes;
2476: ha->info2 = InfoBytes2;
2477:
2478: if (gdth_from_wait) {
2479: wait_hanum = hanum;
2480: wait_index = (int)IStatus;
2481: }
2482:
2483: if (IStatus == ASYNCINDEX) {
2484: TRACE2(("gdth_interrupt() async. event\n"));
2485: gdth_async_event(hanum,Service);
2486: } else {
2487: if (IStatus == SPEZINDEX) {
2488: TRACE2(("Service unknown or not initialized !\n"));
2489: dvr.size = sizeof(dvr.eu.driver);
2490: dvr.eu.driver.ionode = hanum;
2491: gdth_store_event(ES_DRIVER, 4, &dvr);
2492: return;
2493: }
2494: scp = gdth_cmd_tab[IStatus-2][hanum].cmnd;
2495: Service = gdth_cmd_tab[IStatus-2][hanum].service;
2496: gdth_cmd_tab[IStatus-2][hanum].cmnd = UNUSED_CMND;
2497: if (scp == UNUSED_CMND) {
2498: TRACE2(("gdth_interrupt() index to unused command (%d)\n",IStatus));
2499: dvr.size = sizeof(dvr.eu.driver);
2500: dvr.eu.driver.ionode = hanum;
2501: dvr.eu.driver.index = IStatus;
2502: gdth_store_event(ES_DRIVER, 1, &dvr);
2503: return;
2504: }
2505: if (scp == INTERNAL_CMND) {
2506: TRACE(("gdth_interrupt() answer to internal command\n"));
2507: return;
2508: }
2509: TRACE(("gdth_interrupt() sync. status\n"));
2510: gdth_sync_event(hanum,Service,IStatus,scp);
2511: }
2512: gdth_next(hanum);
2513: }
2514:
2515: static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
2516: {
2517: register gdth_ha_str *ha;
2518: gdth_msg_str *msg;
2519: gdth_cmd_str *cmdp;
2520: char c='\r';
2521: ushort i;
2522: gdth_evt_data dvr;
2523:
2524: ha = HADATA(gdth_ctr_tab[hanum]);
2525: cmdp = ha->pccb;
2526: TRACE(("gdth_sync_event() scp %lx serv %d status %d\n",
2527: (ulong)scp,service,ha->status));
2528:
2529: if (service == SCREENSERVICE) {
2530: msg = (gdth_msg_str *)ha->pscratch;
2531: TRACE(("len: %ld, answer: %d, ext: %d, alen: %ld\n",
2532: msg->msg_len,msg->msg_answer,msg->msg_ext,msg->msg_alen));
2533: if (msg->msg_len)
2534: if (!(msg->msg_answer && msg->msg_ext)) {
2535: msg->msg_text[msg->msg_len] = '\0';
2536: printk("%s",msg->msg_text);
2537: }
2538:
2539: if (msg->msg_ext && !msg->msg_answer) {
2540: while (gdth_test_busy(hanum))
2541: gdth_delay(0);
2542: cmdp->Service = SCREENSERVICE;
2543: cmdp->RequestBuffer = SCREEN_CMND;
2544: gdth_get_cmd_index(hanum);
2545: gdth_set_sema0(hanum);
2546: cmdp->OpCode = GDT_READ;
2547: cmdp->BoardNode = LOCALBOARD;
2548: cmdp->u.screen.reserved = 0;
2549: cmdp->u.screen.msg_handle= msg->msg_handle;
2550: cmdp->u.screen.msg_addr = (ulong)msg;
2551: ha->cmd_offs_dpmem = 0;
2552: ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.msg_addr)
2553: + sizeof(ulong);
2554: ha->cmd_cnt = 0;
2555: gdth_copy_command(hanum);
2556: gdth_release_event(hanum);
2557: return 1;
2558: }
2559:
2560: if (msg->msg_answer && msg->msg_alen) {
2561: for (i=0; i<msg->msg_alen && i<MSGLEN; ++i) {
2562: /* getchar() ?? */
2563: /* .. */
2564: if (c == '\r')
2565: break;
2566: msg->msg_text[i] = c;
2567: }
2568: msg->msg_alen -= i;
2569: if (c!='\r' && msg->msg_alen!=0) {
2570: msg->msg_answer = 1;
2571: msg->msg_ext = 1;
2572: } else {
2573: msg->msg_ext = 0;
2574: msg->msg_answer = 0;
2575: }
2576: msg->msg_len = i;
2577: while (gdth_test_busy(hanum))
2578: gdth_delay(0);
2579: cmdp->Service = SCREENSERVICE;
2580: cmdp->RequestBuffer = SCREEN_CMND;
2581: gdth_get_cmd_index(hanum);
2582: gdth_set_sema0(hanum);
2583: cmdp->OpCode = GDT_WRITE;
2584: cmdp->BoardNode = LOCALBOARD;
2585: cmdp->u.screen.reserved = 0;
2586: cmdp->u.screen.msg_handle= msg->msg_handle;
2587: cmdp->u.screen.msg_addr = (ulong)msg;
2588: ha->cmd_offs_dpmem = 0;
2589: ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.msg_addr)
2590: + sizeof(ulong);
2591: ha->cmd_cnt = 0;
2592: gdth_copy_command(hanum);
2593: gdth_release_event(hanum);
2594: return 1;
2595: }
2596: printk("\n");
2597:
2598: } else {
2599: scp->SCp.Message = (int)ha->status;
2600: /* cache or raw service */
2601: if (ha->status == S_OK) {
2602: scp->result = DID_OK << 16;
2603: } else if (ha->status == S_BSY) {
2604: TRACE2(("Controller busy -> retry !\n"));
2605: gdth_putq(hanum,scp,scp->SCp.this_residual);
2606: return 1;
2607: } else {
2608: if (service == CACHESERVICE) {
2609: memset((char*)scp->sense_buffer,0,16);
2610: scp->sense_buffer[0] = 0x70;
2611: scp->sense_buffer[2] = NOT_READY;
2612: scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
2613:
2614: if (scp->done != gdth_scsi_done) {
2615: dvr.size = sizeof(dvr.eu.sync);
2616: dvr.eu.sync.ionode = hanum;
2617: dvr.eu.sync.service = service;
2618: dvr.eu.sync.status = ha->status;
2619: dvr.eu.sync.info = ha->info;
2620: dvr.eu.sync.hostdrive =
2621: #if LINUX_VERSION_CODE >= 0x020000
2622: ha->id[scp->channel][scp->target].hostdrive;
2623: #else
2624: ha->id[NUMDATA(scp->host)->busnum][scp->target].hostdrive;
2625: #endif
2626: if (ha->status >= 0x8000)
2627: gdth_store_event(ES_SYNC, 0, &dvr);
2628: else
2629: gdth_store_event(ES_SYNC, service, &dvr);
2630: }
2631: } else {
2632: if (ha->status!=S_RAW_SCSI || ha->status==S_RAW_ILL || ha->info>=0x100) {
2633: scp->result = DID_BAD_TARGET << 16;
2634: } else {
2635: scp->result = (DID_OK << 16) | ha->info;
2636: }
2637: }
2638: }
2639: if (!scp->SCp.have_data_in)
2640: scp->SCp.have_data_in++;
2641: else
2642: scp->scsi_done(scp);
2643: }
2644:
2645: return 1;
2646: }
2647:
2648: static char *async_cache_tab[] = {
2649: /* 0*/ "\011\000\002\002\002\004\002\006\004"
2650: "GDT HA %u, service %u, async. status %u/%lu unknown",
2651: /* 1*/ "\011\000\002\002\002\004\002\006\004"
2652: "GDT HA %u, service %u, async. status %u/%lu unknown",
2653: /* 2*/ "\005\000\002\006\004"
2654: "GDT HA %u, Host Drive %lu not ready",
2655: /* 3*/ "\005\000\002\006\004"
2656: "GDT HA %u, Host Drive %lu: REASSIGN not successful and/or data error on reassigned blocks. Drive may crash in the future and should be replaced",
2657: /* 4*/ "\005\000\002\006\004"
2658: "GDT HA %u, mirror update on Host Drive %lu failed",
2659: /* 5*/ "\005\000\002\006\004"
2660: "GDT HA %u, Mirror Drive %lu failed",
2661: /* 6*/ "\005\000\002\006\004"
2662: "GDT HA %u, Mirror Drive %lu: REASSIGN not successful and/or data error on reassigned blocks. Drive may crash in the future and should be replaced",
2663: /* 7*/ "\005\000\002\006\004"
2664: "GDT HA %u, Host Drive %lu write protected",
2665: /* 8*/ "\005\000\002\006\004"
2666: "GDT HA %u, media changed in Host Drive %lu",
2667: /* 9*/ "\005\000\002\006\004"
2668: "GDT HA %u, Host Drive %lu is offline",
2669: /*10*/ "\005\000\002\006\004"
2670: "GDT HA %u, media change of Mirror Drive %lu",
2671: /*11*/ "\005\000\002\006\004"
2672: "GDT HA %u, Mirror Drive %lu is write protected",
2673: /*12*/ "\005\000\002\006\004"
2674: "GDT HA %u, general error on Host Drive %lu. Please check the devices of this drive!",
2675: /*13*/ "\007\000\002\006\002\010\002"
2676: "GDT HA %u, Array Drive %u: Cache Drive %u failed",
2677: /*14*/ "\005\000\002\006\002"
2678: "GDT HA %u, Array Drive %u: FAIL state entered",
2679: /*15*/ "\005\000\002\006\002"
2680: "GDT HA %u, Array Drive %u: error",
2681: /*16*/ "\007\000\002\006\002\010\002"
2682: "GDT HA %u, Array Drive %u: failed drive replaced by Cache Drive %u",
2683: /*17*/ "\005\000\002\006\002"
2684: "GDT HA %u, Array Drive %u: parity build failed",
2685: /*18*/ "\005\000\002\006\002"
2686: "GDT HA %u, Array Drive %u: drive rebuild failed",
2687: /*19*/ "\007\000\002\010\002"
2688: "GDT HA %u, Test of Hot Fix %u failed",
2689: /*20*/ "\005\000\002\006\002"
2690: "GDT HA %u, Array Drive %u: drive build finished successfully",
2691: /*21*/ "\005\000\002\006\002"
2692: "GDT HA %u, Array Drive %u: drive rebuild finished successfully",
2693: /*22*/ "\007\000\002\006\002\010\002"
2694: "GDT HA %u, Array Drive %u: Hot Fix %u activated",
2695: /*23*/ "\005\000\002\006\002"
2696: "GDT HA %u, Host Drive %u: processing of i/o aborted due to serious drive error",
2697: /*24*/ "\005\000\002\010\002"
2698: "GDT HA %u, mirror update on Cache Drive %u completed",
2699: /*25*/ "\005\000\002\010\002"
2700: "GDT HA %u, mirror update on Cache Drive %lu failed",
2701: /*26*/ "\005\000\002\006\002"
2702: "GDT HA %u, Array Drive %u: drive rebuild started",
2703: /*27*/ "\005\000\002\012\001"
2704: "GDT HA %u, Fault bus %u: SHELF OK detected",
2705: /*28*/ "\005\000\002\012\001"
2706: "GDT HA %u, Fault bus %u: SHELF not OK detected",
2707: /*29*/ "\007\000\002\012\001\013\001"
2708: "GDT HA %u, Fault bus %u, ID %u: Auto Hot Plug started",
2709: /*30*/ "\007\000\002\012\001\013\001"
2710: "GDT HA %u, Fault bus %u, ID %u: new disk detected",
2711: /*31*/ "\007\000\002\012\001\013\001"
2712: "GDT HA %u, Fault bus %u, ID %u: old disk detected",
2713: /*32*/ "\007\000\002\012\001\013\001"
2714: "GDT HA %u, Fault bus %u, ID %u: plugging an active disk is illegal",
2715: /*33*/ "\007\000\002\012\001\013\001"
2716: "GDT HA %u, Fault bus %u, ID %u: illegal device detected",
2717: /*34*/ "\011\000\002\012\001\013\001\006\004"
2718: "GDT HA %u, Fault bus %u, ID %u: insufficient disk capacity (%lu MB required)",
2719: /*35*/ "\007\000\002\012\001\013\001"
2720: "GDT HA %u, Fault bus %u, ID %u: disk write protected",
2721: /*36*/ "\007\000\002\012\001\013\001"
2722: "GDT HA %u, Fault bus %u, ID %u: disk not available",
2723: /*37*/ "\007\000\002\012\001\006\004"
2724: "GDT HA %u, Fault bus %u: swap detected (%lu)",
2725: /*38*/ "\007\000\002\012\001\013\001"
2726: "GDT HA %u, Fault bus %u, ID %u: Auto Hot Plug finished successfully",
2727: /*39*/ "\007\000\002\012\001\013\001"
2728: "GDT HA %u, Fault bus %u, ID %u: Auto Hot Plug aborted due to user Hot Plug",
2729: /*40*/ "\007\000\002\012\001\013\001"
2730: "GDT HA %u, Fault bus %u, ID %u: Auto Hot Plug aborted",
2731: /*41*/ "\007\000\002\012\001\013\001"
2732: "GDT HA %u, Fault bus %u, ID %u: Auto Hot Plug for Hot Fix started",
2733: /*42*/ "\005\000\002\006\002"
2734: "GDT HA %u, Array Drive %u: drive build started",
2735: /*43*/ "\003\000\002"
2736: "GDT HA %u, DRAM parity error detected",
2737: /*44*/ "\005\000\002\006\002"
2738: "GDT HA %u, Mirror Drive %u: update started",
2739: /*45*/ "\007\000\002\006\002\010\002"
2740: "GDT HA %u, Mirror Drive %u: Hot Fix %u activated",
2741: /*46*/ "\005\000\002\006\002"
2742: "GDT HA %u, Array Drive %u: no matching Pool Hot Fix Drive available",
2743: /*47*/ "\005\000\002\006\002"
2744: "GDT HA %u, Array Drive %u: Pool Hot Fix Drive available",
2745: /*48*/ "\005\000\002\006\002"
2746: "GDT HA %u, Mirror Drive %u: no matching Pool Hot Fix Drive available",
2747: /*49*/ "\005\000\002\006\002"
2748: "GDT HA %u, Mirror Drive %u: Pool Hot Fix Drive available",
2749: /*50*/ "\007\000\002\012\001\013\001"
2750: "GDT HA %u, SCSI bus %u, ID %u: IGNORE_WIDE_RESIDUE message received",
2751: /*51*/ "\005\000\002\006\002"
2752: "GDT HA %u, Array Drive %u: expand started",
2753: /*52*/ "\005\000\002\006\002"
2754: "GDT HA %u, Array Drive %u: expand finished successfully",
2755: /*53*/ "\005\000\002\006\002"
2756: "GDT HA %u, Array Drive %u: expand failed",
2757: /*54*/ "\003\000\002"
2758: "GDT HA %u, CPU temperature critical",
2759: /*55*/ "\003\000\002"
2760: "GDT HA %u, CPU temperature OK",
2761: /*56*/ "\005\000\002\006\004"
2762: "GDT HA %u, Host drive %lu created",
2763: /*57*/ "\005\000\002\006\002"
2764: "GDT HA %u, Array Drive %u: expand restarted",
2765: /*58*/ "\005\000\002\006\002"
2766: "GDT HA %u, Array Drive %u: expand stopped",
2767: };
2768:
2769:
2770: static int gdth_async_event(int hanum,int service)
2771: {
2772: gdth_stackframe stack;
2773: gdth_evt_data dvr;
2774: char *f = NULL;
2775: int i,j;
2776: gdth_ha_str *ha;
2777: gdth_msg_str *msg;
2778: gdth_cmd_str *cmdp;
2779: int cmd_index;
2780:
2781: ha = HADATA(gdth_ctr_tab[hanum]);
2782: cmdp= ha->pccb;
2783: msg = (gdth_msg_str *)ha->pscratch;
2784: TRACE2(("gdth_async_event() ha %d serv %d\n",
2785: hanum,service));
2786:
2787: if (service == SCREENSERVICE) {
2788: if (ha->status == MSG_REQUEST) {
2789: while (gdth_test_busy(hanum))
2790: gdth_delay(0);
2791: cmdp->Service = SCREENSERVICE;
2792: cmdp->RequestBuffer = SCREEN_CMND;
2793: cmd_index = gdth_get_cmd_index(hanum);
2794: gdth_set_sema0(hanum);
2795: cmdp->OpCode = GDT_READ;
2796: cmdp->BoardNode = LOCALBOARD;
2797: cmdp->u.screen.reserved = 0;
2798: cmdp->u.screen.msg_handle= MSG_INV_HANDLE;
2799: cmdp->u.screen.msg_addr = (ulong)msg;
2800: ha->cmd_offs_dpmem = 0;
2801: ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.msg_addr)
2802: + sizeof(ulong);
2803: ha->cmd_cnt = 0;
2804: gdth_copy_command(hanum);
2805: if (ha->type == GDT_EISA)
2806: printk("[EISA slot %d] ",(ushort)ha->brd_phys);
2807: else if (ha->type == GDT_ISA)
2808: printk("[DPMEM 0x%4X] ",(ushort)ha->brd_phys);
2809: else
2810: printk("[PCI %d/%d] ",(ushort)(ha->brd_phys>>8),
2811: (ushort)((ha->brd_phys>>3)&0x1f));
2812: gdth_release_event(hanum);
2813: }
2814:
2815: } else {
2816: dvr.size = sizeof(dvr.eu.async);
2817: dvr.eu.async.ionode = hanum;
2818: dvr.eu.async.service = service;
2819: dvr.eu.async.status = ha->status;
2820: dvr.eu.async.info = ha->info;
2821: *(ulong *)dvr.eu.async.scsi_coord = ha->info2;
2822: gdth_store_event(ES_ASYNC, service, &dvr);
2823:
2824: if (service==CACHESERVICE && INDEX_OK(ha->status,async_cache_tab)) {
2825: TRACE2(("GDT: Async. event cache service, event no.: %d\n",
2826: ha->status));
2827:
2828: f = async_cache_tab[ha->status];
2829:
2830: /* i: parameter to push, j: stack element to fill */
2831: for (j=0,i=1; i < f[0]; i+=2) {
2832: switch (f[i+1]) {
2833: case 4:
2834: stack.b[j++] = *(ulong*)&dvr.eu.stream[(int)f[i]];
2835: break;
2836: case 2:
2837: stack.b[j++] = *(ushort*)&dvr.eu.stream[(int)f[i]];
2838: break;
2839: case 1:
2840: stack.b[j++] = *(unchar*)&dvr.eu.stream[(int)f[i]];
2841: break;
2842: default:
2843: break;
2844: }
2845: }
2846:
2847: printk(&f[f[0]],stack); printk("\n");
2848:
2849: } else {
2850: printk("GDT: Unknown async. event service %d event no. %d\n",
2851: service,ha->status);
2852: }
2853: }
2854: return 1;
2855: }
2856:
2857:
2858: #ifdef GDTH_STATISTICS
2859: void gdth_timeout(ulong data)
2860: {
2861: ulong flags,i;
2862: Scsi_Cmnd *nscp;
2863: gdth_ha_str *ha;
2864: int hanum = 0;
2865:
2866: save_flags(flags);
2867: cli();
2868:
2869: for (act_stats=0,i=0; i<GDTH_MAXCMDS; ++i)
2870: if (gdth_cmd_tab[i][hanum].cmnd != UNUSED_CMND)
2871: ++act_stats;
2872:
2873: ha = HADATA(gdth_ctr_tab[hanum]);
2874: for (act_rq=0,nscp=ha->req_first; nscp; nscp=(Scsi_Cmnd*)nscp->SCp.ptr)
2875: ++act_rq;
2876:
2877: TRACE2(("gdth_to(): ints %ld, ios %ld, act_stats %ld, act_rq %ld\n",
2878: act_ints, act_ios, act_stats, act_rq));
2879: act_ints = act_ios = 0;
2880:
2881: gdth_timer.expires = jiffies + 30 * HZ;
2882: add_timer(&gdth_timer);
2883: restore_flags(flags);
2884: }
2885: #endif
2886:
2887:
2888: __initfunc (int gdth_detect(Scsi_Host_Template *shtp))
2889: {
2890: struct Scsi_Host *shp;
2891: gdth_ha_str *ha;
2892: unsigned long flags;
2893: ulong isa_bios;
2894: ushort eisa_slot,device_id,index;
2895: gdth_pci_str pcistr;
2896: int i,j,hanum;
2897: unchar b;
2898:
2899:
2900: #ifdef DEBUG_GDTH
2901: printk("GDT: This driver contains debugging information !! Trace level = %d\n",
2902: DebugState);
2903: printk(" Destination of debugging information: ");
2904: #ifdef __SERIAL__
2905: #ifdef __COM2__
2906: printk("Serial port COM2\n");
2907: #else
2908: printk("Serial port COM1\n");
2909: #endif
2910: #else
2911: printk("Console\n");
2912: #endif
2913: gdth_delay(3000);
2914: #endif
2915:
2916: TRACE(("gdth_detect()\n"));
2917:
2918: if (disable_gdth_scan) {
2919: printk("GDT: Controller driver disabled from command line !\n");
2920: return 0;
2921: }
2922:
2923: /* initializations */
2924: gdth_polling = TRUE; b = 0;
2925: for (i=0; i<GDTH_MAXCMDS; ++i)
2926: for (j=0; j<MAXHA; ++j)
2927: gdth_cmd_tab[i][j].cmnd = UNUSED_CMND;
2928: for (i=0; i<4; ++i)
2929: for (j=0; j<MAXHA; ++j)
2930: gdth_ioctl_tab[i][j] = NULL;
2931: gdth_clear_events();
2932:
2933: /* scanning for controllers, at first: ISA controller */
2934: for (isa_bios=0xc8000UL; isa_bios<=0xd8000UL; isa_bios+=0x8000UL) {
2935: if (gdth_search_isa(isa_bios)) { /* controller found */
2936: shp = scsi_register(shtp,sizeof(gdth_ext_str));
2937: ha = HADATA(shp);
2938: if (!gdth_init_isa(isa_bios,ha)) {
2939: scsi_unregister(shp);
2940: continue;
2941: }
2942: /* controller found and initialized */
2943: printk("Configuring GDT-ISA HA at BIOS 0x%05lX IRQ %u DRQ %u\n",
2944: isa_bios,ha->irq,ha->drq);
2945:
2946: save_flags(flags);
2947: cli();
2948: #if LINUX_VERSION_CODE >= 0x02015F
2949: if (request_irq(ha->irq,do_gdth_interrupt,SA_INTERRUPT,"gdth",NULL))
2950: #elif LINUX_VERSION_CODE >= 0x010346
2951: if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",NULL))
2952: #else
2953: if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth"))
2954: #endif
2955: {
2956: printk("GDT-ISA: Unable to allocate IRQ\n");
2957: restore_flags(flags);
2958: scsi_unregister(shp);
2959: continue;
2960: }
2961: if (request_dma(ha->drq,"gdth")) {
2962: printk("GDT-ISA: Unable to allocate DMA channel\n");
2963: #if LINUX_VERSION_CODE >= 0x010346
2964: free_irq(ha->irq,NULL);
2965: #else
2966: free_irq(ha->irq);
2967: #endif
2968: restore_flags(flags);
2969: scsi_unregister(shp);
2970: continue;
2971: }
2972: set_dma_mode(ha->drq,DMA_MODE_CASCADE);
2973: enable_dma(ha->drq);
2974: shp->unchecked_isa_dma = 1;
2975: shp->irq = ha->irq;
2976: shp->dma_channel = ha->drq;
2977: for (i=0; i<MAXID; ++i) {
2978: if (ha->id[0][i].type==SIOP_DTYP) {
2979: shp->this_id = i;
2980: break;
2981: }
2982: }
2983: hanum = gdth_ctr_count;
2984: gdth_ctr_tab[gdth_ctr_count++] = shp;
2985: gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
2986:
2987: NUMDATA(shp)->hanum = (ushort)hanum;
2988: NUMDATA(shp)->busnum= 0;
2989:
2990: ha->pccb = CMDDATA(shp);
2991: ha->pscratch = DMADATA(shp);
2992: ha->req_first = NULL;
2993: for (i=0; i<MAXBUS; ++i) {
2994: for (j=0; j<MAXID; ++j) {
2995: ha->id[i][j].type = EMPTY_DTYP;
2996: ha->id[i][j].lock = 0;
2997: ha->id[i][j].heads = 0;
2998: }
2999: }
3000: restore_flags(flags);
3001:
3002: if (!gdth_search_drives(hanum)) {
3003: printk("GDT-ISA: Error during device scan\n");
3004: --gdth_ctr_count;
3005: --gdth_ctr_vcount;
3006: save_flags(flags);
3007: cli();
3008: #if LINUX_VERSION_CODE >= 0x010346
3009: free_irq(ha->irq,NULL);
3010: #else
3011: free_irq(ha->irq);
3012: #endif
3013: restore_flags(flags);
3014: scsi_unregister(shp);
3015: continue;
3016: }
3017:
3018: #if LINUX_VERSION_CODE >= 0x020000
3019: shp->max_id = 8;
3020: shp->max_lun = MAXLUN;
3021: shp->max_channel = ha->bus_cnt - 1;
3022: #else
3023: /* register addit. SCSI channels as virtual controllers */
3024: for (b=1; b<ha->bus_cnt; ++b) {
3025: shp = scsi_register(shtp,sizeof(gdth_num_str));
3026: shp->unchecked_isa_dma = 1;
3027: shp->irq = ha->irq;
3028: shp->dma_channel = ha->drq;
3029: for (i=0; i<MAXID; ++i) {
3030: if (ha->id[b][i].type==SIOP_DTYP) {
3031: shp->this_id = i;
3032: break;
3033: }
3034: }
3035: gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
3036: NUMDATA(shp)->hanum = (ushort)hanum;
3037: NUMDATA(shp)->busnum = b;
3038: }
3039: #endif
3040:
3041: gdth_enable_int(hanum);
3042: }
3043: }
3044:
3045: /* scanning for EISA controllers */
3046: for (eisa_slot=0x1000; eisa_slot<=0x8000; eisa_slot+=0x1000) {
3047: if (gdth_search_eisa(eisa_slot)) { /* controller found */
3048: shp = scsi_register(shtp,sizeof(gdth_ext_str));
3049: ha = HADATA(shp);
3050: if (!gdth_init_eisa(eisa_slot,ha)) {
3051: scsi_unregister(shp);
3052: continue;
3053: }
3054: /* controller found and initialized */
3055: printk("Configuring GDT-EISA HA at Slot %d IRQ %u\n",
3056: eisa_slot>>12,ha->irq);
3057:
3058: save_flags(flags);
3059: cli();
3060: #if LINUX_VERSION_CODE >= 0x02015F
3061: if (request_irq(ha->irq,do_gdth_interrupt,SA_INTERRUPT,"gdth",NULL))
3062: #elif LINUX_VERSION_CODE >= 0x010346
3063: if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",NULL))
3064: #else
3065: if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth"))
3066: #endif
3067: {
3068: printk("GDT-EISA: Unable to allocate IRQ\n");
3069: restore_flags(flags);
3070: scsi_unregister(shp);
3071: continue;
3072: }
3073: shp->unchecked_isa_dma = 0;
3074: shp->irq = ha->irq;
3075: shp->dma_channel = 0xff;
3076: for (i=0; i<MAXID; ++i) {
3077: if (ha->id[0][i].type==SIOP_DTYP) {
3078: shp->this_id = i;
3079: break;
3080: }
3081: }
3082: hanum = gdth_ctr_count;
3083: gdth_ctr_tab[gdth_ctr_count++] = shp;
3084: gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
3085:
3086: NUMDATA(shp)->hanum = (ushort)hanum;
3087: NUMDATA(shp)->busnum= 0;
3088: TRACE2(("EISA detect Bus 0: shp %lx hanum %d\n",
3089: (ulong)shp,NUMDATA(shp)->hanum));
3090:
3091: ha->pccb = CMDDATA(shp);
3092: ha->pscratch = DMADATA(shp);
3093: ha->req_first = NULL;
3094: for (i=0; i<MAXBUS; ++i) {
3095: for (j=0; j<MAXID; ++j) {
3096: ha->id[i][j].type = EMPTY_DTYP;
3097: ha->id[i][j].lock = 0;
3098: ha->id[i][j].heads = 0;
3099: }
3100: }
3101: restore_flags(flags);
3102:
3103: if (!gdth_search_drives(hanum)) {
3104: printk("GDT-EISA: Error during device scan\n");
3105: --gdth_ctr_count;
3106: --gdth_ctr_vcount;
3107: save_flags(flags);
3108: cli();
3109: #if LINUX_VERSION_CODE >= 0x010346
3110: free_irq(ha->irq,NULL);
3111: #else
3112: free_irq(ha->irq);
3113: #endif
3114: restore_flags(flags);
3115: scsi_unregister(shp);
3116: continue;
3117: }
3118:
3119: #if LINUX_VERSION_CODE >= 0x020000
3120: shp->max_id = 8;
3121: shp->max_lun = MAXLUN;
3122: shp->max_channel = ha->bus_cnt - 1;
3123: #else
3124: /* register addit. SCSI channels as virtual controllers */
3125: for (b=1; b<ha->bus_cnt; ++b) {
3126: shp = scsi_register(shtp,sizeof(gdth_num_str));
3127: shp->unchecked_isa_dma = 0;
3128: shp->irq = ha->irq;
3129: shp->dma_channel = 0xff;
3130: for (i=0; i<MAXID; ++i) {
3131: if (ha->id[b][i].type==SIOP_DTYP) {
3132: shp->this_id = i;
3133: break;
3134: }
3135: }
3136: gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
3137: NUMDATA(shp)->hanum = (ushort)hanum;
3138: NUMDATA(shp)->busnum = b;
3139: TRACE2(("EISA detect Bus %d: shp %lx hanum %d\n",
3140: NUMDATA(shp)->busnum,(ulong)shp,
3141: NUMDATA(shp)->hanum));
3142: }
3143: #endif
3144:
3145: gdth_enable_int(hanum);
3146: }
3147: }
3148:
3149: /* scanning for PCI controllers */
3150: for (device_id = 0; device_id <= PCI_DEVICE_ID_VORTEX_GDTMAXRP; ++device_id) {
3151: if (device_id > PCI_DEVICE_ID_VORTEX_GDT6555 &&
3152: device_id < PCI_DEVICE_ID_VORTEX_GDT6x17RP)
3153: continue;
3154: for (index = 0; ; ++index) {
3155: if (!gdth_search_pci(device_id,index,&pcistr))
3156: break; /* next device_id */
3157: shp = scsi_register(shtp,sizeof(gdth_ext_str));
3158: ha = HADATA(shp);
3159: if (!gdth_init_pci(&pcistr,ha)) {
3160: scsi_unregister(shp);
3161: continue;
3162: }
3163: /* controller found and initialized */
3164: printk("Configuring GDT-PCI HA at %d/%d IRQ %u\n",
3165: pcistr.bus,pcistr.device_fn>>3,ha->irq);
3166:
3167: save_flags(flags);
3168: cli();
3169: #if LINUX_VERSION_CODE >= 0x02015F
3170: if (request_irq(ha->irq,do_gdth_interrupt,SA_INTERRUPT|SA_SHIRQ,"gdth",NULL))
3171: #elif LINUX_VERSION_CODE >= 0x010346
3172: if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT|SA_SHIRQ,"gdth",NULL))
3173: #else
3174: if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT|SA_SHIRQ,"gdth"))
3175: #endif
3176: {
3177: printk("GDT-PCI: Unable to allocate IRQ\n");
3178: restore_flags(flags);
3179: scsi_unregister(shp);
3180: continue;
3181: }
3182: shp->unchecked_isa_dma = 0;
3183: shp->irq = ha->irq;
3184: shp->dma_channel = 0xff;
3185: for (i=0; i<MAXID; ++i) {
3186: if (ha->id[0][i].type==SIOP_DTYP) {
3187: shp->this_id = i;
3188: break;
3189: }
3190: }
3191: hanum = gdth_ctr_count;
3192: gdth_ctr_tab[gdth_ctr_count++] = shp;
3193: gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
3194:
3195: NUMDATA(shp)->hanum = (ushort)hanum;
3196: NUMDATA(shp)->busnum= 0;
3197:
3198: ha->pccb = CMDDATA(shp);
3199: ha->pscratch = DMADATA(shp);
3200: ha->req_first = NULL;
3201: for (i=0; i<MAXBUS; ++i) {
3202: for (j=0; j<MAXID; ++j) {
3203: ha->id[i][j].type = EMPTY_DTYP;
3204: ha->id[i][j].lock = 0;
3205: ha->id[i][j].heads = 0;
3206: }
3207: }
3208: restore_flags(flags);
3209:
3210: if (!gdth_search_drives(hanum)) {
3211: printk("GDT-PCI: Error during device scan\n");
3212: --gdth_ctr_count;
3213: --gdth_ctr_vcount;
3214: save_flags(flags);
3215: cli();
3216: #if LINUX_VERSION_CODE >= 0x010346
3217: free_irq(ha->irq,NULL);
3218: #else
3219: free_irq(ha->irq);
3220: #endif
3221: restore_flags(flags);
3222: scsi_unregister(shp);
3223: continue;
3224: }
3225:
3226: #if LINUX_VERSION_CODE >= 0x020000
3227: shp->max_id = MAXID;
3228: shp->max_lun = MAXLUN;
3229: shp->max_channel = ha->bus_cnt - 1;
3230: #else
3231: /* register addit. SCSI channels as virtual controllers */
3232: for (b=1; b<ha->bus_cnt; ++b) {
3233: shp = scsi_register(shtp,sizeof(gdth_num_str));
3234: shp->unchecked_isa_dma = 0;
3235: shp->irq = ha->irq;
3236: shp->dma_channel = 0xff;
3237: for (i=0; i<MAXID; ++i) {
3238: if (ha->id[b][i].type==SIOP_DTYP) {
3239: shp->this_id = i;
3240: break;
3241: }
3242: }
3243: gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
3244: NUMDATA(shp)->hanum = (ushort)hanum;
3245: NUMDATA(shp)->busnum = b;
3246: }
3247: #endif
3248:
3249: gdth_enable_int(hanum);
3250: }
3251: }
3252:
3253: TRACE2(("gdth_detect() %d controller detected\n",gdth_ctr_count));
3254: if (gdth_ctr_count > 0) {
3255: #ifdef GDTH_STATISTICS
3256: TRACE2(("gdth_detect(): Initializing timer !\n"));
3257: init_timer(&gdth_timer);
3258: gdth_timer.expires = jiffies + HZ;
3259: gdth_timer.data = 0L;
3260: gdth_timer.function = gdth_timeout;
3261: add_timer(&gdth_timer);
3262: #endif
3263: #if LINUX_VERSION_CODE >= 0x020100
3264: register_reboot_notifier(&gdth_notifier);
3265: #endif
3266: }
3267: gdth_polling = FALSE;
3268: return gdth_ctr_vcount;
3269: }
3270:
3271:
3272: int gdth_release(struct Scsi_Host *shp)
3273: {
3274: unsigned long flags;
3275:
3276: TRACE2(("gdth_release()\n"));
3277:
3278: if (NUMDATA(shp)->busnum == 0) {
3279: gdth_flush(NUMDATA(shp)->hanum);
3280:
3281: save_flags(flags);
3282: cli();
3283: if (shp->irq) {
3284: #if LINUX_VERSION_CODE >= 0x010346
3285: free_irq(shp->irq,NULL);
3286: #else
3287: free_irq(shp->irq);
3288: #endif
3289: }
3290: if (shp->dma_channel != 0xff) {
3291: free_dma(shp->dma_channel);
3292: }
3293: restore_flags(flags);
3294: gdth_ctr_released++;
3295: TRACE2(("gdth_release(): HA %d of %d\n",
3296: gdth_ctr_released, gdth_ctr_count));
3297:
3298: if (gdth_ctr_released == gdth_ctr_count) {
3299: #ifdef GDTH_STATISTICS
3300: del_timer(&gdth_timer);
3301: #endif
3302: #if LINUX_VERSION_CODE >= 0x020100
3303: unregister_reboot_notifier(&gdth_notifier);
3304: #endif
3305: }
3306: }
3307:
3308: scsi_unregister(shp);
3309: return 0;
3310: }
3311:
3312:
3313: static const char *gdth_ctr_name(int hanum)
3314: {
3315: gdth_ha_str *ha;
3316:
3317: TRACE2(("gdth_ctr_name()\n"));
3318:
3319: ha = HADATA(gdth_ctr_tab[hanum]);
3320:
3321: if (ha->type == GDT_EISA) {
3322: switch (ha->stype) {
3323: case GDT3_ID:
3324: return("GDT3000/3020");
3325: case GDT3A_ID:
3326: return("GDT3000A/3020A/3050A");
3327: case GDT3B_ID:
3328: return("GDT3000B/3010A");
3329: }
3330: } else if (ha->type == GDT_ISA) {
3331: return("GDT2000/2020");
3332: } else if (ha->type == GDT_PCI) {
3333: switch (ha->stype) {
3334: case PCI_DEVICE_ID_VORTEX_GDT60x0:
3335: return("GDT6000/6020/6050");
3336: case PCI_DEVICE_ID_VORTEX_GDT6000B:
3337: return("GDT6000B/6010");
3338: }
3339: }
3340: /* new controllers (GDT_PCINEW, GDT_PCIMPR, ..) use board_info IOCTL! */
3341:
3342: return("");
3343: }
3344:
3345: const char *gdth_info(struct Scsi_Host *shp)
3346: {
3347: int hanum;
3348: gdth_ha_str *ha;
3349:
3350: TRACE2(("gdth_info()\n"));
3351: hanum = NUMDATA(shp)->hanum;
3352: ha = HADATA(gdth_ctr_tab[hanum]);
3353:
3354: return ((const char *)ha->ctr_name);
3355: }
3356:
3357: /* old error handling */
3358: int gdth_abort(Scsi_Cmnd *scp)
3359: {
3360: TRACE2(("gdth_abort() reason %d\n",scp->abort_reason));
3361: return SCSI_ABORT_SNOOZE;
3362: }
3363:
3364: #if LINUX_VERSION_CODE >= 0x010346
3365: int gdth_reset(Scsi_Cmnd *scp, unsigned int reset_flags)
3366: #else
3367: int gdth_reset(Scsi_Cmnd *scp)
3368: #endif
3369: {
3370: TRACE2(("gdth_reset()\n"));
3371: return SCSI_RESET_PUNT;
3372: }
3373:
3374: #if LINUX_VERSION_CODE >= 0x02015F
3375: /* new error handling */
3376: int gdth_eh_abort(Scsi_Cmnd *scp)
3377: {
3378: TRACE2(("gdth_eh_abort()\n"));
3379: return FAILED;
3380: }
3381:
3382: int gdth_eh_device_reset(Scsi_Cmnd *scp)
3383: {
3384: TRACE2(("gdth_eh_device_reset()\n"));
3385: return FAILED;
3386: }
3387:
3388: int gdth_eh_bus_reset(Scsi_Cmnd *scp)
3389: {
3390: TRACE2(("gdth_eh_bus_reset()\n"));
3391: return FAILED;
3392: }
3393:
3394: int gdth_eh_host_reset(Scsi_Cmnd *scp)
3395: {
3396: TRACE2(("gdth_eh_host_reset()\n"));
3397: return FAILED;
3398: }
3399: #endif
3400:
3401: #if LINUX_VERSION_CODE >= 0x010300
3402: int gdth_bios_param(Disk *disk,kdev_t dev,int *ip)
3403: #else
3404: int gdth_bios_param(Disk *disk,int dev,int *ip)
3405: #endif
3406: {
3407: unchar b, t;
3408: int hanum;
3409: gdth_ha_str *ha;
3410: int drv_hds, drv_secs;
3411:
3412: hanum = NUMDATA(disk->device->host)->hanum;
3413: b = disk->device->channel;
3414: t = disk->device->id;
3415: TRACE2(("gdth_bios_param() ha %d bus %d target %d\n", hanum, b, t));
3416: ha = HADATA(gdth_ctr_tab[hanum]);
3417:
3418: if (ha->id[b][t].heads == 0) {
3419: /* raw device: evaluate mapping (sectors per head, heads per cylinder) */
3420: if (disk->capacity /HEADS/SECS <= MAXCYLS) {
3421: drv_hds = HEADS;
3422: drv_secs= SECS;
3423: } else if (disk->capacity /MEDHEADS/MEDSECS <= MAXCYLS) {
3424: drv_hds = MEDHEADS;
3425: drv_secs= MEDSECS;
3426: } else {
3427: drv_hds = BIGHEADS;
3428: drv_secs= BIGSECS;
3429: }
3430: ha->id[b][t].heads = drv_hds;
3431: ha->id[b][t].secs = drv_secs;
3432: TRACE2(("gdth_bios_param(): raw device -> params evaluated\n"));
3433: }
3434:
3435: ip[0] = ha->id[b][t].heads;
3436: ip[1] = ha->id[b][t].secs;
3437: ip[2] = disk->capacity / ip[0] / ip[1];
3438:
3439: TRACE2(("gdth_bios_param(): %d heads, %d secs, %d cyls\n",
3440: ip[0],ip[1],ip[2]));
3441: return 0;
3442: }
3443:
3444:
3445: static void internal_done(Scsi_Cmnd *scp)
3446: {
3447: scp->SCp.sent_command++;
3448: }
3449:
3450: int gdth_command(Scsi_Cmnd *scp)
3451: {
3452: TRACE2(("gdth_command()\n"));
3453:
3454: scp->SCp.sent_command = 0;
3455: gdth_queuecommand(scp,internal_done);
3456:
3457: while (!scp->SCp.sent_command)
3458: barrier();
3459: return scp->result;
3460: }
3461:
3462:
3463: int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *))
3464: {
3465: int hanum;
3466: int priority;
3467:
3468: TRACE(("gdth_queuecommand() cmd 0x%x id %d lun %d\n",
3469: scp->cmnd[0],scp->target,scp->lun));
3470:
3471: scp->scsi_done = (void *)done;
3472: scp->SCp.have_data_in = 1;
3473: hanum = NUMDATA(scp->host)->hanum;
3474: #ifdef GDTH_STATISTICS
3475: ++act_ios;
3476: #endif
3477:
3478: priority = DEFAULT_PRI;
3479: #if LINUX_VERSION_CODE >= 0x010300
3480: if (scp->done == gdth_scsi_done)
3481: priority = scp->SCp.this_residual;
3482: #endif
3483: gdth_putq( hanum, scp, priority );
3484: gdth_next( hanum );
3485: return 0;
3486: }
3487:
3488: /* flush routine */
3489: static void gdth_flush(int hanum)
3490: {
3491: int i, j;
3492: gdth_ha_str *ha;
3493: Scsi_Cmnd scp;
3494: Scsi_Device sdev;
3495: gdth_cmd_str gdtcmd;
3496: char cmnd[12];
3497:
3498: TRACE2(("gdth_flush() hanum %d\n",hanum));
3499: ha = HADATA(gdth_ctr_tab[hanum]);
3500: memset(&sdev,0,sizeof(Scsi_Device));
3501: memset(&scp, 0,sizeof(Scsi_Cmnd));
3502: sdev.host = gdth_ctr_tab[hanum];
3503: sdev.id = sdev.host->this_id;
3504: scp.cmd_len = 12;
3505: scp.host = gdth_ctr_tab[hanum];
3506: scp.target = sdev.host->this_id;
3507: scp.device = &sdev;
3508: scp.use_sg = 0;
3509:
3510: for (i = 0; i < MAXBUS; ++i) {
3511: for (j = 0; j < MAXID; ++j) {
3512: if (ha->id[i][j].type == CACHE_DTYP) {
3513: gdtcmd.BoardNode = LOCALBOARD;
3514: gdtcmd.Service = CACHESERVICE;
3515: gdtcmd.OpCode = GDT_FLUSH;
3516: gdtcmd.u.cache.DeviceNo = ha->id[i][j].hostdrive;
3517: gdtcmd.u.cache.BlockNo = 1;
3518: gdtcmd.u.cache.sg_canz = 0;
3519: TRACE2(("gdth_flush(): flush ha %d drive %d\n",
3520: hanum, ha->id[i][j].hostdrive));
3521: {
3522: struct semaphore sem = MUTEX_LOCKED;
3523: scp.request.rq_status = RQ_SCSI_BUSY;
3524: scp.request.sem = &sem;
3525: scp.SCp.this_residual = IOCTL_PRI;
3526: scsi_do_cmd(&scp, cmnd, &gdtcmd,
3527: sizeof(gdth_cmd_str), gdth_scsi_done,
3528: 30*HZ, 1);
3529: down(&sem);
3530: }
3531: }
3532: }
3533: }
3534: }
3535:
3536: /* shutdown routine */
3537: #if LINUX_VERSION_CODE >= 0x020100
3538: static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
3539: #else
3540: void gdth_halt(void)
3541: #endif
3542: {
3543: int hanum;
3544: Scsi_Cmnd scp;
3545: Scsi_Device sdev;
3546: gdth_cmd_str gdtcmd;
3547: char cmnd[12];
3548:
3549: #if LINUX_VERSION_CODE >= 0x020100
3550: TRACE2(("gdth_halt() event %d\n",event));
3551: if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF)
3552: return NOTIFY_DONE;
3553: #else
3554: TRACE2(("gdth_halt()\n"));
3555: if (halt_called) {
3556: TRACE2(("already called\n"));
3557: return;
3558: }
3559: halt_called = TRUE;
3560: #endif
3561: printk("GDT: Flushing all host drives .. ");
3562: for (hanum = 0; hanum < gdth_ctr_count; ++hanum) {
3563: gdth_flush(hanum);
3564:
3565: /* controller reset */
3566: memset(&sdev,0,sizeof(Scsi_Device));
3567: memset(&scp, 0,sizeof(Scsi_Cmnd));
3568: sdev.host = gdth_ctr_tab[hanum];
3569: sdev.id = sdev.host->this_id;
3570: scp.cmd_len = 12;
3571: scp.host = gdth_ctr_tab[hanum];
3572: scp.target = sdev.host->this_id;
3573: scp.device = &sdev;
3574: scp.use_sg = 0;
3575:
3576: gdtcmd.BoardNode = LOCALBOARD;
3577: gdtcmd.Service = CACHESERVICE;
3578: gdtcmd.OpCode = GDT_RESET;
3579: TRACE2(("gdth_halt(): reset controller %d\n", hanum));
3580: {
3581: struct semaphore sem = MUTEX_LOCKED;
3582: scp.request.rq_status = RQ_SCSI_BUSY;
3583: scp.request.sem = &sem;
3584: scp.SCp.this_residual = IOCTL_PRI;
3585: scsi_do_cmd(&scp, cmnd, &gdtcmd,
3586: sizeof(gdth_cmd_str), gdth_scsi_done,
3587: 10*HZ, 1);
3588: down(&sem);
3589: }
3590: }
3591: printk("Done.\n");
3592:
3593: #ifdef GDTH_STATISTICS
3594: del_timer(&gdth_timer);
3595: #endif
3596: #if LINUX_VERSION_CODE >= 0x020100
3597: unregister_reboot_notifier(&gdth_notifier);
3598: return NOTIFY_OK;
3599: #endif
3600: }
3601:
3602:
3603: /* called from init/main.c */
3604: __initfunc (void gdth_setup(char *str,int *ints))
3605: {
3606: static size_t setup_idx = 0;
3607:
3608: TRACE2(("gdth_setup() str %s ints[0] %d ints[1] %d\n",
3609: str ? str:"NULL", ints[0],
3610: ints[0] ? ints[1]:0));
3611:
3612: if (setup_idx >= MAXHA) {
3613: printk("GDT: gdth_setup() called too many times. Bad LILO params ?\n");
3614: return;
3615: }
3616: if (ints[0] != 1) {
3617: printk("GDT: Illegal command line !\n");
3618: printk("Usage: gdth=<IRQ>\n");
3619: printk("Where: <IRQ>: valid EISA controller IRQ (10,11,12,14)\n");
3620: printk(" or 0 to disable controller driver\n");
3621: return;
3622: }
3623: if (ints[1] == 10 || ints[1] == 11 || ints[1] == 12 || ints[1] == 14) {
3624: irqs[setup_idx++] = ints[1];
3625: irqs[setup_idx] = 0xff;
3626: return;
3627: }
3628: if (ints[1] == 0) {
3629: disable_gdth_scan = TRUE;
3630: return;
3631: }
3632: printk("GDT: Invalid IRQ (%d) specified\n",ints[1]);
3633: }
3634:
3635:
3636: #ifdef MODULE
3637: Scsi_Host_Template driver_template = GDTH;
3638: #include "scsi_module.c"
3639: #endif
3640:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.