The Pedigree Project 0.1
PciAtaController.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 "PciAtaController.h"
21#include "pedigree/kernel/Log.h"
22#include "pedigree/kernel/machine/Controller.h"
23#include "pedigree/kernel/machine/Device.h"
24#include "pedigree/kernel/machine/IrqManager.h"
25#include "pedigree/kernel/machine/Machine.h"
26#include "pedigree/kernel/machine/Pci.h"
27#include "pedigree/kernel/process/CpuAffinity.h"
28#include "pedigree/kernel/process/PerProcessorScheduler.h"
29#include "pedigree/kernel/process/Scheduler.h"
30#include "pedigree/kernel/processor/IoBase.h"
31#include "pedigree/kernel/processor/IoPort.h"
32#include "pedigree/kernel/processor/Processor.h"
33#include "pedigree/kernel/time/Time.h"
34#include "pedigree/kernel/utilities/Vector.h"
35#include "pedigree/kernel/utilities/utility.h"
36
37#include "AtaDisk.h"
38#include "BusMasterIde.h"
39#include "ata-common.h"
40#include "modules/drivers/common/scsi/ScsiController.h"
41
43 : AtaController(pDev, nController, false),
44 m_pCommandRegs(nullptr),
45 m_pControlRegs(nullptr),
46 m_PciControllerType(UnknownController),
47 m_IrqIds(),
48 m_IrqCount(0),
49 m_nController(nController) {
50 // Base construction must finish before the queue selects our placement.
51 initialise();
52 setSpecificType(String("ata-controller"));
53
54 // Determine controller type
56 switch (getPciDeviceId()) {
57 case 0x1230:
58 m_PciControllerType = PIIX;
59 str = "PIIX";
60 break;
61 case 0x7010:
62 m_PciControllerType = PIIX3;
63 str = "PIIX3";
64 break;
65 case 0x7111:
66 m_PciControllerType = PIIX4;
67 str = "PIIX4";
68 break;
69 case 0x2411:
70 m_PciControllerType = ICH;
71 str = "ICH";
72 break;
73 case 0x2421:
74 m_PciControllerType = ICH0;
75 str = "ICH0";
76 break;
77 case 0x244A:
78 case 0x244B:
79 m_PciControllerType = ICH2;
80 str = "ICH2";
81 break;
82 case 0x248A:
83 case 0x248B:
84 m_PciControllerType = ICH3;
85 str = "ICH3";
86 break;
87 case 0x24CA:
88 case 0x24CB:
89 m_PciControllerType = ICH4;
90 str = "ICH4";
91 break;
92 case 0x24DB:
93 m_PciControllerType = ICH5;
94 str = "ICH5";
95 break;
96 default:
97 m_PciControllerType = UnknownController;
98 str = "<unknown>";
99 break;
100 }
101 str += " PCI IDE controller found";
102 NOTICE(static_cast<const char*>(str));
103
104 if (m_PciControllerType == UnknownController)
105 return;
106
107 // Find BAR4 (BusMaster registers)
108 Device::Address* bar4 = 0;
109 for (size_t i = 0; i < addresses().count(); i++) {
110 if (!StringCompare(static_cast<const char*>(addresses()[i]->m_Name), "bar4"))
111 bar4 = addresses()[i];
112 }
113
115
116 // Read the BusMaster interface base address register and tell it where we
117 // would like to talk to it (BAR4).
118 if (bar4) {
119 uint32_t busMasterIfaceAddr = PciBus::instance().readConfigSpace(pDev, 8);
120 busMasterIfaceAddr &= 0xFFFF000F;
121 busMasterIfaceAddr |= bar4->m_Address & 0xFFF0;
122 NOTICE(" - Bus master interface base register at " << bar4->m_Address);
123 PciBus::instance().writeConfigSpace(pDev, 8, busMasterIfaceAddr);
124
125 // Read the command register and then enable I/O space. We do this so
126 // that we can still access drives using PIO. We also enable the
127 // BusMaster function on the controller.
128 uint32_t commandReg = PciBus::instance().readConfigSpace(pDev, 1);
129 commandReg = (commandReg & ~(0x7)) | 0x7;
130 PciBus::instance().writeConfigSpace(pDev, 1, commandReg);
131
132 // Fiddle with the IDE timing registers
133 // TIME0, TIME1, IE0, IE1, PPE0, PPE1, DTE0, DTE1, minimum recovery
134 // time, minimum IORDY sample point, IDE decode enable.
135 uint32_t ideTiming = 0xB3FF;
136 // Apply to both channels.
137 ideTiming |= (ideTiming << 16);
138 PciBus::instance().writeConfigSpace(pDev, 0x10, ideTiming);
139
140 // Write the interrupt line into the PCI space if needed.
141 // This is only meaningful for < PIIX3...
142 if (m_PciControllerType == PIIX) {
143 uint32_t miscFields = PciBus::instance().readConfigSpace(pDev, 0xF);
144 if ((miscFields & 0xF) != getInterruptNumber()) {
145 if (getInterruptNumber()) {
146 miscFields &= ~0xF;
147 miscFields |= getInterruptNumber() & 0xF;
148 }
149 }
150 PciBus::instance().writeConfigSpace(pDev, 0xF, miscFields);
151 }
152
153 // PIIX4+ has Ultra DMA configuration.
155 if (m_PciControllerType == PIIX4) {
156 // UDMACTL register - enable UDMA mode for all drives.
157 uint32_t udmactl = PciBus::instance().readConfigSpace(pDev, 0x12);
158 udmactl |= 0xF;
159 PciBus::instance().writeConfigSpace(pDev, 0x12, udmactl);
160
161 // Set timings for UDMA2 (Ultra DMA 33, max supported by PIIX4).
162 uint32_t timings = PciBus::instance().readConfigSpace(pDev, 0x13);
163 uint16_t target_timings = 0x2 * 0x3333;
164 timings = (timings & 0xFFFF) | target_timings;
165 PciBus::instance().writeConfigSpace(pDev, 0x13, timings);
166 }
167 }
168
169 // The controller must be able to perform BusMaster IDE DMA transfers, or
170 // else we have to fall back to PIO transfers.
171 bool bDma = false;
172 if (bar4 && (pDev->getPciProgInterface() & 0x80)) {
173 NOTICE(" - This is a DMA capable controller");
174 bDma = true;
175 }
176
177#if !KERNEL_PROCESSOR_NO_PORT_IO
178 IoPort* masterCommand = new IoPort("pci-ide-master-cmd");
179 IoPort* slaveCommand = new IoPort("pci-ide-slave-cmd");
180 IoPort* masterControl = new IoPort("pci-ide-master-ctl");
181 IoPort* slaveControl = new IoPort("pci-ide-slave-ctl");
182
184 IoPort* bar4_a = 0;
185 IoPort* bar4_b = 0;
186 BusMasterIde* primaryBusMaster = 0;
187 BusMasterIde* secondaryBusMaster = 0;
188 if (bDma) {
189 uintptr_t addr = bar4->m_Address;
190
191 // Okay, now delete the BAR's IoBase. We're not going to use it again,
192 // and we need the ports.
193 delete bar4->m_Io;
194 bar4->m_Io = 0;
195
196 bar4_a = new IoPort("pci-ide-busmaster-primary");
197 if (!bar4_a->allocate(addr, 8)) {
198 ERROR("Couldn't allocate primary BusMaster ports");
199 delete bar4_a;
200 bar4_a = 0;
201 }
202
203 bar4_b = new IoPort("pci-ide-busmaster-secondary");
204 if (!bar4_b->allocate(addr + 8, 8)) {
205 ERROR("Couldn't allocate secondary BusMaster ports");
206 delete bar4_b;
207 bar4_b = 0;
208 }
209
210 // Create the BusMasterIde objects
211 if (bar4_a) {
212 primaryBusMaster = new BusMasterIde;
213 if (!primaryBusMaster->initialise(bar4_a)) {
214 ERROR("Couldn't initialise primary BusMaster IDE interface");
215 delete primaryBusMaster;
216 delete bar4_a;
217
218 primaryBusMaster = 0;
219 }
220 }
221 if (bar4_b) {
222 secondaryBusMaster = new BusMasterIde;
223 if (!secondaryBusMaster->initialise(bar4_b)) {
224 ERROR("Couldn't initialise secondary BusMaster IDE interface");
225 delete secondaryBusMaster;
226 delete bar4_b;
227
228 secondaryBusMaster = 0;
229 }
230 }
231 }
232
233 // By default, this is the port layout we can expect for the system
235 if (!masterCommand->allocate(0x1F0, 8))
236 ERROR("Couldn't allocate master command ports");
237 if (!masterControl->allocate(0x3F4, 4))
238 ERROR("Couldn't allocate master control ports");
239 if (!slaveCommand->allocate(0x170, 8))
240 ERROR("Couldn't allocate slave command ports");
241 if (!slaveControl->allocate(0x374, 4))
242 ERROR("Couldn't allocate slave control ports");
243
244 // Check for non-existent controllers.
245 AtaStatus masterStatus = ataWait(masterCommand, masterControl);
246 AtaStatus slaveStatus = ataWait(slaveCommand, slaveControl);
247 if (masterStatus.__reg_contents == 0xff) {
248 delete masterCommand;
249 delete masterControl;
250 masterCommand = 0;
251 masterControl = 0;
252 }
253 if (slaveStatus.__reg_contents == 0xff) {
254 delete slaveCommand;
255 delete slaveControl;
256 slaveCommand = 0;
257 slaveControl = 0;
258 }
259
260 // Kick off an SRST on each control port.
261 if (masterControl) {
262 masterControl->write8(0x6, 2);
263 Processor::pause(); // Hold SRST for 5 nanoseconds. /// \todo Better
264 // way of doing this?
265 masterControl->write8(0x2, 2);
266 }
267 if (slaveControl) {
268 slaveControl->write8(0x6, 2);
270 slaveControl->write8(0x2, 2);
271 }
272
273 Time::delay(2 * Time::Multiplier::Millisecond); // Wait 2 ms after clearing.
274
275 if (masterCommand)
276 ataWait(masterCommand, masterControl);
277 if (slaveCommand)
278 ataWait(slaveCommand, slaveControl);
279
280 // Install our IRQ handler
281 if (getInterruptNumber() != 0xFF) {
282 irq_id_t irqId = Machine::instance().getIrqManager()->registerPciIrqHandler(
283 static_cast<IrqHandler*>(this), this, IrqPolicy::pciIntxThreaded());
284 if (irqId) {
285 m_IrqIds[m_IrqCount++] = irqId;
286 }
287 }
288
290 size_t primaryIrq = 14, secondaryIrq = 15;
291 if (primaryIrq != getInterruptNumber()) {
292 irq_id_t irqId = Machine::instance().getIrqManager()->registerIsaIrqHandler(
293 primaryIrq, static_cast<IrqHandler*>(this), IrqPolicy::edgeThreaded());
294 if (irqId) {
295 m_IrqIds[m_IrqCount++] = irqId;
296 }
297 }
298 if (secondaryIrq != getInterruptNumber()) {
299 irq_id_t irqId = Machine::instance().getIrqManager()->registerIsaIrqHandler(
300 secondaryIrq, static_cast<IrqHandler*>(this), IrqPolicy::edgeThreaded());
301 if (irqId) {
302 m_IrqIds[m_IrqCount++] = irqId;
303 }
304 }
305
306 // And finally, create disks
307 if (masterControl) {
308 diskHelper(true, masterCommand, masterControl, primaryBusMaster, primaryIrq);
309 diskHelper(false, masterCommand, masterControl, primaryBusMaster, primaryIrq);
310 }
311
312 if (slaveControl) {
313 diskHelper(true, slaveCommand, slaveControl, secondaryBusMaster, secondaryIrq);
314 diskHelper(false, slaveCommand, slaveControl, secondaryBusMaster, secondaryIrq);
315 }
316#else
317 ERROR("PCI ATA: no good, this machine has no port I/O");
318#endif
319}
320
321PciAtaController::~PciAtaController() {
322 shutdown();
323}
324
326 if (!beginShutdown()) {
327 return;
328 }
329
333
334 IrqManager* irqManager = Machine::instance().getIrqManager();
335 for (size_t i = 0; i < m_IrqCount; ++i) {
336 if (!irqManager->unregisterHandler(m_IrqIds[i], static_cast<IrqHandler*>(this))) {
337 FATAL("PCI ATA controller could not drain an IRQ handler");
338 }
339 m_IrqIds[i] = 0;
340 }
341 m_IrqCount = 0;
342
343 stopDiskDma();
344}
345
346void PciAtaController::diskHelper(bool master, IoBase* cmd, IoBase* ctl, BusMasterIde* dma,
347 size_t irq) {
348 AtaDisk* pDisk = new AtaDisk(this, master, cmd, ctl, dma);
349 pDisk->setInterruptNumber(irq);
350
351 // Allow the initialisation to use sendCommand.
352 size_t n = getNumChildren();
353 addChild(pDisk);
354
355 if (!pDisk->initialise(n)) {
356 removeChild(pDisk);
357 delete pDisk;
358 }
359}
360
361bool PciAtaController::sendCommand(size_t nUnit, uintptr_t pCommand, uint8_t nCommandSize,
362 uintptr_t pRespBuffer, uint16_t nRespBytes, bool bWrite) {
363 Device* pChild = getChild(nUnit);
364 if (!pChild) {
365 ERROR("PCI ATA: sendCommand called with a bad unit number.");
366 return false;
367 }
368
369 AtaDisk* pDisk = static_cast<AtaDisk*>(pChild);
370 return pDisk->sendCommand(nUnit, pCommand, nCommandSize, pRespBuffer, nRespBytes, bWrite);
371}
372
373bool PciAtaController::workerPlacement(ThreadPlacement& placement) const {
374 // IDE completion depends on BSP-routed IRQs. Set placement before a request
375 // can suspend a kernel continuation on another CPU.
376 placement = {};
377 placement.allowed.set(Scheduler::instance().getBootstrapProcessorScheduler()->logicalCpu());
378 return true;
379}
380
381uint64_t PciAtaController::executeRequest(uint64_t p1, uint64_t p2, uint64_t p3, uint64_t p4,
382 uint64_t p5, uint64_t p6, uint64_t p7, uint64_t p8) {
383 AtaDisk* pDisk = reinterpret_cast<AtaDisk*>(p2);
384 if (p1 == SCSI_REQUEST_PAGING) {
385 auto* request = reinterpret_cast<PagingRequest*>(p3);
386 request->result = pDisk->doPagingTransfer(request->operation, request->offset, request->page);
387 return request->result == PagingStatus::Success;
388 }
389 if (p1 == SCSI_REQUEST_READ)
390 return pDisk->doRead(p3);
391 else if (p1 == SCSI_REQUEST_WRITE)
392 return pDisk->doWrite(p3);
393 else if (p1 == SCSI_REQUEST_WRITE_DIRECT)
394 return pDisk->doWriteDirect(p3, static_cast<uintptr_t>(p4));
395 else if (p1 == SCSI_REQUEST_SYNC)
396 return pDisk->doSync(p3);
397 else
398 return 0;
399}
400
402 for (unsigned int i = 0; i < getNumChildren(); i++) {
403 AtaDisk* pDisk = static_cast<AtaDisk*>(getChild(i));
404 if (pDisk->getInterruptNumber() != number)
405 continue;
406
407 BusMasterIde* pBusMaster = pDisk->getBusMaster();
408 if (pBusMaster) {
409 // No active DMA transfer - clear interrupt/error bits.
410 pBusMaster->completeIdleTransaction();
411 }
412 pDisk->irqReceived();
413 }
414 return IrqDisposition::Handled;
415}
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
virtual BusMasterIde * getBusMaster() const
Definition AtaDisk.h:126
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
bool completeIdleTransaction()
bool initialise(IoBase *pBase)
Initialises DMA for a specific channel.
IoBase * m_Io
Definition Device.h:115
uintptr_t m_Address
Definition Device.h:107
uint16_t getPciDeviceId()
Definition Device.h:228
size_t getNumChildren()
Definition Device.cc:143
Device * getChild(size_t n)
Definition Device.cc:139
virtual Vector< Address * > & addresses()
Definition Device.h:266
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
uint8_t getPciProgInterface()
Definition Device.h:232
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
Abstrace base class for hardware I/O capabilities.
Definition IoBase.h:32
I/O port range.
Definition IoPort.h:33
bool allocate(io_port_t ioPort, size_t size)
Definition IoPort.cc:29
virtual void write8(uint8_t value, size_t offset=0)
virtual irq_id_t registerIsaIrqHandler(uint8_t irq, IrqHandler *handler, const IrqPolicy &policy)=0
virtual bool unregisterHandler(irq_id_t Id, IrqHandlerBase *handler)=0
virtual irq_id_t registerPciIrqHandler(IrqHandler *handler, Device *pDevice, const IrqPolicy &policy)=0
PciAtaController(Controller *pDev, int nController=0)
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 shutdown()
virtual IrqDisposition irq(irq_id_t number)
uint32_t readConfigSpace(Device *pDev, uint8_t offset)
void writeConfigSpace(Device *pDev, uint8_t offset, uint32_t data)
static void pause()
virtual void destroy()
virtual void initialise()
static Scheduler & instance()
Definition Scheduler.h:96
void shutdownDiskCaches(bool deviceAvailable=true)
IrqDisposition
Definition IrqHandler.h:31
void clear(bool freeMem=false)
Definition Vector.h:378
Definition cmd.h:30
uint8_t __reg_contents
"Hidden" integer which contains the actual register contents
Definition ata-common.h:46