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