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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * USBA: Solaris USB Architecture support 28 * 29 * ISSUES: 30 */ 31 #define USBA_FRAMEWORK 32 #include <sys/usb/usba.h> 33 #include <sys/usb/usba/hcdi.h> 34 #include <sys/usb/usba/genconsole.h> 35 #include <sys/usb/usba/usba_types.h> 36 #include <sys/usb/usba/usba_impl.h> 37 38 /* 39 * Initialize USB polled support. This routine calls down to the lower 40 * layers to initialize any state information. 41 */ 42 int 43 usb_console_input_init(dev_info_t *dip, 44 usb_pipe_handle_t pipe_handle, 45 uchar_t **state_buf, 46 usb_console_info_t *console_input_info) 47 { 48 int ret; 49 usba_device_t *usba_device; 50 usba_pipe_handle_data_t *ph_data; 51 usb_console_info_impl_t *usb_console_input; 52 53 if (dip == NULL) { 54 55 return (USB_INVALID_ARGS); 56 } 57 58 if (DEVI_IS_DEVICE_REMOVED(dip)) { 59 60 return (USB_FAILURE); 61 } 62 63 usb_console_input = kmem_zalloc( 64 sizeof (struct usb_console_info_impl), KM_SLEEP); 65 66 /* 67 * Save the dip 68 */ 69 usb_console_input->uci_dip = dip; 70 71 /* 72 * Translate the dip into a device. 73 */ 74 usba_device = usba_get_usba_device(dip); 75 76 /* 77 * Get ph_data from pipe handle and hold the data 78 */ 79 if ((ph_data = usba_hold_ph_data(pipe_handle)) == NULL) { 80 kmem_free(usb_console_input, 81 sizeof (struct usb_console_info_impl)); 82 83 return (USB_INVALID_PIPE); 84 } 85 86 /* 87 * Call the lower layer to initialize any state information 88 */ 89 ret = usba_device->usb_hcdi_ops->usba_hcdi_console_input_init( 90 ph_data, state_buf, usb_console_input); 91 92 if (ret != USB_SUCCESS) { 93 kmem_free(usb_console_input, 94 sizeof (struct usb_console_info_impl)); 95 } else { 96 *console_input_info = (usb_console_info_t)usb_console_input; 97 } 98 99 usba_release_ph_data((usba_ph_impl_t *)pipe_handle); 100 101 return (ret); 102 } 103 104 105 /* 106 * Free up any resources that we allocated in the above initialization 107 * routine. 108 */ 109 int 110 usb_console_input_fini(usb_console_info_t console_input_info) 111 { 112 usb_console_info_impl_t *usb_console_input; 113 usba_device_t *usba_device; 114 int ret; 115 116 usb_console_input = (usb_console_info_impl_t *)console_input_info; 117 118 /* 119 * Translate the dip into a device. 120 */ 121 usba_device = usba_get_usba_device(usb_console_input->uci_dip); 122 123 /* 124 * Call the lower layer to free any state information. 125 */ 126 ret = usba_device->usb_hcdi_ops->usba_hcdi_console_input_fini( 127 usb_console_input); 128 129 if (ret == USB_FAILURE) { 130 131 return (ret); 132 } 133 134 /* 135 * We won't be needing this information anymore. 136 */ 137 kmem_free(usb_console_input, sizeof (struct usb_console_info_impl)); 138 139 return (USB_SUCCESS); 140 } 141 142 143 /* 144 * This is the routine that OBP calls to save the USB state information 145 * before using the USB keyboard as an input device. This routine, 146 * and all of the routines that it calls, are responsible for saving 147 * any state information so that it can be restored when OBP mode is 148 * over. At this layer, this code is mainly just a pass through. 149 * 150 * Warning: this code runs in polled mode. 151 */ 152 int 153 usb_console_input_enter(usb_console_info_t console_input_info) 154 { 155 usba_device_t *usba_device; 156 usb_console_info_impl_t *usb_console_input; 157 158 usb_console_input = (usb_console_info_impl_t *)console_input_info; 159 160 /* 161 * Translate the dip into a device. 162 * Do this by directly looking at the dip, do not call 163 * usba_get_usba_device() because this function calls into the DDI. 164 * The ddi then tries to acquire a mutex and the machine hard hangs. 165 */ 166 usba_device = usba_polled_get_usba_device(usb_console_input->uci_dip); 167 168 /* 169 * Call the lower layer to save state information. 170 */ 171 usba_device->usb_hcdi_ops->usba_hcdi_console_input_enter( 172 usb_console_input); 173 174 return (USB_SUCCESS); 175 } 176 177 178 /* 179 * This is the routine that OBP calls when it wants to read a character. 180 * We will call to the lower layers to see if there is any input data 181 * available. At this layer, this code is mainly just a pass through. 182 * 183 * Warning: This code runs in polled mode. 184 */ 185 int 186 usb_console_read(usb_console_info_t console_input_info, uint_t *num_characters) 187 { 188 usba_device_t *usba_device; 189 usb_console_info_impl_t *usb_console_input; 190 191 usb_console_input = (usb_console_info_impl_t *)console_input_info; 192 193 /* 194 * Translate the dip into a device. 195 * Do this by directly looking at the dip, do not call 196 * usba_get_usba_device() because this function calls into the DDI. 197 * The ddi then tries to acquire a mutex and the machine hard hangs. 198 */ 199 usba_device = usba_polled_get_usba_device(usb_console_input->uci_dip); 200 201 /* 202 * Call the lower layer to get a a character. Return the number 203 * of characters read into the buffer. 204 */ 205 return (usba_device->usb_hcdi_ops->usba_hcdi_console_read( 206 usb_console_input, num_characters)); 207 } 208 209 210 /* 211 * This is the routine that OBP calls when it is giving up control of the 212 * USB keyboard. This routine, and the lower layer routines that it calls, 213 * are responsible for restoring the controller state to the state it was 214 * in before OBP took control. At this layer, this code is mainly just a 215 * pass through. 216 * 217 * Warning: This code runs in polled mode. 218 */ 219 int 220 usb_console_input_exit(usb_console_info_t console_input_info) 221 { 222 usba_device_t *usba_device; 223 usb_console_info_impl_t *usb_console_input; 224 225 usb_console_input = (usb_console_info_impl_t *)console_input_info; 226 227 /* 228 * Translate the dip into a device. 229 * Do this by directly looking at the dip, do not call 230 * usba_get_usba_device() because this function calls into the DDI. 231 * The ddi then tries to acquire a mutex and the machine hard hangs. 232 */ 233 usba_device = usba_polled_get_usba_device(usb_console_input->uci_dip); 234 235 /* 236 * Restore the state information. 237 */ 238 usba_device->usb_hcdi_ops->usba_hcdi_console_input_exit( 239 usb_console_input); 240 241 return (USB_SUCCESS); 242 } 243 244 /* 245 * Initialize USB OBP support. This routine calls down to the lower 246 * layers to initialize any state information. 247 */ 248 int 249 usb_console_output_init( 250 dev_info_t *dip, 251 usb_pipe_handle_t pipe_handle, 252 usb_console_info_t *console_output_info) 253 { 254 usba_device_t *usb_device; 255 usb_console_info_impl_t *usb_console_output; 256 int ret; 257 258 /* Translate the dip into a device and check hcdi ops */ 259 usb_device = usba_get_usba_device(dip); 260 if (usb_device->usb_hcdi_ops->usba_hcdi_ops_version < 261 HCDI_OPS_VERSION_1 || 262 usb_device->usb_hcdi_ops->usba_hcdi_console_output_init == NULL) 263 264 return (USB_FAILURE); 265 266 usb_console_output = kmem_zalloc(sizeof (struct usb_console_info_impl), 267 KM_SLEEP); 268 usb_console_output->uci_dip = dip; 269 270 /* 271 * Call the lower layer to initialize any state information 272 */ 273 ret = usb_device->usb_hcdi_ops->usba_hcdi_console_output_init( 274 usba_get_ph_data(pipe_handle), usb_console_output); 275 276 if (ret == USB_FAILURE) { 277 kmem_free(usb_console_output, 278 sizeof (struct usb_console_info_impl)); 279 280 return (ret); 281 } 282 283 *console_output_info = (usb_console_info_t)usb_console_output; 284 285 return (USB_SUCCESS); 286 } 287 288 /* 289 * Free up any resources that we allocated in the above initialization 290 * routine. 291 */ 292 int 293 usb_console_output_fini(usb_console_info_t console_output_info) 294 { 295 usb_console_info_impl_t *usb_console_output; 296 usba_device_t *usb_device; 297 int ret; 298 299 usb_console_output = (usb_console_info_impl_t *)console_output_info; 300 301 /* 302 * Translate the dip into a device. 303 */ 304 usb_device = usba_polled_get_usba_device(usb_console_output->uci_dip); 305 306 /* 307 * Call the lower layer to free any state information. 308 */ 309 ret = usb_device->usb_hcdi_ops->usba_hcdi_console_output_fini( 310 usb_console_output); 311 312 if (ret == USB_FAILURE) { 313 314 return (ret); 315 } 316 317 /* 318 * We won't be needing this information anymore. 319 */ 320 kmem_free(usb_console_output, sizeof (struct usb_console_info_impl)); 321 322 return (USB_SUCCESS); 323 } 324 325 /* 326 * This is the routine that OBP calls to save the USB state information 327 * before using the USB device as an output device. This routine, 328 * and all of the routines that it calls, are responsible for saving 329 * any state information so that it can be restored when OBP mode is 330 * over. At this layer, this code is mainly just a pass through. 331 */ 332 int 333 usb_console_output_enter(usb_console_info_t console_output_info) 334 { 335 usba_device_t *usb_device; 336 usb_console_info_impl_t *usb_console_output; 337 338 usb_console_output = (usb_console_info_impl_t *)console_output_info; 339 340 /* 341 * Translate the dip into a device. 342 */ 343 usb_device = usba_polled_get_usba_device(usb_console_output->uci_dip); 344 345 /* 346 * Call the lower layer to save state information. 347 */ 348 usb_device->usb_hcdi_ops->usba_hcdi_console_output_enter( 349 usb_console_output); 350 351 return (USB_SUCCESS); 352 } 353 354 /* 355 * This is the routine that OBP calls when it wants to write a character. 356 * We will call to the lower layers to write any data 357 * At this layer, this code is mainly just a pass through. 358 */ 359 int 360 usb_console_write(usb_console_info_t console_output_info, 361 uchar_t *buf, uint_t num_characters, uint_t *num_characters_written) 362 { 363 usba_device_t *usb_device; 364 usb_console_info_impl_t *usb_console_output; 365 366 usb_console_output = (usb_console_info_impl_t *)console_output_info; 367 368 /* 369 * Translate the dip into a device. 370 */ 371 usb_device = usba_polled_get_usba_device(usb_console_output->uci_dip); 372 373 /* 374 * Call the lower layer to get a a character. Return the number 375 * of characters read into the buffer. 376 */ 377 return (usb_device->usb_hcdi_ops->usba_hcdi_console_write( 378 usb_console_output, buf, num_characters, 379 num_characters_written)); 380 } 381 382 /* 383 * This is the routine that OBP calls when it is giving up control of the 384 * USB output device. This routine, and the lower layer routines that it 385 * calls, are responsible for restoring the controller state to the state 386 * it was in before OBP took control. At this layer, this code is mainly 387 * just a pass through. 388 */ 389 int 390 usb_console_output_exit(usb_console_info_t console_output_info) 391 { 392 usba_device_t *usb_device; 393 usb_console_info_impl_t *usb_console_output; 394 395 usb_console_output = (usb_console_info_impl_t *)console_output_info; 396 397 /* 398 * Translate the dip into a device. 399 */ 400 usb_device = usba_polled_get_usba_device(usb_console_output->uci_dip); 401 402 /* 403 * Restore the state information. 404 */ 405 usb_device->usb_hcdi_ops->usba_hcdi_console_output_exit( 406 usb_console_output); 407 408 return (USB_SUCCESS); 409 } 410