kernel: remove unused utsname_set_machine()
[unleashed.git] / usr / src / uts / sun / io / dada / impl / dcd_hba.c
blobc50552e8542f450e32bd5a434d19210b4a966308
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <sys/note.h>
29 * Generic SCSI Host Bus Adapter interface implementation
32 #include <sys/dada/dada.h>
34 extern int dcd_options;
36 static kmutex_t dcd_hba_mutex;
38 kmutex_t dcd_log_mutex;
40 struct dcd_hba_inst {
41 dev_info_t *inst_dip;
42 dcd_hba_tran_t *inst_hba_tran;
43 struct dcd_hba_inst *inst_next;
44 struct dcd_hba_inst *inst_prev;
47 static struct dcd_hba_inst *dcd_hba_list = NULL;
48 static struct dcd_hba_inst *dcd_hba_list_tail = NULL;
51 _NOTE(READ_ONLY_DATA(dev_ops))
53 kmutex_t dcd_flag_nointr_mutex;
54 kcondvar_t dcd_flag_nointr_cv;
58 * Called from _init when loading the dcd module.
60 void
61 dcd_initialize_hba_interface()
63 mutex_init(&dcd_hba_mutex, NULL, MUTEX_DRIVER, NULL);
64 mutex_init(&dcd_flag_nointr_mutex, NULL, MUTEX_DRIVER, NULL);
65 cv_init(&dcd_flag_nointr_cv, NULL, CV_DRIVER, NULL);
66 mutex_init(&dcd_log_mutex, NULL, MUTEX_DRIVER, NULL);
70 * Called from fini() when unloading the dcd module.
73 void
74 dcd_uninitialize_hba_interface()
76 mutex_destroy(&dcd_hba_mutex);
77 cv_destroy(&dcd_flag_nointr_cv);
78 mutex_destroy(&dcd_flag_nointr_mutex);
79 mutex_destroy(&dcd_log_mutex);
84 * Called by an HBA from _init()
86 /* ARGSUSED */
87 int
88 dcd_hba_init(struct modlinkage *modlp)
91 return (0);
96 #ifdef NOTNEEDED
97 /* ARGSUSED */
98 int
99 dcd_hba_attach(dev_info_t *dip,
100 ddi_dma_lim_t *hba_lim,
101 dcd_hba_tran_t *hba_tran,
102 int flags,
103 void *hba_options)
106 ddi_dma_attr_t hba_dma_attr;
108 bzero(&hba_dma_attr, sizeof (ddi_dma_attr_t));
110 hba_dma_attr.dma_attr_burstsizes = hba_lim->dlim_burstsizes;
111 hba_dma_attr.dma_attr_minxfer = hba_lim->dlim_minxfer;
113 return (dcd_hba_attach_setup(dip, &hba_dma_attr, hba_tran, flags));
115 #endif
119 dcd_hba_attach(
120 dev_info_t *dip,
121 ddi_dma_attr_t *hba_dma_attr,
122 dcd_hba_tran_t *hba_tran,
123 int flags)
126 struct dcd_hba_inst *elem;
127 int value;
128 int len;
129 char *prop_name;
130 char *errmsg =
131 "dcd_hba_attach: cannott create property '%s' for %s%d\n";
134 * Link this instance into the list
136 elem = kmem_alloc(sizeof (struct dcd_hba_inst), KM_SLEEP);
138 elem->inst_dip = dip;
139 elem->inst_hba_tran = hba_tran;
141 mutex_enter(&dcd_hba_mutex);
142 elem->inst_next = NULL;
143 elem->inst_prev = dcd_hba_list_tail;
145 if (dcd_hba_list == NULL) {
146 dcd_hba_list = elem;
148 if (dcd_hba_list_tail) {
149 dcd_hba_list_tail->inst_next = elem;
151 dcd_hba_list_tail = elem;
152 mutex_exit(&dcd_hba_mutex);
156 * Save all the improtant HBA information that must be accessed
157 * later.
160 hba_tran->tran_hba_dip = dip;
161 hba_tran->tran_hba_flags = flags;
164 * Note: We only need dma_attr_minxfer and dma_attr_burstsize
165 * from the DMA atrributes
168 hba_tran->tran_min_xfer = hba_dma_attr->dma_attr_minxfer;
169 hba_tran->tran_min_burst_size =
170 (1<<(ddi_ffs(hba_dma_attr->dma_attr_burstsizes)-1));
171 hba_tran->tran_max_burst_size =
172 (1<<(ddi_fls(hba_dma_attr->dma_attr_burstsizes)-1));
176 prop_name = "dcd_options";
177 len = 0;
178 if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN, 0, prop_name,
179 NULL, &len) == DDI_PROP_NOT_FOUND) {
180 value = dcd_options;
181 if (ddi_prop_update_int(DDI_MAJOR_T_UNKNOWN, dip,
182 prop_name, value) != DDI_PROP_SUCCESS) {
183 cmn_err(CE_CONT, errmsg, prop_name,
184 ddi_get_name(dip), ddi_get_instance(dip));
190 * XXX : This needs to be removed when code cleanup
191 * ddi_set_driver_private(dip, (caddr_t)hba_tran);
193 #ifdef DEBUG1
194 printf("Called Set driver private with dip %x, tran %x\n",
195 dip, hba_tran);
196 #endif
198 return (DDI_SUCCESS);
203 * called by an HBA to detach an instance of the driver
207 dcd_hba_detach(dev_info_t *dip)
210 dcd_hba_tran_t *hba;
211 struct dcd_hba_inst *elem;
213 hba = ddi_get_driver_private(dip);
214 ddi_set_driver_private(dip, NULL);
215 ASSERT(hba != NULL);
217 hba->tran_hba_dip = (dev_info_t *)NULL;
218 hba->tran_hba_flags = 0;
219 hba->tran_min_burst_size = (uchar_t)0;
220 hba->tran_max_burst_size = (uchar_t)0;
224 * Remove HBA instance from dcd_hba_list
227 mutex_enter(&dcd_hba_mutex);
229 for (elem = dcd_hba_list; elem != NULL;
230 elem = elem->inst_next) {
231 if (elem->inst_dip == dip)
232 break;
235 if (elem == NULL) {
236 cmn_err(CE_NOTE, "dcd_hba_attach: Unknown HBA instance\n");
237 mutex_exit(&dcd_hba_mutex);
240 if (elem == dcd_hba_list) {
241 dcd_hba_list = elem->inst_next;
242 dcd_hba_list->inst_prev = NULL;
243 } else if (elem == dcd_hba_list_tail) {
244 dcd_hba_list_tail = elem->inst_prev;
245 dcd_hba_list_tail->inst_next = NULL;
246 } else {
247 elem->inst_prev->inst_next = elem->inst_next;
248 elem->inst_next->inst_prev = elem->inst_prev;
250 mutex_exit(&dcd_hba_mutex);
252 kmem_free(elem, sizeof (struct dcd_hba_inst));
254 return (DDI_SUCCESS);
257 void
258 dcd_hba_fini()
263 /* ARGSUSED */
264 dcd_hba_tran_t *
265 dcd_hba_tran_alloc(
266 dev_info_t *dip,
267 int flags)
270 return (kmem_zalloc(sizeof (dcd_hba_tran_t),
271 (flags & DCD_HBA_CANSLEEP) ? KM_SLEEP: KM_NOSLEEP));
275 void
276 dcd_hba_tran_free(dcd_hba_tran_t *hba_tran)
279 kmem_free(hba_tran, sizeof (dcd_hba_tran_t));
284 * XXX: Do we really need the following routines.
288 * private wrapper for dcd_pkt's allocated via scsi_hba_pkt_alloc
291 struct dcd_pkt_wrapper {
292 struct dcd_pkt dcd_pkt;
293 int pkt_wrapper_len;
296 _NOTE(SCHEME_PROTECTS_DATA("unique per thread", dcd_pkt_wrapper))
299 * Round up all allocations so that we can gurentee
300 * long-long alignment. This is the same alignment
301 * provided by kmem_alloc().
304 #define ROUNDUP(x) (((x) + 0x07) & ~0x07)
307 * Called by an HBA to allocate a dcd_pkt
310 /* ARGSUSED */
311 struct dcd_pkt *
312 dcd_hba_pkt_alloc(
313 struct dcd_address *ap,
314 int cmdlen,
315 int statuslen,
316 int tgtlen,
317 int hbalen,
318 int (*callback)(caddr_t arg),
319 caddr_t arg)
322 struct dcd_pkt *pkt;
323 struct dcd_pkt_wrapper *hba_pkt;
324 caddr_t p;
325 int pktlen;
329 * Sanity check
331 if (callback != SLEEP_FUNC && callback != NULL_FUNC) {
332 cmn_err(CE_PANIC, " dcd_hba_pkt_alloc: callback must be"
333 " either SLEEP or NULL\n");
338 * Round up so everything gets allocated on long-word boundaries.
341 cmdlen = ROUNDUP(cmdlen);
342 tgtlen = ROUNDUP(tgtlen);
343 hbalen = ROUNDUP(hbalen);
344 statuslen = ROUNDUP(statuslen);
345 pktlen = sizeof (struct dcd_pkt_wrapper) +
346 cmdlen + tgtlen +hbalen + statuslen;
348 hba_pkt = kmem_zalloc(pktlen,
349 (callback = SLEEP_FUNC) ? KM_SLEEP: KM_NOSLEEP);
351 if (hba_pkt == NULL) {
352 ASSERT(callback == NULL_FUNC);
353 return (NULL);
357 * Set up or private info on this pkt
359 hba_pkt->pkt_wrapper_len = pktlen;
360 pkt = &hba_pkt->dcd_pkt;
361 p = (caddr_t)(hba_pkt + 1);
364 * set up pointers to private data areas, cdb and status.
366 if (hbalen > 0) {
367 pkt->pkt_ha_private = (ataopaque_t)p;
368 p += hbalen;
371 if (tgtlen > 0) {
372 pkt->pkt_private = (ataopaque_t)p;
373 p += tgtlen;
376 if (statuslen > 0) {
377 pkt->pkt_scbp = (uchar_t *)p;
378 p += statuslen;
381 if (cmdlen > 0) {
382 pkt->pkt_cdbp = (void *)p;
386 * Initialize the pkt's dcd_address
388 pkt->pkt_address = *ap;
389 #ifdef DEBUG1
390 printf("da_target %x, da_lun %x, a_hba_tran %x\n",
391 pkt->pkt_address.da_target, pkt->pkt_address.da_lun,
392 pkt->pkt_address.a_hba_tran);
393 printf("From address : da_target %x, da_lun %x, a_hba_tran %x\n",
394 ap->da_target, ap->da_lun, ap->a_hba_tran);
395 printf("Pkt %x\n", pkt);
397 #endif
398 return (pkt);
402 /* ARGSUSED */
403 void
404 dcd_hba_pkt_free(
405 struct dcd_address *ap,
406 struct dcd_pkt *pkt)
409 kmem_free((struct dcd_pkt_wrapper *)pkt,
410 ((struct dcd_pkt_wrapper *)pkt)->pkt_wrapper_len);
415 * Called by an HBA to map strings to capability indices
419 dcd_hba_lookup_capstr(char *capstr)
423 * Capability strings, masking the '-' vs '_'.
425 static struct cap_strings {
426 char *cap_string;
427 int cap_index;
428 } cap_string[] = {
429 { "dma-max", DCD_CAP_DMA_MAX },
430 { "dma_max", DCD_CAP_DMA_MAX },
431 { "ultraata", DCD_CAP_ULTRA_ATA },
432 { "busmaster", DCD_CAP_BUS_MASTER },
433 { "overlap", DCD_CAP_OVERLAP },
434 { "parity", DCD_CAP_PARITY },
435 { "sector-size", DCD_CAP_SECTOR_SIZE },
436 { "total-sectors", DCD_CAP_TOTAL_SECTORS },
437 { "geometry", DCD_CAP_GEOMETRY },
438 { "block-mode", DCD_CAP_BLOCKMODE },
439 { "block-factor", DCD_CAP_BLOCKFACTOR },
440 { "dma-support", DCD_CAP_DMA_SUPPORT },
441 { "pio-support", DCD_CAP_PIO_SUPPORT },
442 { "lba-addressing", DCD_CAP_LBA_ADDRESSING },
443 { NULL, 0 }
445 struct cap_strings *cp;
447 for (cp = cap_string; cp->cap_string != NULL; cp++) {
448 if (strcmp(cp->cap_string, capstr) == 0) {
449 return (cp->cap_index);
453 return (-1);