搜尋此網誌

2012年4月17日 星期二

How to design a Mac drivers? --(2)


Create a new project in Xcode

Add project from “IOKit Driver” template

Modify the plist
This file likes the Inf of window drivers. Then add HBA information.


To add the libraries
 
Loading kernel extension at boot time
If the driver would like to support booting, that need add into “Local-Root”

Implement [driver entry]
No support virtual memory, only physical memory. So driver can use it to prepare task directly.
•      Inherit from class IOSCSIParallelInterfaceController
•      InitializeController / StartController
–     driver_init / driver_probe_one
•      TerminateController / StopController [unload driver]
–     driver_exit / driver_detach_one
•      ReportInitiatorIdentifier
–     (struct Scsi_Host *)->unique_id
•      ReportHighestSupportedDeviceID [Max Device ID]
–     (struct Scsi_Host *)->max_id - 1
•      ReportMaximumTaskCount
–     (struct Scsi_Host *)-> can_queue
•      ReportHBAHighestLogicalUnitNumber [Max LUN]
–     (struct Scsi_Host *)->max_lun - 1
•      ReportHBASpecificTaskDataSize [Resource size per Request]
•      ReportHBASpecificDeviceDataSize [Resource size per Device]
•      DoesHBAPerformDeviceManagement [Scan every device behind HBA, driver  has to add/remove single device by itself]
•      DoesHBASupportSCSIParallelFeature
•      ProcessParallelTask [driver_queue_command]
•      FilterInterruptRequest / HandleInterruptRequest [driver_isr_handler]
•      InitializeTargetForID =>[No Supported]

Implement in second step
•      AbortTaskRequest
•      AbortTaskSetRequest
•      ClearACARequest
•      ClearTaskSetRequest
•      LogicalUnitResetRequest
•      TargetResetRequest
•      HandleTimeout (Optional)
•      ReportHBAConstraints (Optional) => [to support 64bits need handle this function]
•      InitializeDMASpecification (Optional)

OS X kernel / Linux functions table
Linux
OS X
printk
IOLog
pci_iomap
mapDeviceMemoryWithIndex
pci_iounmap
(IOMemoryMap *)->release
pci_set_master
setBusMasterEnable
pci_set_dma_mask
initWithSpecification
kzalloc
IOMalloc
kfree
IOFree
INIT_LIST_HEAD
queue_init
list_add_tail
queue_enter
list_for_each_entry
queue_iterate
list_del
queue_remove
list_empty
queue_empty
list_first_entry
queue_first
scsi_sg_count
(IODMACommand *)->fNumSegments
scsi_sglist
(IODMACommand *)->gen64IOVMSegments
scsi_bufflen
GetRequestedDataTransferCount
sg_dma_address
GetDMACommand
cpu_to_le32
OSSwapHostToLittleConstInt32
pci_alloc_consistent
IOMallocContiguous
pci_free_consistent
IOFreeContiguous
pci_map_sg
(IODMACommand *)->prepare
pci_unmap_sg
(IODMACommand *)->complete
ioread32
ioRead32
iowrite32
ioWrite32
udelay
IODelay
msleep
IOSleep
spin_lock_irqsave
IOLockLock
spin_unlock_irqrestore
IOLockUnlock
do_gettimeofday
clock_get_calendar_microtime
scsi_add_device
CreateTargetForID
scsi_remove_device
DestroyTargetForID
scsi_device_lookup
GetTargetForID
pci_write_config_dword
configWrite32
virt_to_phys
(IOMemoryDescriptor *)->getPhysicalAddress
(struct scsi_cmnd *)->scsi_done
CompleteParallelTask
SAM_STAT_GOOD
kSCSITaskStatus_GOOD
SAM_STAT_CHECK_CONDITION
kSCSITaskStatus_CHECK_CONDITION
INQUIRY
kSCSICmd_INQUIRY


Support device PNP
•      IOSCSIParallelInterfaceController::DoesHBAPerformDeviceManagement()
–     [return false]: made the handle of OS discover if that has any attached devices been attaching.
–     [return true]: driver needs to have a mechanism for detecting, adding and removing devices.
•      Create a thread in IOSCSIParallelInterfaceController::StartController() to scan device from id 0 to (max target id -1 ) with INQUIRY command.
•      Create a thread when get a bus change doorbell and scan all devices again.
•      If INQUIRY command status is GOOD: use CreateTargetForID() to add device.
•      ELSE use DestroyTargetForID() to remove device.

Register power management for status change
•      Driver MUST initialize power management; otherwise system can’t go sleep successful.
–        PMinit();
–        joinPMtree();
–        registerPowerDriver();
•      Implement IOSCSIParallelInterfaceController::setPowerState()
–     driver will receive a notification when system get an event change for “SLEEP” or “WAKEUP”.
–     Implement IOSCSIParallelInterfaceController::systemWillShutdown ()
–     driver will receive a notification when system get “RESTART” and “POWEROFF”.

Support 32bit/64bit kernel
•      Build settings:
–     Architectures: Standard (32/64-bit Intel)
–     Build Active Architecture Only: No
•      Starting up with the 32-bit or 64-bit kernel
–     Method 1: Startup key combination
•      64-bit: holding the 6 and 4 keys during startup.
•      32-bit: holding the 3 and 2 keys during startup.
–     Method 2: On-disk setting (persistent)
•      sudo systemsetup -setkernelbootarchitecture x86_64
•      sudo systemsetup -setkernelbootarchitecture i386

Virtual Device for application

How to do verification
•      Load/Unload command:
–     sudo cp –r mvumi.kext /tmp/mvumi.kext
–     sudo kextload /tmp/mvumi.kext
–     sudo kextunload /tmp/mvumi.kext
•      Test tools
–     rwfile
–     AJA System Test
–     Blackmagic Disk Speed Test

Boot OS X from third-party HBA
•      Mac OS X don’t provide a official method to insert driver during OS installation.
•      But we can “CLONE” a existing OS X to HBA and boot from it.
–     1. Install driver to /System/Library/Extensions/
–     2. Restart OS and holding “option” key during startup
–     3. Select “Recovery HD” to boot
–     4. Open a terminal and load driver from:
        /Volumes/Macintosh HD/System/Library/Extensions
–     5. Open “Disk utility”, use “Restore” to clone original disk to HBA.

Build driver package
•      Change the “Build Configuration” to “Release” before release the driver package.

•      Create a pkg file with “PackageMaker”
–     If you didn’t find it in disk, you can download “Auxiliary tools for xcode” from Apple Developer Site.
•      Create a dmg file with command
            hdiutil create test.dmg -srcfolder test.pkg
•      Enjoy!!


沒有留言:

張貼留言