4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * Utility DCD configuration routines.
33 #include <sys/dada/dada.h>
34 #include <sys/modctl.h>
36 extern struct mod_ops mod_miscops
;
38 static struct modlmisc modlmisc
= {
39 &mod_miscops
, /* Type of module */
40 " ATA Bus Utility Routines"
43 static struct modlinkage modlinkage
= {
44 MODREV_1
, (void *)&modlmisc
, NULL
49 static int dcd_test(struct dcd_pkt
*);
50 void makecommand(struct dcd_pkt
*, int, uchar_t
, uint32_t,
51 uchar_t
, uint32_t, uchar_t
, uchar_t
);
57 (void) dcd_initialize_hba_interface();
59 return (mod_install(&modlinkage
));
64 * There is no _fini() routine because this module is never unloaded.
68 struct modinfo
*modinfop
;
71 return (mod_info(&modlinkage
, modinfop
));
75 * The implementation of dcd_probe allows a particular HBA to intercept the call
76 * for any post or pre-processing it may need. The default, if the HBA does not
77 * override it, is to call dcd_hba_probe.
80 dcd_probe(struct dcd_device
*devp
, int (*callback
)())
82 dcd_hba_tran_t
*hba_tran
= devp
->dcd_address
->a_hba_tran
;
84 if (hba_tran
->tran_tgt_probe
!= NULL
) {
85 return ((*hba_tran
->tran_tgt_probe
)(devp
, callback
));
87 return (dcd_hba_probe(devp
, callback
));
95 dcd_unprobe(struct dcd_device
*devp
)
97 if (devp
->dcd_ident
) {
98 kmem_free((caddr_t
)devp
->dcd_ident
, SUN_IDENTSIZE
);
99 devp
->dcd_ident
= (struct dcd_identify
*)NULL
;
103 #define ROUTE (devp->dcd_address)
106 dcd_hba_probe(struct dcd_device
*devp
, int (*callback
)())
109 struct dcd_pkt
*ident_pkt
= NULL
;
110 int rval
= DCDPROBE_NOMEM
;
111 struct buf
*ident_bp
= NULL
;
114 if (devp
->dcd_ident
== NULL
) {
116 printf("Dcd_ident is NULL\n");
119 devp
->dcd_ident
= (struct dcd_identify
*)
120 kmem_alloc(SUN_IDENTSIZE
, ((callback
== SLEEP_FUNC
)?
121 KM_SLEEP
: KM_NOSLEEP
));
122 if (devp
->dcd_ident
== NULL
) {
127 if (callback
!= SLEEP_FUNC
&& callback
!= NULL_FUNC
) {
133 ident_bp
= dcd_alloc_consistent_buf(ROUTE
, (struct buf
*)NULL
,
134 (uint_t
)SUN_IDENTSIZE
, B_READ
, cb_flag
, NULL
);
135 if (ident_bp
== NULL
) {
139 ident_pkt
= dcd_init_pkt(ROUTE
, (struct dcd_pkt
*)NULL
,
140 ident_bp
, sizeof (struct dcd_cmd
), 2, 0,
144 if (ident_pkt
== NULL
) {
145 if (ident_bp
->b_error
== 0)
146 rval
= DCDPROBE_NOMEM_CB
;
152 bzero((caddr_t
)devp
->dcd_ident
, SUN_IDENTSIZE
);
154 makecommand(ident_pkt
, FLAG_NOINTR
, IDENTIFY
, 0, ADD_LBA_MODE
,
155 SUN_IDENTSIZE
, DATA_READ
, 0);
158 * The first identify will tell us whether the target responded
162 if (dcd_test(ident_pkt
) < 0) {
164 printf("dcd_test: failed\n");
166 if (ident_pkt
->pkt_reason
== CMD_INCOMPLETE
) {
167 rval
= DCDPROBE_NORESP
;
171 * retry one more time
173 if (dcd_test(ident_pkt
) < 0) {
174 rval
= DCDPROBE_FAILURE
;
181 printf("Pkt reason %x, scsbp %x\n", ident_pkt
->pkt_reason
,
182 *ident_pkt
->pkt_scbp
);
185 * If we are lucky, this identify succeeded
187 if ((ident_pkt
->pkt_reason
== CMD_CMPLT
) &&
188 (((*ident_pkt
->pkt_scbp
) & STATUS_ATA_MASK
) == 0)) {
193 * the second inquiry, allows the host adapters to try again.
195 if (dcd_test(ident_pkt
) < 0) {
196 if (ident_pkt
->pkt_reason
== CMD_INCOMPLETE
)
197 rval
= DCDPROBE_NORESP
;
199 rval
= DCDPROBE_FAILURE
;
204 * At this point we are guarenteed that something responded
205 * to this target. We don't know yest what kind of device it is.
208 if (dcd_test(ident_pkt
) < 0) {
209 rval
= DCDPROBE_FAILURE
;
215 * If we got no error then receive the indentify data,
217 if ((ident_pkt
->pkt_state
& STATE_XFERRED_DATA
) == 0 &&
218 ident_pkt
->pkt_resid
> 0) {
219 rval
= DCDPROBE_NONCCS
;
221 bcopy((caddr_t
)ident_bp
->b_un
.b_addr
,
222 (caddr_t
)devp
->dcd_ident
, SUN_IDENTSIZE
);
223 rval
= DCDPROBE_EXISTS
;
228 dcd_destroy_pkt(ident_pkt
);
231 dcd_free_consistent_buf(ident_bp
);
238 dcd_test(struct dcd_pkt
*pkt
)
243 pkt
->pkt_flags
|= FLAG_NOINTR
;
244 pkt
->pkt_time
= DCD_POLL_TIMEOUT
;
247 printf("flags %x: timeout %x\n", pkt
->pkt_flags
, pkt
->pkt_time
);
250 if (dcd_transport(pkt
) != TRAN_ACCEPT
) {
252 } else if (pkt
->pkt_reason
== CMD_INCOMPLETE
&&
253 pkt
->pkt_state
== 0) {
255 } else if (pkt
->pkt_reason
!= CMD_CMPLT
) {
257 } else if (((*pkt
->pkt_scbp
) & STATUS_ATA_MASK
) == STATUS_ATA_BUSY
) {
264 printf("dcd_test: rval is %x\n", rval
);
271 makecommand(struct dcd_pkt
*pkt
,
275 uchar_t address_mode
,
281 struct dcd_cmd
*cdbp
= (struct dcd_cmd
*)pkt
->pkt_cdbp
;
284 cdbp
->sector_num
.lba_num
= block
;
285 cdbp
->address_mode
= address_mode
;
286 cdbp
->direction
= direction
;
287 cdbp
->size
= size
; /* Size in bytes */
288 cdbp
->features
= features
;
290 pkt
->pkt_flags
= flags
;
292 printf("pkt flags set in dada %x\n", pkt
->pkt_flags
);
294 printf("command %x, flags %x, block %x, address_mode %x, size %x\n",
295 command
, flags
, block
, address_mode
, size
);