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