2 * Copyright (c) 2011 HighPoint Technologies, Inc.
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 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * $FreeBSD: src/sys/dev/hpt27xx/osm_bsd.c,v 1.1 2011/12/28 23:26:58 delphij Exp $
29 #include <dev/raid/hpt27xx/hpt27xx_config.h>
31 #include <dev/raid/hpt27xx/os_bsd.h>
32 #include <dev/raid/hpt27xx/hptintf.h>
34 static int hpt_probe(device_t dev
)
41 for (him
= him_list
; him
; him
= him
->next
) {
42 for (i
=0; him
->get_supported_device_id(i
, &pci_id
); i
++) {
43 if (him
->get_controller_count
)
44 him
->get_controller_count(&pci_id
,0,0);
45 if ((pci_get_vendor(dev
) == pci_id
.vid
) &&
46 (pci_get_device(dev
) == pci_id
.did
)){
47 KdPrint(("hpt_probe: adapter at PCI %d:%d:%d, IRQ %d",
48 pci_get_bus(dev
), pci_get_slot(dev
), pci_get_function(dev
), pci_get_irq(dev
)
50 device_set_desc(dev
, him
->name
);
51 hba
= (PHBA
)device_get_softc(dev
);
52 memset(hba
, 0, sizeof(HBA
));
53 hba
->ext_type
= EXT_TYPE_HBA
;
54 hba
->ldm_adapter
.him
= him
;
63 static int hpt_attach(device_t dev
)
65 PHBA hba
= (PHBA
)device_get_softc(dev
);
66 HIM
*him
= hba
->ldm_adapter
.him
;
72 KdPrint(("hpt_attach(%d/%d/%d)", pci_get_bus(dev
), pci_get_slot(dev
), pci_get_function(dev
)));
74 pci_enable_busmaster(dev
);
76 pci_id
.vid
= pci_get_vendor(dev
);
77 pci_id
.did
= pci_get_device(dev
);
78 pci_id
.rev
= pci_get_revid(dev
);
79 pci_id
.subsys
= (HPT_U32
)(pci_get_subdevice(dev
)) << 16 | pci_get_subvendor(dev
);
81 size
= him
->get_adapter_size(&pci_id
);
82 hba
->ldm_adapter
.him_handle
= kmalloc(size
, M_DEVBUF
, M_WAITOK
);
83 if (!hba
->ldm_adapter
.him_handle
)
87 hba
->pciaddr
.tree
= 0;
88 hba
->pciaddr
.bus
= pci_get_bus(dev
);
89 hba
->pciaddr
.device
= pci_get_slot(dev
);
90 hba
->pciaddr
.function
= pci_get_function(dev
);
92 if (!him
->create_adapter(&pci_id
, hba
->pciaddr
, hba
->ldm_adapter
.him_handle
, hba
)) {
93 kfree(hba
->ldm_adapter
.him_handle
, M_DEVBUF
);
97 os_printk("adapter at PCI %d:%d:%d, IRQ %d",
98 hba
->pciaddr
.bus
, hba
->pciaddr
.device
, hba
->pciaddr
.function
, pci_get_irq(dev
));
100 if (!ldm_register_adapter(&hba
->ldm_adapter
)) {
101 size
= ldm_get_vbus_size();
102 vbus_ext
= kmalloc(sizeof(VBUS_EXT
) + size
, M_DEVBUF
, M_WAITOK
);
103 memset(vbus_ext
, 0, sizeof(VBUS_EXT
));
104 vbus_ext
->ext_type
= EXT_TYPE_VBUS
;
105 ldm_create_vbus((PVBUS
)vbus_ext
->vbus
, vbus_ext
);
106 ldm_register_adapter(&hba
->ldm_adapter
);
109 ldm_for_each_vbus(vbus
, vbus_ext
) {
110 if (hba
->ldm_adapter
.vbus
==vbus
) {
111 hba
->vbus_ext
= vbus_ext
;
112 hba
->next
= vbus_ext
->hba_list
;
113 vbus_ext
->hba_list
= hba
;
121 * Maybe we'd better to use the bus_dmamem_alloc to alloc DMA memory,
122 * but there are some problems currently (alignment, etc).
124 static __inline
void *__get_free_pages(int order
)
126 /* don't use low memory - other devices may get starved */
127 return contigmalloc(PAGE_SIZE
<<order
,
128 M_DEVBUF
, M_WAITOK
, BUS_SPACE_MAXADDR_24BIT
, BUS_SPACE_MAXADDR
, PAGE_SIZE
, 0);
131 static __inline
void free_pages(void *p
, int order
)
133 contigfree(p
, PAGE_SIZE
<<order
, M_DEVBUF
);
136 static int hpt_alloc_mem(PVBUS_EXT vbus_ext
)
143 for (hba
= vbus_ext
->hba_list
; hba
; hba
= hba
->next
)
144 hba
->ldm_adapter
.him
->get_meminfo(hba
->ldm_adapter
.him_handle
);
146 ldm_get_mem_info((PVBUS
)vbus_ext
->vbus
, 0);
148 for (f
=vbus_ext
->freelist_head
; f
; f
=f
->next
) {
149 KdPrint(("%s: %d*%d=%d bytes",
150 f
->tag
, f
->count
, f
->size
, f
->count
*f
->size
));
151 for (i
=0; i
<f
->count
; i
++) {
152 p
= (void **)kmalloc(f
->size
, M_DEVBUF
, M_WAITOK
);
153 if (!p
) return (ENXIO
);
159 for (f
=vbus_ext
->freelist_dma_head
; f
; f
=f
->next
) {
162 HPT_ASSERT((f
->size
& (f
->alignment
-1))==0);
164 for (order
=0, size
=PAGE_SIZE
; size
<f
->size
; order
++, size
<<=1) ;
166 KdPrint(("%s: %d*%d=%d bytes, order %d",
167 f
->tag
, f
->count
, f
->size
, f
->count
*f
->size
, order
));
168 HPT_ASSERT(f
->alignment
<=PAGE_SIZE
);
170 for (i
=0; i
<f
->count
;) {
171 p
= (void **)__get_free_pages(order
);
173 for (j
= size
/f
->size
; j
&& i
<f
->count
; i
++,j
--) {
175 *(BUS_ADDRESS
*)(p
+1) = (BUS_ADDRESS
)vtophys(p
);
177 p
= (void **)((unsigned long)p
+ f
->size
);
182 HPT_ASSERT(PAGE_SIZE
==DMAPOOL_PAGE_SIZE
);
184 for (i
=0; i
<os_max_cache_pages
; i
++) {
185 p
= (void **)__get_free_pages(0);
187 HPT_ASSERT(((HPT_UPTR
)p
& (DMAPOOL_PAGE_SIZE
-1))==0);
188 dmapool_put_page((PVBUS
)vbus_ext
->vbus
, p
, (BUS_ADDRESS
)vtophys(p
));
194 static void hpt_free_mem(PVBUS_EXT vbus_ext
)
201 for (f
=vbus_ext
->freelist_head
; f
; f
=f
->next
) {
203 if (f
->count
!=f
->reserved_count
) {
204 KdPrint(("memory leak for freelist %s (%d/%d)", f
->tag
, f
->count
, f
->reserved_count
));
207 while ((p
=freelist_get(f
)))
211 for (i
=0; i
<os_max_cache_pages
; i
++) {
212 p
= dmapool_get_page((PVBUS
)vbus_ext
->vbus
, &bus
);
217 for (f
=vbus_ext
->freelist_dma_head
; f
; f
=f
->next
) {
220 if (f
->count
!=f
->reserved_count
) {
221 KdPrint(("memory leak for dma freelist %s (%d/%d)", f
->tag
, f
->count
, f
->reserved_count
));
224 for (order
=0, size
=PAGE_SIZE
; size
<f
->size
; order
++, size
<<=1) ;
226 while ((p
=freelist_get_dma(f
, &bus
))) {
228 free_pages(p
, order
);
230 /* can't free immediately since other blocks in this page may still be in the list */
231 if (((HPT_UPTR
)p
& (PAGE_SIZE
-1))==0)
232 dmapool_put_page((PVBUS
)vbus_ext
->vbus
, p
, bus
);
237 while ((p
= dmapool_get_page((PVBUS
)vbus_ext
->vbus
, &bus
)))
241 static int hpt_init_vbus(PVBUS_EXT vbus_ext
)
245 for (hba
= vbus_ext
->hba_list
; hba
; hba
= hba
->next
)
246 if (!hba
->ldm_adapter
.him
->initialize(hba
->ldm_adapter
.him_handle
)) {
247 KdPrint(("fail to initialize %p", hba
));
251 ldm_initialize_vbus((PVBUS
)vbus_ext
->vbus
, &vbus_ext
->hba_list
->ldm_adapter
);
255 static void hpt_flush_done(PCOMMAND pCmd
)
257 PVDEV vd
= pCmd
->target
;
259 if (mIsArray(vd
->type
) && vd
->u
.array
.transform
&& vd
!=vd
->u
.array
.transform
->target
) {
260 vd
= vd
->u
.array
.transform
->target
;
263 pCmd
->Result
= RETURN_PENDING
;
264 vdev_queue_cmd(pCmd
);
268 *(int *)pCmd
->priv
= 1;
273 * flush a vdev (without retry).
275 static int hpt_flush_vdev(PVBUS_EXT vbus_ext
, PVDEV vd
)
278 int result
= 0, done
;
281 KdPrint(("flusing dev %p", vd
));
283 hpt_lock_vbus(vbus_ext
);
285 if (mIsArray(vd
->type
) && vd
->u
.array
.transform
)
286 count
= MAX(vd
->u
.array
.transform
->source
->cmds_per_request
,
287 vd
->u
.array
.transform
->target
->cmds_per_request
);
289 count
= vd
->cmds_per_request
;
291 pCmd
= ldm_alloc_cmds(vd
->vbus
, count
);
294 hpt_unlock_vbus(vbus_ext
);
298 pCmd
->type
= CMD_TYPE_FLUSH
;
299 pCmd
->flags
.hard_flush
= 1;
301 pCmd
->done
= hpt_flush_done
;
308 while (hpt_sleep(vbus_ext
, pCmd
, 0, "hptfls", HPT_OSM_TIMEOUT
)) {
309 ldm_reset_vbus(vd
->vbus
);
313 KdPrint(("flush result %d", pCmd
->Result
));
315 if (pCmd
->Result
!=RETURN_SUCCESS
)
320 hpt_unlock_vbus(vbus_ext
);
325 static void hpt_stop_tasks(PVBUS_EXT vbus_ext
);
326 static void hpt_shutdown_vbus(PVBUS_EXT vbus_ext
, int howto
)
328 PVBUS vbus
= (PVBUS
)vbus_ext
->vbus
;
332 KdPrint(("hpt_shutdown_vbus"));
334 /* stop all ctl tasks and disable the worker taskqueue */
335 hpt_stop_tasks(vbus_ext
);
336 vbus_ext
->worker
.ta_context
= NULL
;
339 for (i
=0; i
<osm_max_targets
; i
++) {
340 PVDEV vd
= ldm_find_target(vbus
, i
);
343 if (hpt_flush_vdev(vbus_ext
, vd
))
344 hpt_flush_vdev(vbus_ext
, vd
);
348 hpt_lock_vbus(vbus_ext
);
350 hpt_unlock_vbus(vbus_ext
);
352 ldm_release_vbus(vbus
);
354 for (hba
=vbus_ext
->hba_list
; hba
; hba
=hba
->next
)
355 bus_teardown_intr(hba
->pcidev
, hba
->irq_res
, hba
->irq_handle
);
357 hpt_free_mem(vbus_ext
);
359 while ((hba
=vbus_ext
->hba_list
)) {
360 vbus_ext
->hba_list
= hba
->next
;
361 kfree(hba
->ldm_adapter
.him_handle
, M_DEVBUF
);
364 kfree(vbus_ext
, M_DEVBUF
);
365 KdPrint(("hpt_shutdown_vbus done"));
368 static void __hpt_do_tasks(PVBUS_EXT vbus_ext
)
372 tasks
= vbus_ext
->tasks
;
373 vbus_ext
->tasks
= NULL
;
379 t
->func(vbus_ext
->vbus
, t
->data
);
383 static void hpt_do_tasks(PVBUS_EXT vbus_ext
, int pending
)
386 hpt_lock_vbus(vbus_ext
);
387 __hpt_do_tasks(vbus_ext
);
388 hpt_unlock_vbus(vbus_ext
);
392 static void hpt_action(struct cam_sim
*sim
, union ccb
*ccb
);
393 static void hpt_poll(struct cam_sim
*sim
);
394 static void hpt_async(void * callback_arg
, u_int32_t code
, struct cam_path
* path
, void * arg
);
395 static void hpt_pci_intr(void *arg
);
397 static __inline POS_CMDEXT
cmdext_get(PVBUS_EXT vbus_ext
)
399 POS_CMDEXT p
= vbus_ext
->cmdext_list
;
401 vbus_ext
->cmdext_list
= p
->next
;
405 static __inline
void cmdext_put(POS_CMDEXT p
)
407 p
->next
= p
->vbus_ext
->cmdext_list
;
408 p
->vbus_ext
->cmdext_list
= p
;
411 static void hpt_timeout(void *arg
)
413 PCOMMAND pCmd
= (PCOMMAND
)arg
;
414 POS_CMDEXT ext
= (POS_CMDEXT
)pCmd
->priv
;
416 KdPrint(("pCmd %p timeout", pCmd
));
418 ldm_reset_vbus((PVBUS
)ext
->vbus_ext
->vbus
);
421 static void os_cmddone(PCOMMAND pCmd
)
423 POS_CMDEXT ext
= (POS_CMDEXT
)pCmd
->priv
;
424 union ccb
*ccb
= ext
->ccb
;
426 KdPrint(("os_cmddone(%p, %d)", pCmd
, pCmd
->Result
));
428 callout_stop(ccb
->ccb_h
.timeout_ch
);
430 switch(pCmd
->Result
) {
432 ccb
->ccb_h
.status
= CAM_REQ_CMP
;
434 case RETURN_BAD_DEVICE
:
435 ccb
->ccb_h
.status
= CAM_DEV_NOT_THERE
;
437 case RETURN_DEVICE_BUSY
:
438 ccb
->ccb_h
.status
= CAM_BUSY
;
440 case RETURN_INVALID_REQUEST
:
441 ccb
->ccb_h
.status
= CAM_REQ_INVALID
;
443 case RETURN_SELECTION_TIMEOUT
:
444 ccb
->ccb_h
.status
= CAM_SEL_TIMEOUT
;
447 ccb
->ccb_h
.status
= CAM_BUSY
;
450 ccb
->ccb_h
.status
= CAM_SCSI_STATUS_ERROR
;
454 if (pCmd
->flags
.data_in
) {
455 bus_dmamap_sync(ext
->vbus_ext
->io_dmat
, ext
->dma_map
, BUS_DMASYNC_POSTREAD
);
457 else if (pCmd
->flags
.data_out
) {
458 bus_dmamap_sync(ext
->vbus_ext
->io_dmat
, ext
->dma_map
, BUS_DMASYNC_POSTWRITE
);
461 bus_dmamap_unload(ext
->vbus_ext
->io_dmat
, ext
->dma_map
);
468 static int os_buildsgl(PCOMMAND pCmd
, PSG pSg
, int logical
)
470 POS_CMDEXT ext
= (POS_CMDEXT
)pCmd
->priv
;
471 union ccb
*ccb
= ext
->ccb
;
472 bus_dma_segment_t
*sgList
= (bus_dma_segment_t
*)ccb
->csio
.data_ptr
;
476 if (ccb
->ccb_h
.flags
& CAM_DATA_PHYS
)
477 panic("physical address unsupported");
479 if (ccb
->ccb_h
.flags
& CAM_SCATTER_VALID
) {
480 if (ccb
->ccb_h
.flags
& CAM_SG_LIST_PHYS
)
481 panic("physical address unsupported");
483 for (idx
= 0; idx
< ccb
->csio
.sglist_cnt
; idx
++) {
484 os_set_sgptr(&pSg
[idx
], (HPT_U8
*)(HPT_UPTR
)sgList
[idx
].ds_addr
);
485 pSg
[idx
].size
= sgList
[idx
].ds_len
;
486 pSg
[idx
].eot
= (idx
==ccb
->csio
.sglist_cnt
-1)? 1 : 0;
490 os_set_sgptr(pSg
, (HPT_U8
*)ccb
->csio
.data_ptr
);
491 pSg
->size
= ccb
->csio
.dxfer_len
;
497 /* since we have provided physical sg, nobody will ask us to build physical sg */
502 static void hpt_io_dmamap_callback(void *arg
, bus_dma_segment_t
*segs
, int nsegs
, int error
)
504 PCOMMAND pCmd
= (PCOMMAND
)arg
;
505 POS_CMDEXT ext
= (POS_CMDEXT
)pCmd
->priv
;
509 HPT_ASSERT(pCmd
->flags
.physical_sg
);
511 if (error
|| nsegs
== 0)
512 panic("busdma error");
514 HPT_ASSERT(nsegs
<=os_max_sg_descriptors
);
516 for (idx
= 0; idx
< nsegs
; idx
++, psg
++) {
517 psg
->addr
.bus
= segs
[idx
].ds_addr
;
518 psg
->size
= segs
[idx
].ds_len
;
523 if (pCmd
->flags
.data_in
) {
524 bus_dmamap_sync(ext
->vbus_ext
->io_dmat
, ext
->dma_map
, BUS_DMASYNC_PREREAD
);
526 else if (pCmd
->flags
.data_out
) {
527 bus_dmamap_sync(ext
->vbus_ext
->io_dmat
, ext
->dma_map
, BUS_DMASYNC_PREWRITE
);
530 callout_reset(ext
->ccb
->ccb_h
.timeout_ch
, HPT_OSM_TIMEOUT
,
535 static void hpt_scsi_io(PVBUS_EXT vbus_ext
, union ccb
*ccb
)
537 PVBUS vbus
= (PVBUS
)vbus_ext
->vbus
;
543 if (ccb
->ccb_h
.flags
& CAM_CDB_POINTER
)
544 cdb
= ccb
->csio
.cdb_io
.cdb_ptr
;
546 cdb
= ccb
->csio
.cdb_io
.cdb_bytes
;
548 KdPrint(("hpt_scsi_io: ccb %x id %d lun %d cdb %x-%x-%x",
550 ccb
->ccb_h
.target_id
, ccb
->ccb_h
.target_lun
,
551 *(HPT_U32
*)&cdb
[0], *(HPT_U32
*)&cdb
[4], *(HPT_U32
*)&cdb
[8]
554 /* ccb->ccb_h.path_id is not our bus id - don't check it */
555 if (ccb
->ccb_h
.target_lun
!= 0 ||
556 ccb
->ccb_h
.target_id
>= osm_max_targets
||
557 (ccb
->ccb_h
.flags
& CAM_CDB_PHYS
))
559 ccb
->ccb_h
.status
= CAM_TID_INVALID
;
564 vd
= ldm_find_target(vbus
, ccb
->ccb_h
.target_id
);
567 ccb
->ccb_h
.status
= CAM_TID_INVALID
;
573 case TEST_UNIT_READY
:
574 case START_STOP_UNIT
:
575 case SYNCHRONIZE_CACHE
:
576 ccb
->ccb_h
.status
= CAM_REQ_CMP
;
581 PINQUIRYDATA inquiryData
;
582 memset(ccb
->csio
.data_ptr
, 0, ccb
->csio
.dxfer_len
);
583 inquiryData
= (PINQUIRYDATA
)ccb
->csio
.data_ptr
;
585 inquiryData
->AdditionalLength
= 31;
586 inquiryData
->CommandQueue
= 1;
587 memcpy(&inquiryData
->VendorId
, "HPT ", 8);
588 memcpy(&inquiryData
->ProductId
, "DISK 0_0 ", 16);
590 if (vd
->target_id
/ 10) {
591 inquiryData
->ProductId
[7] = (vd
->target_id
% 100) / 10 + '0';
592 inquiryData
->ProductId
[8] = (vd
->target_id
% 100) % 10 + '0';
595 inquiryData
->ProductId
[7] = (vd
->target_id
% 100) % 10 + '0';
597 memcpy(&inquiryData
->ProductRevisionLevel
, "4.00", 4);
599 ccb
->ccb_h
.status
= CAM_REQ_CMP
;
605 HPT_U8
*rbuf
= ccb
->csio
.data_ptr
;
608 if (vd
->capacity
>0xfffffffful
)
611 cap
= vd
->capacity
- 1;
613 rbuf
[0] = (HPT_U8
)(cap
>>24);
614 rbuf
[1] = (HPT_U8
)(cap
>>16);
615 rbuf
[2] = (HPT_U8
)(cap
>>8);
616 rbuf
[3] = (HPT_U8
)cap
;
622 ccb
->ccb_h
.status
= CAM_REQ_CMP
;
626 case SERVICE_ACTION_IN
:
628 HPT_U8
*rbuf
= ccb
->csio
.data_ptr
;
629 HPT_U64 cap
= vd
->capacity
- 1;
631 rbuf
[0] = (HPT_U8
)(cap
>>56);
632 rbuf
[1] = (HPT_U8
)(cap
>>48);
633 rbuf
[2] = (HPT_U8
)(cap
>>40);
634 rbuf
[3] = (HPT_U8
)(cap
>>32);
635 rbuf
[4] = (HPT_U8
)(cap
>>24);
636 rbuf
[5] = (HPT_U8
)(cap
>>16);
637 rbuf
[6] = (HPT_U8
)(cap
>>8);
638 rbuf
[7] = (HPT_U8
)cap
;
644 ccb
->ccb_h
.status
= CAM_REQ_CMP
;
656 case 0x8f: /* VERIFY_16 */
658 pCmd
= ldm_alloc_cmds(vbus
, vd
->cmds_per_request
);
660 KdPrint(("Failed to allocate command!"));
661 ccb
->ccb_h
.status
= CAM_BUSY
;
669 pCmd
->uCmd
.Ide
.Lba
= ((HPT_U32
)cdb
[1] << 16) | ((HPT_U32
)cdb
[2] << 8) | (HPT_U32
)cdb
[3];
670 pCmd
->uCmd
.Ide
.nSectors
= (HPT_U16
) cdb
[4];
674 case 0x8f: /* VERIFY_16 */
677 ((HPT_U64
)cdb
[2]<<56) |
678 ((HPT_U64
)cdb
[3]<<48) |
679 ((HPT_U64
)cdb
[4]<<40) |
680 ((HPT_U64
)cdb
[5]<<32) |
681 ((HPT_U64
)cdb
[6]<<24) |
682 ((HPT_U64
)cdb
[7]<<16) |
683 ((HPT_U64
)cdb
[8]<<8) |
685 pCmd
->uCmd
.Ide
.Lba
= block
;
686 pCmd
->uCmd
.Ide
.nSectors
= (HPT_U16
)cdb
[13] | ((HPT_U16
)cdb
[12]<<8);
691 pCmd
->uCmd
.Ide
.Lba
= (HPT_U32
)cdb
[5] | ((HPT_U32
)cdb
[4] << 8) | ((HPT_U32
)cdb
[3] << 16) | ((HPT_U32
)cdb
[2] << 24);
692 pCmd
->uCmd
.Ide
.nSectors
= (HPT_U16
) cdb
[8] | ((HPT_U16
)cdb
[7]<<8);
700 pCmd
->flags
.data_in
= 1;
705 pCmd
->flags
.data_out
= 1;
708 pCmd
->priv
= ext
= cmdext_get(vbus_ext
);
712 pCmd
->done
= os_cmddone
;
713 pCmd
->buildsgl
= os_buildsgl
;
715 pCmd
->psg
= ext
->psg
;
717 if (ccb
->ccb_h
.flags
& CAM_SCATTER_VALID
) {
719 bus_dma_segment_t
*sgList
= (bus_dma_segment_t
*)ccb
->csio
.data_ptr
;
721 if (ccb
->ccb_h
.flags
& CAM_SG_LIST_PHYS
)
722 pCmd
->flags
.physical_sg
= 1;
724 for (idx
= 0; idx
< ccb
->csio
.sglist_cnt
; idx
++) {
725 pCmd
->psg
[idx
].addr
.bus
= sgList
[idx
].ds_addr
;
726 pCmd
->psg
[idx
].size
= sgList
[idx
].ds_len
;
727 pCmd
->psg
[idx
].eot
= (idx
==ccb
->csio
.sglist_cnt
-1)? 1 : 0;
730 callout_reset(ccb
->ccb_h
.timeout_ch
, HPT_OSM_TIMEOUT
,
736 pCmd
->flags
.physical_sg
= 1;
737 error
= bus_dmamap_load(vbus_ext
->io_dmat
,
739 ccb
->csio
.data_ptr
, ccb
->csio
.dxfer_len
,
740 hpt_io_dmamap_callback
, pCmd
,
743 KdPrint(("bus_dmamap_load return %d", error
));
744 if (error
&& error
!=EINPROGRESS
) {
745 os_printk("bus_dmamap_load error %d", error
);
748 ccb
->ccb_h
.status
= CAM_REQ_CMP_ERR
;
756 ccb
->ccb_h
.status
= CAM_REQ_INVALID
;
764 static void hpt_action(struct cam_sim
*sim
, union ccb
*ccb
)
766 PVBUS_EXT vbus_ext
= (PVBUS_EXT
)cam_sim_softc(sim
);
768 KdPrint(("hpt_action(fn=%d, id=%d)", ccb
->ccb_h
.func_code
, ccb
->ccb_h
.target_id
));
770 switch (ccb
->ccb_h
.func_code
) {
773 hpt_lock_vbus(vbus_ext
);
774 hpt_scsi_io(vbus_ext
, ccb
);
775 hpt_unlock_vbus(vbus_ext
);
779 hpt_lock_vbus(vbus_ext
);
780 ldm_reset_vbus((PVBUS
)vbus_ext
->vbus
);
781 hpt_unlock_vbus(vbus_ext
);
784 case XPT_GET_TRAN_SETTINGS
:
785 case XPT_SET_TRAN_SETTINGS
:
786 ccb
->ccb_h
.status
= CAM_FUNC_NOTAVAIL
;
789 case XPT_CALC_GEOMETRY
:
790 ccb
->ccg
.heads
= 255;
791 ccb
->ccg
.secs_per_track
= 63;
792 ccb
->ccg
.cylinders
= ccb
->ccg
.volume_size
/ (ccb
->ccg
.heads
* ccb
->ccg
.secs_per_track
);
793 ccb
->ccb_h
.status
= CAM_REQ_CMP
;
798 struct ccb_pathinq
*cpi
= &ccb
->cpi
;
800 cpi
->version_num
= 1;
801 cpi
->hba_inquiry
= PI_SDTR_ABLE
;
802 cpi
->target_sprt
= 0;
803 cpi
->hba_misc
= PIM_NOBUSRESET
;
804 cpi
->hba_eng_cnt
= 0;
805 cpi
->max_target
= osm_max_targets
;
807 cpi
->unit_number
= cam_sim_unit(sim
);
808 cpi
->bus_id
= cam_sim_bus(sim
);
809 cpi
->initiator_id
= osm_max_targets
;
810 cpi
->base_transfer_speed
= 3300;
812 strncpy(cpi
->sim_vid
, "FreeBSD", SIM_IDLEN
);
813 strncpy(cpi
->hba_vid
, "HPT ", HBA_IDLEN
);
814 strncpy(cpi
->dev_name
, cam_sim_name(sim
), DEV_IDLEN
);
815 cpi
->transport
= XPORT_SPI
;
816 cpi
->transport_version
= 2;
817 cpi
->protocol
= PROTO_SCSI
;
818 cpi
->protocol_version
= SCSI_REV_2
;
819 cpi
->maxio
= HPT27XX_DFLTPHYS
;
820 cpi
->ccb_h
.status
= CAM_REQ_CMP
;
825 ccb
->ccb_h
.status
= CAM_REQ_INVALID
;
833 static void hpt_pci_intr(void *arg
)
835 PVBUS_EXT vbus_ext
= (PVBUS_EXT
)arg
;
836 hpt_lock_vbus(vbus_ext
);
837 ldm_intr((PVBUS
)vbus_ext
->vbus
);
838 hpt_unlock_vbus(vbus_ext
);
841 static void hpt_poll(struct cam_sim
*sim
)
843 hpt_pci_intr(cam_sim_softc(sim
));
846 static void hpt_async(void * callback_arg
, u_int32_t code
, struct cam_path
* path
, void * arg
)
848 KdPrint(("hpt_async"));
851 static int hpt_shutdown(device_t dev
)
853 KdPrint(("hpt_shutdown(dev=%p)", dev
));
857 static int hpt_detach(device_t dev
)
859 /* we don't allow the driver to be unloaded. */
863 static void hpt_ioctl_done(struct _IOCTL_ARG
*arg
)
865 arg
->ioctl_cmnd
= NULL
;
869 static void __hpt_do_ioctl(PVBUS_EXT vbus_ext
, IOCTL_ARG
*ioctl_args
)
871 ioctl_args
->result
= -1;
872 ioctl_args
->done
= hpt_ioctl_done
;
873 ioctl_args
->ioctl_cmnd
= (void *)1;
875 hpt_lock_vbus(vbus_ext
);
876 ldm_ioctl((PVBUS
)vbus_ext
->vbus
, ioctl_args
);
878 while (ioctl_args
->ioctl_cmnd
) {
879 if (hpt_sleep(vbus_ext
, ioctl_args
, 0, "hptctl", HPT_OSM_TIMEOUT
)==0)
881 ldm_reset_vbus((PVBUS
)vbus_ext
->vbus
);
882 __hpt_do_tasks(vbus_ext
);
885 /* KdPrint(("ioctl %x result %d", ioctl_args->dwIoControlCode, ioctl_args->result)); */
887 hpt_unlock_vbus(vbus_ext
);
890 static void hpt_do_ioctl(IOCTL_ARG
*ioctl_args
)
895 ldm_for_each_vbus(vbus
, vbus_ext
) {
896 __hpt_do_ioctl(vbus_ext
, ioctl_args
);
897 if (ioctl_args
->result
!=HPT_IOCTL_RESULT_WRONG_VBUS
)
902 #define HPT_DO_IOCTL(code, inbuf, insize, outbuf, outsize) ({\
904 arg.dwIoControlCode = code;\
905 arg.lpInBuffer = inbuf;\
906 arg.lpOutBuffer = outbuf;\
907 arg.nInBufferSize = insize;\
908 arg.nOutBufferSize = outsize;\
909 arg.lpBytesReturned = NULL;\
914 #define DEVICEID_VALID(id) ((id) && ((HPT_U32)(id)!=0xffffffff))
916 static int hpt_get_logical_devices(DEVICEID
* pIds
, int nMaxCount
)
919 HPT_U32 count
= nMaxCount
-1;
921 if (HPT_DO_IOCTL(HPT_IOCTL_GET_LOGICAL_DEVICES
,
922 &count
, sizeof(HPT_U32
), pIds
, sizeof(DEVICEID
)*nMaxCount
))
925 nMaxCount
= (int)pIds
[0];
926 for (i
=0; i
<nMaxCount
; i
++) pIds
[i
] = pIds
[i
+1];
930 static int hpt_get_device_info_v3(DEVICEID id
, PLOGICAL_DEVICE_INFO_V3 pInfo
)
932 return HPT_DO_IOCTL(HPT_IOCTL_GET_DEVICE_INFO_V3
,
933 &id
, sizeof(DEVICEID
), pInfo
, sizeof(LOGICAL_DEVICE_INFO_V3
));
936 /* not belong to this file logically, but we want to use ioctl interface */
937 static int __hpt_stop_tasks(PVBUS_EXT vbus_ext
, DEVICEID id
)
939 LOGICAL_DEVICE_INFO_V3 devinfo
;
941 DEVICEID param
[2] = { id
, 0 };
943 if (hpt_get_device_info_v3(id
, &devinfo
))
946 if (devinfo
.Type
!=LDT_ARRAY
)
949 if (devinfo
.u
.array
.Flags
& ARRAY_FLAG_REBUILDING
)
950 param
[1] = AS_REBUILD_ABORT
;
951 else if (devinfo
.u
.array
.Flags
& ARRAY_FLAG_VERIFYING
)
952 param
[1] = AS_VERIFY_ABORT
;
953 else if (devinfo
.u
.array
.Flags
& ARRAY_FLAG_INITIALIZING
)
954 param
[1] = AS_INITIALIZE_ABORT
;
955 else if (devinfo
.u
.array
.Flags
& ARRAY_FLAG_TRANSFORMING
)
956 param
[1] = AS_TRANSFORM_ABORT
;
960 KdPrint(("SET_ARRAY_STATE(%x, %d)", param
[0], param
[1]));
961 result
= HPT_DO_IOCTL(HPT_IOCTL_SET_ARRAY_STATE
,
962 param
, sizeof(param
), 0, 0);
964 for (i
=0; i
<devinfo
.u
.array
.nDisk
; i
++)
965 if (DEVICEID_VALID(devinfo
.u
.array
.Members
[i
]))
966 __hpt_stop_tasks(vbus_ext
, devinfo
.u
.array
.Members
[i
]);
971 static void hpt_stop_tasks(PVBUS_EXT vbus_ext
)
976 count
= hpt_get_logical_devices((DEVICEID
*)&ids
, sizeof(ids
)/sizeof(ids
[0]));
978 for (i
=0; i
<count
; i
++)
979 __hpt_stop_tasks(vbus_ext
, ids
[i
]);
982 static d_open_t hpt_open
;
983 static d_close_t hpt_close
;
984 static d_ioctl_t hpt_ioctl
;
985 static void hpt_bus_scan_cb(struct cam_periph
*periph
, union ccb
*ccb
);
986 static int hpt_rescan_bus(void);
988 static struct dev_ops hpt_ops
= {
989 { driver_name
, 0, 0 },
991 .d_close
= hpt_close
,
992 .d_ioctl
= hpt_ioctl
,
995 static struct intr_config_hook hpt_ich
;
998 * hpt_final_init will be called after all hpt_attach.
1000 static void hpt_final_init(void *dummy
)
1007 /* Clear the config hook */
1008 config_intrhook_disestablish(&hpt_ich
);
1010 /* allocate memory */
1012 ldm_for_each_vbus(vbus
, vbus_ext
) {
1013 if (hpt_alloc_mem(vbus_ext
)) {
1014 os_printk("out of memory");
1021 os_printk("no controller detected.");
1025 /* initializing hardware */
1026 ldm_for_each_vbus(vbus
, vbus_ext
) {
1027 /* make timer available here */
1028 callout_init(&vbus_ext
->timer
);
1029 if (hpt_init_vbus(vbus_ext
)) {
1030 os_printk("fail to initialize hardware");
1035 /* register CAM interface */
1036 ldm_for_each_vbus(vbus
, vbus_ext
) {
1037 struct cam_devq
*devq
;
1038 struct ccb_setasync
*ccb
;
1040 lockinit(&vbus_ext
->lock
, "hptsleeplock", 0, LK_CANRECURSE
);
1041 if (bus_dma_tag_create(NULL
,/* parent */
1043 BUS_SPACE_MAXADDR_32BIT
+1, /* boundary */
1044 BUS_SPACE_MAXADDR
, /* lowaddr */
1045 BUS_SPACE_MAXADDR
, /* highaddr */
1046 PAGE_SIZE
* (os_max_sg_descriptors
-1), /* maxsize */
1047 os_max_sg_descriptors
, /* nsegments */
1048 0x10000, /* maxsegsize */
1049 BUS_DMA_WAITOK
, /* flags */
1050 &vbus_ext
->io_dmat
/* tag */))
1055 for (i
=0; i
<os_max_queue_comm
; i
++) {
1056 POS_CMDEXT ext
= (POS_CMDEXT
)kmalloc(sizeof(OS_CMDEXT
), M_DEVBUF
, M_WAITOK
);
1058 os_printk("Can't alloc cmdext(%d)", i
);
1061 ext
->vbus_ext
= vbus_ext
;
1062 ext
->next
= vbus_ext
->cmdext_list
;
1063 vbus_ext
->cmdext_list
= ext
;
1065 if (bus_dmamap_create(vbus_ext
->io_dmat
, 0, &ext
->dma_map
)) {
1066 os_printk("Can't create dma map(%d)", i
);
1071 if ((devq
= cam_simq_alloc(os_max_queue_comm
)) == NULL
) {
1072 os_printk("cam_simq_alloc failed");
1076 vbus_ext
->sim
= cam_sim_alloc(hpt_action
, hpt_poll
, driver_name
,
1077 vbus_ext
, 0, &sim_mplock
, os_max_queue_comm
, /*tagged*/8, devq
);
1078 cam_simq_release(devq
);
1080 if (!vbus_ext
->sim
) {
1081 os_printk("cam_sim_alloc failed");
1085 if (xpt_bus_register(vbus_ext
->sim
, 0) != CAM_SUCCESS
) {
1086 os_printk("xpt_bus_register failed");
1087 cam_sim_free(vbus_ext
->sim
);
1088 vbus_ext
->sim
= NULL
;
1092 if (xpt_create_path(&vbus_ext
->path
, /*periph */ NULL
,
1093 cam_sim_path(vbus_ext
->sim
), CAM_TARGET_WILDCARD
,
1094 CAM_LUN_WILDCARD
) != CAM_REQ_CMP
)
1096 os_printk("xpt_create_path failed");
1097 xpt_bus_deregister(cam_sim_path(vbus_ext
->sim
));
1098 cam_sim_free(vbus_ext
->sim
);
1099 vbus_ext
->sim
= NULL
;
1103 ccb
= &xpt_alloc_ccb()->csa
;
1104 xpt_setup_ccb(&ccb
->ccb_h
, vbus_ext
->path
, /*priority*/5);
1105 ccb
->ccb_h
.func_code
= XPT_SASYNC_CB
;
1106 ccb
->event_enable
= AC_LOST_DEVICE
;
1107 ccb
->callback
= hpt_async
;
1108 ccb
->callback_arg
= vbus_ext
;
1109 xpt_action((union ccb
*)ccb
);
1110 xpt_free_ccb(&ccb
->ccb_h
);
1112 for (hba
= vbus_ext
->hba_list
; hba
; hba
= hba
->next
) {
1114 if ((hba
->irq_res
= bus_alloc_resource(hba
->pcidev
,
1115 SYS_RES_IRQ
, &rid
, 0, ~0ul, 1, RF_SHAREABLE
| RF_ACTIVE
)) == NULL
)
1117 os_printk("can't allocate interrupt");
1121 if (bus_setup_intr(hba
->pcidev
, hba
->irq_res
, 0,
1122 hpt_pci_intr
, vbus_ext
, &hba
->irq_handle
, NULL
))
1124 os_printk("can't set up interrupt");
1127 hba
->ldm_adapter
.him
->intr_control(hba
->ldm_adapter
.him_handle
, HPT_TRUE
);
1131 vbus_ext
->shutdown_eh
= EVENTHANDLER_REGISTER(shutdown_final
,
1132 hpt_shutdown_vbus
, vbus_ext
, SHUTDOWN_PRI_DEFAULT
);
1133 if (!vbus_ext
->shutdown_eh
)
1134 os_printk("Shutdown event registration failed");
1137 ldm_for_each_vbus(vbus
, vbus_ext
) {
1138 TASK_INIT(&vbus_ext
->worker
, 0, (task_fn_t
*)hpt_do_tasks
, vbus_ext
);
1139 if (vbus_ext
->tasks
)
1140 TASK_ENQUEUE(&vbus_ext
->worker
);
1143 make_dev(&hpt_ops
, DRIVER_MINOR
, UID_ROOT
, GID_OPERATOR
,
1144 S_IRUSR
| S_IWUSR
, driver_name
);
1147 #if defined(KLD_MODULE)
1149 typedef struct driverlink
*driverlink_t
;
1151 kobj_class_t driver
;
1152 TAILQ_ENTRY(driverlink
) link
; /* list of drivers in devclass */
1155 typedef TAILQ_HEAD(driver_list
, driverlink
) driver_list_t
;
1158 TAILQ_ENTRY(devclass
) link
;
1159 devclass_t parent
; /* parent in devclass hierarchy */
1160 driver_list_t drivers
; /* bus devclasses store drivers for bus */
1162 device_t
*devices
; /* array of devices indexed by unit */
1163 int maxunit
; /* size of devices array */
1166 static void override_kernel_driver(void)
1168 driverlink_t dl
, dlfirst
;
1169 driver_t
*tmpdriver
;
1170 devclass_t dc
= devclass_find("pci");
1173 dlfirst
= TAILQ_FIRST(&dc
->drivers
);
1174 for (dl
= dlfirst
; dl
; dl
= TAILQ_NEXT(dl
, link
)) {
1175 if(strcmp(dl
->driver
->name
, driver_name
) == 0) {
1176 tmpdriver
=dl
->driver
;
1177 dl
->driver
=dlfirst
->driver
;
1178 dlfirst
->driver
=tmpdriver
;
1186 #define override_kernel_driver()
1189 static void hpt_init(void *dummy
)
1192 os_printk("%s %s", driver_name_long
, driver_ver
);
1194 override_kernel_driver();
1197 hpt_ich
.ich_func
= hpt_final_init
;
1198 hpt_ich
.ich_arg
= NULL
;
1199 hpt_ich
.ich_desc
= "hpt27xx";
1200 if (config_intrhook_establish(&hpt_ich
) != 0) {
1201 kprintf("%s: cannot establish configuration hook\n",
1206 SYSINIT(hptinit
, SI_SUB_CONFIGURE
, SI_ORDER_FIRST
, hpt_init
, NULL
);
1209 * CAM driver interface
1211 static device_method_t driver_methods
[] = {
1212 /* Device interface */
1213 DEVMETHOD(device_probe
, hpt_probe
),
1214 DEVMETHOD(device_attach
, hpt_attach
),
1215 DEVMETHOD(device_detach
, hpt_detach
),
1216 DEVMETHOD(device_shutdown
, hpt_shutdown
),
1220 static driver_t hpt_pci_driver
= {
1226 static devclass_t hpt_devclass
;
1229 #error "no TARGETNAME found"
1232 /* use this to make TARGETNAME be expanded */
1233 #define __DRIVER_MODULE(p1, p2, p3, p4, p5, p6) DRIVER_MODULE(p1, p2, p3, p4, p5, p6)
1234 #define __MODULE_VERSION(p1, p2) MODULE_VERSION(p1, p2)
1235 #define __MODULE_DEPEND(p1, p2, p3, p4, p5) MODULE_DEPEND(p1, p2, p3, p4, p5)
1236 __DRIVER_MODULE(TARGETNAME
, pci
, hpt_pci_driver
, hpt_devclass
, NULL
, NULL
);
1237 __MODULE_VERSION(TARGETNAME
, 1);
1238 __MODULE_DEPEND(TARGETNAME
, cam
, 1, 1, 1);
1240 typedef struct cdev
* ioctl_dev_t
;
1242 typedef struct thread
* ioctl_thread_t
;
1244 static int hpt_open(struct dev_open_args
*ap
)
1249 static int hpt_close(struct dev_close_args
*ap
)
1254 static int hpt_ioctl(struct dev_ioctl_args
*ap
)
1256 u_long cmd
= ap
->a_cmd
;
1257 caddr_t data
= ap
->a_data
;
1258 PHPT_IOCTL_PARAM piop
=(PHPT_IOCTL_PARAM
)data
;
1259 IOCTL_ARG ioctl_args
;
1260 HPT_U32 bytesReturned
;
1263 case HPT_DO_IOCONTROL
:
1265 if (piop
->Magic
== HPT_IOCTL_MAGIC
|| piop
->Magic
== HPT_IOCTL_MAGIC32
) {
1266 KdPrint(("ioctl=%x in=%p len=%d out=%p len=%d\n",
1267 piop
->dwIoControlCode
,
1269 piop
->nInBufferSize
,
1271 piop
->nOutBufferSize
));
1273 memset(&ioctl_args
, 0, sizeof(ioctl_args
));
1275 ioctl_args
.dwIoControlCode
= piop
->dwIoControlCode
;
1276 ioctl_args
.nInBufferSize
= piop
->nInBufferSize
;
1277 ioctl_args
.nOutBufferSize
= piop
->nOutBufferSize
;
1278 ioctl_args
.lpBytesReturned
= &bytesReturned
;
1280 if (ioctl_args
.nInBufferSize
) {
1281 ioctl_args
.lpInBuffer
= kmalloc(ioctl_args
.nInBufferSize
, M_DEVBUF
, M_WAITOK
);
1282 if (!ioctl_args
.lpInBuffer
)
1284 if (copyin((void*)piop
->lpInBuffer
,
1285 ioctl_args
.lpInBuffer
, piop
->nInBufferSize
))
1289 if (ioctl_args
.nOutBufferSize
) {
1290 ioctl_args
.lpOutBuffer
= kmalloc(ioctl_args
.nOutBufferSize
, M_DEVBUF
, M_WAITOK
);
1291 if (!ioctl_args
.lpOutBuffer
)
1297 hpt_do_ioctl(&ioctl_args
);
1301 if (ioctl_args
.result
==HPT_IOCTL_RESULT_OK
) {
1302 if (piop
->nOutBufferSize
) {
1303 if (copyout(ioctl_args
.lpOutBuffer
,
1304 (void*)piop
->lpOutBuffer
, piop
->nOutBufferSize
))
1307 if (piop
->lpBytesReturned
) {
1308 if (copyout(&bytesReturned
,
1309 (void*)piop
->lpBytesReturned
, sizeof(HPT_U32
)))
1312 if (ioctl_args
.lpInBuffer
) kfree(ioctl_args
.lpInBuffer
, M_DEVBUF
);
1313 if (ioctl_args
.lpOutBuffer
) kfree(ioctl_args
.lpOutBuffer
, M_DEVBUF
);
1317 if (ioctl_args
.lpInBuffer
) kfree(ioctl_args
.lpInBuffer
, M_DEVBUF
);
1318 if (ioctl_args
.lpOutBuffer
) kfree(ioctl_args
.lpOutBuffer
, M_DEVBUF
);
1326 return hpt_rescan_bus();
1329 KdPrint(("invalid command!"));
1335 static int hpt_rescan_bus(void)
1337 struct cam_path
*path
;
1344 ldm_for_each_vbus(vbus
, vbus_ext
) {
1345 if (xpt_create_path(&path
, xpt_periph
, cam_sim_path(vbus_ext
->sim
),
1346 CAM_TARGET_WILDCARD
, CAM_LUN_WILDCARD
) != CAM_REQ_CMP
) {
1350 ccb
= xpt_alloc_ccb();
1351 bzero(ccb
, sizeof(union ccb
));
1352 xpt_setup_ccb(&ccb
->ccb_h
, path
, 5);
1353 ccb
->ccb_h
.func_code
= XPT_SCAN_BUS
;
1354 ccb
->ccb_h
.cbfcnp
= hpt_bus_scan_cb
;
1355 ccb
->crcn
.flags
= CAM_FLAG_NONE
;
1364 static void hpt_bus_scan_cb(struct cam_periph
*periph
, union ccb
*ccb
)
1366 if (ccb
->ccb_h
.status
!= CAM_REQ_CMP
)
1367 KdPrint(("cam_scan_callback: failure status = %x",ccb
->ccb_h
.status
));
1369 KdPrint(("Scan bus successfully!"));
1371 xpt_free_path(ccb
->ccb_h
.path
);
1372 xpt_free_ccb(&ccb
->ccb_h
);