mirror of
https://github.com/Zeal-Operating-System/ZealOS.git
synced 2024-12-28 08:16:31 +00:00
dbf8647d59
Added top & right borders to RawDr. Improved spacing in some debug and compiler reporting. Fixed RawPutChar and EdLite tab width. Fixed Ui missing '0x' prefix syntax highlighter bug. Added 32BitPaint demo.
946 lines
99 KiB
HTML
Executable file
946 lines
99 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.08">
|
|
<style type="text/css">
|
|
body {background-color:#000000;}
|
|
.cF0{color:#ffffff;background-color:#000000;}
|
|
.cF1{color:#3465a4;background-color:#000000;}
|
|
.cF2{color:#4e9a06;background-color:#000000;}
|
|
.cF3{color:#06989a;background-color:#000000;}
|
|
.cF4{color:#a24444;background-color:#000000;}
|
|
.cF5{color:#75507b;background-color:#000000;}
|
|
.cF6{color:#ce982f;background-color:#000000;}
|
|
.cF7{color:#bcc0b9;background-color:#000000;}
|
|
.cF8{color:#555753;background-color:#000000;}
|
|
.cF9{color:#729fcf;background-color:#000000;}
|
|
.cFA{color:#82bc49;background-color:#000000;}
|
|
.cFB{color:#34e2e2;background-color:#000000;}
|
|
.cFC{color:#ac3535;background-color:#000000;}
|
|
.cFD{color:#ad7fa8;background-color:#000000;}
|
|
.cFE{color:#fce94f;background-color:#000000;}
|
|
.cFF{color:#000000;background-color:#000000;}
|
|
</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>AHCILBA48CapacityGet</span><span class=cF0>(</span><span class=cF9>U16</span><span class=cF0> *id_record)
|
|
<a name="l12"></a>{</span><span class=cF2>//Get capacity of drive, in LBA blocks.</span><span class=cF0>
|
|
<a name="l13"></a></span><span class=cF2>//Capacity is stored in a U64, so we take the shortcut</span><span class=cF0>
|
|
<a name="l14"></a></span><span class=cF2>//and access the U16-indexed ID record as U64 indexed. Zero-based value.</span><span class=cF0>
|
|
<a name="l15"></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="l16"></a>}
|
|
<a name="l17"></a>
|
|
<a name="l18"></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="l19"></a>{</span><span class=cF2>//Get next free command slot in port; if none, throw error.</span><span class=cF0>
|
|
<a name="l20"></a> </span><span class=cF9>I64</span><span class=cF0> i;
|
|
<a name="l21"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port = &</span><span class=cFB>blkdev</span><span class=cF0>.ahci_hba->ports[port_num];
|
|
<a name="l22"></a> </span><span class=cF9>U32</span><span class=cF0> slots = port->sata_active | port->cmd_issue;
|
|
<a name="l23"></a>
|
|
<a name="l24"></a> </span><span class=cF1>for</span><span class=cF0> (i = </span><span class=cFE>0</span><span class=cF0>; i < </span><span class=cFB>blkdev</span><span class=cF0>.cmd_slot_count; i++)
|
|
<a name="l25"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l26"></a> </span><span class=cF1>if</span><span class=cF0> (!</span><span class=cF7>(</span><span class=cF0>slots & </span><span class=cFE>1</span><span class=cF7>)</span><span class=cF0>)
|
|
<a name="l27"></a> </span><span class=cF1>return</span><span class=cF0> i;
|
|
<a name="l28"></a>
|
|
<a name="l29"></a> slots >>= </span><span class=cFE>1</span><span class=cF0>;
|
|
<a name="l30"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l31"></a>
|
|
<a name="l32"></a> </span><span class=cF5>SysErr</span><span class=cF0>(</span><span class=cF6>"AHCI: No empty command slots on port %d!\n"</span><span class=cF0>, port_num);
|
|
<a name="l33"></a> </span><span class=cF5>throw</span><span class=cF0>(</span><span class=cF6>'AHCI'</span><span class=cF0>);
|
|
<a name="l34"></a>}
|
|
<a name="l35"></a>
|
|
<a name="l36"></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="l37"></a>{</span><span class=cF2>//Check if the command engine is running on port.</span><span class=cF0>
|
|
<a name="l38"></a> </span><span class=cF1>return</span><span class=cF0> !(</span><span class=cFB>blkdev</span><span class=cF0>.ahci_hba->ports[port_num].command & </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="l39"></a>}
|
|
<a name="l40"></a>
|
|
<a name="l41"></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="l42"></a>{</span><span class=cF2>//Stop command engine on port.</span><span class=cF0>
|
|
<a name="l43"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port = &</span><span class=cFB>blkdev</span><span class=cF0>.ahci_hba->ports[port_num];
|
|
<a name="l44"></a>
|
|
<a name="l45"></a> </span><span class=cF5>Btr</span><span class=cF0>(&port->command, </span><span class=cF3>AHCI_PxCMDf_ST</span><span class=cF0>);
|
|
<a name="l46"></a> </span><span class=cF5>Btr</span><span class=cF0>(&port->command, </span><span class=cF3>AHCI_PxCMDf_FRE</span><span class=cF0>);
|
|
<a name="l47"></a>
|
|
<a name="l48"></a> </span><span class=cF1>while</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&port->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>&port->command, </span><span class=cF3>AHCI_PxCMDf_FR</span><span class=cF7>)</span><span class=cF0>);
|
|
<a name="l49"></a>}
|
|
<a name="l50"></a>
|
|
<a name="l51"></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="l52"></a>{</span><span class=cF2>//Start command engine on port.</span><span class=cF0>
|
|
<a name="l53"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port = &</span><span class=cFB>blkdev</span><span class=cF0>.ahci_hba->ports[port_num];
|
|
<a name="l54"></a>
|
|
<a name="l55"></a> </span><span class=cF1>while</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&port->command, </span><span class=cF3>AHCI_PxCMDf_CR</span><span class=cF7>)</span><span class=cF0>);
|
|
<a name="l56"></a>
|
|
<a name="l57"></a> </span><span class=cF5>Bts</span><span class=cF0>(&port->command, </span><span class=cF3>AHCI_PxCMDf_FRE</span><span class=cF0>);
|
|
<a name="l58"></a> </span><span class=cF5>Bts</span><span class=cF0>(&port->command, </span><span class=cF3>AHCI_PxCMDf_ST</span><span class=cF0>);
|
|
<a name="l59"></a>}
|
|
<a name="l60"></a>
|
|
<a name="l61"></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="l62"></a>{</span><span class=cF2>//Wait until DRQ & BSY are clear in port task file.</span><span class=cF0>
|
|
<a name="l63"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port = &</span><span class=cFB>blkdev</span><span class=cF0>.ahci_hba->ports[port_num];
|
|
<a name="l64"></a>
|
|
<a name="l65"></a> </span><span class=cF1>do</span><span class=cF0>
|
|
<a name="l66"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l67"></a> </span><span class=cF1>if</span><span class=cF0> (!</span><span class=cF7>(</span><span class=cF0>port->task_file_data & (</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="l68"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>TRUE</span><span class=cF0>;
|
|
<a name="l69"></a> </span><span class=cF5>Yield</span><span class=cF0>; </span><span class=cF2>// don't hang OS</span><span class=cF0>
|
|
<a name="l70"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l71"></a> </span><span class=cF1>while</span><span class=cF0> (timeout > </span><span class=cF5>tS</span><span class=cF0>);
|
|
<a name="l72"></a>
|
|
<a name="l73"></a> </span><span class=cF1>if</span><span class=cF0> (throwing)
|
|
<a name="l74"></a> </span><span class=cF7>{</span><span class=cF0> </span><span class=cF5>SysErr</span><span class=cF0>(</span><span class=cF6>"AHCI: Port %d hung.\n"</span><span class=cF0>, port_num);
|
|
<a name="l75"></a> </span><span class=cF5>throw</span><span class=cF0>(</span><span class=cF6>'AHCI'</span><span class=cF0>);
|
|
<a name="l76"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l77"></a>
|
|
<a name="l78"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>FALSE</span><span class=cF0>;
|
|
<a name="l79"></a>}
|
|
<a name="l80"></a>
|
|
<a name="l81"></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="l82"></a>{</span><span class=cF2>//Software reset of port. Port command engine must be started after this.</span><span class=cF0>
|
|
<a name="l83"></a> </span><span class=cF2>//If port is not responsive we do a full reset.</span><span class=cF0>
|
|
<a name="l84"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port = &</span><span class=cFB>blkdev</span><span class=cF0>.ahci_hba->ports[port_num];
|
|
<a name="l85"></a>
|
|
<a name="l86"></a> </span><span class=cFD>AHCIPortCmdStop</span><span class=cF0>(port_num);
|
|
<a name="l87"></a>
|
|
<a name="l88"></a> port->interrupt_status = port->interrupt_status; </span><span class=cF2>//Acknowledge all interrupt statuses.</span><span class=cF0>
|
|
<a name="l89"></a>
|
|
<a name="l90"></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="l91"></a> </span><span class=cF7>{</span><span class=cF2>//Perform 'more intrusive' HBA<->Port comm reset (sec. 10.4.2 of spec).</span><span class=cF0>
|
|
<a name="l92"></a> port->sata_ctrl = </span><span class=cF3>AHCI_PxSCTLF_DET_INIT</span><span class=cF0>;
|
|
<a name="l93"></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="l94"></a> port->sata_ctrl = </span><span class=cFE>0</span><span class=cF0>;
|
|
<a name="l95"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l96"></a>
|
|
<a name="l97"></a> </span><span class=cF1>while</span><span class=cF0> (port->sata_status & </span><span class=cFE>0xF</span><span class=cF0> != </span><span class=cF3>AHCI_PxSSTSF_DET_PRESENT</span><span class=cF0>);
|
|
<a name="l98"></a>
|
|
<a name="l99"></a> port->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="l100"></a>}
|
|
<a name="l101"></a>
|
|
<a name="l102"></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="l103"></a>{</span><span class=cF2>//Get current command slot header on port.</span><span class=cF0>
|
|
<a name="l104"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port = &</span><span class=cFB>blkdev</span><span class=cF0>.ahci_hba->ports[port_num];
|
|
<a name="l105"></a> </span><span class=cF9>CPortCmdHeader</span><span class=cF0> *cmd_header = port->cmd_list_base;
|
|
<a name="l106"></a>
|
|
<a name="l107"></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="l108"></a>}
|
|
<a name="l109"></a>
|
|
<a name="l110"></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="l111"></a>{</span><span class=cF2>//Wait on command completion after command issue, and double check any error.</span><span class=cF0>
|
|
<a name="l112"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port = &</span><span class=cFB>blkdev</span><span class=cF0>.ahci_hba->ports[port_num];
|
|
<a name="l113"></a>
|
|
<a name="l114"></a> </span><span class=cF1>while</span><span class=cF0> (</span><span class=cF3>TRUE</span><span class=cF0>)
|
|
<a name="l115"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l116"></a> </span><span class=cF1>if</span><span class=cF0> (!</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&port->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="l117"></a> </span><span class=cF1>break</span><span class=cF0>;
|
|
<a name="l118"></a>
|
|
<a name="l119"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&port->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://tomawezome.github.io/ZealOS/Kernel/KernelA.HH.html#l2930"><span class=cF4>ATAS_ERR</span></a><span class=cF2>)</span><span class=cF0>
|
|
<a name="l120"></a> {
|
|
<a name="l121"></a>error:
|
|
<a name="l122"></a> </span><span class=cF5>SysErr</span><span class=cF0>(</span><span class=cF6>"AHCI: Port %d: Command failed!\n"</span><span class=cF0>, port_num);
|
|
<a name="l123"></a> </span><span class=cF5>throw</span><span class=cF0>(</span><span class=cF6>'AHCI'</span><span class=cF0>);
|
|
<a name="l124"></a> }
|
|
<a name="l125"></a>
|
|
<a name="l126"></a> </span><span class=cF5>Yield</span><span class=cF0>; </span><span class=cF2>// don't hang OS</span><span class=cF0>
|
|
<a name="l127"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l128"></a>
|
|
<a name="l129"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&port->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="l130"></a> </span><span class=cF1>goto</span><span class=cF0> error;
|
|
<a name="l131"></a>}
|
|
<a name="l132"></a>
|
|
<a name="l133"></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="l134"></a>{
|
|
<a name="l135"></a> </span><span class=cF9>CPortCmdTable</span><span class=cF0> *cmd_table;
|
|
<a name="l136"></a> </span><span class=cF9>CFisH2D</span><span class=cF0> *cmd_fis;
|
|
<a name="l137"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port = bd->ahci_port;
|
|
<a name="l138"></a> </span><span class=cF9>I64</span><span class=cF0> cmd_slot = </span><span class=cFD>AHCIPortCmdSlotGet</span><span class=cF0>(bd->port_num);
|
|
<a name="l139"></a> </span><span class=cF9>CPortCmdHeader</span><span class=cF0> *cmd_header = </span><span class=cFD>AHCIPortActiveHeaderGet</span><span class=cF0>(bd->port_num, cmd_slot);
|
|
<a name="l140"></a> </span><span class=cF9>U32</span><span class=cF0> *buf;
|
|
<a name="l141"></a>
|
|
<a name="l142"></a> </span><span class=cF1>if</span><span class=cF0> (port->signature != </span><span class=cF3>AHCI_PxSIG_ATAPI</span><span class=cF0>)
|
|
<a name="l143"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l144"></a> </span><span class=cF5>SysErr</span><span class=cF0>(</span><span class=cF6>"AHCI: Drive is not an ATAPI drive!\n"</span><span class=cF0>);
|
|
<a name="l145"></a> </span><span class=cF5>throw</span><span class=cF0>(</span><span class=cF6>'AHCI'</span><span class=cF0>);
|
|
<a name="l146"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l147"></a>
|
|
<a name="l148"></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>->code_heap);
|
|
<a name="l149"></a>
|
|
<a name="l150"></a> </span><span class=cF5>Bts</span><span class=cF0>(&cmd_header->desc, </span><span class=cF3>AHCI_CH_DESCf_A</span><span class=cF0>);
|
|
<a name="l151"></a>
|
|
<a name="l152"></a> cmd_table = cmd_header->cmd_table_base;
|
|
<a name="l153"></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="l154"></a>
|
|
<a name="l155"></a> </span><span class=cF2>//Set up single PRD</span><span class=cF0>
|
|
<a name="l156"></a> cmd_table->prdt[</span><span class=cFE>0</span><span class=cF0>].data_base = buf;
|
|
<a name="l157"></a> cmd_table->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="l158"></a> cmd_header->prdt_len = </span><span class=cFE>1</span><span class=cF0>;
|
|
<a name="l159"></a>
|
|
<a name="l160"></a> cmd_fis = &cmd_table->cmd_fis;
|
|
<a name="l161"></a>
|
|
<a name="l162"></a> cmd_fis->type = </span><span class=cF3>FISt_H2D</span><span class=cF0>;
|
|
<a name="l163"></a> </span><span class=cF5>Bts</span><span class=cF0>(&cmd_fis->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="l164"></a> cmd_fis->command = </span><span class=cF3>ATA_PACKET</span><span class=cF0>;
|
|
<a name="l165"></a> cmd_table->acmd[</span><span class=cFE>0</span><span class=cF0>] = </span><span class=cF3>ATAPI_READ_CAPACITY</span><span class=cF0> >> </span><span class=cFE>8</span><span class=cF0>;
|
|
<a name="l166"></a>
|
|
<a name="l167"></a> </span><span class=cFD>AHCIPortWait</span><span class=cF0>(bd->port_num, </span><span class=cF5>tS</span><span class=cF0> + </span><span class=cFE>2</span><span class=cF0>);
|
|
<a name="l168"></a> </span><span class=cF5>Bts</span><span class=cF0>(&port->cmd_issue, cmd_slot); </span><span class=cF2>//Issue the command.</span><span class=cF0>
|
|
<a name="l169"></a>
|
|
<a name="l170"></a> </span><span class=cF1>try</span><span class=cF0>
|
|
<a name="l171"></a> </span><span class=cFD>AHCIPortCmdWait</span><span class=cF0>(bd->port_num, cmd_slot);
|
|
<a name="l172"></a> </span><span class=cF1>catch</span><span class=cF0>
|
|
<a name="l173"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l174"></a> </span><span class=cF5>Fs</span><span class=cF0>->catch_except = </span><span class=cF3>TRUE</span><span class=cF0>;
|
|
<a name="l175"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cFE>0</span><span class=cF0>;
|
|
<a name="l176"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l177"></a>
|
|
<a name="l178"></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="l179"></a>}
|
|
<a name="l180"></a>
|
|
<a name="l181"></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="l182"></a>{
|
|
<a name="l183"></a> </span><span class=cF9>CPortCmdTable</span><span class=cF0> *cmd_table;
|
|
<a name="l184"></a> </span><span class=cF9>CFisH2D</span><span class=cF0> *cmd_fis;
|
|
<a name="l185"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port = bd->ahci_port;
|
|
<a name="l186"></a> </span><span class=cF9>I64</span><span class=cF0> cmd_slot = </span><span class=cFD>AHCIPortCmdSlotGet</span><span class=cF0>(bd->port_num);
|
|
<a name="l187"></a> </span><span class=cF9>CPortCmdHeader</span><span class=cF0> *cmd_header = </span><span class=cFD>AHCIPortActiveHeaderGet</span><span class=cF0>(bd->port_num, cmd_slot);
|
|
<a name="l188"></a>
|
|
<a name="l189"></a> </span><span class=cF1>if</span><span class=cF0> (port->signature != </span><span class=cF3>AHCI_PxSIG_ATAPI</span><span class=cF0>)
|
|
<a name="l190"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l191"></a> </span><span class=cF5>SysErr</span><span class=cF0>(</span><span class=cF6>"AHCI: Drive is not an ATAPI drive!\n"</span><span class=cF0>);
|
|
<a name="l192"></a> </span><span class=cF5>throw</span><span class=cF0>(</span><span class=cF6>'AHCI'</span><span class=cF0>);
|
|
<a name="l193"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l194"></a>
|
|
<a name="l195"></a> </span><span class=cF5>Bts</span><span class=cF0>(&cmd_header->desc, </span><span class=cF3>AHCI_CH_DESCf_A</span><span class=cF0>);
|
|
<a name="l196"></a>
|
|
<a name="l197"></a> cmd_table = cmd_header->cmd_table_base;
|
|
<a name="l198"></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="l199"></a>
|
|
<a name="l200"></a> cmd_fis = &cmd_table->cmd_fis;
|
|
<a name="l201"></a>
|
|
<a name="l202"></a> cmd_fis->type = </span><span class=cF3>FISt_H2D</span><span class=cF0>;
|
|
<a name="l203"></a> </span><span class=cF5>Bts</span><span class=cF0>(&cmd_fis->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="l204"></a> cmd_fis->command = </span><span class=cF3>ATA_PACKET</span><span class=cF0>;
|
|
<a name="l205"></a> cmd_table->acmd[</span><span class=cFE>0</span><span class=cF0>] = </span><span class=cF3>ATAPI_SEEK</span><span class=cF0> >> </span><span class=cFE>8</span><span class=cF0>;
|
|
<a name="l206"></a> cmd_table->acmd[</span><span class=cFE>2</span><span class=cF0>] = blk.u8[</span><span class=cFE>4</span><span class=cF0>];
|
|
<a name="l207"></a> cmd_table->acmd[</span><span class=cFE>3</span><span class=cF0>] = blk.u8[</span><span class=cFE>3</span><span class=cF0>];
|
|
<a name="l208"></a> cmd_table->acmd[</span><span class=cFE>4</span><span class=cF0>] = blk.u8[</span><span class=cFE>2</span><span class=cF0>];
|
|
<a name="l209"></a> cmd_table->acmd[</span><span class=cFE>5</span><span class=cF0>] = blk.u8[</span><span class=cFE>1</span><span class=cF0>];
|
|
<a name="l210"></a>
|
|
<a name="l211"></a> </span><span class=cFD>AHCIPortWait</span><span class=cF0>(bd->port_num, </span><span class=cF5>tS</span><span class=cF0> + </span><span class=cFE>2</span><span class=cF0>);
|
|
<a name="l212"></a> </span><span class=cF5>Bts</span><span class=cF0>(&port->cmd_issue, cmd_slot); </span><span class=cF2>//Issue the command.</span><span class=cF0>
|
|
<a name="l213"></a>
|
|
<a name="l214"></a> </span><span class=cF1>try</span><span class=cF0>
|
|
<a name="l215"></a> </span><span class=cFD>AHCIPortCmdWait</span><span class=cF0>(bd->port_num, cmd_slot);
|
|
<a name="l216"></a> </span><span class=cF1>catch</span><span class=cF0>
|
|
<a name="l217"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l218"></a> </span><span class=cF5>Fs</span><span class=cF0>->catch_except = </span><span class=cF3>TRUE</span><span class=cF0>;
|
|
<a name="l219"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>FALSE</span><span class=cF0>;
|
|
<a name="l220"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l221"></a>
|
|
<a name="l222"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>TRUE</span><span class=cF0>;
|
|
<a name="l223"></a>}
|
|
<a name="l224"></a>
|
|
<a name="l225"></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="l226"></a>{
|
|
<a name="l227"></a> </span><span class=cF9>CPortCmdTable</span><span class=cF0> *cmd_table;
|
|
<a name="l228"></a> </span><span class=cF9>CFisH2D</span><span class=cF0> *cmd_fis;
|
|
<a name="l229"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port = bd->ahci_port;
|
|
<a name="l230"></a> </span><span class=cF9>I64</span><span class=cF0> cmd_slot = </span><span class=cFD>AHCIPortCmdSlotGet</span><span class=cF0>(bd->port_num);
|
|
<a name="l231"></a> </span><span class=cF9>CPortCmdHeader</span><span class=cF0> *cmd_header = </span><span class=cFD>AHCIPortActiveHeaderGet</span><span class=cF0>(bd->port_num, cmd_slot);
|
|
<a name="l232"></a>
|
|
<a name="l233"></a> </span><span class=cF1>if</span><span class=cF0> (port->signature != </span><span class=cF3>AHCI_PxSIG_ATAPI</span><span class=cF0>)
|
|
<a name="l234"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l235"></a> </span><span class=cF5>SysErr</span><span class=cF0>(</span><span class=cF6>"AHCI: Drive is not an ATAPI drive!\n"</span><span class=cF0>);
|
|
<a name="l236"></a> </span><span class=cF5>throw</span><span class=cF0>(</span><span class=cF6>'AHCI'</span><span class=cF0>);
|
|
<a name="l237"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l238"></a>
|
|
<a name="l239"></a> </span><span class=cF5>Bts</span><span class=cF0>(&cmd_header->desc, </span><span class=cF3>AHCI_CH_DESCf_A</span><span class=cF0>);
|
|
<a name="l240"></a>
|
|
<a name="l241"></a> cmd_table = cmd_header->cmd_table_base;
|
|
<a name="l242"></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="l243"></a>
|
|
<a name="l244"></a> cmd_fis = &cmd_table->cmd_fis;
|
|
<a name="l245"></a>
|
|
<a name="l246"></a> cmd_fis->type = </span><span class=cF3>FISt_H2D</span><span class=cF0>;
|
|
<a name="l247"></a> </span><span class=cF5>Bts</span><span class=cF0>(&cmd_fis->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="l248"></a> cmd_fis->command = </span><span class=cF3>ATA_PACKET</span><span class=cF0>;
|
|
<a name="l249"></a> cmd_table->acmd[</span><span class=cFE>0</span><span class=cF0>] = </span><span class=cF3>ATAPI_START_STOP_UNIT</span><span class=cF0> >> </span><span class=cFE>8</span><span class=cF0>;
|
|
<a name="l250"></a> cmd_table->acmd[</span><span class=cFE>4</span><span class=cF0>] = </span><span class=cF1>start</span><span class=cF0>;
|
|
<a name="l251"></a>
|
|
<a name="l252"></a> </span><span class=cFD>AHCIPortWait</span><span class=cF0>(bd->port_num, </span><span class=cF5>tS</span><span class=cF0> + </span><span class=cFE>2</span><span class=cF0>);
|
|
<a name="l253"></a> </span><span class=cF5>Bts</span><span class=cF0>(&port->cmd_issue, cmd_slot); </span><span class=cF2>//Issue the command.</span><span class=cF0>
|
|
<a name="l254"></a>
|
|
<a name="l255"></a> </span><span class=cF1>try</span><span class=cF0>
|
|
<a name="l256"></a> </span><span class=cFD>AHCIPortCmdWait</span><span class=cF0>(bd->port_num, cmd_slot);
|
|
<a name="l257"></a> </span><span class=cF1>catch</span><span class=cF0>
|
|
<a name="l258"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l259"></a> </span><span class=cF5>Fs</span><span class=cF0>->catch_except = </span><span class=cF3>TRUE</span><span class=cF0>;
|
|
<a name="l260"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>FALSE</span><span class=cF0>;
|
|
<a name="l261"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l262"></a>
|
|
<a name="l263"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>TRUE</span><span class=cF0>;
|
|
<a name="l264"></a>}
|
|
<a name="l265"></a>
|
|
<a name="l266"></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="l267"></a>{ </span><span class=cF2>// returns whether disc tray was successfully ejected.</span><span class=cF0>
|
|
<a name="l268"></a> </span><span class=cF1>try</span><span class=cF0>
|
|
<a name="l269"></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="l270"></a> </span><span class=cF1>catch</span><span class=cF0>
|
|
<a name="l271"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l272"></a> </span><span class=cF5>Fs</span><span class=cF0>->catch_except = </span><span class=cF3>TRUE</span><span class=cF0>;
|
|
<a name="l273"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>FALSE</span><span class=cF0>;
|
|
<a name="l274"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l275"></a>}
|
|
<a name="l276"></a>
|
|
<a name="l277"></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="l278"></a>{ </span><span class=cF2>// returns whether disc tray was successfully closed & disc loaded.</span><span class=cF0>
|
|
<a name="l279"></a> </span><span class=cF1>try</span><span class=cF0>
|
|
<a name="l280"></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="l281"></a> </span><span class=cF1>catch</span><span class=cF0>
|
|
<a name="l282"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l283"></a> </span><span class=cF5>Fs</span><span class=cF0>->catch_except = </span><span class=cF3>TRUE</span><span class=cF0>;
|
|
<a name="l284"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>FALSE</span><span class=cF0>;
|
|
<a name="l285"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l286"></a>}
|
|
<a name="l287"></a>
|
|
<a name="l288"></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="l289"></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="l290"></a> </span><span class=cF9>CPortCmdTable</span><span class=cF0> *cmd_table;
|
|
<a name="l291"></a> </span><span class=cF9>CFisH2D</span><span class=cF0> *cmd_fis;
|
|
<a name="l292"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port = bd->ahci_port;
|
|
<a name="l293"></a> </span><span class=cF9>I64</span><span class=cF0> cmd_slot = </span><span class=cFD>AHCIPortCmdSlotGet</span><span class=cF0>(bd->port_num);
|
|
<a name="l294"></a> </span><span class=cF9>CPortCmdHeader</span><span class=cF0> *cmd_header = </span><span class=cFD>AHCIPortActiveHeaderGet</span><span class=cF0>(bd->port_num, cmd_slot);
|
|
<a name="l295"></a> </span><span class=cF9>U16</span><span class=cF0> *dev_id_record;
|
|
<a name="l296"></a>
|
|
<a name="l297"></a> port->interrupt_status = port->interrupt_status; </span><span class=cF2>//TODO: Why?</span><span class=cF0>
|
|
<a name="l298"></a>
|
|
<a name="l299"></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="l300"></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>->code_heap);
|
|
<a name="l301"></a>
|
|
<a name="l302"></a> cmd_table = cmd_header->cmd_table_base;
|
|
<a name="l303"></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="l304"></a>
|
|
<a name="l305"></a> </span><span class=cF2>//Set up single PRD</span><span class=cF0>
|
|
<a name="l306"></a> cmd_table->prdt[</span><span class=cFE>0</span><span class=cF0>].data_base = dev_id_record;
|
|
<a name="l307"></a> cmd_table->prdt[</span><span class=cFE>0</span><span class=cF0>].data_base_upper = </span><span class=cFE>0</span><span class=cF0>;
|
|
<a name="l308"></a> cmd_table->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="l309"></a> cmd_header->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="l310"></a>
|
|
<a name="l311"></a> </span><span class=cF2>//Setup command FIS</span><span class=cF0>
|
|
<a name="l312"></a> cmd_fis = &cmd_table->cmd_fis;
|
|
<a name="l313"></a>
|
|
<a name="l314"></a> cmd_fis->type = </span><span class=cF3>FISt_H2D</span><span class=cF0>;
|
|
<a name="l315"></a> </span><span class=cF5>Bts</span><span class=cF0>(&cmd_fis->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="l316"></a>
|
|
<a name="l317"></a> </span><span class=cF1>if</span><span class=cF0> (port->signature == </span><span class=cF3>AHCI_PxSIG_ATAPI</span><span class=cF0>)
|
|
<a name="l318"></a> cmd_fis->command = </span><span class=cF3>ATA_IDENTIFY_PACKET</span><span class=cF0>;
|
|
<a name="l319"></a> </span><span class=cF1>else</span><span class=cF0>
|
|
<a name="l320"></a> cmd_fis->command = </span><span class=cF3>ATA_IDENTIFY</span><span class=cF0>;
|
|
<a name="l321"></a>
|
|
<a name="l322"></a> cmd_fis->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="l323"></a>
|
|
<a name="l324"></a> </span><span class=cF2>//Wait on previous command to complete.</span><span class=cF0>
|
|
<a name="l325"></a> </span><span class=cFD>AHCIPortWait</span><span class=cF0>(bd->port_num, </span><span class=cF5>tS</span><span class=cF0> + </span><span class=cFE>2</span><span class=cF0>);
|
|
<a name="l326"></a>
|
|
<a name="l327"></a> </span><span class=cF5>Bts</span><span class=cF0>(&port->cmd_issue, cmd_slot); </span><span class=cF2>//Issue the command.</span><span class=cF0>
|
|
<a name="l328"></a> </span><span class=cFD>AHCIPortCmdWait</span><span class=cF0>(bd->port_num, cmd_slot);
|
|
<a name="l329"></a>
|
|
<a name="l330"></a> </span><span class=cF5>Free</span><span class=cF0>(bd->dev_id_record);
|
|
<a name="l331"></a> bd->dev_id_record = dev_id_record;
|
|
<a name="l332"></a>
|
|
<a name="l333"></a> </span><span class=cF1>if</span><span class=cF0> (port->signature == </span><span class=cF3>AHCI_PxSIG_ATA</span><span class=cF0>)
|
|
<a name="l334"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l335"></a> bd->max_blk = </span><span class=cFD>AHCILBA48CapacityGet</span><span class=cF0>(dev_id_record);
|
|
<a name="l336"></a> </span><span class=cF6>"MAX BLOCK %d, disk size %d MiB\n"</span><span class=cF0>, bd->max_blk, bd->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="l337"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l338"></a> </span><span class=cF1>else</span><span class=cF0>
|
|
<a name="l339"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l340"></a> bd->max_blk = </span><span class=cFD>AHCIAtapiCapacityGet</span><span class=cF0>(bd);
|
|
<a name="l341"></a> </span><span class=cF6>"MAX BLOCK %d, disk size %d MiB\n"</span><span class=cF0>, bd->max_blk, bd->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="l342"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l343"></a>}
|
|
<a name="l344"></a>
|
|
<a name="l345"></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="l346"></a>{</span><span class=cF2>//Make sure buffer is accessible by HBA controller.</span><span class=cF0>
|
|
<a name="l347"></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="l348"></a></span><span class=cF2>//MAlloc provides U64-aligned addresses, and can allocate in the code heap ( <4GB ).</span><span class=cF0>
|
|
<a name="l349"></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="l350"></a> </span><span class=cF1>if</span><span class=cF0>(user_buf + buf_size > </span><span class=cF3>U32_MAX</span><span class=cF0> || user_buf & </span><span class=cFE>1</span><span class=cF0>)
|
|
<a name="l351"></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="l352"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>"Aligning buffer under 32-bit range\n";</span><span class=cF0>
|
|
<a name="l353"></a>
|
|
<a name="l354"></a> </span><span class=cF5>Free</span><span class=cF0>(bd->prd_buf);
|
|
<a name="l355"></a> bd->prd_buf = </span><span class=cF5>MAlloc</span><span class=cF0>(buf_size, </span><span class=cFB>sys_task</span><span class=cF0>->code_heap);
|
|
<a name="l356"></a>
|
|
<a name="l357"></a> </span><span class=cF5>Bts</span><span class=cF0>(&bd->flags, </span><span class=cF3>BDf_INTERNAL_BUF</span><span class=cF0>);
|
|
<a name="l358"></a>
|
|
<a name="l359"></a> </span><span class=cF1>if</span><span class=cF0> (write)
|
|
<a name="l360"></a> </span><span class=cF5>MemCopy</span><span class=cF0>(bd->prd_buf, user_buf, buf_size);
|
|
<a name="l361"></a>
|
|
<a name="l362"></a> </span><span class=cF1>return</span><span class=cF0> bd->prd_buf;
|
|
<a name="l363"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l364"></a> </span><span class=cF5>Btr</span><span class=cF0>(&bd->flags, </span><span class=cF3>BDF_INTERNAL_BUF</span><span class=cF0>);
|
|
<a name="l365"></a>
|
|
<a name="l366"></a> </span><span class=cF1>return</span><span class=cF0> user_buf;
|
|
<a name="l367"></a>}
|
|
<a name="l368"></a>
|
|
<a name="l369"></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="l370"></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="l371"></a></span><span class=cF2>//Don't use this, use the AHCIAtaBlksRead and AHCIAtaBlksWrite functions.</span><span class=cF0>
|
|
<a name="l372"></a> </span><span class=cF9>CPortCmdTable</span><span class=cF0> *cmd_table;
|
|
<a name="l373"></a> </span><span class=cF9>CFisH2D</span><span class=cF0> *cmd_fis;
|
|
<a name="l374"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port = bd->ahci_port;
|
|
<a name="l375"></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->port_num);
|
|
<a name="l376"></a> </span><span class=cF9>CPortCmdHeader</span><span class=cF0> *cmd_header = </span><span class=cFD>AHCIPortActiveHeaderGet</span><span class=cF0>(bd->port_num, cmd_slot);
|
|
<a name="l377"></a> </span><span class=cF1>U8</span><span class=cF0> *internal_buf_tmp, *internal_buf;
|
|
<a name="l378"></a> </span><span class=cF1>Bool</span><span class=cF0> unlock;
|
|
<a name="l379"></a>
|
|
<a name="l380"></a> </span><span class=cF1>if</span><span class=cF0> (port->signature != </span><span class=cF3>AHCI_PxSIG_ATA</span><span class=cF0>)
|
|
<a name="l381"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l382"></a> </span><span class=cF5>SysErr</span><span class=cF0>(</span><span class=cF6>"AHCI: Drive is not an ATA drive!\n"</span><span class=cF0>);
|
|
<a name="l383"></a> </span><span class=cF5>throw</span><span class=cF0>(</span><span class=cF6>'AHCI'</span><span class=cF0>);
|
|
<a name="l384"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l385"></a>
|
|
<a name="l386"></a> </span><span class=cF1>if</span><span class=cF0> (count < </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="l387"></a> </span><span class=cF1>if</span><span class=cF0> (count > </span><span class=cF3>AHCI_PRDT_MAX_BLOCKS</span><span class=cF0>)
|
|
<a name="l388"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l389"></a> </span><span class=cF5>SysErr</span><span class=cF0>(</span><span class=cF6>"AHCI: Block count %d max allowed in one command (%d)"</span><span class=cF0>, count, </span><span class=cF3>AHCI_PRDT_MAX_BLOCKS</span><span class=cF0>);
|
|
<a name="l390"></a> </span><span class=cF5>throw</span><span class=cF0>(</span><span class=cF6>'AHCI'</span><span class=cF0>);
|
|
<a name="l391"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l392"></a>
|
|
<a name="l393"></a> unlock = </span><span class=cF5>BlkDevLock</span><span class=cF0>(bd);
|
|
<a name="l394"></a>
|
|
<a name="l395"></a> </span><span class=cF2>//Determine buffer size and PRDT length.</span><span class=cF0>
|
|
<a name="l396"></a> buf_size = buf_size_tmp = count * </span><span class=cF3>BLK_SIZE</span><span class=cF0>;
|
|
<a name="l397"></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="l398"></a>
|
|
<a name="l399"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>"PRDT Length:\t%d\n", prdt_len;</span><span class=cF0>
|
|
<a name="l400"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>"Count:\t\t\t%d\n", count;</span><span class=cF0>
|
|
<a name="l401"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>"Buffer size:\t%X\n", buf_size;</span><span class=cF0>
|
|
<a name="l402"></a>
|
|
<a name="l403"></a> cmd_header->prdt_len = prdt_len; </span><span class=cF2>//Set PRD table length in cmd header.</span><span class=cF0>
|
|
<a name="l404"></a> </span><span class=cF2>//Set 'write' bit depending on 'write' argument.</span><span class=cF0>
|
|
<a name="l405"></a> </span><span class=cF5>BEqual</span><span class=cF0>(&cmd_header->desc, </span><span class=cF3>AHCI_CH_DESCf_W</span><span class=cF0>, write);
|
|
<a name="l406"></a>
|
|
<a name="l407"></a> internal_buf = internal_buf_tmp = </span><span class=cFD>AHCIBufferAlign</span><span class=cF0>(bd, buf, buf_size, write);
|
|
<a name="l408"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>"Buffer:\t\t\t0x%X\n", internal_buf;</span><span class=cF0>
|
|
<a name="l409"></a>
|
|
<a name="l410"></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="l411"></a>
|
|
<a name="l412"></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="l413"></a> cmd_table = cmd_header->cmd_table_base;
|
|
<a name="l414"></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="l415"></a>
|
|
<a name="l416"></a> </span><span class=cF2>//Create 'prdt_len' amount of PRD entries in the command table</span><span class=cF0>
|
|
<a name="l417"></a> </span><span class=cF1>for</span><span class=cF0> (i = </span><span class=cFE>0</span><span class=cF0>; i < prdt_len; i++)
|
|
<a name="l418"></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="l419"></a> </span><span class=cF1>if</span><span class=cF0> (buf_size_tmp > </span><span class=cF3>AHCI_PRD_MAX_BYTES</span><span class=cF0>)
|
|
<a name="l420"></a> byte_count = </span><span class=cF3>AHCI_PRD_MAX_BYTES</span><span class=cF0>;
|
|
<a name="l421"></a> </span><span class=cF1>else</span><span class=cF0>
|
|
<a name="l422"></a> byte_count = buf_size_tmp;
|
|
<a name="l423"></a>
|
|
<a name="l424"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>"prdt[%d].data_base_addr = 0x%X\n" , i, internal_buf_tmp;</span><span class=cF0>
|
|
<a name="l425"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>"prdt[%d].data_byte_count = 0x%X\n\n", i, byte_count;</span><span class=cF0>
|
|
<a name="l426"></a>
|
|
<a name="l427"></a> cmd_table->prdt[i].data_base = internal_buf_tmp;
|
|
<a name="l428"></a> cmd_table->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="l429"></a> buf_size_tmp -= byte_count;
|
|
<a name="l430"></a> internal_buf_tmp += byte_count;
|
|
<a name="l431"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l432"></a> </span><span class=cF2>//Setup the command FIS.</span><span class=cF0>
|
|
<a name="l433"></a> cmd_fis = &cmd_table->cmd_fis;
|
|
<a name="l434"></a>
|
|
<a name="l435"></a> cmd_fis->type = </span><span class=cF3>FISt_H2D</span><span class=cF0>;
|
|
<a name="l436"></a> </span><span class=cF5>Bts</span><span class=cF0>(&cmd_fis->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="l437"></a>
|
|
<a name="l438"></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="l439"></a> cmd_fis->command = </span><span class=cF3>ATA_WRITE_DMA_EXT</span><span class=cF0>;
|
|
<a name="l440"></a> </span><span class=cF1>else</span><span class=cF0>
|
|
<a name="l441"></a> cmd_fis->command = </span><span class=cF3>ATA_READ_DMA_EXT</span><span class=cF0>;
|
|
<a name="l442"></a>
|
|
<a name="l443"></a> </span><span class=cF2>//Fill in the rest of the command FIS.</span><span class=cF0>
|
|
<a name="l444"></a> cmd_fis->lba0 = blk.u8[</span><span class=cFE>0</span><span class=cF0>];
|
|
<a name="l445"></a> cmd_fis->lba1 = blk.u8[</span><span class=cFE>1</span><span class=cF0>];
|
|
<a name="l446"></a> cmd_fis->lba2 = blk.u8[</span><span class=cFE>2</span><span class=cF0>];
|
|
<a name="l447"></a> cmd_fis->device = </span><span class=cFE>1</span><span class=cF0> << </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="l448"></a> cmd_fis->lba3 = blk.u8[</span><span class=cFE>3</span><span class=cF0>];
|
|
<a name="l449"></a> cmd_fis->lba4 = blk.u8[</span><span class=cFE>4</span><span class=cF0>];
|
|
<a name="l450"></a> cmd_fis->lba5 = blk.u8[</span><span class=cFE>5</span><span class=cF0>];
|
|
<a name="l451"></a> cmd_fis->count = count;
|
|
<a name="l452"></a>
|
|
<a name="l453"></a> </span><span class=cF2>//Wait on previous command to complete.</span><span class=cF0>
|
|
<a name="l454"></a> </span><span class=cFD>AHCIPortWait</span><span class=cF0>(bd->port_num, </span><span class=cF5>tS</span><span class=cF0> + </span><span class=cFE>2</span><span class=cF0>);
|
|
<a name="l455"></a> </span><span class=cF2>//Issue the command.</span><span class=cF0>
|
|
<a name="l456"></a> </span><span class=cF5>Bts</span><span class=cF0>(&port->cmd_issue, cmd_slot);
|
|
<a name="l457"></a> </span><span class=cF2>//Wait on command to finish.</span><span class=cF0>
|
|
<a name="l458"></a> </span><span class=cFD>AHCIPortCmdWait</span><span class=cF0>(bd->port_num, cmd_slot);
|
|
<a name="l459"></a>
|
|
<a name="l460"></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="l461"></a> </span><span class=cF1>if</span><span class=cF0> (bd->flags & </span><span class=cF3>BDF_INTERNAL_BUF</span><span class=cF0>)
|
|
<a name="l462"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l463"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>"Writing back internal buffer\n";</span><span class=cF0>
|
|
<a name="l464"></a> </span><span class=cF5>MemCopy</span><span class=cF0>(buf, internal_buf, buf_size);
|
|
<a name="l465"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l466"></a>
|
|
<a name="l467"></a> </span><span class=cF1>if</span><span class=cF0> (unlock)
|
|
<a name="l468"></a> </span><span class=cF5>BlkDevUnlock</span><span class=cF0>(bd);
|
|
<a name="l469"></a>
|
|
<a name="l470"></a> </span><span class=cF1>return</span><span class=cF0> cmd_header->prd_byte_count;
|
|
<a name="l471"></a>}
|
|
<a name="l472"></a>
|
|
<a name="l473"></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="l474"></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="l475"></a> </span><span class=cF9>I64</span><span class=cF0> byte_count = </span><span class=cFE>0</span><span class=cF0>;
|
|
<a name="l476"></a> </span><span class=cF1>if</span><span class=cF0> (!count)
|
|
<a name="l477"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cFE>0</span><span class=cF0>;
|
|
<a name="l478"></a> </span><span class=cF1>if</span><span class=cF0> (count <= </span><span class=cF3>AHCI_PRDT_MAX_BLOCKS</span><span class=cF0>)
|
|
<a name="l479"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l480"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>"$GREEN$READ less than MAX_BLOCKS$FG$\n";</span><span class=cF0>
|
|
<a name="l481"></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="l482"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l483"></a> </span><span class=cF1>else</span><span class=cF0>
|
|
<a name="l484"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l485"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>"$GREEN$READ greater than MAX_BLOCKS\n";</span><span class=cF0>
|
|
<a name="l486"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>"read count: %d\n$FG$", count;</span><span class=cF0>
|
|
<a name="l487"></a> </span><span class=cF1>while</span><span class=cF0> (count > </span><span class=cF3>AHCI_PRDT_MAX_BLOCKS</span><span class=cF0>)
|
|
<a name="l488"></a> {
|
|
<a name="l489"></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="l490"></a> count -= </span><span class=cF3>AHCI_PRDT_MAX_BLOCKS</span><span class=cF0>;
|
|
<a name="l491"></a> blk += </span><span class=cF3>AHCI_PRDT_MAX_BLOCKS</span><span class=cF0>;
|
|
<a name="l492"></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="l493"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>"$GREEN$read count: %d\n$FG$", count;</span><span class=cF0>
|
|
<a name="l494"></a> }
|
|
<a name="l495"></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="l496"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l497"></a>
|
|
<a name="l498"></a> </span><span class=cFB>blkdev</span><span class=cF0>.read_count += (count * bd->blk_size) >> </span><span class=cF3>BLK_SIZE_BITS</span><span class=cF0>;
|
|
<a name="l499"></a>
|
|
<a name="l500"></a> </span><span class=cF1>return</span><span class=cF0> byte_count;
|
|
<a name="l501"></a>}
|
|
<a name="l502"></a>
|
|
<a name="l503"></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="l504"></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="l505"></a> </span><span class=cF9>I64</span><span class=cF0> byte_count = </span><span class=cFE>0</span><span class=cF0>;
|
|
<a name="l506"></a>
|
|
<a name="l507"></a> </span><span class=cF1>if</span><span class=cF0> (!count)
|
|
<a name="l508"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cFE>0</span><span class=cF0>;
|
|
<a name="l509"></a> </span><span class=cF1>if</span><span class=cF0> (count <= </span><span class=cF3>AHCI_PRDT_MAX_BLOCKS</span><span class=cF0>)
|
|
<a name="l510"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l511"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>"$GREEN$WRITE less than MAX_BLOCKS$FG$\n";</span><span class=cF0>
|
|
<a name="l512"></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="l513"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l514"></a> </span><span class=cF1>else</span><span class=cF0>
|
|
<a name="l515"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l516"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>"$GREEN$WRITE greater than MAX_BLOCKS\n";</span><span class=cF0>
|
|
<a name="l517"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>"write count: %d$FG$\n", count;</span><span class=cF0>
|
|
<a name="l518"></a> </span><span class=cF1>while</span><span class=cF0> (count > </span><span class=cF3>AHCI_PRDT_MAX_BLOCKS</span><span class=cF0>)
|
|
<a name="l519"></a> {
|
|
<a name="l520"></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="l521"></a> count -= </span><span class=cF3>AHCI_PRDT_MAX_BLOCKS</span><span class=cF0>;
|
|
<a name="l522"></a> blk += </span><span class=cF3>AHCI_PRDT_MAX_BLOCKS</span><span class=cF0>;
|
|
<a name="l523"></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="l524"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>"$GREEN$write count: %d\n$FG$\n", count;</span><span class=cF0>
|
|
<a name="l525"></a> }
|
|
<a name="l526"></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="l527"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l528"></a>
|
|
<a name="l529"></a> </span><span class=cF1>return</span><span class=cF0> byte_count;
|
|
<a name="l530"></a>}
|
|
<a name="l531"></a>
|
|
<a name="l532"></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="l533"></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="l534"></a> </span><span class=cF9>CPortCmdTable</span><span class=cF0> *cmd_table;
|
|
<a name="l535"></a> </span><span class=cF9>CFisH2D</span><span class=cF0> *cmd_fis;
|
|
<a name="l536"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port = bd->ahci_port;
|
|
<a name="l537"></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->port_num);
|
|
<a name="l538"></a> </span><span class=cF9>CPortCmdHeader</span><span class=cF0> *cmd_header = </span><span class=cFD>AHCIPortActiveHeaderGet</span><span class=cF0>(bd->port_num, cmd_slot);
|
|
<a name="l539"></a> </span><span class=cF1>U8</span><span class=cF0> *internal_buf, *internal_buf_tmp;
|
|
<a name="l540"></a> </span><span class=cF9>CAtapiReadCmd</span><span class=cF0> read_cmd;
|
|
<a name="l541"></a> </span><span class=cF1>Bool</span><span class=cF0> unlock;
|
|
<a name="l542"></a>
|
|
<a name="l543"></a> </span><span class=cF1>if</span><span class=cF0> (port->signature != </span><span class=cF3>AHCI_PxSIG_ATAPI</span><span class=cF0>)
|
|
<a name="l544"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l545"></a> </span><span class=cF5>SysErr</span><span class=cF0>(</span><span class=cF6>"AHCI: Drive is not an ATAPI drive!\n"</span><span class=cF0>);
|
|
<a name="l546"></a> </span><span class=cF5>throw</span><span class=cF0>(</span><span class=cF6>'AHCI'</span><span class=cF0>);
|
|
<a name="l547"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l548"></a> </span><span class=cF1>if</span><span class=cF0> (count < </span><span class=cFE>1</span><span class=cF0>)
|
|
<a name="l549"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cFE>0</span><span class=cF0>;
|
|
<a name="l550"></a>
|
|
<a name="l551"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF1>lock</span><span class=cF0>)
|
|
<a name="l552"></a> unlock = </span><span class=cF5>BlkDevLock</span><span class=cF0>(bd);
|
|
<a name="l553"></a>
|
|
<a name="l554"></a> buf_size = buf_size_tmp = count * </span><span class=cF3>DVD_BLK_SIZE</span><span class=cF0>;
|
|
<a name="l555"></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="l556"></a>
|
|
<a name="l557"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>"PRDT Length:\t%d\n", prdt_len;</span><span class=cF0>
|
|
<a name="l558"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>"Count:\t\t\t%d\n", count;</span><span class=cF0>
|
|
<a name="l559"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>"Buffer size:\t%X\n", buf_size;</span><span class=cF0>
|
|
<a name="l560"></a>
|
|
<a name="l561"></a> cmd_header->prdt_len = prdt_len;
|
|
<a name="l562"></a>
|
|
<a name="l563"></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="l564"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>"Buffer:\t\t\t0x%X\n", internal_buf;</span><span class=cF0>
|
|
<a name="l565"></a>
|
|
<a name="l566"></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="l567"></a>
|
|
<a name="l568"></a> </span><span class=cF5>Bts</span><span class=cF0>(&cmd_header->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="l569"></a>
|
|
<a name="l570"></a> cmd_table = cmd_header->cmd_table_base;
|
|
<a name="l571"></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="l572"></a>
|
|
<a name="l573"></a> </span><span class=cF1>for</span><span class=cF0> (i = </span><span class=cFE>0</span><span class=cF0>; i < prdt_len; i++)
|
|
<a name="l574"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l575"></a> </span><span class=cF1>if</span><span class=cF0> (buf_size_tmp > </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="l576"></a> byte_count = </span><span class=cF3>AHCI_PRD_MAX_BYTES</span><span class=cF0>;
|
|
<a name="l577"></a> </span><span class=cF1>else</span><span class=cF0>
|
|
<a name="l578"></a> byte_count = buf_size_tmp;
|
|
<a name="l579"></a>
|
|
<a name="l580"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>"prdt[%d].data_base_addr = 0x%X\n" , i, internal_buf_tmp;</span><span class=cF0>
|
|
<a name="l581"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>"prdt[%d].data_byte_count = 0x%X\n\n", i, byte_count;</span><span class=cF0>
|
|
<a name="l582"></a> cmd_table->prdt[i].data_base = internal_buf_tmp;
|
|
<a name="l583"></a> cmd_table->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="l584"></a>
|
|
<a name="l585"></a> buf_size_tmp -= byte_count;
|
|
<a name="l586"></a> internal_buf_tmp += byte_count;
|
|
<a name="l587"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l588"></a>
|
|
<a name="l589"></a> cmd_fis = &cmd_table->cmd_fis;
|
|
<a name="l590"></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="l591"></a>
|
|
<a name="l592"></a> cmd_fis->type = </span><span class=cF3>FISt_H2D</span><span class=cF0>;
|
|
<a name="l593"></a> </span><span class=cF5>Bts</span><span class=cF0>(&cmd_fis->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="l594"></a>
|
|
<a name="l595"></a> cmd_fis->feature_low = </span><span class=cFE>1</span><span class=cF0>; </span><span class=cF2>//Necessary?</span><span class=cF0>
|
|
<a name="l596"></a> cmd_fis->command = </span><span class=cF3>ATA_PACKET</span><span class=cF0>;
|
|
<a name="l597"></a>
|
|
<a name="l598"></a> </span><span class=cF5>MemSet</span><span class=cF0>(&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="l599"></a> read_cmd.command = </span><span class=cF3>ATAPI_READ</span><span class=cF0> >> </span><span class=cFE>8</span><span class=cF0>; </span><span class=cF2>//FIX</span><span class=cF0>
|
|
<a name="l600"></a> read_cmd.lba = </span><span class=cF5>EndianU32</span><span class=cF0>(blk);
|
|
<a name="l601"></a> read_cmd.count = </span><span class=cF5>EndianU32</span><span class=cF0>(count);
|
|
<a name="l602"></a> </span><span class=cF5>MemCopy</span><span class=cF0>(&cmd_table->acmd, &read_cmd, </span><span class=cFE>16</span><span class=cF0>);
|
|
<a name="l603"></a>
|
|
<a name="l604"></a> cmd_fis->count = count; </span><span class=cF2>//Necessary?</span><span class=cF0>
|
|
<a name="l605"></a>
|
|
<a name="l606"></a> </span><span class=cFD>AHCIPortWait</span><span class=cF0>(bd->port_num, </span><span class=cF5>tS</span><span class=cF0> + </span><span class=cFE>2</span><span class=cF0>);
|
|
<a name="l607"></a>
|
|
<a name="l608"></a> </span><span class=cF5>Bts</span><span class=cF0>(&port->cmd_issue, cmd_slot);
|
|
<a name="l609"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>Sleep(1000);</span><span class=cF0>
|
|
<a name="l610"></a> </span><span class=cFD>AHCIPortCmdWait</span><span class=cF0>(bd->port_num, cmd_slot);
|
|
<a name="l611"></a>
|
|
<a name="l612"></a> </span><span class=cF1>if</span><span class=cF0> (bd->flags & </span><span class=cF3>BDF_INTERNAL_BUF</span><span class=cF0>)
|
|
<a name="l613"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l614"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>"Writing back internal buffer\n";</span><span class=cF0>
|
|
<a name="l615"></a> </span><span class=cF5>MemCopy</span><span class=cF0>(buf, internal_buf, buf_size);
|
|
<a name="l616"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l617"></a>
|
|
<a name="l618"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF1>lock</span><span class=cF0> && unlock)
|
|
<a name="l619"></a> </span><span class=cF5>BlkDevUnlock</span><span class=cF0>(bd);
|
|
<a name="l620"></a>
|
|
<a name="l621"></a> </span><span class=cF1>return</span><span class=cF0> cmd_header->prd_byte_count;
|
|
<a name="l622"></a>}
|
|
<a name="l623"></a>
|
|
<a name="l624"></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="l625"></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="l626"></a> </span><span class=cF9>CPortCmdHeader</span><span class=cF0> *cmd_header;
|
|
<a name="l627"></a> </span><span class=cF9>I64</span><span class=cF0> i;
|
|
<a name="l628"></a>
|
|
<a name="l629"></a> bd->ahci_port = port;
|
|
<a name="l630"></a> bd->port_num = port_num;
|
|
<a name="l631"></a>
|
|
<a name="l632"></a> </span><span class=cF5>AHCIPortReset</span><span class=cF0>(port_num);
|
|
<a name="l633"></a> </span><span class=cFD>AHCIPortCmdStart</span><span class=cF0>(port_num);
|
|
<a name="l634"></a>
|
|
<a name="l635"></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="l636"></a> port->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="l637"></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="l638"></a> </span><span class=cFD>AHCIPortCmdStop</span><span class=cF0>(port_num);
|
|
<a name="l639"></a>
|
|
<a name="l640"></a> </span><span class=cF2>//'1K-byte' align as per SATA spec.</span><span class=cF0>
|
|
<a name="l641"></a> port->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>->code_heap);
|
|
<a name="l642"></a> port->cmd_list_base_upper = </span><span class=cFE>0</span><span class=cF0>;
|
|
<a name="l643"></a>
|
|
<a name="l644"></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="l645"></a> port->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>->code_heap);
|
|
<a name="l646"></a> port->fis_base_upper = </span><span class=cFE>0</span><span class=cF0>;
|
|
<a name="l647"></a>
|
|
<a name="l648"></a> </span><span class=cF1>for</span><span class=cF0> (i = </span><span class=cFE>0</span><span class=cF0>; i < </span><span class=cFB>blkdev</span><span class=cF0>.cmd_slot_count; i++)
|
|
<a name="l649"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l650"></a> cmd_header = &port->cmd_list_base(</span><span class=cF9>CPortCmdHeader</span><span class=cF0> *)[i];
|
|
<a name="l651"></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="l652"></a> cmd_header->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="l653"></a>
|
|
<a name="l654"></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="l655"></a> cmd_header->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>->code_heap);
|
|
<a name="l656"></a> cmd_header->cmd_table_base_upper = </span><span class=cFE>0</span><span class=cF0>;
|
|
<a name="l657"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l658"></a> </span><span class=cFD>AHCIPortCmdStart</span><span class=cF0>(port_num);
|
|
<a name="l659"></a> </span><span class=cFD>AHCIPortIdentify</span><span class=cF0>(bd);
|
|
<a name="l660"></a>}
|
|
<a name="l661"></a>
|
|
<a name="l662"></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="l663"></a>{
|
|
<a name="l664"></a> </span><span class=cF1>Bool</span><span class=cF0> unlock, okay = </span><span class=cF3>FALSE</span><span class=cF0>;
|
|
<a name="l665"></a> </span><span class=cF9>CPortCmdHeader</span><span class=cF0> *cmd_header;
|
|
<a name="l666"></a> </span><span class=cF9>I64</span><span class=cF0> i;
|
|
<a name="l667"></a>
|
|
<a name="l668"></a> </span><span class=cF1>if</span><span class=cF0> (!bd->ahci_port)
|
|
<a name="l669"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>FALSE</span><span class=cF0>;
|
|
<a name="l670"></a>
|
|
<a name="l671"></a> unlock = </span><span class=cF5>BlkDevLock</span><span class=cF0>(bd);
|
|
<a name="l672"></a>
|
|
<a name="l673"></a> </span><span class=cF2>// if we re-init a port, keep memory from leaking.</span><span class=cF0>
|
|
<a name="l674"></a> </span><span class=cF1>for</span><span class=cF0> (i = </span><span class=cFE>0</span><span class=cF0>; i < </span><span class=cFB>blkdev</span><span class=cF0>.cmd_slot_count; i++)
|
|
<a name="l675"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l676"></a> cmd_header = &bd->ahci_port->cmd_list_base(</span><span class=cF9>CPortCmdHeader</span><span class=cF0> *)[i];
|
|
<a name="l677"></a> </span><span class=cF5>Free</span><span class=cF0>(cmd_header->cmd_table_base);
|
|
<a name="l678"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l679"></a> </span><span class=cF5>Free</span><span class=cF0>(bd->ahci_port->cmd_list_base);
|
|
<a name="l680"></a> </span><span class=cF5>Free</span><span class=cF0>(bd->ahci_port->fis_base);
|
|
<a name="l681"></a>
|
|
<a name="l682"></a> </span><span class=cF2>// try to init the port, catch if fails.</span><span class=cF0>
|
|
<a name="l683"></a> </span><span class=cF1>try</span><span class=cF0>
|
|
<a name="l684"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l685"></a> </span><span class=cF5>AHCIPortInit</span><span class=cF0>(bd, bd->ahci_port, bd->port_num);
|
|
<a name="l686"></a>
|
|
<a name="l687"></a> </span><span class=cF1>if</span><span class=cF0> (bd->type == </span><span class=cF3>BDT_ATAPI</span><span class=cF0>)
|
|
<a name="l688"></a> okay = </span><span class=cF5>AHCIAtapiStartStop</span><span class=cF0>(bd, </span><span class=cF3>TRUE</span><span class=cF0>);
|
|
<a name="l689"></a> </span><span class=cF1>else</span><span class=cF0>
|
|
<a name="l690"></a> okay = </span><span class=cF3>TRUE</span><span class=cF0>;
|
|
<a name="l691"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l692"></a> </span><span class=cF1>catch</span><span class=cF0>
|
|
<a name="l693"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l694"></a> </span><span class=cF5>Fs</span><span class=cF0>->catch_except = </span><span class=cF3>TRUE</span><span class=cF0>;
|
|
<a name="l695"></a> okay = </span><span class=cF3>FALSE</span><span class=cF0>;
|
|
<a name="l696"></a> </span><span class=cF3>ST_WARN_ST</span><span class=cF0> </span><span class=cF6>"AHCIAtaInit"</span><span class=cF0>;
|
|
<a name="l697"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l698"></a>
|
|
<a name="l699"></a> </span><span class=cF1>if</span><span class=cF0> (unlock)
|
|
<a name="l700"></a> </span><span class=cF5>BlkDevUnlock</span><span class=cF0>(bd);
|
|
<a name="l701"></a>
|
|
<a name="l702"></a> </span><span class=cF1>return</span><span class=cF0> okay;
|
|
<a name="l703"></a>}
|
|
<a name="l704"></a>
|
|
<a name="l705"></a></span><span class=cF1>U0</span><span class=cF0> </span><span class=cF5>AHCIHbaReset</span><span class=cF0>()
|
|
<a name="l706"></a>{
|
|
<a name="l707"></a> </span><span class=cF5>Bts</span><span class=cF0>(&</span><span class=cFB>blkdev</span><span class=cF0>.ahci_hba->ghc, </span><span class=cF3>AHCI_GHCf_HBA_RESET</span><span class=cF0>);
|
|
<a name="l708"></a> </span><span class=cF1>while</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&</span><span class=cFB>blkdev</span><span class=cF0>.ahci_hba->ghc, </span><span class=cF3>AHCI_GHCf_HBA_RESET</span><span class=cF7>)</span><span class=cF0>);
|
|
<a name="l709"></a> </span><span class=cF5>Bts</span><span class=cF0>(&</span><span class=cFB>blkdev</span><span class=cF0>.ahci_hba->ghc, </span><span class=cF3>AHCI_GHCf_AHCI_ENABLE</span><span class=cF0>);
|
|
<a name="l710"></a>}
|
|
<a name="l711"></a>
|
|
<a name="l712"></a></span><span class=cF1>U0</span><span class=cF0> </span><span class=cFD>AHCIInit</span><span class=cF0>()
|
|
<a name="l713"></a>{
|
|
<a name="l714"></a> </span><span class=cF9>CAHCIHba</span><span class=cF0> *hba;
|
|
<a name="l715"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port;
|
|
<a name="l716"></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> << </span><span class=cFE>16</span><span class=cF0> | </span><span class=cF3>PCISC_AHCI</span><span class=cF0> << </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="l717"></a>
|
|
<a name="l718"></a> </span><span class=cF6>"\n"</span><span class=cF0>;
|
|
<a name="l719"></a>
|
|
<a name="l720"></a> </span><span class=cF1>if</span><span class=cF0> (bdf == -</span><span class=cFE>1</span><span class=cF0>)
|
|
<a name="l721"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l722"></a> </span><span class=cF6>"AHCI: No AHCI controller found.\n"</span><span class=cF0>;
|
|
<a name="l723"></a> </span><span class=cF1>return</span><span class=cF0>;
|
|
<a name="l724"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l725"></a>
|
|
<a name="l726"></a> </span><span class=cF6>"AHCI: Controller found\n"</span><span class=cF0>;
|
|
<a name="l727"></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>) & ~</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="l728"></a> </span><span class=cFB>blkdev</span><span class=cF0>.ahci_hba = hba;
|
|
<a name="l729"></a>
|
|
<a name="l730"></a>
|
|
<a name="l731"></a> </span><span class=cF5>Bts</span><span class=cF0>(&</span><span class=cFB>blkdev</span><span class=cF0>.ahci_hba->ghc, </span><span class=cF3>AHCI_GHCf_AHCI_ENABLE</span><span class=cF0>);
|
|
<a name="l732"></a> </span><span class=cF6>"AHCI: GHC.AE\n"</span><span class=cF0>;
|
|
<a name="l733"></a>
|
|
<a name="l734"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>AHCIHbaReset;</span><span class=cF0>
|
|
<a name="l735"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>"AHCI: HBA Reset\n";</span><span class=cF0>
|
|
<a name="l736"></a>
|
|
<a name="l737"></a>
|
|
<a name="l738"></a> </span><span class=cF2>//Transferring ownership from BIOS if supported.</span><span class=cF0>
|
|
<a name="l739"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&hba->caps_ext, </span><span class=cF3>AHCI_CAPSEXTf_BOH</span><span class=cF7>)</span><span class=cF0>)
|
|
<a name="l740"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l741"></a> </span><span class=cF5>Bts</span><span class=cF0>(&hba->bohc, </span><span class=cF3>AHCI_BOHCf_OOS</span><span class=cF0>);
|
|
<a name="l742"></a> </span><span class=cF6>"AHCI: Transferring ownership from BIOS\n"</span><span class=cF0>;
|
|
<a name="l743"></a>
|
|
<a name="l744"></a> </span><span class=cF1>while</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&hba->bohc, </span><span class=cF3>AHCI_BOHCf_BOS</span><span class=cF7>)</span><span class=cF0>);
|
|
<a name="l745"></a>
|
|
<a name="l746"></a> </span><span class=cF5>Sleep</span><span class=cF0>(</span><span class=cFE>25</span><span class=cF0>);
|
|
<a name="l747"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&hba->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="l748"></a> </span><span class=cF5>Sleep</span><span class=cF0>(</span><span class=cFE>2000</span><span class=cF0>);
|
|
<a name="l749"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l750"></a>
|
|
<a name="l751"></a> </span><span class=cFB>blkdev</span><span class=cF0>.cmd_slot_count = (hba->caps & </span><span class=cFE>0x1F00</span><span class=cF0>) >> </span><span class=cFE>8</span><span class=cF0>;
|
|
<a name="l752"></a> </span><span class=cF6>"AHCI: Command slot count: %d\n"</span><span class=cF0>, </span><span class=cFB>blkdev</span><span class=cF0>.cmd_slot_count;
|
|
<a name="l753"></a>
|
|
<a name="l754"></a> </span><span class=cF1>for</span><span class=cF0> (i = </span><span class=cFE>0</span><span class=cF0>; i < </span><span class=cF3>AHCI_MAX_PORTS</span><span class=cF0>; i++)
|
|
<a name="l755"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l756"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&hba->ports_implemented, i</span><span class=cF7>)</span><span class=cF0>)
|
|
<a name="l757"></a> {</span><span class=cF2>//Make ports idle?</span><span class=cF0>
|
|
<a name="l758"></a> port = &hba->ports[i];
|
|
<a name="l759"></a> </span><span class=cF6>"AHCI: Port %2d signature 0x%08X "</span><span class=cF0>, i, port->signature;
|
|
<a name="l760"></a> </span><span class=cF1>if</span><span class=cF0> (port->signature == </span><span class=cF3>AHCI_PxSIG_ATA</span><span class=cF0> || port->signature == </span><span class=cF3>AHCI_PxSIG_ATAPI</span><span class=cF0>)
|
|
<a name="l761"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l762"></a> </span><span class=cF1>if</span><span class=cF0> (port->signature == </span><span class=cF3>AHCI_PxSIG_ATAPI</span><span class=cF0>)
|
|
<a name="l763"></a> {
|
|
<a name="l764"></a> </span><span class=cF5>Bts</span><span class=cF0>(&port->command, </span><span class=cF3>AHCI_PxCMDf_ATAPI</span><span class=cF0>);
|
|
<a name="l765"></a> </span><span class=cF6>"ATAPI drive\n"</span><span class=cF0>;
|
|
<a name="l766"></a> }
|
|
<a name="l767"></a> </span><span class=cF1>else</span><span class=cF0> </span><span class=cF1>if</span><span class=cF0> (port->signature == </span><span class=cF3>AHCI_PxSIG_ATA</span><span class=cF0>)
|
|
<a name="l768"></a> </span><span class=cF6>"ATA drive\n"</span><span class=cF0>;
|
|
<a name="l769"></a>
|
|
<a name="l770"></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="l771"></a> {
|
|
<a name="l772"></a> </span><span class=cF6>"AHCI: Port not idle\n"</span><span class=cF0>;
|
|
<a name="l773"></a> </span><span class=cFD>AHCIPortCmdStop</span><span class=cF0>(i);
|
|
<a name="l774"></a> }
|
|
<a name="l775"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l776"></a> </span><span class=cF1>else</span><span class=cF0>
|
|
<a name="l777"></a> </span><span class=cF6>"Unknown\n"</span><span class=cF0>;
|
|
<a name="l778"></a> }
|
|
<a name="l779"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l780"></a> </span><span class=cF6>"\n"</span><span class=cF0>;
|
|
<a name="l781"></a>}
|
|
<a name="l782"></a>
|
|
<a name="l783"></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="l784"></a>{
|
|
<a name="l785"></a> </span><span class=cF9>I64</span><span class=cF0> i;
|
|
<a name="l786"></a> </span><span class=cF9>CAHCIPort</span><span class=cF0> *port;
|
|
<a name="l787"></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="l788"></a> </span><span class=cF9>CKernel</span><span class=cF0> *kernel;
|
|
<a name="l789"></a>
|
|
<a name="l790"></a> </span><span class=cF1>for</span><span class=cF0> (i = </span><span class=cFE>0</span><span class=cF0>; i < </span><span class=cF3>AHCI_MAX_PORTS</span><span class=cF0>; i++)
|
|
<a name="l791"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l792"></a> </span><span class=cF1>if</span><span class=cF0> (</span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&</span><span class=cFB>blkdev</span><span class=cF0>.ahci_hba->ports_implemented, i</span><span class=cF7>)</span><span class=cF0>)
|
|
<a name="l793"></a> {
|
|
<a name="l794"></a> port = &</span><span class=cFB>blkdev</span><span class=cF0>.ahci_hba->ports[i];
|
|
<a name="l795"></a> </span><span class=cF6>"AHCI: BootDVDProbeAll: Saw port at %2d with signature 0x%0X\n"</span><span class=cF0>, i, port->signature;
|
|
<a name="l796"></a>
|
|
<a name="l797"></a> </span><span class=cF1>if</span><span class=cF0> (port->signature == </span><span class=cF3>AHCI_PxSIG_ATAPI</span><span class=cF0>)
|
|
<a name="l798"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l799"></a> </span><span class=cF6>"AHCI: Probing ATAPI drive at port %d\n"</span><span class=cF0>, i;
|
|
<a name="l800"></a>
|
|
<a name="l801"></a> </span><span class=cF5>AHCIPortInit</span><span class=cF0>(bd, port, i);
|
|
<a name="l802"></a>
|
|
<a name="l803"></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="l804"></a>
|
|
<a name="l805"></a> kernel = buf + </span><span class=cFB>sys_boot_src</span><span class=cF0>.u16[</span><span class=cFE>1</span><span class=cF0>] << </span><span class=cF3>BLK_SIZE_BITS</span><span class=cF0>;
|
|
<a name="l806"></a>
|
|
<a name="l807"></a> </span><span class=cF1>if</span><span class=cF0> (kernel->compile_time == </span><span class=cFB>sys_compile_time</span><span class=cF0>)
|
|
<a name="l808"></a> {
|
|
<a name="l809"></a> </span><span class=cF6>"AHCI: Found sys_compile_time at BLK %d on Port %d\n"</span><span class=cF0>, </span><span class=cFB>sys_boot_blk</span><span class=cF0>, i;
|
|
<a name="l810"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>TRUE</span><span class=cF0>;
|
|
<a name="l811"></a> }
|
|
<a name="l812"></a> </span><span class=cF1>else</span><span class=cF0>
|
|
<a name="l813"></a> </span><span class=cF6>"AHCI: Did not find matching sys_compile_time on Port %d\n"</span><span class=cF0>, i;
|
|
<a name="l814"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l815"></a> }
|
|
<a name="l816"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l817"></a>
|
|
<a name="l818"></a> </span><span class=cF5>Panic</span><span class=cF0>(</span><span class=cF6>"Could not find ATAPI boot drive"</span><span class=cF0>);
|
|
<a name="l819"></a>
|
|
<a name="l820"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>FALSE</span><span class=cF0>;
|
|
<a name="l821"></a>}
|
|
<a name="l822"></a>
|
|
<a name="l823"></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="l824"></a>{
|
|
<a name="l825"></a> </span><span class=cF9>CBlkDev</span><span class=cF0> *bd = drive->bd;
|
|
<a name="l826"></a> </span><span class=cF9>I64</span><span class=cF0> spc = bd->blk_size >> </span><span class=cF3>BLK_SIZE_BITS</span><span class=cF0>, n, blk2,
|
|
<a name="l827"></a> l2 = bd->max_reads << </span><span class=cFE>1</span><span class=cF0> + spc << </span><span class=cFE>1</span><span class=cF0>;
|
|
<a name="l828"></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 << BLK_SIZE_BITS);</span><span class=cF0>
|
|
<a name="l829"></a>
|
|
<a name="l830"></a> </span><span class=cF1>if</span><span class=cF0> (bd->type == </span><span class=cF3>BDT_ATAPI</span><span class=cF0>)
|
|
<a name="l831"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l832"></a> dvd_buf = </span><span class=cF5>MAlloc</span><span class=cF0>(l2 << </span><span class=cF3>BLK_SIZE_BITS</span><span class=cF0>);
|
|
<a name="l833"></a>
|
|
<a name="l834"></a> </span><span class=cF1>if</span><span class=cF0> (blk <= bd->max_reads)
|
|
<a name="l835"></a> blk2 = </span><span class=cFE>0</span><span class=cF0>;
|
|
<a name="l836"></a> </span><span class=cF1>else</span><span class=cF0>
|
|
<a name="l837"></a> blk2 = </span><span class=cF5>FloorU64</span><span class=cF0>(blk - bd->max_reads, spc);
|
|
<a name="l838"></a>
|
|
<a name="l839"></a> </span><span class=cF1>if</span><span class=cF0> (blk2 + l2 > drive->size + drive->drv_offset)
|
|
<a name="l840"></a> l2 = drive->size + drive->drv_offset - blk2;
|
|
<a name="l841"></a>
|
|
<a name="l842"></a> n = (l2 + spc - </span><span class=cFE>1</span><span class=cF0>) / spc;
|
|
<a name="l843"></a>
|
|
<a name="l844"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>"AHCIAtapiBlksRead(bd, dvd_buf, %d, %d);", blk2 / spc, n;</span><span class=cF0>
|
|
<a name="l845"></a> </span><span class=cF5>AHCIAtapiBlksRead</span><span class=cF0>(bd, dvd_buf, blk2 / spc, n);
|
|
<a name="l846"></a>
|
|
<a name="l847"></a> </span><span class=cF1>if</span><span class=cF0> (bd->flags & </span><span class=cF3>BDF_READ_CACHE</span><span class=cF0>)
|
|
<a name="l848"></a> </span><span class=cFD>DiskCacheAdd</span><span class=cF0>(drive, dvd_buf, blk2, n * spc);
|
|
<a name="l849"></a>
|
|
<a name="l850"></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> << </span><span class=cF3>BLK_SIZE_BITS</span><span class=cF0>, count << </span><span class=cF3>BLK_SIZE_BITS</span><span class=cF0>);
|
|
<a name="l851"></a> </span><span class=cF5>Free</span><span class=cF0>(dvd_buf);
|
|
<a name="l852"></a>
|
|
<a name="l853"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l854"></a> </span><span class=cF1>else</span><span class=cF0>
|
|
<a name="l855"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>FALSE</span><span class=cF0>;
|
|
<a name="l856"></a>
|
|
<a name="l857"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>TRUE</span><span class=cF0>;
|
|
<a name="l858"></a>}
|
|
<a name="l859"></a>
|
|
<a name="l860"></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="l861"></a>{
|
|
<a name="l862"></a> </span><span class=cF9>CBlkDev</span><span class=cF0> *bd = drive->bd;
|
|
<a name="l863"></a>
|
|
<a name="l864"></a> </span><span class=cF1>if</span><span class=cF0> (bd->type == </span><span class=cF3>BDT_ATA</span><span class=cF0>)
|
|
<a name="l865"></a> </span><span class=cF5>AHCIAtaBlksRead</span><span class=cF0>(bd, buf, blk, count);
|
|
<a name="l866"></a> </span><span class=cF1>else</span><span class=cF0>
|
|
<a name="l867"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>FALSE</span><span class=cF0>;
|
|
<a name="l868"></a>
|
|
<a name="l869"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>TRUE</span><span class=cF0>;
|
|
<a name="l870"></a>}
|
|
<a name="l871"></a>
|
|
<a name="l872"></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="l873"></a>{
|
|
<a name="l874"></a> </span><span class=cF9>CBlkDev</span><span class=cF0> *bd = drive->bd;
|
|
<a name="l875"></a>
|
|
<a name="l876"></a> </span><span class=cF5>AHCIAtaBlksWrite</span><span class=cF0>(bd, buf, blk, count);
|
|
<a name="l877"></a>
|
|
<a name="l878"></a> </span><span class=cFB>blkdev</span><span class=cF0>.write_count += count;
|
|
<a name="l879"></a>
|
|
<a name="l880"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF3>TRUE</span><span class=cF0>;
|
|
<a name="l881"></a>}
|
|
<a name="l882"></a>
|
|
<a name="l883"></a></span><span class=cF2>/*</span><span class=cF0>
|
|
<a name="l884"></a></span><span class=cF2>AHCIInit;</span><span class=cF0>
|
|
<a name="l885"></a>
|
|
<a name="l886"></a></span><span class=cF2>#define BLKS 65537</span><span class=cF0>
|
|
<a name="l887"></a>
|
|
<a name="l888"></a></span><span class=cF2>U0 rw()</span><span class=cF0>
|
|
<a name="l889"></a></span><span class=cF2>{</span><span class=cF0>
|
|
<a name="l890"></a> </span><span class=cF2>U8 *buf = MAlloc(BLKS * BLK_SIZE);</span><span class=cF0>
|
|
<a name="l891"></a> </span><span class=cF2>U8 *buf2 = MAlloc(BLKS * DVD_BLK_SIZE);</span><span class=cF0>
|
|
<a name="l892"></a> </span><span class=cF2>U8 *buf3 = CAlloc(BLKS * DVD_BLK_SIZE);</span><span class=cF0>
|
|
<a name="l893"></a>
|
|
<a name="l894"></a> </span><span class=cF2>MemSet(buf, 0xFF, BLKS * BLK_SIZE);</span><span class=cF0>
|
|
<a name="l895"></a>
|
|
<a name="l896"></a> </span><span class=cF2>CBlkDev *bd = CAlloc(sizeof(CBlkDev));</span><span class=cF0>
|
|
<a name="l897"></a> </span><span class=cF2>CBlkDev *bd2 = CAlloc(sizeof(CBlkDev));</span><span class=cF0>
|
|
<a name="l898"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>AHCIPortInit(bd, &blkdev.ahci_hba->ports[0], 0);</span><span class=cF0>
|
|
<a name="l899"></a> </span><span class=cF2>AHCIPortInit(bd2, &blkdev.ahci_hba->ports[1], 1);</span><span class=cF0>
|
|
<a name="l900"></a>
|
|
<a name="l901"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>"$PURPLE$Byte count: %X$FG$\n", AHCIAtaBlksWrite(bd, buf, 0, BLKS); //write</span><span class=cF0>
|
|
<a name="l902"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>"$PURPLE$Byte count: %X$FG$\n", AHCIAtaBlksRead(bd, buf2, 0, BLKS);//read</span><span class=cF0>
|
|
<a name="l903"></a>
|
|
<a name="l904"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>"$PURPLE$Byte count: %X$FG$\n", AHCIAtapiBlksRead(bd2, buf3, 0, BLKS);//read</span><span class=cF0>
|
|
<a name="l905"></a>
|
|
<a name="l906"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>D(buf2 + (BLKS - 5) * BLK_SIZE, 5 * BLK_SIZE);</span><span class=cF0>
|
|
<a name="l907"></a>
|
|
<a name="l908"></a> </span><span class=cF2>"Capacity: %d\n", AHCIAtapiCapacityGet(bd2);</span><span class=cF0>
|
|
<a name="l909"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>D(buf3 + DVD_BLK_SIZE * (BLKS - 5), 5 * DVD_BLK_SIZE);</span><span class=cF0>
|
|
<a name="l910"></a> </span><span class=cF2>Free(buf);</span><span class=cF0>
|
|
<a name="l911"></a> </span><span class=cF2>Free(buf2);</span><span class=cF0>
|
|
<a name="l912"></a> </span><span class=cF2>Free(buf3);</span><span class=cF0>
|
|
<a name="l913"></a> </span><span class=cF2>Free(bd);</span><span class=cF0>
|
|
<a name="l914"></a> </span><span class=cF2>Free(bd2);</span><span class=cF0>
|
|
<a name="l915"></a></span><span class=cF2>}</span><span class=cF0>
|
|
<a name="l916"></a>
|
|
<a name="l917"></a></span><span class=cF2>rw;</span><span class=cF0>
|
|
<a name="l918"></a></span><span class=cF2>*/</span></pre></body>
|
|
</html>
|