ZealOS/docs/Kernel/BlkDev/DiskAHCI.CC.html
TomAwezome 1b75d91002 Fix Mount AHCI Port selection.
Add arg to SATARep to specify drive types to show.
Add checks in AHCIPortInit to verify port signatures, add helper method to get signatures from port.
2021-08-02 16:40:05 -04:00

1272 lines
139 KiB
HTML
Executable file

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=US-ASCII">
<meta name="generator" content="ZealOS V0.13">
<style type="text/css">
body {background-color:#fef1f0;}
.cF0{color:#000000;background-color:#fef1f0;}
.cF1{color:#0148a4;background-color:#fef1f0;}
.cF2{color:#3b7901;background-color:#fef1f0;}
.cF3{color:#057c7e;background-color:#fef1f0;}
.cF4{color:#bb2020;background-color:#fef1f0;}
.cF5{color:#9e42ae;background-color:#fef1f0;}
.cF6{color:#b57901;background-color:#fef1f0;}
.cF7{color:#b2b6af;background-color:#fef1f0;}
.cF8{color:#555753;background-color:#fef1f0;}
.cF9{color:#678fbb;background-color:#fef1f0;}
.cFA{color:#82bc49;background-color:#fef1f0;}
.cFB{color:#0097a2;background-color:#fef1f0;}
.cFC{color:#e26a6a;background-color:#fef1f0;}
.cFD{color:#c671bc;background-color:#fef1f0;}
.cFE{color:#c7ab00;background-color:#fef1f0;}
.cFF{color:#fef1f0;background-color:#fef1f0;}
</style>
</head>
<body>
<pre style="font-family:monospace;font-size:12pt">
<a name="l1"></a><span class=cF2>/*</span><span class=cF0>
<a name="l2"></a></span><span class=cF2>- Perhaps make more references to spec in comments</span><span class=cF0>
<a name="l3"></a>
<a name="l4"></a></span><span class=cF2>- ATAPI RW</span><span class=cF0>
<a name="l5"></a>
<a name="l6"></a></span><span class=cF2>- Remove Buffer alignment check and just do it on every call</span><span class=cF0>
<a name="l7"></a>
<a name="l8"></a></span><span class=cF2>- AHCIATAPISetMaxSpeed?</span><span class=cF0>
<a name="l9"></a></span><span class=cF2>*/</span><span class=cF0>
<a name="l10"></a>
<a name="l11"></a></span><span class=cF9>I64</span><span class=cF0> </span><span class=cFD>AHCI_DEBUG</span><span class=cF0> = </span><span class=cF3>FALSE</span><span class=cF0>;
<a name="l12"></a></span><span class=cF1>U0</span><span class=cF0> </span><span class=cF5>AHCIDebugMode</span><span class=cF0>(</span><span class=cF1>Bool</span><span class=cF0> mode=</span><span class=cF3>ON</span><span class=cF0>)
<a name="l13"></a>{
<a name="l14"></a> </span><span class=cFD>AHCI_DEBUG</span><span class=cF0> = mode;
<a name="l15"></a>}
<a name="l16"></a>
<a name="l17"></a></span><span class=cF1>U0</span><span class=cF0> </span><span class=cF5>AHCIDebug</span><span class=cF0>(</span><span class=cF9>I64</span><span class=cF0> port_num)
<a name="l18"></a>{
<a name="l19"></a> </span><span class=cF9>CAHCIHba</span><span class=cF0> *hba = </span><span class=cFB>blkdev</span><span class=cF0>.ahci_hba;
<a name="l20"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port = &amp;hba-&gt;ports[port_num];
<a name="l21"></a>
<a name="l22"></a> </span><span class=cF6>&quot;\n&quot;</span><span class=cF0>;
<a name="l23"></a> </span><span class=cF5>CallerRep</span><span class=cF0>;
<a name="l24"></a>
<a name="l25"></a> </span><span class=cF6>&quot;\nAHCI Port: %d&quot;</span><span class=cF0>, port_num;
<a name="l26"></a>
<a name="l27"></a> </span><span class=cF6>&quot;\nPort Interrupt Status: %b&quot;</span><span class=cF0>, port-&gt;interrupt_status;
<a name="l28"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;port-&gt;interrupt_status, </span><span class=cF3>AHCI_PxIf_CPDS</span><span class=cF7>)</span><span class=cF0>)
<a name="l29"></a> </span><span class=cF6>&quot;\n\tCold Port Detect Status&quot;</span><span class=cF0>;
<a name="l30"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;port-&gt;interrupt_status, </span><span class=cF3>AHCI_PxIf_TFE</span><span class=cF7>)</span><span class=cF0>)
<a name="l31"></a> </span><span class=cF6>&quot;\n\tTask File Error&quot;</span><span class=cF0>;
<a name="l32"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;port-&gt;interrupt_status, </span><span class=cF3>AHCI_PxIf_HBFS</span><span class=cF7>)</span><span class=cF0>)
<a name="l33"></a> </span><span class=cF6>&quot;\n\tHost Bus Fatal Error&quot;</span><span class=cF0>;
<a name="l34"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;port-&gt;interrupt_status, </span><span class=cF3>AHCI_PxIf_HBDS</span><span class=cF7>)</span><span class=cF0>)
<a name="l35"></a> </span><span class=cF6>&quot;\n\tHost Bus Data Error&quot;</span><span class=cF0>;
<a name="l36"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;port-&gt;interrupt_status, </span><span class=cF3>AHCI_PxIf_IFS</span><span class=cF7>)</span><span class=cF0>)
<a name="l37"></a> </span><span class=cF6>&quot;\n\tSATA Interface Fatal Error&quot;</span><span class=cF0>;
<a name="l38"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;port-&gt;interrupt_status, </span><span class=cF3>AHCI_PxIf_INFS</span><span class=cF7>)</span><span class=cF0>)
<a name="l39"></a> </span><span class=cF6>&quot;\n\tSATA Interface Non-Fatal Error&quot;</span><span class=cF0>;
<a name="l40"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;port-&gt;interrupt_status, </span><span class=cF3>AHCI_PxIf_OFS</span><span class=cF7>)</span><span class=cF0>)
<a name="l41"></a> </span><span class=cF6>&quot;\n\tOverflow Status (HBA RX bytes &gt; PRDT bytes)&quot;</span><span class=cF0>;
<a name="l42"></a> </span><span class=cF6>&quot;\nPort Command: %b&quot;</span><span class=cF0>, port-&gt;command;
<a name="l43"></a> </span><span class=cF6>&quot;\nPort Command Issue: %b&quot;</span><span class=cF0>, port-&gt;cmd_issue;
<a name="l44"></a> </span><span class=cF6>&quot;\nPort Task File Data: %b&quot;</span><span class=cF0>, port-&gt;task_file_data;
<a name="l45"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;port-&gt;task_file_data, </span><span class=cF3>AHCI_PxTFDf_STS_ERR</span><span class=cF7>)</span><span class=cF0>)
<a name="l46"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l47"></a> </span><span class=cF6>&quot;\n\tTask File Data Error&quot;</span><span class=cF0>;
<a name="l48"></a> </span><span class=cF6>&quot;\n\tTask File Data Error Register: %b&quot;</span><span class=cF0>, port-&gt;task_file_data.u8[</span><span class=cFE>1</span><span class=cF0>];
<a name="l49"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l50"></a> </span><span class=cF6>&quot;\nPort Interrupt Enable: %b&quot;</span><span class=cF0>, port-&gt;interrupt_enable;
<a name="l51"></a> </span><span class=cF6>&quot;\nPort SATA Status: %b&quot;</span><span class=cF0>, port-&gt;sata_status;
<a name="l52"></a> </span><span class=cF6>&quot;\nPort SATA Ctrl: %b&quot;</span><span class=cF0>, port-&gt;sata_ctrl;
<a name="l53"></a> </span><span class=cF6>&quot;\nPort SATA Error: %b&quot;</span><span class=cF0>, port-&gt;sata_error;
<a name="l54"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;port-&gt;sata_error, </span><span class=cF3>AHCI_PxSERR_ERR_I</span><span class=cF7>)</span><span class=cF0>)
<a name="l55"></a> </span><span class=cF6>&quot;\n\tRecovered Data Integrity Error&quot;</span><span class=cF0>;
<a name="l56"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;port-&gt;sata_error, </span><span class=cF3>AHCI_PxSERR_ERR_M</span><span class=cF7>)</span><span class=cF0>)
<a name="l57"></a> </span><span class=cF6>&quot;\n\tRecovered Communication Error&quot;</span><span class=cF0>;
<a name="l58"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;port-&gt;sata_error, </span><span class=cF3>AHCI_PxSERR_ERR_T</span><span class=cF7>)</span><span class=cF0>)
<a name="l59"></a> </span><span class=cF6>&quot;\n\tTransient Data Integrity Error&quot;</span><span class=cF0>;
<a name="l60"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;port-&gt;sata_error, </span><span class=cF3>AHCI_PxSERR_ERR_C</span><span class=cF7>)</span><span class=cF0>)
<a name="l61"></a> </span><span class=cF6>&quot;\n\tPersistent Communication Error&quot;</span><span class=cF0>;
<a name="l62"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;port-&gt;sata_error, </span><span class=cF3>AHCI_PxSERR_ERR_P</span><span class=cF7>)</span><span class=cF0>)
<a name="l63"></a> </span><span class=cF6>&quot;\n\tSATA Protocol Error&quot;</span><span class=cF0>;
<a name="l64"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;port-&gt;sata_error, </span><span class=cF3>AHCI_PxSERR_ERR_E</span><span class=cF7>)</span><span class=cF0>)
<a name="l65"></a> </span><span class=cF6>&quot;\n\tInternal Error&quot;</span><span class=cF0>;
<a name="l66"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;port-&gt;sata_error, </span><span class=cF3>AHCI_PxSERR_DIAG_I</span><span class=cF7>)</span><span class=cF0>)
<a name="l67"></a> </span><span class=cF6>&quot;\n\tPHY Internal Error&quot;</span><span class=cF0>;
<a name="l68"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;port-&gt;sata_error, </span><span class=cF3>AHCI_PxSERR_DIAG_C</span><span class=cF7>)</span><span class=cF0>)
<a name="l69"></a> </span><span class=cF6>&quot;\n\tLink Layer CRC Error&quot;</span><span class=cF0>;
<a name="l70"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;port-&gt;sata_error, </span><span class=cF3>AHCI_PxSERR_DIAG_H</span><span class=cF7>)</span><span class=cF0>)
<a name="l71"></a> </span><span class=cF6>&quot;\n\tHandshake Error&quot;</span><span class=cF0>;
<a name="l72"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;port-&gt;sata_error, </span><span class=cF3>AHCI_PxSERR_DIAG_S</span><span class=cF7>)</span><span class=cF0>)
<a name="l73"></a> </span><span class=cF6>&quot;\n\tLink Sequence Error&quot;</span><span class=cF0>;
<a name="l74"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;port-&gt;sata_error, </span><span class=cF3>AHCI_PxSERR_DIAG_T</span><span class=cF7>)</span><span class=cF0>)
<a name="l75"></a> </span><span class=cF6>&quot;\n\tTransport State Transition Error&quot;</span><span class=cF0>;
<a name="l76"></a> </span><span class=cF6>&quot;\nPort SATA Active: %b&quot;</span><span class=cF0>, port-&gt;sata_active;
<a name="l77"></a> </span><span class=cF6>&quot;\nPort SATA Notif: %b&quot;</span><span class=cF0>, port-&gt;sata_notif;
<a name="l78"></a>
<a name="l79"></a> </span><span class=cF6>&quot;\n&quot;</span><span class=cF0>;
<a name="l80"></a>
<a name="l81"></a> </span><span class=cF6>&quot;\nHBA Capabilities: %b&quot;</span><span class=cF0>, hba-&gt;caps;
<a name="l82"></a> </span><span class=cF6>&quot;\nHBA Interrupt Status: %b&quot;</span><span class=cF0>, hba-&gt;interrupt_status;
<a name="l83"></a> </span><span class=cF1>if</span><span class=cF0> (hba-&gt;interrupt_status)
<a name="l84"></a> </span><span class=cF6>&quot;\n\t(Each set bit is a port with pending interrupt)&quot;</span><span class=cF0>;
<a name="l85"></a> </span><span class=cF6>&quot;\nHBA Ports Implemented: %b&quot;</span><span class=cF0>, hba-&gt;ports_implemented;
<a name="l86"></a> </span><span class=cF6>&quot;\nHBA Version: 0x%0X&quot;</span><span class=cF0>, hba-&gt;version;
<a name="l87"></a> </span><span class=cF6>&quot;\nHBA Ext Capabilities: %b&quot;</span><span class=cF0>, hba-&gt;caps_ext;
<a name="l88"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;hba-&gt;caps_ext, </span><span class=cF3>AHCI_CAPSEXTf_BOH</span><span class=cF7>)</span><span class=cF0>)
<a name="l89"></a> </span><span class=cF6>&quot;\n\tBIOS/OS Handoff supported.&quot;</span><span class=cF0>;
<a name="l90"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;hba-&gt;caps_ext, </span><span class=cF3>AHCI_CAPSEXTf_NVMP</span><span class=cF7>)</span><span class=cF0>)
<a name="l91"></a> </span><span class=cF6>&quot;\n\tNVMHCI Supported (Non-Volatile Memory Host Controller Interface)&quot;</span><span class=cF0>;
<a name="l92"></a> </span><span class=cF6>&quot;\nHBA BIOS/OS Handoff: %b&quot;</span><span class=cF0>, hba-&gt;bohc;
<a name="l93"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;hba-&gt;bohc, </span><span class=cF3>AHCI_BOHCf_BOS</span><span class=cF7>)</span><span class=cF0>)
<a name="l94"></a> </span><span class=cF6>&quot;\n\tBIOS owns AHCI Controller&quot;</span><span class=cF0>;
<a name="l95"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;hba-&gt;bohc, </span><span class=cF3>AHCI_BOHCf_BB</span><span class=cF7>)</span><span class=cF0>)
<a name="l96"></a> </span><span class=cF6>&quot;\n\tBIOS Busy&quot;</span><span class=cF0>;
<a name="l97"></a>
<a name="l98"></a> </span><span class=cF6>&quot;\n&quot;</span><span class=cF0>;
<a name="l99"></a>
<a name="l100"></a>}
<a name="l101"></a>
<a name="l102"></a></span><span class=cF9>I64</span><span class=cF0> </span><span class=cFD>AHCILBA48CapacityGet</span><span class=cF0>(</span><span class=cF9>U16</span><span class=cF0> *id_record)
<a name="l103"></a>{</span><span class=cF2>//Get capacity of drive, in LBA blocks.</span><span class=cF0>
<a name="l104"></a></span><span class=cF2>//Capacity is stored in a U64, so we take the shortcut</span><span class=cF0>
<a name="l105"></a></span><span class=cF2>//and access the U16-indexed ID record as U64 indexed. Zero-based value.</span><span class=cF0>
<a name="l106"></a> </span><span class=cF1>return</span><span class=cF0> (id_record)(</span><span class=cF9>U64</span><span class=cF0> *)[</span><span class=cF3>ATA_IDENT_LBA48_CAPACITY</span><span class=cF0> / </span><span class=cFE>4</span><span class=cF0>] - </span><span class=cFE>1</span><span class=cF0>;
<a name="l107"></a>}
<a name="l108"></a>
<a name="l109"></a></span><span class=cF9>I64</span><span class=cF0> </span><span class=cFD>AHCIPortCmdSlotGet</span><span class=cF0>(</span><span class=cF9>I64</span><span class=cF0> port_num)
<a name="l110"></a>{</span><span class=cF2>//Get next free command slot in port; if none, throw error.</span><span class=cF0>
<a name="l111"></a> </span><span class=cF9>I64</span><span class=cF0> i;
<a name="l112"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port = &amp;</span><span class=cFB>blkdev</span><span class=cF0>.ahci_hba-&gt;ports[port_num];
<a name="l113"></a> </span><span class=cF9>U32</span><span class=cF0> slots = port-&gt;sata_active | port-&gt;cmd_issue;
<a name="l114"></a>
<a name="l115"></a> </span><span class=cF1>for</span><span class=cF0> (i = </span><span class=cFE>0</span><span class=cF0>; i &lt; </span><span class=cFB>blkdev</span><span class=cF0>.cmd_slot_count; i++)
<a name="l116"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l117"></a> </span><span class=cF1>if</span><span class=cF0> (!</span><span class=cF7>(</span><span class=cF0>slots &amp; </span><span class=cFE>1</span><span class=cF7>)</span><span class=cF0>)
<a name="l118"></a> </span><span class=cF1>return</span><span class=cF0> i;
<a name="l119"></a>
<a name="l120"></a> slots &gt;&gt;= </span><span class=cFE>1</span><span class=cF0>;
<a name="l121"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l122"></a>
<a name="l123"></a> </span><span class=cF5>SysErr</span><span class=cF0>(</span><span class=cF6>&quot;AHCI: No empty command slots on port %d!\n&quot;</span><span class=cF0>, port_num);
<a name="l124"></a> </span><span class=cF5>throw</span><span class=cF0>(</span><span class=cF6>'AHCI'</span><span class=cF0>);
<a name="l125"></a>}
<a name="l126"></a>
<a name="l127"></a></span><span class=cF9>I64</span><span class=cF0> </span><span class=cF5>AHCIPortSignatureGet</span><span class=cF0>(</span><span class=cF9>I64</span><span class=cF0> port_num)
<a name="l128"></a>{
<a name="l129"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port;
<a name="l130"></a>
<a name="l131"></a> </span><span class=cF1>if</span><span class=cF0> (port_num &lt; </span><span class=cFE>0</span><span class=cF0> || port_num &gt; </span><span class=cF3>AHCI_MAX_PORTS</span><span class=cF0>)
<a name="l132"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>NULL</span><span class=cF0>;
<a name="l133"></a>
<a name="l134"></a> port = &amp;</span><span class=cFB>blkdev</span><span class=cF0>.ahci_hba-&gt;ports[port_num];
<a name="l135"></a> </span><span class=cF1>return</span><span class=cF0> port-&gt;signature;
<a name="l136"></a>}
<a name="l137"></a>
<a name="l138"></a></span><span class=cF1>Bool</span><span class=cF0> </span><span class=cFD>AHCIPortIsIdle</span><span class=cF0>(</span><span class=cF9>I64</span><span class=cF0> port_num)
<a name="l139"></a>{</span><span class=cF2>//Check if the command engine is running on port.</span><span class=cF0>
<a name="l140"></a> </span><span class=cF1>return</span><span class=cF0> !(</span><span class=cFB>blkdev</span><span class=cF0>.ahci_hba-&gt;ports[port_num].command &amp; </span><span class=cF7>(</span><span class=cF3>AHCI_PxCMDF_ST</span><span class=cF0> | </span><span class=cF3>AHCI_PxCMDF_CR</span><span class=cF0> | </span><span class=cF3>AHCI_PxCMDF_FR</span><span class=cF0> | </span><span class=cF3>AHCI_PxCMDF_FRE</span><span class=cF7>)</span><span class=cF0>);
<a name="l141"></a>}
<a name="l142"></a>
<a name="l143"></a></span><span class=cF1>U0</span><span class=cF0> </span><span class=cFD>AHCIPortCmdStop</span><span class=cF0>(</span><span class=cF9>I64</span><span class=cF0> port_num)
<a name="l144"></a>{</span><span class=cF2>//Stop command engine on port.</span><span class=cF0>
<a name="l145"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port = &amp;</span><span class=cFB>blkdev</span><span class=cF0>.ahci_hba-&gt;ports[port_num];
<a name="l146"></a>
<a name="l147"></a> </span><span class=cF5>Btr</span><span class=cF0>(&amp;port-&gt;command, </span><span class=cF3>AHCI_PxCMDf_ST</span><span class=cF0>);
<a name="l148"></a> </span><span class=cF5>Btr</span><span class=cF0>(&amp;port-&gt;command, </span><span class=cF3>AHCI_PxCMDf_FRE</span><span class=cF0>);
<a name="l149"></a>
<a name="l150"></a> </span><span class=cF1>while</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;port-&gt;command, </span><span class=cF3>AHCI_PxCMDf_CR</span><span class=cF7>)</span><span class=cF0> || </span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;port-&gt;command, </span><span class=cF3>AHCI_PxCMDf_FR</span><span class=cF7>)</span><span class=cF0>);
<a name="l151"></a>}
<a name="l152"></a>
<a name="l153"></a></span><span class=cF1>U0</span><span class=cF0> </span><span class=cFD>AHCIPortCmdStart</span><span class=cF0>(</span><span class=cF9>I64</span><span class=cF0> port_num)
<a name="l154"></a>{</span><span class=cF2>//Start command engine on port.</span><span class=cF0>
<a name="l155"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port = &amp;</span><span class=cFB>blkdev</span><span class=cF0>.ahci_hba-&gt;ports[port_num];
<a name="l156"></a>
<a name="l157"></a> </span><span class=cF1>while</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;port-&gt;command, </span><span class=cF3>AHCI_PxCMDf_CR</span><span class=cF7>)</span><span class=cF0>);
<a name="l158"></a>
<a name="l159"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;port-&gt;command, </span><span class=cF3>AHCI_PxCMDf_FRE</span><span class=cF0>);
<a name="l160"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;port-&gt;command, </span><span class=cF3>AHCI_PxCMDf_ST</span><span class=cF0>);
<a name="l161"></a>}
<a name="l162"></a>
<a name="l163"></a></span><span class=cF1>Bool</span><span class=cF0> </span><span class=cFD>AHCIPortWait</span><span class=cF0>(</span><span class=cF9>I64</span><span class=cF0> port_num, </span><span class=cF1>F64</span><span class=cF0> timeout, </span><span class=cF1>Bool</span><span class=cF0> throwing=</span><span class=cF3>TRUE</span><span class=cF0>)
<a name="l164"></a>{</span><span class=cF2>//Wait until DRQ &amp; BSY are clear in port task file.</span><span class=cF0>
<a name="l165"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port = &amp;</span><span class=cFB>blkdev</span><span class=cF0>.ahci_hba-&gt;ports[port_num];
<a name="l166"></a> </span><span class=cF1>U8</span><span class=cF0> str[</span><span class=cF3>STR_LEN</span><span class=cF0>];
<a name="l167"></a>
<a name="l168"></a> </span><span class=cF1>do</span><span class=cF0>
<a name="l169"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l170"></a> </span><span class=cF1>if</span><span class=cF0> (!</span><span class=cF7>(</span><span class=cF0>port-&gt;task_file_data &amp; (</span><span class=cF3>ATAS_DRQ</span><span class=cF0> | </span><span class=cF3>ATAS_BSY</span><span class=cF0>)</span><span class=cF7>)</span><span class=cF0>)
<a name="l171"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>TRUE</span><span class=cF0>;
<a name="l172"></a> </span><span class=cF5>Yield</span><span class=cF0>; </span><span class=cF2>// don't hang OS</span><span class=cF0>
<a name="l173"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l174"></a> </span><span class=cF1>while</span><span class=cF0> (timeout &gt; </span><span class=cF5>tS</span><span class=cF0>);
<a name="l175"></a>
<a name="l176"></a> </span><span class=cF1>if</span><span class=cF0> (throwing)
<a name="l177"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l178"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cFD>AHCI_DEBUG</span><span class=cF0>)
<a name="l179"></a> {
<a name="l180"></a> </span><span class=cF5>StrPrint</span><span class=cF0>(str, </span><span class=cF6>&quot;Run AHCIDebug(%d);&quot;</span><span class=cF0>, port_num);
<a name="l181"></a> </span><span class=cF5>Debug</span><span class=cF0>(str);
<a name="l182"></a> }
<a name="l183"></a>
<a name="l184"></a> </span><span class=cF5>SysErr</span><span class=cF0>(</span><span class=cF6>&quot;AHCI: Port %d hung.\n&quot;</span><span class=cF0>, port_num);
<a name="l185"></a> </span><span class=cF5>throw</span><span class=cF0>(</span><span class=cF6>'AHCI'</span><span class=cF0>);
<a name="l186"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l187"></a>
<a name="l188"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>FALSE</span><span class=cF0>;
<a name="l189"></a>}
<a name="l190"></a>
<a name="l191"></a></span><span class=cF1>U0</span><span class=cF0> </span><span class=cF5>AHCIPortReset</span><span class=cF0>(</span><span class=cF9>I64</span><span class=cF0> port_num)
<a name="l192"></a>{</span><span class=cF2>//Software reset of port. Port command engine must be started after this.</span><span class=cF0>
<a name="l193"></a> </span><span class=cF2>//If port is not responsive we do a full reset.</span><span class=cF0>
<a name="l194"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port = &amp;</span><span class=cFB>blkdev</span><span class=cF0>.ahci_hba-&gt;ports[port_num];
<a name="l195"></a>
<a name="l196"></a> </span><span class=cFD>AHCIPortCmdStop</span><span class=cF0>(port_num);
<a name="l197"></a>
<a name="l198"></a> port-&gt;interrupt_status = port-&gt;interrupt_status; </span><span class=cF2>//Acknowledge all interrupt statuses.</span><span class=cF0>
<a name="l199"></a>
<a name="l200"></a> </span><span class=cF1>if</span><span class=cF0> (!</span><span class=cFD>AHCIPortWait</span><span class=cF7>(</span><span class=cF0>port_num, </span><span class=cF5>tS</span><span class=cF0> + </span><span class=cFE>1</span><span class=cF7>)</span><span class=cF0>)
<a name="l201"></a> </span><span class=cF7>{</span><span class=cF2>//Perform 'more intrusive' HBA&lt;-&gt;Port comm reset (sec. 10.4.2 of spec).</span><span class=cF0>
<a name="l202"></a> port-&gt;sata_ctrl = </span><span class=cF3>AHCI_PxSCTLF_DET_INIT</span><span class=cF0>;
<a name="l203"></a> </span><span class=cF5>Sleep</span><span class=cF0>(</span><span class=cFE>2</span><span class=cF0>); </span><span class=cF2>//Spec says 1 millisecond</span><span class=cF0>
<a name="l204"></a> port-&gt;sata_ctrl = </span><span class=cFE>0</span><span class=cF0>;
<a name="l205"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l206"></a>
<a name="l207"></a> </span><span class=cF1>while</span><span class=cF0> (port-&gt;sata_status &amp; </span><span class=cFE>0xF</span><span class=cF0> != </span><span class=cF3>AHCI_PxSSTSF_DET_PRESENT</span><span class=cF0>);
<a name="l208"></a>
<a name="l209"></a> port-&gt;sata_error = ~</span><span class=cFE>0</span><span class=cF0>; </span><span class=cF2>//Write all 1s to sata error register.</span><span class=cF0>
<a name="l210"></a>}
<a name="l211"></a>
<a name="l212"></a></span><span class=cF9>CPortCmdHeader</span><span class=cF0> *</span><span class=cFD>AHCIPortActiveHeaderGet</span><span class=cF0>(</span><span class=cF9>I64</span><span class=cF0> port_num, </span><span class=cF9>I64</span><span class=cF0> cmd_slot)
<a name="l213"></a>{</span><span class=cF2>//Get current command slot header on port.</span><span class=cF0>
<a name="l214"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port = &amp;</span><span class=cFB>blkdev</span><span class=cF0>.ahci_hba-&gt;ports[port_num];
<a name="l215"></a> </span><span class=cF9>CPortCmdHeader</span><span class=cF0> *cmd_header = port-&gt;cmd_list_base;
<a name="l216"></a>
<a name="l217"></a> </span><span class=cF1>return</span><span class=cF0> cmd_header + cmd_slot; </span><span class=cF2>//Move up pointer to the slot we have in the command list.</span><span class=cF0>
<a name="l218"></a>}
<a name="l219"></a>
<a name="l220"></a></span><span class=cF1>U0</span><span class=cF0> </span><span class=cFD>AHCIPortCmdWait</span><span class=cF0>(</span><span class=cF9>I64</span><span class=cF0> port_num, </span><span class=cF9>I64</span><span class=cF0> cmd_slot)
<a name="l221"></a>{</span><span class=cF2>//Wait on command completion after command issue, and double check any error.</span><span class=cF0>
<a name="l222"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port = &amp;</span><span class=cFB>blkdev</span><span class=cF0>.ahci_hba-&gt;ports[port_num];
<a name="l223"></a> </span><span class=cF1>U8</span><span class=cF0> str[</span><span class=cF3>STR_LEN</span><span class=cF0>];
<a name="l224"></a>
<a name="l225"></a> </span><span class=cF1>while</span><span class=cF0> (</span><span class=cF3>TRUE</span><span class=cF0>)
<a name="l226"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l227"></a> </span><span class=cF1>if</span><span class=cF0> (!</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;port-&gt;cmd_issue, cmd_slot</span><span class=cF7>)</span><span class=cF0>) </span><span class=cF2>//When command has been processed</span><span class=cF0>
<a name="l228"></a> </span><span class=cF1>break</span><span class=cF0>;
<a name="l229"></a>
<a name="l230"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;port-&gt;interrupt_status, </span><span class=cF3>AHCI_PxIf_TFE</span><span class=cF7>)</span><span class=cF0>) </span><span class=cF2>//Task File Error (</span><a href="https://zeal-operating-system.github.io/ZealOS/Kernel/KernelA.HH.html#l2971"><span class=cF4>ATAS_ERR</span></a><span class=cF2>)</span><span class=cF0>
<a name="l231"></a> {
<a name="l232"></a>error:
<a name="l233"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cFD>AHCI_DEBUG</span><span class=cF0>)
<a name="l234"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l235"></a> </span><span class=cF5>StrPrint</span><span class=cF0>(str, </span><span class=cF6>&quot;Run AHCIDebug(%d);&quot;</span><span class=cF0>, port_num);
<a name="l236"></a> </span><span class=cF5>Debug</span><span class=cF0>(str);
<a name="l237"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l238"></a>
<a name="l239"></a> </span><span class=cF5>SysErr</span><span class=cF0>(</span><span class=cF6>&quot;AHCI: Port %d: Command failed!\n&quot;</span><span class=cF0>, port_num);
<a name="l240"></a> </span><span class=cF5>throw</span><span class=cF0>(</span><span class=cF6>'AHCI'</span><span class=cF0>);
<a name="l241"></a> }
<a name="l242"></a>
<a name="l243"></a> </span><span class=cF5>Yield</span><span class=cF0>; </span><span class=cF2>// don't hang OS</span><span class=cF0>
<a name="l244"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l245"></a>
<a name="l246"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;port-&gt;interrupt_status, </span><span class=cF3>AHCI_PxIf_TFE</span><span class=cF7>)</span><span class=cF0>) </span><span class=cF2>//Second safety check</span><span class=cF0>
<a name="l247"></a> </span><span class=cF1>goto</span><span class=cF0> error;
<a name="l248"></a>}
<a name="l249"></a>
<a name="l250"></a></span><span class=cF9>I64</span><span class=cF0> </span><span class=cFD>AHCIAtapiCapacityGet</span><span class=cF0>(</span><span class=cF9>CBlkDev</span><span class=cF0> *bd)
<a name="l251"></a>{
<a name="l252"></a> </span><span class=cF9>CPortCmdTable</span><span class=cF0> *cmd_table;
<a name="l253"></a> </span><span class=cF9>CFisH2D</span><span class=cF0> *cmd_fis;
<a name="l254"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port = bd-&gt;ahci_port;
<a name="l255"></a> </span><span class=cF9>I64</span><span class=cF0> cmd_slot = </span><span class=cFD>AHCIPortCmdSlotGet</span><span class=cF0>(bd-&gt;port_num);
<a name="l256"></a> </span><span class=cF9>CPortCmdHeader</span><span class=cF0> *cmd_header = </span><span class=cFD>AHCIPortActiveHeaderGet</span><span class=cF0>(bd-&gt;port_num, cmd_slot);
<a name="l257"></a> </span><span class=cF9>U32</span><span class=cF0> *buf;
<a name="l258"></a>
<a name="l259"></a> </span><span class=cF1>if</span><span class=cF0> (port-&gt;signature != </span><span class=cF3>AHCI_PxSIG_ATAPI</span><span class=cF0>)
<a name="l260"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l261"></a> </span><span class=cF5>SysErr</span><span class=cF0>(</span><span class=cF6>&quot;AHCI: Drive is not an ATAPI drive!\n&quot;</span><span class=cF0>);
<a name="l262"></a> </span><span class=cF5>throw</span><span class=cF0>(</span><span class=cF6>'AHCI'</span><span class=cF0>);
<a name="l263"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l264"></a>
<a name="l265"></a> buf = </span><span class=cF5>CAlloc</span><span class=cF0>(</span><span class=cFE>8</span><span class=cF0>, </span><span class=cFB>sys_task</span><span class=cF0>-&gt;code_heap);
<a name="l266"></a>
<a name="l267"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;cmd_header-&gt;desc, </span><span class=cF3>AHCI_CH_DESCf_A</span><span class=cF0>);
<a name="l268"></a>
<a name="l269"></a> cmd_table = cmd_header-&gt;cmd_table_base;
<a name="l270"></a> </span><span class=cF5>MemSet</span><span class=cF0>(cmd_table, </span><span class=cFE>0</span><span class=cF0>, </span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF9>CPortCmdTable</span><span class=cF7>)</span><span class=cF0>);
<a name="l271"></a>
<a name="l272"></a> </span><span class=cF2>//Set up single PRD</span><span class=cF0>
<a name="l273"></a> cmd_table-&gt;prdt[</span><span class=cFE>0</span><span class=cF0>].data_base = buf;
<a name="l274"></a> cmd_table-&gt;prdt[</span><span class=cFE>0</span><span class=cF0>].data_byte_count = </span><span class=cF3>DVD_BLK_SIZE</span><span class=cF0> - </span><span class=cFE>1</span><span class=cF0>; </span><span class=cF2>//Zero-based value</span><span class=cF0>
<a name="l275"></a> cmd_header-&gt;prdt_len = </span><span class=cFE>1</span><span class=cF0>;
<a name="l276"></a>
<a name="l277"></a> cmd_fis = cmd_table-&gt;cmd_fis;
<a name="l278"></a>
<a name="l279"></a> cmd_fis-&gt;type = </span><span class=cF3>FISt_H2D</span><span class=cF0>;
<a name="l280"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;cmd_fis-&gt;desc, </span><span class=cF3>AHCI_CF_DESCf_C</span><span class=cF0>); </span><span class=cF2>//Set Command bit in H2D FIS.</span><span class=cF0>
<a name="l281"></a> cmd_fis-&gt;command = </span><span class=cF3>ATA_PACKET</span><span class=cF0>;
<a name="l282"></a> cmd_table-&gt;acmd[</span><span class=cFE>0</span><span class=cF0>] = </span><span class=cF3>ATAPI_READ_CAPACITY</span><span class=cF0> &gt;&gt; </span><span class=cFE>8</span><span class=cF0>;
<a name="l283"></a>
<a name="l284"></a> </span><span class=cFD>AHCIPortWait</span><span class=cF0>(bd-&gt;port_num, </span><span class=cF5>tS</span><span class=cF0> + </span><span class=cFE>2</span><span class=cF0>);
<a name="l285"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;port-&gt;cmd_issue, cmd_slot); </span><span class=cF2>//Issue the command.</span><span class=cF0>
<a name="l286"></a>
<a name="l287"></a> </span><span class=cF1>try</span><span class=cF0>
<a name="l288"></a> </span><span class=cFD>AHCIPortCmdWait</span><span class=cF0>(bd-&gt;port_num, cmd_slot);
<a name="l289"></a> </span><span class=cF1>catch</span><span class=cF0>
<a name="l290"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l291"></a> </span><span class=cF5>Fs</span><span class=cF0>-&gt;catch_except = </span><span class=cF3>TRUE</span><span class=cF0>;
<a name="l292"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cFE>0</span><span class=cF0>;
<a name="l293"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l294"></a>
<a name="l295"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF5>EndianU32</span><span class=cF0>(buf[</span><span class=cFE>0</span><span class=cF0>]);
<a name="l296"></a>}
<a name="l297"></a>
<a name="l298"></a></span><span class=cF1>Bool</span><span class=cF0> </span><span class=cF5>AHCIAtapiSeek</span><span class=cF0>(</span><span class=cF9>CBlkDev</span><span class=cF0> *bd, </span><span class=cF9>I64</span><span class=cF0> blk)
<a name="l299"></a>{
<a name="l300"></a> </span><span class=cF9>CPortCmdTable</span><span class=cF0> *cmd_table;
<a name="l301"></a> </span><span class=cF9>CFisH2D</span><span class=cF0> *cmd_fis;
<a name="l302"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port = bd-&gt;ahci_port;
<a name="l303"></a> </span><span class=cF9>I64</span><span class=cF0> cmd_slot = </span><span class=cFD>AHCIPortCmdSlotGet</span><span class=cF0>(bd-&gt;port_num);
<a name="l304"></a> </span><span class=cF9>CPortCmdHeader</span><span class=cF0> *cmd_header = </span><span class=cFD>AHCIPortActiveHeaderGet</span><span class=cF0>(bd-&gt;port_num, cmd_slot);
<a name="l305"></a>
<a name="l306"></a> </span><span class=cF1>if</span><span class=cF0> (port-&gt;signature != </span><span class=cF3>AHCI_PxSIG_ATAPI</span><span class=cF0>)
<a name="l307"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l308"></a> </span><span class=cF5>SysErr</span><span class=cF0>(</span><span class=cF6>&quot;AHCI: Drive is not an ATAPI drive!\n&quot;</span><span class=cF0>);
<a name="l309"></a> </span><span class=cF5>throw</span><span class=cF0>(</span><span class=cF6>'AHCI'</span><span class=cF0>);
<a name="l310"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l311"></a>
<a name="l312"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;cmd_header-&gt;desc, </span><span class=cF3>AHCI_CH_DESCf_A</span><span class=cF0>);
<a name="l313"></a>
<a name="l314"></a> cmd_table = cmd_header-&gt;cmd_table_base;
<a name="l315"></a> </span><span class=cF5>MemSet</span><span class=cF0>(cmd_table, </span><span class=cFE>0</span><span class=cF0>, </span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF9>CPortCmdTable</span><span class=cF7>)</span><span class=cF0>);
<a name="l316"></a>
<a name="l317"></a> cmd_fis = cmd_table-&gt;cmd_fis;
<a name="l318"></a>
<a name="l319"></a> cmd_fis-&gt;type = </span><span class=cF3>FISt_H2D</span><span class=cF0>;
<a name="l320"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;cmd_fis-&gt;desc, </span><span class=cF3>AHCI_CF_DESCf_C</span><span class=cF0>); </span><span class=cF2>//Set Command bit in H2D FIS.</span><span class=cF0>
<a name="l321"></a> cmd_fis-&gt;command = </span><span class=cF3>ATA_PACKET</span><span class=cF0>;
<a name="l322"></a> cmd_table-&gt;acmd[</span><span class=cFE>0</span><span class=cF0>] = </span><span class=cF3>ATAPI_SEEK</span><span class=cF0> &gt;&gt; </span><span class=cFE>8</span><span class=cF0>;
<a name="l323"></a> cmd_table-&gt;acmd[</span><span class=cFE>2</span><span class=cF0>] = blk.u8[</span><span class=cFE>3</span><span class=cF0>];
<a name="l324"></a> cmd_table-&gt;acmd[</span><span class=cFE>3</span><span class=cF0>] = blk.u8[</span><span class=cFE>2</span><span class=cF0>];
<a name="l325"></a> cmd_table-&gt;acmd[</span><span class=cFE>4</span><span class=cF0>] = blk.u8[</span><span class=cFE>1</span><span class=cF0>];
<a name="l326"></a> cmd_table-&gt;acmd[</span><span class=cFE>5</span><span class=cF0>] = blk.u8[</span><span class=cFE>0</span><span class=cF0>];
<a name="l327"></a>
<a name="l328"></a> </span><span class=cFD>AHCIPortWait</span><span class=cF0>(bd-&gt;port_num, </span><span class=cF5>tS</span><span class=cF0> + </span><span class=cFE>2</span><span class=cF0>);
<a name="l329"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;port-&gt;cmd_issue, cmd_slot); </span><span class=cF2>//Issue the command.</span><span class=cF0>
<a name="l330"></a>
<a name="l331"></a> </span><span class=cF1>try</span><span class=cF0>
<a name="l332"></a> </span><span class=cFD>AHCIPortCmdWait</span><span class=cF0>(bd-&gt;port_num, cmd_slot);
<a name="l333"></a> </span><span class=cF1>catch</span><span class=cF0>
<a name="l334"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l335"></a> </span><span class=cF5>Fs</span><span class=cF0>-&gt;catch_except = </span><span class=cF3>TRUE</span><span class=cF0>;
<a name="l336"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>FALSE</span><span class=cF0>;
<a name="l337"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l338"></a>
<a name="l339"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>TRUE</span><span class=cF0>;
<a name="l340"></a>}
<a name="l341"></a>
<a name="l342"></a></span><span class=cF1>Bool</span><span class=cF0> </span><span class=cFD>AHCIAtapiSync</span><span class=cF0>(</span><span class=cF9>CBlkDev</span><span class=cF0> *bd)
<a name="l343"></a>{</span><span class=cF2>//untested</span><span class=cF0>
<a name="l344"></a> </span><span class=cF9>CPortCmdTable</span><span class=cF0> *cmd_table;
<a name="l345"></a> </span><span class=cF9>CFisH2D</span><span class=cF0> *cmd_fis;
<a name="l346"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port = bd-&gt;ahci_port;
<a name="l347"></a> </span><span class=cF9>I64</span><span class=cF0> cmd_slot = </span><span class=cFD>AHCIPortCmdSlotGet</span><span class=cF0>(bd-&gt;port_num);
<a name="l348"></a> </span><span class=cF9>CPortCmdHeader</span><span class=cF0> *cmd_header = </span><span class=cFD>AHCIPortActiveHeaderGet</span><span class=cF0>(bd-&gt;port_num, cmd_slot);
<a name="l349"></a>
<a name="l350"></a> </span><span class=cF1>if</span><span class=cF0> (port-&gt;signature != </span><span class=cF3>AHCI_PxSIG_ATAPI</span><span class=cF0>)
<a name="l351"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l352"></a> </span><span class=cF5>SysErr</span><span class=cF0>(</span><span class=cF6>&quot;AHCI: Drive is not an ATAPI drive!\n&quot;</span><span class=cF0>);
<a name="l353"></a> </span><span class=cF5>throw</span><span class=cF0>(</span><span class=cF6>'AHCI'</span><span class=cF0>);
<a name="l354"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l355"></a>
<a name="l356"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;cmd_header-&gt;desc, </span><span class=cF3>AHCI_CH_DESCf_A</span><span class=cF0>);
<a name="l357"></a>
<a name="l358"></a> cmd_table = cmd_header-&gt;cmd_table_base;
<a name="l359"></a> </span><span class=cF5>MemSet</span><span class=cF0>(cmd_table, </span><span class=cFE>0</span><span class=cF0>, </span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF9>CPortCmdTable</span><span class=cF7>)</span><span class=cF0>);
<a name="l360"></a>
<a name="l361"></a> cmd_fis = cmd_table-&gt;cmd_fis;
<a name="l362"></a>
<a name="l363"></a> cmd_fis-&gt;type = </span><span class=cF3>FISt_H2D</span><span class=cF0>;
<a name="l364"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;cmd_fis-&gt;desc, </span><span class=cF3>AHCI_CF_DESCf_C</span><span class=cF0>); </span><span class=cF2>//Set Command bit in H2D FIS.</span><span class=cF0>
<a name="l365"></a> cmd_fis-&gt;command = </span><span class=cF3>ATA_PACKET</span><span class=cF0>;
<a name="l366"></a> cmd_table-&gt;acmd[</span><span class=cFE>0</span><span class=cF0>] = </span><span class=cF3>ATAPI_SYNC_CACHE</span><span class=cF0> &gt;&gt; </span><span class=cFE>8</span><span class=cF0>;
<a name="l367"></a>
<a name="l368"></a> </span><span class=cFD>AHCIPortWait</span><span class=cF0>(bd-&gt;port_num, </span><span class=cF5>tS</span><span class=cF0> + </span><span class=cFE>2</span><span class=cF0>);
<a name="l369"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;port-&gt;cmd_issue, cmd_slot); </span><span class=cF2>//Issue the command.</span><span class=cF0>
<a name="l370"></a>
<a name="l371"></a> </span><span class=cF1>try</span><span class=cF0>
<a name="l372"></a> </span><span class=cFD>AHCIPortCmdWait</span><span class=cF0>(bd-&gt;port_num, cmd_slot);
<a name="l373"></a> </span><span class=cF1>catch</span><span class=cF0>
<a name="l374"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l375"></a> </span><span class=cF5>Fs</span><span class=cF0>-&gt;catch_except = </span><span class=cF3>TRUE</span><span class=cF0>;
<a name="l376"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>FALSE</span><span class=cF0>;
<a name="l377"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l378"></a>
<a name="l379"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>TRUE</span><span class=cF0>;
<a name="l380"></a>}
<a name="l381"></a>
<a name="l382"></a></span><span class=cF1>Bool</span><span class=cF0> </span><span class=cFD>AHCIAtapiClose</span><span class=cF0>(</span><span class=cF9>CBlkDev</span><span class=cF0> *bd, </span><span class=cF9>I64</span><span class=cF0> close_field=</span><span class=cFE>0x200</span><span class=cF0>, </span><span class=cF9>I64</span><span class=cF0> track=</span><span class=cFE>0</span><span class=cF0>)
<a name="l383"></a>{</span><span class=cF2>//untested</span><span class=cF0>
<a name="l384"></a> </span><span class=cF9>CPortCmdTable</span><span class=cF0> *cmd_table;
<a name="l385"></a> </span><span class=cF9>CFisH2D</span><span class=cF0> *cmd_fis;
<a name="l386"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port = bd-&gt;ahci_port;
<a name="l387"></a> </span><span class=cF9>I64</span><span class=cF0> cmd_slot = </span><span class=cFD>AHCIPortCmdSlotGet</span><span class=cF0>(bd-&gt;port_num);
<a name="l388"></a> </span><span class=cF9>CPortCmdHeader</span><span class=cF0> *cmd_header = </span><span class=cFD>AHCIPortActiveHeaderGet</span><span class=cF0>(bd-&gt;port_num, cmd_slot);
<a name="l389"></a>
<a name="l390"></a> </span><span class=cF1>if</span><span class=cF0> (port-&gt;signature != </span><span class=cF3>AHCI_PxSIG_ATAPI</span><span class=cF0>)
<a name="l391"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l392"></a> </span><span class=cF5>SysErr</span><span class=cF0>(</span><span class=cF6>&quot;AHCI: Drive is not an ATAPI drive!\n&quot;</span><span class=cF0>);
<a name="l393"></a> </span><span class=cF5>throw</span><span class=cF0>(</span><span class=cF6>'AHCI'</span><span class=cF0>);
<a name="l394"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l395"></a>
<a name="l396"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;cmd_header-&gt;desc, </span><span class=cF3>AHCI_CH_DESCf_A</span><span class=cF0>);
<a name="l397"></a>
<a name="l398"></a> cmd_table = cmd_header-&gt;cmd_table_base;
<a name="l399"></a> </span><span class=cF5>MemSet</span><span class=cF0>(cmd_table, </span><span class=cFE>0</span><span class=cF0>, </span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF9>CPortCmdTable</span><span class=cF7>)</span><span class=cF0>);
<a name="l400"></a>
<a name="l401"></a> cmd_fis = cmd_table-&gt;cmd_fis;
<a name="l402"></a>
<a name="l403"></a> cmd_fis-&gt;type = </span><span class=cF3>FISt_H2D</span><span class=cF0>;
<a name="l404"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;cmd_fis-&gt;desc, </span><span class=cF3>AHCI_CF_DESCf_C</span><span class=cF0>); </span><span class=cF2>//Set Command bit in H2D FIS.</span><span class=cF0>
<a name="l405"></a> cmd_fis-&gt;command = </span><span class=cF3>ATA_PACKET</span><span class=cF0>;
<a name="l406"></a> cmd_table-&gt;acmd[</span><span class=cFE>0</span><span class=cF0>] = </span><span class=cF3>ATAPI_CLOSE_TRACK_SESSION</span><span class=cF0> &gt;&gt; </span><span class=cFE>8</span><span class=cF0>;
<a name="l407"></a> cmd_table-&gt;acmd[</span><span class=cFE>2</span><span class=cF0>] = close_field.u8[</span><span class=cFE>1</span><span class=cF0>];
<a name="l408"></a> cmd_table-&gt;acmd[</span><span class=cFE>4</span><span class=cF0>] = track.u8[</span><span class=cFE>1</span><span class=cF0>];
<a name="l409"></a> cmd_table-&gt;acmd[</span><span class=cFE>5</span><span class=cF0>] = track.u8[</span><span class=cFE>0</span><span class=cF0>];
<a name="l410"></a>
<a name="l411"></a> </span><span class=cFD>AHCIPortWait</span><span class=cF0>(bd-&gt;port_num, </span><span class=cF5>tS</span><span class=cF0> + </span><span class=cFE>2</span><span class=cF0>);
<a name="l412"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;port-&gt;cmd_issue, cmd_slot); </span><span class=cF2>//Issue the command.</span><span class=cF0>
<a name="l413"></a>
<a name="l414"></a> </span><span class=cF1>try</span><span class=cF0>
<a name="l415"></a> </span><span class=cFD>AHCIPortCmdWait</span><span class=cF0>(bd-&gt;port_num, cmd_slot);
<a name="l416"></a> </span><span class=cF1>catch</span><span class=cF0>
<a name="l417"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l418"></a> </span><span class=cF5>Fs</span><span class=cF0>-&gt;catch_except = </span><span class=cF3>TRUE</span><span class=cF0>;
<a name="l419"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>FALSE</span><span class=cF0>;
<a name="l420"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l421"></a>
<a name="l422"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>TRUE</span><span class=cF0>;
<a name="l423"></a>}
<a name="l424"></a>
<a name="l425"></a></span><span class=cF2>//TODO #define some bits/constants</span><span class=cF0>
<a name="l426"></a></span><span class=cF1>Bool</span><span class=cF0> </span><span class=cFD>AHCIAtapiFormat</span><span class=cF0>(</span><span class=cF9>CBlkDev</span><span class=cF0> *bd, </span><span class=cF9>I64</span><span class=cF0> count)
<a name="l427"></a>{ </span><span class=cF2>// untested</span><span class=cF0>
<a name="l428"></a> </span><span class=cF9>CPortCmdTable</span><span class=cF0> *cmd_table;
<a name="l429"></a> </span><span class=cF9>CFisH2D</span><span class=cF0> *cmd_fis;
<a name="l430"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port = bd-&gt;ahci_port;
<a name="l431"></a> </span><span class=cF9>I64</span><span class=cF0> cmd_slot = </span><span class=cFD>AHCIPortCmdSlotGet</span><span class=cF0>(bd-&gt;port_num);
<a name="l432"></a> </span><span class=cF9>CPortCmdHeader</span><span class=cF0> *cmd_header = </span><span class=cFD>AHCIPortActiveHeaderGet</span><span class=cF0>(bd-&gt;port_num, cmd_slot);
<a name="l433"></a> </span><span class=cF9>CAtapiFormatCmd</span><span class=cF0> format_cmd;
<a name="l434"></a> </span><span class=cF9>CAtapiFormatParamList</span><span class=cF0> *format_list;
<a name="l435"></a>
<a name="l436"></a> </span><span class=cF1>if</span><span class=cF0> (port-&gt;signature != </span><span class=cF3>AHCI_PxSIG_ATAPI</span><span class=cF0>)
<a name="l437"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l438"></a> </span><span class=cF5>SysErr</span><span class=cF0>(</span><span class=cF6>&quot;AHCI: Drive is not an ATAPI drive!\n&quot;</span><span class=cF0>);
<a name="l439"></a> </span><span class=cF5>throw</span><span class=cF0>(</span><span class=cF6>'AHCI'</span><span class=cF0>);
<a name="l440"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l441"></a>
<a name="l442"></a> format_list = </span><span class=cF5>CAlloc</span><span class=cF0>(</span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF9>CAtapiFormatParamList</span><span class=cF7>)</span><span class=cF0>, </span><span class=cFB>sys_task</span><span class=cF0>-&gt;code_heap);
<a name="l443"></a> format_list-&gt;length = </span><span class=cF5>EndianU16</span><span class=cF0>(</span><span class=cFE>8</span><span class=cF0>);
<a name="l444"></a> format_list-&gt;num_blocks = </span><span class=cF5>EndianU32</span><span class=cF0>(count</span><span class=cF7>(</span><span class=cF9>U32</span><span class=cF7>)</span><span class=cF0>); </span><span class=cF2>// remove this safety-cast if not needed</span><span class=cF0>
<a name="l445"></a> format_list-&gt;extra[</span><span class=cFE>1</span><span class=cF0>] = </span><span class=cFE>0x80</span><span class=cF0>;
<a name="l446"></a>
<a name="l447"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;cmd_header-&gt;desc, </span><span class=cF3>AHCI_CH_DESCf_A</span><span class=cF0>);
<a name="l448"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>Bts(&amp;cmd_header-&gt;desc, AHCI_CH_DESCf_W); // do we need to set Write ?</span><span class=cF0>
<a name="l449"></a>
<a name="l450"></a> cmd_table = cmd_header-&gt;cmd_table_base;
<a name="l451"></a> </span><span class=cF5>MemSet</span><span class=cF0>(cmd_table, </span><span class=cFE>0</span><span class=cF0>, </span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF9>CPortCmdTable</span><span class=cF7>)</span><span class=cF0>);
<a name="l452"></a>
<a name="l453"></a> cmd_table-&gt;prdt[</span><span class=cFE>0</span><span class=cF0>].data_base = format_list;
<a name="l454"></a> cmd_table-&gt;prdt[</span><span class=cFE>0</span><span class=cF0>].data_byte_count = </span><span class=cFE>12</span><span class=cF0> - </span><span class=cFE>1</span><span class=cF0>; </span><span class=cF2>// zero based, size of format parameter list</span><span class=cF0>
<a name="l455"></a> cmd_header-&gt;prdt_len = </span><span class=cFE>1</span><span class=cF0>;
<a name="l456"></a>
<a name="l457"></a> cmd_fis = cmd_table-&gt;cmd_fis;
<a name="l458"></a>
<a name="l459"></a> cmd_fis-&gt;type = </span><span class=cF3>FISt_H2D</span><span class=cF0>;
<a name="l460"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>cmd_fis-&gt;feature_low= 0x23; // Formattable?...</span><span class=cF0>
<a name="l461"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;cmd_fis-&gt;desc, </span><span class=cF3>AHCI_CF_DESCf_C</span><span class=cF0>); </span><span class=cF2>//Set Command bit in H2D FIS.</span><span class=cF0>
<a name="l462"></a> cmd_fis-&gt;command = </span><span class=cF3>ATA_PACKET</span><span class=cF0>;
<a name="l463"></a>
<a name="l464"></a> </span><span class=cF5>MemSet</span><span class=cF0>(&amp;format_cmd, </span><span class=cFE>0</span><span class=cF0>, </span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF9>CAtapiFormatCmd</span><span class=cF7>)</span><span class=cF0>);
<a name="l465"></a> format_cmd.command = </span><span class=cF3>ATAPI_FORMAT_UNIT</span><span class=cF0> &gt;&gt; </span><span class=cFE>8</span><span class=cF0>; </span><span class=cF2>//FIX</span><span class=cF0>
<a name="l466"></a> format_cmd.code = </span><span class=cFE>1</span><span class=cF0> | </span><span class=cFE>1</span><span class=cF0> &lt;&lt; </span><span class=cFE>4</span><span class=cF0>; </span><span class=cF2>// TODO !!! FORMAT UNIT CODE FLAGS (1 mandatory, 1&lt;&lt;4 mandatory for MM drives)</span><span class=cF0>
<a name="l467"></a> </span><span class=cF5>MemCopy</span><span class=cF0>(&amp;cmd_table-&gt;acmd, &amp;format_cmd, </span><span class=cFE>6</span><span class=cF0>); </span><span class=cF2>// ?</span><span class=cF0>
<a name="l468"></a>
<a name="l469"></a> </span><span class=cFD>AHCIPortWait</span><span class=cF0>(bd-&gt;port_num, </span><span class=cF5>tS</span><span class=cF0> + </span><span class=cFE>2</span><span class=cF0>);
<a name="l470"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;port-&gt;cmd_issue, cmd_slot); </span><span class=cF2>//Issue the command.</span><span class=cF0>
<a name="l471"></a>
<a name="l472"></a> </span><span class=cF1>try</span><span class=cF0>
<a name="l473"></a> </span><span class=cFD>AHCIPortCmdWait</span><span class=cF0>(bd-&gt;port_num, cmd_slot);
<a name="l474"></a> </span><span class=cF1>catch</span><span class=cF0>
<a name="l475"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l476"></a> </span><span class=cF5>Fs</span><span class=cF0>-&gt;catch_except = </span><span class=cF3>TRUE</span><span class=cF0>;
<a name="l477"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>FALSE</span><span class=cF0>;
<a name="l478"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l479"></a>
<a name="l480"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>TRUE</span><span class=cF0>;
<a name="l481"></a>}
<a name="l482"></a>
<a name="l483"></a></span><span class=cF1>Bool</span><span class=cF0> </span><span class=cF5>AHCIAtapiStartStop</span><span class=cF0>(</span><span class=cF9>CBlkDev</span><span class=cF0> *bd, </span><span class=cF1>Bool</span><span class=cF0> </span><span class=cF1>start</span><span class=cF0>)
<a name="l484"></a>{
<a name="l485"></a> </span><span class=cF9>CPortCmdTable</span><span class=cF0> *cmd_table;
<a name="l486"></a> </span><span class=cF9>CFisH2D</span><span class=cF0> *cmd_fis;
<a name="l487"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port = bd-&gt;ahci_port;
<a name="l488"></a> </span><span class=cF9>I64</span><span class=cF0> cmd_slot = </span><span class=cFD>AHCIPortCmdSlotGet</span><span class=cF0>(bd-&gt;port_num);
<a name="l489"></a> </span><span class=cF9>CPortCmdHeader</span><span class=cF0> *cmd_header = </span><span class=cFD>AHCIPortActiveHeaderGet</span><span class=cF0>(bd-&gt;port_num, cmd_slot);
<a name="l490"></a>
<a name="l491"></a> </span><span class=cF1>if</span><span class=cF0> (port-&gt;signature != </span><span class=cF3>AHCI_PxSIG_ATAPI</span><span class=cF0>)
<a name="l492"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l493"></a> </span><span class=cF5>SysErr</span><span class=cF0>(</span><span class=cF6>&quot;AHCI: Drive is not an ATAPI drive!\n&quot;</span><span class=cF0>);
<a name="l494"></a> </span><span class=cF5>throw</span><span class=cF0>(</span><span class=cF6>'AHCI'</span><span class=cF0>);
<a name="l495"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l496"></a>
<a name="l497"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;cmd_header-&gt;desc, </span><span class=cF3>AHCI_CH_DESCf_A</span><span class=cF0>);
<a name="l498"></a>
<a name="l499"></a> cmd_table = cmd_header-&gt;cmd_table_base;
<a name="l500"></a> </span><span class=cF5>MemSet</span><span class=cF0>(cmd_table, </span><span class=cFE>0</span><span class=cF0>, </span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF9>CPortCmdTable</span><span class=cF7>)</span><span class=cF0>);
<a name="l501"></a>
<a name="l502"></a> cmd_fis = cmd_table-&gt;cmd_fis;
<a name="l503"></a>
<a name="l504"></a> cmd_fis-&gt;type = </span><span class=cF3>FISt_H2D</span><span class=cF0>;
<a name="l505"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;cmd_fis-&gt;desc, </span><span class=cF3>AHCI_CF_DESCf_C</span><span class=cF0>); </span><span class=cF2>//Set Command bit in H2D FIS.</span><span class=cF0>
<a name="l506"></a> cmd_fis-&gt;command = </span><span class=cF3>ATA_PACKET</span><span class=cF0>;
<a name="l507"></a> cmd_table-&gt;acmd[</span><span class=cFE>0</span><span class=cF0>] = </span><span class=cF3>ATAPI_START_STOP_UNIT</span><span class=cF0> &gt;&gt; </span><span class=cFE>8</span><span class=cF0>;
<a name="l508"></a> cmd_table-&gt;acmd[</span><span class=cFE>4</span><span class=cF0>] = </span><span class=cF1>start</span><span class=cF0>;
<a name="l509"></a>
<a name="l510"></a> </span><span class=cFD>AHCIPortWait</span><span class=cF0>(bd-&gt;port_num, </span><span class=cF5>tS</span><span class=cF0> + </span><span class=cFE>2</span><span class=cF0>);
<a name="l511"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;port-&gt;cmd_issue, cmd_slot); </span><span class=cF2>//Issue the command.</span><span class=cF0>
<a name="l512"></a>
<a name="l513"></a> </span><span class=cF1>try</span><span class=cF0>
<a name="l514"></a> </span><span class=cFD>AHCIPortCmdWait</span><span class=cF0>(bd-&gt;port_num, cmd_slot);
<a name="l515"></a> </span><span class=cF1>catch</span><span class=cF0>
<a name="l516"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l517"></a> </span><span class=cF5>Fs</span><span class=cF0>-&gt;catch_except = </span><span class=cF3>TRUE</span><span class=cF0>;
<a name="l518"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>FALSE</span><span class=cF0>;
<a name="l519"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l520"></a>
<a name="l521"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>TRUE</span><span class=cF0>;
<a name="l522"></a>}
<a name="l523"></a>
<a name="l524"></a></span><span class=cF1>Bool</span><span class=cF0> </span><span class=cF5>DiscEject</span><span class=cF0>(</span><span class=cF1>U8</span><span class=cF0> drv_let)
<a name="l525"></a>{ </span><span class=cF2>// returns whether disc tray was successfully ejected.</span><span class=cF0>
<a name="l526"></a> </span><span class=cF1>try</span><span class=cF0>
<a name="l527"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF5>AHCIAtapiStartStop</span><span class=cF0>(</span><span class=cF5>Letter2BlkDev</span><span class=cF7>(</span><span class=cF0>drv_let</span><span class=cF7>)</span><span class=cF0>, </span><span class=cFE>2</span><span class=cF0>);
<a name="l528"></a> </span><span class=cF1>catch</span><span class=cF0>
<a name="l529"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l530"></a> </span><span class=cF5>Fs</span><span class=cF0>-&gt;catch_except = </span><span class=cF3>TRUE</span><span class=cF0>;
<a name="l531"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>FALSE</span><span class=cF0>;
<a name="l532"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l533"></a>}
<a name="l534"></a>
<a name="l535"></a></span><span class=cF1>Bool</span><span class=cF0> </span><span class=cF5>DiscLoad</span><span class=cF0>(</span><span class=cF1>U8</span><span class=cF0> drv_let)
<a name="l536"></a>{ </span><span class=cF2>// returns whether disc tray was successfully closed &amp; disc loaded.</span><span class=cF0>
<a name="l537"></a> </span><span class=cF1>try</span><span class=cF0>
<a name="l538"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF5>AHCIAtapiStartStop</span><span class=cF0>(</span><span class=cF5>Letter2BlkDev</span><span class=cF7>(</span><span class=cF0>drv_let</span><span class=cF7>)</span><span class=cF0>, </span><span class=cFE>3</span><span class=cF0>);
<a name="l539"></a> </span><span class=cF1>catch</span><span class=cF0>
<a name="l540"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l541"></a> </span><span class=cF5>Fs</span><span class=cF0>-&gt;catch_except = </span><span class=cF3>TRUE</span><span class=cF0>;
<a name="l542"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>FALSE</span><span class=cF0>;
<a name="l543"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l544"></a>}
<a name="l545"></a>
<a name="l546"></a></span><span class=cF1>U0</span><span class=cF0> </span><span class=cFD>AHCIPortIdentify</span><span class=cF0>(</span><span class=cF9>CBlkDev</span><span class=cF0> *bd)
<a name="l547"></a>{</span><span class=cF2>//Perform ATA_IDENTIFY command on ATA/ATAPI drive and store capacity and id record.</span><span class=cF0>
<a name="l548"></a> </span><span class=cF9>CPortCmdTable</span><span class=cF0> *cmd_table;
<a name="l549"></a> </span><span class=cF9>CFisH2D</span><span class=cF0> *cmd_fis;
<a name="l550"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port = bd-&gt;ahci_port;
<a name="l551"></a> </span><span class=cF9>I64</span><span class=cF0> cmd_slot = </span><span class=cFD>AHCIPortCmdSlotGet</span><span class=cF0>(bd-&gt;port_num);
<a name="l552"></a> </span><span class=cF9>CPortCmdHeader</span><span class=cF0> *cmd_header = </span><span class=cFD>AHCIPortActiveHeaderGet</span><span class=cF0>(bd-&gt;port_num, cmd_slot);
<a name="l553"></a> </span><span class=cF9>U16</span><span class=cF0> *dev_id_record;
<a name="l554"></a>
<a name="l555"></a> port-&gt;interrupt_status = port-&gt;interrupt_status; </span><span class=cF2>//TODO: Why?</span><span class=cF0>
<a name="l556"></a>
<a name="l557"></a> </span><span class=cF2>//Using the code heap for this alloc to stay under 32-bit address space.</span><span class=cF0>
<a name="l558"></a> dev_id_record = </span><span class=cF5>CAlloc</span><span class=cF0>(</span><span class=cFE>512</span><span class=cF0>, </span><span class=cFB>sys_task</span><span class=cF0>-&gt;code_heap);
<a name="l559"></a>
<a name="l560"></a> cmd_table = cmd_header-&gt;cmd_table_base;
<a name="l561"></a> </span><span class=cF5>MemSet</span><span class=cF0>(cmd_table, </span><span class=cFE>0</span><span class=cF0>, </span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF9>CPortCmdTable</span><span class=cF7>)</span><span class=cF0>);
<a name="l562"></a>
<a name="l563"></a> </span><span class=cF2>//Set up single PRD</span><span class=cF0>
<a name="l564"></a> cmd_table-&gt;prdt[</span><span class=cFE>0</span><span class=cF0>].data_base = dev_id_record;
<a name="l565"></a> cmd_table-&gt;prdt[</span><span class=cFE>0</span><span class=cF0>].data_base_upper = </span><span class=cFE>0</span><span class=cF0>;
<a name="l566"></a> cmd_table-&gt;prdt[</span><span class=cFE>0</span><span class=cF0>].data_byte_count = </span><span class=cFE>512</span><span class=cF0> - </span><span class=cFE>1</span><span class=cF0>; </span><span class=cF2>//Zero-based value</span><span class=cF0>
<a name="l567"></a> cmd_header-&gt;prdt_len = </span><span class=cFE>1</span><span class=cF0>; </span><span class=cF2>//1 PRD, as described above, which contains the address to put the ID record.</span><span class=cF0>
<a name="l568"></a>
<a name="l569"></a> </span><span class=cF2>//Setup command FIS</span><span class=cF0>
<a name="l570"></a> cmd_fis = cmd_table-&gt;cmd_fis;
<a name="l571"></a>
<a name="l572"></a> cmd_fis-&gt;type = </span><span class=cF3>FISt_H2D</span><span class=cF0>;
<a name="l573"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;cmd_fis-&gt;desc, </span><span class=cF3>AHCI_CF_DESCf_C</span><span class=cF0>); </span><span class=cF2>//Set Command bit in H2D FIS.</span><span class=cF0>
<a name="l574"></a>
<a name="l575"></a> </span><span class=cF1>if</span><span class=cF0> (port-&gt;signature == </span><span class=cF3>AHCI_PxSIG_ATAPI</span><span class=cF0>)
<a name="l576"></a> cmd_fis-&gt;command = </span><span class=cF3>ATA_IDENTIFY_PACKET</span><span class=cF0>;
<a name="l577"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l578"></a> cmd_fis-&gt;command = </span><span class=cF3>ATA_IDENTIFY</span><span class=cF0>;
<a name="l579"></a>
<a name="l580"></a> cmd_fis-&gt;device = </span><span class=cFE>0</span><span class=cF0>; </span><span class=cF2>//No bits need to be set in the device register.</span><span class=cF0>
<a name="l581"></a>
<a name="l582"></a> </span><span class=cF2>//Wait on previous command to complete.</span><span class=cF0>
<a name="l583"></a> </span><span class=cFD>AHCIPortWait</span><span class=cF0>(bd-&gt;port_num, </span><span class=cF5>tS</span><span class=cF0> + </span><span class=cFE>2</span><span class=cF0>);
<a name="l584"></a>
<a name="l585"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;port-&gt;cmd_issue, cmd_slot); </span><span class=cF2>//Issue the command.</span><span class=cF0>
<a name="l586"></a> </span><span class=cFD>AHCIPortCmdWait</span><span class=cF0>(bd-&gt;port_num, cmd_slot);
<a name="l587"></a>
<a name="l588"></a> </span><span class=cF5>Free</span><span class=cF0>(bd-&gt;dev_id_record);
<a name="l589"></a> bd-&gt;dev_id_record = dev_id_record;
<a name="l590"></a>
<a name="l591"></a> </span><span class=cF1>if</span><span class=cF0> (port-&gt;signature == </span><span class=cF3>AHCI_PxSIG_ATA</span><span class=cF0>)
<a name="l592"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l593"></a> bd-&gt;max_blk = </span><span class=cFD>AHCILBA48CapacityGet</span><span class=cF0>(dev_id_record);
<a name="l594"></a> </span><span class=cF6>&quot;MAX BLOCK %d, disk size %d MiB\n&quot;</span><span class=cF0>, bd-&gt;max_blk, bd-&gt;max_blk * </span><span class=cF3>BLK_SIZE</span><span class=cF0> / </span><span class=cFE>1024</span><span class=cF0> / </span><span class=cFE>1024</span><span class=cF0>;
<a name="l595"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l596"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l597"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l598"></a> bd-&gt;max_blk = </span><span class=cFD>AHCIAtapiCapacityGet</span><span class=cF0>(bd);
<a name="l599"></a> </span><span class=cF6>&quot;MAX BLOCK %d, disk size %d MiB\n&quot;</span><span class=cF0>, bd-&gt;max_blk, bd-&gt;max_blk * </span><span class=cF3>DVD_BLK_SIZE</span><span class=cF0> / </span><span class=cFE>1024</span><span class=cF0> / </span><span class=cFE>1024</span><span class=cF0>;
<a name="l600"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l601"></a>}
<a name="l602"></a>
<a name="l603"></a></span><span class=cF1>U8</span><span class=cF0> *</span><span class=cFD>AHCIBufferAlign</span><span class=cF0>(</span><span class=cF9>CBlkDev</span><span class=cF0> *bd, </span><span class=cF1>U8</span><span class=cF0> *user_buf, </span><span class=cF9>I64</span><span class=cF0> buf_size, </span><span class=cF1>Bool</span><span class=cF0> write)
<a name="l604"></a>{</span><span class=cF2>//Make sure buffer is accessible by HBA controller.</span><span class=cF0>
<a name="l605"></a></span><span class=cF2>//Controller requires a U16 aligned buffer and in 32-bit address space (We are not using 64-bit capabilities).</span><span class=cF0>
<a name="l606"></a></span><span class=cF2>//MAlloc provides U64-aligned addresses, and can allocate in the code heap ( &lt;4GB ).</span><span class=cF0>
<a name="l607"></a></span><span class=cF2>//In the case of an inadequate buffer address being passed in, we will use a MAlloced internal buffer.</span><span class=cF0>
<a name="l608"></a> </span><span class=cF1>if</span><span class=cF0>(user_buf + buf_size &gt; </span><span class=cF3>U32_MAX</span><span class=cF0> || user_buf &amp; </span><span class=cFE>1</span><span class=cF0>)
<a name="l609"></a> </span><span class=cF7>{</span><span class=cF2>//if the buffer is not within 32-bit address space or not U16-aligned</span><span class=cF0>
<a name="l610"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>&quot;Aligning buffer under 32-bit range\n&quot;;</span><span class=cF0>
<a name="l611"></a>
<a name="l612"></a> </span><span class=cF5>Free</span><span class=cF0>(bd-&gt;prd_buf);
<a name="l613"></a> bd-&gt;prd_buf = </span><span class=cF5>MAlloc</span><span class=cF0>(buf_size, </span><span class=cFB>sys_task</span><span class=cF0>-&gt;code_heap);
<a name="l614"></a>
<a name="l615"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;bd-&gt;flags, </span><span class=cF3>BDf_INTERNAL_BUF</span><span class=cF0>);
<a name="l616"></a>
<a name="l617"></a> </span><span class=cF1>if</span><span class=cF0> (write)
<a name="l618"></a> </span><span class=cF5>MemCopy</span><span class=cF0>(bd-&gt;prd_buf, user_buf, buf_size);
<a name="l619"></a>
<a name="l620"></a> </span><span class=cF1>return</span><span class=cF0> bd-&gt;prd_buf;
<a name="l621"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l622"></a> </span><span class=cF5>Btr</span><span class=cF0>(&amp;bd-&gt;flags, </span><span class=cF3>BDF_INTERNAL_BUF</span><span class=cF0>);
<a name="l623"></a>
<a name="l624"></a> </span><span class=cF1>return</span><span class=cF0> user_buf;
<a name="l625"></a>}
<a name="l626"></a>
<a name="l627"></a></span><span class=cF9>I64</span><span class=cF0> </span><span class=cF5>AHCIAtaBlksRW</span><span class=cF0>(</span><span class=cF9>CBlkDev</span><span class=cF0> *bd, </span><span class=cF1>U8</span><span class=cF0> *buf, </span><span class=cF9>I64</span><span class=cF0> blk, </span><span class=cF9>I64</span><span class=cF0> count, </span><span class=cF1>Bool</span><span class=cF0> write)
<a name="l628"></a>{</span><span class=cF2>//Read/Write ATA disk blocks. Returns number of bytes transferred between system and disk.</span><span class=cF0>
<a name="l629"></a></span><span class=cF2>//Don't use this, use the AHCIAtaBlksRead and AHCIAtaBlksWrite functions.</span><span class=cF0>
<a name="l630"></a> </span><span class=cF9>CPortCmdTable</span><span class=cF0> *cmd_table;
<a name="l631"></a> </span><span class=cF9>CFisH2D</span><span class=cF0> *cmd_fis;
<a name="l632"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port = bd-&gt;ahci_port;
<a name="l633"></a> </span><span class=cF9>I64</span><span class=cF0> i, buf_size, buf_size_tmp, byte_count, prdt_len, cmd_slot = </span><span class=cFD>AHCIPortCmdSlotGet</span><span class=cF0>(bd-&gt;port_num);
<a name="l634"></a> </span><span class=cF9>CPortCmdHeader</span><span class=cF0> *cmd_header = </span><span class=cFD>AHCIPortActiveHeaderGet</span><span class=cF0>(bd-&gt;port_num, cmd_slot);
<a name="l635"></a> </span><span class=cF1>U8</span><span class=cF0> *internal_buf_tmp, *internal_buf;
<a name="l636"></a> </span><span class=cF1>Bool</span><span class=cF0> unlock;
<a name="l637"></a>
<a name="l638"></a> </span><span class=cF1>if</span><span class=cF0> (port-&gt;signature != </span><span class=cF3>AHCI_PxSIG_ATA</span><span class=cF0>)
<a name="l639"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l640"></a> </span><span class=cF5>SysErr</span><span class=cF0>(</span><span class=cF6>&quot;AHCI: Drive is not an ATA drive!\n&quot;</span><span class=cF0>);
<a name="l641"></a> </span><span class=cF5>throw</span><span class=cF0>(</span><span class=cF6>'AHCI'</span><span class=cF0>);
<a name="l642"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l643"></a>
<a name="l644"></a> </span><span class=cF1>if</span><span class=cF0> (count &lt; </span><span class=cFE>1</span><span class=cF0>) </span><span class=cF1>return</span><span class=cF0> </span><span class=cFE>0</span><span class=cF0>;
<a name="l645"></a> </span><span class=cF1>if</span><span class=cF0> (count &gt; </span><span class=cF3>AHCI_PRDT_MAX_BLOCKS</span><span class=cF0>)
<a name="l646"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l647"></a> </span><span class=cF5>SysErr</span><span class=cF0>(</span><span class=cF6>&quot;AHCI: Block count %d max allowed in one command (%d)&quot;</span><span class=cF0>, count, </span><span class=cF3>AHCI_PRDT_MAX_BLOCKS</span><span class=cF0>);
<a name="l648"></a> </span><span class=cF5>throw</span><span class=cF0>(</span><span class=cF6>'AHCI'</span><span class=cF0>);
<a name="l649"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l650"></a>
<a name="l651"></a> unlock = </span><span class=cF5>BlkDevLock</span><span class=cF0>(bd);
<a name="l652"></a>
<a name="l653"></a> </span><span class=cF2>//Determine buffer size and PRDT length.</span><span class=cF0>
<a name="l654"></a> buf_size = buf_size_tmp = count * </span><span class=cF3>BLK_SIZE</span><span class=cF0>;
<a name="l655"></a> prdt_len = (buf_size - </span><span class=cFE>1</span><span class=cF0>) / </span><span class=cF3>AHCI_PRD_MAX_BYTES</span><span class=cF0> + </span><span class=cFE>1</span><span class=cF0>;
<a name="l656"></a>
<a name="l657"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>&quot;PRDT Length:\t%d\n&quot;, prdt_len;</span><span class=cF0>
<a name="l658"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>&quot;Count:\t\t\t%d\n&quot;, count;</span><span class=cF0>
<a name="l659"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>&quot;Buffer size:\t%X\n&quot;, buf_size;</span><span class=cF0>
<a name="l660"></a>
<a name="l661"></a> cmd_header-&gt;prdt_len = prdt_len; </span><span class=cF2>//Set PRD table length in cmd header.</span><span class=cF0>
<a name="l662"></a> </span><span class=cF2>//Set 'write' bit depending on 'write' argument.</span><span class=cF0>
<a name="l663"></a> </span><span class=cF5>BEqual</span><span class=cF0>(&amp;cmd_header-&gt;desc, </span><span class=cF3>AHCI_CH_DESCf_W</span><span class=cF0>, write);
<a name="l664"></a>
<a name="l665"></a> internal_buf = internal_buf_tmp = </span><span class=cFD>AHCIBufferAlign</span><span class=cF0>(bd, buf, buf_size, write);
<a name="l666"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>&quot;Buffer:\t\t\t0x%X\n&quot;, internal_buf;</span><span class=cF0>
<a name="l667"></a>
<a name="l668"></a> </span><span class=cF1>if</span><span class=cF0> (!internal_buf) </span><span class=cF5>throw</span><span class=cF0>(</span><span class=cF6>'AHCI'</span><span class=cF0>); </span><span class=cF2>//Will probably never happen.</span><span class=cF0>
<a name="l669"></a>
<a name="l670"></a> </span><span class=cF2>//Obtain command table and zero it. This contains the command FIS and the PRDT.</span><span class=cF0>
<a name="l671"></a> cmd_table = cmd_header-&gt;cmd_table_base;
<a name="l672"></a> </span><span class=cF5>MemSet</span><span class=cF0>(cmd_table, </span><span class=cFE>0</span><span class=cF0>, </span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF9>CPortCmdTable</span><span class=cF7>)</span><span class=cF0>);
<a name="l673"></a>
<a name="l674"></a> </span><span class=cF2>//Create 'prdt_len' amount of PRD entries in the command table</span><span class=cF0>
<a name="l675"></a> </span><span class=cF1>for</span><span class=cF0> (i = </span><span class=cFE>0</span><span class=cF0>; i &lt; prdt_len; i++)
<a name="l676"></a> </span><span class=cF7>{</span><span class=cF2>//Use max PRD size until the remaining buffer is smaller than max size.</span><span class=cF0>
<a name="l677"></a> </span><span class=cF1>if</span><span class=cF0> (buf_size_tmp &gt; </span><span class=cF3>AHCI_PRD_MAX_BYTES</span><span class=cF0>)
<a name="l678"></a> byte_count = </span><span class=cF3>AHCI_PRD_MAX_BYTES</span><span class=cF0>;
<a name="l679"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l680"></a> byte_count = buf_size_tmp;
<a name="l681"></a>
<a name="l682"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>&quot;prdt[%d].data_base_addr = 0x%X\n&quot; , i, internal_buf_tmp;</span><span class=cF0>
<a name="l683"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>&quot;prdt[%d].data_byte_count = 0x%X\n\n&quot;, i, byte_count;</span><span class=cF0>
<a name="l684"></a>
<a name="l685"></a> cmd_table-&gt;prdt[i].data_base = internal_buf_tmp;
<a name="l686"></a> cmd_table-&gt;prdt[i].data_byte_count = byte_count - </span><span class=cFE>1</span><span class=cF0>; </span><span class=cF2>//Zero-based value</span><span class=cF0>
<a name="l687"></a> buf_size_tmp -= byte_count;
<a name="l688"></a> internal_buf_tmp += byte_count;
<a name="l689"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l690"></a> </span><span class=cF2>//Setup the command FIS.</span><span class=cF0>
<a name="l691"></a> cmd_fis = cmd_table-&gt;cmd_fis;
<a name="l692"></a>
<a name="l693"></a> cmd_fis-&gt;type = </span><span class=cF3>FISt_H2D</span><span class=cF0>;
<a name="l694"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;cmd_fis-&gt;desc, </span><span class=cF3>AHCI_CF_DESCf_C</span><span class=cF0>); </span><span class=cF2>//Set Command bit in H2D FIS</span><span class=cF0>
<a name="l695"></a>
<a name="l696"></a> </span><span class=cF1>if</span><span class=cF0> (write) </span><span class=cF2>//Assumed support for LBA48.</span><span class=cF0>
<a name="l697"></a> cmd_fis-&gt;command = </span><span class=cF3>ATA_WRITE_DMA_EXT</span><span class=cF0>;
<a name="l698"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l699"></a> cmd_fis-&gt;command = </span><span class=cF3>ATA_READ_DMA_EXT</span><span class=cF0>;
<a name="l700"></a>
<a name="l701"></a> </span><span class=cF2>//Fill in the rest of the command FIS.</span><span class=cF0>
<a name="l702"></a> cmd_fis-&gt;lba0 = blk.u8[</span><span class=cFE>0</span><span class=cF0>];
<a name="l703"></a> cmd_fis-&gt;lba1 = blk.u8[</span><span class=cFE>1</span><span class=cF0>];
<a name="l704"></a> cmd_fis-&gt;lba2 = blk.u8[</span><span class=cFE>2</span><span class=cF0>];
<a name="l705"></a> cmd_fis-&gt;device = </span><span class=cFE>1</span><span class=cF0> &lt;&lt; </span><span class=cFE>6</span><span class=cF0>; </span><span class=cF2>//Required as per ATA8-ACS section 7.25.3</span><span class=cF0>
<a name="l706"></a> cmd_fis-&gt;lba3 = blk.u8[</span><span class=cFE>3</span><span class=cF0>];
<a name="l707"></a> cmd_fis-&gt;lba4 = blk.u8[</span><span class=cFE>4</span><span class=cF0>];
<a name="l708"></a> cmd_fis-&gt;lba5 = blk.u8[</span><span class=cFE>5</span><span class=cF0>];
<a name="l709"></a> cmd_fis-&gt;count = count;
<a name="l710"></a>
<a name="l711"></a> </span><span class=cF2>//Wait on previous command to complete.</span><span class=cF0>
<a name="l712"></a> </span><span class=cFD>AHCIPortWait</span><span class=cF0>(bd-&gt;port_num, </span><span class=cF5>tS</span><span class=cF0> + </span><span class=cFE>2</span><span class=cF0>);
<a name="l713"></a> </span><span class=cF2>//Issue the command.</span><span class=cF0>
<a name="l714"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;port-&gt;cmd_issue, cmd_slot);
<a name="l715"></a> </span><span class=cF2>//Wait on command to finish.</span><span class=cF0>
<a name="l716"></a> </span><span class=cFD>AHCIPortCmdWait</span><span class=cF0>(bd-&gt;port_num, cmd_slot);
<a name="l717"></a>
<a name="l718"></a> </span><span class=cF1>if</span><span class=cF0> (!write) </span><span class=cF2>//If internal_buf was created it back to argument buf.</span><span class=cF0>
<a name="l719"></a> </span><span class=cF1>if</span><span class=cF0> (bd-&gt;flags &amp; </span><span class=cF3>BDF_INTERNAL_BUF</span><span class=cF0>)
<a name="l720"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l721"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>&quot;Writing back internal buffer\n&quot;;</span><span class=cF0>
<a name="l722"></a> </span><span class=cF5>MemCopy</span><span class=cF0>(buf, internal_buf, buf_size);
<a name="l723"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l724"></a>
<a name="l725"></a> </span><span class=cF1>if</span><span class=cF0> (unlock)
<a name="l726"></a> </span><span class=cF5>BlkDevUnlock</span><span class=cF0>(bd);
<a name="l727"></a>
<a name="l728"></a> </span><span class=cF1>return</span><span class=cF0> cmd_header-&gt;prd_byte_count;
<a name="l729"></a>}
<a name="l730"></a>
<a name="l731"></a></span><span class=cF9>I64</span><span class=cF0> </span><span class=cF5>AHCIAtaBlksRead</span><span class=cF0>(</span><span class=cF9>CBlkDev</span><span class=cF0> *bd, </span><span class=cF1>U8</span><span class=cF0> *buf, </span><span class=cF9>I64</span><span class=cF0> blk, </span><span class=cF9>I64</span><span class=cF0> count)
<a name="l732"></a>{</span><span class=cF2>//Read 'blk' amount of blocks from AHCI disk device. Returns num of bytes transferred between disk and memory.</span><span class=cF0>
<a name="l733"></a> </span><span class=cF9>I64</span><span class=cF0> byte_count = </span><span class=cFE>0</span><span class=cF0>;
<a name="l734"></a> </span><span class=cF1>if</span><span class=cF0> (!count)
<a name="l735"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cFE>0</span><span class=cF0>;
<a name="l736"></a> </span><span class=cF1>if</span><span class=cF0> (count &lt;= </span><span class=cF3>AHCI_PRDT_MAX_BLOCKS</span><span class=cF0>)
<a name="l737"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l738"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>&quot;$GREEN$READ less than MAX_BLOCKS$FG$\n&quot;;</span><span class=cF0>
<a name="l739"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF5>AHCIAtaBlksRW</span><span class=cF0>(bd, buf, blk, count, </span><span class=cF3>FALSE</span><span class=cF0>);
<a name="l740"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l741"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l742"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l743"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>&quot;$GREEN$READ greater than MAX_BLOCKS\n&quot;;</span><span class=cF0>
<a name="l744"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>&quot;read count: %d\n$FG$&quot;, count;</span><span class=cF0>
<a name="l745"></a> </span><span class=cF1>while</span><span class=cF0> (count &gt; </span><span class=cF3>AHCI_PRDT_MAX_BLOCKS</span><span class=cF0>)
<a name="l746"></a> {
<a name="l747"></a> byte_count += </span><span class=cF5>AHCIAtaBlksRW</span><span class=cF0>(bd, buf, blk, </span><span class=cF3>AHCI_PRDT_MAX_BLOCKS</span><span class=cF0>, </span><span class=cF3>FALSE</span><span class=cF0>);
<a name="l748"></a> count -= </span><span class=cF3>AHCI_PRDT_MAX_BLOCKS</span><span class=cF0>;
<a name="l749"></a> blk += </span><span class=cF3>AHCI_PRDT_MAX_BLOCKS</span><span class=cF0>;
<a name="l750"></a> buf += </span><span class=cF3>AHCI_PRDT_MAX_BLOCKS</span><span class=cF0> * </span><span class=cF3>BLK_SIZE</span><span class=cF0>;
<a name="l751"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>&quot;$GREEN$read count: %d\n$FG$&quot;, count;</span><span class=cF0>
<a name="l752"></a> }
<a name="l753"></a> byte_count += </span><span class=cF5>AHCIAtaBlksRW</span><span class=cF0>(bd, buf, blk, count, </span><span class=cF3>FALSE</span><span class=cF0>);
<a name="l754"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l755"></a>
<a name="l756"></a> </span><span class=cFB>blkdev</span><span class=cF0>.read_count += (count * bd-&gt;blk_size) &gt;&gt; </span><span class=cF3>BLK_SIZE_BITS</span><span class=cF0>;
<a name="l757"></a>
<a name="l758"></a> </span><span class=cF1>return</span><span class=cF0> byte_count;
<a name="l759"></a>}
<a name="l760"></a>
<a name="l761"></a></span><span class=cF9>I64</span><span class=cF0> </span><span class=cF5>AHCIAtaBlksWrite</span><span class=cF0>(</span><span class=cF9>CBlkDev</span><span class=cF0> *bd, </span><span class=cF1>U8</span><span class=cF0> *buf, </span><span class=cF9>I64</span><span class=cF0> blk, </span><span class=cF9>I64</span><span class=cF0> count)
<a name="l762"></a>{</span><span class=cF2>//Write 'blk' amount of blocks to AHCI disk device. Returns num of bytes transferred between memory and disk.</span><span class=cF0>
<a name="l763"></a> </span><span class=cF9>I64</span><span class=cF0> byte_count = </span><span class=cFE>0</span><span class=cF0>;
<a name="l764"></a>
<a name="l765"></a> </span><span class=cF1>if</span><span class=cF0> (!count)
<a name="l766"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cFE>0</span><span class=cF0>;
<a name="l767"></a> </span><span class=cF1>if</span><span class=cF0> (count &lt;= </span><span class=cF3>AHCI_PRDT_MAX_BLOCKS</span><span class=cF0>)
<a name="l768"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l769"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>&quot;$GREEN$WRITE less than MAX_BLOCKS$FG$\n&quot;;</span><span class=cF0>
<a name="l770"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF5>AHCIAtaBlksRW</span><span class=cF0>(bd, buf, blk, count, </span><span class=cF3>TRUE</span><span class=cF0>);
<a name="l771"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l772"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l773"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l774"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>&quot;$GREEN$WRITE greater than MAX_BLOCKS\n&quot;;</span><span class=cF0>
<a name="l775"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>&quot;write count: %d$FG$\n&quot;, count;</span><span class=cF0>
<a name="l776"></a> </span><span class=cF1>while</span><span class=cF0> (count &gt; </span><span class=cF3>AHCI_PRDT_MAX_BLOCKS</span><span class=cF0>)
<a name="l777"></a> {
<a name="l778"></a> byte_count += </span><span class=cF5>AHCIAtaBlksRW</span><span class=cF0>(bd, buf, blk, </span><span class=cF3>AHCI_PRDT_MAX_BLOCKS</span><span class=cF0>, </span><span class=cF3>TRUE</span><span class=cF0>);
<a name="l779"></a> count -= </span><span class=cF3>AHCI_PRDT_MAX_BLOCKS</span><span class=cF0>;
<a name="l780"></a> blk += </span><span class=cF3>AHCI_PRDT_MAX_BLOCKS</span><span class=cF0>;
<a name="l781"></a> buf += </span><span class=cF3>AHCI_PRDT_MAX_BLOCKS</span><span class=cF0> * </span><span class=cF3>BLK_SIZE</span><span class=cF0>;
<a name="l782"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>&quot;$GREEN$write count: %d\n$FG$\n&quot;, count;</span><span class=cF0>
<a name="l783"></a> }
<a name="l784"></a> byte_count += </span><span class=cF5>AHCIAtaBlksRW</span><span class=cF0>(bd, buf, blk, count, </span><span class=cF3>TRUE</span><span class=cF0>);
<a name="l785"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l786"></a>
<a name="l787"></a> </span><span class=cF1>return</span><span class=cF0> byte_count;
<a name="l788"></a>}
<a name="l789"></a>
<a name="l790"></a></span><span class=cF9>I64</span><span class=cF0> </span><span class=cF5>AHCIAtapiBlksRead</span><span class=cF0>(</span><span class=cF9>CBlkDev</span><span class=cF0> *bd, </span><span class=cF1>U8</span><span class=cF0> *buf, </span><span class=cF9>I64</span><span class=cF0> blk, </span><span class=cF9>I64</span><span class=cF0> count, </span><span class=cF1>Bool</span><span class=cF0> </span><span class=cF1>lock</span><span class=cF0>=</span><span class=cF3>TRUE</span><span class=cF0>)
<a name="l791"></a>{</span><span class=cF2>//Read 'blk' amount of blocks from from AHCI ATAPI device. Returns num of bytes transferred.</span><span class=cF0>
<a name="l792"></a> </span><span class=cF9>CPortCmdTable</span><span class=cF0> *cmd_table;
<a name="l793"></a> </span><span class=cF9>CFisH2D</span><span class=cF0> *cmd_fis;
<a name="l794"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port = bd-&gt;ahci_port;
<a name="l795"></a> </span><span class=cF9>I64</span><span class=cF0> i, byte_count, buf_size, buf_size_tmp, prdt_len, cmd_slot = </span><span class=cFD>AHCIPortCmdSlotGet</span><span class=cF0>(bd-&gt;port_num);
<a name="l796"></a> </span><span class=cF9>CPortCmdHeader</span><span class=cF0> *cmd_header = </span><span class=cFD>AHCIPortActiveHeaderGet</span><span class=cF0>(bd-&gt;port_num, cmd_slot);
<a name="l797"></a> </span><span class=cF1>U8</span><span class=cF0> *internal_buf, *internal_buf_tmp;
<a name="l798"></a> </span><span class=cF9>CAtapiReadCmd</span><span class=cF0> read_cmd;
<a name="l799"></a> </span><span class=cF1>Bool</span><span class=cF0> unlock;
<a name="l800"></a>
<a name="l801"></a> </span><span class=cF1>if</span><span class=cF0> (port-&gt;signature != </span><span class=cF3>AHCI_PxSIG_ATAPI</span><span class=cF0>)
<a name="l802"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l803"></a> </span><span class=cF5>SysErr</span><span class=cF0>(</span><span class=cF6>&quot;AHCI: Drive is not an ATAPI drive!\n&quot;</span><span class=cF0>);
<a name="l804"></a> </span><span class=cF5>throw</span><span class=cF0>(</span><span class=cF6>'AHCI'</span><span class=cF0>);
<a name="l805"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l806"></a> </span><span class=cF1>if</span><span class=cF0> (count &lt; </span><span class=cFE>1</span><span class=cF0>)
<a name="l807"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cFE>0</span><span class=cF0>;
<a name="l808"></a>
<a name="l809"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF1>lock</span><span class=cF0>)
<a name="l810"></a> unlock = </span><span class=cF5>BlkDevLock</span><span class=cF0>(bd);
<a name="l811"></a>
<a name="l812"></a> buf_size = buf_size_tmp = count * </span><span class=cF3>DVD_BLK_SIZE</span><span class=cF0>;
<a name="l813"></a> prdt_len = (buf_size - </span><span class=cFE>1</span><span class=cF0>) / </span><span class=cF3>AHCI_PRD_MAX_BYTES</span><span class=cF0> + </span><span class=cFE>1</span><span class=cF0>;
<a name="l814"></a>
<a name="l815"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>&quot;PRDT Length:\t%d\n&quot;, prdt_len;</span><span class=cF0>
<a name="l816"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>&quot;Count:\t\t\t%d\n&quot;, count;</span><span class=cF0>
<a name="l817"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>&quot;Buffer size:\t%X\n&quot;, buf_size;</span><span class=cF0>
<a name="l818"></a>
<a name="l819"></a> cmd_header-&gt;prdt_len = prdt_len;
<a name="l820"></a>
<a name="l821"></a> internal_buf = internal_buf_tmp = </span><span class=cFD>AHCIBufferAlign</span><span class=cF0>(bd, buf, buf_size, </span><span class=cF3>FALSE</span><span class=cF0>);
<a name="l822"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>&quot;Buffer:\t\t\t0x%X\n&quot;, internal_buf;</span><span class=cF0>
<a name="l823"></a>
<a name="l824"></a> </span><span class=cF1>if</span><span class=cF0> (!internal_buf) </span><span class=cF5>throw</span><span class=cF0>(</span><span class=cF6>'AHCI'</span><span class=cF0>);
<a name="l825"></a>
<a name="l826"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;cmd_header-&gt;desc, </span><span class=cF3>AHCI_CH_DESCf_A</span><span class=cF0>); </span><span class=cF2>//Set ATAPI flag in command header</span><span class=cF0>
<a name="l827"></a>
<a name="l828"></a> cmd_table = cmd_header-&gt;cmd_table_base;
<a name="l829"></a> </span><span class=cF5>MemSet</span><span class=cF0>(cmd_table, </span><span class=cFE>0</span><span class=cF0>, </span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF9>CPortCmdTable</span><span class=cF7>)</span><span class=cF0>);
<a name="l830"></a>
<a name="l831"></a> </span><span class=cF1>for</span><span class=cF0> (i = </span><span class=cFE>0</span><span class=cF0>; i &lt; prdt_len; i++)
<a name="l832"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l833"></a> </span><span class=cF1>if</span><span class=cF0> (buf_size_tmp &gt; </span><span class=cF3>AHCI_PRD_MAX_BYTES</span><span class=cF0>) </span><span class=cF2>//SHOULD PROBABLY BE ATAPI MAX BYTES</span><span class=cF0>
<a name="l834"></a> byte_count = </span><span class=cF3>AHCI_PRD_MAX_BYTES</span><span class=cF0>;
<a name="l835"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l836"></a> byte_count = buf_size_tmp;
<a name="l837"></a>
<a name="l838"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>&quot;prdt[%d].data_base_addr = 0x%X\n&quot; , i, internal_buf_tmp;</span><span class=cF0>
<a name="l839"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>&quot;prdt[%d].data_byte_count = 0x%X\n\n&quot;, i, byte_count;</span><span class=cF0>
<a name="l840"></a> cmd_table-&gt;prdt[i].data_base = internal_buf_tmp;
<a name="l841"></a> cmd_table-&gt;prdt[i].data_byte_count = byte_count - </span><span class=cFE>1</span><span class=cF0>; </span><span class=cF2>//Zero-based value</span><span class=cF0>
<a name="l842"></a>
<a name="l843"></a> buf_size_tmp -= byte_count;
<a name="l844"></a> internal_buf_tmp += byte_count;
<a name="l845"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l846"></a>
<a name="l847"></a> cmd_fis = cmd_table-&gt;cmd_fis;
<a name="l848"></a> </span><span class=cF5>MemSet</span><span class=cF0>(cmd_fis, </span><span class=cFE>0</span><span class=cF0>, </span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF9>CFisH2D</span><span class=cF7>)</span><span class=cF0>);
<a name="l849"></a>
<a name="l850"></a> cmd_fis-&gt;type = </span><span class=cF3>FISt_H2D</span><span class=cF0>;
<a name="l851"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;cmd_fis-&gt;desc, </span><span class=cF3>AHCI_CF_DESCf_C</span><span class=cF0>); </span><span class=cF2>//Set Command bit in H2D FIS </span><span class=cF0>
<a name="l852"></a>
<a name="l853"></a> cmd_fis-&gt;feature_low = </span><span class=cFE>1</span><span class=cF0>; </span><span class=cF2>//Necessary?</span><span class=cF0>
<a name="l854"></a> cmd_fis-&gt;command = </span><span class=cF3>ATA_PACKET</span><span class=cF0>;
<a name="l855"></a>
<a name="l856"></a> </span><span class=cF5>MemSet</span><span class=cF0>(&amp;read_cmd, </span><span class=cFE>0</span><span class=cF0>, </span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF9>CAtapiReadCmd</span><span class=cF7>)</span><span class=cF0>);
<a name="l857"></a> read_cmd.command = </span><span class=cF3>ATAPI_READ</span><span class=cF0> &gt;&gt; </span><span class=cFE>8</span><span class=cF0>; </span><span class=cF2>//FIX</span><span class=cF0>
<a name="l858"></a> read_cmd.lba = </span><span class=cF5>EndianU32</span><span class=cF0>(blk);
<a name="l859"></a> read_cmd.count = </span><span class=cF5>EndianU32</span><span class=cF0>(count);
<a name="l860"></a> </span><span class=cF5>MemCopy</span><span class=cF0>(&amp;cmd_table-&gt;acmd, &amp;read_cmd, </span><span class=cFE>16</span><span class=cF0>);
<a name="l861"></a>
<a name="l862"></a> cmd_fis-&gt;count = count; </span><span class=cF2>//Necessary?</span><span class=cF0>
<a name="l863"></a>
<a name="l864"></a> </span><span class=cFD>AHCIPortWait</span><span class=cF0>(bd-&gt;port_num, </span><span class=cF5>tS</span><span class=cF0> + </span><span class=cFE>2</span><span class=cF0>);
<a name="l865"></a>
<a name="l866"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;port-&gt;cmd_issue, cmd_slot);
<a name="l867"></a> </span><span class=cFD>AHCIPortCmdWait</span><span class=cF0>(bd-&gt;port_num, cmd_slot);
<a name="l868"></a>
<a name="l869"></a> </span><span class=cF1>if</span><span class=cF0> (bd-&gt;flags &amp; </span><span class=cF3>BDF_INTERNAL_BUF</span><span class=cF0>)
<a name="l870"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l871"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>&quot;Writing back internal buffer\n&quot;;</span><span class=cF0>
<a name="l872"></a> </span><span class=cF5>MemCopy</span><span class=cF0>(buf, internal_buf, buf_size);
<a name="l873"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l874"></a>
<a name="l875"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF1>lock</span><span class=cF0> &amp;&amp; unlock)
<a name="l876"></a> </span><span class=cF5>BlkDevUnlock</span><span class=cF0>(bd);
<a name="l877"></a>
<a name="l878"></a> </span><span class=cF1>return</span><span class=cF0> cmd_header-&gt;prd_byte_count;
<a name="l879"></a>}
<a name="l880"></a>
<a name="l881"></a></span><span class=cF9>I64</span><span class=cF0> </span><span class=cFD>AHCIAtapiBlksWrite</span><span class=cF0>(</span><span class=cF9>CBlkDev</span><span class=cF0> *bd, </span><span class=cF1>U8</span><span class=cF0> *buf, </span><span class=cF9>I64</span><span class=cF0> blk, </span><span class=cF9>I64</span><span class=cF0> count, </span><span class=cF1>Bool</span><span class=cF0> </span><span class=cF1>lock</span><span class=cF0>=</span><span class=cF3>TRUE</span><span class=cF0>)
<a name="l882"></a>{ </span><span class=cF2>// untested</span><span class=cF0>
<a name="l883"></a> </span><span class=cF9>CPortCmdTable</span><span class=cF0> *cmd_table;
<a name="l884"></a> </span><span class=cF9>CFisH2D</span><span class=cF0> *cmd_fis;
<a name="l885"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port = bd-&gt;ahci_port;
<a name="l886"></a> </span><span class=cF9>I64</span><span class=cF0> i, byte_count, buf_size, buf_size_tmp, prdt_len, cmd_slot;
<a name="l887"></a> </span><span class=cF9>CPortCmdHeader</span><span class=cF0> *cmd_header;
<a name="l888"></a> </span><span class=cF1>U8</span><span class=cF0> *internal_buf, *internal_buf_tmp;
<a name="l889"></a> </span><span class=cF1>Bool</span><span class=cF0> unlock;
<a name="l890"></a>
<a name="l891"></a> </span><span class=cF1>if</span><span class=cF0> (port-&gt;signature != </span><span class=cF3>AHCI_PxSIG_ATAPI</span><span class=cF0>)
<a name="l892"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l893"></a> </span><span class=cF5>SysErr</span><span class=cF0>(</span><span class=cF6>&quot;AHCI: Drive is not an ATAPI drive!\n&quot;</span><span class=cF0>);
<a name="l894"></a> </span><span class=cF5>throw</span><span class=cF0>(</span><span class=cF6>'AHCI'</span><span class=cF0>);
<a name="l895"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l896"></a> </span><span class=cF1>if</span><span class=cF0> (count &lt; </span><span class=cFE>1</span><span class=cF0>)
<a name="l897"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cFE>0</span><span class=cF0>;
<a name="l898"></a>
<a name="l899"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF1>lock</span><span class=cF0>)
<a name="l900"></a> unlock = </span><span class=cF5>BlkDevLock</span><span class=cF0>(bd);
<a name="l901"></a>
<a name="l902"></a>
<a name="l903"></a> </span><span class=cFD>AHCIPortWait</span><span class=cF0>(bd-&gt;port_num, </span><span class=cF5>tS</span><span class=cF0> + </span><span class=cFE>2</span><span class=cF0>);
<a name="l904"></a> </span><span class=cF5>AHCIAtapiSeek</span><span class=cF0>(bd, blk);
<a name="l905"></a> </span><span class=cFD>AHCIPortWait</span><span class=cF0>(bd-&gt;port_num, </span><span class=cF5>tS</span><span class=cF0> + </span><span class=cFE>2</span><span class=cF0>);
<a name="l906"></a> </span><span class=cFD>AHCIAtapiFormat</span><span class=cF0>(bd, count); </span><span class=cF2>// ??..</span><span class=cF0>
<a name="l907"></a> bd-&gt;flags |= </span><span class=cF3>BDF_LAST_WAS_WRITE</span><span class=cF0>; </span><span class=cF2>// ??..</span><span class=cF0>
<a name="l908"></a> </span><span class=cFD>AHCIPortWait</span><span class=cF0>(bd-&gt;port_num, </span><span class=cF5>tS</span><span class=cF0> + </span><span class=cFE>2</span><span class=cF0>);
<a name="l909"></a> </span><span class=cF5>AHCIAtapiSeek</span><span class=cF0>(bd, blk);
<a name="l910"></a>
<a name="l911"></a> cmd_slot = </span><span class=cFD>AHCIPortCmdSlotGet</span><span class=cF0>(bd-&gt;port_num);
<a name="l912"></a> cmd_header = </span><span class=cFD>AHCIPortActiveHeaderGet</span><span class=cF0>(bd-&gt;port_num, cmd_slot);
<a name="l913"></a>
<a name="l914"></a> buf_size = buf_size_tmp = count * </span><span class=cF3>DVD_BLK_SIZE</span><span class=cF0>;
<a name="l915"></a> prdt_len = (buf_size - </span><span class=cFE>1</span><span class=cF0>) / </span><span class=cF3>AHCI_PRD_MAX_BYTES</span><span class=cF0> + </span><span class=cFE>1</span><span class=cF0>;
<a name="l916"></a>
<a name="l917"></a> cmd_header-&gt;prdt_len = prdt_len;
<a name="l918"></a>
<a name="l919"></a> internal_buf = internal_buf_tmp = </span><span class=cFD>AHCIBufferAlign</span><span class=cF0>(bd, buf, buf_size, </span><span class=cF3>FALSE</span><span class=cF0>);
<a name="l920"></a>
<a name="l921"></a> </span><span class=cF1>if</span><span class=cF0> (!internal_buf) </span><span class=cF5>throw</span><span class=cF0>(</span><span class=cF6>'AHCI'</span><span class=cF0>);
<a name="l922"></a>
<a name="l923"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;cmd_header-&gt;desc, </span><span class=cF3>AHCI_CH_DESCf_A</span><span class=cF0>); </span><span class=cF2>//Set ATAPI flag in command header</span><span class=cF0>
<a name="l924"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;cmd_header-&gt;desc, </span><span class=cF3>AHCI_CH_DESCf_W</span><span class=cF0>); </span><span class=cF2>//Set WRITE flag in command header</span><span class=cF0>
<a name="l925"></a>
<a name="l926"></a> cmd_table = cmd_header-&gt;cmd_table_base;
<a name="l927"></a> </span><span class=cF5>MemSet</span><span class=cF0>(cmd_table, </span><span class=cFE>0</span><span class=cF0>, </span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF9>CPortCmdTable</span><span class=cF7>)</span><span class=cF0>);
<a name="l928"></a>
<a name="l929"></a> </span><span class=cF1>for</span><span class=cF0> (i = </span><span class=cFE>0</span><span class=cF0>; i &lt; prdt_len; i++)
<a name="l930"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l931"></a> </span><span class=cF1>if</span><span class=cF0> (buf_size_tmp &gt; </span><span class=cF3>AHCI_PRD_MAX_BYTES</span><span class=cF0>) </span><span class=cF2>//SHOULD PROBABLY BE ATAPI MAX BYTES</span><span class=cF0>
<a name="l932"></a> byte_count = </span><span class=cF3>AHCI_PRD_MAX_BYTES</span><span class=cF0>;
<a name="l933"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l934"></a> byte_count = buf_size_tmp;
<a name="l935"></a> cmd_table-&gt;prdt[i].data_base = internal_buf_tmp;
<a name="l936"></a> cmd_table-&gt;prdt[i].data_byte_count = byte_count - </span><span class=cFE>1</span><span class=cF0>; </span><span class=cF2>//Zero-based value</span><span class=cF0>
<a name="l937"></a>
<a name="l938"></a> buf_size_tmp -= byte_count;
<a name="l939"></a> internal_buf_tmp += byte_count;
<a name="l940"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l941"></a>
<a name="l942"></a> cmd_fis = cmd_table-&gt;cmd_fis;
<a name="l943"></a> </span><span class=cF5>MemSet</span><span class=cF0>(cmd_fis, </span><span class=cFE>0</span><span class=cF0>, </span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF9>CFisH2D</span><span class=cF7>)</span><span class=cF0>);
<a name="l944"></a>
<a name="l945"></a> cmd_fis-&gt;type = </span><span class=cF3>FISt_H2D</span><span class=cF0>;
<a name="l946"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;cmd_fis-&gt;desc, </span><span class=cF3>AHCI_CF_DESCf_C</span><span class=cF0>); </span><span class=cF2>//Set Command bit in H2D FIS </span><span class=cF0>
<a name="l947"></a> cmd_fis-&gt;command = </span><span class=cF3>ATA_PACKET</span><span class=cF0>;
<a name="l948"></a> cmd_table-&gt;acmd[</span><span class=cFE>0</span><span class=cF0>] =</span><span class=cF3>ATAPI_WRITE</span><span class=cF0> &gt;&gt; </span><span class=cFE>8</span><span class=cF0>;
<a name="l949"></a> cmd_table-&gt;acmd[</span><span class=cFE>2</span><span class=cF0>] = blk.u8[</span><span class=cFE>3</span><span class=cF0>];
<a name="l950"></a> cmd_table-&gt;acmd[</span><span class=cFE>3</span><span class=cF0>] = blk.u8[</span><span class=cFE>2</span><span class=cF0>];
<a name="l951"></a> cmd_table-&gt;acmd[</span><span class=cFE>4</span><span class=cF0>] = blk.u8[</span><span class=cFE>1</span><span class=cF0>];
<a name="l952"></a> cmd_table-&gt;acmd[</span><span class=cFE>5</span><span class=cF0>] = blk.u8[</span><span class=cFE>0</span><span class=cF0>];
<a name="l953"></a> cmd_table-&gt;acmd[</span><span class=cFE>6</span><span class=cF0>] = count.u8[</span><span class=cFE>3</span><span class=cF0>];
<a name="l954"></a> cmd_table-&gt;acmd[</span><span class=cFE>7</span><span class=cF0>] = count.u8[</span><span class=cFE>2</span><span class=cF0>];
<a name="l955"></a> cmd_table-&gt;acmd[</span><span class=cFE>8</span><span class=cF0>] = count.u8[</span><span class=cFE>1</span><span class=cF0>];
<a name="l956"></a> cmd_table-&gt;acmd[</span><span class=cFE>9</span><span class=cF0>] = count.u8[</span><span class=cFE>0</span><span class=cF0>];
<a name="l957"></a>
<a name="l958"></a> cmd_fis-&gt;count = count; </span><span class=cF2>//Necessary?</span><span class=cF0>
<a name="l959"></a>
<a name="l960"></a> </span><span class=cFD>AHCIPortWait</span><span class=cF0>(bd-&gt;port_num, </span><span class=cF5>tS</span><span class=cF0> + </span><span class=cFE>2</span><span class=cF0>);
<a name="l961"></a>
<a name="l962"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;port-&gt;cmd_issue, cmd_slot);
<a name="l963"></a> </span><span class=cFD>AHCIPortCmdWait</span><span class=cF0>(bd-&gt;port_num, cmd_slot);
<a name="l964"></a>
<a name="l965"></a> </span><span class=cF1>if</span><span class=cF0> (bd-&gt;flags &amp; </span><span class=cF3>BDF_INTERNAL_BUF</span><span class=cF0>)
<a name="l966"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l967"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>&quot;Writing back internal buffer\n&quot;;</span><span class=cF0>
<a name="l968"></a> </span><span class=cF5>MemCopy</span><span class=cF0>(buf, internal_buf, buf_size);
<a name="l969"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l970"></a>
<a name="l971"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF1>lock</span><span class=cF0> &amp;&amp; unlock)
<a name="l972"></a> </span><span class=cF5>BlkDevUnlock</span><span class=cF0>(bd);
<a name="l973"></a>
<a name="l974"></a> </span><span class=cF1>return</span><span class=cF0> cmd_header-&gt;prd_byte_count;
<a name="l975"></a>}
<a name="l976"></a>
<a name="l977"></a></span><span class=cF1>U0</span><span class=cF0> </span><span class=cF5>AHCIPortInit</span><span class=cF0>(</span><span class=cF9>CBlkDev</span><span class=cF0> *bd, </span><span class=cF9>CAHCIPort</span><span class=cF0> *port, </span><span class=cF9>I64</span><span class=cF0> port_num)
<a name="l978"></a>{</span><span class=cF2>//Initialize base addresses for command list and FIS receive area and start command execution on port.</span><span class=cF0>
<a name="l979"></a> </span><span class=cF9>CPortCmdHeader</span><span class=cF0> *cmd_header;
<a name="l980"></a> </span><span class=cF9>I64</span><span class=cF0> i;
<a name="l981"></a>
<a name="l982"></a> </span><span class=cF1>if</span><span class=cF0> (!</span><span class=cF7>(</span><span class=cF0>port-&gt;signature == </span><span class=cF3>AHCI_PxSIG_ATAPI</span><span class=cF0> || port-&gt;signature == </span><span class=cF3>AHCI_PxSIG_ATA</span><span class=cF7>)</span><span class=cF0>)
<a name="l983"></a> </span><span class=cF5>Debug</span><span class=cF0>(</span><span class=cF6>&quot;AHCI Port/BlkDev error: Invalid Port Signature&quot;</span><span class=cF0>);
<a name="l984"></a>
<a name="l985"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Letter2BlkDevType</span><span class=cF7>(</span><span class=cF0>bd-&gt;first_drive_let</span><span class=cF7>)</span><span class=cF0> == </span><span class=cF3>BDT_ATA</span><span class=cF0> &amp;&amp; port-&gt;signature == </span><span class=cF3>AHCI_PxSIG_ATAPI</span><span class=cF0>)
<a name="l986"></a> </span><span class=cF5>Debug</span><span class=cF0>(</span><span class=cF6>&quot;AHCI Port/BlkDev type mismatch: BlkDev ATA, Port ATAPI&quot;</span><span class=cF0>);
<a name="l987"></a>
<a name="l988"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Letter2BlkDevType</span><span class=cF7>(</span><span class=cF0>bd-&gt;first_drive_let</span><span class=cF7>)</span><span class=cF0> == </span><span class=cF3>BDT_ATAPI</span><span class=cF0> &amp;&amp; port-&gt;signature == </span><span class=cF3>AHCI_PxSIG_ATA</span><span class=cF0>)
<a name="l989"></a> </span><span class=cF5>Debug</span><span class=cF0>(</span><span class=cF6>&quot;AHCI Port/BlkDev type mismatch: BlkDev ATAPI, Port ATA&quot;</span><span class=cF0>);
<a name="l990"></a>
<a name="l991"></a> bd-&gt;ahci_port = port;
<a name="l992"></a> bd-&gt;port_num = port_num;
<a name="l993"></a>
<a name="l994"></a> </span><span class=cF5>AHCIPortReset</span><span class=cF0>(port_num);
<a name="l995"></a> </span><span class=cFD>AHCIPortCmdStart</span><span class=cF0>(port_num);
<a name="l996"></a>
<a name="l997"></a> </span><span class=cF2>//Spin up, power on device. If the capability isn't suppport the bits will be read-only and this won't do anything.</span><span class=cF0>
<a name="l998"></a> port-&gt;command |= </span><span class=cF3>AHCI_PxCMDF_POD</span><span class=cF0> | </span><span class=cF3>AHCI_PxCMDF_SUD</span><span class=cF0>;
<a name="l999"></a> </span><span class=cF5>Sleep</span><span class=cF0>(</span><span class=cFE>100</span><span class=cF0>); </span><span class=cF2>//Why?</span><span class=cF0>
<a name="l1000"></a> </span><span class=cFD>AHCIPortCmdStop</span><span class=cF0>(port_num);
<a name="l1001"></a>
<a name="l1002"></a> </span><span class=cF2>//'1K-byte' align as per SATA spec.</span><span class=cF0>
<a name="l1003"></a> port-&gt;cmd_list_base = </span><span class=cF5>CAllocAligned</span><span class=cF0>(</span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF9>CPortCmdHeader</span><span class=cF7>)</span><span class=cF0> * </span><span class=cFB>blkdev</span><span class=cF0>.cmd_slot_count, </span><span class=cFE>1024</span><span class=cF0>, </span><span class=cFB>sys_task</span><span class=cF0>-&gt;code_heap);
<a name="l1004"></a> port-&gt;cmd_list_base_upper = </span><span class=cFE>0</span><span class=cF0>;
<a name="l1005"></a>
<a name="l1006"></a> </span><span class=cF2>//Alloc where received FISes will be copied to. '256-byte' align as per spec.</span><span class=cF0>
<a name="l1007"></a> port-&gt;fis_base = </span><span class=cF5>CAllocAligned</span><span class=cF0>(</span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF9>CFisReceived</span><span class=cF7>)</span><span class=cF0>, </span><span class=cFE>256</span><span class=cF0>, </span><span class=cFB>sys_task</span><span class=cF0>-&gt;code_heap);
<a name="l1008"></a> port-&gt;fis_base_upper = </span><span class=cFE>0</span><span class=cF0>;
<a name="l1009"></a>
<a name="l1010"></a> </span><span class=cF1>for</span><span class=cF0> (i = </span><span class=cFE>0</span><span class=cF0>; i &lt; </span><span class=cFB>blkdev</span><span class=cF0>.cmd_slot_count; i++)
<a name="l1011"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1012"></a> cmd_header = &amp;port-&gt;cmd_list_base(</span><span class=cF9>CPortCmdHeader</span><span class=cF0> *)[i];
<a name="l1013"></a> </span><span class=cF2>//Write Command FIS Length (CFL, a fixed size) in bits 4:0 of the desc. Takes size in U32s.</span><span class=cF0>
<a name="l1014"></a> cmd_header-&gt;desc = </span><span class=cF1>sizeof</span><span class=cF0>(</span><span class=cF9>CFisH2D</span><span class=cF0>) / </span><span class=cF1>sizeof</span><span class=cF0>(</span><span class=cF9>U32</span><span class=cF0>);
<a name="l1015"></a>
<a name="l1016"></a> </span><span class=cF2>//'128-byte' align as per SATA spec, minus 1 since length is 1-based.</span><span class=cF0>
<a name="l1017"></a> cmd_header-&gt;cmd_table_base = </span><span class=cF5>CAllocAligned</span><span class=cF0>(</span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF9>CPortCmdTable</span><span class=cF7>)</span><span class=cF0> + </span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF9>CPrdtEntry</span><span class=cF7>)</span><span class=cF0> * </span><span class=cF7>(</span><span class=cF3>AHCI_PRDT_MAX_LEN</span><span class=cF0> - </span><span class=cFE>1</span><span class=cF7>)</span><span class=cF0>, </span><span class=cFE>128</span><span class=cF0>, </span><span class=cFB>sys_task</span><span class=cF0>-&gt;code_heap);
<a name="l1018"></a> cmd_header-&gt;cmd_table_base_upper = </span><span class=cFE>0</span><span class=cF0>;
<a name="l1019"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1020"></a> </span><span class=cFD>AHCIPortCmdStart</span><span class=cF0>(port_num);
<a name="l1021"></a> </span><span class=cFD>AHCIPortIdentify</span><span class=cF0>(bd);
<a name="l1022"></a>}
<a name="l1023"></a>
<a name="l1024"></a></span><span class=cF1>Bool</span><span class=cF0> </span><span class=cFD>AHCIAtaInit</span><span class=cF0>(</span><span class=cF9>CBlkDev</span><span class=cF0> *bd)
<a name="l1025"></a>{
<a name="l1026"></a> </span><span class=cF1>Bool</span><span class=cF0> unlock, okay = </span><span class=cF3>FALSE</span><span class=cF0>;
<a name="l1027"></a> </span><span class=cF9>CPortCmdHeader</span><span class=cF0> *cmd_header;
<a name="l1028"></a> </span><span class=cF9>I64</span><span class=cF0> i;
<a name="l1029"></a>
<a name="l1030"></a> </span><span class=cF1>if</span><span class=cF0> (!bd-&gt;ahci_port)
<a name="l1031"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>FALSE</span><span class=cF0>;
<a name="l1032"></a>
<a name="l1033"></a> unlock = </span><span class=cF5>BlkDevLock</span><span class=cF0>(bd);
<a name="l1034"></a>
<a name="l1035"></a> </span><span class=cF2>// if we re-init a port, keep memory from leaking.</span><span class=cF0>
<a name="l1036"></a> </span><span class=cF1>for</span><span class=cF0> (i = </span><span class=cFE>0</span><span class=cF0>; i &lt; </span><span class=cFB>blkdev</span><span class=cF0>.cmd_slot_count; i++)
<a name="l1037"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1038"></a> cmd_header = &amp;bd-&gt;ahci_port-&gt;cmd_list_base(</span><span class=cF9>CPortCmdHeader</span><span class=cF0> *)[i];
<a name="l1039"></a> </span><span class=cF5>Free</span><span class=cF0>(cmd_header-&gt;cmd_table_base);
<a name="l1040"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1041"></a> </span><span class=cF5>Free</span><span class=cF0>(bd-&gt;ahci_port-&gt;cmd_list_base);
<a name="l1042"></a> </span><span class=cF5>Free</span><span class=cF0>(bd-&gt;ahci_port-&gt;fis_base);
<a name="l1043"></a>
<a name="l1044"></a> </span><span class=cF2>// try to init the port, catch if fails.</span><span class=cF0>
<a name="l1045"></a> </span><span class=cF1>try</span><span class=cF0>
<a name="l1046"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1047"></a> </span><span class=cF5>AHCIPortInit</span><span class=cF0>(bd, bd-&gt;ahci_port, bd-&gt;port_num);
<a name="l1048"></a>
<a name="l1049"></a> </span><span class=cF1>if</span><span class=cF0> (bd-&gt;type == </span><span class=cF3>BDT_ATAPI</span><span class=cF0>)
<a name="l1050"></a> okay = </span><span class=cF5>AHCIAtapiStartStop</span><span class=cF0>(bd, </span><span class=cF3>TRUE</span><span class=cF0>);
<a name="l1051"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l1052"></a> okay = </span><span class=cF3>TRUE</span><span class=cF0>;
<a name="l1053"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1054"></a> </span><span class=cF1>catch</span><span class=cF0>
<a name="l1055"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1056"></a> </span><span class=cF5>Fs</span><span class=cF0>-&gt;catch_except = </span><span class=cF3>TRUE</span><span class=cF0>;
<a name="l1057"></a> okay = </span><span class=cF3>FALSE</span><span class=cF0>;
<a name="l1058"></a> </span><span class=cF3>ST_WARN_ST</span><span class=cF0> </span><span class=cF6>&quot;AHCIAtaInit&quot;</span><span class=cF0>;
<a name="l1059"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1060"></a>
<a name="l1061"></a> </span><span class=cF1>if</span><span class=cF0> (unlock)
<a name="l1062"></a> </span><span class=cF5>BlkDevUnlock</span><span class=cF0>(bd);
<a name="l1063"></a>
<a name="l1064"></a> </span><span class=cF1>return</span><span class=cF0> okay;
<a name="l1065"></a>}
<a name="l1066"></a>
<a name="l1067"></a></span><span class=cF1>U0</span><span class=cF0> </span><span class=cF5>AHCIHbaReset</span><span class=cF0>()
<a name="l1068"></a>{
<a name="l1069"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;</span><span class=cFB>blkdev</span><span class=cF0>.ahci_hba-&gt;ghc, </span><span class=cF3>AHCI_GHCf_HBA_RESET</span><span class=cF0>);
<a name="l1070"></a> </span><span class=cF1>while</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;</span><span class=cFB>blkdev</span><span class=cF0>.ahci_hba-&gt;ghc, </span><span class=cF3>AHCI_GHCf_HBA_RESET</span><span class=cF7>)</span><span class=cF0>);
<a name="l1071"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;</span><span class=cFB>blkdev</span><span class=cF0>.ahci_hba-&gt;ghc, </span><span class=cF3>AHCI_GHCf_AHCI_ENABLE</span><span class=cF0>);
<a name="l1072"></a>}
<a name="l1073"></a>
<a name="l1074"></a></span><span class=cF1>U0</span><span class=cF0> </span><span class=cFD>AHCIInit</span><span class=cF0>()
<a name="l1075"></a>{
<a name="l1076"></a> </span><span class=cF9>CAHCIHba</span><span class=cF0> *hba;
<a name="l1077"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port;
<a name="l1078"></a> </span><span class=cF9>I64</span><span class=cF0> i, bdf = </span><span class=cF5>PCIClassFind</span><span class=cF0>(</span><span class=cF3>PCIC_STORAGE</span><span class=cF0> &lt;&lt; </span><span class=cFE>16</span><span class=cF0> | </span><span class=cF3>PCISC_AHCI</span><span class=cF0> &lt;&lt; </span><span class=cFE>8</span><span class=cF0> + </span><span class=cFE>1</span><span class=cF0>, </span><span class=cFE>0</span><span class=cF0>); </span><span class=cF2>//0x010601, last byte prog_if, AHCI version 1.0</span><span class=cF0>
<a name="l1079"></a>
<a name="l1080"></a> </span><span class=cF6>&quot;\n&quot;</span><span class=cF0>;
<a name="l1081"></a>
<a name="l1082"></a> </span><span class=cF1>if</span><span class=cF0> (bdf == -</span><span class=cFE>1</span><span class=cF0>)
<a name="l1083"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1084"></a> </span><span class=cF6>&quot;AHCI: No AHCI controller found.\n&quot;</span><span class=cF0>;
<a name="l1085"></a> </span><span class=cF1>return</span><span class=cF0>;
<a name="l1086"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1087"></a>
<a name="l1088"></a> </span><span class=cF6>&quot;AHCI: Controller found\n&quot;</span><span class=cF0>;
<a name="l1089"></a> hba = </span><span class=cFB>dev</span><span class=cF0>.uncached_alias + </span><span class=cF5>PCIReadU32</span><span class=cF0>(bdf.u8[</span><span class=cFE>2</span><span class=cF0>], bdf.u8[</span><span class=cFE>1</span><span class=cF0>], bdf.u8[</span><span class=cFE>0</span><span class=cF0>], </span><span class=cF3>PCIR_BASE5</span><span class=cF0>) &amp; ~</span><span class=cFE>0x1F</span><span class=cF0>; </span><span class=cF2>//Last 4 bits not part of address.</span><span class=cF0>
<a name="l1090"></a> </span><span class=cFB>blkdev</span><span class=cF0>.ahci_hba = hba;
<a name="l1091"></a>
<a name="l1092"></a>
<a name="l1093"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;</span><span class=cFB>blkdev</span><span class=cF0>.ahci_hba-&gt;ghc, </span><span class=cF3>AHCI_GHCf_AHCI_ENABLE</span><span class=cF0>);
<a name="l1094"></a> </span><span class=cF6>&quot;AHCI: GHC.AE\n&quot;</span><span class=cF0>;
<a name="l1095"></a>
<a name="l1096"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>AHCIHbaReset;</span><span class=cF0>
<a name="l1097"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>&quot;AHCI: HBA Reset\n&quot;;</span><span class=cF0>
<a name="l1098"></a>
<a name="l1099"></a>
<a name="l1100"></a> </span><span class=cF2>//Transferring ownership from BIOS if supported.</span><span class=cF0>
<a name="l1101"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;hba-&gt;caps_ext, </span><span class=cF3>AHCI_CAPSEXTf_BOH</span><span class=cF7>)</span><span class=cF0>)
<a name="l1102"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1103"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;hba-&gt;bohc, </span><span class=cF3>AHCI_BOHCf_OOS</span><span class=cF0>);
<a name="l1104"></a> </span><span class=cF6>&quot;AHCI: Transferring ownership from BIOS\n&quot;</span><span class=cF0>;
<a name="l1105"></a>
<a name="l1106"></a> </span><span class=cF1>while</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;hba-&gt;bohc, </span><span class=cF3>AHCI_BOHCf_BOS</span><span class=cF7>)</span><span class=cF0>);
<a name="l1107"></a>
<a name="l1108"></a> </span><span class=cF5>Sleep</span><span class=cF0>(</span><span class=cFE>25</span><span class=cF0>);
<a name="l1109"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;hba-&gt;bohc, </span><span class=cF3>AHCI_BOHCf_BB</span><span class=cF7>)</span><span class=cF0>) </span><span class=cF2>//if Bios Busy is still set after 25 mS, wait 2 seconds.</span><span class=cF0>
<a name="l1110"></a> </span><span class=cF5>Sleep</span><span class=cF0>(</span><span class=cFE>2000</span><span class=cF0>);
<a name="l1111"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1112"></a>
<a name="l1113"></a> </span><span class=cFB>blkdev</span><span class=cF0>.cmd_slot_count = (hba-&gt;caps &amp; </span><span class=cFE>0x1F00</span><span class=cF0>) &gt;&gt; </span><span class=cFE>8</span><span class=cF0>;
<a name="l1114"></a> </span><span class=cF6>&quot;AHCI: Command slot count: %d\n&quot;</span><span class=cF0>, </span><span class=cFB>blkdev</span><span class=cF0>.cmd_slot_count;
<a name="l1115"></a>
<a name="l1116"></a> </span><span class=cF1>for</span><span class=cF0> (i = </span><span class=cFE>0</span><span class=cF0>; i &lt; </span><span class=cF3>AHCI_MAX_PORTS</span><span class=cF0>; i++)
<a name="l1117"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1118"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;hba-&gt;ports_implemented, i</span><span class=cF7>)</span><span class=cF0>)
<a name="l1119"></a> {</span><span class=cF2>//Make ports idle?</span><span class=cF0>
<a name="l1120"></a> port = &amp;hba-&gt;ports[i];
<a name="l1121"></a> </span><span class=cF6>&quot;AHCI: Port %2d signature 0x%08X &quot;</span><span class=cF0>, i, port-&gt;signature;
<a name="l1122"></a> </span><span class=cF1>if</span><span class=cF0> (port-&gt;signature == </span><span class=cF3>AHCI_PxSIG_ATA</span><span class=cF0> || port-&gt;signature == </span><span class=cF3>AHCI_PxSIG_ATAPI</span><span class=cF0>)
<a name="l1123"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1124"></a> </span><span class=cF1>if</span><span class=cF0> (port-&gt;signature == </span><span class=cF3>AHCI_PxSIG_ATAPI</span><span class=cF0>)
<a name="l1125"></a> {
<a name="l1126"></a> </span><span class=cF5>Bts</span><span class=cF0>(&amp;port-&gt;command, </span><span class=cF3>AHCI_PxCMDf_ATAPI</span><span class=cF0>);
<a name="l1127"></a> </span><span class=cF6>&quot;ATAPI drive\n&quot;</span><span class=cF0>;
<a name="l1128"></a> }
<a name="l1129"></a> </span><span class=cF1>else</span><span class=cF0> </span><span class=cF1>if</span><span class=cF0> (port-&gt;signature == </span><span class=cF3>AHCI_PxSIG_ATA</span><span class=cF0>)
<a name="l1130"></a> </span><span class=cF6>&quot;ATA drive\n&quot;</span><span class=cF0>;
<a name="l1131"></a>
<a name="l1132"></a> </span><span class=cF1>if</span><span class=cF0> (!</span><span class=cFD>AHCIPortIsIdle</span><span class=cF7>(</span><span class=cF0>i</span><span class=cF7>)</span><span class=cF0>)
<a name="l1133"></a> {
<a name="l1134"></a> </span><span class=cF6>&quot;AHCI: Port not idle\n&quot;</span><span class=cF0>;
<a name="l1135"></a> </span><span class=cFD>AHCIPortCmdStop</span><span class=cF0>(i);
<a name="l1136"></a> }
<a name="l1137"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1138"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l1139"></a> </span><span class=cF6>&quot;Unknown\n&quot;</span><span class=cF0>;
<a name="l1140"></a> }
<a name="l1141"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1142"></a> </span><span class=cF6>&quot;\n&quot;</span><span class=cF0>;
<a name="l1143"></a>}
<a name="l1144"></a>
<a name="l1145"></a></span><span class=cF1>Bool</span><span class=cF0> </span><span class=cFD>AHCIBootDVDProbeAll</span><span class=cF0>(</span><span class=cF9>CBlkDev</span><span class=cF0> *bd)
<a name="l1146"></a>{
<a name="l1147"></a> </span><span class=cF9>I64</span><span class=cF0> i;
<a name="l1148"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port;
<a name="l1149"></a> </span><span class=cF1>U8</span><span class=cF0> *buf = </span><span class=cF5>CAlloc</span><span class=cF0>(</span><span class=cF3>DVD_BLK_SIZE</span><span class=cF0>);
<a name="l1150"></a> </span><span class=cF9>CKernel</span><span class=cF0> *kernel;
<a name="l1151"></a>
<a name="l1152"></a> </span><span class=cF1>for</span><span class=cF0> (i = </span><span class=cFE>0</span><span class=cF0>; i &lt; </span><span class=cF3>AHCI_MAX_PORTS</span><span class=cF0>; i++)
<a name="l1153"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1154"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&amp;</span><span class=cFB>blkdev</span><span class=cF0>.ahci_hba-&gt;ports_implemented, i</span><span class=cF7>)</span><span class=cF0>)
<a name="l1155"></a> {
<a name="l1156"></a> port = &amp;</span><span class=cFB>blkdev</span><span class=cF0>.ahci_hba-&gt;ports[i];
<a name="l1157"></a> </span><span class=cF6>&quot;AHCI: BootDVDProbeAll: Saw port at %2d with signature 0x%0X\n&quot;</span><span class=cF0>, i, port-&gt;signature;
<a name="l1158"></a>
<a name="l1159"></a> </span><span class=cF1>if</span><span class=cF0> (port-&gt;signature == </span><span class=cF3>AHCI_PxSIG_ATAPI</span><span class=cF0>)
<a name="l1160"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1161"></a> </span><span class=cF6>&quot;AHCI: Probing ATAPI drive at port %d\n&quot;</span><span class=cF0>, i;
<a name="l1162"></a>
<a name="l1163"></a> </span><span class=cF5>AHCIPortInit</span><span class=cF0>(bd, port, i);
<a name="l1164"></a>
<a name="l1165"></a> </span><span class=cF5>AHCIAtapiBlksRead</span><span class=cF0>(bd, buf, </span><span class=cFB>sys_boot_blk</span><span class=cF0>, </span><span class=cFE>1</span><span class=cF0>, </span><span class=cF3>FALSE</span><span class=cF0>);
<a name="l1166"></a>
<a name="l1167"></a> kernel = buf + </span><span class=cFB>sys_boot_src</span><span class=cF0>.u16[</span><span class=cFE>1</span><span class=cF0>] &lt;&lt; </span><span class=cF3>BLK_SIZE_BITS</span><span class=cF0>;
<a name="l1168"></a>
<a name="l1169"></a> </span><span class=cF1>if</span><span class=cF0> (kernel-&gt;compile_time == </span><span class=cFB>sys_compile_time</span><span class=cF0>)
<a name="l1170"></a> {
<a name="l1171"></a> </span><span class=cF6>&quot;AHCI: Found sys_compile_time at BLK %d on Port %d\n&quot;</span><span class=cF0>, </span><span class=cFB>sys_boot_blk</span><span class=cF0>, i;
<a name="l1172"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>TRUE</span><span class=cF0>;
<a name="l1173"></a> }
<a name="l1174"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l1175"></a> </span><span class=cF6>&quot;AHCI: Did not find matching sys_compile_time on Port %d\n&quot;</span><span class=cF0>, i;
<a name="l1176"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1177"></a> }
<a name="l1178"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1179"></a>
<a name="l1180"></a> </span><span class=cF5>Panic</span><span class=cF0>(</span><span class=cF6>&quot;Could not find ATAPI boot drive&quot;</span><span class=cF0>);
<a name="l1181"></a>
<a name="l1182"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>FALSE</span><span class=cF0>;
<a name="l1183"></a>}
<a name="l1184"></a>
<a name="l1185"></a></span><span class=cF1>Bool</span><span class=cF0> </span><span class=cFD>AHCIAtapiRBlks</span><span class=cF0>(</span><span class=cF9>CDrive</span><span class=cF0> *drive, </span><span class=cF1>U8</span><span class=cF0> *buf, </span><span class=cF9>I64</span><span class=cF0> blk, </span><span class=cF9>I64</span><span class=cF0> count)
<a name="l1186"></a>{
<a name="l1187"></a> </span><span class=cF9>CBlkDev</span><span class=cF0> *bd = drive-&gt;bd;
<a name="l1188"></a> </span><span class=cF9>I64</span><span class=cF0> spc = bd-&gt;blk_size &gt;&gt; </span><span class=cF3>BLK_SIZE_BITS</span><span class=cF0>, n, blk2,
<a name="l1189"></a> l2 = bd-&gt;max_reads &lt;&lt; </span><span class=cFE>1</span><span class=cF0> + spc &lt;&lt; </span><span class=cFE>1</span><span class=cF0>;
<a name="l1190"></a> </span><span class=cF1>U8</span><span class=cF0> *dvd_buf;</span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>= MAlloc(l2 &lt;&lt; BLK_SIZE_BITS);</span><span class=cF0>
<a name="l1191"></a>
<a name="l1192"></a> </span><span class=cF1>if</span><span class=cF0> (bd-&gt;type == </span><span class=cF3>BDT_ATAPI</span><span class=cF0>)
<a name="l1193"></a> </span><span class=cF7>{</span><span class=cF0>
<a name="l1194"></a> dvd_buf = </span><span class=cF5>MAlloc</span><span class=cF0>(l2 &lt;&lt; </span><span class=cF3>BLK_SIZE_BITS</span><span class=cF0>);
<a name="l1195"></a>
<a name="l1196"></a> </span><span class=cF1>if</span><span class=cF0> (blk &lt;= bd-&gt;max_reads)
<a name="l1197"></a> blk2 = </span><span class=cFE>0</span><span class=cF0>;
<a name="l1198"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l1199"></a> blk2 = </span><span class=cF5>FloorU64</span><span class=cF0>(blk - bd-&gt;max_reads, spc);
<a name="l1200"></a>
<a name="l1201"></a> </span><span class=cF1>if</span><span class=cF0> (blk2 + l2 &gt; drive-&gt;size + drive-&gt;drv_offset)
<a name="l1202"></a> l2 = drive-&gt;size + drive-&gt;drv_offset - blk2;
<a name="l1203"></a>
<a name="l1204"></a> n = (l2 + spc - </span><span class=cFE>1</span><span class=cF0>) / spc;
<a name="l1205"></a>
<a name="l1206"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>&quot;AHCIAtapiBlksRead(bd, dvd_buf, %d, %d);&quot;, blk2 / spc, n;</span><span class=cF0>
<a name="l1207"></a> </span><span class=cF5>AHCIAtapiBlksRead</span><span class=cF0>(bd, dvd_buf, blk2 / spc, n);
<a name="l1208"></a>
<a name="l1209"></a> </span><span class=cF1>if</span><span class=cF0> (bd-&gt;flags &amp; </span><span class=cF3>BDF_READ_CACHE</span><span class=cF0>)
<a name="l1210"></a> </span><span class=cFD>DiskCacheAdd</span><span class=cF0>(drive, dvd_buf, blk2, n * spc);
<a name="l1211"></a>
<a name="l1212"></a> </span><span class=cF5>MemCopy</span><span class=cF0>(buf, dvd_buf + </span><span class=cF7>(</span><span class=cF0>blk - blk2</span><span class=cF7>)</span><span class=cF0> &lt;&lt; </span><span class=cF3>BLK_SIZE_BITS</span><span class=cF0>, count &lt;&lt; </span><span class=cF3>BLK_SIZE_BITS</span><span class=cF0>);
<a name="l1213"></a> </span><span class=cF5>Free</span><span class=cF0>(dvd_buf);
<a name="l1214"></a>
<a name="l1215"></a> </span><span class=cF7>}</span><span class=cF0>
<a name="l1216"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l1217"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>FALSE</span><span class=cF0>;
<a name="l1218"></a>
<a name="l1219"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>TRUE</span><span class=cF0>;
<a name="l1220"></a>}
<a name="l1221"></a>
<a name="l1222"></a></span><span class=cF1>Bool</span><span class=cF0> </span><span class=cFD>AHCIAtaRBlks</span><span class=cF0>(</span><span class=cF9>CDrive</span><span class=cF0> *drive, </span><span class=cF1>U8</span><span class=cF0> *buf, </span><span class=cF9>I64</span><span class=cF0> blk, </span><span class=cF9>I64</span><span class=cF0> count)
<a name="l1223"></a>{
<a name="l1224"></a> </span><span class=cF9>CBlkDev</span><span class=cF0> *bd = drive-&gt;bd;
<a name="l1225"></a>
<a name="l1226"></a> </span><span class=cF1>if</span><span class=cF0> (bd-&gt;type == </span><span class=cF3>BDT_ATA</span><span class=cF0>)
<a name="l1227"></a> </span><span class=cF5>AHCIAtaBlksRead</span><span class=cF0>(bd, buf, blk, count);
<a name="l1228"></a> </span><span class=cF1>else</span><span class=cF0>
<a name="l1229"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>FALSE</span><span class=cF0>;
<a name="l1230"></a>
<a name="l1231"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>TRUE</span><span class=cF0>;
<a name="l1232"></a>}
<a name="l1233"></a>
<a name="l1234"></a></span><span class=cF1>Bool</span><span class=cF0> </span><span class=cFD>AHCIAtaWBlks</span><span class=cF0>(</span><span class=cF9>CDrive</span><span class=cF0> *drive, </span><span class=cF1>U8</span><span class=cF0> *buf, </span><span class=cF9>I64</span><span class=cF0> blk, </span><span class=cF9>I64</span><span class=cF0> count)
<a name="l1235"></a>{
<a name="l1236"></a> </span><span class=cF9>CBlkDev</span><span class=cF0> *bd = drive-&gt;bd;
<a name="l1237"></a>
<a name="l1238"></a> </span><span class=cF5>AHCIAtaBlksWrite</span><span class=cF0>(bd, buf, blk, count);
<a name="l1239"></a>
<a name="l1240"></a> </span><span class=cFB>blkdev</span><span class=cF0>.write_count += count;
<a name="l1241"></a>
<a name="l1242"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>TRUE</span><span class=cF0>;
<a name="l1243"></a>}
</span></pre></body>
</html>