ser16550.c 83 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506
  1. /*++
  2. Copyright (c) 2014 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. ser16550.c
  5. Abstract:
  6. This module implements a kernel driver for 16550-like UARTs.
  7. Author:
  8. Evan Green 21-Nov-2014
  9. Environment:
  10. Kernel
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include <minoca/kernel/driver.h>
  16. #include <minoca/fw/acpitabs.h>
  17. #include <minoca/kernel/kdebug.h>
  18. //
  19. // --------------------------------------------------------------------- Macros
  20. //
  21. //
  22. // Macros to read from and write to 16550 registers.
  23. //
  24. #define SER16550_READ8(_Device, _Register) \
  25. (_Device)->Read8((_Device), (_Register))
  26. #define SER16550_WRITE8(_Device, _Register, _Value) \
  27. (_Device)->Write8((_Device), (_Register), (_Value))
  28. //
  29. // This macro returns the offset of a given register from its base.
  30. //
  31. #define SER16550_REGISTER_OFFSET(_Device, _Register) \
  32. ((_Device)->RegisterOffset + ((_Register) << (_Device)->RegisterShift))
  33. //
  34. // This macro evaluates to non-zero if the given Oxford device ID has two
  35. // UARTs. This matches against the Mode[2:0] bits being 101 and the UART_EN bit
  36. // being set.
  37. //
  38. #define SER16550_OXFORD_DUAL_UARTS(_DeviceId) \
  39. (((_DeviceId) & 0x0078) == 0x0058)
  40. //
  41. // ---------------------------------------------------------------- Definitions
  42. //
  43. #define SER16550_ALLOCATION_TAG 0x36317253
  44. #define SER16550_DEFAULT_BUFFER_SIZE 2048
  45. #define SER16550_DEFAULT_BASE_BAUD 115200
  46. #define SER16550A_FIFO_SIZE 16
  47. #define SER16550_MAX_FIFO 256
  48. #define SERIAL_PORT_DEVICE_ID_FORMAT "Serial%d"
  49. #define SERIAL_PORT_DEVICE_ID_SIZE 50
  50. //
  51. // Standard 16x50 register definitions.
  52. //
  53. #define SER16550_LINE_CONTROL_5_DATA_BITS 0x00
  54. #define SER16550_LINE_CONTROL_6_DATA_BITS 0x01
  55. #define SER16550_LINE_CONTROL_7_DATA_BITS 0x02
  56. #define SER16550_LINE_CONTROL_8_DATA_BITS 0x03
  57. #define SER16550_LINE_CONTROL_2_STOP_BITS 0x04
  58. #define SER16550_LINE_CONTROL_PARITY_ENABLE 0x08
  59. #define SER16550_LINE_CONTROL_EVEN_PARITY 0x10
  60. #define SER16550_LINE_CONTROL_SET_PARITY 0x20
  61. #define SER16550_LINE_CONTROL_SET_BREAK 0x40
  62. #define SER16550_LINE_CONTROL_DIVISOR_LATCH 0x80
  63. #define SER16550_FIFO_CONTROL_ENABLE 0x01
  64. #define SER16550_FIFO_CONTROL_CLEAR_RECEIVE 0x02
  65. #define SER16550_FIFO_CONTROL_CLEAR_TRANSMIT 0x04
  66. #define SER16550_FIFO_CONTROL_MULTI_DMA 0x08
  67. #define SER16550_FIFO_CONTROL_64_BYTE_FIFO 0x20
  68. #define SER16550_FIFO_CONTROL_RX_TRIGGER_1 (0 << 6)
  69. #define SER16550_FIFO_CONTROL_RX_TRIGGER_4 (1 << 6)
  70. #define SER16550_FIFO_CONTROL_RX_TRIGGER_8 (2 << 6)
  71. #define SER16550_FIFO_CONTROL_RX_TRIGGER_14 (3 << 6)
  72. #define SER16550_MODEM_CONTROL_DTR 0x01
  73. #define SER16550_MODEM_CONTROL_RTS 0x02
  74. #define SER16550_MODEM_CONTROL_OP1 0x04
  75. #define SER16550_MODEM_CONTROL_ENABLE_INTERRUPT 0x08
  76. #define SER16550_MODEM_CONTROL_LOOPBACK 0x10
  77. #define SER16550_MODEM_CONTROL_ENABLE_FLOW_CONTROL 0x20
  78. #define SER16550_INTERRUPT_ENABLE_RX_DATA 0x01
  79. #define SER16550_INTERRUPT_ENABLE_TX_EMPTY 0x02
  80. #define SER16550_INTERRUPT_ENABLE_RX_STATUS 0x04
  81. #define SER16550_INTERRUPT_ENABLE_MODEM_STATUS 0x08
  82. #define SER16550_INTERRUPT_STATUS_NONE_PENDING 0x01
  83. #define SER16550_INTERRUPT_STATUS_RX_DATA_ERROR 0x06
  84. #define SER16550_INTERRUPT_STATUS_RX_DATA_READY 0x04
  85. #define SER16550_INTERRUPT_STATUS_RX_TIMEOUT 0x0C
  86. #define SER16550_INTERRUPT_STATUS_TX_EMPTY 0x02
  87. #define SER16550_INTERRUPT_STATUS_MODEM_STATUS 0x00
  88. #define SER16550_INTERRUPT_STATUS_MASK 0x0E
  89. #define SER16550_LINE_STATUS_RX_READY 0x01
  90. #define SER16550_LINE_STATUS_OVERRUN_ERROR 0x02
  91. #define SER16550_LINE_STATUS_PARITY_ERROR 0x04
  92. #define SER16550_LINE_STATUS_FRAMING_ERROR 0x08
  93. #define SER16550_LINE_STATUS_BREAK 0x10
  94. #define SER16550_LINE_STATUS_TX_HOLDING_EMPTY 0x20
  95. #define SER16550_LINE_STATUS_TX_EMPTY 0x40
  96. #define SER16550_LINE_STATUS_FIFO_ERROR 0x80
  97. #define SER16550_LINE_STATUS_ERROR_MASK \
  98. (SER16550_LINE_STATUS_OVERRUN_ERROR | SER16550_LINE_STATUS_PARITY_ERROR | \
  99. SER16550_LINE_STATUS_FRAMING_ERROR | SER16550_LINE_STATUS_FIFO_ERROR)
  100. #define SER16550_LINE_STATUS_RX_MASK \
  101. (SER16550_LINE_STATUS_RX_READY | SER16550_LINE_STATUS_BREAK)
  102. //
  103. // Known vendors and devices.
  104. //
  105. #define SER16550_PCI_DEVICE_ID_FORMAT "VEN_%x&DEV_%x"
  106. #define SER16550_VENDOR_INTEL 0x8086
  107. #define SER16550_INTEL_QUARK 0x0936
  108. #define SER16550_VENDOR_OXFORD 0x1415
  109. #define SER16550_OXFORD_UART_OFFSET 0x1000
  110. #define SER16550_OXFORD_UART_STRIDE 0x200
  111. #define SER16550_OXFORD_BASE_BAUD 3916800
  112. //
  113. // Intel Quark UART information.
  114. //
  115. #define SER16550_INTEL_QUARK_UART_BASE_BAUD 2764800
  116. #define SER16550_INTEL_QUARK_UART_REGISTER_SHIFT 2
  117. //
  118. // ------------------------------------------------------ Data Type Definitions
  119. //
  120. typedef enum _SER16550_OBJECT_TYPE {
  121. Ser16550ObjectInvalid,
  122. Ser16550ObjectParent,
  123. Ser16550ObjectChild
  124. } SER16550_OBJECT_TYPE, *PSER16550_OBJECT_TYPE;
  125. typedef enum _SER16550_VARIANT {
  126. Ser16550VariantInvalid,
  127. Ser16550VariantGeneric,
  128. Ser16550VariantQuark,
  129. Ser16550VariantOxford,
  130. } SER16550_VARIANT, *PSER16550_VARIANT;
  131. typedef enum _SER16550_REGISTER {
  132. Ser16550Data = 0,
  133. Ser16550DivisorLow = 0,
  134. Ser16550InterruptEnable = 1,
  135. Ser16550DivisorHigh = 1,
  136. Ser16550InterruptStatus = 2,
  137. Ser16550FifoControl = 2,
  138. Ser16550LineControl = 3,
  139. Ser16550ModemControl = 4,
  140. Ser16550LineStatus = 5,
  141. Ser16550ModemStatus = 6,
  142. Ser16550Scratch = 7
  143. } SER16550_REGISTER, *PSER16550_REGISTER;
  144. typedef struct _SER16550_CHILD SER16550_CHILD, *PSER16550_CHILD;
  145. typedef
  146. UCHAR
  147. (*PSER16550_READ8) (
  148. PSER16550_CHILD Device,
  149. SER16550_REGISTER Register
  150. );
  151. /*++
  152. Routine Description:
  153. This routine reads a 16550 register.
  154. Arguments:
  155. Device - Supplies a pointer to the device context.
  156. Register - Supplies the register to read.
  157. Return Value:
  158. Returns the value at the register.
  159. --*/
  160. typedef
  161. VOID
  162. (*PSER16550_WRITE8) (
  163. PSER16550_CHILD Device,
  164. SER16550_REGISTER Register,
  165. UCHAR Value
  166. );
  167. /*++
  168. Routine Description:
  169. This routine writes to a 16550 register.
  170. Arguments:
  171. Device - Supplies a pointer to the device context.
  172. Register - Supplies the register to write to.
  173. Value - Supplies the value to write.
  174. Return Value:
  175. None.
  176. --*/
  177. /*++
  178. Structure Description:
  179. This structure stores the common header for a 16550 object.
  180. Members:
  181. Type - Stores the serial object type.
  182. ReferenceCount - Stores the reference count on the object.
  183. --*/
  184. typedef struct _SER16550_OBJECT {
  185. SER16550_OBJECT_TYPE Type;
  186. ULONG ReferenceCount;
  187. } SER16550_OBJECT, *PSER16550_OBJECT;
  188. /*++
  189. Structure Description:
  190. This structure stores information about a 16550 parent context.
  191. Members:
  192. Header - Store the common 16550 object header.
  193. Device - Stores the OS device this device belongs to.
  194. InterruptLine - Stores the interrupt line that this controller's interrupt
  195. comes in on.
  196. InterruptVector - Stores the interrupt vector that this controller's
  197. interrupt comes in on.
  198. InterruptResourcesFound - Stores a boolean indicating whether or not the
  199. interrupt line and interrupt vector fields are valid.
  200. InterruptHandle - Stores a pointer to the handle received when the
  201. interrupt was connected.
  202. InterruptLock - Stores the spin lock synchronizing access to the pending
  203. status bits.
  204. Variant - Stores the variant type of 16550 controller.
  205. VendorId - Stores the PCI vendor ID of the device, or 0 if this was not a
  206. PCI device.
  207. DeviceId - Stores the PCI device ID of thd device.
  208. ChildObjects - Stores an array of child objects.
  209. ChildDevices - Stores an array of child devices.
  210. ChildCount - Stores the count of the number of children.
  211. RegisterShift - Stores the number of bits to shift left to get from a 16550
  212. register to an actual device register. By default this is applied to
  213. all children.
  214. BaseBaud - Stores the baud rate when the divisor is set to 1.
  215. Removed - Stores a boolean indicating that the device has been removed.
  216. --*/
  217. typedef struct _SER16550_PARENT {
  218. SER16550_OBJECT Header;
  219. PDEVICE Device;
  220. ULONGLONG InterruptLine;
  221. ULONGLONG InterruptVector;
  222. BOOL InterruptResourcesFound;
  223. HANDLE InterruptHandle;
  224. KSPIN_LOCK InterruptLock;
  225. SER16550_VARIANT Variant;
  226. USHORT VendorId;
  227. USHORT DeviceId;
  228. PSER16550_CHILD ChildObjects;
  229. PDEVICE *ChildDevices;
  230. UINTN ChildCount;
  231. ULONG RegisterShift;
  232. ULONG BaseBaud;
  233. BOOL Removed;
  234. } SER16550_PARENT, *PSER16550_PARENT;
  235. /*++
  236. Structure Description:
  237. This structure stores information about a 16550 port.
  238. Members:
  239. Header - Store the common 16550 object header.
  240. Parent - Stores a pointer to the parent structure.
  241. Read8 - Stores a pointer to a function used to perform an 8-bit register
  242. read.
  243. Write8 - Stores a pointer to a function used to perform an 8-bit register
  244. write.
  245. Index - Stores the index of this child into the parent.
  246. PhysicalAddress - Stores the base physical address of the register region,
  247. if the UART is memory mapped.
  248. MappedAddress - Stores the virtual address of the register region, if the
  249. UART is memory mapped.
  250. MappedSize - Stores the size of the mapping.
  251. IoPortAddress - Stores the I/O port address of the registers if the region
  252. is I/O port based.
  253. Terminal - Stores a pointer to the terminal device.
  254. TransmitBuffer - Stores the ring buffer of bytes waiting to be sent.
  255. TransmitStart - Stores the index of the next byte the hardware will send
  256. out.
  257. TransmitEnd - Stores the index of the next byte to be added to the buffer.
  258. TransmitSize - Stores the size of the transmit buffer in bytes.
  259. TransmitFifoSize - Stores the size of the hardware transmit FIFO in bytes.
  260. ReceiveBuffer - Stores the buffer of received bytes.
  261. ReceiveStart - Stores the index of the next byte software should read.
  262. ReceiveEnd - Stores the index of the next byte the hardware will add.
  263. ReceiveSize - Stores the size of the receive buffer in bytes.
  264. ControlFlags - Stores the currently set control flags. See
  265. TERMINAL_CONTROL_* definitions.
  266. BaudRate - Stores the currently set baud rate. This may be zero if the
  267. device is not configured.
  268. RegisterOffset - Stores the offset in bytes from the begining of the
  269. register region to the 16550ish registers.
  270. RegisterShift - Stores the number of bits to shift left to get from a 16550
  271. register to an actual device register.
  272. TransmitLock - Stores a pointer to the lock serializing access to the
  273. transmit buffer.
  274. ReceiveLock - Stores a pointer to the lock serializing access to the
  275. receive buffer.
  276. TransmitReady - Stores an event that is signaled when the UART can accept
  277. more outgoing data.
  278. ReceiveReady - Stores an event that is signaled when this receive buffer
  279. has data.
  280. InterruptWorkPending - Stores a boolean indicating that the interrupt
  281. worker needs to process this child.
  282. ShouldUnmap - Stores a boolean indicating that this child owns the mapping
  283. and should unmap it to clean up.
  284. InterruptEnable - Stores a shadow copy of the interrupt enable register.
  285. --*/
  286. struct _SER16550_CHILD {
  287. SER16550_OBJECT Header;
  288. PSER16550_PARENT Parent;
  289. PSER16550_READ8 Read8;
  290. PSER16550_WRITE8 Write8;
  291. UINTN Index;
  292. PRESOURCE_ALLOCATION Resource;
  293. PHYSICAL_ADDRESS PhysicalAddress;
  294. PVOID MappedAddress;
  295. UINTN MappedSize;
  296. USHORT IoPortAddress;
  297. PIO_HANDLE Terminal;
  298. PUCHAR TransmitBuffer;
  299. UINTN TransmitStart;
  300. UINTN TransmitEnd;
  301. UINTN TransmitSize;
  302. UINTN TransmitFifoSize;
  303. PUCHAR ReceiveBuffer;
  304. UINTN ReceiveStart;
  305. UINTN ReceiveEnd;
  306. UINTN ReceiveSize;
  307. LONG ControlFlags;
  308. ULONG BaudRate;
  309. ULONG RegisterOffset;
  310. ULONG RegisterShift;
  311. PQUEUED_LOCK TransmitLock;
  312. PQUEUED_LOCK ReceiveLock;
  313. PKEVENT TransmitReady;
  314. PKEVENT ReceiveReady;
  315. BOOL InterruptWorkPending;
  316. BOOL ShouldUnmap;
  317. UCHAR InterruptEnable;
  318. };
  319. //
  320. // ----------------------------------------------- Internal Function Prototypes
  321. //
  322. KSTATUS
  323. Ser16550AddDevice (
  324. PVOID Driver,
  325. PSTR DeviceId,
  326. PSTR ClassId,
  327. PSTR CompatibleIds,
  328. PVOID DeviceToken
  329. );
  330. VOID
  331. Ser16550DispatchStateChange (
  332. PIRP Irp,
  333. PVOID DeviceContext,
  334. PVOID IrpContext
  335. );
  336. VOID
  337. Ser16550DispatchOpen (
  338. PIRP Irp,
  339. PVOID DeviceContext,
  340. PVOID IrpContext
  341. );
  342. VOID
  343. Ser16550DispatchClose (
  344. PIRP Irp,
  345. PVOID DeviceContext,
  346. PVOID IrpContext
  347. );
  348. VOID
  349. Ser16550DispatchIo (
  350. PIRP Irp,
  351. PVOID DeviceContext,
  352. PVOID IrpContext
  353. );
  354. VOID
  355. Ser16550DispatchSystemControl (
  356. PIRP Irp,
  357. PVOID DeviceContext,
  358. PVOID IrpContext
  359. );
  360. VOID
  361. Ser16550DispatchUserControl (
  362. PIRP Irp,
  363. PVOID DeviceContext,
  364. PVOID IrpContext
  365. );
  366. INTERRUPT_STATUS
  367. Ser16550InterruptService (
  368. PVOID Context
  369. );
  370. INTERRUPT_STATUS
  371. Ser16550InterruptServiceWorker (
  372. PVOID Context
  373. );
  374. KSTATUS
  375. Ser16550pParentProcessResourceRequirements (
  376. PIRP Irp,
  377. PSER16550_PARENT Device
  378. );
  379. KSTATUS
  380. Ser16550pParentStartDevice (
  381. PIRP Irp,
  382. PSER16550_PARENT Device
  383. );
  384. KSTATUS
  385. Ser16550pInitializeChildrenGeneric (
  386. PSER16550_PARENT Parent,
  387. PRESOURCE_ALLOCATION_LIST AllocationList
  388. );
  389. KSTATUS
  390. Ser16550pInitializeChildrenOxford (
  391. PSER16550_PARENT Parent,
  392. PRESOURCE_ALLOCATION_LIST AllocationList
  393. );
  394. KSTATUS
  395. Ser16550pInitializeChild (
  396. PSER16550_PARENT Parent,
  397. UINTN Index
  398. );
  399. VOID
  400. Ser16550pParentEnumerateChildren (
  401. PIRP Irp,
  402. PSER16550_PARENT Device
  403. );
  404. VOID
  405. Ser16550pChildStartDevice (
  406. PIRP Irp,
  407. PSER16550_CHILD Device
  408. );
  409. VOID
  410. Ser16550pChildDispatchSystemControl (
  411. PIRP Irp,
  412. PSER16550_CHILD Device
  413. );
  414. VOID
  415. Ser16550pChildDispatchUserControl (
  416. PIRP Irp,
  417. PSER16550_CHILD Device
  418. );
  419. VOID
  420. Ser16550pStartTransmit (
  421. PSER16550_CHILD Device
  422. );
  423. VOID
  424. Ser16550pStopTransmit (
  425. PSER16550_CHILD Device
  426. );
  427. KSTATUS
  428. Ser16550pConfigureDevice (
  429. PSER16550_CHILD Device,
  430. ULONG TerminalControlFlags,
  431. ULONG BaudRate
  432. );
  433. ULONG
  434. Ser16550pGetFifoSize (
  435. PSER16550_CHILD Device
  436. );
  437. VOID
  438. Ser16550pAddReference (
  439. PSER16550_OBJECT Object
  440. );
  441. VOID
  442. Ser16550pReleaseReference (
  443. PSER16550_OBJECT Object
  444. );
  445. VOID
  446. Ser16550pDestroyDevice (
  447. PSER16550_OBJECT Object
  448. );
  449. UCHAR
  450. Ser16550pReadIo8 (
  451. PSER16550_CHILD Device,
  452. SER16550_REGISTER Register
  453. );
  454. VOID
  455. Ser16550pWriteIo8 (
  456. PSER16550_CHILD Device,
  457. SER16550_REGISTER Register,
  458. UCHAR Value
  459. );
  460. UCHAR
  461. Ser16550pReadMemory8 (
  462. PSER16550_CHILD Device,
  463. SER16550_REGISTER Register
  464. );
  465. VOID
  466. Ser16550pWriteMemory8 (
  467. PSER16550_CHILD Device,
  468. SER16550_REGISTER Register,
  469. UCHAR Value
  470. );
  471. //
  472. // -------------------------------------------------------------------- Globals
  473. //
  474. PDRIVER Ser16550Driver = NULL;
  475. //
  476. // ------------------------------------------------------------------ Functions
  477. //
  478. KSTATUS
  479. DriverEntry (
  480. PDRIVER Driver
  481. )
  482. /*++
  483. Routine Description:
  484. This routine is the entry point for the 16550 driver. It registers its
  485. other dispatch functions, and performs driver-wide initialization.
  486. Arguments:
  487. Driver - Supplies a pointer to the driver object.
  488. Return Value:
  489. STATUS_SUCCESS on success.
  490. Failure code on error.
  491. --*/
  492. {
  493. DRIVER_FUNCTION_TABLE FunctionTable;
  494. KSTATUS Status;
  495. Ser16550Driver = Driver;
  496. RtlZeroMemory(&FunctionTable, sizeof(DRIVER_FUNCTION_TABLE));
  497. FunctionTable.Version = DRIVER_FUNCTION_TABLE_VERSION;
  498. FunctionTable.AddDevice = Ser16550AddDevice;
  499. FunctionTable.DispatchStateChange = Ser16550DispatchStateChange;
  500. FunctionTable.DispatchOpen = Ser16550DispatchOpen;
  501. FunctionTable.DispatchClose = Ser16550DispatchClose;
  502. FunctionTable.DispatchIo = Ser16550DispatchIo;
  503. FunctionTable.DispatchSystemControl = Ser16550DispatchSystemControl;
  504. FunctionTable.DispatchUserControl = Ser16550DispatchUserControl;
  505. Status = IoRegisterDriverFunctions(Driver, &FunctionTable);
  506. return Status;
  507. }
  508. KSTATUS
  509. Ser16550AddDevice (
  510. PVOID Driver,
  511. PSTR DeviceId,
  512. PSTR ClassId,
  513. PSTR CompatibleIds,
  514. PVOID DeviceToken
  515. )
  516. /*++
  517. Routine Description:
  518. This routine is called when a device is detected for which the 16550 device
  519. acts as the function driver. The driver will attach itself to the stack.
  520. Arguments:
  521. Driver - Supplies a pointer to the driver being called.
  522. DeviceId - Supplies a pointer to a string with the device ID.
  523. ClassId - Supplies a pointer to a string containing the device's class ID.
  524. CompatibleIds - Supplies a pointer to a string containing device IDs
  525. that would be compatible with this device.
  526. DeviceToken - Supplies an opaque token that the driver can use to identify
  527. the device in the system. This token should be used when attaching to
  528. the stack.
  529. Return Value:
  530. STATUS_SUCCESS on success.
  531. Failure code if the driver was unsuccessful in attaching itself.
  532. --*/
  533. {
  534. ULONG ItemsScanned;
  535. PSER16550_PARENT Parent;
  536. ULONG PciDeviceId;
  537. ULONG PciVendorId;
  538. KSTATUS Status;
  539. Parent = MmAllocateNonPagedPool(sizeof(SER16550_PARENT),
  540. SER16550_ALLOCATION_TAG);
  541. if (Parent == NULL) {
  542. return STATUS_INSUFFICIENT_RESOURCES;
  543. }
  544. RtlZeroMemory(Parent, sizeof(SER16550_PARENT));
  545. Parent->Header.Type = Ser16550ObjectParent;
  546. Parent->Device = DeviceToken;
  547. Parent->BaseBaud = SER16550_DEFAULT_BASE_BAUD;
  548. Parent->Variant = Ser16550VariantGeneric;
  549. Parent->InterruptHandle = INVALID_HANDLE;
  550. KeInitializeSpinLock(&(Parent->InterruptLock));
  551. //
  552. // Detect variants by PCI vendor and device ID.
  553. //
  554. Status = RtlStringScan(DeviceId,
  555. -1,
  556. SER16550_PCI_DEVICE_ID_FORMAT,
  557. sizeof(SER16550_PCI_DEVICE_ID_FORMAT),
  558. CharacterEncodingDefault,
  559. &ItemsScanned,
  560. &PciVendorId,
  561. &PciDeviceId);
  562. if ((KSUCCESS(Status)) && (ItemsScanned == 2)) {
  563. Parent->VendorId = PciVendorId;
  564. Parent->DeviceId = PciDeviceId;
  565. switch (PciVendorId) {
  566. case SER16550_VENDOR_INTEL:
  567. if (PciDeviceId == SER16550_INTEL_QUARK) {
  568. Parent->Variant = Ser16550VariantQuark;
  569. Parent->RegisterShift =
  570. SER16550_INTEL_QUARK_UART_REGISTER_SHIFT;
  571. Parent->BaseBaud = SER16550_INTEL_QUARK_UART_BASE_BAUD;
  572. }
  573. break;
  574. case SER16550_VENDOR_OXFORD:
  575. Parent->Variant = Ser16550VariantOxford;
  576. break;
  577. default:
  578. break;
  579. }
  580. }
  581. Status = IoAttachDriverToDevice(Driver, DeviceToken, Parent);
  582. if (!KSUCCESS(Status)) {
  583. goto AddDeviceEnd;
  584. }
  585. AddDeviceEnd:
  586. if (!KSUCCESS(Status)) {
  587. if (Parent != NULL) {
  588. MmFreePagedPool(Parent);
  589. }
  590. }
  591. return Status;
  592. }
  593. VOID
  594. Ser16550DispatchStateChange (
  595. PIRP Irp,
  596. PVOID DeviceContext,
  597. PVOID IrpContext
  598. )
  599. /*++
  600. Routine Description:
  601. This routine handles State Change IRPs.
  602. Arguments:
  603. Irp - Supplies a pointer to the I/O request packet.
  604. DeviceContext - Supplies the context pointer supplied by the driver when it
  605. attached itself to the driver stack. Presumably this pointer contains
  606. driver-specific device context.
  607. IrpContext - Supplies the context pointer supplied by the driver when
  608. the IRP was created.
  609. Return Value:
  610. None.
  611. --*/
  612. {
  613. PSER16550_CHILD Child;
  614. PSER16550_OBJECT Object;
  615. PSER16550_PARENT Parent;
  616. KSTATUS Status;
  617. ASSERT(Irp->MajorCode == IrpMajorStateChange);
  618. if ((Irp->Direction == IrpUp) && (!KSUCCESS(IoGetIrpStatus(Irp)))) {
  619. return;
  620. }
  621. Object = DeviceContext;
  622. switch (Object->Type) {
  623. //
  624. // In this case the driver is the functional driver for the controller.
  625. //
  626. case Ser16550ObjectParent:
  627. Parent = PARENT_STRUCTURE(Object, SER16550_PARENT, Header);
  628. switch (Irp->MinorCode) {
  629. case IrpMinorQueryResources:
  630. //
  631. // On the way up, filter the resource requirements to add interrupt
  632. // vectors to any lines.
  633. //
  634. if (Irp->Direction == IrpUp) {
  635. Status = Ser16550pParentProcessResourceRequirements(Irp,
  636. Parent);
  637. if (!KSUCCESS(Status)) {
  638. IoCompleteIrp(Ser16550Driver, Irp, Status);
  639. }
  640. }
  641. break;
  642. case IrpMinorStartDevice:
  643. //
  644. // Attempt to fire the thing up if the bus has already started it.
  645. //
  646. if (Irp->Direction == IrpUp) {
  647. Status = Ser16550pParentStartDevice(Irp, Parent);
  648. if (!KSUCCESS(Status)) {
  649. IoCompleteIrp(Ser16550Driver, Irp, Status);
  650. }
  651. }
  652. break;
  653. case IrpMinorQueryChildren:
  654. if (Irp->Direction == IrpUp) {
  655. Ser16550pParentEnumerateChildren(Irp, Parent);
  656. }
  657. break;
  658. case IrpMinorRemoveDevice:
  659. Ser16550pReleaseReference(Object);
  660. IoCompleteIrp(Ser16550Driver, Irp, STATUS_SUCCESS);
  661. break;
  662. default:
  663. break;
  664. }
  665. break;
  666. //
  667. // In this case the object is the bus driver for an individual port.
  668. //
  669. case Ser16550ObjectChild:
  670. Child = PARENT_STRUCTURE(Object, SER16550_CHILD, Header);
  671. switch (Irp->MinorCode) {
  672. case IrpMinorQueryResources:
  673. IoCompleteIrp(Ser16550Driver, Irp, STATUS_SUCCESS);
  674. break;
  675. case IrpMinorStartDevice:
  676. Ser16550pChildStartDevice(Irp, Child);
  677. break;
  678. case IrpMinorQueryChildren:
  679. IoCompleteIrp(Ser16550Driver, Irp, STATUS_SUCCESS);
  680. break;
  681. case IrpMinorRemoveDevice:
  682. ASSERT(Child->Parent->Removed != FALSE);
  683. KeAcquireQueuedLock(Child->ReceiveLock);
  684. KeAcquireQueuedLock(Child->TransmitLock);
  685. if (Child->Terminal != NULL) {
  686. IoTerminalSetDevice(Child->Terminal, NULL);
  687. IoClose(Child->Terminal);
  688. Child->Terminal = NULL;
  689. }
  690. if (Child->TransmitReady != NULL) {
  691. KeSignalEvent(Child->TransmitReady, SignalOptionSignalAll);
  692. }
  693. if (Child->ReceiveReady != NULL) {
  694. KeSignalEvent(Child->ReceiveReady, SignalOptionSignalAll);
  695. }
  696. KeReleaseQueuedLock(Child->ReceiveLock);
  697. KeReleaseQueuedLock(Child->TransmitLock);
  698. Ser16550pReleaseReference(Object);
  699. IoCompleteIrp(Ser16550Driver, Irp, STATUS_SUCCESS);
  700. break;
  701. default:
  702. break;
  703. }
  704. break;
  705. default:
  706. ASSERT(FALSE);
  707. break;
  708. }
  709. return;
  710. }
  711. VOID
  712. Ser16550DispatchOpen (
  713. PIRP Irp,
  714. PVOID DeviceContext,
  715. PVOID IrpContext
  716. )
  717. /*++
  718. Routine Description:
  719. This routine handles Open IRPs.
  720. Arguments:
  721. Irp - Supplies a pointer to the I/O request packet.
  722. DeviceContext - Supplies the context pointer supplied by the driver when it
  723. attached itself to the driver stack. Presumably this pointer contains
  724. driver-specific device context.
  725. IrpContext - Supplies the context pointer supplied by the driver when
  726. the IRP was created.
  727. Return Value:
  728. None.
  729. --*/
  730. {
  731. PSER16550_OBJECT Object;
  732. Object = DeviceContext;
  733. if (Object->Type == Ser16550ObjectChild) {
  734. Ser16550pAddReference(Object);
  735. Irp->U.Open.DeviceContext =
  736. PARENT_STRUCTURE(Object, SER16550_CHILD, Header);
  737. IoCompleteIrp(Ser16550Driver, Irp, STATUS_SUCCESS);
  738. }
  739. return;
  740. }
  741. VOID
  742. Ser16550DispatchClose (
  743. PIRP Irp,
  744. PVOID DeviceContext,
  745. PVOID IrpContext
  746. )
  747. /*++
  748. Routine Description:
  749. This routine handles Close IRPs.
  750. Arguments:
  751. Irp - Supplies a pointer to the I/O request packet.
  752. DeviceContext - Supplies the context pointer supplied by the driver when it
  753. attached itself to the driver stack. Presumably this pointer contains
  754. driver-specific device context.
  755. IrpContext - Supplies the context pointer supplied by the driver when
  756. the IRP was created.
  757. Return Value:
  758. None.
  759. --*/
  760. {
  761. PSER16550_CHILD Child;
  762. Child = Irp->U.Close.DeviceContext;
  763. ASSERT(Child->Header.Type == Ser16550ObjectChild);
  764. Ser16550pReleaseReference(&(Child->Header));
  765. IoCompleteIrp(Ser16550Driver, Irp, STATUS_SUCCESS);
  766. return;
  767. }
  768. VOID
  769. Ser16550DispatchIo (
  770. PIRP Irp,
  771. PVOID DeviceContext,
  772. PVOID IrpContext
  773. )
  774. /*++
  775. Routine Description:
  776. This routine handles I/O IRPs.
  777. Arguments:
  778. Irp - Supplies a pointer to the I/O request packet.
  779. DeviceContext - Supplies the context pointer supplied by the driver when it
  780. attached itself to the driver stack. Presumably this pointer contains
  781. driver-specific device context.
  782. IrpContext - Supplies the context pointer supplied by the driver when
  783. the IRP was created.
  784. Return Value:
  785. None.
  786. --*/
  787. {
  788. UINTN BytesRemaining;
  789. PSER16550_CHILD Child;
  790. UINTN CopySize;
  791. UINTN CopyStart;
  792. PIO_BUFFER IoBuffer;
  793. UINTN IoBufferOffset;
  794. PQUEUED_LOCK Lock;
  795. UINTN Next;
  796. RUNLEVEL OldRunLevel;
  797. PSER16550_PARENT Parent;
  798. UINTN ReceiveEnd;
  799. UINTN ReceiveStart;
  800. KSTATUS Status;
  801. UINTN TransmitEnd;
  802. UINTN TransmitStart;
  803. ASSERT(Irp->Direction == IrpDown);
  804. Child = Irp->U.ReadWrite.DeviceContext;
  805. IoBuffer = Irp->U.ReadWrite.IoBuffer;
  806. IoBufferOffset = 0;
  807. BytesRemaining = Irp->U.ReadWrite.IoSizeInBytes;
  808. Parent = Child->Parent;
  809. ASSERT(Child->Header.Type == Ser16550ObjectChild);
  810. if (Irp->MinorCode == IrpMinorIoRead) {
  811. Lock = Child->ReceiveLock;
  812. } else {
  813. ASSERT(Irp->MinorCode == IrpMinorIoWrite);
  814. Lock = Child->TransmitLock;
  815. }
  816. KeAcquireQueuedLock(Lock);
  817. if (Irp->MinorCode == IrpMinorIoWrite) {
  818. while (BytesRemaining != 0) {
  819. if (Parent->Removed != FALSE) {
  820. Status = STATUS_DEVICE_NOT_CONNECTED;
  821. goto DispatchIoEnd;
  822. }
  823. TransmitEnd = Child->TransmitEnd;
  824. TransmitStart = Child->TransmitStart;
  825. if (TransmitEnd >= TransmitStart) {
  826. CopySize = Child->TransmitSize - TransmitEnd;
  827. } else {
  828. CopySize = TransmitStart - TransmitEnd;
  829. }
  830. //
  831. // If the transmit buffer is full, then wait until a byte can be
  832. // added.
  833. //
  834. if (CopySize == 0) {
  835. //
  836. // If the transmitter isn't working at all, kick off the
  837. // process.
  838. //
  839. OldRunLevel = IoRaiseToInterruptRunLevel(
  840. Parent->InterruptHandle);
  841. KeAcquireSpinLock(&(Parent->InterruptLock));
  842. Ser16550pStartTransmit(Child);
  843. KeReleaseSpinLock(&(Parent->InterruptLock));
  844. KeLowerRunLevel(OldRunLevel);
  845. KeSignalEvent(Child->TransmitReady, SignalOptionUnsignal);
  846. KeReleaseQueuedLock(Lock);
  847. KeWaitForEvent(Child->TransmitReady,
  848. FALSE,
  849. WAIT_TIME_INDEFINITE);
  850. KeAcquireQueuedLock(Lock);
  851. continue;
  852. }
  853. if (CopySize > BytesRemaining) {
  854. CopySize = BytesRemaining;
  855. }
  856. CopyStart = TransmitEnd;
  857. Next = CopyStart + CopySize;
  858. ASSERT(Next <= Child->TransmitSize);
  859. if (Next == Child->TransmitSize) {
  860. Next = 0;
  861. }
  862. if (Next == TransmitStart) {
  863. CopySize -= 1;
  864. if (Next == 0) {
  865. Next = Child->TransmitSize - 1;
  866. } else {
  867. Next -= 1;
  868. }
  869. }
  870. Status = MmCopyIoBufferData(IoBuffer,
  871. &(Child->TransmitBuffer[CopyStart]),
  872. IoBufferOffset,
  873. CopySize,
  874. FALSE);
  875. if (!KSUCCESS(Status)) {
  876. goto DispatchIoEnd;
  877. }
  878. IoBufferOffset += CopySize;
  879. BytesRemaining -= CopySize;
  880. Child->TransmitEnd = Next;
  881. }
  882. //
  883. // Kick off the transfer if needed.
  884. //
  885. OldRunLevel = IoRaiseToInterruptRunLevel(Parent->InterruptHandle);
  886. KeAcquireSpinLock(&(Parent->InterruptLock));
  887. Ser16550pStartTransmit(Child);
  888. KeReleaseSpinLock(&(Parent->InterruptLock));
  889. KeLowerRunLevel(OldRunLevel);
  890. } else {
  891. ASSERT(Irp->MinorCode == IrpMinorIoRead);
  892. while (BytesRemaining != 0) {
  893. if (Child->Parent->Removed != FALSE) {
  894. Status = STATUS_DEVICE_NOT_CONNECTED;
  895. goto DispatchIoEnd;
  896. }
  897. ReceiveEnd = Child->ReceiveEnd;
  898. ReceiveStart = Child->ReceiveStart;
  899. if (ReceiveEnd > ReceiveStart) {
  900. CopySize = ReceiveEnd - ReceiveStart;
  901. } else {
  902. CopySize = Child->ReceiveSize - ReceiveStart;
  903. }
  904. //
  905. // Handle an empty receive buffer.
  906. //
  907. if (CopySize == 0) {
  908. //
  909. // If some bytes were read in, then return them now.
  910. //
  911. if (BytesRemaining != Irp->U.ReadWrite.IoSizeInBytes) {
  912. break;
  913. }
  914. //
  915. // Block waiting for more bytes to come in.
  916. //
  917. KeSignalEvent(Child->ReceiveReady, SignalOptionUnsignal);
  918. KeReleaseQueuedLock(Lock);
  919. KeWaitForEvent(Child->ReceiveReady,
  920. FALSE,
  921. WAIT_TIME_INDEFINITE);
  922. KeAcquireQueuedLock(Lock);
  923. continue;
  924. }
  925. CopyStart = ReceiveStart;
  926. if (CopySize > BytesRemaining) {
  927. CopySize = BytesRemaining;
  928. }
  929. ASSERT((CopySize < Child->ReceiveSize) &&
  930. (CopyStart + CopySize <= Child->ReceiveSize));
  931. Status = MmCopyIoBufferData(IoBuffer,
  932. &(Child->ReceiveBuffer[CopyStart]),
  933. IoBufferOffset,
  934. CopySize,
  935. TRUE);
  936. if (!KSUCCESS(Status)) {
  937. goto DispatchIoEnd;
  938. }
  939. IoBufferOffset += CopySize;
  940. BytesRemaining -= CopySize;
  941. CopyStart += CopySize;
  942. if (CopyStart == Child->ReceiveSize) {
  943. CopyStart = 0;
  944. }
  945. Child->ReceiveStart = CopyStart;
  946. }
  947. }
  948. Status = STATUS_SUCCESS;
  949. DispatchIoEnd:
  950. KeReleaseQueuedLock(Lock);
  951. Irp->U.ReadWrite.IoBytesCompleted = Irp->U.ReadWrite.IoSizeInBytes -
  952. BytesRemaining;
  953. IoCompleteIrp(Ser16550Driver, Irp, Status);
  954. return;
  955. }
  956. VOID
  957. Ser16550DispatchSystemControl (
  958. PIRP Irp,
  959. PVOID DeviceContext,
  960. PVOID IrpContext
  961. )
  962. /*++
  963. Routine Description:
  964. This routine handles System Control IRPs.
  965. Arguments:
  966. Irp - Supplies a pointer to the I/O request packet.
  967. DeviceContext - Supplies the context pointer supplied by the driver when it
  968. attached itself to the driver stack. Presumably this pointer contains
  969. driver-specific device context.
  970. IrpContext - Supplies the context pointer supplied by the driver when
  971. the IRP was created.
  972. Return Value:
  973. None.
  974. --*/
  975. {
  976. PSER16550_CHILD Child;
  977. ASSERT(Irp->MajorCode == IrpMajorSystemControl);
  978. Child = DeviceContext;
  979. switch (Child->Header.Type) {
  980. case Ser16550ObjectParent:
  981. break;
  982. case Ser16550ObjectChild:
  983. Ser16550pChildDispatchSystemControl(Irp, Child);
  984. break;
  985. default:
  986. ASSERT(FALSE);
  987. break;
  988. }
  989. return;
  990. }
  991. VOID
  992. Ser16550DispatchUserControl (
  993. PIRP Irp,
  994. PVOID DeviceContext,
  995. PVOID IrpContext
  996. )
  997. /*++
  998. Routine Description:
  999. This routine handles User Control IRPs.
  1000. Arguments:
  1001. Irp - Supplies a pointer to the I/O request packet.
  1002. DeviceContext - Supplies the context pointer supplied by the driver when it
  1003. attached itself to the driver stack. Presumably this pointer contains
  1004. driver-specific device context.
  1005. IrpContext - Supplies the context pointer supplied by the driver when
  1006. the IRP was created.
  1007. Return Value:
  1008. None.
  1009. --*/
  1010. {
  1011. PSER16550_CHILD Child;
  1012. ASSERT(Irp->MajorCode == IrpMajorUserControl);
  1013. Child = DeviceContext;
  1014. switch (Child->Header.Type) {
  1015. case Ser16550ObjectParent:
  1016. break;
  1017. case Ser16550ObjectChild:
  1018. Ser16550pChildDispatchUserControl(Irp, Child);
  1019. break;
  1020. default:
  1021. ASSERT(FALSE);
  1022. break;
  1023. }
  1024. return;
  1025. }
  1026. INTERRUPT_STATUS
  1027. Ser16550InterruptService (
  1028. PVOID Context
  1029. )
  1030. /*++
  1031. Routine Description:
  1032. This routine implements the EHCI interrupt service routine.
  1033. Arguments:
  1034. Context - Supplies the context pointer given to the system when the
  1035. interrupt was connected. In this case, this points to the EHCI
  1036. controller.
  1037. Return Value:
  1038. Interrupt status.
  1039. --*/
  1040. {
  1041. UCHAR Byte;
  1042. PSER16550_CHILD Child;
  1043. UINTN ChildIndex;
  1044. ULONG Count;
  1045. BOOL DidSomething;
  1046. UCHAR InterruptRegister;
  1047. INTERRUPT_STATUS InterruptStatus;
  1048. UCHAR LineStatus;
  1049. UINTN Next;
  1050. PSER16550_PARENT Parent;
  1051. InterruptStatus = InterruptStatusNotClaimed;
  1052. Parent = Context;
  1053. //
  1054. // Loop over every serial port this interrupt services.
  1055. //
  1056. for (ChildIndex = 0; ChildIndex < Parent->ChildCount; ChildIndex += 1) {
  1057. Child = &(Parent->ChildObjects[ChildIndex]);
  1058. //
  1059. // Skip invalid children.
  1060. //
  1061. if (Child->Header.Type != Ser16550ObjectChild) {
  1062. continue;
  1063. }
  1064. //
  1065. // Quickly exit if the UART is not interrupting.
  1066. //
  1067. InterruptRegister = SER16550_READ8(Child, Ser16550InterruptStatus);
  1068. if ((InterruptRegister & SER16550_INTERRUPT_STATUS_NONE_PENDING) != 0) {
  1069. continue;
  1070. }
  1071. InterruptStatus = InterruptStatusClaimed;
  1072. do {
  1073. DidSomething = FALSE;
  1074. LineStatus = SER16550_READ8(Child, Ser16550LineStatus);
  1075. if ((LineStatus & SER16550_LINE_STATUS_ERROR_MASK) != 0) {
  1076. DidSomething = TRUE;
  1077. //
  1078. // TODO: Actually handle 16550 line status errors.
  1079. //
  1080. if ((LineStatus & SER16550_LINE_STATUS_OVERRUN_ERROR) != 0) {
  1081. RtlDebugPrint("16550: Overrun Error.\n");
  1082. } else if ((LineStatus &
  1083. SER16550_LINE_STATUS_PARITY_ERROR) != 0) {
  1084. RtlDebugPrint("16550: Parity Error.\n");
  1085. } else if ((LineStatus &
  1086. SER16550_LINE_STATUS_FRAMING_ERROR) != 0) {
  1087. RtlDebugPrint("16550: Framing Error.\n");
  1088. } else if ((LineStatus &
  1089. SER16550_LINE_STATUS_FIFO_ERROR) != 0) {
  1090. RtlDebugPrint("16550: Fifo Error.\n");
  1091. }
  1092. }
  1093. //
  1094. // Transmit more stuff if possible.
  1095. //
  1096. if ((LineStatus & SER16550_LINE_STATUS_TX_HOLDING_EMPTY) != 0) {
  1097. KeAcquireSpinLock(&(Child->Parent->InterruptLock));
  1098. for (Count = 0; Count < Child->TransmitFifoSize; Count += 1) {
  1099. if (Child->TransmitStart == Child->TransmitEnd) {
  1100. Ser16550pStopTransmit(Child);
  1101. break;
  1102. } else {
  1103. Byte = Child->TransmitBuffer[Child->TransmitStart];
  1104. SER16550_WRITE8(Child, Ser16550Data, Byte);
  1105. Next = Child->TransmitStart + 1;
  1106. if (Next == Child->TransmitSize) {
  1107. Next = 0;
  1108. }
  1109. Child->TransmitStart = Next;
  1110. DidSomething = TRUE;
  1111. }
  1112. }
  1113. KeReleaseSpinLock(&(Child->Parent->InterruptLock));
  1114. Child->InterruptWorkPending = TRUE;
  1115. }
  1116. //
  1117. // Receive a byte data if possible.
  1118. //
  1119. if ((LineStatus & SER16550_LINE_STATUS_RX_MASK) != 0) {
  1120. DidSomething = TRUE;
  1121. //
  1122. // TODO: Actually handle a 16550 break.
  1123. //
  1124. if ((LineStatus & SER16550_LINE_STATUS_BREAK) != 0) {
  1125. RtlDebugPrint("16550: Break\n");
  1126. } else if ((LineStatus & SER16550_LINE_STATUS_RX_READY) != 0) {
  1127. Byte = SER16550_READ8(Child, Ser16550Data);
  1128. Next = Child->ReceiveEnd + 1;
  1129. if (Next == Child->ReceiveSize) {
  1130. Next = 0;
  1131. }
  1132. if (Next == Child->ReceiveStart) {
  1133. RtlDebugPrint("Uart RX Overflow\n");
  1134. } else {
  1135. Child->ReceiveBuffer[Child->ReceiveEnd] = Byte;
  1136. Child->ReceiveEnd = Next;
  1137. }
  1138. }
  1139. }
  1140. } while (DidSomething != FALSE);
  1141. }
  1142. return InterruptStatus;
  1143. }
  1144. INTERRUPT_STATUS
  1145. Ser16550InterruptServiceWorker (
  1146. PVOID Context
  1147. )
  1148. /*++
  1149. Routine Description:
  1150. This routine processes interrupts for the 16550 UART at low level.
  1151. Arguments:
  1152. Context - Supplies a context pointer, which in this case points to the
  1153. parent controller.
  1154. Return Value:
  1155. Interrupt status.
  1156. --*/
  1157. {
  1158. UINTN BytesCompleted;
  1159. PSER16550_CHILD Child;
  1160. UINTN ChildIndex;
  1161. INTERRUPT_STATUS InterruptStatus;
  1162. PIO_BUFFER IoBuffer;
  1163. UINTN Next;
  1164. PSER16550_PARENT Parent;
  1165. UINTN ReceiveEnd;
  1166. UINTN ReceiveStart;
  1167. UINTN Size;
  1168. KSTATUS Status;
  1169. Parent = Context;
  1170. ASSERT(KeGetRunLevel() == RunLevelLow);
  1171. InterruptStatus = InterruptStatusNotClaimed;
  1172. //
  1173. // Loop over every serial port this interrupt services.
  1174. //
  1175. for (ChildIndex = 0; ChildIndex < Parent->ChildCount; ChildIndex += 1) {
  1176. Child = &(Parent->ChildObjects[ChildIndex]);
  1177. if (Child->InterruptWorkPending == FALSE) {
  1178. continue;
  1179. }
  1180. Child->InterruptWorkPending = FALSE;
  1181. InterruptStatus = InterruptStatusClaimed;
  1182. //
  1183. // Signal the transmit ready event if some data was processed by now.
  1184. //
  1185. KeAcquireQueuedLock(Child->TransmitLock);
  1186. Next = Child->TransmitEnd + 1;
  1187. if (Next == Child->TransmitSize) {
  1188. Next = 0;
  1189. }
  1190. if (Next != Child->TransmitStart) {
  1191. KeSignalEvent(Child->TransmitReady, SignalOptionSignalAll);
  1192. }
  1193. KeReleaseQueuedLock(Child->TransmitLock);
  1194. //
  1195. // If there's a terminal, feed the terminal. Otherwise, maintain the
  1196. // event.
  1197. //
  1198. KeAcquireQueuedLock(Child->ReceiveLock);
  1199. ReceiveEnd = Child->ReceiveEnd;
  1200. ReceiveStart = Child->ReceiveStart;
  1201. while (ReceiveStart != ReceiveEnd) {
  1202. if (ReceiveEnd >= ReceiveStart) {
  1203. Size = ReceiveEnd - ReceiveStart;
  1204. } else {
  1205. Size = Child->ReceiveSize - ReceiveStart;
  1206. }
  1207. Status = MmCreateIoBuffer(Child->ReceiveBuffer + ReceiveStart,
  1208. Size,
  1209. IO_BUFFER_FLAG_KERNEL_MODE_DATA,
  1210. &IoBuffer);
  1211. BytesCompleted = 0;
  1212. if (KSUCCESS(Status)) {
  1213. if (Child->Terminal != NULL) {
  1214. Status = IoWrite(Child->Terminal,
  1215. IoBuffer,
  1216. Size,
  1217. 0,
  1218. 0,
  1219. &BytesCompleted);
  1220. } else {
  1221. KeSignalEvent(Child->ReceiveReady, SignalOptionSignalAll);
  1222. }
  1223. MmFreeIoBuffer(IoBuffer);
  1224. if (!KSUCCESS(Status)) {
  1225. RtlDebugPrint("Ser16550: Failed terminal write: %x\n",
  1226. Status);
  1227. }
  1228. }
  1229. ASSERT(ReceiveStart + BytesCompleted <= Child->ReceiveSize);
  1230. ReceiveStart += BytesCompleted;
  1231. if (ReceiveStart == Child->ReceiveSize) {
  1232. ReceiveStart = 0;
  1233. }
  1234. Child->ReceiveStart = ReceiveStart;
  1235. if (BytesCompleted == 0) {
  1236. break;
  1237. }
  1238. ReceiveEnd = Child->ReceiveEnd;
  1239. ReceiveStart = Child->ReceiveStart;
  1240. }
  1241. KeReleaseQueuedLock(Child->ReceiveLock);
  1242. }
  1243. return InterruptStatus;
  1244. }
  1245. //
  1246. // --------------------------------------------------------- Internal Functions
  1247. //
  1248. KSTATUS
  1249. Ser16550pParentProcessResourceRequirements (
  1250. PIRP Irp,
  1251. PSER16550_PARENT Device
  1252. )
  1253. /*++
  1254. Routine Description:
  1255. This routine filters through the resource requirements presented by the
  1256. bus for a 16550 parent device. It adds an interrupt vector requirement for
  1257. any interrupt line requested.
  1258. Arguments:
  1259. Irp - Supplies a pointer to the I/O request packet.
  1260. Device - Supplies a pointer to this parent device.
  1261. Return Value:
  1262. Status code.
  1263. --*/
  1264. {
  1265. PRESOURCE_CONFIGURATION_LIST Requirements;
  1266. KSTATUS Status;
  1267. RESOURCE_REQUIREMENT VectorRequirement;
  1268. ASSERT((Irp->MajorCode == IrpMajorStateChange) &&
  1269. (Irp->MinorCode == IrpMinorQueryResources));
  1270. //
  1271. // Initialize a nice interrupt vector requirement in preparation.
  1272. //
  1273. RtlZeroMemory(&VectorRequirement, sizeof(RESOURCE_REQUIREMENT));
  1274. VectorRequirement.Type = ResourceTypeInterruptVector;
  1275. VectorRequirement.Minimum = 0;
  1276. VectorRequirement.Maximum = -1;
  1277. VectorRequirement.Length = 1;
  1278. Requirements = Irp->U.QueryResources.ResourceRequirements;
  1279. Status = IoCreateAndAddInterruptVectorsForLines(Requirements,
  1280. &VectorRequirement);
  1281. if (!KSUCCESS(Status)) {
  1282. goto ParentProcessResourceRequirementsEnd;
  1283. }
  1284. ParentProcessResourceRequirementsEnd:
  1285. return Status;
  1286. }
  1287. KSTATUS
  1288. Ser16550pParentStartDevice (
  1289. PIRP Irp,
  1290. PSER16550_PARENT Device
  1291. )
  1292. /*++
  1293. Routine Description:
  1294. This routine starts up the 16550 controller.
  1295. Arguments:
  1296. Irp - Supplies a pointer to the I/O request packet.
  1297. Device - Supplies a pointer to this 16550 device.
  1298. Return Value:
  1299. Status code.
  1300. --*/
  1301. {
  1302. PRESOURCE_ALLOCATION Allocation;
  1303. PRESOURCE_ALLOCATION_LIST AllocationList;
  1304. UINTN ChildCount;
  1305. IO_CONNECT_INTERRUPT_PARAMETERS Connect;
  1306. PRESOURCE_ALLOCATION LineAllocation;
  1307. KSTATUS Status;
  1308. ChildCount = 0;
  1309. //
  1310. // Loop through the allocated resources to get the interrupt and count the
  1311. // number of BARs.
  1312. //
  1313. AllocationList = Irp->U.StartDevice.ProcessorLocalResources;
  1314. Allocation = IoGetNextResourceAllocation(AllocationList, NULL);
  1315. while (Allocation != NULL) {
  1316. //
  1317. // If the resource is an interrupt vector, then it should have an
  1318. // owning interrupt line allocation.
  1319. //
  1320. if (Allocation->Type == ResourceTypeInterruptVector) {
  1321. //
  1322. // Currently only one interrupt resource is expected.
  1323. //
  1324. ASSERT(Device->InterruptResourcesFound == FALSE);
  1325. ASSERT(Allocation->OwningAllocation != NULL);
  1326. //
  1327. // Save the line and vector number.
  1328. //
  1329. LineAllocation = Allocation->OwningAllocation;
  1330. Device->InterruptLine = LineAllocation->Allocation;
  1331. Device->InterruptVector = Allocation->Allocation;
  1332. Device->InterruptResourcesFound = TRUE;
  1333. } else if (Allocation->Type == ResourceTypePhysicalAddressSpace) {
  1334. ChildCount += 1;
  1335. } else if (Allocation->Type == ResourceTypeIoPort) {
  1336. ChildCount += 1;
  1337. }
  1338. //
  1339. // Get the next allocation in the list.
  1340. //
  1341. Allocation = IoGetNextResourceAllocation(AllocationList, Allocation);
  1342. }
  1343. //
  1344. // Some variants override the child count.
  1345. //
  1346. switch (Device->Variant) {
  1347. case Ser16550VariantQuark:
  1348. ChildCount = 1;
  1349. break;
  1350. case Ser16550VariantOxford:
  1351. //
  1352. // Oxford devices just have a single UART, except for a couple
  1353. // (specified by the mode bits encoded in the device ID) that have two.
  1354. //
  1355. ASSERT(Device->VendorId == SER16550_VENDOR_OXFORD);
  1356. ChildCount = 1;
  1357. if (SER16550_OXFORD_DUAL_UARTS(Device->DeviceId) != FALSE) {
  1358. ChildCount = 2;
  1359. }
  1360. break;
  1361. default:
  1362. break;
  1363. }
  1364. if (ChildCount == 0) {
  1365. Status = STATUS_NOT_CONFIGURED;
  1366. goto ParentStartDeviceEnd;
  1367. }
  1368. //
  1369. // Allocate the child arrays.
  1370. //
  1371. if (ChildCount != Device->ChildCount) {
  1372. ASSERT(Device->ChildCount == 0);
  1373. Device->ChildDevices = MmAllocatePagedPool(ChildCount * sizeof(PDEVICE),
  1374. SER16550_ALLOCATION_TAG);
  1375. if (Device->ChildDevices == NULL) {
  1376. Status = STATUS_INSUFFICIENT_RESOURCES;
  1377. goto ParentStartDeviceEnd;
  1378. }
  1379. RtlZeroMemory(Device->ChildDevices, ChildCount * sizeof(PDEVICE));
  1380. Device->ChildObjects = MmAllocatePagedPool(
  1381. ChildCount * sizeof(SER16550_CHILD),
  1382. SER16550_ALLOCATION_TAG);
  1383. if (Device->ChildObjects == NULL) {
  1384. Status = STATUS_INSUFFICIENT_RESOURCES;
  1385. goto ParentStartDeviceEnd;
  1386. }
  1387. RtlZeroMemory(Device->ChildObjects,
  1388. ChildCount * sizeof(SER16550_CHILD));
  1389. Device->ChildCount = ChildCount;
  1390. }
  1391. //
  1392. // Initialize the child devices with their correct resources.
  1393. //
  1394. switch (Device->Variant) {
  1395. case Ser16550VariantOxford:
  1396. Status = Ser16550pInitializeChildrenOxford(Device, AllocationList);
  1397. break;
  1398. case Ser16550VariantQuark:
  1399. case Ser16550VariantGeneric:
  1400. Status = Ser16550pInitializeChildrenGeneric(Device, AllocationList);
  1401. break;
  1402. default:
  1403. ASSERT(FALSE);
  1404. Status = STATUS_INVALID_CONFIGURATION;
  1405. }
  1406. if (!KSUCCESS(Status)) {
  1407. goto ParentStartDeviceEnd;
  1408. }
  1409. //
  1410. // Attempt to connect the interrupt.
  1411. //
  1412. if ((Device->InterruptResourcesFound != FALSE) &&
  1413. (Device->InterruptHandle == INVALID_HANDLE)) {
  1414. RtlZeroMemory(&Connect, sizeof(IO_CONNECT_INTERRUPT_PARAMETERS));
  1415. Connect.Version = IO_CONNECT_INTERRUPT_PARAMETERS_VERSION;
  1416. Connect.Device = Irp->Device;
  1417. Connect.LineNumber = Device->InterruptLine;
  1418. Connect.Vector = Device->InterruptVector;
  1419. Connect.InterruptServiceRoutine = Ser16550InterruptService;
  1420. Connect.LowLevelServiceRoutine = Ser16550InterruptServiceWorker;
  1421. Connect.Context = Device;
  1422. Connect.Interrupt = &(Device->InterruptHandle);
  1423. Status = IoConnectInterrupt(&Connect);
  1424. if (!KSUCCESS(Status)) {
  1425. goto ParentStartDeviceEnd;
  1426. }
  1427. }
  1428. Status = STATUS_SUCCESS;
  1429. ParentStartDeviceEnd:
  1430. if (!KSUCCESS(Status)) {
  1431. if (Device->InterruptHandle != INVALID_HANDLE) {
  1432. IoDisconnectInterrupt(Device->InterruptHandle);
  1433. Device->InterruptHandle = INVALID_HANDLE;
  1434. }
  1435. }
  1436. return Status;
  1437. }
  1438. KSTATUS
  1439. Ser16550pInitializeChildrenGeneric (
  1440. PSER16550_PARENT Parent,
  1441. PRESOURCE_ALLOCATION_LIST AllocationList
  1442. )
  1443. /*++
  1444. Routine Description:
  1445. This routine initializes the child device structures for a standard 16550
  1446. UART device. In a standard device, each BAR is assumed to correspond to
  1447. a UART, up to the number of children.
  1448. Arguments:
  1449. Parent - Supplies a pointer to the parent.
  1450. AllocationList - Supplies a pointer to the resource allocation list.
  1451. Return Value:
  1452. Status code.
  1453. --*/
  1454. {
  1455. PRESOURCE_ALLOCATION Allocation;
  1456. UINTN ChildIndex;
  1457. PSER16550_CHILD ChildObject;
  1458. UINTN ReleaseCount;
  1459. KSTATUS Status;
  1460. Allocation = IoGetNextResourceAllocation(AllocationList, NULL);
  1461. ChildIndex = 0;
  1462. while (ChildIndex < Parent->ChildCount) {
  1463. ASSERT(Allocation != NULL);
  1464. //
  1465. // For each BAR found, initialize a child device.
  1466. //
  1467. if ((Allocation->Type == ResourceTypePhysicalAddressSpace) ||
  1468. (Allocation->Type == ResourceTypeIoPort)) {
  1469. ChildObject = &(Parent->ChildObjects[ChildIndex]);
  1470. Status = Ser16550pInitializeChild(Parent, ChildIndex);
  1471. if (!KSUCCESS(Status)) {
  1472. goto InitializeChildrenGenericEnd;
  1473. }
  1474. if (Allocation->Type == ResourceTypePhysicalAddressSpace) {
  1475. ChildObject->MappedSize = Allocation->Length;
  1476. ChildObject->PhysicalAddress = Allocation->Allocation;
  1477. ChildObject->MappedAddress = MmMapPhysicalAddress(
  1478. Allocation->Allocation,
  1479. Allocation->Length,
  1480. TRUE,
  1481. FALSE,
  1482. TRUE);
  1483. if (ChildObject->MappedAddress == NULL) {
  1484. Status = STATUS_INSUFFICIENT_RESOURCES;
  1485. goto InitializeChildrenGenericEnd;
  1486. }
  1487. ChildObject->Read8 = Ser16550pReadMemory8;
  1488. ChildObject->Write8 = Ser16550pWriteMemory8;
  1489. ChildObject->ShouldUnmap = TRUE;
  1490. } else {
  1491. ChildObject->IoPortAddress = (USHORT)(Allocation->Allocation);
  1492. ChildObject->Read8 = Ser16550pReadIo8;
  1493. ChildObject->Write8 = Ser16550pWriteIo8;
  1494. }
  1495. ChildIndex += 1;
  1496. }
  1497. //
  1498. // Get the next allocation in the list.
  1499. //
  1500. Allocation = IoGetNextResourceAllocation(AllocationList, Allocation);
  1501. }
  1502. Status = STATUS_SUCCESS;
  1503. InitializeChildrenGenericEnd:
  1504. if (!KSUCCESS(Status)) {
  1505. ASSERT(ChildIndex != Parent->ChildCount);
  1506. ReleaseCount = ChildIndex;
  1507. for (ChildIndex = 0; ChildIndex <= ReleaseCount; ChildIndex += 1) {
  1508. ASSERT(Parent->ChildObjects[ChildIndex].Header.ReferenceCount == 1);
  1509. Ser16550pReleaseReference(
  1510. &(Parent->ChildObjects[ChildIndex].Header));
  1511. }
  1512. }
  1513. return Status;
  1514. }
  1515. KSTATUS
  1516. Ser16550pInitializeChildrenOxford (
  1517. PSER16550_PARENT Parent,
  1518. PRESOURCE_ALLOCATION_LIST AllocationList
  1519. )
  1520. /*++
  1521. Routine Description:
  1522. This routine initializes the child device structures for an Oxford UART.
  1523. Arguments:
  1524. Parent - Supplies a pointer to the parent.
  1525. AllocationList - Supplies a pointer to the resource allocation list.
  1526. Return Value:
  1527. Status code.
  1528. --*/
  1529. {
  1530. PRESOURCE_ALLOCATION Allocation;
  1531. UINTN ChildIndex;
  1532. PSER16550_CHILD ChildObject;
  1533. UINTN ReleaseCount;
  1534. KSTATUS Status;
  1535. //
  1536. // Find the first BAR, which is where the single or dual UART resides.
  1537. //
  1538. Allocation = IoGetNextResourceAllocation(AllocationList, NULL);
  1539. while (Allocation != NULL) {
  1540. if ((Allocation->Type == ResourceTypePhysicalAddressSpace) ||
  1541. (Allocation->Type == ResourceTypeIoPort)) {
  1542. break;
  1543. }
  1544. //
  1545. // Get the next allocation in the list.
  1546. //
  1547. Allocation = IoGetNextResourceAllocation(AllocationList, Allocation);
  1548. }
  1549. if (Allocation == NULL) {
  1550. return STATUS_NOT_CONFIGURED;
  1551. }
  1552. //
  1553. // If the BAR is an I/O port, then this is a legacy compatible controller.
  1554. //
  1555. if (Allocation->Type == ResourceTypeIoPort) {
  1556. ChildIndex = 0;
  1557. ChildObject = &(Parent->ChildObjects[0]);
  1558. Status = Ser16550pInitializeChild(Parent, 0);
  1559. if (!KSUCCESS(Status)) {
  1560. goto InitializeChildrenGenericEnd;
  1561. }
  1562. ChildObject->IoPortAddress = (USHORT)(Allocation->Allocation);
  1563. ChildObject->Read8 = Ser16550pReadIo8;
  1564. ChildObject->Write8 = Ser16550pWriteIo8;
  1565. //
  1566. // This is a native UART.
  1567. //
  1568. } else {
  1569. Parent->BaseBaud = SER16550_OXFORD_BASE_BAUD;
  1570. for (ChildIndex = 0; ChildIndex < Parent->ChildCount; ChildIndex += 1) {
  1571. ChildObject = &(Parent->ChildObjects[ChildIndex]);
  1572. Status = Ser16550pInitializeChild(Parent, ChildIndex);
  1573. if (!KSUCCESS(Status)) {
  1574. goto InitializeChildrenGenericEnd;
  1575. }
  1576. ChildObject->MappedSize = Allocation->Length;
  1577. ChildObject->PhysicalAddress = Allocation->Allocation;
  1578. if (ChildIndex == 0) {
  1579. ChildObject->MappedAddress = MmMapPhysicalAddress(
  1580. Allocation->Allocation,
  1581. Allocation->Length,
  1582. TRUE,
  1583. FALSE,
  1584. TRUE);
  1585. if (ChildObject->MappedAddress == NULL) {
  1586. Status = STATUS_INSUFFICIENT_RESOURCES;
  1587. goto InitializeChildrenGenericEnd;
  1588. }
  1589. ChildObject->ShouldUnmap = TRUE;
  1590. } else {
  1591. ChildObject->MappedAddress =
  1592. Parent->ChildObjects[0].MappedAddress;
  1593. }
  1594. ChildObject->RegisterOffset = SER16550_OXFORD_UART_OFFSET +
  1595. (ChildIndex *
  1596. SER16550_OXFORD_UART_STRIDE);
  1597. ChildObject->Read8 = Ser16550pReadMemory8;
  1598. ChildObject->Write8 = Ser16550pWriteMemory8;
  1599. }
  1600. }
  1601. Status = STATUS_SUCCESS;
  1602. InitializeChildrenGenericEnd:
  1603. if (!KSUCCESS(Status)) {
  1604. ASSERT(ChildIndex != Parent->ChildCount);
  1605. ReleaseCount = ChildIndex;
  1606. for (ChildIndex = 0; ChildIndex <= ReleaseCount; ChildIndex += 1) {
  1607. ASSERT(Parent->ChildObjects[ChildIndex].Header.ReferenceCount == 1);
  1608. Ser16550pReleaseReference(
  1609. &(Parent->ChildObjects[ChildIndex].Header));
  1610. }
  1611. }
  1612. return Status;
  1613. }
  1614. KSTATUS
  1615. Ser16550pInitializeChild (
  1616. PSER16550_PARENT Parent,
  1617. UINTN Index
  1618. )
  1619. /*++
  1620. Routine Description:
  1621. This routine creates the resources associated with a 16550 UART child.
  1622. Arguments:
  1623. Parent - Supplies a pointer to the parent.
  1624. Index - Supplies the child index within the parent.
  1625. Return Value:
  1626. Status code.
  1627. --*/
  1628. {
  1629. PSER16550_CHILD ChildObject;
  1630. KSTATUS Status;
  1631. ChildObject = &(Parent->ChildObjects[Index]);
  1632. ChildObject->Header.Type = Ser16550ObjectChild;
  1633. ChildObject->Header.ReferenceCount = 1;
  1634. ChildObject->Parent = Parent;
  1635. ChildObject->Index = Index;
  1636. ChildObject->RegisterOffset = 0;
  1637. ChildObject->RegisterShift = Parent->RegisterShift;
  1638. if (ChildObject->TransmitBuffer == NULL) {
  1639. ChildObject->TransmitBuffer = MmAllocateNonPagedPool(
  1640. SER16550_DEFAULT_BUFFER_SIZE,
  1641. SER16550_ALLOCATION_TAG);
  1642. if (ChildObject->TransmitBuffer == NULL) {
  1643. Status = STATUS_INSUFFICIENT_RESOURCES;
  1644. goto InitializeChildEnd;
  1645. }
  1646. ChildObject->TransmitSize = SER16550_DEFAULT_BUFFER_SIZE;
  1647. ChildObject->TransmitStart = 0;
  1648. ChildObject->TransmitEnd = 0;
  1649. }
  1650. if (ChildObject->ReceiveBuffer == NULL) {
  1651. ChildObject->ReceiveBuffer = MmAllocateNonPagedPool(
  1652. SER16550_DEFAULT_BUFFER_SIZE,
  1653. SER16550_ALLOCATION_TAG);
  1654. if (ChildObject->ReceiveBuffer == NULL) {
  1655. Status = STATUS_INSUFFICIENT_RESOURCES;
  1656. goto InitializeChildEnd;
  1657. }
  1658. ChildObject->ReceiveSize = SER16550_DEFAULT_BUFFER_SIZE;
  1659. ChildObject->ReceiveStart = 0;
  1660. ChildObject->ReceiveEnd = 0;
  1661. }
  1662. if (ChildObject->TransmitLock == NULL) {
  1663. ChildObject->TransmitLock = KeCreateQueuedLock();
  1664. if (ChildObject->TransmitLock == NULL) {
  1665. Status = STATUS_INSUFFICIENT_RESOURCES;
  1666. goto InitializeChildEnd;
  1667. }
  1668. }
  1669. if (ChildObject->ReceiveLock == NULL) {
  1670. ChildObject->ReceiveLock = KeCreateQueuedLock();
  1671. if (ChildObject->ReceiveLock == NULL) {
  1672. Status = STATUS_INSUFFICIENT_RESOURCES;
  1673. goto InitializeChildEnd;
  1674. }
  1675. }
  1676. if (ChildObject->TransmitReady == NULL) {
  1677. ChildObject->TransmitReady = KeCreateEvent(NULL);
  1678. if (ChildObject->TransmitReady == NULL) {
  1679. Status = STATUS_INSUFFICIENT_RESOURCES;
  1680. goto InitializeChildEnd;
  1681. }
  1682. KeSignalEvent(ChildObject->TransmitReady,
  1683. SignalOptionSignalAll);
  1684. }
  1685. if (ChildObject->ReceiveReady == NULL) {
  1686. ChildObject->ReceiveReady = KeCreateEvent(NULL);
  1687. if (ChildObject->ReceiveReady == NULL) {
  1688. Status = STATUS_INSUFFICIENT_RESOURCES;
  1689. goto InitializeChildEnd;
  1690. }
  1691. }
  1692. Status = STATUS_SUCCESS;
  1693. InitializeChildEnd:
  1694. return Status;
  1695. }
  1696. VOID
  1697. Ser16550pParentEnumerateChildren (
  1698. PIRP Irp,
  1699. PSER16550_PARENT Device
  1700. )
  1701. /*++
  1702. Routine Description:
  1703. This routine enumerates all ports in the serial controller.
  1704. Arguments:
  1705. Irp - Supplies a pointer to the I/O request packet.
  1706. Device - Supplies a pointer to this 16550 device.
  1707. Return Value:
  1708. None.
  1709. --*/
  1710. {
  1711. UINTN ChildIndex;
  1712. CHAR DeviceId[SERIAL_PORT_DEVICE_ID_SIZE];
  1713. KSTATUS Status;
  1714. //
  1715. // Create child devices for each child.
  1716. //
  1717. for (ChildIndex = 0; ChildIndex < Device->ChildCount; ChildIndex += 1) {
  1718. ASSERT(Device->ChildObjects[ChildIndex].Header.Type ==
  1719. Ser16550ObjectChild);
  1720. if (Device->ChildDevices[ChildIndex] == NULL) {
  1721. RtlPrintToString(DeviceId,
  1722. SERIAL_PORT_DEVICE_ID_SIZE,
  1723. CharacterEncodingDefault,
  1724. SERIAL_PORT_DEVICE_ID_FORMAT,
  1725. ChildIndex);
  1726. Status = IoCreateDevice(Ser16550Driver,
  1727. &(Device->ChildObjects[ChildIndex]),
  1728. Device->Device,
  1729. DeviceId,
  1730. CHARACTER_CLASS_ID,
  1731. NULL,
  1732. &(Device->ChildDevices[ChildIndex]));
  1733. if (!KSUCCESS(Status)) {
  1734. goto ParentEnumerateChildrenEnd;
  1735. }
  1736. }
  1737. }
  1738. Status = IoMergeChildArrays(Irp,
  1739. Device->ChildDevices,
  1740. Device->ChildCount,
  1741. SER16550_ALLOCATION_TAG);
  1742. if (!KSUCCESS(Status)) {
  1743. goto ParentEnumerateChildrenEnd;
  1744. }
  1745. ParentEnumerateChildrenEnd:
  1746. IoCompleteIrp(Ser16550Driver, Irp, Status);
  1747. return;
  1748. }
  1749. VOID
  1750. Ser16550pChildStartDevice (
  1751. PIRP Irp,
  1752. PSER16550_CHILD Device
  1753. )
  1754. /*++
  1755. Routine Description:
  1756. This routine starts an individual 16550serial port.
  1757. Arguments:
  1758. Irp - Supplies a pointer to the I/O request packet.
  1759. Device - Supplies a pointer to this 16550 device.
  1760. Return Value:
  1761. None.
  1762. --*/
  1763. {
  1764. PIO_HANDLE DeviceHandle;
  1765. PDEBUG_HANDOFF_DATA HandoffData;
  1766. KSTATUS Status;
  1767. DeviceHandle = NULL;
  1768. //
  1769. // Determine if this UART is being used by the kernel debug transport, and
  1770. // fail to start up if it is (as the kernel debugger owns it).
  1771. //
  1772. Status = KdGetDeviceInformation(&HandoffData);
  1773. if ((KSUCCESS(Status)) &&
  1774. (HandoffData != NULL) &&
  1775. (HandoffData->PortType == DEBUG_PORT_TYPE_SERIAL) &&
  1776. ((HandoffData->PortSubType == DEBUG_PORT_SERIAL_16550) ||
  1777. (HandoffData->PortSubType == DEBUG_PORT_SERIAL_16550_COMPATIBLE))) {
  1778. if (HandoffData->Identifier == Device->PhysicalAddress) {
  1779. Status = STATUS_RESOURCE_IN_USE;
  1780. goto ChildStartDeviceEnd;
  1781. }
  1782. }
  1783. //
  1784. // Create the terminal object.
  1785. //
  1786. if (Device->Terminal == NULL) {
  1787. Status = IoCreateTerminal(TRUE,
  1788. NULL,
  1789. NULL,
  1790. NULL,
  1791. 0,
  1792. NULL,
  1793. 0,
  1794. IO_ACCESS_READ | IO_ACCESS_WRITE,
  1795. OPEN_FLAG_NO_CONTROLLING_TERMINAL,
  1796. TERMINAL_DEFAULT_PERMISSIONS,
  1797. TERMINAL_DEFAULT_PERMISSIONS,
  1798. &(Device->Terminal));
  1799. if (!KSUCCESS(Status)) {
  1800. goto ChildStartDeviceEnd;
  1801. }
  1802. //
  1803. // Open a handle to this very device.
  1804. //
  1805. Status = IoOpenDevice(Irp->Device,
  1806. IO_ACCESS_READ | IO_ACCESS_WRITE,
  1807. 0,
  1808. &DeviceHandle,
  1809. NULL,
  1810. NULL,
  1811. NULL);
  1812. if (!KSUCCESS(Status)) {
  1813. goto ChildStartDeviceEnd;
  1814. }
  1815. //
  1816. // Associate the hardware device with the terminal. The terminal now
  1817. // owns the handle.
  1818. //
  1819. Status = IoTerminalSetDevice(Device->Terminal, DeviceHandle);
  1820. if (!KSUCCESS(Status)) {
  1821. goto ChildStartDeviceEnd;
  1822. }
  1823. DeviceHandle = NULL;
  1824. }
  1825. Status = STATUS_SUCCESS;
  1826. ChildStartDeviceEnd:
  1827. if (DeviceHandle != NULL) {
  1828. IoClose(DeviceHandle);
  1829. }
  1830. if (!KSUCCESS(Status)) {
  1831. if (Device->Terminal != NULL) {
  1832. IoClose(Device->Terminal);
  1833. Device->Terminal = NULL;
  1834. }
  1835. }
  1836. IoCompleteIrp(Ser16550Driver, Irp, Status);
  1837. return;
  1838. }
  1839. VOID
  1840. Ser16550pChildDispatchSystemControl (
  1841. PIRP Irp,
  1842. PSER16550_CHILD Device
  1843. )
  1844. /*++
  1845. Routine Description:
  1846. This routine handles system control IRPs for the 16550 child device.
  1847. Arguments:
  1848. Irp - Supplies a pointer to the I/O request packet.
  1849. Device - Supplies a pointer to this 16550 device.
  1850. Return Value:
  1851. None. The IRP will be completed appropriately.
  1852. --*/
  1853. {
  1854. PVOID Context;
  1855. PSYSTEM_CONTROL_FILE_OPERATION FileOperation;
  1856. PSYSTEM_CONTROL_LOOKUP Lookup;
  1857. PFILE_PROPERTIES Properties;
  1858. ULONGLONG PropertiesFileSize;
  1859. KSTATUS Status;
  1860. Context = Irp->U.SystemControl.SystemContext;
  1861. switch (Irp->MinorCode) {
  1862. case IrpMinorSystemControlLookup:
  1863. Lookup = (PSYSTEM_CONTROL_LOOKUP)Context;
  1864. Status = STATUS_PATH_NOT_FOUND;
  1865. if (Lookup->Root != FALSE) {
  1866. //
  1867. // Enable opening of the root as a character device.
  1868. //
  1869. Properties = &(Lookup->Properties);
  1870. Properties->FileId = 0;
  1871. Properties->Type = IoObjectCharacterDevice;
  1872. Properties->HardLinkCount = 1;
  1873. Properties->BlockSize = 0;
  1874. Properties->BlockCount = 0;
  1875. WRITE_INT64_SYNC(&(Properties->FileSize), 0);
  1876. Status = STATUS_SUCCESS;
  1877. }
  1878. IoCompleteIrp(Ser16550Driver, Irp, Status);
  1879. break;
  1880. //
  1881. // Fail if the properties being written are different.
  1882. //
  1883. case IrpMinorSystemControlWriteFileProperties:
  1884. FileOperation = (PSYSTEM_CONTROL_FILE_OPERATION)Context;
  1885. Properties = FileOperation->FileProperties;
  1886. READ_INT64_SYNC(&(Properties->FileSize), &PropertiesFileSize);
  1887. if ((Properties->FileId != 0) ||
  1888. (Properties->Type != IoObjectCharacterDevice) ||
  1889. (Properties->HardLinkCount != 1) ||
  1890. (Properties->BlockSize != 0) ||
  1891. (Properties->BlockCount != 0) ||
  1892. (PropertiesFileSize != 0)) {
  1893. Status = STATUS_NOT_SUPPORTED;
  1894. } else {
  1895. Status = STATUS_SUCCESS;
  1896. }
  1897. IoCompleteIrp(Ser16550Driver, Irp, Status);
  1898. break;
  1899. //
  1900. // Do not support hard disk device truncation.
  1901. //
  1902. case IrpMinorSystemControlTruncate:
  1903. IoCompleteIrp(Ser16550Driver, Irp, STATUS_NOT_SUPPORTED);
  1904. break;
  1905. //
  1906. // Gather and return device information.
  1907. //
  1908. case IrpMinorSystemControlDeviceInformation:
  1909. break;
  1910. //
  1911. // Send all pending output data.
  1912. // TODO: Wait for all pending output data to be complete.
  1913. //
  1914. case IrpMinorSystemControlSynchronize:
  1915. Status = STATUS_SUCCESS;
  1916. IoCompleteIrp(Ser16550Driver, Irp, Status);
  1917. break;
  1918. //
  1919. // Ignore everything unrecognized.
  1920. //
  1921. default:
  1922. break;
  1923. }
  1924. return;
  1925. }
  1926. VOID
  1927. Ser16550pChildDispatchUserControl (
  1928. PIRP Irp,
  1929. PSER16550_CHILD Device
  1930. )
  1931. /*++
  1932. Routine Description:
  1933. This routine handles user control IRPs for the 16550 child device.
  1934. Arguments:
  1935. Irp - Supplies a pointer to the I/O request packet.
  1936. Device - Supplies a pointer to this 16550 device.
  1937. Return Value:
  1938. None. The IRP will be completed appropriately.
  1939. --*/
  1940. {
  1941. TERMINAL_USER_CONTROL_CODE ControlCode;
  1942. KSTATUS Status;
  1943. TERMINAL_SETTINGS TerminalSettings;
  1944. TERMINAL_SETTINGS_OLD TerminalSettingsOld;
  1945. Status = STATUS_NOT_HANDLED;
  1946. ControlCode = Irp->MinorCode;
  1947. switch (ControlCode) {
  1948. case TerminalControlSetAttributesFlush:
  1949. //
  1950. // Flush the input.
  1951. //
  1952. Device->ReceiveStart = Device->ReceiveEnd;
  1953. //
  1954. // Fall through.
  1955. //
  1956. case TerminalControlSetAttributesDrain:
  1957. //
  1958. // TODO: Flush the output.
  1959. //
  1960. //
  1961. // Fall through.
  1962. //
  1963. case TerminalControlSetAttributes:
  1964. if (Irp->U.UserControl.FromKernelMode != FALSE) {
  1965. RtlCopyMemory(&TerminalSettings,
  1966. Irp->U.UserControl.UserBuffer,
  1967. sizeof(TERMINAL_SETTINGS));
  1968. Status = STATUS_SUCCESS;
  1969. } else {
  1970. Status = MmCopyFromUserMode(&TerminalSettings,
  1971. Irp->U.UserControl.UserBuffer,
  1972. sizeof(TERMINAL_SETTINGS));
  1973. if (!KSUCCESS(Status)) {
  1974. break;
  1975. }
  1976. }
  1977. if (TerminalSettings.InputSpeed != TerminalSettings.OutputSpeed) {
  1978. Status = STATUS_NOT_SUPPORTED;
  1979. break;
  1980. }
  1981. if ((TerminalSettings.ControlFlags != Device->ControlFlags) ||
  1982. (TerminalSettings.OutputSpeed != Device->BaudRate)) {
  1983. Status = Ser16550pConfigureDevice(Device,
  1984. TerminalSettings.ControlFlags,
  1985. TerminalSettings.OutputSpeed);
  1986. if (!KSUCCESS(Status)) {
  1987. break;
  1988. }
  1989. Device->ControlFlags = TerminalSettings.ControlFlags;
  1990. Device->BaudRate = TerminalSettings.OutputSpeed;
  1991. }
  1992. break;
  1993. case TerminalControlSetAttributesFlushOld:
  1994. //
  1995. // Flush the input.
  1996. //
  1997. Device->ReceiveStart = Device->ReceiveEnd;
  1998. //
  1999. // Fall through.
  2000. //
  2001. case TerminalControlSetAttributesDrainOld:
  2002. //
  2003. // TODO: Flush the output.
  2004. //
  2005. //
  2006. // Fall through.
  2007. //
  2008. case TerminalControlSetAttributesOld:
  2009. if (Irp->U.UserControl.FromKernelMode != FALSE) {
  2010. RtlCopyMemory(&TerminalSettingsOld,
  2011. Irp->U.UserControl.UserBuffer,
  2012. sizeof(TERMINAL_SETTINGS_OLD));
  2013. Status = STATUS_SUCCESS;
  2014. } else {
  2015. Status = MmCopyFromUserMode(&TerminalSettingsOld,
  2016. Irp->U.UserControl.UserBuffer,
  2017. sizeof(TERMINAL_SETTINGS_OLD));
  2018. if (!KSUCCESS(Status)) {
  2019. break;
  2020. }
  2021. }
  2022. if (TerminalSettingsOld.ControlFlags != Device->ControlFlags) {
  2023. Status = Ser16550pConfigureDevice(Device,
  2024. TerminalSettingsOld.ControlFlags,
  2025. Device->BaudRate);
  2026. if (!KSUCCESS(Status)) {
  2027. break;
  2028. }
  2029. Device->ControlFlags = TerminalSettingsOld.ControlFlags;
  2030. }
  2031. break;
  2032. case TerminalControlSendBreak:
  2033. //
  2034. // TODO: Send a serial break.
  2035. //
  2036. break;
  2037. case TerminalControlFlowControl:
  2038. //
  2039. // TODO: Handle serial flow control.
  2040. //
  2041. break;
  2042. case TerminalControlFlush:
  2043. //
  2044. // TODO: Handle serial flush.
  2045. //
  2046. break;
  2047. case TerminalControlGetModemStatus:
  2048. //
  2049. // TODO: Get serial modem status.
  2050. //
  2051. break;
  2052. case TerminalControlOrModemStatus:
  2053. //
  2054. // TODO: Get serial control/modem status.
  2055. //
  2056. break;
  2057. case TerminalControlClearModemStatus:
  2058. //
  2059. // TODO: Clear serial modem status.
  2060. //
  2061. break;
  2062. case TerminalControlSetModemStatus:
  2063. //
  2064. // TODO: Set serial modem status.
  2065. //
  2066. break;
  2067. case TerminalControlGetSoftCarrier:
  2068. case TerminalControlSetSoftCarrier:
  2069. //
  2070. // TODO: Get/set serial soft carrier status.
  2071. //
  2072. break;
  2073. case TerminalControlSendBreakPosix:
  2074. case TerminalControlStartBreak:
  2075. case TerminalControlStopBreak:
  2076. //
  2077. // TODO: Send a serial break.
  2078. //
  2079. Status = STATUS_SUCCESS;
  2080. break;
  2081. case TerminalControlGetAttributes:
  2082. case TerminalControlGetAttributesOld:
  2083. case TerminalControlSetExclusive:
  2084. case TerminalControlClearExclusive:
  2085. case TerminalControlGetOutputQueueSize:
  2086. case TerminalControlGetInputQueueSize:
  2087. case TerminalControlInsertInInputQueue:
  2088. case TerminalControlGetWindowSize:
  2089. case TerminalControlSetWindowSize:
  2090. case TerminalControlRedirectLocalConsole:
  2091. case TerminalControlSetPacketMode:
  2092. case TerminalControlGiveUpControllingTerminal:
  2093. case TerminalControlSetControllingTerminal:
  2094. case TerminalControlGetProcessGroup:
  2095. case TerminalControlSetProcessGroup:
  2096. case TerminalControlGetCurrentSessionId:
  2097. default:
  2098. break;
  2099. }
  2100. if (Status != STATUS_NOT_HANDLED) {
  2101. IoCompleteIrp(Ser16550Driver, Irp, Status);
  2102. }
  2103. return;
  2104. }
  2105. VOID
  2106. Ser16550pStartTransmit (
  2107. PSER16550_CHILD Device
  2108. )
  2109. /*++
  2110. Routine Description:
  2111. This routine starts transmission on the 16550 device.
  2112. Arguments:
  2113. Device - Supplies a pointer to the device.
  2114. Return Value:
  2115. None.
  2116. --*/
  2117. {
  2118. if ((Device->InterruptEnable & SER16550_INTERRUPT_ENABLE_TX_EMPTY) == 0) {
  2119. Device->InterruptEnable |= SER16550_INTERRUPT_ENABLE_TX_EMPTY;
  2120. SER16550_WRITE8(Device,
  2121. Ser16550InterruptEnable,
  2122. Device->InterruptEnable);
  2123. }
  2124. return;
  2125. }
  2126. VOID
  2127. Ser16550pStopTransmit (
  2128. PSER16550_CHILD Device
  2129. )
  2130. /*++
  2131. Routine Description:
  2132. This routine stops transmission on the 16550 device.
  2133. Arguments:
  2134. Device - Supplies a pointer to the device.
  2135. Return Value:
  2136. None.
  2137. --*/
  2138. {
  2139. if ((Device->InterruptEnable & SER16550_INTERRUPT_ENABLE_TX_EMPTY) != 0) {
  2140. Device->InterruptEnable &= ~SER16550_INTERRUPT_ENABLE_TX_EMPTY;
  2141. SER16550_WRITE8(Device,
  2142. Ser16550InterruptEnable,
  2143. Device->InterruptEnable);
  2144. }
  2145. return;
  2146. }
  2147. KSTATUS
  2148. Ser16550pConfigureDevice (
  2149. PSER16550_CHILD Device,
  2150. ULONG TerminalControlFlags,
  2151. ULONG BaudRate
  2152. )
  2153. /*++
  2154. Routine Description:
  2155. This routine configures the serial device, including baud rate, data bits,
  2156. stop bits, and parity.
  2157. Arguments:
  2158. Device - Supplies a pointer to the device.
  2159. TerminalControlFlags - Supplies the bitfield of terminal control flags
  2160. governing parity, data width, and stop bits. See TERMINAL_CONTROL_*
  2161. definitions.
  2162. BaudRate - Supplies the requested baud rate.
  2163. Return Value:
  2164. Status code.
  2165. --*/
  2166. {
  2167. ULONG CurrentBaud;
  2168. ULONG Divisor;
  2169. UCHAR Value;
  2170. //
  2171. // Compute the appropriate divisor.
  2172. //
  2173. Divisor = 1;
  2174. if (BaudRate > Device->Parent->BaseBaud) {
  2175. return STATUS_NOT_SUPPORTED;
  2176. }
  2177. Divisor = 1;
  2178. while (TRUE) {
  2179. CurrentBaud = Device->Parent->BaseBaud / Divisor;
  2180. if ((CurrentBaud <= BaudRate) || (CurrentBaud == 0)) {
  2181. break;
  2182. }
  2183. Divisor += 1;
  2184. }
  2185. if ((CurrentBaud == 0) || (Divisor > MAX_USHORT)) {
  2186. return STATUS_NOT_SUPPORTED;
  2187. }
  2188. //
  2189. // Disable all interrupts.
  2190. //
  2191. Device->InterruptEnable = 0;
  2192. SER16550_WRITE8(Device, Ser16550InterruptEnable, Device->InterruptEnable);
  2193. //
  2194. // Set the divisor latch enable bit to get at the divisor registers.
  2195. //
  2196. Value = SER16550_LINE_CONTROL_DIVISOR_LATCH;
  2197. SER16550_WRITE8(Device, Ser16550LineControl, Value);
  2198. //
  2199. // Write the computed divisor value.
  2200. //
  2201. SER16550_WRITE8(Device, Ser16550DivisorLow, (UCHAR)(Divisor & 0x00FF));
  2202. SER16550_WRITE8(Device,
  2203. Ser16550DivisorHigh,
  2204. (UCHAR)((Divisor >> 8) & 0x00FF));
  2205. //
  2206. // Enable the FIFOs.
  2207. //
  2208. SER16550_WRITE8(Device, Ser16550LineControl, 0);
  2209. Value = SER16550_FIFO_CONTROL_ENABLE;
  2210. SER16550_WRITE8(Device, Ser16550FifoControl, Value);
  2211. //
  2212. // Figure out the appropriate line control register value.
  2213. //
  2214. Value = 0;
  2215. switch (TerminalControlFlags & TERMINAL_CONTROL_CHARACTER_SIZE_MASK) {
  2216. case TERMINAL_CONTROL_5_BITS_PER_CHARACTER:
  2217. Value |= SER16550_LINE_CONTROL_5_DATA_BITS;
  2218. break;
  2219. case TERMINAL_CONTROL_6_BITS_PER_CHARACTER:
  2220. Value |= SER16550_LINE_CONTROL_6_DATA_BITS;
  2221. break;
  2222. case TERMINAL_CONTROL_7_BITS_PER_CHARACTER:
  2223. Value |= SER16550_LINE_CONTROL_7_DATA_BITS;
  2224. break;
  2225. case TERMINAL_CONTROL_8_BITS_PER_CHARACTER:
  2226. Value |= SER16550_LINE_CONTROL_8_DATA_BITS;
  2227. break;
  2228. default:
  2229. return STATUS_NOT_SUPPORTED;
  2230. }
  2231. if ((TerminalControlFlags & TERMINAL_CONTROL_2_STOP_BITS) != 0) {
  2232. Value |= SER16550_LINE_CONTROL_2_STOP_BITS;
  2233. }
  2234. if ((TerminalControlFlags & TERMINAL_CONTROL_ENABLE_PARITY) != 0) {
  2235. Value |= SER16550_LINE_CONTROL_PARITY_ENABLE |
  2236. SER16550_LINE_CONTROL_SET_PARITY;
  2237. if ((TerminalControlFlags & TERMINAL_CONTROL_ODD_PARITY) == 0) {
  2238. Value |= SER16550_LINE_CONTROL_EVEN_PARITY;
  2239. }
  2240. }
  2241. //
  2242. // Write the line control, which also flips the divisor registers back to
  2243. // their normal registers.
  2244. //
  2245. SER16550_WRITE8(Device, Ser16550LineControl, Value);
  2246. //
  2247. // Initialize the modem control register, which includes flow control
  2248. // (currently disabled).
  2249. //
  2250. Value = 0;
  2251. SER16550_WRITE8(Device, Ser16550ModemControl, Value);
  2252. //
  2253. // Initialize the FIFO size.
  2254. //
  2255. Device->TransmitFifoSize = Ser16550pGetFifoSize(Device);
  2256. //
  2257. // Enable interrupts.
  2258. //
  2259. Device->InterruptEnable = SER16550_INTERRUPT_ENABLE_RX_DATA |
  2260. SER16550_INTERRUPT_ENABLE_RX_STATUS;
  2261. SER16550_WRITE8(Device, Ser16550InterruptEnable, Device->InterruptEnable);
  2262. return STATUS_SUCCESS;
  2263. }
  2264. ULONG
  2265. Ser16550pGetFifoSize (
  2266. PSER16550_CHILD Device
  2267. )
  2268. /*++
  2269. Routine Description:
  2270. This routine determines the size of the serial port FIFO.
  2271. Arguments:
  2272. Device - Supplies a pointer to the device.
  2273. Return Value:
  2274. Returns the FIFO size.
  2275. --*/
  2276. {
  2277. UCHAR DivisorHigh;
  2278. UCHAR DivisorLow;
  2279. ULONG Index;
  2280. UCHAR LineControl;
  2281. UCHAR ModemControl;
  2282. UCHAR Value;
  2283. LineControl = SER16550_READ8(Device, Ser16550LineControl);
  2284. SER16550_WRITE8(Device, Ser16550LineControl, 0);
  2285. ModemControl = SER16550_READ8(Device, Ser16550ModemControl);
  2286. Value = SER16550_FIFO_CONTROL_ENABLE |
  2287. SER16550_FIFO_CONTROL_CLEAR_TRANSMIT |
  2288. SER16550_FIFO_CONTROL_CLEAR_RECEIVE;
  2289. SER16550_WRITE8(Device, Ser16550FifoControl, Value);
  2290. SER16550_WRITE8(Device,
  2291. Ser16550ModemControl,
  2292. SER16550_MODEM_CONTROL_LOOPBACK);
  2293. Value = SER16550_LINE_CONTROL_DIVISOR_LATCH;
  2294. SER16550_WRITE8(Device, Ser16550LineControl, Value);
  2295. DivisorLow = SER16550_READ8(Device, Ser16550DivisorLow);
  2296. DivisorHigh = SER16550_READ8(Device, Ser16550DivisorHigh);
  2297. SER16550_WRITE8(Device, Ser16550DivisorLow, 1);
  2298. SER16550_WRITE8(Device, Ser16550DivisorHigh, 0);
  2299. Value = SER16550_LINE_CONTROL_8_DATA_BITS;
  2300. SER16550_WRITE8(Device, Ser16550LineControl, Value);
  2301. for (Index = 0; Index < SER16550_MAX_FIFO; Index += 1) {
  2302. SER16550_WRITE8(Device, Ser16550Data, Index);
  2303. }
  2304. KeDelayExecution(FALSE, FALSE, 10 * MICROSECONDS_PER_MILLISECOND);
  2305. for (Index = 0; Index < SER16550_MAX_FIFO; Index += 1) {
  2306. if ((SER16550_READ8(Device, Ser16550LineStatus) &
  2307. SER16550_LINE_STATUS_RX_READY) == 0) {
  2308. break;
  2309. }
  2310. SER16550_READ8(Device, Ser16550Data);
  2311. }
  2312. SER16550_WRITE8(Device, Ser16550ModemControl, ModemControl);
  2313. Value = SER16550_LINE_CONTROL_DIVISOR_LATCH;
  2314. SER16550_WRITE8(Device, Ser16550LineControl, Value);
  2315. SER16550_WRITE8(Device, Ser16550DivisorLow, DivisorLow);
  2316. SER16550_WRITE8(Device, Ser16550DivisorHigh, DivisorHigh);
  2317. SER16550_WRITE8(Device, Ser16550LineControl, LineControl);
  2318. return Index;
  2319. }
  2320. VOID
  2321. Ser16550pAddReference (
  2322. PSER16550_OBJECT Object
  2323. )
  2324. /*++
  2325. Routine Description:
  2326. This routine adds a reference on the given 16550 context.
  2327. Arguments:
  2328. Object - Supplies a pointer to the 16550 object.
  2329. Return Value:
  2330. None.
  2331. --*/
  2332. {
  2333. ULONG OldReferenceCount;
  2334. OldReferenceCount = RtlAtomicAdd32(&(Object->ReferenceCount), 1);
  2335. ASSERT(OldReferenceCount < 0x10000000);
  2336. return;
  2337. }
  2338. VOID
  2339. Ser16550pReleaseReference (
  2340. PSER16550_OBJECT Object
  2341. )
  2342. /*++
  2343. Routine Description:
  2344. This routine releases a reference on a 16550 object.
  2345. Arguments:
  2346. Object - Supplies a pointer to the 16550 object.
  2347. Return Value:
  2348. None.
  2349. --*/
  2350. {
  2351. ULONG OldReferenceCount;
  2352. OldReferenceCount = RtlAtomicAdd32(&(Object->ReferenceCount), (ULONG)-1);
  2353. ASSERT((OldReferenceCount != 0) && (OldReferenceCount < 0x10000000));
  2354. if (OldReferenceCount == 1) {
  2355. Ser16550pDestroyDevice(Object);
  2356. }
  2357. return;
  2358. }
  2359. VOID
  2360. Ser16550pDestroyDevice (
  2361. PSER16550_OBJECT Object
  2362. )
  2363. /*++
  2364. Routine Description:
  2365. This routine destroys a 16550 object.
  2366. Arguments:
  2367. Object - Supplies a pointer to the 16550 object.
  2368. Return Value:
  2369. None.
  2370. --*/
  2371. {
  2372. PSER16550_CHILD Child;
  2373. PSER16550_PARENT Parent;
  2374. switch (Object->Type) {
  2375. case Ser16550ObjectParent:
  2376. Parent = PARENT_STRUCTURE(Object, SER16550_PARENT, Header);
  2377. if (Parent->ChildDevices != NULL) {
  2378. MmFreePagedPool(Parent->ChildDevices);
  2379. Parent->ChildDevices = NULL;
  2380. }
  2381. if (Parent->ChildObjects != NULL) {
  2382. MmFreePagedPool(Parent->ChildObjects);
  2383. Parent->ChildObjects = NULL;
  2384. }
  2385. Parent->Header.Type = Ser16550ObjectInvalid;
  2386. MmFreeNonPagedPool(Parent);
  2387. break;
  2388. case Ser16550ObjectChild:
  2389. Child = PARENT_STRUCTURE(Object, SER16550_CHILD, Header);
  2390. Child->Header.Type = Ser16550ObjectInvalid;
  2391. if (Child->Terminal != NULL) {
  2392. IoTerminalSetDevice(Child->Terminal, NULL);
  2393. IoClose(Child->Terminal);
  2394. Child->Terminal = NULL;
  2395. }
  2396. if ((Child->MappedAddress != NULL) && (Child->ShouldUnmap != FALSE)) {
  2397. ASSERT(Child->MappedSize != 0);
  2398. MmUnmapAddress(Child->MappedAddress, Child->MappedSize);
  2399. Child->MappedAddress = NULL;
  2400. Child->MappedSize = 0;
  2401. }
  2402. if (Child->TransmitBuffer != NULL) {
  2403. MmFreeNonPagedPool(Child->TransmitBuffer);
  2404. Child->TransmitBuffer = NULL;
  2405. Child->TransmitSize = 0;
  2406. Child->TransmitStart = 0;
  2407. Child->TransmitEnd = 0;
  2408. }
  2409. if (Child->ReceiveBuffer != NULL) {
  2410. MmFreeNonPagedPool(Child->ReceiveBuffer);
  2411. Child->ReceiveBuffer = NULL;
  2412. Child->ReceiveSize = 0;
  2413. Child->ReceiveStart = 0;
  2414. Child->ReceiveEnd = 0;
  2415. }
  2416. if (Child->TransmitLock != NULL) {
  2417. KeDestroyQueuedLock(Child->TransmitLock);
  2418. Child->TransmitLock = NULL;
  2419. }
  2420. if (Child->ReceiveLock != NULL) {
  2421. KeDestroyQueuedLock(Child->ReceiveLock);
  2422. Child->ReceiveLock = NULL;
  2423. }
  2424. if (Child->TransmitReady == NULL) {
  2425. KeDestroyEvent(Child->TransmitReady);
  2426. Child->TransmitReady = NULL;
  2427. }
  2428. if (Child->ReceiveReady == NULL) {
  2429. KeDestroyEvent(Child->ReceiveReady);
  2430. Child->ReceiveReady = NULL;
  2431. }
  2432. break;
  2433. default:
  2434. ASSERT(FALSE);
  2435. return;
  2436. }
  2437. return;
  2438. }
  2439. UCHAR
  2440. Ser16550pReadIo8 (
  2441. PSER16550_CHILD Device,
  2442. SER16550_REGISTER Register
  2443. )
  2444. /*++
  2445. Routine Description:
  2446. This routine reads an I/O port based 16550 register.
  2447. Arguments:
  2448. Device - Supplies a pointer to the device context.
  2449. Register - Supplies the register to read.
  2450. Return Value:
  2451. Returns the value at the register.
  2452. --*/
  2453. {
  2454. USHORT Port;
  2455. Port = Device->IoPortAddress + SER16550_REGISTER_OFFSET(Device, Register);
  2456. return HlIoPortInByte(Port);
  2457. }
  2458. VOID
  2459. Ser16550pWriteIo8 (
  2460. PSER16550_CHILD Device,
  2461. SER16550_REGISTER Register,
  2462. UCHAR Value
  2463. )
  2464. /*++
  2465. Routine Description:
  2466. This routine writes to an I/O port based 16550 register.
  2467. Arguments:
  2468. Device - Supplies a pointer to the device context.
  2469. Register - Supplies the register to write to.
  2470. Value - Supplies the value to write.
  2471. Return Value:
  2472. None.
  2473. --*/
  2474. {
  2475. USHORT Port;
  2476. Port = Device->IoPortAddress + SER16550_REGISTER_OFFSET(Device, Register);
  2477. HlIoPortOutByte(Port, Value);
  2478. return;
  2479. }
  2480. UCHAR
  2481. Ser16550pReadMemory8 (
  2482. PSER16550_CHILD Device,
  2483. SER16550_REGISTER Register
  2484. )
  2485. /*++
  2486. Routine Description:
  2487. This routine reads a memory-based 16550 register.
  2488. Arguments:
  2489. Device - Supplies a pointer to the device context.
  2490. Register - Supplies the register to read.
  2491. Return Value:
  2492. Returns the value at the register.
  2493. --*/
  2494. {
  2495. PVOID Address;
  2496. Address = Device->MappedAddress +
  2497. SER16550_REGISTER_OFFSET(Device, Register);
  2498. return HlReadRegister8(Address);
  2499. }
  2500. VOID
  2501. Ser16550pWriteMemory8 (
  2502. PSER16550_CHILD Device,
  2503. SER16550_REGISTER Register,
  2504. UCHAR Value
  2505. )
  2506. /*++
  2507. Routine Description:
  2508. This routine writes to a memory-based 16550 register.
  2509. Arguments:
  2510. Device - Supplies a pointer to the device context.
  2511. Register - Supplies the register to write to.
  2512. Value - Supplies the value to write.
  2513. Return Value:
  2514. None.
  2515. --*/
  2516. {
  2517. PVOID Address;
  2518. Address = Device->MappedAddress +
  2519. SER16550_REGISTER_OFFSET(Device, Register);
  2520. HlWriteRegister8(Address, Value);
  2521. return;
  2522. }