Example #1
0
void VirtioBlk::irq_handler() {

  debug2("<VirtioBlk> IRQ handler\n");

  //Virtio Std. § 4.1.5.5, steps 1-3

  // Step 1. read ISR
  unsigned char isr = hw::inp(iobase() + VIRTIO_PCI_ISR);

  // Step 2. A) - one of the queues have changed
  if (isr & 1) {
    // This now means service RX & TX interchangeably
    service_RX();
  }

  // Step 2. B)
  if (isr & 2) {
    debug("\t <VirtioBlk> Configuration change:\n");

    // Getting the MAC + status
    //debug("\t             Old status: 0x%x\n", config.status);
    get_config();
    //debug("\t             New status: 0x%x \n", config.status);
  }

}
Example #2
0
VirtioBlk::VirtioBlk(hw::PCI_Device& d)
  : Virtio(d), hw::Drive(), req(queue_size(0), 0, iobase()), inflight(0)
{
  INFO("VirtioBlk", "Driver initializing");
  {
    auto& reqs = Statman::get().create(
      Stat::UINT32, blkname() + ".requests");
    this->requests = &reqs.get_uint32();
    *this->requests = 0;

    auto& err = Statman::get().create(
      Stat::UINT32, blkname() + ".errors");
    this->errors = &err.get_uint32();
    *this->errors = 0;
  }

  uint32_t needed_features =
    FEAT(VIRTIO_BLK_F_BLK_SIZE);
  negotiate_features(needed_features);

  CHECK(features() & FEAT(VIRTIO_BLK_F_BARRIER),
        "Barrier is enabled");
  CHECK(features() & FEAT(VIRTIO_BLK_F_SIZE_MAX),
        "Size-max is known");
  CHECK(features() & FEAT(VIRTIO_BLK_F_SEG_MAX),
        "Seg-max is known");
  CHECK(features() & FEAT(VIRTIO_BLK_F_GEOMETRY),
        "Geometry structure is used");
  CHECK(features() & FEAT(VIRTIO_BLK_F_RO),
        "Device is read-only");
  CHECK(features() & FEAT(VIRTIO_BLK_F_BLK_SIZE),
        "Block-size is known");
  CHECK(features() & FEAT(VIRTIO_BLK_F_SCSI),
        "SCSI is enabled :(");
  CHECK(features() & FEAT(VIRTIO_BLK_F_FLUSH),
        "Flush enabled");

  CHECK ((features() & needed_features) == needed_features,
         "Negotiated needed features");

  // Step 1 - Initialize REQ queue
  auto success = assign_queue(0, (uint32_t) req.queue_desc());
  CHECK(success, "Request queue assigned (0x%x) to device",
        (uint32_t) req.queue_desc());

  // Step 3 - Fill receive queue with buffers
  // DEBUG: Disable
  INFO("VirtioBlk", "Queue size: %i\tRequest size: %u\n",
       req.size(), sizeof(request_t));

  // Get device configuration
  get_config();

  // Signal setup complete.
  setup_complete((features() & needed_features) == needed_features);
  CHECK((features() & needed_features) == needed_features, "Signalled driver OK");

  // Hook up IRQ handler (inherited from Virtio)
  if (is_msix())
  {
    // update IRQ subscriptions
    IRQ_manager::get().subscribe(irq() + 0, {this, &VirtioBlk::service_RX});
    IRQ_manager::get().subscribe(irq() + 1, {this, &VirtioBlk::msix_conf_handler});
  }
  else
  {
    auto del(delegate<void()>{this, &VirtioBlk::irq_handler});
    IRQ_manager::get().subscribe(irq(), del);
  }

  // Done
  INFO("VirtioBlk", "Block device with %llu sectors capacity", config.capacity);
}
Example #3
0
bool Virtio::assign_queue(uint16_t index, uint32_t queue_desc){
  hw::outpw(iobase() + VIRTIO_PCI_QUEUE_SEL, index);
  hw::outpd(iobase() + VIRTIO_PCI_QUEUE_PFN, OS::page_nr_from_addr(queue_desc));
  return hw::inpd(iobase() + VIRTIO_PCI_QUEUE_PFN) == OS::page_nr_from_addr(queue_desc);
}
Example #4
0
uint32_t Virtio::queue_size(uint16_t index){
  hw::outpw(iobase() + VIRTIO_PCI_QUEUE_SEL, index);
  return hw::inpw(iobase() + VIRTIO_PCI_QUEUE_SIZE);
}