Esempio n. 1
0
void insw(int port, short *ptr, int len)
{
	unsigned short *io_ptr = (unsigned short *)(_IO_BASE+port);
	_insw(io_ptr, ptr, len);
}
Esempio n. 2
0
/**
 * Initialize disk device driver. Reserves memory for data structures
 * and register driver to the interrupt handler.
 *
 * @param desc Pointer to the PCI IO device descriptor of the controller
 *
 * @return Pointer to the device structure of the controller
 */
int disk_init(io_descriptor_t *desc)
{
  /* Cast it */
  pci_conf_t *pci = (pci_conf_t*)(uint64_t*) desc;

  /* Set bases to default values */
  uint16_t iobase1 = IDE_PRIMARY_CMD_BASE;
  uint16_t iobase2 = IDE_SECONDARY_CMD_BASE;
  uint16_t ctrlbase1 = IDE_PRIMARY_CTRL_BASE;
  uint16_t ctrlbase2 = IDE_SECONDARY_CTRL_BASE;
  uint16_t busmaster = pci->bar4;
  uint32_t i, j, count = 0;
  uint16_t buf[256];

  /* Check for compatability mode */
  if(pci->prog_if & 0x1)
    {
      /* Native mode for channel 1 */
      iobase1 = (uint16_t)pci->bar0;
      ctrlbase1 = (uint16_t)pci->bar1;

      /* Check if they can be relocated */
      if(iobase1 & 0x1)
        iobase1--;

      if(ctrlbase1 & 0x1)
        ctrlbase1--;
    }

  if(pci->prog_if & 0x4)
    {
      /* Native mode for channel 2 */
      iobase2 = (uint16_t)pci->bar2;
      ctrlbase2 = (uint16_t)pci->bar3;

      /* Check if they can be relocated */
      if(iobase2 & 0x1)
        iobase2--;

      if(ctrlbase2 & 0x1)
        ctrlbase2--;
    }

  /* Setup Channels */
  ide_channels[IDE_PRIMARY].busm = busmaster;
  ide_channels[IDE_PRIMARY].base = iobase1;
  ide_channels[IDE_PRIMARY].ctrl = ctrlbase1;
  ide_channels[IDE_PRIMARY].irq = IDE_PRIMARY_IRQ;
  ide_channels[IDE_PRIMARY].irq_wait = 0;
  ide_channels[IDE_PRIMARY].dma_phys = 0;
  ide_channels[IDE_PRIMARY].dma_virt = 0;
  ide_channels[IDE_PRIMARY].dma_buf_phys = 0;
  ide_channels[IDE_PRIMARY].dma_buf_virt = 0;

  ide_channels[IDE_SECONDARY].busm = busmaster;
  ide_channels[IDE_SECONDARY].base = iobase2;
  ide_channels[IDE_SECONDARY].ctrl = ctrlbase2;
  ide_channels[IDE_SECONDARY].irq = IDE_SECONDARY_IRQ;
  ide_channels[IDE_SECONDARY].irq_wait = 0;
  ide_channels[IDE_SECONDARY].dma_phys = 0;
  ide_channels[IDE_SECONDARY].dma_virt = 0;
  ide_channels[IDE_SECONDARY].dma_buf_phys = 0;
  ide_channels[IDE_SECONDARY].dma_buf_virt = 0;

  /* Install interrupts */
  interrupt_register(IDE_PRIMARY_IRQ, (int_handler_t)ide_irq_handler0, 0);
  interrupt_register(IDE_SECONDARY_IRQ, (int_handler_t)ide_irq_handler1, 0);

  /* Disable Irqs, we use polling mode */
  ide_write(IDE_PRIMARY, IDE_REGISTER_CTRL, 2);
  ide_write(IDE_SECONDARY, IDE_REGISTER_CTRL, 2);

  /* Enumerate devices */
  /* We send an IDE_IDENTIFY command to each device, on
   * each channel, and see if it responds */
  for(i = 0; i < IDE_CHANNELS_PER_CTRL; i++)
    {
      for(j = 0; j < IDE_DEVICES_PER_CHANNEL; j++)
        {
          /* Variables */
          uint8_t error = 0, type = 0, status = 0;
          uint32_t lba28 = 0;
          uint64_t lba48 = 0;
          ide_devices[count].present = 0;                       //assume no drive

          /* Step 1. Select drive */
          ide_write(i, IDE_REGISTER_HDDSEL, 0xA0 | (j << 4));
          ide_delay(i);

          /* Step 2. Send IDE_IDENTIFY */
          ide_write(i, IDE_REGISTER_SECCOUNT0, 0);
          ide_write(i, IDE_REGISTER_LBA0, 0);
          ide_write(i, IDE_REGISTER_LBA1, 0);
          ide_write(i, IDE_REGISTER_LBA2, 0);
          ide_write(i, IDE_REGISTER_LBA2, 0);
          ide_write(i, IDE_REGISTER_COMMAND, IDE_COMMAND_IDENTIFY);
          ide_delay(i);

          /* Step 3. Poll */
          status = _inb(ide_channels[i].base + IDE_REGISTER_STATUS);
          if(status == 0 || status == 0x7F || status == 0xFF)
            {
              count++;
              continue;
            }

          /* Wuhuu! device is here */
          while(1)
            {
              status = _inb(ide_channels[i].base + IDE_REGISTER_STATUS);

              if(status & 0x1)
                {
                  error = 1;
                  break;
                }

              if(!(status & IDE_ATA_BUSY) && (status & IDE_ATA_DRQ))
                {
                  break;
                }
            }

          /* Step 4. Probe for ATAPI */
          if(error != 0)
            {
              /* Get type */
              uint8_t cl = _inb(ide_channels[i].base + IDE_REGISTER_LBA1);
              uint8_t ch = _inb(ide_channels[i].base + IDE_REGISTER_LBA2);

              if(cl == 0x14 && ch == 0xEB)              /* PATAPI */
                type = 1;
              else if(cl == 0x69 && ch == 0x96) /* SATAPI */
                type = 1;
              else
                {
                  /* Unknown Type */
                  count++;
                  continue;
                }

              /* Identify */
              ide_write(i, IDE_REGISTER_COMMAND, IDE_COMMAND_PACKET);
              ide_delay(i);
            }

          /* Step 5. Read identification space */
          _insw(ide_channels[i].base + IDE_REGISTER_DATA, 256, (uint8_t*)buf);

          /* Step 6. Read device parameters */
          ide_devices[count].present = 1;
          ide_devices[count].type = type;
          ide_devices[count].channel = i;
          ide_devices[count].drive = j;
          ide_devices[count].signature = (*(uint16_t*)(buf));
          ide_devices[count].capabilities = (*(uint16_t*)(buf + 49));
          ide_devices[count].commandset = (*(uint32_t*)(buf + 82));

          /* Step 7. Get geometry */
          lba28 = (*(uint32_t*)(buf + 60));
          lba48 = (*(uint64_t*)(buf + 100));

          if(lba48)
            {
              ide_devices[count].totalsectors = lba48;
              ide_devices[count].cylinders = (*(uint16_t*)(buf + 1));
              ide_devices[count].headspercylinder = (*(uint16_t*)(buf + 3));
              ide_devices[count].secsperhead = (*(uint64_t*)(buf + 6));
              ide_devices[count].flags |= 0x1;
            }
          else if(lba28 && !lba48)
            {
              ide_devices[count].totalsectors = lba28;
              ide_devices[count].cylinders = (*(uint16_t*)(buf + 1));
              ide_devices[count].headspercylinder = (*(uint16_t*)(buf + 3));
              ide_devices[count].secsperhead = (*(uint64_t*)(buf + 6));
            }
          else
            {
              ide_devices[count].totalsectors = 0;
              ide_devices[count].cylinders = 0;
              ide_devices[count].headspercylinder = 0;
              ide_devices[count].secsperhead = 0;
            }

          /* Register filesystem */
          ide_dev[count].real_device = &(ide_channels[0]);
          ide_dev[count].type = TYPECODE_DISK;
          ide_dev[count].generic_device = &ide_gbd[count];
          ide_dev[count].io_address = count;

          /* Setup ide device */
          ide_gbd[count].device = &ide_dev[count];
          ide_gbd[count].write_block  = ide_write_block;
          ide_gbd[count].read_block   = ide_read_block;
          ide_gbd[count].block_size     = ide_get_sectorsize;
          ide_gbd[count].total_blocks = ide_get_sectorcount;

          device_register(&ide_dev[count]);

          /* Increase count */
          count++;
        }
    }


  return 0;
}