1 /* 2 * CDDL HEADER START 3 * 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. 7 * 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. 12 * 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] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 /* 26 * SD card host support. This is the API that host drivers access. 27 */ 28 29 #include <sys/types.h> 30 #include <sys/conf.h> 31 #include <sys/cmn_err.h> 32 #include <sys/varargs.h> 33 #include <sys/ddi.h> 34 #include <sys/sunddi.h> 35 #include <sys/sdcard/sda.h> 36 #include <sys/sdcard/sda_impl.h> 37 38 /* 39 * Implementation. 40 */ 41 42 void 43 sda_host_init_ops(struct dev_ops *devops) 44 { 45 bd_mod_init(devops); 46 } 47 48 void 49 sda_host_fini_ops(struct dev_ops *devops) 50 { 51 bd_mod_fini(devops); 52 } 53 54 sda_host_t * 55 sda_host_alloc(dev_info_t *dip, int nslot, sda_ops_t *ops, ddi_dma_attr_t *dma) 56 { 57 sda_host_t *h; 58 59 if (ops->so_version != SDA_OPS_VERSION) { 60 return (NULL); 61 } 62 63 h = kmem_zalloc(sizeof (*h), KM_SLEEP); 64 h->h_nslot = nslot; 65 h->h_slots = kmem_zalloc(sizeof (sda_slot_t) * nslot, KM_SLEEP); 66 h->h_dma = dma; 67 h->h_dip = dip; 68 69 /* initialize each slot */ 70 for (int i = 0; i < nslot; i++) { 71 sda_slot_t *slot = &h->h_slots[i]; 72 73 slot->s_hostp = h; 74 slot->s_slot_num = i; 75 slot->s_ops = *ops; 76 77 sda_slot_init(slot); 78 } 79 80 return (h); 81 } 82 83 void 84 sda_host_free(sda_host_t *h) 85 { 86 for (int i = 0; i < h->h_nslot; i++) { 87 sda_slot_fini(&h->h_slots[i]); 88 } 89 90 kmem_free(h->h_slots, sizeof (sda_slot_t) * h->h_nslot); 91 kmem_free(h, sizeof (*h)); 92 } 93 94 void 95 sda_host_set_private(sda_host_t *h, int num, void *private) 96 { 97 h->h_slots[num].s_prv = private; 98 } 99 100 int 101 sda_host_attach(sda_host_t *h) 102 { 103 /* 104 * Attach slots. 105 */ 106 for (int i = 0; i < h->h_nslot; i++) { 107 108 sda_slot_attach(&h->h_slots[i]); 109 110 /* 111 * Initiate card detection. 112 */ 113 sda_host_detect(h, i); 114 } 115 116 return (DDI_SUCCESS); 117 } 118 119 void 120 sda_host_detach(sda_host_t *h) 121 { 122 /* 123 * Detach slots. 124 */ 125 for (int i = 0; i < h->h_nslot; i++) { 126 sda_slot_detach(&h->h_slots[i]); 127 } 128 } 129 130 void 131 sda_host_suspend(sda_host_t *h) 132 { 133 for (int i = 0; i < h->h_nslot; i++) { 134 sda_slot_suspend(&h->h_slots[i]); 135 } 136 } 137 138 void 139 sda_host_resume(sda_host_t *h) 140 { 141 for (int i = 0; i < h->h_nslot; i++) { 142 sda_slot_resume(&h->h_slots[i]); 143 } 144 } 145 146 void 147 sda_host_transfer(sda_host_t *h, int num, sda_err_t errno) 148 { 149 sda_slot_transfer(&h->h_slots[num], errno); 150 } 151 152 void 153 sda_host_detect(sda_host_t *h, int num) 154 { 155 sda_slot_detect(&h->h_slots[num]); 156 } 157 158 void 159 sda_host_fault(sda_host_t *h, int num, sda_fault_t fail) 160 { 161 sda_slot_fault(&h->h_slots[num], fail); 162 } 163 164 void 165 sda_host_log(sda_host_t *h, int snum, const char *fmt, ...) 166 { 167 va_list ap; 168 169 va_start(ap, fmt); 170 if (h != NULL) { 171 sda_slot_log(&h->h_slots[snum], fmt, ap); 172 } else { 173 sda_slot_log(NULL, fmt, ap); 174 } 175 va_end(ap); 176 } 177