2 * Copyright (c) 1997 by Simon Shapiro
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions, and the following disclaimer,
10 * without modification, immediately at the beginning of the file.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * dpt_control.c: Control Functions and /dev entry points for /dev/dpt*
34 * Caveat Emptor! This is work in progress. The interfaces and
35 * functionality of this code will change (possibly radically) in the
39 #ident "$FreeBSD: src/sys/dev/dpt/dpt_control.c,v 1.16 1999/09/25 18:23:48 phk Exp $"
40 #ident "$DragonFly: src/sys/dev/raid/dpt/dpt_control.c,v 1.14 2006/12/28 21:23:58 dillon Exp $"
44 #include <machine/cputypes.h>
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/malloc.h>
48 #include <sys/kernel.h>
52 #include <sys/thread2.h>
54 #include <vm/vm_kern.h>
55 #include <vm/vm_extern.h>
57 #include <scsi/scsiconf.h>
61 #define INLINE __inline
63 extern char osrelease
[];
65 enum dpt_message dpt_message
;
66 enum dpt_immediate_cmd dpt_immediate_cmd
;
68 static dpt_sysinfo_t dpt_sysinfo
;
70 /* Entry points and other prototypes */
71 static vm_offset_t
dpt_physmap(u_int32_t paddr
, vm_size_t size
);
72 static void dpt_unphysmap(u_int8_t
* vaddr
, vm_size_t size
);
74 static void dpt_get_sysinfo(void);
76 static int dpt_open(cdev_t dev
, int flags
, int fmt
, struct proc
* p
);
77 static int dpt_close(cdev_t dev
, int flags
, int fmt
, struct proc
* p
);
78 static int dpt_write(cdev_t dev
, struct uio
* uio
, int ioflag
);
79 static int dpt_read(cdev_t dev
, struct uio
* uio
, int ioflag
);
80 static int dpt_ioctl(cdev_t dev
, u_long cmd
, caddr_t cmdarg
, int flags
, struct proc
* p
);
83 /* This has to be modified as the processor and CPU are not known yet */
84 static dpt_sig_t dpt_sig
= {
85 'd', 'P', 't', 'S', 'i', 'G',
86 SIG_VERSION
, PROC_INTEL
, PROC_386
,
87 FT_HBADRVR
, FTF_PROTECTED
,
89 CAP_PASS
| CAP_OVERLAP
| CAP_RAID0
| CAP_RAID1
| CAP_RAID5
| CAP_ASPI
,
90 DEV_ALL
, ADF_SC4_PCI
| ADF_SC3_PCI
, 0, 0,
91 DPT_RELEASE
, DPT_VERSION
, DPT_PATCH
,
92 DPT_MONTH
, DPT_DAY
, DPT_YEAR
,
93 "DPT FreeBSD Driver (c) 1997 Simon Shapiro"
96 #define CDEV_MAJOR DPT_CDEV_MAJOR
98 /* Normally, this is a static structure. But we need it in pci/dpt_pci.c */
99 static struct cdevsw dpt_cdevsw
= {
101 /* maj */ CDEV_MAJOR
,
107 /* close */ dpt_close
,
109 /* write */ dpt_write
,
110 /* ioctl */ dpt_ioctl
,
113 /* strategy */ nostrategy
,
118 static struct buf
*dpt_inbuf
[DPT_MAX_ADAPTERS
];
119 static char dpt_rw_command
[DPT_MAX_ADAPTERS
][DPT_RW_CMD_LEN
+ 1];
123 * Given a minor device number,
124 * return the pointer to its softc structure
128 dpt_minor2softc(int minor_no
)
132 if (dpt_minor2unit(minor_no
& ~SCSI_CONTROL_MASK
) == -1)
135 for (dpt
= TAILQ_FIRST(&dpt_softc_list
);
136 (dpt
!= NULL
) && (dpt
->unit
!= (minor_no
& ~SCSI_CONTROL_MASK
));
137 dpt
= TAILQ_NEXT(dpt
, links
));
143 * Map a physical address to virtual one.
144 * This is a first cut, experimental thing
146 * Paddr is the physical address to map
147 * size is the size of the region, in bytes.
148 * Because of alignment problems, we actually round up the size requested to
149 * the next page count.
153 dpt_physmap(u_int32_t req_paddr
, vm_size_t req_size
)
163 size
= (req_size
/ PAGE_SIZE
+ 1) * PAGE_SIZE
;
164 paddr
= req_paddr
& 0xfffff000;
165 offset
= req_paddr
- paddr
;
167 va
= kmem_alloc_pageable(&kernel_map
, size
);
168 if (va
== (vm_offset_t
) 0)
171 for (ndx
= 0; ndx
< size
; ndx
+= PAGE_SIZE
) {
172 pmap_kenter(va
+ ndx
, paddr
+ ndx
);
176 return (va
+ offset
);
181 * Release virtual space allocated by physmap We ASSUME that the correct
182 * start address and the correct LENGTH are given.
184 * Disaster will follow if these assumptions are false!
188 dpt_unphysmap(u_int8_t
* vaddr
, vm_size_t size
)
192 for (ndx
= 0; ndx
< size
; ndx
+= PAGE_SIZE
) {
193 pmap_kremove((vm_offset_t
) vaddr
+ ndx
);
196 kmem_free(&kernel_map
, (vm_offset_t
) vaddr
, size
);
200 * Collect interesting system information
201 * The following is one of the worst hacks I have ever allowed my
202 * name to be associated with.
203 * There MUST be a system structure that provides this data.
207 dpt_get_sysinfo(void)
213 bzero(&dpt_sysinfo
, sizeof(dpt_sysinfo_t
));
216 * This is really silly, but we better run this in splhigh as we
217 * have no clue what we bump into.
218 * Let's hope anyone else who does this sort of things protects them
225 dpt_sig
.Processor
= dpt_sysinfo
.processorType
= PROC_386
;
228 dpt_sig
.Processor
= dpt_sysinfo
.processorType
= PROC_486
;
231 dpt_sig
.Processor
= dpt_sysinfo
.processorType
= PROC_PENTIUM
;
234 dpt_sig
.Processor
= dpt_sysinfo
.processorType
= PROC_P6
;
237 dpt_sig
.Processor
= dpt_sysinfo
.flags
&= ~SI_ProcessorValid
;
241 /* Get The First Drive Type From CMOS */
250 dpt_sysinfo
.drive0CMOS
= j
;
252 /* Get The Second Drive Type From CMOS */
258 dpt_sysinfo
.drive1CMOS
= j
;
260 /* Get The Number Of Drives From The Bios Data Area */
261 if ((addr
= (char *) dpt_physmap(0x0475, 1024)) == NULL
) {
262 kprintf("DPT: Cannot map BIOS address 0x0475. No sysinfo... :-(\n");
265 dpt_sysinfo
.numDrives
= *addr
;
266 dpt_unphysmap(addr
, 1024);
268 /* Get the processor fields from the SIG structure, and set the flags */
269 dpt_sysinfo
.processorFamily
= dpt_sig
.ProcessorFamily
;
270 dpt_sysinfo
.flags
= SI_CMOS_Valid
| SI_NumDrivesValid
;
272 /* Go out and look for SmartROM */
273 for (i
= 0; i
< 3; ++i
) {
276 addr
= (char *) dpt_physmap(0xC8000, 1024);
278 addr
= (char *) dpt_physmap(0xD8000, 1024);
280 addr
= (char *) dpt_physmap(0xDC000, 1024);
286 if (*((u_int16_t
*) addr
) == 0xaa55) {
287 if ((*((u_int32_t
*) (addr
+ 6)) == 0x00202053)
288 && (*((u_int32_t
*) (addr
+ 10)) == 0x00545044)) {
292 dpt_unphysmap(addr
, 1024);
297 * If i < 3, we founday it so set up a pointer to the starting
298 * version digit by searching for it.
302 for (i
= 0; i
< 64; ++i
)
303 if ((addr
[i
] == ' ') && (addr
[i
+ 1] == 'v'))
308 dpt_unphysmap(addr
, 1024);
312 /* If all is well, set up the SmartROM version fields */
314 dpt_sysinfo
.smartROMMajorVersion
= *addr
- '0'; /* Assumes ASCII */
315 dpt_sysinfo
.smartROMMinorVersion
= *(addr
+ 2);
316 dpt_sysinfo
.smartROMRevision
= *(addr
+ 3);
317 dpt_sysinfo
.flags
|= SI_SmartROMverValid
;
319 dpt_sysinfo
.flags
|= SI_NO_SmartROM
;
322 /* Get the conventional memory size from CMOS */
328 dpt_sysinfo
.conventionalMemSize
= j
;
331 * Get the extended memory found at power on from CMOS
338 dpt_sysinfo
.extendedMemSize
= j
;
339 dpt_sysinfo
.flags
|= SI_MemorySizeValid
;
341 /* If there is 1 or 2 drives found, set up the drive parameters */
342 if (dpt_sysinfo
.numDrives
> 0) {
343 /* Get the pointer from int 41 for the first drive parameters */
344 addr
= (char *) dpt_physmap(0x0104, 1024);
347 j
= *((ushort
*) (addr
+ 2));
349 j
+= *((ushort
*) (addr
));
350 dpt_unphysmap(addr
, 1024);
351 addr
= (char *) dpt_physmap(j
, 1024);
354 dpt_sysinfo
.drives
[0].cylinders
= *((ushort
*) addr
);
355 dpt_sysinfo
.drives
[0].heads
= *(addr
+ 2);
356 dpt_sysinfo
.drives
[0].sectors
= *(addr
+ 14);
357 dpt_unphysmap(addr
, 1024);
360 if (dpt_sysinfo
.numDrives
> 1) {
362 * Get the pointer from Int 46 for the second drive
365 addr
= (char *) dpt_physmap(0x01118, 1024);
366 j
= *((ushort
*) (addr
+ 2));
368 j
+= *((ushort
*) (addr
));
369 dpt_unphysmap(addr
, 1024);
370 addr
= (char *) dpt_physmap(j
, 1024);
373 dpt_sysinfo
.drives
[1].cylinders
= *((ushort
*) addr
);
374 dpt_sysinfo
.drives
[1].heads
= *(addr
+ 2);
375 dpt_sysinfo
.drives
[1].sectors
= *(addr
+ 14);
376 dpt_unphysmap(addr
, 1024);
379 dpt_sysinfo
.flags
|= SI_DriveParamsValid
;
383 /* Get the processor information */
384 dpt_sysinfo
.flags
|= SI_ProcessorValid
;
386 /* Get the bus I/O bus information */
387 dpt_sysinfo
.flags
|= SI_BusTypeValid
;
388 dpt_sysinfo
.busType
= HBA_BUS_PCI
;
390 /* XXX Use _FreeBSD_Version_ */
391 dpt_sysinfo
.osType
= OS_FREEBSD
;
392 dpt_sysinfo
.osMajorVersion
= osrelease
[0] - '0';
393 if (osrelease
[1] == '.')
394 dpt_sysinfo
.osMinorVersion
= osrelease
[2] - '0';
396 dpt_sysinfo
.osMinorVersion
= 0;
397 if (osrelease
[3] == '.')
398 dpt_sysinfo
.osRevision
= osrelease
[4] - '0';
400 dpt_sysinfo
.osMinorVersion
= 0;
401 if (osrelease
[5] == '.')
402 dpt_sysinfo
.osSubRevision
= osrelease
[6] - '0';
404 dpt_sysinfo
.osMinorVersion
= 0;
407 dpt_sysinfo
.flags
|= SI_OSversionValid
;
411 dpt_open(cdev_t dev
, int flags
, int fmt
, struct proc
* p
)
416 minor_no
= minor(dev
);
418 if (dpt_minor2unit(minor_no
) == -1)
421 dpt
= dpt_minor2softc(minor_no
);
428 if (dpt
->state
& DPT_HA_CONTROL_ACTIVE
) {
432 if ((dpt_inbuf
[minor_no
& ~SCSI_CONTROL_MASK
] = geteblk(PAGE_SIZE
))
434 #ifdef DPT_DEBUG_CONTROL
435 kprintf("dpt%d: Failed to obtain an I/O buffer\n",
436 minor_no
& ~SCSI_CONTROL_MASK
);
443 dpt
->state
|= DPT_HA_CONTROL_ACTIVE
;
449 dpt_close(cdev_t dev
, int flags
, int fmt
, struct proc
* p
)
454 minor_no
= minor(dev
);
455 dpt
= dpt_minor2softc(minor_no
);
457 if ((dpt_minor2unit(minor_no
) == -1) || (dpt
== NULL
))
460 brelse(dpt_inbuf
[minor_no
& ~SCSI_CONTROL_MASK
]);
461 dpt
->state
&= ~DPT_HA_CONTROL_ACTIVE
;
467 dpt_write(cdev_t dev
, struct uio
* uio
, int ioflag
)
473 minor_no
= minor(dev
);
475 if (minor_no
& SCSI_CONTROL_MASK
) {
476 #ifdef DPT_DEBUG_CONTROL
477 kprintf("dpt%d: I/O attempted to control channel (%x)\n",
478 dpt_minor2unit(minor_no
), minor_no
);
482 unit
= dpt_minor2unit(minor_no
);
486 } else if (uio
->uio_resid
> DPT_RW_CMD_LEN
) {
492 cp
= dpt_inbuf
[minor_no
]->b_data
;
493 length
= uio
->uio_resid
; /* uiomove will change it! */
495 if ((error
= uiomove(cp
, length
, uio
) != 0)) {
496 #ifdef DPT_DEBUG_CONTROL
497 kprintf("dpt%d: uiomove(%x, %d, %x) failed (%d)\n",
498 minor_no
, cp
, length
, uio
, error
);
504 /* A real kludge, to allow plain echo(1) to work */
505 if (cp
[length
- 1] == '\n')
506 cp
[length
- 1] = '\0';
508 strncpy(dpt_rw_command
[unit
], cp
, DPT_RW_CMD_LEN
);
509 #ifdef DPT_DEBUG_CONTROL
511 * For lack of anything better to do;
512 * For now, dump the data so we can look at it and rejoice
514 kprintf("dpt%d: Command \"%s\" arrived\n",
515 unit
, dpt_rw_command
[unit
]);
524 dpt_read(cdev_t dev
, struct uio
* uio
, int ioflag
)
530 minor_no
= minor(dev
);
533 #ifdef DPT_DEBUG_CONTROL
534 kprintf("dpt%d: read, count = %d, dev = %08x\n",
535 minor_no
, uio
->uio_resid
, dev
);
538 if (minor_no
& SCSI_CONTROL_MASK
) {
539 #ifdef DPT_DEBUG_CONTROL
540 kprintf("dpt%d: I/O attempted to control channel (%x)\n",
541 dpt_minor2unit(minor_no
), minor_no
);
545 if (dpt_minor2unit(minor_no
) == -1) {
549 * else if ( uio->uio_resid > PAGE_SIZE ) { return(E2BIG); }
559 if ((dpt
= dpt_minor2softc(minor_no
)) == NULL
)
562 work_buffer
= (u_int8_t
*) kmalloc(PAGE_SIZE
, M_TEMP
, M_WAITOK
);
568 command
= dpt_rw_command
[dpt
->unit
];
569 if (strcmp(command
, DPT_RW_CMD_DUMP_SOFTC
) == 0) {
570 x
= ksprintf(wbp
, "dpt%d:%s:%s:%s:%s:%x\n",
572 dpt
->board_data
.vendor
,
573 dpt
->board_data
.modelNum
,
574 dpt
->board_data
.firmware
,
575 dpt
->board_data
.protocol
,
580 } else if (strcmp(command
, DPT_RW_CMD_DUMP_SYSINFO
) == 0) {
581 x
= ksprintf(wbp
, "dpt%d:%d:%d:%d:%d:%d:%d:%d:%d:%s:"
582 "%d:%d:%d:%d:%d:%d:%d:%d\n",
584 dpt_sysinfo
.drive0CMOS
,
585 dpt_sysinfo
.drive1CMOS
,
586 dpt_sysinfo
.numDrives
,
587 dpt_sysinfo
.processorFamily
,
588 dpt_sysinfo
.processorType
,
589 dpt_sysinfo
.smartROMMajorVersion
,
590 dpt_sysinfo
.smartROMMinorVersion
,
591 dpt_sysinfo
.smartROMRevision
,
592 i2bin(dpt_sysinfo
.flags
,
593 sizeof(dpt
->queue_status
) * 8),
594 dpt_sysinfo
.conventionalMemSize
,
595 dpt_sysinfo
.extendedMemSize
,
596 dpt_sysinfo
.osType
, dpt_sysinfo
.osMajorVersion
,
597 dpt_sysinfo
.osMinorVersion
, dpt_sysinfo
.osRevision
,
598 dpt_sysinfo
.osSubRevision
, dpt_sysinfo
.busType
);
602 for (ndx
= 0; ndx
< 16; ndx
++) {
603 if (dpt_sysinfo
.drives
[ndx
].cylinders
!= 0) {
604 x
= ksprintf(wbp
, "dpt%d:d%dc%dh%ds%d\n",
607 dpt_sysinfo
.drives
[ndx
].cylinders
,
608 dpt_sysinfo
.drives
[ndx
].heads
,
609 dpt_sysinfo
.drives
[ndx
].sectors
);
614 } else if (strcmp(command
, DPT_RW_CMD_DUMP_METRICS
) == 0) {
616 "dpt%d: No metrics available.\n"
617 "Run the dpt_dm command, or use the\n"
618 "DPT_IOCTL_INTERNAL_METRICS ioctl system call\n",
622 } else if (strcmp(command
, DPT_RW_CMD_CLEAR_METRICS
) == 0) {
623 #ifdef DPT_MEASURE_PERFORMANCE
624 dpt_reset_performance(dpt
);
625 #endif /* DPT_MEASURE_PERFORMANCE */
627 x
= ksprintf(wbp
, "dpt%d: Metrics have been cleared\n",
631 } else if (strcmp(command
, DPT_RW_CMD_SHOW_LED
) == 0) {
633 x
= ksprintf(wbp
, "dpt%d:%s\n",
634 dpt
->unit
, i2bin(dpt_blinking_led(dpt
), 8));
638 #ifdef DPT_DEBUG_CONTROL
639 kprintf("dpt%d: Bad READ state (%s)\n", minor_no
, command
);
646 work_buffer
[work_size
++] = '\0';
647 error
= uiomove(work_buffer
, work_size
, uio
);
649 #ifdef DPT_DEBUG_CONTROL
651 kprintf("dpt%d: READ uimove failed (%d)\n", dpt
->unit
, error
);
661 * This is the control syscall interface.
662 * It should be binary compatible with UnixWare,
663 * if not totally syntatically so.
667 dpt_ioctl(cdev_t dev
, u_long cmd
, caddr_t cmdarg
, int flags
, struct proc
* p
)
671 dpt_user_softc_t udpt
;
674 eata_pt_t
*eata_pass_thru
;
676 minor_no
= minor(dev
);
679 if (!(minor_no
& SCSI_CONTROL_MASK
)) {
680 #ifdef DPT_DEBUG_CONTROL
681 kprintf("dpt%d: Control attempted to I/O channel (%x)\n",
682 dpt_minor2unit(minor_no
), minor_no
);
686 minor_no
&= ~SCSI_CONTROL_MASK
;
688 #ifdef DPT_DEBUG_CONTROL
689 kprintf("dpt%d: IOCTL(%x, %x, %p, %x, %p)\n",
690 minor_no
, dev
, cmd
, cmdarg
, flags
, p
);
693 if ((dpt
= dpt_minor2softc(minor_no
)) == NULL
)
697 #ifdef DPT_MEASURE_PERFORMANCE
698 case DPT_IOCTL_INTERNAL_METRICS
:
699 memcpy(cmdarg
, &dpt
->performance
, sizeof(dpt
->performance
));
701 #endif /* DPT_MEASURE_PERFORMANCE */
702 case DPT_IOCTL_SOFTC
:
703 udpt
.unit
= dpt
->unit
;
704 udpt
.handle_interrupts
= dpt
->handle_interrupts
;
705 udpt
.target_mode_enabled
= dpt
->target_mode_enabled
;
706 udpt
.spare
= dpt
->spare
;
708 udpt
.total_ccbs_count
= dpt
->total_ccbs_count
;
709 udpt
.free_ccbs_count
= dpt
->free_ccbs_count
;
710 udpt
.waiting_ccbs_count
= dpt
->waiting_ccbs_count
;
711 udpt
.submitted_ccbs_count
= dpt
->submitted_ccbs_count
;
712 udpt
.completed_ccbs_count
= dpt
->completed_ccbs_count
;
714 udpt
.queue_status
= dpt
->queue_status
;
715 udpt
.free_lock
= dpt
->free_lock
;
716 udpt
.waiting_lock
= dpt
->waiting_lock
;
717 udpt
.submitted_lock
= dpt
->submitted_lock
;
718 udpt
.completed_lock
= dpt
->completed_lock
;
720 udpt
.commands_processed
= dpt
->commands_processed
;
721 udpt
.lost_interrupts
= dpt
->lost_interrupts
;
723 udpt
.channels
= dpt
->channels
;
724 udpt
.max_id
= dpt
->max_id
;
725 udpt
.max_lun
= dpt
->max_lun
;
727 udpt
.io_base
= dpt
->io_base
;
728 udpt
.v_membase
= (u_int8_t
*) dpt
->v_membase
;
729 udpt
.p_membase
= (u_int8_t
*) dpt
->p_membase
;
732 udpt
.dma_channel
= dpt
->dma_channel
;
734 udpt
.board_data
= dpt
->board_data
;
735 udpt
.EATA_revision
= dpt
->EATA_revision
;
736 udpt
.bustype
= dpt
->bustype
;
737 udpt
.state
= dpt
->state
;
739 udpt
.primary
= dpt
->primary
;
740 udpt
.more_support
= dpt
->more_support
;
741 udpt
.immediate_support
= dpt
->immediate_support
;
742 udpt
.broken_INQUIRY
= dpt
->broken_INQUIRY
;
743 udpt
.spare2
= dpt
->spare2
;
745 for (ndx
= 0; ndx
< MAX_CHANNELS
; ndx
++) {
746 udpt
.resetlevel
[ndx
] = dpt
->resetlevel
[ndx
];
747 udpt
.hostid
[ndx
] = dpt
->hostid
[ndx
];
750 udpt
.last_ccb
= dpt
->last_ccb
;
751 udpt
.cplen
= dpt
->cplen
;
752 udpt
.cppadlen
= dpt
->cppadlen
;
753 udpt
.queuesize
= dpt
->queuesize
;
754 udpt
.sgsize
= dpt
->sgsize
;
755 udpt
.cache_type
= dpt
->cache_type
;
756 udpt
.cache_size
= dpt
->cache_size
;
758 memcpy(cmdarg
, &udpt
, sizeof(dpt_user_softc_t
));
762 eata_pass_thru
= (eata_pt_t
*) cmdarg
;
764 if ((eata_pass_thru
->eataID
[0] != 'E')
765 || (eata_pass_thru
->eataID
[1] != 'A')
766 || (eata_pass_thru
->eataID
[2] != 'T')
767 || (eata_pass_thru
->eataID
[3] != 'A')) {
770 switch (eata_pass_thru
->command
) {
772 return (copyout((char *) &dpt_sig
,
773 (caddr_t
*) eata_pass_thru
->command_buffer
,
776 return (copyout((char *) &dpt_controllers_present
,
777 (caddr_t
*) eata_pass_thru
->command_buffer
,
778 sizeof(dpt_controllers_present
)));
781 dpt_compat_ha_t compat_softc
;
784 compat_softc
.ha_state
= dpt
->state
; /* Different Meaning! */
785 for (ndx
= 0; ndx
< MAX_CHANNELS
; ndx
++)
786 compat_softc
.ha_id
[ndx
] = dpt
->hostid
[ndx
];
788 compat_softc
.ha_vect
= dpt
->irq
;
789 compat_softc
.ha_base
= BaseRegister(dpt
);
790 compat_softc
.ha_max_jobs
= dpt
->total_ccbs_count
;
791 compat_softc
.ha_cache
= dpt
->cache_type
;
792 compat_softc
.ha_cachesize
= dpt
->cache_size
;
793 compat_softc
.ha_nbus
= dpt
->dma_channel
+ 1;
794 compat_softc
.ha_ntargets
= dpt
->max_id
+ 1;
795 compat_softc
.ha_nluns
= dpt
->max_lun
+ 1;
796 compat_softc
.ha_tshift
= (dpt
->max_id
== 7) ? 3 : 4;
797 compat_softc
.ha_bshift
= 2;
798 compat_softc
.ha_npend
= dpt
->submitted_ccbs_count
;
799 compat_softc
.ha_active_jobs
= dpt
->waiting_ccbs_count
;
800 strncpy(compat_softc
.ha_fw_version
,
801 dpt
->board_data
.firmware
,
802 sizeof(compat_softc
.ha_fw_version
));
803 compat_softc
.ha_ccb
= NULL
;
804 compat_softc
.ha_cblist
= NULL
;
805 compat_softc
.ha_dev
= NULL
;
806 compat_softc
.ha_StPkt_lock
= NULL
;
807 compat_softc
.ha_ccb_lock
= NULL
;
808 compat_softc
.ha_LuQWaiting
= NULL
;
809 compat_softc
.ha_QWait_lock
= NULL
;
810 compat_softc
.ha_QWait_opri
= NULL
;
812 return (copyout((char *) &compat_softc
,
813 (caddr_t
*) eata_pass_thru
->command_buffer
,
814 sizeof(dpt_compat_ha_t
)));
819 return (copyout((char *) &dpt_sysinfo
,
820 (caddr_t
*) eata_pass_thru
->command_buffer
,
821 sizeof(dpt_sysinfo
)));
823 result
= dpt_user_cmd(dpt
, eata_pass_thru
, cmdarg
, minor_no
);
826 result
= dpt_blinking_led(dpt
);
827 return (copyout((caddr_t
) & result
,
828 (caddr_t
*) eata_pass_thru
->command_buffer
,
831 kprintf("dpt%d: Invalid (%x) pass-throu command\n",
832 dpt
->unit
, eata_pass_thru
->command
);
837 kprintf("dpt%d: Invalid (%lx) IOCTL\n", dpt
->unit
, cmd
);
845 static dpt_devsw_installed
= 0;
848 dpt_drvinit(void *unused
)
850 if (!dpt_devsw_installed
) {
852 kprintf("DPT: RAID Manager driver, Version %d.%d.%d\n",
853 DPT_CTL_RELEASE
, DPT_CTL_VERSION
, DPT_CTL_PATCH
);
855 /* Add the I/O (data) channel */
856 cdevsw_add(&dpt_cdevsw
, 0, 0);
858 dpt_devsw_installed
= 1;
863 SYSINIT(dpt_dev
, SI_SUB_DRIVERS
, SI_ORDER_MIDDLE
+ CDEV_MAJOR
, dpt_drvinit
, NULL
)
864 /* End of the dpt_control driver */