1/* 2 * Copyright (c) 2006-2012 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24#include <sys/errno.h> 25#include <sys/proc.h> 26#include <IOKit/storage/IOBDMediaBSDClient.h> 27 28#define super IOMediaBSDClient 29OSDefineMetaClassAndStructors(IOBDMediaBSDClient, IOMediaBSDClient) 30 31typedef struct 32{ 33 uint8_t format; 34 35 uint8_t reserved0008[3]; 36 37 uint32_t address; 38 uint8_t grantID; 39 uint8_t layer; 40 41 uint8_t reserved0080[4]; 42 43 uint16_t bufferLength; 44 user32_addr_t buffer; 45} dk_bd_read_structure_32_t; 46 47typedef struct 48{ 49 uint8_t format; 50 51 uint8_t reserved0008[3]; 52 53 uint32_t address; 54 uint8_t grantID; 55 uint8_t layer; 56 57 uint8_t reserved0080[4]; 58 59 uint16_t bufferLength; 60 user64_addr_t buffer; 61} dk_bd_read_structure_64_t; 62 63typedef struct 64{ 65 uint8_t format; 66 uint8_t keyClass; 67 68 uint8_t reserved0016[2]; 69 70 uint32_t address; 71 uint8_t grantID; 72 73 uint8_t reserved0072[5]; 74 75 uint16_t bufferLength; 76 user32_addr_t buffer; 77} dk_bd_report_key_32_t; 78 79typedef struct 80{ 81 uint8_t format; 82 uint8_t keyClass; 83 84 uint8_t reserved0016[2]; 85 86 uint32_t address; 87 uint8_t grantID; 88 89 uint8_t reserved0072[5]; 90 91 uint16_t bufferLength; 92 user64_addr_t buffer; 93} dk_bd_report_key_64_t; 94 95typedef struct 96{ 97 uint8_t format; 98 uint8_t keyClass; 99 100 uint8_t reserved0016[6]; 101 102 uint8_t grantID; 103 104 uint8_t reserved0072[5]; 105 106 uint16_t bufferLength; 107 user32_addr_t buffer; 108} dk_bd_send_key_32_t; 109 110typedef struct 111{ 112 uint8_t format; 113 uint8_t keyClass; 114 115 uint8_t reserved0016[6]; 116 117 uint8_t grantID; 118 119 uint8_t reserved0072[5]; 120 121 uint16_t bufferLength; 122 user64_addr_t buffer; 123} dk_bd_send_key_64_t; 124 125typedef struct 126{ 127 uint8_t reserved0000[14]; 128 129 uint16_t bufferLength; 130 user32_addr_t buffer; 131} dk_bd_read_disc_info_32_t; 132 133typedef struct 134{ 135 uint8_t reserved0000[14]; 136 137 uint16_t bufferLength; 138 user64_addr_t buffer; 139} dk_bd_read_disc_info_64_t; 140 141typedef struct 142{ 143 uint8_t reserved0000[4]; 144 145 uint32_t address; 146 uint8_t addressType; 147 148 uint8_t reserved0072[5]; 149 150 uint16_t bufferLength; 151 user32_addr_t buffer; 152} dk_bd_read_track_info_32_t; 153 154typedef struct 155{ 156 uint8_t reserved0000[4]; 157 158 uint32_t address; 159 uint8_t addressType; 160 161 uint8_t reserved0072[5]; 162 163 uint16_t bufferLength; 164 user64_addr_t buffer; 165} dk_bd_read_track_info_64_t; 166 167#define DKIOCBDREADSTRUCTURE32 _IOW('d', 160, dk_bd_read_structure_32_t) 168#define DKIOCBDREADSTRUCTURE64 _IOW('d', 160, dk_bd_read_structure_64_t) 169#define DKIOCBDREPORTKEY32 _IOW('d', 161, dk_bd_report_key_32_t) 170#define DKIOCBDREPORTKEY64 _IOW('d', 161, dk_bd_report_key_64_t) 171#define DKIOCBDSENDKEY32 _IOW('d', 162, dk_bd_send_key_32_t) 172#define DKIOCBDSENDKEY64 _IOW('d', 162, dk_bd_send_key_64_t) 173 174#define DKIOCBDREADDISCINFO32 _IOWR('d', 164, dk_bd_read_disc_info_32_t) 175#define DKIOCBDREADDISCINFO64 _IOWR('d', 164, dk_bd_read_disc_info_64_t) 176#define DKIOCBDREADTRACKINFO32 _IOWR('d', 165, dk_bd_read_track_info_32_t) 177#define DKIOCBDREADTRACKINFO64 _IOWR('d', 165, dk_bd_read_track_info_64_t) 178 179static bool DKIOC_IS_RESERVED(caddr_t data, uint32_t reserved) 180{ 181 UInt32 index; 182 183 for ( index = 0; index < sizeof(reserved) * 8; index++, reserved >>= 1 ) 184 { 185 if ( (reserved & 1) ) 186 { 187 if ( data[index] ) return true; 188 } 189 } 190 191 return false; 192} 193 194static IOMemoryDescriptor * DKIOC_PREPARE_BUFFER( user_addr_t address, 195 UInt32 length, 196 IODirection direction, 197 proc_t proc ) 198{ 199 IOMemoryDescriptor * buffer = 0; 200 201 if ( address && length ) 202 { 203 buffer = IOMemoryDescriptor::withAddressRange( // (create the buffer) 204 /* address */ address, 205 /* length */ length, 206 /* options */ direction, 207 /* task */ (proc == kernproc) ? kernel_task : current_task() ); 208 } 209 210 if ( buffer ) 211 { 212 if ( buffer->prepare() != kIOReturnSuccess ) // (prepare the buffer) 213 { 214 buffer->release(); 215 buffer = 0; 216 } 217 } 218 219 return buffer; 220} 221 222static void DKIOC_COMPLETE_BUFFER(IOMemoryDescriptor * buffer) 223{ 224 if ( buffer ) 225 { 226 buffer->complete(); // (complete the buffer) 227 buffer->release(); // (release the buffer) 228 } 229} 230 231IOBDMedia * IOBDMediaBSDClient::getProvider() const 232{ 233 // 234 // Obtain this object's provider. We override the superclass's method 235 // to return a more specific subclass of IOService -- IOBDMedia. This 236 // method serves simply as a convenience to subclass developers. 237 // 238 239 return (IOBDMedia *) IOService::getProvider(); 240} 241 242int IOBDMediaBSDClient::ioctl( dev_t dev, 243 u_long cmd, 244 caddr_t data, 245 int flags, 246 proc_t proc ) 247{ 248 // 249 // Process a BD-specific ioctl. 250 // 251 252 IOMemoryDescriptor * buffer = 0; 253 int error = 0; 254 IOReturn status = kIOReturnSuccess; 255 256 switch ( cmd ) 257 { 258 case DKIOCBDREADSTRUCTURE32: // (dk_bd_read_structure_32_t *) 259 { 260 dk_bd_read_structure_32_t * request; 261 262 request = (dk_bd_read_structure_32_t *) data; 263 264 if ( proc_is64bit(proc) ) { error = ENOTTY; break; } 265 266 if ( DKIOC_IS_RESERVED(data, 0x3C0E) ) { error = EINVAL; break; } 267 268 buffer = DKIOC_PREPARE_BUFFER( 269 /* address */ CAST_USER_ADDR_T(request->buffer), 270 /* length */ request->bufferLength, 271 /* direction */ kIODirectionIn, 272 /* proc */ proc ); 273 274 status = getProvider()->readStructure( 275 /* buffer */ buffer, 276 /* format */ request->format, 277 /* address */ request->address, 278 /* layer */ request->layer, 279 /* grantID */ request->grantID ); 280 281 status = (status == kIOReturnUnderrun) ? kIOReturnSuccess : status; 282 283 DKIOC_COMPLETE_BUFFER(buffer); 284 285 } break; 286 287 case DKIOCBDREADSTRUCTURE64: // (dk_bd_read_structure_64_t *) 288 { 289 dk_bd_read_structure_64_t * request; 290 291 request = (dk_bd_read_structure_64_t *) data; 292 293 if ( proc_is64bit(proc) == 0 ) { error = ENOTTY; break; } 294 295 if ( DKIOC_IS_RESERVED(data, 0x3C0E) ) { error = EINVAL; break; } 296 297 buffer = DKIOC_PREPARE_BUFFER( 298 /* address */ request->buffer, 299 /* length */ request->bufferLength, 300 /* direction */ kIODirectionIn, 301 /* proc */ proc ); 302 303 status = getProvider()->readStructure( 304 /* buffer */ buffer, 305 /* format */ request->format, 306 /* address */ request->address, 307 /* layer */ request->layer, 308 /* grantID */ request->grantID ); 309 310 status = (status == kIOReturnUnderrun) ? kIOReturnSuccess : status; 311 312 DKIOC_COMPLETE_BUFFER(buffer); 313 314 } break; 315 316 case DKIOCBDREPORTKEY32: // (dk_bd_report_key_32_t *) 317 { 318 dk_bd_report_key_32_t * request = (dk_bd_report_key_32_t *) data; 319 320 if ( proc_is64bit(proc) ) { error = ENOTTY; break; } 321 322 if ( DKIOC_IS_RESERVED(data, 0x3E0C) ) { error = EINVAL; break; } 323 324 buffer = DKIOC_PREPARE_BUFFER( 325 /* address */ CAST_USER_ADDR_T(request->buffer), 326 /* length */ request->bufferLength, 327 /* direction */ kIODirectionIn, 328 /* proc */ proc ); 329 330 status = getProvider()->reportKey( 331 /* buffer */ buffer, 332 /* keyClass */ request->keyClass, 333 /* address */ request->address, 334 /* grantID */ request->grantID, 335 /* format */ request->format ); 336 337 status = (status == kIOReturnUnderrun) ? kIOReturnSuccess : status; 338 339 DKIOC_COMPLETE_BUFFER(buffer); 340 341 } break; 342 343 case DKIOCBDREPORTKEY64: // (dk_bd_report_key_64_t *) 344 { 345 dk_bd_report_key_64_t * request = (dk_bd_report_key_64_t *) data; 346 347 if ( proc_is64bit(proc) == 0 ) { error = ENOTTY; break; } 348 349 if ( DKIOC_IS_RESERVED(data, 0x3E0C) ) { error = EINVAL; break; } 350 351 buffer = DKIOC_PREPARE_BUFFER( 352 /* address */ request->buffer, 353 /* length */ request->bufferLength, 354 /* direction */ kIODirectionIn, 355 /* proc */ proc ); 356 357 status = getProvider()->reportKey( 358 /* buffer */ buffer, 359 /* keyClass */ request->keyClass, 360 /* address */ request->address, 361 /* grantID */ request->grantID, 362 /* format */ request->format ); 363 364 status = (status == kIOReturnUnderrun) ? kIOReturnSuccess : status; 365 366 DKIOC_COMPLETE_BUFFER(buffer); 367 368 } break; 369 370 case DKIOCBDSENDKEY32: // (dk_bd_send_key_32_t *) 371 { 372 dk_bd_send_key_32_t * request = (dk_bd_send_key_32_t *) data; 373 374 if ( proc_is64bit(proc) ) { error = ENOTTY; break; } 375 376 if ( DKIOC_IS_RESERVED(data, 0x3EFC) ) { error = EINVAL; break; } 377 378 buffer = DKIOC_PREPARE_BUFFER( 379 /* address */ CAST_USER_ADDR_T(request->buffer), 380 /* length */ request->bufferLength, 381 /* direction */ kIODirectionOut, 382 /* proc */ proc ); 383 384 status = getProvider()->sendKey( 385 /* buffer */ buffer, 386 /* keyClass */ request->keyClass, 387 /* grantID */ request->grantID, 388 /* format */ request->format ); 389 390 status = (status == kIOReturnUnderrun) ? kIOReturnSuccess : status; 391 392 DKIOC_COMPLETE_BUFFER(buffer); 393 394 } break; 395 396 case DKIOCBDSENDKEY64: // (dk_bd_send_key_64_t *) 397 { 398 dk_bd_send_key_64_t * request = (dk_bd_send_key_64_t *) data; 399 400 if ( proc_is64bit(proc) == 0 ) { error = ENOTTY; break; } 401 402 if ( DKIOC_IS_RESERVED(data, 0x3EFC) ) { error = EINVAL; break; } 403 404 buffer = DKIOC_PREPARE_BUFFER( 405 /* address */ request->buffer, 406 /* length */ request->bufferLength, 407 /* direction */ kIODirectionOut, 408 /* proc */ proc ); 409 410 status = getProvider()->sendKey( 411 /* buffer */ buffer, 412 /* keyClass */ request->keyClass, 413 /* grantID */ request->grantID, 414 /* format */ request->format ); 415 416 status = (status == kIOReturnUnderrun) ? kIOReturnSuccess : status; 417 418 DKIOC_COMPLETE_BUFFER(buffer); 419 420 } break; 421 422 case DKIOCBDGETSPEED: // (uint16_t *) 423 { 424 status = getProvider()->getSpeed((uint16_t *)data); 425 426 } break; 427 428 case DKIOCBDSETSPEED: // (uint16_t *) 429 { 430 status = getProvider()->setSpeed(*(uint16_t *)data); 431 432 } break; 433 434 case DKIOCBDREADDISCINFO32: // (dk_bd_read_disc_info_32_t *) 435 { 436 dk_bd_read_disc_info_32_t * request; 437 438 request = (dk_bd_read_disc_info_32_t *) data; 439 440 if ( proc_is64bit(proc) ) { error = ENOTTY; break; } 441 442 if ( DKIOC_IS_RESERVED(data, 0x3FFF) ) { error = EINVAL; break; } 443 444 buffer = DKIOC_PREPARE_BUFFER( 445 /* address */ CAST_USER_ADDR_T(request->buffer), 446 /* length */ request->bufferLength, 447 /* direction */ kIODirectionIn, 448 /* proc */ proc ); 449 450 status = getProvider()->readDiscInfo( 451 /* buffer */ buffer, 452 /* type */ 0, 453 /* actualByteCount */ &request->bufferLength ); 454 455 status = (status == kIOReturnUnderrun) ? kIOReturnSuccess : status; 456 457 DKIOC_COMPLETE_BUFFER(buffer); 458 459 } break; 460 461 case DKIOCBDREADDISCINFO64: // (dk_bd_read_disc_info_64_t *) 462 { 463 dk_bd_read_disc_info_64_t * request; 464 465 request = (dk_bd_read_disc_info_64_t *) data; 466 467 if ( proc_is64bit(proc) == 0 ) { error = ENOTTY; break; } 468 469 if ( DKIOC_IS_RESERVED(data, 0x3FFF) ) { error = EINVAL; break; } 470 471 buffer = DKIOC_PREPARE_BUFFER( 472 /* address */ request->buffer, 473 /* length */ request->bufferLength, 474 /* direction */ kIODirectionIn, 475 /* proc */ proc ); 476 477 status = getProvider()->readDiscInfo( 478 /* buffer */ buffer, 479 /* type */ 0, 480 /* actualByteCount */ &request->bufferLength ); 481 482 status = (status == kIOReturnUnderrun) ? kIOReturnSuccess : status; 483 484 DKIOC_COMPLETE_BUFFER(buffer); 485 486 } break; 487 488 case DKIOCBDREADTRACKINFO32: // (dk_bd_read_track_info_32_t *) 489 { 490 dk_bd_read_track_info_32_t * request; 491 492 request = (dk_bd_read_track_info_32_t *) data; 493 494 if ( proc_is64bit(proc) ) { error = ENOTTY; break; } 495 496 if ( DKIOC_IS_RESERVED(data, 0x3E0F) ) { error = EINVAL; break; } 497 498 buffer = DKIOC_PREPARE_BUFFER( 499 /* address */ CAST_USER_ADDR_T(request->buffer), 500 /* length */ request->bufferLength, 501 /* direction */ kIODirectionIn, 502 /* proc */ proc ); 503 504 status = getProvider()->readTrackInfo( 505 /* buffer */ buffer, 506 /* address */ request->address, 507 /* addressType */ request->addressType, 508 /* open */ 0, 509 /* actualByteCount */ &request->bufferLength ); 510 511 status = (status == kIOReturnUnderrun) ? kIOReturnSuccess : status; 512 513 DKIOC_COMPLETE_BUFFER(buffer); 514 515 } break; 516 517 case DKIOCBDREADTRACKINFO64: // (dk_bd_read_track_info_64_t *) 518 { 519 dk_bd_read_track_info_64_t * request; 520 521 request = (dk_bd_read_track_info_64_t *) data; 522 523 if ( proc_is64bit(proc) == 0 ) { error = ENOTTY; break; } 524 525 if ( DKIOC_IS_RESERVED(data, 0x3E0F) ) { error = EINVAL; break; } 526 527 buffer = DKIOC_PREPARE_BUFFER( 528 /* address */ request->buffer, 529 /* length */ request->bufferLength, 530 /* direction */ kIODirectionIn, 531 /* proc */ proc ); 532 533 status = getProvider()->readTrackInfo( 534 /* buffer */ buffer, 535 /* address */ request->address, 536 /* addressType */ request->addressType, 537 /* open */ 0, 538 /* actualByteCount */ &request->bufferLength ); 539 540 status = (status == kIOReturnUnderrun) ? kIOReturnSuccess : status; 541 542 DKIOC_COMPLETE_BUFFER(buffer); 543 544 } break; 545 546 case DKIOCBDSPLITTRACK: // splitTrack(uint32_t *) 547 { 548 status = getProvider()->splitTrack(*(uint32_t *)data); 549 550 } break; 551 552 default: 553 { 554 // 555 // A foreign ioctl was received. Ask our superclass' opinion. 556 // 557 558 error = super::ioctl(dev, cmd, data, flags, proc); 559 560 } break; 561 } 562 563 return error ? error : getProvider()->errnoFromReturn(status); 564} 565 566OSMetaClassDefineReservedUnused(IOBDMediaBSDClient, 0); 567OSMetaClassDefineReservedUnused(IOBDMediaBSDClient, 1); 568OSMetaClassDefineReservedUnused(IOBDMediaBSDClient, 2); 569OSMetaClassDefineReservedUnused(IOBDMediaBSDClient, 3); 570OSMetaClassDefineReservedUnused(IOBDMediaBSDClient, 4); 571OSMetaClassDefineReservedUnused(IOBDMediaBSDClient, 5); 572OSMetaClassDefineReservedUnused(IOBDMediaBSDClient, 6); 573OSMetaClassDefineReservedUnused(IOBDMediaBSDClient, 7); 574