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 "AtaDisk.h"
22 #include "modules/drivers/common/scsi/ScsiController.h"
23 #include "pedigree/kernel/Log.h"
24 #include "pedigree/kernel/machine/Device.h"
25 #include "pedigree/kernel/machine/IrqManager.h"
26 #include "pedigree/kernel/machine/Machine.h"
27 #include "pedigree/kernel/processor/IoBase.h"
28 #include "pedigree/kernel/time/Time.h"
29 #include "pedigree/kernel/utilities/Vector.h"
30 #include "pedigree/kernel/utilities/new"
31 
32 class Controller;
33 class IrqHandler;
34 
35 IsaAtaController::IsaAtaController(Controller *pDev, int nController)
36  : AtaController(pDev, nController)
37 {
38  setSpecificType(String("ata-controller"));
39 
40  // Initialise our ports.
41  bool bPortsFound = false;
42  for (unsigned int i = 0; i < m_Addresses.count(); i++)
43  {
44  if (m_Addresses[i]->m_Name == "command" ||
45  m_Addresses[i]->m_Name == "bar0")
46  {
47  m_pCommandRegs = m_Addresses[i]->m_Io;
48  bPortsFound = true;
49  }
50  if (m_Addresses[i]->m_Name == "control" ||
51  m_Addresses[i]->m_Name == "bar1")
52  {
53  m_pControlRegs = m_Addresses[i]->m_Io;
54  bPortsFound = true;
55  }
56  }
57 
58  if (!bPortsFound)
59  {
60  ERROR("ISA ATA: No addresses found for this controller");
61  return;
62  }
63 
64  // Look for a floating bus
65  if (m_pControlRegs->read8(6) == 0xFF || m_pCommandRegs->read8(7) == 0xFF)
66  {
67  // No devices on this controller
68  return;
69  }
70 
71  m_Children.clear();
72 
73  // Set up the RequestQueue
74  initialise();
75 
76  // Perform a software reset.
77  m_pControlRegs->write8(0x04, 6); // Assert SRST
78  Time::delay(5 * Time::Multiplier::Millisecond);
79 
80  m_pControlRegs->write8(0, 6); // Negate SRST
81  Time::delay(5 * Time::Multiplier::Millisecond);
82 
83  // Poll until BSY is clear. Until BSY is clear, no other bits in the
84  // alternate status register are considered valid.
85  uint8_t status = 0;
86  while (1) // ((status&0xC0) != 0) && ((status&0x9) == 0) )
87  {
88  status = m_pControlRegs->read8(6);
89  if (status & 0x80)
90  continue;
91  else if (status & 0x1)
92  {
93  NOTICE("Error during ATA software reset, status = " << status);
94  return;
95  }
96  else
97  break;
98  }
99 
100  // Create two disks - master and slave.
101  AtaDisk *pMaster = new AtaDisk(this, true, m_pCommandRegs, m_pControlRegs);
102  AtaDisk *pSlave = new AtaDisk(this, false, m_pCommandRegs, m_pControlRegs);
103 
104  pMaster->setInterruptNumber(getInterruptNumber());
105  pSlave->setInterruptNumber(getInterruptNumber());
106 
107  size_t masterN = getNumChildren();
108  addChild(pMaster);
109  size_t slaveN = getNumChildren();
110  addChild(pSlave);
111 
112  // Try and initialise the disks.
113  bool masterInitialised = pMaster->initialise(masterN);
114  bool slaveInitialised = pSlave->initialise(slaveN);
115 
116  Machine::instance().getIrqManager()->registerIsaIrqHandler(
117  getInterruptNumber(), static_cast<IrqHandler *>(this));
118 
119  if (!masterInitialised)
120  {
121  removeChild(pMaster);
122  delete pMaster;
123  }
124 
125  if (!slaveInitialised)
126  {
127  removeChild(pSlave);
128  delete pSlave;
129  }
130 }
131 
132 IsaAtaController::~IsaAtaController()
133 {
134 }
135 
136 bool IsaAtaController::sendCommand(
137  size_t nUnit, uintptr_t pCommand, uint8_t nCommandSize,
138  uintptr_t pRespBuffer, uint16_t nRespBytes, bool bWrite)
139 {
140  Device *pChild = getChild(nUnit);
141  if (!pChild)
142  {
143  ERROR("ISA ATA: sendCommand called with a bad unit number.");
144  return false;
145  }
146 
147  AtaDisk *pDisk = static_cast<AtaDisk *>(pChild);
148  return pDisk->sendCommand(
149  nUnit, pCommand, nCommandSize, pRespBuffer, nRespBytes, bWrite);
150 }
151 
153  uint64_t p1, uint64_t p2, uint64_t p3, uint64_t p4, uint64_t p5,
154  uint64_t p6, uint64_t p7, uint64_t p8)
155 {
156  AtaDisk *pDisk = reinterpret_cast<AtaDisk *>(p2);
157  if (p1 == SCSI_REQUEST_READ)
158  return pDisk->doRead(p3);
159  else if (p1 == SCSI_REQUEST_WRITE)
160  return pDisk->doWrite(p3);
161  else
162  return 0;
163 }
164 
165 bool IsaAtaController::irq(irq_id_t number, InterruptState &state)
166 {
167  for (unsigned int i = 0; i < getNumChildren(); i++)
168  {
169  AtaDisk *pDisk = static_cast<AtaDisk *>(getChild(i));
170  pDisk->irqReceived();
171  }
172 
173  return true;
174 }
bool initialise(size_t nUnit=~0)
Definition: AtaDisk.cc:60
virtual void setInterruptNumber(uintptr_t n)
Definition: Device.h:268
virtual uint64_t doWrite(uint64_t location)
Definition: AtaDisk.cc:943
Definition: String.h:49
virtual bool irq(irq_id_t number, InterruptState &state)
virtual uint64_t doRead(uint64_t location)
Definition: AtaDisk.cc:681
Definition: Device.h:43
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)
bool initialise() INITIALISATION_ONLY
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
virtual void irqReceived()
Definition: AtaDisk.cc:1156
virtual irq_id_t registerIsaIrqHandler(uint8_t irq, IrqHandler *handler, bool bEdge=false)=0
#define ERROR(text)
Definition: Log.h:82