ad86b17db486e2f5a5a86489f10984c227dc817f
[dragonfly.git] / sys / dev / raid / hpt27xx / osm_bsd.c
1 /*-
2  * Copyright (c) 2011 HighPoint Technologies, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
13  *
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
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD: src/sys/dev/hpt27xx/osm_bsd.c,v 1.1 2011/12/28 23:26:58 delphij Exp $
27  */
28
29 #include <dev/raid/hpt27xx/hpt27xx_config.h>
30
31 #include <dev/raid/hpt27xx/os_bsd.h>
32 #include <dev/raid/hpt27xx/hptintf.h>
33
34 static int hpt_probe(device_t dev)
35 {
36         PCI_ID pci_id;
37         HIM *him;
38         int i;
39         PHBA hba;
40
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)
49                                 ));
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;
55                                 return 0;
56                         }
57                 }
58         }
59
60         return (ENXIO);
61 }
62
63 static int hpt_attach(device_t dev)
64 {
65         PHBA hba = (PHBA)device_get_softc(dev);
66         HIM *him = hba->ldm_adapter.him;
67         PCI_ID pci_id;
68         HPT_UINT size;
69         PVBUS vbus;
70         PVBUS_EXT vbus_ext;
71
72         KdPrint(("hpt_attach(%d/%d/%d)", pci_get_bus(dev), pci_get_slot(dev), pci_get_function(dev)));
73
74         pci_enable_busmaster(dev);
75
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);
80
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)
84                 return ENXIO;
85
86         hba->pcidev = dev;
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);
91
92         if (!him->create_adapter(&pci_id, hba->pciaddr, hba->ldm_adapter.him_handle, hba)) {
93                 kfree(hba->ldm_adapter.him_handle, M_DEVBUF);
94                 return -1;
95         }
96
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));
99
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                 if (!vbus_ext) {
104                         kfree(hba->ldm_adapter.him_handle, M_DEVBUF);
105                         return -1;
106                 }
107                 memset(vbus_ext, 0, sizeof(VBUS_EXT));
108                 vbus_ext->ext_type = EXT_TYPE_VBUS;
109                 ldm_create_vbus((PVBUS)vbus_ext->vbus, vbus_ext);
110                 ldm_register_adapter(&hba->ldm_adapter);
111         }
112
113         ldm_for_each_vbus(vbus, vbus_ext) {
114                 if (hba->ldm_adapter.vbus==vbus) {
115                         hba->vbus_ext = vbus_ext;
116                         hba->next = vbus_ext->hba_list;
117                         vbus_ext->hba_list = hba;
118                         break;
119                 }
120         }
121         return 0;
122 }
123
124 /*
125  * Maybe we'd better to use the bus_dmamem_alloc to alloc DMA memory,
126  * but there are some problems currently (alignment, etc).
127  */
128 static __inline void *__get_free_pages(int order)
129 {
130         /* don't use low memory - other devices may get starved */
131         return contigmalloc(PAGE_SIZE<<order,
132                         M_DEVBUF, M_WAITOK, BUS_SPACE_MAXADDR_24BIT, BUS_SPACE_MAXADDR, PAGE_SIZE, 0);
133 }
134
135 static __inline void free_pages(void *p, int order)
136 {
137         contigfree(p, PAGE_SIZE<<order, M_DEVBUF);
138 }
139
140 static int hpt_alloc_mem(PVBUS_EXT vbus_ext)
141 {
142         PHBA hba;
143         struct freelist *f;
144         HPT_UINT i;
145         void **p;
146
147         for (hba = vbus_ext->hba_list; hba; hba = hba->next)
148                 hba->ldm_adapter.him->get_meminfo(hba->ldm_adapter.him_handle);
149
150         ldm_get_mem_info((PVBUS)vbus_ext->vbus, 0);
151
152         for (f=vbus_ext->freelist_head; f; f=f->next) {
153                 KdPrint(("%s: %d*%d=%d bytes",
154                         f->tag, f->count, f->size, f->count*f->size));
155                 for (i=0; i<f->count; i++) {
156                         p = (void **)kmalloc(f->size, M_DEVBUF, M_WAITOK);
157                         if (!p) return (ENXIO);
158                         *p = f->head;
159                         f->head = p;
160                 }
161         }
162
163         for (f=vbus_ext->freelist_dma_head; f; f=f->next) {
164                 int order, size, j;
165
166                 HPT_ASSERT((f->size & (f->alignment-1))==0);
167
168                 for (order=0, size=PAGE_SIZE; size<f->size; order++, size<<=1) ;
169
170                 KdPrint(("%s: %d*%d=%d bytes, order %d",
171                         f->tag, f->count, f->size, f->count*f->size, order));
172                 HPT_ASSERT(f->alignment<=PAGE_SIZE);
173
174                 for (i=0; i<f->count;) {
175                         p = (void **)__get_free_pages(order);
176                         if (!p) return -1;
177                         for (j = size/f->size; j && i<f->count; i++,j--) {
178                                 *p = f->head;
179                                 *(BUS_ADDRESS *)(p+1) = (BUS_ADDRESS)vtophys(p);
180                                 f->head = p;
181                                 p = (void **)((unsigned long)p + f->size);
182                         }
183                 }
184         }
185
186         HPT_ASSERT(PAGE_SIZE==DMAPOOL_PAGE_SIZE);
187
188         for (i=0; i<os_max_cache_pages; i++) {
189                 p = (void **)__get_free_pages(0);
190                 if (!p) return -1;
191                 HPT_ASSERT(((HPT_UPTR)p & (DMAPOOL_PAGE_SIZE-1))==0);
192                 dmapool_put_page((PVBUS)vbus_ext->vbus, p, (BUS_ADDRESS)vtophys(p));
193         }
194
195         return 0;
196 }
197
198 static void hpt_free_mem(PVBUS_EXT vbus_ext)
199 {
200         struct freelist *f;
201         void *p;
202         int i;
203         BUS_ADDRESS bus;
204
205         for (f=vbus_ext->freelist_head; f; f=f->next) {
206 #if DBG
207                 if (f->count!=f->reserved_count) {
208                         KdPrint(("memory leak for freelist %s (%d/%d)", f->tag, f->count, f->reserved_count));
209                 }
210 #endif
211                 while ((p=freelist_get(f)))
212                         kfree(p, M_DEVBUF);
213         }
214
215         for (i=0; i<os_max_cache_pages; i++) {
216                 p = dmapool_get_page((PVBUS)vbus_ext->vbus, &bus);
217                 HPT_ASSERT(p);
218                 free_pages(p, 0);
219         }
220
221         for (f=vbus_ext->freelist_dma_head; f; f=f->next) {
222                 int order, size;
223 #if DBG
224                 if (f->count!=f->reserved_count) {
225                         KdPrint(("memory leak for dma freelist %s (%d/%d)", f->tag, f->count, f->reserved_count));
226                 }
227 #endif
228                 for (order=0, size=PAGE_SIZE; size<f->size; order++, size<<=1) ;
229
230                 while ((p=freelist_get_dma(f, &bus))) {
231                         if (order)
232                                 free_pages(p, order);
233                         else {
234                         /* can't free immediately since other blocks in this page may still be in the list */
235                                 if (((HPT_UPTR)p & (PAGE_SIZE-1))==0)
236                                         dmapool_put_page((PVBUS)vbus_ext->vbus, p, bus);
237                         }
238                 }
239         }
240
241         while ((p = dmapool_get_page((PVBUS)vbus_ext->vbus, &bus)))
242                 free_pages(p, 0);
243 }
244
245 static int hpt_init_vbus(PVBUS_EXT vbus_ext)
246 {
247         PHBA hba;
248
249         for (hba = vbus_ext->hba_list; hba; hba = hba->next)
250                 if (!hba->ldm_adapter.him->initialize(hba->ldm_adapter.him_handle)) {
251                         KdPrint(("fail to initialize %p", hba));
252                         return -1;
253                 }
254
255         ldm_initialize_vbus((PVBUS)vbus_ext->vbus, &vbus_ext->hba_list->ldm_adapter);
256         return 0;
257 }
258
259 static void hpt_flush_done(PCOMMAND pCmd)
260 {
261         PVDEV vd = pCmd->target;
262
263         if (mIsArray(vd->type) && vd->u.array.transform && vd!=vd->u.array.transform->target) {
264                 vd = vd->u.array.transform->target;
265                 HPT_ASSERT(vd);
266                 pCmd->target = vd;
267                 pCmd->Result = RETURN_PENDING;
268                 vdev_queue_cmd(pCmd);
269                 return;
270         }
271
272         *(int *)pCmd->priv = 1;
273         wakeup(pCmd);
274 }
275
276 /*
277  * flush a vdev (without retry).
278  */
279 static int hpt_flush_vdev(PVBUS_EXT vbus_ext, PVDEV vd)
280 {
281         PCOMMAND pCmd;
282         int result = 0, done;
283         HPT_UINT count;
284
285         KdPrint(("flusing dev %p", vd));
286
287         hpt_lock_vbus(vbus_ext);
288
289         if (mIsArray(vd->type) && vd->u.array.transform)
290                 count = MAX(vd->u.array.transform->source->cmds_per_request,
291                                         vd->u.array.transform->target->cmds_per_request);
292         else
293                 count = vd->cmds_per_request;
294
295         pCmd = ldm_alloc_cmds(vd->vbus, count);
296
297         if (!pCmd) {
298                 hpt_unlock_vbus(vbus_ext);
299                 return -1;
300         }
301
302         pCmd->type = CMD_TYPE_FLUSH;
303         pCmd->flags.hard_flush = 1;
304         pCmd->target = vd;
305         pCmd->done = hpt_flush_done;
306         done = 0;
307         pCmd->priv = &done;
308
309         ldm_queue_cmd(pCmd);
310
311         if (!done) {
312                 while (hpt_sleep(vbus_ext, pCmd, 0, "hptfls", HPT_OSM_TIMEOUT)) {
313                         ldm_reset_vbus(vd->vbus);
314                 }
315         }
316
317         KdPrint(("flush result %d", pCmd->Result));
318
319         if (pCmd->Result!=RETURN_SUCCESS)
320                 result = -1;
321
322         ldm_free_cmds(pCmd);
323
324         hpt_unlock_vbus(vbus_ext);
325
326         return result;
327 }
328
329 static void hpt_stop_tasks(PVBUS_EXT vbus_ext);
330 static void hpt_shutdown_vbus(PVBUS_EXT vbus_ext, int howto)
331 {
332         PVBUS     vbus = (PVBUS)vbus_ext->vbus;
333         PHBA hba;
334         int i;
335
336         KdPrint(("hpt_shutdown_vbus"));
337
338         /* stop all ctl tasks and disable the worker taskqueue */
339         hpt_stop_tasks(vbus_ext);
340         vbus_ext->worker.ta_context = 0;
341
342         /* flush devices */
343         for (i=0; i<osm_max_targets; i++) {
344                 PVDEV vd = ldm_find_target(vbus, i);
345                 if (vd) {
346                         /* retry once */
347                         if (hpt_flush_vdev(vbus_ext, vd))
348                                 hpt_flush_vdev(vbus_ext, vd);
349                 }
350         }
351
352         hpt_lock_vbus(vbus_ext);
353         ldm_shutdown(vbus);
354         hpt_unlock_vbus(vbus_ext);
355
356         ldm_release_vbus(vbus);
357
358         for (hba=vbus_ext->hba_list; hba; hba=hba->next)
359                 bus_teardown_intr(hba->pcidev, hba->irq_res, hba->irq_handle);
360
361         hpt_free_mem(vbus_ext);
362
363         while ((hba=vbus_ext->hba_list)) {
364                 vbus_ext->hba_list = hba->next;
365                 kfree(hba->ldm_adapter.him_handle, M_DEVBUF);
366         }
367
368         kfree(vbus_ext, M_DEVBUF);
369         KdPrint(("hpt_shutdown_vbus done"));
370 }
371
372 static void __hpt_do_tasks(PVBUS_EXT vbus_ext)
373 {
374         OSM_TASK *tasks;
375
376         tasks = vbus_ext->tasks;
377         vbus_ext->tasks = 0;
378
379         while (tasks) {
380                 OSM_TASK *t = tasks;
381                 tasks = t->next;
382                 t->next = 0;
383                 t->func(vbus_ext->vbus, t->data);
384         }
385 }
386
387 static void hpt_do_tasks(PVBUS_EXT vbus_ext, int pending)
388 {
389         if(vbus_ext){
390                 hpt_lock_vbus(vbus_ext);
391                 __hpt_do_tasks(vbus_ext);
392                 hpt_unlock_vbus(vbus_ext);
393         }
394 }
395
396 static void hpt_action(struct cam_sim *sim, union ccb *ccb);
397 static void hpt_poll(struct cam_sim *sim);
398 static void hpt_async(void * callback_arg, u_int32_t code, struct cam_path * path, void * arg);
399 static void hpt_pci_intr(void *arg);
400
401 static __inline POS_CMDEXT cmdext_get(PVBUS_EXT vbus_ext)
402 {
403         POS_CMDEXT p = vbus_ext->cmdext_list;
404         if (p)
405                 vbus_ext->cmdext_list = p->next;
406         return p;
407 }
408
409 static __inline void cmdext_put(POS_CMDEXT p)
410 {
411         p->next = p->vbus_ext->cmdext_list;
412         p->vbus_ext->cmdext_list = p;
413 }
414
415 static void hpt_timeout(void *arg)
416 {
417         PCOMMAND pCmd = (PCOMMAND)arg;
418         POS_CMDEXT ext = (POS_CMDEXT)pCmd->priv;
419
420         KdPrint(("pCmd %p timeout", pCmd));
421
422         ldm_reset_vbus((PVBUS)ext->vbus_ext->vbus);
423 }
424
425 static void os_cmddone(PCOMMAND pCmd)
426 {
427         POS_CMDEXT ext = (POS_CMDEXT)pCmd->priv;
428         union ccb *ccb = ext->ccb;
429
430         KdPrint(("os_cmddone(%p, %d)", pCmd, pCmd->Result));
431
432         callout_stop(&ccb->ccb_h.timeout_ch);
433
434         switch(pCmd->Result) {
435         case RETURN_SUCCESS:
436                 ccb->ccb_h.status = CAM_REQ_CMP;
437                 break;
438         case RETURN_BAD_DEVICE:
439                 ccb->ccb_h.status = CAM_DEV_NOT_THERE;
440                 break;
441         case RETURN_DEVICE_BUSY:
442                 ccb->ccb_h.status = CAM_BUSY;
443                 break;
444         case RETURN_INVALID_REQUEST:
445                 ccb->ccb_h.status = CAM_REQ_INVALID;
446                 break;
447         case RETURN_SELECTION_TIMEOUT:
448                 ccb->ccb_h.status = CAM_SEL_TIMEOUT;
449                 break;
450         case RETURN_RETRY:
451                 ccb->ccb_h.status = CAM_BUSY;
452                 break;
453         default:
454                 ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
455                 break;
456         }
457
458         if (pCmd->flags.data_in) {
459                 bus_dmamap_sync(ext->vbus_ext->io_dmat, ext->dma_map, BUS_DMASYNC_POSTREAD);
460         }
461         else if (pCmd->flags.data_out) {
462                 bus_dmamap_sync(ext->vbus_ext->io_dmat, ext->dma_map, BUS_DMASYNC_POSTWRITE);
463         }
464
465         bus_dmamap_unload(ext->vbus_ext->io_dmat, ext->dma_map);
466
467         cmdext_put(ext);
468         ldm_free_cmds(pCmd);
469         xpt_done(ccb);
470 }
471
472 static int os_buildsgl(PCOMMAND pCmd, PSG pSg, int logical)
473 {
474         POS_CMDEXT ext = (POS_CMDEXT)pCmd->priv;
475         union ccb *ccb = ext->ccb;
476         bus_dma_segment_t *sgList = (bus_dma_segment_t *)ccb->csio.data_ptr;
477         int idx;
478
479         if(logical)     {
480                 if (ccb->ccb_h.flags & CAM_DATA_PHYS)
481                         panic("physical address unsupported");
482
483                 if (ccb->ccb_h.flags & CAM_SCATTER_VALID) {
484                         if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS)
485                                 panic("physical address unsupported");
486
487                         for (idx = 0; idx < ccb->csio.sglist_cnt; idx++) {
488                                 os_set_sgptr(&pSg[idx], (HPT_U8 *)(HPT_UPTR)sgList[idx].ds_addr);
489                                 pSg[idx].size = sgList[idx].ds_len;
490                                 pSg[idx].eot = (idx==ccb->csio.sglist_cnt-1)? 1 : 0;
491                         }
492                 }
493                 else {
494                         os_set_sgptr(pSg, (HPT_U8 *)ccb->csio.data_ptr);
495                         pSg->size = ccb->csio.dxfer_len;
496                         pSg->eot = 1;
497                 }
498                 return TRUE;
499         }
500
501         /* since we have provided physical sg, nobody will ask us to build physical sg */
502         HPT_ASSERT(0);
503         return FALSE;
504 }
505
506 static void hpt_io_dmamap_callback(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
507 {
508         PCOMMAND pCmd = (PCOMMAND)arg;
509         POS_CMDEXT ext = (POS_CMDEXT)pCmd->priv;
510         PSG psg = pCmd->psg;
511         int idx;
512
513         HPT_ASSERT(pCmd->flags.physical_sg);
514
515         if (error || nsegs == 0)
516                 panic("busdma error");
517
518         HPT_ASSERT(nsegs<=os_max_sg_descriptors);
519
520         for (idx = 0; idx < nsegs; idx++, psg++) {
521                 psg->addr.bus = segs[idx].ds_addr;
522                 psg->size = segs[idx].ds_len;
523                 psg->eot = 0;
524         }
525         psg[-1].eot = 1;
526
527         if (pCmd->flags.data_in) {
528                 bus_dmamap_sync(ext->vbus_ext->io_dmat, ext->dma_map, BUS_DMASYNC_PREREAD);
529         }
530         else if (pCmd->flags.data_out) {
531                 bus_dmamap_sync(ext->vbus_ext->io_dmat, ext->dma_map, BUS_DMASYNC_PREWRITE);
532         }
533
534         callout_reset(&ext->ccb->ccb_h.timeout_ch, HPT_OSM_TIMEOUT, hpt_timeout, pCmd);
535         ldm_queue_cmd(pCmd);
536 }
537
538 static void hpt_scsi_io(PVBUS_EXT vbus_ext, union ccb *ccb)
539 {
540         PVBUS vbus = (PVBUS)vbus_ext->vbus;
541         PVDEV vd;
542         PCOMMAND pCmd;
543         POS_CMDEXT ext;
544         HPT_U8 *cdb;
545
546         if (ccb->ccb_h.flags & CAM_CDB_POINTER)
547                 cdb = ccb->csio.cdb_io.cdb_ptr;
548         else
549                 cdb = ccb->csio.cdb_io.cdb_bytes;
550
551         KdPrint(("hpt_scsi_io: ccb %x id %d lun %d cdb %x-%x-%x",
552                 ccb,
553                 ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
554                 *(HPT_U32 *)&cdb[0], *(HPT_U32 *)&cdb[4], *(HPT_U32 *)&cdb[8]
555         ));
556
557         /* ccb->ccb_h.path_id is not our bus id - don't check it */
558         if (ccb->ccb_h.target_lun != 0 ||
559                 ccb->ccb_h.target_id >= osm_max_targets ||
560                 (ccb->ccb_h.flags & CAM_CDB_PHYS))
561         {
562                 ccb->ccb_h.status = CAM_TID_INVALID;
563                 xpt_done(ccb);
564                 return;
565         }
566
567         vd = ldm_find_target(vbus, ccb->ccb_h.target_id);
568
569         if (!vd) {
570                 ccb->ccb_h.status = CAM_TID_INVALID;
571                 xpt_done(ccb);
572                 return;
573         }
574
575         switch (cdb[0]) {
576         case TEST_UNIT_READY:
577         case START_STOP_UNIT:
578         case SYNCHRONIZE_CACHE:
579                 ccb->ccb_h.status = CAM_REQ_CMP;
580                 break;
581
582         case INQUIRY:
583                 {
584                         PINQUIRYDATA inquiryData;
585                         memset(ccb->csio.data_ptr, 0, ccb->csio.dxfer_len);
586                         inquiryData = (PINQUIRYDATA)ccb->csio.data_ptr;
587
588                         inquiryData->AdditionalLength = 31;
589                         inquiryData->CommandQueue = 1;
590                         memcpy(&inquiryData->VendorId, "HPT     ", 8);
591                         memcpy(&inquiryData->ProductId, "DISK 0_0        ", 16);
592
593                         if (vd->target_id / 10) {
594                                 inquiryData->ProductId[7] = (vd->target_id % 100) / 10 + '0';
595                                 inquiryData->ProductId[8] = (vd->target_id % 100) % 10 + '0';
596                         }
597                         else
598                                 inquiryData->ProductId[7] = (vd->target_id % 100) % 10 + '0';
599
600                         memcpy(&inquiryData->ProductRevisionLevel, "4.00", 4);
601
602                         ccb->ccb_h.status = CAM_REQ_CMP;
603                 }
604                 break;
605
606         case READ_CAPACITY:
607         {
608                 HPT_U8 *rbuf = ccb->csio.data_ptr;
609                 HPT_U32 cap;
610
611                 if (vd->capacity>0xfffffffful)
612                         cap = 0xfffffffful;
613                 else
614                         cap = vd->capacity - 1;
615
616                 rbuf[0] = (HPT_U8)(cap>>24);
617                 rbuf[1] = (HPT_U8)(cap>>16);
618                 rbuf[2] = (HPT_U8)(cap>>8);
619                 rbuf[3] = (HPT_U8)cap;
620                 rbuf[4] = 0;
621                 rbuf[5] = 0;
622                 rbuf[6] = 2;
623                 rbuf[7] = 0;
624
625                 ccb->ccb_h.status = CAM_REQ_CMP;
626                 break;
627         }
628
629         case SERVICE_ACTION_IN:
630         {
631                 HPT_U8 *rbuf = ccb->csio.data_ptr;
632                 HPT_U64 cap = vd->capacity - 1;
633
634                 rbuf[0] = (HPT_U8)(cap>>56);
635                 rbuf[1] = (HPT_U8)(cap>>48);
636                 rbuf[2] = (HPT_U8)(cap>>40);
637                 rbuf[3] = (HPT_U8)(cap>>32);
638                 rbuf[4] = (HPT_U8)(cap>>24);
639                 rbuf[5] = (HPT_U8)(cap>>16);
640                 rbuf[6] = (HPT_U8)(cap>>8);
641                 rbuf[7] = (HPT_U8)cap;
642                 rbuf[8] = 0;
643                 rbuf[9] = 0;
644                 rbuf[10] = 2;
645                 rbuf[11] = 0;
646
647                 ccb->ccb_h.status = CAM_REQ_CMP;
648                 break;
649         }
650
651         case READ_6:
652         case READ_10:
653         case READ_16:
654         case WRITE_6:
655         case WRITE_10:
656         case WRITE_16:
657         case 0x13:
658         case 0x2f:
659         case 0x8f: /* VERIFY_16 */
660         {
661                 pCmd = ldm_alloc_cmds(vbus, vd->cmds_per_request);
662                 if(!pCmd){
663                         KdPrint(("Failed to allocate command!"));
664                         ccb->ccb_h.status = CAM_BUSY;
665                         break;
666                 }
667
668                 switch (cdb[0]) {
669                 case READ_6:
670                 case WRITE_6:
671                 case 0x13:
672                         pCmd->uCmd.Ide.Lba =  ((HPT_U32)cdb[1] << 16) | ((HPT_U32)cdb[2] << 8) | (HPT_U32)cdb[3];
673                         pCmd->uCmd.Ide.nSectors = (HPT_U16) cdb[4];
674                         break;
675                 case READ_16:
676                 case WRITE_16:
677                 case 0x8f: /* VERIFY_16 */
678                 {
679                         HPT_U64 block =
680                                 ((HPT_U64)cdb[2]<<56) |
681                                 ((HPT_U64)cdb[3]<<48) |
682                                 ((HPT_U64)cdb[4]<<40) |
683                                 ((HPT_U64)cdb[5]<<32) |
684                                 ((HPT_U64)cdb[6]<<24) |
685                                 ((HPT_U64)cdb[7]<<16) |
686                                 ((HPT_U64)cdb[8]<<8) |
687                                 ((HPT_U64)cdb[9]);
688                         pCmd->uCmd.Ide.Lba = block;
689                         pCmd->uCmd.Ide.nSectors = (HPT_U16)cdb[13] | ((HPT_U16)cdb[12]<<8);
690                         break;
691                 }
692
693                 default:
694                         pCmd->uCmd.Ide.Lba = (HPT_U32)cdb[5] | ((HPT_U32)cdb[4] << 8) | ((HPT_U32)cdb[3] << 16) | ((HPT_U32)cdb[2] << 24);
695                         pCmd->uCmd.Ide.nSectors = (HPT_U16) cdb[8] | ((HPT_U16)cdb[7]<<8);
696                         break;
697                 }
698
699                 switch (cdb[0]) {
700                 case READ_6:
701                 case READ_10:
702                 case READ_16:
703                         pCmd->flags.data_in = 1;
704                         break;
705                 case WRITE_6:
706                 case WRITE_10:
707                 case WRITE_16:
708                         pCmd->flags.data_out = 1;
709                         break;
710                 }
711                 pCmd->priv = ext = cmdext_get(vbus_ext);
712                 HPT_ASSERT(ext);
713                 ext->ccb = ccb;
714                 pCmd->target = vd;
715                 pCmd->done = os_cmddone;
716                 pCmd->buildsgl = os_buildsgl;
717
718                 pCmd->psg = ext->psg;
719
720                 if (ccb->ccb_h.flags & CAM_SCATTER_VALID) {
721                         int idx;
722                         bus_dma_segment_t *sgList = (bus_dma_segment_t *)ccb->csio.data_ptr;
723
724                         if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS)
725                                 pCmd->flags.physical_sg = 1;
726
727                         for (idx = 0; idx < ccb->csio.sglist_cnt; idx++) {
728                                 pCmd->psg[idx].addr.bus = sgList[idx].ds_addr;
729                                 pCmd->psg[idx].size = sgList[idx].ds_len;
730                                 pCmd->psg[idx].eot = (idx==ccb->csio.sglist_cnt-1)? 1 : 0;
731                         }
732
733                         callout_reset(&ccb->ccb_h.timeout_ch, HPT_OSM_TIMEOUT, hpt_timeout, pCmd);
734                         ldm_queue_cmd(pCmd);
735                 }
736                 else {
737                         int error;
738                         pCmd->flags.physical_sg = 1;
739                         error = bus_dmamap_load(vbus_ext->io_dmat,
740                                                 ext->dma_map,
741                                                 ccb->csio.data_ptr, ccb->csio.dxfer_len,
742                                                 hpt_io_dmamap_callback, pCmd,
743                                         BUS_DMA_WAITOK
744                                         );
745                         KdPrint(("bus_dmamap_load return %d", error));
746                         if (error && error!=EINPROGRESS) {
747                                 os_printk("bus_dmamap_load error %d", error);
748                                 cmdext_put(ext);
749                                 ldm_free_cmds(pCmd);
750                                 ccb->ccb_h.status = CAM_REQ_CMP_ERR;
751                                 xpt_done(ccb);
752                         }
753                 }
754                 return;
755         }
756
757         default:
758                 ccb->ccb_h.status = CAM_REQ_INVALID;
759                 break;
760         }
761
762         xpt_done(ccb);
763         return;
764 }
765
766 static void hpt_action(struct cam_sim *sim, union ccb *ccb)
767 {
768         PVBUS_EXT vbus_ext = (PVBUS_EXT)cam_sim_softc(sim);
769
770         KdPrint(("hpt_action(fn=%d, id=%d)", ccb->ccb_h.func_code, ccb->ccb_h.target_id));
771
772         switch (ccb->ccb_h.func_code) {
773
774         case XPT_SCSI_IO:
775                 hpt_lock_vbus(vbus_ext);
776                 hpt_scsi_io(vbus_ext, ccb);
777                 hpt_unlock_vbus(vbus_ext);
778                 return;
779
780         case XPT_RESET_BUS:
781                 hpt_lock_vbus(vbus_ext);
782                 ldm_reset_vbus((PVBUS)vbus_ext->vbus);
783                 hpt_unlock_vbus(vbus_ext);
784                 break;
785
786         case XPT_GET_TRAN_SETTINGS:
787         case XPT_SET_TRAN_SETTINGS:
788                 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
789                 break;
790
791         case XPT_CALC_GEOMETRY:
792                 ccb->ccg.heads = 255;
793                 ccb->ccg.secs_per_track = 63;
794                 ccb->ccg.cylinders = ccb->ccg.volume_size / (ccb->ccg.heads * ccb->ccg.secs_per_track);
795                 ccb->ccb_h.status = CAM_REQ_CMP;
796                 break;
797
798         case XPT_PATH_INQ:
799         {
800                 struct ccb_pathinq *cpi = &ccb->cpi;
801
802                 cpi->version_num = 1;
803                 cpi->hba_inquiry = PI_SDTR_ABLE;
804                 cpi->target_sprt = 0;
805                 cpi->hba_misc = PIM_NOBUSRESET;
806                 cpi->hba_eng_cnt = 0;
807                 cpi->max_target = osm_max_targets;
808                 cpi->max_lun = 0;
809                 cpi->unit_number = cam_sim_unit(sim);
810                 cpi->bus_id = cam_sim_bus(sim);
811                 cpi->initiator_id = osm_max_targets;
812                 cpi->base_transfer_speed = 3300;
813
814                 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
815                 strncpy(cpi->hba_vid, "HPT   ", HBA_IDLEN);
816                 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
817                 cpi->transport = XPORT_SPI;
818                 cpi->transport_version = 2;
819                 cpi->protocol = PROTO_SCSI;
820                 cpi->protocol_version = SCSI_REV_2;
821                 cpi->maxio = HPT27XX_DFLTPHYS;
822                 cpi->ccb_h.status = CAM_REQ_CMP;
823                 break;
824         }
825
826         default:
827                 ccb->ccb_h.status = CAM_REQ_INVALID;
828                 break;
829         }
830
831         xpt_done(ccb);
832         return;
833 }
834
835 static void hpt_pci_intr(void *arg)
836 {
837         PVBUS_EXT vbus_ext = (PVBUS_EXT)arg;
838         hpt_lock_vbus(vbus_ext);
839         ldm_intr((PVBUS)vbus_ext->vbus);
840         hpt_unlock_vbus(vbus_ext);
841 }
842
843 static void hpt_poll(struct cam_sim *sim)
844 {
845         hpt_pci_intr(cam_sim_softc(sim));
846 }
847
848 static void hpt_async(void * callback_arg, u_int32_t code, struct cam_path * path, void * arg)
849 {
850         KdPrint(("hpt_async"));
851 }
852
853 static int hpt_shutdown(device_t dev)
854 {
855         KdPrint(("hpt_shutdown(dev=%p)", dev));
856         return 0;
857 }
858
859 static int hpt_detach(device_t dev)
860 {
861         /* we don't allow the driver to be unloaded. */
862         return EBUSY;
863 }
864
865 static void hpt_ioctl_done(struct _IOCTL_ARG *arg)
866 {
867         arg->ioctl_cmnd = 0;
868         wakeup(arg);
869 }
870
871 static void __hpt_do_ioctl(PVBUS_EXT vbus_ext, IOCTL_ARG *ioctl_args)
872 {
873         ioctl_args->result = -1;
874         ioctl_args->done = hpt_ioctl_done;
875         ioctl_args->ioctl_cmnd = (void *)1;
876
877         hpt_lock_vbus(vbus_ext);
878         ldm_ioctl((PVBUS)vbus_ext->vbus, ioctl_args);
879
880         while (ioctl_args->ioctl_cmnd) {
881                 if (hpt_sleep(vbus_ext, ioctl_args, 0, "hptctl", HPT_OSM_TIMEOUT)==0)
882                         break;
883                 ldm_reset_vbus((PVBUS)vbus_ext->vbus);
884                 __hpt_do_tasks(vbus_ext);
885         }
886
887         /* KdPrint(("ioctl %x result %d", ioctl_args->dwIoControlCode, ioctl_args->result)); */
888
889         hpt_unlock_vbus(vbus_ext);
890 }
891
892 static void hpt_do_ioctl(IOCTL_ARG *ioctl_args)
893 {
894         PVBUS vbus;
895         PVBUS_EXT vbus_ext;
896
897         ldm_for_each_vbus(vbus, vbus_ext) {
898                 __hpt_do_ioctl(vbus_ext, ioctl_args);
899                 if (ioctl_args->result!=HPT_IOCTL_RESULT_WRONG_VBUS)
900                         return;
901         }
902 }
903
904 #define HPT_DO_IOCTL(code, inbuf, insize, outbuf, outsize) ({\
905         IOCTL_ARG arg;\
906         arg.dwIoControlCode = code;\
907         arg.lpInBuffer = inbuf;\
908         arg.lpOutBuffer = outbuf;\
909         arg.nInBufferSize = insize;\
910         arg.nOutBufferSize = outsize;\
911         arg.lpBytesReturned = 0;\
912         hpt_do_ioctl(&arg);\
913         arg.result;\
914 })
915
916 #define DEVICEID_VALID(id) ((id) && ((HPT_U32)(id)!=0xffffffff))
917
918 static int hpt_get_logical_devices(DEVICEID * pIds, int nMaxCount)
919 {
920         int i;
921         HPT_U32 count = nMaxCount-1;
922
923         if (HPT_DO_IOCTL(HPT_IOCTL_GET_LOGICAL_DEVICES,
924                         &count, sizeof(HPT_U32), pIds, sizeof(DEVICEID)*nMaxCount))
925                 return -1;
926
927         nMaxCount = (int)pIds[0];
928         for (i=0; i<nMaxCount; i++) pIds[i] = pIds[i+1];
929         return nMaxCount;
930 }
931
932 static int hpt_get_device_info_v3(DEVICEID id, PLOGICAL_DEVICE_INFO_V3 pInfo)
933 {
934         return HPT_DO_IOCTL(HPT_IOCTL_GET_DEVICE_INFO_V3,
935                                 &id, sizeof(DEVICEID), pInfo, sizeof(LOGICAL_DEVICE_INFO_V3));
936 }
937
938 /* not belong to this file logically, but we want to use ioctl interface */
939 static int __hpt_stop_tasks(PVBUS_EXT vbus_ext, DEVICEID id)
940 {
941         LOGICAL_DEVICE_INFO_V3 devinfo;
942         int i, result;
943         DEVICEID param[2] = { id, 0 };
944
945         if (hpt_get_device_info_v3(id, &devinfo))
946                 return -1;
947
948         if (devinfo.Type!=LDT_ARRAY)
949                 return -1;
950
951         if (devinfo.u.array.Flags & ARRAY_FLAG_REBUILDING)
952                 param[1] = AS_REBUILD_ABORT;
953         else if (devinfo.u.array.Flags & ARRAY_FLAG_VERIFYING)
954                 param[1] = AS_VERIFY_ABORT;
955         else if (devinfo.u.array.Flags & ARRAY_FLAG_INITIALIZING)
956                 param[1] = AS_INITIALIZE_ABORT;
957         else if (devinfo.u.array.Flags & ARRAY_FLAG_TRANSFORMING)
958                 param[1] = AS_TRANSFORM_ABORT;
959         else
960                 return -1;
961
962         KdPrint(("SET_ARRAY_STATE(%x, %d)", param[0], param[1]));
963         result = HPT_DO_IOCTL(HPT_IOCTL_SET_ARRAY_STATE,
964                                 param, sizeof(param), 0, 0);
965
966         for (i=0; i<devinfo.u.array.nDisk; i++)
967                 if (DEVICEID_VALID(devinfo.u.array.Members[i]))
968                         __hpt_stop_tasks(vbus_ext, devinfo.u.array.Members[i]);
969
970         return result;
971 }
972
973 static void hpt_stop_tasks(PVBUS_EXT vbus_ext)
974 {
975         DEVICEID ids[32];
976         int i, count;
977
978         count = hpt_get_logical_devices((DEVICEID *)&ids, sizeof(ids)/sizeof(ids[0]));
979
980         for (i=0; i<count; i++)
981                 __hpt_stop_tasks(vbus_ext, ids[i]);
982 }
983
984 static  d_open_t        hpt_open;
985 static  d_close_t       hpt_close;
986 static  d_ioctl_t       hpt_ioctl;
987 static  void            hpt_bus_scan_cb(struct cam_periph *periph, union ccb *ccb);
988 static  int             hpt_rescan_bus(void);
989
990 static struct dev_ops hpt_ops = {
991         { driver_name, 0, 0 },
992         .d_open =       hpt_open,
993         .d_close =      hpt_close,
994         .d_ioctl =      hpt_ioctl,
995 };
996
997 static struct intr_config_hook hpt_ich;
998
999 /*
1000  * hpt_final_init will be called after all hpt_attach.
1001  */
1002 static void hpt_final_init(void *dummy)
1003 {
1004         int       i;
1005         PVBUS_EXT vbus_ext;
1006         PVBUS vbus;
1007         PHBA hba;
1008
1009         /* Clear the config hook */
1010         config_intrhook_disestablish(&hpt_ich);
1011
1012         /* allocate memory */
1013         i = 0;
1014         ldm_for_each_vbus(vbus, vbus_ext) {
1015                 if (hpt_alloc_mem(vbus_ext)) {
1016                         os_printk("out of memory");
1017                         return;
1018                 }
1019                 i++;
1020         }
1021
1022         if (!i) {
1023                         os_printk("no controller detected.");
1024                 return;
1025         }
1026
1027         /* initializing hardware */
1028         ldm_for_each_vbus(vbus, vbus_ext) {
1029                 /* make timer available here */
1030                 callout_init(&vbus_ext->timer);
1031                 if (hpt_init_vbus(vbus_ext)) {
1032                         os_printk("fail to initialize hardware");
1033                         break; /* FIXME */
1034                 }
1035         }
1036
1037         /* register CAM interface */
1038         ldm_for_each_vbus(vbus, vbus_ext) {
1039                 struct cam_devq *devq;
1040                 struct ccb_setasync     ccb;
1041
1042                 lockinit(&vbus_ext->lock, "hptsleeplock", 0, LK_CANRECURSE);
1043                 if (bus_dma_tag_create(NULL,/* parent */
1044                                 4,      /* alignment */
1045                                 BUS_SPACE_MAXADDR_32BIT+1, /* boundary */
1046                                 BUS_SPACE_MAXADDR,      /* lowaddr */
1047                                 BUS_SPACE_MAXADDR,      /* highaddr */
1048                                 NULL, NULL,             /* filter, filterarg */
1049                                 PAGE_SIZE * (os_max_sg_descriptors-1),  /* maxsize */
1050                                 os_max_sg_descriptors,  /* nsegments */
1051                                 0x10000,        /* maxsegsize */
1052                                 BUS_DMA_WAITOK,         /* flags */
1053                                 &vbus_ext->io_dmat      /* tag */))
1054                 {
1055                         return ;
1056                 }
1057
1058                 for (i=0; i<os_max_queue_comm; i++) {
1059                         POS_CMDEXT ext = (POS_CMDEXT)kmalloc(sizeof(OS_CMDEXT), M_DEVBUF, M_WAITOK);
1060                         if (!ext) {
1061                                 os_printk("Can't alloc cmdext(%d)", i);
1062                                 return ;
1063                         }
1064                         ext->vbus_ext = vbus_ext;
1065                         ext->next = vbus_ext->cmdext_list;
1066                         vbus_ext->cmdext_list = ext;
1067
1068                         if (bus_dmamap_create(vbus_ext->io_dmat, 0, &ext->dma_map)) {
1069                                 os_printk("Can't create dma map(%d)", i);
1070                                 return ;
1071                         }
1072                 }
1073
1074                 if ((devq = cam_simq_alloc(os_max_queue_comm)) == NULL) {
1075                         os_printk("cam_simq_alloc failed");
1076                         return ;
1077                 }
1078
1079                 vbus_ext->sim = cam_sim_alloc(hpt_action, hpt_poll, driver_name,
1080                                 vbus_ext, 0, &sim_mplock, os_max_queue_comm, /*tagged*/8,  devq);
1081
1082                 if (!vbus_ext->sim) {
1083                         os_printk("cam_sim_alloc failed");
1084                         cam_simq_release(devq);
1085                         return ;
1086                 }
1087                 cam_simq_release(devq);
1088
1089                 if (xpt_bus_register(vbus_ext->sim, 0) != CAM_SUCCESS) {
1090                         os_printk("xpt_bus_register failed");
1091                         cam_sim_free(vbus_ext->sim);
1092                         vbus_ext->sim = NULL;
1093                         return ;
1094                 }
1095
1096                 if (xpt_create_path(&vbus_ext->path, /*periph */ NULL,
1097                                 cam_sim_path(vbus_ext->sim), CAM_TARGET_WILDCARD,
1098                                 CAM_LUN_WILDCARD) != CAM_REQ_CMP)
1099                 {
1100                         os_printk("xpt_create_path failed");
1101                         xpt_bus_deregister(cam_sim_path(vbus_ext->sim));
1102                         cam_sim_free(vbus_ext->sim);
1103                         vbus_ext->sim = NULL;
1104                         return ;
1105                 }
1106
1107                 xpt_setup_ccb(&ccb.ccb_h, vbus_ext->path, /*priority*/5);
1108                 ccb.ccb_h.func_code = XPT_SASYNC_CB;
1109                 ccb.event_enable = AC_LOST_DEVICE;
1110                 ccb.callback = hpt_async;
1111                 ccb.callback_arg = vbus_ext;
1112                 xpt_action((union ccb *)&ccb);
1113
1114                 for (hba = vbus_ext->hba_list; hba; hba = hba->next) {
1115                         int rid = 0;
1116                         if ((hba->irq_res = bus_alloc_resource(hba->pcidev,
1117                                 SYS_RES_IRQ, &rid, 0, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE)) == NULL)
1118                         {
1119                                 os_printk("can't allocate interrupt");
1120                                 return ;
1121                         }
1122
1123                         if (bus_setup_intr(hba->pcidev, hba->irq_res, 0,
1124                                 hpt_pci_intr, vbus_ext, &hba->irq_handle, NULL))
1125                         {
1126                                 os_printk("can't set up interrupt");
1127                                 return ;
1128                         }
1129                         hba->ldm_adapter.him->intr_control(hba->ldm_adapter.him_handle, HPT_TRUE);
1130
1131                 }
1132
1133                 vbus_ext->shutdown_eh = EVENTHANDLER_REGISTER(shutdown_final,
1134                                                                         hpt_shutdown_vbus, vbus_ext, SHUTDOWN_PRI_DEFAULT);
1135                 if (!vbus_ext->shutdown_eh)
1136                         os_printk("Shutdown event registration failed");
1137         }
1138
1139         ldm_for_each_vbus(vbus, vbus_ext) {
1140                 TASK_INIT(&vbus_ext->worker, 0, (task_fn_t *)hpt_do_tasks, vbus_ext);
1141                 if (vbus_ext->tasks)
1142                         TASK_ENQUEUE(&vbus_ext->worker);
1143         }
1144
1145         make_dev(&hpt_ops, DRIVER_MINOR, UID_ROOT, GID_OPERATOR,
1146             S_IRUSR | S_IWUSR, driver_name);
1147 }
1148
1149 #if defined(KLD_MODULE) && (__FreeBSD_version >= 503000)
1150
1151 typedef struct driverlink *driverlink_t;
1152 struct driverlink {
1153         kobj_class_t    driver;
1154         TAILQ_ENTRY(driverlink) link;   /* list of drivers in devclass */
1155 };
1156
1157 typedef TAILQ_HEAD(driver_list, driverlink) driver_list_t;
1158
1159 struct devclass {
1160         TAILQ_ENTRY(devclass) link;
1161         devclass_t      parent;         /* parent in devclass hierarchy */
1162         driver_list_t   drivers;     /* bus devclasses store drivers for bus */
1163         char            *name;
1164         device_t        *devices;       /* array of devices indexed by unit */
1165         int             maxunit;        /* size of devices array */
1166 };
1167
1168 static void override_kernel_driver(void)
1169 {
1170         driverlink_t dl, dlfirst;
1171         driver_t *tmpdriver;
1172         devclass_t dc = devclass_find("pci");
1173
1174         if (dc){
1175                 dlfirst = TAILQ_FIRST(&dc->drivers);
1176                 for (dl = dlfirst; dl; dl = TAILQ_NEXT(dl, link)) {
1177                         if(strcmp(dl->driver->name, driver_name) == 0) {
1178                                 tmpdriver=dl->driver;
1179                                 dl->driver=dlfirst->driver;
1180                                 dlfirst->driver=tmpdriver;
1181                                 break;
1182                         }
1183                 }
1184         }
1185 }
1186
1187 #else
1188 #define override_kernel_driver()
1189 #endif
1190
1191 static void hpt_init(void *dummy)
1192 {
1193                 os_printk("%s %s", driver_name_long, driver_ver);
1194
1195         override_kernel_driver();
1196         init_config();
1197
1198         hpt_ich.ich_func = hpt_final_init;
1199         hpt_ich.ich_arg = NULL;
1200         if (config_intrhook_establish(&hpt_ich) != 0) {
1201                 kprintf("%s: cannot establish configuration hook\n",
1202                     driver_name_long);
1203         }
1204
1205 }
1206 SYSINIT(hptinit, SI_SUB_CONFIGURE, SI_ORDER_FIRST, hpt_init, NULL);
1207
1208 /*
1209  * CAM driver interface
1210  */
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),
1217         { 0, 0 }
1218 };
1219
1220 static driver_t hpt_pci_driver = {
1221         driver_name,
1222         driver_methods,
1223         sizeof(HBA)
1224 };
1225
1226 static devclass_t       hpt_devclass;
1227
1228 #ifndef TARGETNAME
1229 #error "no TARGETNAME found"
1230 #endif
1231
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, 0, 0);
1237 __MODULE_VERSION(TARGETNAME, 1);
1238 __MODULE_DEPEND(TARGETNAME, cam, 1, 1, 1);
1239
1240 typedef struct cdev * ioctl_dev_t;
1241
1242 typedef struct thread * ioctl_thread_t;
1243
1244 static int hpt_open(struct dev_open_args *ap)
1245 {
1246         return 0;
1247 }
1248
1249 static int hpt_close(struct dev_close_args *ap)
1250 {
1251         return 0;
1252 }
1253
1254 static int hpt_ioctl(struct dev_ioctl_args *ap)
1255 {
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;
1261
1262         switch (cmd){
1263         case HPT_DO_IOCONTROL:
1264         {
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,
1268                                 piop->lpInBuffer,
1269                                 piop->nInBufferSize,
1270                                 piop->lpOutBuffer,
1271                                 piop->nOutBufferSize));
1272
1273                 memset(&ioctl_args, 0, sizeof(ioctl_args));
1274
1275                 ioctl_args.dwIoControlCode = piop->dwIoControlCode;
1276                 ioctl_args.nInBufferSize = piop->nInBufferSize;
1277                 ioctl_args.nOutBufferSize = piop->nOutBufferSize;
1278                 ioctl_args.lpBytesReturned = &bytesReturned;
1279
1280                 if (ioctl_args.nInBufferSize) {
1281                         ioctl_args.lpInBuffer = kmalloc(ioctl_args.nInBufferSize, M_DEVBUF, M_WAITOK);
1282                         if (!ioctl_args.lpInBuffer)
1283                                 goto invalid;
1284                         if (copyin((void*)piop->lpInBuffer,
1285                                         ioctl_args.lpInBuffer, piop->nInBufferSize))
1286                                 goto invalid;
1287                 }
1288
1289                 if (ioctl_args.nOutBufferSize) {
1290                         ioctl_args.lpOutBuffer = kmalloc(ioctl_args.nOutBufferSize, M_DEVBUF, M_WAITOK);
1291                         if (!ioctl_args.lpOutBuffer)
1292                                 goto invalid;
1293                 }
1294
1295                 get_mplock();
1296
1297                 hpt_do_ioctl(&ioctl_args);
1298
1299                 rel_mplock();
1300
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))
1305                                         goto invalid;
1306                         }
1307                         if (piop->lpBytesReturned) {
1308                                 if (copyout(&bytesReturned,
1309                                         (void*)piop->lpBytesReturned, sizeof(HPT_U32)))
1310                                         goto invalid;
1311                         }
1312                         if (ioctl_args.lpInBuffer) kfree(ioctl_args.lpInBuffer, M_DEVBUF);
1313                         if (ioctl_args.lpOutBuffer) kfree(ioctl_args.lpOutBuffer, M_DEVBUF);
1314                         return 0;
1315                 }
1316 invalid:
1317                 if (ioctl_args.lpInBuffer) kfree(ioctl_args.lpInBuffer, M_DEVBUF);
1318                 if (ioctl_args.lpOutBuffer) kfree(ioctl_args.lpOutBuffer, M_DEVBUF);
1319                 return EFAULT;
1320         }
1321         return EFAULT;
1322         }
1323
1324         case HPT_SCAN_BUS:
1325         {
1326                 return hpt_rescan_bus();
1327         }
1328         default:
1329                 KdPrint(("invalid command!"));
1330                 return EFAULT;
1331         }
1332
1333 }
1334
1335 static int      hpt_rescan_bus(void)
1336 {
1337         struct cam_path         *path;
1338         union ccb                       *ccb;
1339         PVBUS                           vbus;
1340         PVBUS_EXT                       vbus_ext;
1341
1342         get_mplock();
1343
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)
1347                         return(EIO);
1348                 if ((ccb = kmalloc(sizeof(union ccb), M_TEMP, M_WAITOK)) == NULL)
1349                         return(ENOMEM);
1350                 bzero(ccb, sizeof(union ccb));
1351                 xpt_setup_ccb(&ccb->ccb_h, path, 5);
1352                 ccb->ccb_h.func_code = XPT_SCAN_BUS;
1353                 ccb->ccb_h.cbfcnp = hpt_bus_scan_cb;
1354                 ccb->crcn.flags = CAM_FLAG_NONE;
1355                 xpt_action(ccb);
1356         }
1357
1358         rel_mplock();
1359
1360         return(0);
1361 }
1362
1363 static  void    hpt_bus_scan_cb(struct cam_periph *periph, union ccb *ccb)
1364 {
1365         if (ccb->ccb_h.status != CAM_REQ_CMP)
1366                 KdPrint(("cam_scan_callback: failure status = %x",ccb->ccb_h.status));
1367         else
1368                 KdPrint(("Scan bus successfully!"));
1369
1370         xpt_free_path(ccb->ccb_h.path);
1371         kfree(ccb, M_TEMP);
1372         return;
1373 }