12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999 |
- /*++
- Copyright (c) 2014 Minoca Corp.
- This file is licensed under the terms of the GNU General Public License
- version 3. Alternative licensing terms are available. Contact
- info@minocacorp.com for details. See the LICENSE file at the root of this
- project for complete licensing information.
- Module Name:
- sdomap4.c
- Abstract:
- This module implements the SD/MMC driver for TI OMAP4 SoCs.
- Author:
- Evan Green 16-Mar-2014
- Environment:
- Kernel
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include <minoca/kernel/driver.h>
- #include "sdomap4.h"
- //
- // --------------------------------------------------------------------- Macros
- //
- //
- // These macros read and write SD controller registers.
- //
- #define SD_OMAP4_READ_REGISTER(_Device, _Register) \
- HlReadRegister32((_Device)->ControllerBase + (_Register))
- #define SD_OMAP4_WRITE_REGISTER(_Device, _Register, _Value) \
- HlWriteRegister32((_Device)->ControllerBase + (_Register), (_Value))
- //
- // ---------------------------------------------------------------- Definitions
- //
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- KSTATUS
- SdOmap4AddDevice (
- PVOID Driver,
- PCSTR DeviceId,
- PCSTR ClassId,
- PCSTR CompatibleIds,
- PVOID DeviceToken
- );
- VOID
- SdOmap4DispatchStateChange (
- PIRP Irp,
- PVOID DeviceContext,
- PVOID IrpContext
- );
- VOID
- SdOmap4DispatchOpen (
- PIRP Irp,
- PVOID DeviceContext,
- PVOID IrpContext
- );
- VOID
- SdOmap4DispatchClose (
- PIRP Irp,
- PVOID DeviceContext,
- PVOID IrpContext
- );
- VOID
- SdOmap4DispatchIo (
- PIRP Irp,
- PVOID DeviceContext,
- PVOID IrpContext
- );
- VOID
- SdOmap4DispatchSystemControl (
- PIRP Irp,
- PVOID DeviceContext,
- PVOID IrpContext
- );
- VOID
- SdOmap4ParentDispatchStateChange (
- PIRP Irp,
- PSD_OMAP4_CONTEXT Context,
- PVOID IrpContext
- );
- VOID
- SdOmap4ChildDispatchStateChange (
- PIRP Irp,
- PSD_OMAP4_CHILD Child,
- PVOID IrpContext
- );
- KSTATUS
- SdOmap4ParentProcessResourceRequirements (
- PIRP Irp,
- PSD_OMAP4_CONTEXT Device
- );
- KSTATUS
- SdOmap4ParentStartDevice (
- PIRP Irp,
- PSD_OMAP4_CONTEXT Device
- );
- KSTATUS
- SdOmap4ParentQueryChildren (
- PIRP Irp,
- PSD_OMAP4_CONTEXT Device
- );
- KSTATUS
- SdOmap4ResetController (
- PSD_OMAP4_CONTEXT Device
- );
- INTERRUPT_STATUS
- SdOmap4InterruptService (
- PVOID Context
- );
- INTERRUPT_STATUS
- SdOmap4InterruptServiceDispatch (
- PVOID Context
- );
- VOID
- SdOmap4SdDmaCompletion (
- PSD_CONTROLLER Controller,
- PVOID Context,
- UINTN BytesTransferred,
- KSTATUS Status
- );
- PSD_OMAP4_CHILD
- SdOmap4pCreateChild (
- PSD_OMAP4_CONTEXT Device
- );
- VOID
- SdOmap4pDestroyChild (
- PSD_OMAP4_CHILD Child
- );
- VOID
- SdOmap4pChildAddReference (
- PSD_OMAP4_CHILD Child
- );
- VOID
- SdOmap4pChildReleaseReference (
- PSD_OMAP4_CHILD Child
- );
- KSTATUS
- SdOmap4ChildBlockIoReset (
- PVOID DiskToken
- );
- KSTATUS
- SdOmap4ChildBlockIoRead (
- PVOID DiskToken,
- PIO_BUFFER IoBuffer,
- ULONGLONG BlockAddress,
- UINTN BlockCount,
- PUINTN BlocksCompleted
- );
- KSTATUS
- SdOmap4ChildBlockIoWrite (
- PVOID DiskToken,
- PIO_BUFFER IoBuffer,
- ULONGLONG BlockAddress,
- UINTN BlockCount,
- PUINTN BlocksCompleted
- );
- KSTATUS
- SdOmap4PerformIoPolled (
- PIRP_READ_WRITE IrpReadWrite,
- PSD_OMAP4_CHILD Child,
- BOOL Write,
- BOOL LockRequired
- );
- KSTATUS
- SdOmap4GetSetBusWidth (
- PSD_CONTROLLER Controller,
- PVOID Context,
- BOOL Set
- );
- KSTATUS
- SdOmap4InitializeDma (
- PSD_OMAP4_CONTEXT Device
- );
- VOID
- SdOmap4DmaInterfaceCallback (
- PVOID Context,
- PDEVICE Device,
- PVOID InterfaceBuffer,
- ULONG InterfaceBufferSize,
- BOOL Arrival
- );
- VOID
- SdOmap4PerformDmaIo (
- PSD_OMAP4_CHILD Child,
- PIRP Irp
- );
- KSTATUS
- SdOmap4SetupEdma (
- PSD_OMAP4_CHILD Child,
- PULONGLONG Size
- );
- VOID
- SdOmap4EdmaCompletion (
- PDMA_TRANSFER Transfer
- );
- VOID
- SdOmap4DmaCompletion (
- PSD_CONTROLLER Controller,
- PVOID Context,
- UINTN BytesTransferred,
- KSTATUS Status
- );
- //
- // -------------------------------------------------------------------- Globals
- //
- PDRIVER SdOmap4Driver = NULL;
- UUID SdOmap4DiskInterfaceUuid = UUID_DISK_INTERFACE;
- UUID SdOmap4DmaUuid = UUID_DMA_INTERFACE;
- UUID SdOmap4Edma3Uuid = UUID_EDMA_CONTROLLER;
- DISK_INTERFACE SdOmap4DiskInterfaceTemplate = {
- DISK_INTERFACE_VERSION,
- NULL,
- 0,
- 0,
- NULL,
- SdOmap4ChildBlockIoReset,
- SdOmap4ChildBlockIoRead,
- SdOmap4ChildBlockIoWrite
- };
- //
- // ------------------------------------------------------------------ Functions
- //
- KSTATUS
- DriverEntry (
- PDRIVER Driver
- )
- /*++
- Routine Description:
- This routine is the entry point for the SD/MMC driver. It registers its
- other dispatch functions, and performs driver-wide initialization.
- Arguments:
- Driver - Supplies a pointer to the driver object.
- Return Value:
- STATUS_SUCCESS on success.
- Failure code on error.
- --*/
- {
- DRIVER_FUNCTION_TABLE FunctionTable;
- KSTATUS Status;
- SdOmap4Driver = Driver;
- RtlZeroMemory(&FunctionTable, sizeof(DRIVER_FUNCTION_TABLE));
- FunctionTable.Version = DRIVER_FUNCTION_TABLE_VERSION;
- FunctionTable.AddDevice = SdOmap4AddDevice;
- FunctionTable.DispatchStateChange = SdOmap4DispatchStateChange;
- FunctionTable.DispatchOpen = SdOmap4DispatchOpen;
- FunctionTable.DispatchClose = SdOmap4DispatchClose;
- FunctionTable.DispatchIo = SdOmap4DispatchIo;
- FunctionTable.DispatchSystemControl = SdOmap4DispatchSystemControl;
- Status = IoRegisterDriverFunctions(Driver, &FunctionTable);
- return Status;
- }
- KSTATUS
- SdOmap4AddDevice (
- PVOID Driver,
- PCSTR DeviceId,
- PCSTR ClassId,
- PCSTR CompatibleIds,
- PVOID DeviceToken
- )
- /*++
- Routine Description:
- This routine is called when a device is detected for which the SD/MMC driver
- acts as the function driver. The driver will attach itself to the stack.
- Arguments:
- Driver - Supplies a pointer to the driver being called.
- DeviceId - Supplies a pointer to a string with the device ID.
- ClassId - Supplies a pointer to a string containing the device's class ID.
- CompatibleIds - Supplies a pointer to a string containing device IDs
- that would be compatible with this device.
- DeviceToken - Supplies an opaque token that the driver can use to identify
- the device in the system. This token should be used when attaching to
- the stack.
- Return Value:
- STATUS_SUCCESS on success.
- Failure code if the driver was unsuccessful in attaching itself.
- --*/
- {
- PSD_OMAP4_CONTEXT Context;
- KSTATUS Status;
- //
- // Allocate non-paged pool because this device could be the paging device.
- //
- Context = MmAllocateNonPagedPool(sizeof(SD_OMAP4_CONTEXT),
- SD_ALLOCATION_TAG);
- if (Context == NULL) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto AddDeviceEnd;
- }
- RtlZeroMemory(Context, sizeof(SD_OMAP4_CONTEXT));
- Context->Type = SdOmap4Parent;
- Context->InterruptHandle = INVALID_HANDLE;
- Context->Lock = KeCreateQueuedLock();
- if (Context->Lock == NULL) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto AddDeviceEnd;
- }
- if (IoAreDeviceIdsEqual(DeviceId, SD_OMAP4_DEVICE_ID) != 0) {
- Context->Soc = SdTiSocOmap4;
- } else if (IoAreDeviceIdsEqual(DeviceId, SD_AM335_DEVICE_ID) != 0) {
- Context->Soc = SdTiSocAm335;
- } else {
- ASSERT(FALSE);
- Status = STATUS_NO_ELIGIBLE_DEVICES;
- goto AddDeviceEnd;
- }
- Status = IoAttachDriverToDevice(Driver, DeviceToken, Context);
- if (!KSUCCESS(Status)) {
- goto AddDeviceEnd;
- }
- AddDeviceEnd:
- if (!KSUCCESS(Status)) {
- if (Context != NULL) {
- MmFreeNonPagedPool(Context);
- }
- }
- return Status;
- }
- VOID
- SdOmap4DispatchStateChange (
- PIRP Irp,
- PVOID DeviceContext,
- PVOID IrpContext
- )
- /*++
- Routine Description:
- This routine handles State Change IRPs.
- Arguments:
- Irp - Supplies a pointer to the I/O request packet.
- DeviceContext - Supplies the context pointer supplied by the driver when it
- attached itself to the driver stack. Presumably this pointer contains
- driver-specific device context.
- IrpContext - Supplies the context pointer supplied by the driver when
- the IRP was created.
- Return Value:
- None.
- --*/
- {
- PSD_OMAP4_CONTEXT Context;
- ASSERT(Irp->MajorCode == IrpMajorStateChange);
- Context = DeviceContext;
- switch (Context->Type) {
- case SdOmap4Parent:
- SdOmap4ParentDispatchStateChange(Irp, Context, IrpContext);
- break;
- case SdOmap4Child:
- SdOmap4ChildDispatchStateChange(Irp,
- (PSD_OMAP4_CHILD)Context,
- IrpContext);
- break;
- default:
- ASSERT(FALSE);
- break;
- }
- return;
- }
- VOID
- SdOmap4DispatchOpen (
- PIRP Irp,
- PVOID DeviceContext,
- PVOID IrpContext
- )
- /*++
- Routine Description:
- This routine handles Open IRPs.
- Arguments:
- Irp - Supplies a pointer to the I/O request packet.
- DeviceContext - Supplies the context pointer supplied by the driver when it
- attached itself to the driver stack. Presumably this pointer contains
- driver-specific device context.
- IrpContext - Supplies the context pointer supplied by the driver when
- the IRP was created.
- Return Value:
- None.
- --*/
- {
- PSD_OMAP4_CHILD Child;
- Child = DeviceContext;
- //
- // Only the child can be opened or closed.
- //
- if (Child->Type != SdOmap4Child) {
- return;
- }
- SdOmap4pChildAddReference(Child);
- IoCompleteIrp(SdOmap4Driver, Irp, STATUS_SUCCESS);
- return;
- }
- VOID
- SdOmap4DispatchClose (
- PIRP Irp,
- PVOID DeviceContext,
- PVOID IrpContext
- )
- /*++
- Routine Description:
- This routine handles Close IRPs.
- Arguments:
- Irp - Supplies a pointer to the I/O request packet.
- DeviceContext - Supplies the context pointer supplied by the driver when it
- attached itself to the driver stack. Presumably this pointer contains
- driver-specific device context.
- IrpContext - Supplies the context pointer supplied by the driver when
- the IRP was created.
- Return Value:
- None.
- --*/
- {
- PSD_OMAP4_CHILD Child;
- Child = DeviceContext;
- if (Child->Type != SdOmap4Child) {
- return;
- }
- SdOmap4pChildReleaseReference(Child);
- IoCompleteIrp(SdOmap4Driver, Irp, STATUS_SUCCESS);
- return;
- }
- VOID
- SdOmap4DispatchIo (
- PIRP Irp,
- PVOID DeviceContext,
- PVOID IrpContext
- )
- /*++
- Routine Description:
- This routine handles I/O IRPs.
- Arguments:
- Irp - Supplies a pointer to the I/O request packet.
- DeviceContext - Supplies the context pointer supplied by the driver when it
- attached itself to the driver stack. Presumably this pointer contains
- driver-specific device context.
- IrpContext - Supplies the context pointer supplied by the driver when
- the IRP was created.
- Return Value:
- None.
- --*/
- {
- PSD_OMAP4_CHILD Child;
- BOOL CompleteIrp;
- PSD_CONTROLLER Controller;
- ULONG IrpReadWriteFlags;
- KSTATUS IrpStatus;
- KSTATUS Status;
- BOOL Write;
- ASSERT(KeGetRunLevel() == RunLevelLow);
- Child = DeviceContext;
- if (Child->Type != SdOmap4Child) {
- ASSERT(FALSE);
- return;
- }
- CompleteIrp = TRUE;
- Controller = Child->Controller;
- Write = FALSE;
- if (Irp->MinorCode == IrpMinorIoWrite) {
- Write = TRUE;
- }
- //
- // Polled I/O is shared by a few code paths and prepares the IRP for I/O
- // further down the stack. It should also only be hit in the down direction
- // path as it always completes the IRP.
- //
- if ((Child->Flags & SD_OMAP4_CHILD_FLAG_DMA_SUPPORTED) == 0) {
- ASSERT(Irp->Direction == IrpDown);
- Status = SdOmap4PerformIoPolled(&(Irp->U.ReadWrite),
- Child,
- Write,
- TRUE);
- goto DispatchIoEnd;
- }
- //
- // Set the IRP read/write flags for the preparation and completion steps.
- //
- IrpReadWriteFlags = IRP_READ_WRITE_FLAG_DMA;
- if (Write != FALSE) {
- IrpReadWriteFlags |= IRP_READ_WRITE_FLAG_WRITE;
- }
- if (Irp->Direction == IrpDown) {
- Controller->Try = 0;
- }
- //
- // If the IRP is on the way up, then clean up after the DMA as this IRP is
- // still sitting in the channel. An IRP going up is already complete.
- //
- if (Irp->Direction == IrpUp) {
- ASSERT(Irp == Child->Irp);
- Child->Irp = NULL;
- //
- // Try to recover on failure.
- //
- IrpStatus = IoGetIrpStatus(Irp);
- if (!KSUCCESS(IrpStatus)) {
- Status = SdErrorRecovery(Controller);
- if (!KSUCCESS(Status)) {
- IrpStatus = Status;
- IoUpdateIrpStatus(Irp, IrpStatus);
- }
- //
- // Do not make further attempts if the media is gone or enough
- // attempts have been made.
- //
- if (((Controller->Flags &
- SD_CONTROLLER_FLAG_MEDIA_CHANGED) != 0) ||
- ((Controller->Flags &
- SD_CONTROLLER_FLAG_MEDIA_PRESENT) == 0) ||
- (Controller->Try >= SD_MAX_IO_RETRIES)) {
- IrpStatus = STATUS_SUCCESS;
- } else {
- Controller->Try += 1;
- }
- }
- KeReleaseQueuedLock(Child->ControllerLock);
- Status = IoCompleteReadWriteIrp(&(Irp->U.ReadWrite),
- IrpReadWriteFlags);
- if (!KSUCCESS(Status)) {
- IoUpdateIrpStatus(Irp, Status);
- }
- //
- // Potentially return the completed IRP.
- //
- if (KSUCCESS(IrpStatus)) {
- CompleteIrp = FALSE;
- goto DispatchIoEnd;
- }
- }
- //
- // Start the DMA on the way down.
- //
- Irp->U.ReadWrite.IoBytesCompleted = 0;
- Irp->U.ReadWrite.NewIoOffset = Irp->U.ReadWrite.IoOffset;
- ASSERT(Irp->U.ReadWrite.IoBuffer != NULL);
- ASSERT((Child->BlockCount != 0) && (Child->BlockShift != 0));
- ASSERT(IS_ALIGNED(Irp->U.ReadWrite.IoOffset,
- 1 << Child->BlockShift) != FALSE);
- ASSERT(IS_ALIGNED(Irp->U.ReadWrite.IoSizeInBytes,
- 1 << Child->BlockShift) != FALSE);
- //
- // Before acquiring the controller's lock and starting the DMA, prepare
- // the I/O context for SD (i.e. it must use physical addresses that
- // are less than 4GB and be sector size aligned).
- //
- Status = IoPrepareReadWriteIrp(&(Irp->U.ReadWrite),
- 1 << Child->BlockShift,
- 0,
- MAX_ULONG,
- IrpReadWriteFlags);
- if (!KSUCCESS(Status)) {
- goto DispatchIoEnd;
- }
- //
- // Lock the controller to serialize access to the hardware.
- //
- KeAcquireQueuedLock(Child->ControllerLock);
- if (((Controller->Flags & SD_CONTROLLER_FLAG_MEDIA_PRESENT) == 0) ||
- ((Controller->Flags & SD_CONTROLLER_FLAG_MEDIA_CHANGED) != 0)) {
- Status = STATUS_NO_MEDIA;
- if ((Controller->Flags & SD_CONTROLLER_FLAG_MEDIA_CHANGED) != 0) {
- Status = STATUS_MEDIA_CHANGED;
- }
- KeReleaseQueuedLock(Child->ControllerLock);
- IoCompleteReadWriteIrp(&(Irp->U.ReadWrite), IrpReadWriteFlags);
- goto DispatchIoEnd;
- }
- //
- // If it's DMA, just send it on through.
- //
- Child->Irp = Irp;
- CompleteIrp = FALSE;
- IoPendIrp(SdOmap4Driver, Irp);
- SdOmap4PerformDmaIo(Child, Irp);
- //
- // DMA transfers are self perpetuating, so after kicking off this
- // first transfer, return. This returns with the lock held because
- // I/O is still in progress.
- //
- ASSERT(KeIsQueuedLockHeld(Child->ControllerLock) != FALSE);
- DispatchIoEnd:
- if (CompleteIrp != FALSE) {
- IoCompleteIrp(SdOmap4Driver, Irp, Status);
- }
- return;
- }
- VOID
- SdOmap4DispatchSystemControl (
- PIRP Irp,
- PVOID DeviceContext,
- PVOID IrpContext
- )
- /*++
- Routine Description:
- This routine handles System Control IRPs.
- Arguments:
- Irp - Supplies a pointer to the I/O request packet.
- DeviceContext - Supplies the context pointer supplied by the driver when it
- attached itself to the driver stack. Presumably this pointer contains
- driver-specific device context.
- IrpContext - Supplies the context pointer supplied by the driver when
- the IRP was created.
- Return Value:
- None.
- --*/
- {
- PSD_OMAP4_CHILD Child;
- PVOID Context;
- PSYSTEM_CONTROL_FILE_OPERATION FileOperation;
- PSYSTEM_CONTROL_LOOKUP Lookup;
- PFILE_PROPERTIES Properties;
- ULONGLONG PropertiesFileSize;
- KSTATUS Status;
- Context = Irp->U.SystemControl.SystemContext;
- Child = DeviceContext;
- //
- // Only child devices are supported.
- //
- if (Child->Type != SdOmap4Child) {
- ASSERT(Child->Type == SdOmap4Parent);
- return;
- }
- switch (Irp->MinorCode) {
- case IrpMinorSystemControlLookup:
- Lookup = (PSYSTEM_CONTROL_LOOKUP)Context;
- Status = STATUS_PATH_NOT_FOUND;
- if (Lookup->Root != FALSE) {
- //
- // Enable opening of the root as a single file.
- //
- Properties = &(Lookup->Properties);
- Properties->FileId = 0;
- Properties->Type = IoObjectBlockDevice;
- Properties->HardLinkCount = 1;
- Properties->BlockCount = Child->BlockCount;
- Properties->BlockSize = 1 << Child->BlockShift;
- WRITE_INT64_SYNC(&(Properties->FileSize),
- Child->BlockCount << Child->BlockShift);
- Status = STATUS_SUCCESS;
- }
- IoCompleteIrp(SdOmap4Driver, Irp, Status);
- break;
- //
- // Writes to the disk's properties are not allowed. Fail if the data
- // has changed.
- //
- case IrpMinorSystemControlWriteFileProperties:
- FileOperation = (PSYSTEM_CONTROL_FILE_OPERATION)Context;
- Properties = FileOperation->FileProperties;
- READ_INT64_SYNC(&(Properties->FileSize), &PropertiesFileSize);
- if ((Properties->FileId != 0) ||
- (Properties->Type != IoObjectBlockDevice) ||
- (Properties->HardLinkCount != 1) ||
- (Properties->BlockSize != (1 << Child->BlockShift)) ||
- (Properties->BlockCount != Child->BlockCount) ||
- (PropertiesFileSize != (Child->BlockCount << Child->BlockShift))) {
- Status = STATUS_NOT_SUPPORTED;
- } else {
- Status = STATUS_SUCCESS;
- }
- IoCompleteIrp(SdOmap4Driver, Irp, Status);
- break;
- //
- // Do not support hard disk device truncation.
- //
- case IrpMinorSystemControlTruncate:
- IoCompleteIrp(SdOmap4Driver, Irp, STATUS_NOT_SUPPORTED);
- break;
- //
- // Gather and return device information.
- //
- case IrpMinorSystemControlDeviceInformation:
- break;
- case IrpMinorSystemControlSynchronize:
- IoCompleteIrp(SdOmap4Driver, Irp, STATUS_SUCCESS);
- break;
- //
- // Ignore everything unrecognized.
- //
- default:
- ASSERT(FALSE);
- break;
- }
- return;
- }
- VOID
- SdOmap4ParentDispatchStateChange (
- PIRP Irp,
- PSD_OMAP4_CONTEXT Context,
- PVOID IrpContext
- )
- /*++
- Routine Description:
- This routine handles State Change IRPs for a parent device.
- Arguments:
- Irp - Supplies a pointer to the I/O request packet.
- Context - Supplies a pointer to the controller information.
- IrpContext - Supplies the context pointer supplied by the driver when
- the IRP was created.
- Return Value:
- None.
- --*/
- {
- KSTATUS Status;
- if (Irp->Direction == IrpUp) {
- if (!KSUCCESS(IoGetIrpStatus(Irp))) {
- return;
- }
- switch (Irp->MinorCode) {
- case IrpMinorQueryResources:
- Status = SdOmap4ParentProcessResourceRequirements(Irp, Context);
- if (!KSUCCESS(Status)) {
- IoCompleteIrp(SdOmap4Driver, Irp, Status);
- }
- break;
- case IrpMinorStartDevice:
- Status = SdOmap4ParentStartDevice(Irp, Context);
- if (!KSUCCESS(Status)) {
- IoCompleteIrp(SdOmap4Driver, Irp, Status);
- }
- break;
- case IrpMinorQueryChildren:
- Status = SdOmap4ParentQueryChildren(Irp, Context);
- if (!KSUCCESS(Status)) {
- IoCompleteIrp(SdOmap4Driver, Irp, Status);
- }
- break;
- default:
- break;
- }
- }
- return;
- }
- VOID
- SdOmap4ChildDispatchStateChange (
- PIRP Irp,
- PSD_OMAP4_CHILD Child,
- PVOID IrpContext
- )
- /*++
- Routine Description:
- This routine handles State Change IRPs for a parent device.
- Arguments:
- Irp - Supplies a pointer to the I/O request packet.
- Child - Supplies a pointer to the child device information.
- IrpContext - Supplies the context pointer supplied by the driver when
- the IRP was created.
- Return Value:
- None.
- --*/
- {
- BOOL CompleteIrp;
- KSTATUS Status;
- ASSERT(Irp->MajorCode == IrpMajorStateChange);
- //
- // The IRP is on its way down the stack. Do most processing here.
- //
- if (Irp->Direction == IrpDown) {
- Status = STATUS_NOT_SUPPORTED;
- CompleteIrp = TRUE;
- switch (Irp->MinorCode) {
- case IrpMinorQueryResources:
- Status = STATUS_SUCCESS;
- break;
- case IrpMinorStartDevice:
- Status = STATUS_SUCCESS;
- if (Child->DiskInterface.DiskToken == NULL) {
- RtlCopyMemory(&(Child->DiskInterface),
- &SdOmap4DiskInterfaceTemplate,
- sizeof(DISK_INTERFACE));
- Child->DiskInterface.BlockSize = 1 << Child->BlockShift;
- Child->DiskInterface.BlockCount = Child->BlockCount;
- Child->DiskInterface.DiskToken = Child;
- Status = IoCreateInterface(&SdOmap4DiskInterfaceUuid,
- Child->Device,
- &(Child->DiskInterface),
- sizeof(DISK_INTERFACE));
- if (!KSUCCESS(Status)) {
- Child->DiskInterface.DiskToken = NULL;
- }
- }
- break;
- case IrpMinorQueryChildren:
- Irp->U.QueryChildren.Children = NULL;
- Irp->U.QueryChildren.ChildCount = 0;
- Status = STATUS_SUCCESS;
- break;
- case IrpMinorQueryInterface:
- break;
- case IrpMinorRemoveDevice:
- if (Child->DiskInterface.DiskToken != NULL) {
- Status = IoDestroyInterface(&SdOmap4DiskInterfaceUuid,
- Child->Device,
- &(Child->DiskInterface));
- ASSERT(KSUCCESS(Status));
- Child->DiskInterface.DiskToken = NULL;
- }
- SdOmap4pChildReleaseReference(Child);
- Status = STATUS_SUCCESS;
- break;
- //
- // Pass all other IRPs down.
- //
- default:
- CompleteIrp = FALSE;
- break;
- }
- //
- // Complete the IRP unless there's a reason not to.
- //
- if (CompleteIrp != FALSE) {
- IoCompleteIrp(SdOmap4Driver, Irp, Status);
- }
- //
- // The IRP is completed and is on its way back up.
- //
- } else {
- ASSERT(Irp->Direction == IrpUp);
- }
- return;
- }
- KSTATUS
- SdOmap4ParentProcessResourceRequirements (
- PIRP Irp,
- PSD_OMAP4_CONTEXT Device
- )
- /*++
- Routine Description:
- This routine filters through the resource requirements presented by the
- bus for a SD OMAP4 Host controller. It adds an interrupt vector requirement
- for any interrupt line requested.
- Arguments:
- Irp - Supplies a pointer to the I/O request packet.
- Device - Supplies a pointer to this device.
- Return Value:
- Status code.
- --*/
- {
- PRESOURCE_CONFIGURATION_LIST Requirements;
- KSTATUS Status;
- RESOURCE_REQUIREMENT VectorRequirement;
- ASSERT((Irp->MajorCode == IrpMajorStateChange) &&
- (Irp->MinorCode == IrpMinorQueryResources));
- //
- // Initialize a nice interrupt vector requirement in preparation.
- //
- RtlZeroMemory(&VectorRequirement, sizeof(RESOURCE_REQUIREMENT));
- VectorRequirement.Type = ResourceTypeInterruptVector;
- VectorRequirement.Minimum = 0;
- VectorRequirement.Maximum = -1;
- VectorRequirement.Length = 1;
- //
- // Loop through all configuration lists, creating a vector for each line.
- //
- Requirements = Irp->U.QueryResources.ResourceRequirements;
- Status = IoCreateAndAddInterruptVectorsForLines(Requirements,
- &VectorRequirement);
- if (!KSUCCESS(Status)) {
- goto ProcessResourceRequirementsEnd;
- }
- ProcessResourceRequirementsEnd:
- return Status;
- }
- KSTATUS
- SdOmap4ParentStartDevice (
- PIRP Irp,
- PSD_OMAP4_CONTEXT Device
- )
- /*++
- Routine Description:
- This routine starts up the OMAP4 SD controller.
- Arguments:
- Irp - Supplies a pointer to the I/O request packet.
- Device - Supplies a pointer to this SD OMAP4 device.
- Return Value:
- Status code.
- --*/
- {
- PRESOURCE_ALLOCATION Allocation;
- PRESOURCE_ALLOCATION_LIST AllocationList;
- IO_CONNECT_INTERRUPT_PARAMETERS Connect;
- PRESOURCE_ALLOCATION ControllerBase;
- PRESOURCE_ALLOCATION DmaRx;
- PRESOURCE_ALLOCATION DmaTx;
- PRESOURCE_ALLOCATION LineAllocation;
- SD_INITIALIZATION_BLOCK Parameters;
- KSTATUS Status;
- ControllerBase = NULL;
- DmaRx = NULL;
- DmaTx = NULL;
- //
- // Loop through the allocated resources to get the controller base and the
- // interrupt.
- //
- AllocationList = Irp->U.StartDevice.ProcessorLocalResources;
- Allocation = IoGetNextResourceAllocation(AllocationList, NULL);
- while (Allocation != NULL) {
- //
- // If the resource is an interrupt vector, then it should have an
- // owning interrupt line allocation.
- //
- if (Allocation->Type == ResourceTypeInterruptVector) {
- //
- // Currently only one interrupt resource is expected.
- //
- ASSERT((Device->Flags &
- SD_OMAP4_DEVICE_FLAG_INTERRUPT_RESOURCES_FOUND) == 0);
- ASSERT(Allocation->OwningAllocation != NULL);
- //
- // Save the line and vector number.
- //
- LineAllocation = Allocation->OwningAllocation;
- Device->InterruptLine = LineAllocation->Allocation;
- Device->InterruptVector = Allocation->Allocation;
- RtlAtomicOr32(&(Device->Flags),
- SD_OMAP4_DEVICE_FLAG_INTERRUPT_RESOURCES_FOUND);
- } else if (Allocation->Type == ResourceTypePhysicalAddressSpace) {
- ASSERT(ControllerBase == NULL);
- ControllerBase = Allocation;
- } else if (Allocation->Type == ResourceTypeDmaChannel) {
- if (DmaTx == NULL) {
- DmaTx = Allocation;
- } else if (DmaRx == NULL) {
- DmaRx = Allocation;
- }
- }
- //
- // Get the next allocation in the list.
- //
- Allocation = IoGetNextResourceAllocation(AllocationList, Allocation);
- }
- //
- // Fail to start if the controller base was not found.
- //
- if ((ControllerBase == NULL) ||
- (ControllerBase->Length < SD_OMAP4_CONTROLLER_LENGTH)) {
- Status = STATUS_INVALID_CONFIGURATION;
- goto StartDeviceEnd;
- }
- //
- // Initialize OMAP4 specific stuff.
- //
- Device->ControllerPhysical = ControllerBase->Allocation;
- if (Device->ControllerBase == NULL) {
- Device->ControllerBase = MmMapPhysicalAddress(
- ControllerBase->Allocation,
- ControllerBase->Length,
- TRUE,
- FALSE,
- TRUE);
- if (Device->ControllerBase == NULL) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto StartDeviceEnd;
- }
- }
- if (Device->Soc == SdTiSocOmap4) {
- OmapI2cInitialize();
- Status = Omap4Twl6030InitializeMmcPower();
- if (!KSUCCESS(Status)) {
- ASSERT(FALSE);
- goto StartDeviceEnd;
- }
- } else if (Device->Soc == SdTiSocAm335) {
- //
- // Try to fire up system DMA.
- //
- Device->TxDmaResource = DmaTx;
- Device->RxDmaResource = DmaRx;
- if ((DmaTx != NULL) && (DmaRx != NULL)) {
- Status = SdOmap4InitializeDma(Device);
- if (!KSUCCESS(Status)) {
- Device->TxDmaResource = NULL;
- Device->RxDmaResource = NULL;
- }
- }
- }
- Status = SdOmap4ResetController(Device);
- if (Status == STATUS_NO_MEDIA) {
- Status = STATUS_SUCCESS;
- goto StartDeviceEnd;
- } else if (!KSUCCESS(Status)) {
- RtlDebugPrint("SdOmap4ResetController Failed: %d\n", Status);
- goto StartDeviceEnd;
- }
- //
- // Initialize the standard SD controller.
- //
- if (Device->Controller == NULL) {
- RtlZeroMemory(&Parameters, sizeof(SD_INITIALIZATION_BLOCK));
- Parameters.StandardControllerBase =
- Device->ControllerBase + SD_OMAP4_CONTROLLER_SD_REGISTER_OFFSET;
- Parameters.Voltages = SD_VOLTAGE_29_30 | SD_VOLTAGE_30_31;
- Parameters.HostCapabilities = SD_MODE_4BIT |
- SD_MODE_8BIT |
- SD_MODE_HIGH_SPEED |
- SD_MODE_AUTO_CMD12 |
- SD_MODE_CMD23;
- if (Device->Dma != NULL) {
- Parameters.HostCapabilities |= SD_MODE_SYSTEM_DMA;
- }
- Parameters.FundamentalClock = SD_OMAP4_FUNDAMENTAL_CLOCK_SPEED;
- Parameters.FunctionTable.GetSetBusWidth = SdOmap4GetSetBusWidth;
- Parameters.ConsumerContext = Device;
- Parameters.OsDevice = Irp->Device;
- Device->Controller = SdCreateController(&Parameters);
- if (Device->Controller == NULL) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto StartDeviceEnd;
- }
- }
- //
- // Attempt to connect the interrupt before initializing the controller. The
- // initialization process may trigger some interrupts.
- //
- if (Device->InterruptHandle == INVALID_HANDLE) {
- RtlZeroMemory(&Connect, sizeof(IO_CONNECT_INTERRUPT_PARAMETERS));
- Connect.Version = IO_CONNECT_INTERRUPT_PARAMETERS_VERSION;
- Connect.Device = Irp->Device;
- Connect.LineNumber = Device->InterruptLine;
- Connect.Vector = Device->InterruptVector;
- Connect.InterruptServiceRoutine = SdOmap4InterruptService;
- Connect.DispatchServiceRoutine = SdOmap4InterruptServiceDispatch;
- Connect.Context = Device;
- Connect.Interrupt = &(Device->InterruptHandle);
- Status = IoConnectInterrupt(&Connect);
- if (!KSUCCESS(Status)) {
- goto StartDeviceEnd;
- }
- Device->Controller->InterruptHandle = Device->InterruptHandle;
- }
- Status = STATUS_SUCCESS;
- StartDeviceEnd:
- if (!KSUCCESS(Status)) {
- if (Device->InterruptHandle != INVALID_HANDLE) {
- IoDisconnectInterrupt(Device->InterruptHandle);
- Device->InterruptHandle = INVALID_HANDLE;
- }
- if (Device->Controller != NULL) {
- SdDestroyController(Device->Controller);
- Device->Controller = NULL;
- }
- }
- return Status;
- }
- KSTATUS
- SdOmap4ParentQueryChildren (
- PIRP Irp,
- PSD_OMAP4_CONTEXT Device
- )
- /*++
- Routine Description:
- This routine potentially enumerates the disk device for the SD OMAP4
- controller.
- Arguments:
- Irp - Supplies a pointer to the I/O request packet.
- Device - Supplies a pointer to this device.
- Return Value:
- Status code.
- --*/
- {
- ULONG BlockSize;
- PSTR DeviceId;
- ULONG FlagsMask;
- PSD_OMAP4_CHILD NewChild;
- ULONG OldFlags;
- KSTATUS Status;
- NewChild = NULL;
- //
- // Check to see if any changes to the children are pending.
- //
- FlagsMask = ~(SD_CONTROLLER_FLAG_INSERTION_PENDING |
- SD_CONTROLLER_FLAG_REMOVAL_PENDING);
- OldFlags = RtlAtomicAnd32(&(Device->Controller->Flags), FlagsMask);
- //
- // If either a removal or insertion is pending, clean out the old child.
- // In practice, not all removals interrupt, meaning that two insertions can
- // arrive in a row.
- //
- FlagsMask = SD_CONTROLLER_FLAG_INSERTION_PENDING |
- SD_CONTROLLER_FLAG_REMOVAL_PENDING;
- if ((OldFlags & FlagsMask) != 0) {
- if (Device->Child != NULL) {
- KeAcquireQueuedLock(Device->Lock);
- RtlAtomicAnd32(&(Device->Controller->Flags),
- ~SD_CONTROLLER_FLAG_MEDIA_PRESENT);
- KeReleaseQueuedLock(Device->Lock);
- Device->Child = NULL;
- }
- }
- //
- // If an insertion is pending, try to enumerate the child.
- //
- if ((OldFlags & SD_CONTROLLER_FLAG_INSERTION_PENDING) != 0) {
- ASSERT(Device->Child == NULL);
- RtlAtomicAnd32(&(Device->Controller->Flags),
- ~SD_CONTROLLER_FLAG_MEDIA_CHANGED);
- Status = SdInitializeController(Device->Controller, FALSE);
- if (!KSUCCESS(Status)) {
- if (Status == STATUS_TIMEOUT) {
- Status = STATUS_SUCCESS;
- } else {
- RtlDebugPrint("SdInitializeController failed: %d\n", Status);
- }
- goto ParentQueryChildrenEnd;
- }
- NewChild = SdOmap4pCreateChild(Device);
- if (NewChild == NULL) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto ParentQueryChildrenEnd;
- }
- BlockSize = 0;
- Status = SdGetMediaParameters(NewChild->Controller,
- &(NewChild->BlockCount),
- &BlockSize);
- if (!KSUCCESS(Status)) {
- if (Status == STATUS_NO_MEDIA) {
- Status = STATUS_SUCCESS;
- }
- goto ParentQueryChildrenEnd;
- }
- ASSERT(POWER_OF_2(BlockSize) != FALSE);
- NewChild->BlockShift = RtlCountTrailingZeros32(BlockSize);
- //
- // Try to enable DMA, but it's okay if it doesn't succeed. DMA is
- // currently disabled on the TI AM33xx until EDMA is implemented.
- //
- if ((Device->Dma != NULL) || (Device->Soc != SdTiSocAm335)) {
- Status = SdStandardInitializeDma(Device->Controller);
- if (KSUCCESS(Status)) {
- NewChild->Flags |= SD_OMAP4_CHILD_FLAG_DMA_SUPPORTED;
- } else if (Status == STATUS_NO_MEDIA) {
- Status = STATUS_SUCCESS;
- goto ParentQueryChildrenEnd;
- }
- }
- DeviceId = SD_MMC_DEVICE_ID;
- if (SD_IS_CARD_SD(Device->Controller)) {
- DeviceId = SD_CARD_DEVICE_ID;
- }
- Status = IoCreateDevice(SdOmap4Driver,
- NewChild,
- Irp->Device,
- DeviceId,
- DISK_CLASS_ID,
- NULL,
- &(NewChild->Device));
- if (!KSUCCESS(Status)) {
- return Status;
- }
- Device->Child = NewChild;
- NewChild = NULL;
- }
- //
- // If there's no child present, don't enumerate it.
- //
- if (Device->Child == NULL) {
- return STATUS_SUCCESS;
- }
- ASSERT((Device->Child != NULL) && (Device->Child->Device != NULL));
- //
- // Enumerate the one child.
- //
- Status = IoMergeChildArrays(Irp,
- &(Device->Child->Device),
- 1,
- SD_ALLOCATION_TAG);
- ParentQueryChildrenEnd:
- if (NewChild != NULL) {
- ASSERT(NewChild->Device == NULL);
- SdOmap4pChildReleaseReference(NewChild);
- }
- return Status;
- }
- KSTATUS
- SdOmap4ResetController (
- PSD_OMAP4_CONTEXT Device
- )
- /*++
- Routine Description:
- This routine resets the OMAP4 SD controller and card.
- Arguments:
- Device - Supplies a pointer to this SD OMAP4 device.
- Return Value:
- Status code.
- --*/
- {
- ULONG ClockControl;
- ULONG Divisor;
- ULONGLONG Frequency;
- ULONG Register;
- KSTATUS Status;
- ULONGLONG Timeout;
- ULONG Value;
- Frequency = HlQueryTimeCounterFrequency();
- //
- // Perform a soft reset on the HSMMC part.
- //
- SD_OMAP4_WRITE_REGISTER(Device,
- SD_OMAP4_SYSCONFIG_REGISTER,
- SD_OMAP4_SYSCONFIG_SOFT_RESET);
- Status = STATUS_TIMEOUT;
- Timeout = KeGetRecentTimeCounter() + (Frequency * SD_OMAP4_TIMEOUT);
- do {
- if ((SD_OMAP4_READ_REGISTER(Device, SD_OMAP4_SYSSTATUS_REGISTER) &
- SD_OMAP4_SYSSTATUS_RESET_DONE) != 0) {
- Status = STATUS_SUCCESS;
- break;
- }
- } while (KeGetRecentTimeCounter() <= Timeout);
- if (!KSUCCESS(Status)) {
- return Status;
- }
- //
- // Perform a reset on the SD controller.
- //
- Register = SD_OMAP4_CONTROLLER_SD_REGISTER_OFFSET + SdRegisterClockControl;
- Value = SD_OMAP4_READ_REGISTER(Device, Register);
- Value |= SD_CLOCK_CONTROL_RESET_ALL;
- Status = STATUS_TIMEOUT;
- Timeout = KeGetRecentTimeCounter() + (Frequency * SD_OMAP4_TIMEOUT);
- do {
- if ((SD_OMAP4_READ_REGISTER(Device, Register) &
- SD_CLOCK_CONTROL_RESET_ALL) == 0) {
- Status = STATUS_SUCCESS;
- break;
- }
- } while (KeGetRecentTimeCounter() <= Timeout);
- if (!KSUCCESS(Status)) {
- return Status;
- }
- Register = SD_OMAP4_CONTROLLER_SD_REGISTER_OFFSET +
- SdRegisterInterruptStatus;
- SD_OMAP4_WRITE_REGISTER(Device, Register, 0xFFFFFFFF);
- //
- // Set up the host control register for 3 Volts.
- //
- Register = SD_OMAP4_CONTROLLER_SD_REGISTER_OFFSET + SdRegisterHostControl;
- Value = SD_HOST_CONTROL_POWER_3V0;
- SD_OMAP4_WRITE_REGISTER(Device, Register, Value);
- //
- // Add the 3.0V and 1.8V capabilities to the capability register.
- //
- Register = SD_OMAP4_CONTROLLER_SD_REGISTER_OFFSET + SdRegisterCapabilities;
- Value = SD_OMAP4_READ_REGISTER(Device, Register);
- Value |= SD_CAPABILITY_VOLTAGE_3V0 | SD_CAPABILITY_VOLTAGE_1V8;
- SD_OMAP4_WRITE_REGISTER(Device, Register, Value);
- //
- // Initialize the HSMMC control register.
- //
- Register = SD_OMAP4_CON_REGISTER;
- Value = SD_OMAP4_READ_REGISTER(Device, Register) &
- SD_OMAP4_CON_DEBOUNCE_MASK;
- SD_OMAP4_WRITE_REGISTER(Device, Register, Value);
- //
- // Set up the clock control register for 400kHz in preparation for sending
- // CMD0 with INIT held.
- //
- Register = SD_OMAP4_CONTROLLER_SD_REGISTER_OFFSET + SdRegisterClockControl;
- ClockControl = SD_CLOCK_CONTROL_DEFAULT_TIMEOUT <<
- SD_CLOCK_CONTROL_TIMEOUT_SHIFT;
- SD_OMAP4_WRITE_REGISTER(Device, Register, ClockControl);
- Divisor = SD_OMAP4_INITIAL_DIVISOR;
- ClockControl |= (Divisor & SD_CLOCK_CONTROL_DIVISOR_MASK) <<
- SD_CLOCK_CONTROL_DIVISOR_SHIFT;
- ClockControl |= (Divisor & SD_CLOCK_CONTROL_DIVISOR_HIGH_MASK) >>
- SD_CLOCK_CONTROL_DIVISOR_HIGH_SHIFT;
- ClockControl |= SD_CLOCK_CONTROL_INTERNAL_CLOCK_ENABLE;
- SD_OMAP4_WRITE_REGISTER(Device, Register, ClockControl);
- SD_OMAP4_WRITE_REGISTER(Device, Register, ClockControl);
- Status = STATUS_TIMEOUT;
- Timeout = KeGetRecentTimeCounter() + (Frequency * SD_OMAP4_TIMEOUT);
- do {
- Value = SD_OMAP4_READ_REGISTER(Device, Register);
- if ((Value & SD_CLOCK_CONTROL_CLOCK_STABLE) != 0) {
- Status = STATUS_SUCCESS;
- break;
- }
- } while (KeGetRecentTimeCounter() <= Timeout);
- if (!KSUCCESS(Status)) {
- return Status;
- }
- ClockControl |= SD_CLOCK_CONTROL_SD_CLOCK_ENABLE;
- SD_OMAP4_WRITE_REGISTER(Device, Register, ClockControl);
- Register = SD_OMAP4_CONTROLLER_SD_REGISTER_OFFSET + SdRegisterHostControl;
- Value = SD_OMAP4_READ_REGISTER(Device, Register);
- Value |= SD_HOST_CONTROL_POWER_ENABLE;
- SD_OMAP4_WRITE_REGISTER(Device, Register, Value);
- Register = SD_OMAP4_CONTROLLER_SD_REGISTER_OFFSET +
- SdRegisterInterruptStatusEnable;
- Value = SD_INTERRUPT_STATUS_ENABLE_DEFAULT_MASK;
- SD_OMAP4_WRITE_REGISTER(Device, Register, Value);
- //
- // Reset the card by setting the init flag and issuing the card reset (go
- // idle, command 0) command.
- //
- Register = SD_OMAP4_CON_REGISTER;
- Value = SD_OMAP4_READ_REGISTER(Device, Register) | SD_OMAP4_CON_INIT |
- SD_OMAP4_CON_DMA_MASTER;
- SD_OMAP4_WRITE_REGISTER(Device, Register, Value);
- //
- // Write a 0 to the command register to issue the command.
- //
- Register = SD_OMAP4_CONTROLLER_SD_REGISTER_OFFSET + SdRegisterCommand;
- SD_OMAP4_WRITE_REGISTER(Device, Register, 0);
- //
- // Wait for the command to complete.
- //
- Register = SD_OMAP4_CONTROLLER_SD_REGISTER_OFFSET +
- SdRegisterInterruptStatus;
- Status = STATUS_TIMEOUT;
- Timeout = KeGetRecentTimeCounter() + (Frequency * SD_OMAP4_TIMEOUT);
- do {
- Value = SD_OMAP4_READ_REGISTER(Device, Register);
- if (Value != 0) {
- if ((Value & SD_INTERRUPT_STATUS_COMMAND_COMPLETE) != 0) {
- Status = STATUS_SUCCESS;
- } else if ((Value &
- SD_INTERRUPT_STATUS_COMMAND_TIMEOUT_ERROR) != 0) {
- Status = STATUS_NO_MEDIA;
- } else {
- Status = STATUS_DEVICE_IO_ERROR;
- }
- SD_OMAP4_WRITE_REGISTER(Device, Register, Value);
- break;
- }
- } while (KeGetRecentTimeCounter() <= Timeout);
- //
- // Disable the INIT line.
- //
- Register = SD_OMAP4_CON_REGISTER;
- Value = SD_OMAP4_READ_REGISTER(Device, Register) & (~SD_OMAP4_CON_INIT);
- SD_OMAP4_WRITE_REGISTER(Device, Register, Value);
- if (!KSUCCESS(Status)) {
- return Status;
- }
- return STATUS_SUCCESS;
- }
- INTERRUPT_STATUS
- SdOmap4InterruptService (
- PVOID Context
- )
- /*++
- Routine Description:
- This routine implements the OMAP4 SD interrupt service routine.
- Arguments:
- Context - Supplies the context pointer given to the system when the
- interrupt was connected. In this case, this points to the OMAP4 SD
- controller.
- Return Value:
- Interrupt status.
- --*/
- {
- PSD_OMAP4_CONTEXT Device;
- Device = Context;
- return SdStandardInterruptService(Device->Controller);
- }
- INTERRUPT_STATUS
- SdOmap4InterruptServiceDispatch (
- PVOID Context
- )
- /*++
- Routine Description:
- This routine implements the dispatch level OMAP4 SD interrupt service
- routine.
- Arguments:
- Context - Supplies the context pointer given to the system when the
- interrupt was connected. In this case, this points to the OMAP4 SD
- controller.
- Return Value:
- Interrupt status.
- --*/
- {
- PSD_OMAP4_CONTEXT Device;
- Device = Context;
- return SdStandardInterruptServiceDispatch(Device->Controller);
- }
- VOID
- SdOmap4SdDmaCompletion (
- PSD_CONTROLLER Controller,
- PVOID Context,
- UINTN BytesTransferred,
- KSTATUS Status
- )
- /*++
- Routine Description:
- This routine is called by the SD library when a DMA transfer completes.
- This routine is called from a DPC and, as a result, can get called back
- at dispatch level.
- Arguments:
- Controller - Supplies a pointer to the controller.
- Context - Supplies a context pointer passed to the library when the DMA
- request was issued.
- BytesTransferred - Supplies the number of bytes transferred in the request.
- Status - Supplies the status code representing the completion of the I/O.
- Return Value:
- None.
- --*/
- {
- PSD_OMAP4_CHILD Child;
- Child = Context;
- if ((!KSUCCESS(Status)) || (Child->Parent->Dma == NULL)) {
- if (Child->Parent->Dma != NULL) {
- Child->Parent->Dma->Cancel(Child->Parent->Dma,
- Child->Parent->DmaTransfer);
- }
- if (!KSUCCESS(Status)) {
- RtlDebugPrint("OMAP4 SD Completion %d Bytes %ld\n",
- Status,
- BytesTransferred);
- }
- SdOmap4DmaCompletion(Controller, Context, BytesTransferred, Status);
- //
- // If this is an SD interrupt coming in and system DMA is enabled, only
- // complete the transfer if SD came in last.
- //
- } else if (RtlAtomicAdd32(&(Child->RemainingInterrupts), -1) == 1) {
- SdOmap4DmaCompletion(Controller, Context, 0, Status);
- }
- return;
- }
- PSD_OMAP4_CHILD
- SdOmap4pCreateChild (
- PSD_OMAP4_CONTEXT Device
- )
- /*++
- Routine Description:
- This routine creates an SD child context.
- Arguments:
- Device - Supplies a pointer to the parent device to which the child belongs.
- Return Value:
- Returns a pointer to the new child on success or NULL on failure.
- --*/
- {
- PSD_OMAP4_CHILD Child;
- Child = MmAllocateNonPagedPool(sizeof(SD_OMAP4_CHILD), SD_ALLOCATION_TAG);
- if (Child == NULL) {
- return NULL;
- }
- RtlZeroMemory(Child, sizeof(SD_OMAP4_CHILD));
- Child->Type = SdOmap4Child;
- Child->Parent = Device;
- Child->Controller = Device->Controller;
- Child->ControllerLock = Device->Lock;
- Child->ReferenceCount = 1;
- return Child;
- }
- VOID
- SdOmap4pDestroyChild (
- PSD_OMAP4_CHILD Child
- )
- /*++
- Routine Description:
- This routine destroys the given SD child device.
- Arguments:
- Child - Supplies a pointer to the SD child device to destroy.
- Return Value:
- None.
- --*/
- {
- ASSERT(Child->DiskInterface.DiskToken == NULL);
- ASSERT(Child->Irp == NULL);
- MmFreeNonPagedPool(Child);
- return;
- }
- VOID
- SdOmap4pChildAddReference (
- PSD_OMAP4_CHILD Child
- )
- /*++
- Routine Description:
- This routine adds a reference to SD child device.
- Arguments:
- Child - Supplies a pointer to the SD child device.
- Return Value:
- None.
- --*/
- {
- ULONG OldReferenceCount;
- OldReferenceCount = RtlAtomicAdd32(&(Child->ReferenceCount), 1);
- ASSERT((OldReferenceCount != 0) && (OldReferenceCount < 0x10000000));
- return;
- }
- VOID
- SdOmap4pChildReleaseReference (
- PSD_OMAP4_CHILD Child
- )
- /*++
- Routine Description:
- This routine releases a reference from the SD child.
- Arguments:
- Child - Supplies a pointer to the SD child.
- Return Value:
- None.
- --*/
- {
- ULONG OldReferenceCount;
- OldReferenceCount = RtlAtomicAdd32(&(Child->ReferenceCount), (ULONG)-1);
- ASSERT((OldReferenceCount != 0) && (OldReferenceCount < 0x10000000));
- if (OldReferenceCount == 1) {
- SdOmap4pDestroyChild(Child);
- }
- return;
- }
- KSTATUS
- SdOmap4ChildBlockIoReset (
- PVOID DiskToken
- )
- /*++
- Routine Description:
- This routine must be called immediately before using the block read and
- write routines in order to allow the disk to reset any I/O channels in
- preparation for imminent block I/O. This routine is called at high run
- level.
- Arguments:
- DiskToken - Supplies an opaque token for the disk. The appropriate token is
- retrieved by querying the disk device information.
- Return Value:
- Status code.
- --*/
- {
- PSD_OMAP4_CHILD Child;
- KSTATUS Status;
- ASSERT(KeGetRunLevel() == RunLevelHigh);
- Child = (PSD_OMAP4_CHILD)DiskToken;
- //
- // Put the SD controller into critical execution mode.
- //
- SdSetCriticalMode(Child->Controller, TRUE);
- //
- // Abort any current transaction that might have been left incomplete
- // when the crash occurred.
- //
- Status = SdAbortTransaction(Child->Controller, FALSE);
- return Status;
- }
- KSTATUS
- SdOmap4ChildBlockIoRead (
- PVOID DiskToken,
- PIO_BUFFER IoBuffer,
- ULONGLONG BlockAddress,
- UINTN BlockCount,
- PUINTN BlocksCompleted
- )
- /*++
- Routine Description:
- This routine reads the block contents from the disk into the given I/O
- buffer using polled I/O. It does so without acquiring any locks or
- allocating any resources, as this routine is used for crash dump support
- when the system is in a very fragile state. This routine must be called at
- high level.
- Arguments:
- DiskToken - Supplies an opaque token for the disk. The appropriate token is
- retrieved by querying the disk device information.
- IoBuffer - Supplies a pointer to the I/O buffer where the data will be read.
- BlockAddress - Supplies the block index to read (for physical disk, this is
- the LBA).
- BlockCount - Supplies the number of blocks to read.
- BlocksCompleted - Supplies a pointer that receives the total number of
- blocks read.
- Return Value:
- Status code.
- --*/
- {
- PSD_OMAP4_CHILD Child;
- IRP_READ_WRITE IrpReadWrite;
- KSTATUS Status;
- ASSERT(KeGetRunLevel() == RunLevelHigh);
- Child = (PSD_OMAP4_CHILD)DiskToken;
- IrpReadWrite.IoBuffer = IoBuffer;
- IrpReadWrite.IoOffset = BlockAddress << Child->BlockShift;
- IrpReadWrite.IoSizeInBytes = BlockCount << Child->BlockShift;
- //
- // As this read routine is meant for critical code paths (crash dump),
- // indicate that the channel should not be locked when performing the I/O.
- // It may be that some other thread holds the lock, which would cause a
- // dead lock as all other processors and threads are likely frozen.
- //
- Status = SdOmap4PerformIoPolled(&IrpReadWrite, Child, FALSE, FALSE);
- *BlocksCompleted = IrpReadWrite.IoBytesCompleted >> Child->BlockShift;
- return Status;
- }
- KSTATUS
- SdOmap4ChildBlockIoWrite (
- PVOID DiskToken,
- PIO_BUFFER IoBuffer,
- ULONGLONG BlockAddress,
- UINTN BlockCount,
- PUINTN BlocksCompleted
- )
- /*++
- Routine Description:
- This routine writes the contents of the given I/O buffer to the disk using
- polled I/O. It does so without acquiring any locks or allocating any
- resources, as this routine is used for crash dump support when the system
- is in a very fragile state. This routine must be called at high level.
- Arguments:
- DiskToken - Supplies an opaque token for the disk. The appropriate token is
- retrieved by querying the disk device information.
- IoBuffer - Supplies a pointer to the I/O buffer containing the data to
- write.
- BlockAddress - Supplies the block index to write to (for physical disk,
- this is the LBA).
- BlockCount - Supplies the number of blocks to write.
- BlocksCompleted - Supplies a pointer that receives the total number of
- blocks written.
- Return Value:
- Status code.
- --*/
- {
- PSD_OMAP4_CHILD Child;
- IRP_READ_WRITE IrpReadWrite;
- KSTATUS Status;
- ASSERT(KeGetRunLevel() == RunLevelHigh);
- Child = (PSD_OMAP4_CHILD)DiskToken;
- IrpReadWrite.IoBuffer = IoBuffer;
- IrpReadWrite.IoOffset = BlockAddress << Child->BlockShift;
- IrpReadWrite.IoSizeInBytes = BlockCount << Child->BlockShift;
- //
- // As this write routine is meant for critical code paths (crash dump),
- // indicate that the channel should not be locked when performing the I/O.
- // It may be that some other thread holds the lock, which would cause a
- // dead lock as all other processors and threads are likely frozen.
- //
- Status = SdOmap4PerformIoPolled(&IrpReadWrite, Child, TRUE, FALSE);
- *BlocksCompleted = IrpReadWrite.IoBytesCompleted >> Child->BlockShift;
- return Status;
- }
- KSTATUS
- SdOmap4PerformIoPolled (
- PIRP_READ_WRITE IrpReadWrite,
- PSD_OMAP4_CHILD Child,
- BOOL Write,
- BOOL LockRequired
- )
- /*++
- Routine Description:
- This routine performs polled I/O data transfers.
- Arguments:
- IrpReadWrite - Supplies a pointer to the IRP's read/write context.
- Child - Supplies a pointer to the SD child device.
- Write - Supplies a boolean indicating if this is a read operation (TRUE) or
- a write operation (FALSE).
- LockRequired - Supplies a boolean indicating if this operation requires the
- child's controller lock to be acquired (TRUE) or not (FALSE).
- Return Value:
- None.
- --*/
- {
- UINTN BlockCount;
- ULONGLONG BlockOffset;
- UINTN BytesRemaining;
- UINTN BytesThisRound;
- KSTATUS CompletionStatus;
- PSD_CONTROLLER Controller;
- PIO_BUFFER_FRAGMENT Fragment;
- UINTN FragmentIndex;
- UINTN FragmentOffset;
- PIO_BUFFER IoBuffer;
- UINTN IoBufferOffset;
- ULONG IrpReadWriteFlags;
- BOOL LockHeld;
- BOOL ReadWriteIrpPrepared;
- KSTATUS Status;
- PVOID VirtualAddress;
- Controller = Child->Controller;
- IrpReadWrite->IoBytesCompleted = 0;
- LockHeld = FALSE;
- ReadWriteIrpPrepared = FALSE;
- ASSERT(IrpReadWrite->IoBuffer != NULL);
- ASSERT(Child->Type == SdOmap4Child);
- ASSERT((Child->BlockCount != 0) && (Child->BlockShift != 0));
- //
- // Validate the supplied I/O buffer is aligned and big enough.
- //
- IrpReadWriteFlags = IRP_READ_WRITE_FLAG_POLLED;
- if (Write != FALSE) {
- IrpReadWriteFlags |= IRP_READ_WRITE_FLAG_WRITE;
- }
- Status = IoPrepareReadWriteIrp(IrpReadWrite,
- 1 << Child->BlockShift,
- 0,
- MAX_ULONGLONG,
- IrpReadWriteFlags);
- if (!KSUCCESS(Status)) {
- goto PerformIoPolledEnd;
- }
- ReadWriteIrpPrepared = TRUE;
- //
- // Make sure the I/O buffer is mapped before use. SD depends on the buffer
- // being mapped.
- //
- IoBuffer = IrpReadWrite->IoBuffer;
- Status = MmMapIoBuffer(IoBuffer, FALSE, FALSE, FALSE);
- if (!KSUCCESS(Status)) {
- goto PerformIoPolledEnd;
- }
- //
- // Find the starting fragment based on the current offset.
- //
- IoBufferOffset = MmGetIoBufferCurrentOffset(IoBuffer);
- FragmentIndex = 0;
- FragmentOffset = 0;
- while (IoBufferOffset != 0) {
- ASSERT(FragmentIndex < IoBuffer->FragmentCount);
- Fragment = &(IoBuffer->Fragment[FragmentIndex]);
- if (IoBufferOffset < Fragment->Size) {
- FragmentOffset = IoBufferOffset;
- break;
- }
- IoBufferOffset -= Fragment->Size;
- FragmentIndex += 1;
- }
- if (LockRequired != FALSE) {
- KeAcquireQueuedLock(Child->ControllerLock);
- LockHeld = TRUE;
- }
- if ((Controller->Flags & SD_CONTROLLER_FLAG_MEDIA_CHANGED) != 0) {
- Status = STATUS_MEDIA_CHANGED;
- goto PerformIoPolledEnd;
- } else if ((Controller->Flags & SD_CONTROLLER_FLAG_MEDIA_PRESENT) == 0) {
- Status = STATUS_NO_MEDIA;
- goto PerformIoPolledEnd;
- }
- //
- // Loop reading in or writing out each fragment in the I/O buffer.
- //
- BytesRemaining = IrpReadWrite->IoSizeInBytes;
- ASSERT(IS_ALIGNED(BytesRemaining, 1 << Child->BlockShift) != FALSE);
- ASSERT(IS_ALIGNED(IrpReadWrite->IoOffset, 1 << Child->BlockShift) != FALSE);
- BlockOffset = IrpReadWrite->IoOffset >> Child->BlockShift;
- while (BytesRemaining != 0) {
- ASSERT(FragmentIndex < IoBuffer->FragmentCount);
- Fragment = &(IoBuffer->Fragment[FragmentIndex]);
- VirtualAddress = Fragment->VirtualAddress + FragmentOffset;
- BytesThisRound = Fragment->Size - FragmentOffset;
- if (BytesRemaining < BytesThisRound) {
- BytesThisRound = BytesRemaining;
- }
- ASSERT(IS_ALIGNED(BytesThisRound, (1 << Child->BlockShift)) != FALSE);
- BlockCount = BytesThisRound >> Child->BlockShift;
- //
- // Make sure the system isn't trying to do I/O off the end of the disk.
- //
- ASSERT(BlockOffset < Child->BlockCount);
- ASSERT(BlockCount >= 1);
- Status = SdBlockIoPolled(Controller,
- BlockOffset,
- BlockCount,
- VirtualAddress,
- Write);
- if (!KSUCCESS(Status)) {
- goto PerformIoPolledEnd;
- }
- BlockOffset += BlockCount;
- BytesRemaining -= BytesThisRound;
- IrpReadWrite->IoBytesCompleted += BytesThisRound;
- FragmentOffset += BytesThisRound;
- if (FragmentOffset >= Fragment->Size) {
- FragmentIndex += 1;
- FragmentOffset = 0;
- }
- }
- Status = STATUS_SUCCESS;
- PerformIoPolledEnd:
- if (LockHeld != FALSE) {
- KeReleaseQueuedLock(Child->ControllerLock);
- }
- if (ReadWriteIrpPrepared != FALSE) {
- CompletionStatus = IoCompleteReadWriteIrp(IrpReadWrite,
- IrpReadWriteFlags);
- if (!KSUCCESS(CompletionStatus) && KSUCCESS(Status)) {
- Status = CompletionStatus;
- }
- }
- IrpReadWrite->NewIoOffset = IrpReadWrite->IoOffset +
- IrpReadWrite->IoBytesCompleted;
- return Status;
- }
- KSTATUS
- SdOmap4GetSetBusWidth (
- PSD_CONTROLLER Controller,
- PVOID Context,
- BOOL Set
- )
- /*++
- Routine Description:
- This routine gets or sets the controller's bus width. The bus width is
- stored in the controller structure.
- Arguments:
- Controller - Supplies a pointer to the controller.
- Context - Supplies a context pointer passed to the SD/MMC library upon
- creation of the controller.
- Set - Supplies a boolean indicating whether the bus width should be queried
- or set.
- Return Value:
- Status code.
- --*/
- {
- PSD_OMAP4_CONTEXT Device;
- KSTATUS Status;
- ULONG Value;
- Device = Context;
- Status = SdStandardGetSetBusWidth(Controller, Context, Set);
- if (!KSUCCESS(Status)) {
- return Status;
- }
- Value = SD_OMAP4_READ_REGISTER(Device, SD_OMAP4_CON_REGISTER);
- switch (Controller->BusWidth) {
- case 1:
- case 4:
- Value &= ~SD_OMAP4_CON_8BIT;
- break;
- case 8:
- Value |= SD_OMAP4_CON_8BIT;
- break;
- default:
- ASSERT(FALSE);
- return STATUS_INVALID_PARAMETER;
- }
- SD_OMAP4_WRITE_REGISTER(Device, SD_OMAP4_CON_REGISTER, Value);
- return STATUS_SUCCESS;
- }
- KSTATUS
- SdOmap4InitializeDma (
- PSD_OMAP4_CONTEXT Device
- )
- /*++
- Routine Description:
- This routine attempts to wire up EDMA on the SD controller.
- Arguments:
- Device - Supplies a pointer to this SD OMAP4 device.
- Return Value:
- Status code.
- --*/
- {
- UINTN AllocationSize;
- PEDMA_CONFIGURATION Configuration;
- DMA_INFORMATION Information;
- PRESOURCE_ALLOCATION Resource;
- KSTATUS Status;
- PDMA_TRANSFER Transfer;
- Resource = Device->TxDmaResource;
- ASSERT((Resource != NULL) &&
- (Device->RxDmaResource != NULL) &&
- (Resource->Provider == Device->RxDmaResource->Provider));
- Status = IoRegisterForInterfaceNotifications(&SdOmap4DmaUuid,
- SdOmap4DmaInterfaceCallback,
- Resource->Provider,
- Device,
- TRUE);
- if (!KSUCCESS(Status)) {
- goto InitializeDmaEnd;
- }
- if (Device->Dma == NULL) {
- Status = STATUS_NOT_SUPPORTED;
- goto InitializeDmaEnd;
- }
- RtlZeroMemory(&Information, sizeof(DMA_INFORMATION));
- Information.Version = DMA_INFORMATION_VERSION;
- Status = Device->Dma->GetInformation(Device->Dma, &Information);
- if (!KSUCCESS(Status)) {
- goto InitializeDmaEnd;
- }
- if (RtlAreUuidsEqual(&(Information.ControllerUuid), &SdOmap4Edma3Uuid) ==
- FALSE) {
- Status = STATUS_NOT_SUPPORTED;
- goto InitializeDmaEnd;
- }
- if (Device->DmaTransfer == NULL) {
- Status = Device->Dma->AllocateTransfer(Device->Dma, &Transfer);
- if (!KSUCCESS(Status)) {
- goto InitializeDmaEnd;
- }
- Device->DmaTransfer = Transfer;
- AllocationSize = sizeof(EDMA_CONFIGURATION);
- Configuration = MmAllocateNonPagedPool(AllocationSize,
- SD_ALLOCATION_TAG);
- if (Configuration == NULL) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto InitializeDmaEnd;
- }
- RtlZeroMemory(Configuration, AllocationSize);
- Device->EdmaConfiguration = Configuration;
- //
- // Fill in some of the fields that will never change transfer to
- // transfer.
- //
- Transfer->Configuration = Configuration;
- Transfer->ConfigurationSize = sizeof(EDMA_CONFIGURATION);
- Transfer->CompletionCallback = SdOmap4EdmaCompletion;
- Transfer->Width = 32;
- Transfer->Device.Address = Device->ControllerPhysical +
- SD_OMAP4_CONTROLLER_SD_REGISTER_OFFSET +
- SdRegisterBufferDataPort;
- Configuration->Mode = EdmaTriggerModeEvent;
- Configuration->Param.ACount = 4;
- }
- InitializeDmaEnd:
- if (!KSUCCESS(Status)) {
- if (Device->DmaTransfer != NULL) {
- Device->Dma->FreeTransfer(Device->Dma, Device->DmaTransfer);
- Device->DmaTransfer = NULL;
- }
- if (Device->EdmaConfiguration != NULL) {
- MmFreeNonPagedPool(Device->EdmaConfiguration);
- Device->EdmaConfiguration = NULL;
- }
- IoUnregisterForInterfaceNotifications(&SdOmap4DmaUuid,
- SdOmap4DmaInterfaceCallback,
- Resource->Provider,
- Device);
- }
- return Status;
- }
- VOID
- SdOmap4DmaInterfaceCallback (
- PVOID Context,
- PDEVICE Device,
- PVOID InterfaceBuffer,
- ULONG InterfaceBufferSize,
- BOOL Arrival
- )
- /*++
- Routine Description:
- This routine is called to notify listeners that an interface has arrived
- or departed.
- Arguments:
- Context - Supplies the caller's context pointer, supplied when the caller
- requested interface notifications.
- Device - Supplies a pointer to the device exposing or deleting the
- interface.
- InterfaceBuffer - Supplies a pointer to the interface buffer of the
- interface.
- InterfaceBufferSize - Supplies the buffer size.
- Arrival - Supplies TRUE if a new interface is arriving, or FALSE if an
- interface is departing.
- Return Value:
- None.
- --*/
- {
- PSD_OMAP4_CONTEXT Sd;
- Sd = Context;
- ASSERT(InterfaceBufferSize >= sizeof(DMA_INTERFACE));
- ASSERT((Sd->Dma == NULL) || (Sd->Dma == InterfaceBuffer));
- if (Arrival != FALSE) {
- Sd->Dma = InterfaceBuffer;
- } else {
- Sd->Dma = NULL;
- }
- return;
- }
- VOID
- SdOmap4PerformDmaIo (
- PSD_OMAP4_CHILD Child,
- PIRP Irp
- )
- /*++
- Routine Description:
- This routine performs DMA-based I/O for the OMAP SD controller.
- Arguments:
- Child - Supplies a pointer to the child device.
- Irp - Supplies a pointer to the partially completed IRP.
- Return Value:
- None.
- --*/
- {
- UINTN BlockCount;
- ULONGLONG BlockOffset;
- IO_OFFSET IoOffset;
- ULONGLONG IoSize;
- KSTATUS Status;
- BOOL Write;
- IoOffset = Irp->U.ReadWrite.IoOffset + Irp->U.ReadWrite.IoBytesCompleted;
- BlockOffset = IoOffset >> Child->BlockShift;
- IoSize = Irp->U.ReadWrite.IoSizeInBytes - Irp->U.ReadWrite.IoBytesCompleted;
- Write = FALSE;
- if (Irp->MinorCode == IrpMinorIoWrite) {
- Write = TRUE;
- }
- ASSERT(BlockOffset < Child->BlockCount);
- //
- // Set up the DMA transfer if the controller uses system DMA.
- //
- if (Child->Parent->Dma != NULL) {
- ASSERT(Child->Parent->Soc == SdTiSocAm335);
- Status = SdOmap4SetupEdma(Child, &IoSize);
- if (!KSUCCESS(Status)) {
- IoCompleteIrp(SdOmap4Driver, Irp, Status);
- return;
- }
- } else {
- Child->RemainingInterrupts = 1;
- }
- BlockCount = IoSize >> Child->BlockShift;
- ASSERT((BlockCount >= 1) && ((BlockCount << Child->BlockShift) == IoSize));
- SdStandardBlockIoDma(Child->Controller,
- BlockOffset,
- BlockCount,
- Irp->U.ReadWrite.IoBuffer,
- Irp->U.ReadWrite.IoBytesCompleted,
- Write,
- SdOmap4SdDmaCompletion,
- Child);
- return;
- }
- KSTATUS
- SdOmap4SetupEdma (
- PSD_OMAP4_CHILD Child,
- PULONGLONG Size
- )
- /*++
- Routine Description:
- This routine submits a system DMA request on behalf of the SD controller.
- Arguments:
- Child - Supplies a pointer to the child device.
- Size - Supplies a pointer where the actual size of the DMA transfer will
- be returned on success.
- Return Value:
- Status code.
- --*/
- {
- ULONG BlockLength;
- ULONG Channel;
- PEDMA_CONFIGURATION Configuration;
- PDMA_INTERFACE Dma;
- PDMA_TRANSFER DmaTransfer;
- PIRP Irp;
- KSTATUS Status;
- Dma = Child->Parent->Dma;
- DmaTransfer = Child->Parent->DmaTransfer;
- Configuration = DmaTransfer->Configuration;
- Irp = Child->Irp;
- DmaTransfer->Memory = Irp->U.ReadWrite.IoBuffer;
- DmaTransfer->Completed = Irp->U.ReadWrite.IoBytesCompleted;
- DmaTransfer->Size = Irp->U.ReadWrite.IoSizeInBytes;
- DmaTransfer->UserContext = Child;
- Configuration->Param.Options = EDMA_TRANSFER_AB_SYNCHRONIZED |
- EDMA_TRANSFER_FIFO_WIDTH_32;
- if (Irp->MinorCode == IrpMinorIoWrite) {
- DmaTransfer->Allocation = Child->Parent->TxDmaResource;
- Channel = DmaTransfer->Allocation->Allocation;
- DmaTransfer->Direction = DmaTransferToDevice;
- BlockLength = Child->Controller->WriteBlockLength;
- Configuration->Param.BCount = BlockLength / Configuration->Param.ACount;
- Configuration->Param.SourceBIndex = Configuration->Param.ACount;
- Configuration->Param.SourceCIndex = BlockLength;
- Configuration->Param.DestinationBIndex = 0;
- Configuration->Param.DestinationCIndex = 0;
- Configuration->Param.Options |= EDMA_TRANSFER_DESTINATION_FIFO |
- ((Channel <<
- EDMA_TRANSFER_COMPLETION_CODE_SHIFT) &
- EDMA_TRANSFER_COMPLETION_CODE_MASK);
- } else {
- DmaTransfer->Allocation = Child->Parent->RxDmaResource;
- Channel = DmaTransfer->Allocation->Allocation;
- DmaTransfer->Direction = DmaTransferFromDevice;
- BlockLength = Child->Controller->ReadBlockLength;
- Configuration->Param.BCount = BlockLength / Configuration->Param.ACount;
- Configuration->Param.DestinationBIndex = Configuration->Param.ACount;
- Configuration->Param.DestinationCIndex = BlockLength;
- Configuration->Param.SourceBIndex = 0;
- Configuration->Param.SourceCIndex = 0;
- Configuration->Param.Options |= EDMA_TRANSFER_SOURCE_FIFO |
- ((Channel <<
- EDMA_TRANSFER_COMPLETION_CODE_SHIFT) &
- EDMA_TRANSFER_COMPLETION_CODE_MASK);
- }
- ASSERT(Child->RemainingInterrupts == 0);
- Child->RemainingInterrupts = 2;
- Status = Dma->Submit(Dma, DmaTransfer);
- *Size = DmaTransfer->Size - DmaTransfer->Completed;
- return Status;
- }
- VOID
- SdOmap4EdmaCompletion (
- PDMA_TRANSFER Transfer
- )
- /*++
- Routine Description:
- This routine is called when a transfer set has completed or errored out.
- Arguments:
- Transfer - Supplies a pointer to the transfer that completed.
- Return Value:
- None.
- --*/
- {
- PSD_OMAP4_CHILD Child;
- UINTN CompletedThisRound;
- KSTATUS Status;
- Child = Transfer->UserContext;
- Status = Transfer->Status;
- CompletedThisRound = Transfer->Completed -
- Child->Irp->U.ReadWrite.IoBytesCompleted;
- if (!KSUCCESS(Status)) {
- RtlDebugPrint("OMAP4 EDMA SD Completion %d Bytes %ld\n",
- Status,
- CompletedThisRound);
- }
- SdOmap4DmaCompletion(Child->Controller, Child, CompletedThisRound, Status);
- return;
- }
- VOID
- SdOmap4DmaCompletion (
- PSD_CONTROLLER Controller,
- PVOID Context,
- UINTN BytesTransferred,
- KSTATUS Status
- )
- /*++
- Routine Description:
- This routine is called indirectly by either the EDMA code or the SD library
- code once the transfer has actually completed. It either completes the IRP
- or fires up a new transfer.
- Arguments:
- Controller - Supplies a pointer to the controller.
- Context - Supplies a context pointer passed to the library when the DMA
- request was issued.
- BytesTransferred - Supplies the number of bytes transferred in the request
- this round.
- Status - Supplies the status code representing the completion of the I/O.
- Return Value:
- None.
- --*/
- {
- PSD_OMAP4_CHILD Child;
- PIRP Irp;
- Child = Context;
- Irp = Child->Irp;
- ASSERT(Irp != NULL);
- if (!KSUCCESS(Status)) {
- RtlAtomicAdd32(&(Child->RemainingInterrupts), -1);
- RtlDebugPrint("SD OMAP4 Failed 0x%x 0x%I64x 0x%x: %d\n",
- Irp->MinorCode,
- Irp->U.ReadWrite.IoOffset,
- Irp->U.ReadWrite.IoSizeInBytes,
- Status);
- SdAbortTransaction(Controller, FALSE);
- IoCompleteIrp(SdOmap4Driver, Irp, Status);
- return;
- }
- if (BytesTransferred != 0) {
- Irp->U.ReadWrite.IoBytesCompleted += BytesTransferred;
- Irp->U.ReadWrite.NewIoOffset += BytesTransferred;
- //
- // If more interrupts are expected, don't complete just yet.
- //
- if (RtlAtomicAdd32(&(Child->RemainingInterrupts), -1) != 1) {
- return;
- }
- //
- // Otherwise if this is SD and it was the last remaining interrupt, the
- // DMA portion better be complete already.
- //
- } else {
- ASSERT(Child->RemainingInterrupts == 0);
- }
- //
- // If this transfer's over, complete the IRP.
- //
- if (Irp->U.ReadWrite.IoBytesCompleted ==
- Irp->U.ReadWrite.IoSizeInBytes) {
- IoCompleteIrp(SdOmap4Driver, Irp, Status);
- return;
- }
- SdOmap4PerformDmaIo(Child, Irp);
- return;
- }
|