The Pedigree Project 0.1
IsaAtaController.cc
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include "IsaAtaController.h"
21#include "pedigree/kernel/Log.h"
22#include "pedigree/kernel/machine/Device.h"
23#include "pedigree/kernel/machine/IrqManager.h"
24#include "pedigree/kernel/machine/Machine.h"
25#include "pedigree/kernel/processor/IoBase.h"
26#include "pedigree/kernel/time/Time.h"
27#include "pedigree/kernel/utilities/Vector.h"
28#include "pedigree/kernel/utilities/new"
29
30#include "AtaDisk.h"
31#include "modules/drivers/common/scsi/ScsiController.h"
32
33class Controller;
34
35IsaAtaController::IsaAtaController(Controller* pDev, int nController)
36 : AtaController(pDev, nController), m_IrqId(0) {
37 setSpecificType(String("ata-controller"));
38
39 // Initialise our ports.
40 bool bPortsFound = false;
41 for (unsigned int i = 0; i < m_Addresses.count(); i++) {
42 if (m_Addresses[i]->m_Name.compare("command") || m_Addresses[i]->m_Name.compare("bar0")) {
43 m_pCommandRegs = m_Addresses[i]->m_Io;
44 bPortsFound = true;
45 }
46 if (m_Addresses[i]->m_Name.compare("control") || m_Addresses[i]->m_Name.compare("bar1")) {
47 m_pControlRegs = m_Addresses[i]->m_Io;
48 bPortsFound = true;
49 }
50 }
51
52 if (!bPortsFound) {
53 ERROR("ISA ATA: No addresses found for this controller");
54 return;
55 }
56
57 // Look for a floating bus
58 if (m_pControlRegs->read8(6) == 0xFF || m_pCommandRegs->read8(7) == 0xFF) {
59 // No devices on this controller
60 return;
61 }
62
64
65 // Set up the RequestQueue
66 initialise();
67
68 // Perform a software reset.
69 m_pControlRegs->write8(0x04, 6); // Assert SRST
70 Time::delay(5 * Time::Multiplier::Millisecond);
71
72 m_pControlRegs->write8(0, 6); // Negate SRST
73 Time::delay(5 * Time::Multiplier::Millisecond);
74
75 // Use the shared bounded wait after reset. A controller which keeps BSY
76 // asserted must leave this channel offline instead of hanging discovery.
77 const AtaStatus status = ataWait(m_pCommandRegs, m_pControlRegs);
78 if (status.reg.err || status.reg.bsy) {
79 NOTICE("Error during ATA software reset, status = " << status.__reg_contents);
80 return;
81 }
82
83 // Create two disks - master and slave.
84 AtaDisk* pMaster = new AtaDisk(this, true, m_pCommandRegs, m_pControlRegs);
85 AtaDisk* pSlave = new AtaDisk(this, false, m_pCommandRegs, m_pControlRegs);
86
89
90 size_t masterN = getNumChildren();
91 addChild(pMaster);
92 size_t slaveN = getNumChildren();
93 addChild(pSlave);
94
95 // Try and initialise the disks.
96 bool masterInitialised = pMaster->initialise(masterN);
97 bool slaveInitialised = pSlave->initialise(slaveN);
98
99 m_IrqId = Machine::instance().getIrqManager()->registerIsaIrqHandler(
100 getInterruptNumber(), static_cast<IrqHandler*>(this), IrqPolicy::edgeThreaded());
101
102 if (!masterInitialised) {
103 removeChild(pMaster);
104 delete pMaster;
105 }
106
107 if (!slaveInitialised) {
108 removeChild(pSlave);
109 delete pSlave;
110 }
111}
112
113IsaAtaController::~IsaAtaController() {
114 shutdown();
115}
116
118 if (!beginShutdown()) {
119 return;
120 }
121
125
126 if (m_IrqId && !Machine::instance().getIrqManager()->unregisterHandler(
127 m_IrqId, static_cast<IrqHandler*>(this))) {
128 FATAL("ISA ATA controller could not drain its IRQ handler");
129 }
130 m_IrqId = 0;
131
132 stopDiskDma();
133}
134
135bool IsaAtaController::sendCommand(size_t nUnit, uintptr_t pCommand, uint8_t nCommandSize,
136 uintptr_t pRespBuffer, uint16_t nRespBytes, bool bWrite) {
137 Device* pChild = getChild(nUnit);
138 if (!pChild) {
139 ERROR("ISA ATA: sendCommand called with a bad unit number.");
140 return false;
141 }
142
143 AtaDisk* pDisk = static_cast<AtaDisk*>(pChild);
144 return pDisk->sendCommand(nUnit, pCommand, nCommandSize, pRespBuffer, nRespBytes, bWrite);
145}
146
147uint64_t IsaAtaController::executeRequest(uint64_t p1, uint64_t p2, uint64_t p3, uint64_t p4,
148 uint64_t p5, uint64_t p6, uint64_t p7, uint64_t p8) {
149 AtaDisk* pDisk = reinterpret_cast<AtaDisk*>(p2);
150 if (p1 == SCSI_REQUEST_READ)
151 return pDisk->doRead(p3);
152 else if (p1 == SCSI_REQUEST_WRITE)
153 return pDisk->doWrite(p3);
154 else if (p1 == SCSI_REQUEST_WRITE_DIRECT)
155 return pDisk->doWriteDirect(p3, static_cast<uintptr_t>(p4));
156 else if (p1 == SCSI_REQUEST_SYNC)
157 return pDisk->doSync(p3);
158 else
159 return 0;
160}
161
163 for (unsigned int i = 0; i < getNumChildren(); i++) {
164 AtaDisk* pDisk = static_cast<AtaDisk*>(getChild(i));
165 pDisk->irqReceived();
166 }
167
168 return IrqDisposition::Handled;
169}
void maskDiskInterrupts()
virtual MUST_USE_RESULT uint64_t doWriteDirect(uint64_t location, uintptr_t page)
Definition AtaDisk.cc:1124
virtual uint64_t doWrite(uint64_t location)
Definition AtaDisk.cc:1089
bool initialise(size_t nUnit=~0)
Definition AtaDisk.cc:258
virtual uint64_t doRead(uint64_t location)
Definition AtaDisk.cc:844
virtual void irqReceived()
Definition AtaDisk.cc:1361
size_t getNumChildren()
Definition Device.cc:143
Device * getChild(size_t n)
Definition Device.cc:139
virtual void setInterruptNumber(uintptr_t n)
Definition Device.h:276
void addChild(Device *pDevice)
Definition Device.cc:135
virtual void setSpecificType(String str)
Definition Device.h:187
Vector< Address * > m_Addresses
Definition Device.h:349
Vector< Device * > m_Children
Definition Device.h:351
virtual uintptr_t getInterruptNumber()
Definition Device.h:271
void removeChild(size_t n)
Definition Device.cc:147
virtual irq_id_t registerIsaIrqHandler(uint8_t irq, IrqHandler *handler, const IrqPolicy &policy)=0
virtual void shutdown()
virtual IrqDisposition irq(irq_id_t number)
virtual uint64_t executeRequest(uint64_t p1, uint64_t p2, uint64_t p3, uint64_t p4, uint64_t p5, uint64_t p6, uint64_t p7, uint64_t p8)
virtual void destroy()
void shutdownDiskCaches(bool deviceAvailable=true)
IrqDisposition
Definition IrqHandler.h:31
void clear(bool freeMem=false)
Definition Vector.h:378