Example #1
0
File: ide.c Project: YMChenLiye/os
//硬盘读入sec_cnt个扇区的数据到buf
static void read_from_sector(struct disk* hd,void* buf,uint8_t sec_cnt){
	uint32_t size_in_byte;
	if(sec_cnt == 0){
		//因为sec_cnt是8为变量,由主调函数将其赋值时,若为256则会将最高位的1丢掉变为0
		size_in_byte = 256 * 512;
	}else{
		size_in_byte = sec_cnt * 512;
	}
	insw(reg_data(hd->my_channel),buf,size_in_byte / 2);
}
Example #2
0
// RAMのaddrからsizeバイトdstに読み込み。
void
ne_getblock(ne_t* ne, ushort addr, int size, void* dst)
{
  ne_rdma_setup(ne, CR_DM_RR, addr, size);
  if (ne->is16bit)
    insw(ne->base + NE_DATA, dst, size);
  else
    insb(ne->base + NE_DATA, dst, size);
  return;
}
static void q40ide_input_data(ide_drive_t *drive, struct request *rq,
			      void *buf, unsigned int len)
{
	unsigned long data_addr = drive->hwif->io_ports.data_addr;

	if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS)
		return insw(data_addr, buf, (len + 1) / 2);

	insw_swapw(data_addr, buf, (len + 1) / 2);
}
//-------------------------------------------------------------------------------------------------------------------------------
//
//  读取硬盘分区信息函数
//
//-------------------------------------------------------------------------------------------------------------------------------
int ReadPartition(void)
{
	int i = 0;
	int sector, head, cylinder;
	unsigned char buffer[512];
	struct partition* p;

#ifndef HD_BOOT_SECTOR
#define HD_BOOT_SECTOR 0
#endif

  ConsolePrintf("Check the hard disk partition\n");

	sector = HD_BOOT_SECTOR &0xff;
	cylinder = (HD_BOOT_SECTOR &0xffff00)>>8;
	head = (HD_BOOT_SECTOR &0xf000000)>>24;
  
	while(inb(HD_STATUS) & 0x80);
	io_wait();
	outb(0,HD_CMD);
	outb(1,0x1f2);                   ///////////读写的扇区数.这个端口应该是:0X1F2,下面开始增加一
	outb(HD_BOOT_SECTOR,0x1f3);      ////////开始扇区
	outb(cylinder,0x1f4);            ///////开始柱面
	outb(cylinder>>8,0x1f5);         ///////开始柱面高位
	outb(0xE0|(0 <<4)|head,0x1f6);   /////主磁盘
	outb(0x20,0x1F7);                ////read命令
  while(inb(HD_STATUS) & 0x80);
	insw(0x1F0, buffer, 256);

	if (buffer[510] != (unsigned char) 0x55 || buffer[511] != (unsigned char) 0xAA){
		ConsolePrintFault();
		ConsoleWarning("  read_partition(): Can't Read Harddisk(IDE) partition data\n");
		return -1;
	}
  
	ConsolePrintOK();
	for (i=1;i<5;i++)
	{

	   p = (struct partition*)&buffer[0x1be + (i-1)*0x10]; //partition table offset after 446 byte.
		 hd[i].start_sect = p->start_sec;  	                 // 从0算起的绝对扇区(分区表的起始扇区,不是FAT表的)
		 hd[i].start_head=p->start_head;
		 hd[i].start_cyl=p->start_cyl;
		 hd[i].nr_sects = p->size;                           // 分区扇区总数 
		 hd[i].flag = p->type;
		 hd[i].lowsec = p->lowsec;
		 hd[i].type = GetPartitionName( p->type);
	   hd[i].name = 0x42+i;
	   FindActivePartition(p, i);
	}

	ReadIDEInfo();

	return 0;
}
Example #5
0
static int ad7606_par16_read_block(struct device *dev,
				 int count, void *buf)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
	struct ad7606_state *st = iio_priv(indio_dev);

	insw((unsigned long) st->base_address, buf, count);

	return 0;
}
Example #6
0
static inline void hfa384x_insw_debug(struct net_device *dev, int a,
				      u8 *buf, int wc)
{
	struct hostap_interface *iface = dev->priv;
	local_info_t *local = iface->local;
	unsigned long flags;

	spin_lock_irqsave(&local->lock, flags);
	prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INSW, a, wc);
	insw(dev->base_addr + a, buf, wc);
	spin_unlock_irqrestore(&local->lock, flags);
}
Example #7
0
/*
**  Name:	void pio_getblock(dpeth_t *dep, u16_t offset,
**  				int size, void *dst)
**  Function:	Reads a block of packet from board (Prog. I/O).
*/
static void pio_getblock(dpeth_t *dep, u16_t offset, int size, void *dst)
{

  /* Sets up board for reading */
  ns_rw_setup(dep, CR_DM_RR, size, offset);

#if PIO16 == 0
  insb(dep->de_data_port, SELF, dst, size);
#else
  if (dep->de_16bit == TRUE) {
	insw(dep->de_data_port, dst, size);
  } else {
	insb(dep->de_data_port, dst, size);
  }
#endif
  return;
}
//-------------------------------------------------------------------------------------------------------------------------------
//
//  硬盘读写处理函数
//
//-------------------------------------------------------------------------------------------------------------------------------
void HardDiskRW(int RW, unsigned long sectors, void* buffer)
{
  unsigned __eflag;
	int sector, head, cylinder;

  save_eflags(&__eflag);

	sector   = sectors &0xff;
	cylinder = (sectors &0xffff00)>>8;
	head     = (sectors &0xf000000)>>24;

	while(inb(HD_STATUS) & 0x80);
	io_wait();
	outb(0,HD_CMD);

	outb(1,0x1f2);                 ///////////读写的扇区数.这个端口应该是:0X1F2,下面开始增加一
	outb(sector,0x1f3);            ////////开始扇区
	outb(cylinder,0x1f4);          ///////开始柱面
	outb(cylinder>>8,0x1f5);       ///////开始柱面高位
	outb(0xE0|(0 <<4)|head,0x1f6); /////主磁盘

	if (RW == READ)
	{                              ////read命令
	    outb(0x20,0x1F7);         
        while(inb(HD_STATUS) & 0x80);
	    insw(0x1F0, buffer, 256);
	}
	else if (RW == WRITE)
	{                             ////write命令

	if (inb(HD_STATUS & 0x01)) {
		ConsoleWarning("  issue write_command command error !\n");
		return;
	}

		 outb(0x30,0x1F7);   
	   while((inb(HD_STATUS) & 0x08) == 0);       //DRQ
	     outsw(0x1F0, buffer, 256);
     }
	else {
		ConsoleWarning("  Panic:bad command:you only can read or write on harddisk!");
	}
	restore_eflags(__eflag);
	return;
}
Example #9
0
static void read_intr(void)
{
	struct request *req;
	int i, retries = 100000;

	do {
		i = (unsigned) inb_p(HD_STATUS);
		if (i & BUSY_STAT)
			continue;
		if (!OK_STATUS(i))
			break;
		if (i & DRQ_STAT)
			goto ok_to_read;
	} while (--retries > 0);
	dump_status("read_intr", i);
	bad_rw_intr();
	hd_request();
	return;
ok_to_read:
	req = CURRENT;
	insw(HD_DATA,req->buffer,256);
	req->sector++;
	req->buffer += 512;
	req->errors = 0;
	i = --req->nr_sectors;
	--req->current_nr_sectors;
#ifdef DEBUG
	printk("%s: read: sector %ld, remaining = %ld, buffer=%p\n",
		req->rq_disk->disk_name, req->sector, req->nr_sectors,
		req->buffer+512);
#endif
	if (req->current_nr_sectors <= 0)
		end_request(req, 1);
	if (i > 0) {
		SET_HANDLER(&read_intr);
		return;
	}
	(void) inb_p(HD_STATUS);
#if (HD_DELAY > 0)
	last_req = read_timer();
#endif
	if (elv_next_request(QUEUE))
		hd_request();
	return;
}
/**************************************************************************
POLL - Wait for a frame
***************************************************************************/
static int tiara_poll(struct nic *nic)
{
	unsigned int		len;

	if (inb(ioaddr + DLCR_RECV_MODE) & BUF_EMPTY)
		return (0);
	/* Ack packet */
	outw(CLR_RCV_STATUS, ioaddr + DLCR_RECV_STAT);
	len = inw(ioaddr + BMPR_MEM_PORT);		/* throw away status */
	len = inw(ioaddr + BMPR_MEM_PORT);
	/* Drop overlength packets */
	if (len > ETH_FRAME_LEN)
		return (0);		/* should we drain the buffer? */
	insw(ioaddr + BMPR_MEM_PORT, nic->packet, len / 2);
	/* If it's our own, drop it */
	if (memcmp(nic->packet + ETH_ALEN, nic->node_addr, ETH_ALEN) == 0)
		return (0);
	nic->packetlen = len;
	return (1);
}
Example #11
0
void
bus_space_read_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
    u_int16_t *ptr, bus_size_t cnt)
{
	if ((t) == X86_BUS_SPACE_IO) {
		insw(h + o, ptr, cnt);
	} else {
		void *dummy1;
		int dummy2;
		void *dummy3;
		int __x;
		__asm __volatile(" cld				;"
		"1:	movw (%2),%%ax				;"
		"	stosw					;"
		"	loop 1b"				:
		    "=D" (dummy1), "=c" (dummy2), "=r" (dummy3), "=&a" (__x) :
		    "0" ((ptr)), "1" ((cnt)), "2" (h + o)       :
		    "memory");
	}
}
Example #12
0
/*
 * This is used for most PIO data transfers *from* the IDE interface
 *
 * These routines will round up any request for an odd number of bytes,
 * so if an odd len is specified, be sure that there's at least one
 * extra byte allocated for the buffer.
 */
void ide_input_data(ide_drive_t *drive, struct ide_cmd *cmd, void *buf,
		    unsigned int len)
{
	ide_hwif_t *hwif = drive->hwif;
	struct ide_io_ports *io_ports = &hwif->io_ports;
	unsigned long data_addr = io_ports->data_addr;
	unsigned int words = (len + 1) >> 1;
	u8 io_32bit = drive->io_32bit;
	u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;

	if (io_32bit) {
		unsigned long uninitialized_var(flags);

		if ((io_32bit & 2) && !mmio) {
			local_irq_save_nort(flags);
			ata_vlb_sync(io_ports->nsect_addr);
		}

		words >>= 1;
		if (mmio)
			__ide_mm_insl((void __iomem *)data_addr, buf, words);
		else
			insl(data_addr, buf, words);

		if ((io_32bit & 2) && !mmio)
			local_irq_restore_nort(flags);

		if (((len + 1) & 3) < 2)
			return;

		buf += len & ~3;
		words = 1;
	}

	if (mmio)
		__ide_mm_insw((void __iomem *)data_addr, buf, words);
	else
		insw(data_addr, buf, words);
}
//-------------------------------------------------------------------------------------------------------------------------------
//
//  检测硬盘存在函数
//
//-------------------------------------------------------------------------------------------------------------------------------
static int	GetIDENum(void)
{
	 unsigned short    buffer[256];
	 char              *text;
	 unsigned char     c_disks;
 
   c_disks = ReadCmos(0x12);
	
	if (c_disks & 0xf0){
		if (c_disks & 0x0f){
			NR_HD_DEV = 2;
		}
		else{
			NR_HD_DEV = 1;
	   }
    }
	else{
		  NR_HD_DEV = 0;
		  return 0;
	}

	outb(0xA0,0x1F6); // Get first/second drive 
	outb(0xEC,0x1F7);  // 获取驱动器信息数据 
    
	memset(HardDiskInfo, 0, sizeof(struct HardDiskStruct));

	while (inb(HD_STATUS)&0x80);
	insw(0x1f0, buffer, 256);  //将数据读到缓冲区
	HardDiskInfo[0].sect = buffer[6];
	HardDiskInfo[0].head = buffer[3];
	HardDiskInfo[0].cyl =  buffer[1];

	text = (unsigned char*)&buffer[27];
	SwapChar(text);
	strcpy(HardDiskName, text);
  HardDiskName[15]=0;

	return NR_HD_DEV;
}
static void read_intr(void)
{
	struct request *req;
	int i, retries = 100000;

	do {
		i = (unsigned) inb_p(HD_STATUS);
		if (i & BUSY_STAT)
			continue;
		if (!OK_STATUS(i))
			break;
		if (i & DRQ_STAT)
			goto ok_to_read;
	} while (--retries > 0);
	dump_status("read_intr", i);
	bad_rw_intr();
	hd_request();
	return;

ok_to_read:
	req = hd_req;
	insw(HD_DATA, req->buffer, 256);
#ifdef DEBUG
	printk("%s: read: sector %ld, remaining = %u, buffer=%p\n",
	       req->rq_disk->disk_name, blk_rq_pos(req) + 1,
	       blk_rq_sectors(req) - 1, req->buffer+512);
#endif
	if (hd_end_request(0, 512)) {
		SET_HANDLER(&read_intr);
		return;
	}

	(void) inb_p(HD_STATUS);
#if (HD_DELAY > 0)
	last_req = read_timer();
#endif
	hd_request();
}
Example #15
0
static void ioport_read16r(void __iomem *addr, void *dst, unsigned long count)
{
	insw(ADDR2PORT(addr), dst, count);
}
Example #16
0
/* Use the ATA IDENTIFY command to find out what kind of drive is
* attached to the given bus/slot.  */
uint32
ata_identify (uint32 bus, uint32 drive)
{
 uint8 status;
 uint16 buffer[256];

 
 ata_drive_select (bus, drive);

   // while(!(status=inb(ATA_COMMAND(bus)) & 0x60)){
   //  rprintf("loop0");
   // }

   outb (ATA_COMMAND (bus),0xEC);       /* Send IDENTIFY command */
 
 ATA_SELECT_DELAY (bus);
 
 status = inb (ATA_COMMAND (bus));
 if (status == 0) {
     // rprintf ("ATA bus %X drive %X does not exist\n", bus, drive);
   return NOTCD;
 }
 
 if (status & 0x1) {
     /* Drive does not support IDENTIFY.  Probably a CD-ROM. */
   goto guess_identity;
 }
 
   /* Poll the Status port (0x1F7) until bit 7 (BSY, value = 0x80)
    * clears, and bit 3 (DRQ, value = 8) sets -- or until bit 0 (ERR,
    * value = 1) sets. */
     
     while ((status = inb (ATA_COMMAND (bus))) & 0x80){
       asm volatile ("pause");
     // printf("%s\n","busy");
   }     /* BUSY */

       while (!((status = inb (ATA_COMMAND (bus))) & 0x8) && !(status & 0x01)){
     // printf("%x",status);
         asm volatile ("pause");
       }

       if (status & 0x1) {
    // rprintf ("ATA bus %X drive %X caused error.\n", bus, drive);
        goto guess_identity;
      }
      
   /* Read 256 words */
      insw (ATA_DATA (bus), buffer, 256);
      
 #ifdef DEBUG_ATA
      {
       int i, j;
       
     // DLOG ("IDENTIFY (bus: %X drive: %X) command output:", bus, drive);
     /* dump to com1 */
       for (i = 0; i < 32; i++) {
         for (j = 0; j < 8; j++) {
          rprintf ("%.4X ", buffer[i * 32 + j]);
        }
        rprintf ("\n");
      }
    }
 #endif
    
    if (buffer[83] & (1 << 10))
   // rprintf ("LBA48 mode supported.\n");
   // rprintf ("LBA48 addressable sectors: %.4X %.4X %.4X %.4X\n",
   //                buffer[100], buffer[101], buffer[102], buffer[103]);
     rprintf("not a cd");   
   return NOTCD;

   guess_identity:{
     uint8 b1, b2;
     
     b1 = inb (ATA_ADDRESS2 (bus));
     b2 = inb (ATA_ADDRESS3 (bus));
     
     // rprintf ("ata_detect: %.2X %.2X\n", b1, b2);
     
     if (b1 == 0x14 && b2 == 0xEB) {
       rprintf("is a CD");
       // rprintf("P-ATAPI detected\n");
       return ISCD;
     }

     //TODO: probar eliminar estos
     if (b1 == 0x69 && b2 == 0x96) {
      rprintf("is a CD");
       // rprintf ("S-ATAPI detected\n");
      return ISCD;
    }
    if (b1 == 0x3C && b2 == 0xC3) {
     rprintf("is a CD");
       // rprintf ("SATA detected\n");
     return ISCD;
   }
   rprintf("NOT a CD");
   return NOTCD;
 }
}
Example #17
0
/* receive a single frame and assemble datagram
 * (this is the heart of the interrupt routine)
 */
static int
sb1000_rx(struct net_device *dev)
{

#define FRAMESIZE 184
	unsigned char st[2], buffer[FRAMESIZE], session_id, frame_id;
	short dlen;
	int ioaddr, ns;
	unsigned int skbsize;
	struct sk_buff *skb;
	struct sb1000_private *lp = netdev_priv(dev);
	struct net_device_stats *stats = &dev->stats;

	/* SB1000 frame constants */
	const int FrameSize = FRAMESIZE;
	const int NewDatagramHeaderSkip = 8;
	const int NewDatagramHeaderSize = NewDatagramHeaderSkip + 18;
	const int NewDatagramDataSize = FrameSize - NewDatagramHeaderSize;
	const int ContDatagramHeaderSkip = 7;
	const int ContDatagramHeaderSize = ContDatagramHeaderSkip + 1;
	const int ContDatagramDataSize = FrameSize - ContDatagramHeaderSize;
	const int TrailerSize = 4;

	ioaddr = dev->base_addr;

	insw(ioaddr, (unsigned short*) st, 1);
#ifdef XXXDEBUG
printk("cm0: received: %02x %02x\n", st[0], st[1]);
#endif /* XXXDEBUG */
	lp->rx_frames++;

	/* decide if it is a good or bad frame */
	for (ns = 0; ns < NPIDS; ns++) {
		session_id = lp->rx_session_id[ns];
		frame_id = lp->rx_frame_id[ns];
		if (st[0] == session_id) {
			if (st[1] == frame_id || (!frame_id && (st[1] & 0xf0) == 0x30)) {
				goto good_frame;
			} else if ((st[1] & 0xf0) == 0x30 && (st[0] & 0x40)) {
				goto skipped_frame;
			} else {
				goto bad_frame;
			}
		} else if (st[0] == (session_id | 0x40)) {
			if ((st[1] & 0xf0) == 0x30) {
				goto skipped_frame;
			} else {
				goto bad_frame;
			}
		}
	}
	goto bad_frame;

skipped_frame:
	stats->rx_frame_errors++;
	skb = lp->rx_skb[ns];
	if (sb1000_debug > 1)
		printk(KERN_WARNING "%s: missing frame(s): got %02x %02x "
			"expecting %02x %02x\n", dev->name, st[0], st[1],
			skb ? session_id : session_id | 0x40, frame_id);
	if (skb) {
		dev_kfree_skb(skb);
		skb = NULL;
	}

good_frame:
	lp->rx_frame_id[ns] = 0x30 | ((st[1] + 1) & 0x0f);
	/* new datagram */
	if (st[0] & 0x40) {
		/* get data length */
		insw(ioaddr, buffer, NewDatagramHeaderSize / 2);
#ifdef XXXDEBUG
printk("cm0: IP identification: %02x%02x  fragment offset: %02x%02x\n", buffer[30], buffer[31], buffer[32], buffer[33]);
#endif /* XXXDEBUG */
		if (buffer[0] != NewDatagramHeaderSkip) {
			if (sb1000_debug > 1)
				printk(KERN_WARNING "%s: new datagram header skip error: "
					"got %02x expecting %02x\n", dev->name, buffer[0],
					NewDatagramHeaderSkip);
			stats->rx_length_errors++;
			insw(ioaddr, buffer, NewDatagramDataSize / 2);
			goto bad_frame_next;
		}
		dlen = ((buffer[NewDatagramHeaderSkip + 3] & 0x0f) << 8 |
			buffer[NewDatagramHeaderSkip + 4]) - 17;
		if (dlen > SB1000_MRU) {
			if (sb1000_debug > 1)
				printk(KERN_WARNING "%s: datagram length (%d) greater "
					"than MRU (%d)\n", dev->name, dlen, SB1000_MRU);
			stats->rx_length_errors++;
			insw(ioaddr, buffer, NewDatagramDataSize / 2);
			goto bad_frame_next;
		}
		lp->rx_dlen[ns] = dlen;
		/* compute size to allocate for datagram */
		skbsize = dlen + FrameSize;
		if ((skb = alloc_skb(skbsize, GFP_ATOMIC)) == NULL) {
			if (sb1000_debug > 1)
				printk(KERN_WARNING "%s: can't allocate %d bytes long "
					"skbuff\n", dev->name, skbsize);
			stats->rx_dropped++;
			insw(ioaddr, buffer, NewDatagramDataSize / 2);
			goto dropped_frame;
		}
		skb->dev = dev;
		skb_reset_mac_header(skb);
		skb->protocol = (unsigned short) buffer[NewDatagramHeaderSkip + 16];
		insw(ioaddr, skb_put(skb, NewDatagramDataSize),
			NewDatagramDataSize / 2);
		lp->rx_skb[ns] = skb;
	} else {
		/* continuation of previous datagram */
		insw(ioaddr, buffer, ContDatagramHeaderSize / 2);
		if (buffer[0] != ContDatagramHeaderSkip) {
			if (sb1000_debug > 1)
				printk(KERN_WARNING "%s: cont datagram header skip error: "
					"got %02x expecting %02x\n", dev->name, buffer[0],
					ContDatagramHeaderSkip);
			stats->rx_length_errors++;
			insw(ioaddr, buffer, ContDatagramDataSize / 2);
			goto bad_frame_next;
		}
		skb = lp->rx_skb[ns];
		insw(ioaddr, skb_put(skb, ContDatagramDataSize),
			ContDatagramDataSize / 2);
		dlen = lp->rx_dlen[ns];
	}
	if (skb->len < dlen + TrailerSize) {
		lp->rx_session_id[ns] &= ~0x40;
		return 0;
	}

	/* datagram completed: send to upper level */
	skb_trim(skb, dlen);
	netif_rx(skb);
	stats->rx_bytes+=dlen;
	stats->rx_packets++;
	lp->rx_skb[ns] = NULL;
	lp->rx_session_id[ns] |= 0x40;
	return 0;

bad_frame:
	insw(ioaddr, buffer, FrameSize / 2);
	if (sb1000_debug > 1)
		printk(KERN_WARNING "%s: frame error: got %02x %02x\n",
			dev->name, st[0], st[1]);
	stats->rx_frame_errors++;
bad_frame_next:
	if (sb1000_debug > 2)
		sb1000_print_status_buffer(dev->name, st, buffer, FrameSize);
dropped_frame:
	stats->rx_errors++;
	if (ns < NPIDS) {
		if ((skb = lp->rx_skb[ns])) {
			dev_kfree_skb(skb);
			lp->rx_skb[ns] = NULL;
		}
		lp->rx_session_id[ns] |= 0x40;
	}
	return -1;
}
Example #18
0
/**************************************************************************
ETH_POLL - Wait for a frame
***************************************************************************/
int
EtherReceive(char *pkt, int maxlen)
{
	/* common variables */
	int len;
	/* variables for 3C509 */
	short status, cst;
	register short rx_fifo;

	cst = inw(BASE + EP_STATUS);

#ifdef EDEBUG
	if (cst & 0x1FFF)
		printf("-%x-",cst);
#endif

	if ((cst & (S_RX_COMPLETE|S_RX_EARLY)) == 0) {
		/* acknowledge  everything */
		outw(BASE + EP_COMMAND, ACK_INTR| (cst & S_5_INTS));
		outw(BASE + EP_COMMAND, C_INTR_LATCH);

		return 0;
	}

	status = inw(BASE + EP_W1_RX_STATUS);
#ifdef EDEBUG
	printf("*%x*",status);
#endif

	if (status & ERR_RX) {
		outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
		return 0;
	}

	rx_fifo = status & RX_BYTES_MASK;
	if (rx_fifo == 0)
		return 0;

	if (rx_fifo > maxlen)
		goto zulang;

	/* read packet */
#ifdef EDEBUG
	printf("[l=%d",rx_fifo);
#endif
	insw(BASE + EP_W1_RX_PIO_RD_1, pkt, rx_fifo / 2);
	if (rx_fifo & 1)
		pkt[rx_fifo-1] = inb(BASE + EP_W1_RX_PIO_RD_1);
	len = rx_fifo;

	for (;;) {
		status = inw(BASE + EP_W1_RX_STATUS);
#ifdef EDEBUG
		printf("*%x*",status);
#endif
		rx_fifo = status & RX_BYTES_MASK;

		if (rx_fifo > 0) {
			if ((len + rx_fifo) > maxlen)
				goto zulang;

			insw(BASE + EP_W1_RX_PIO_RD_1, pkt + len, rx_fifo / 2);
			if (rx_fifo & 1)
				pkt[len + rx_fifo-1] = inb(BASE + EP_W1_RX_PIO_RD_1);
			len += rx_fifo;
#ifdef EDEBUG
			printf("+%d",rx_fifo);
#endif
		}

		if ((status & RX_INCOMPLETE) == 0) {
#ifdef EDEBUG
			printf("=%d",len);
#endif
			break;
		}

		delay(1000);
	}

	/* acknowledge reception of packet */
	outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
	while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS)
		continue;

	return len;

 zulang:
	outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
	while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS)
		continue;
	return 0;
}
Example #19
0
bool ATAManager::GetDeviceInformation(ushort controller, uchar device, DeviceInfo &devInfo)
{
	AutoDisable	lock;	// disable ints
	uchar		statusReg;
	
	MemSet(&devInfo, 0, sizeof(DeviceInfo)); // just zero it out
		
	// delay for 400ns
	ATADriver::Delay400ns(controller);
	
	// check the status register
	statusReg = inb(controller | ATADriver::ALT_STATUS_REG);
	
	// if we get 0xFF from the status register then no controller :-(
	if(statusReg == 0xFF)
		return false;
	
// 	DEBUG("*** START (%x) ***\n", statusReg);
	
	// wait for the drive to not be busy
	do { statusReg = inb(controller | ATADriver::ALT_STATUS_REG); }
	while(statusReg & ATADriver::BUSY);
	
// 	DEBUG("STATUS REG: %x\n", statusReg);
	
	asm("cli");	// clear interrupts
	
	// wait for the drive to be ready
	do { statusReg = inb(controller | ATADriver::ALT_STATUS_REG); }
	while(!(statusReg & ATADriver::DRIVE_READY));
	
// 	DEBUG("STATUS REG: %x\n", statusReg);
	
	// select the device
	outb(controller | ATADriver::DRIVE_HEAD_REG, device);
	
	// send the "IDENTIFY DRIVE" command
	outb(controller | ATADriver::COMMAND_REG, ATADriver::IDENT_DEV);
	
	asm("sti");	// enable interrupts
	
// 	DEBUG("SENT COMMAND\n");
	
	// INT HAPPENS HERE
	
	// wait for the driver to not be busy
	do { statusReg = inb(controller | ATADriver::ALT_STATUS_REG); }
	while(statusReg & ATADriver::BUSY);
	
// 	DEBUG("STATUS REG: %x\n", statusReg);
	
	asm("cli");	// clear interrupts
	
	// poll to see if the drive is ready
	do { statusReg = inb(controller | ATADriver::ALT_STATUS_REG); }
	while(!(statusReg & ATADriver::DRIVE_READY) && (statusReg & ATADriver::DATA_READY));
	
// 	DEBUG("STATUS REG: %x\n", statusReg);
	
	ushort	tmpBuf[256];
	
	// getting an error probably means we're dealing with ATAPI
	if(statusReg & ATADriver::ERROR)
	{
// 		DEBUG("GOT AN ERROR\n");
		
		uchar cl, ch;
		
		// read in cylinder high & low to check for ATAPI
		cl = inb(controller | ATADriver::CYLINDER_LOW_REG);
		ch = inb(controller | ATADriver::CYLINDER_HIGH_REG);
		
// 		DEBUG("LOW 0x%x == 0x14 && HIGH 0x%x == 0xeb\n", cl, ch);
		
 		if(cl == 0x14 && ch == 0xeb)	// we have a packet device
		{
			// perform a software reset
			ATADriver::ResetController(controller);
		}
			
		else	// some other error
			PANIC("Unknown error identifying drives", false);
		
		//
		// Reset this device
		//
			
		// wait for the drive to not be busy
/*		do { statusReg = inb(controller | ATADriver::ALT_STATUS_REG); }
		while(statusReg & ATADriver::BUSY);

		asm("cli");
		
		// wait for the drive to be ready
		do { statusReg = inb(controller | ATADriver::ALT_STATUS_REG); }
		while(!(statusReg & ATADriver::DRIVE_READY));

		// select the device
		outb(controller | ATADriver::DRIVE_HEAD_REG, device);
		
		// send the "RESET DEVICE" command
		outb(controller | ATADriver::COMMAND_REG, ATADriver::RESET_DEVICE);
		
		asm("sti");
		
		// wait for the drive to not be busy
		do { statusReg = inb(controller | ATADriver::ALT_STATUS_REG); }
		while(statusReg & ATADriver::BUSY);
		
		statusReg = inb(controller | ATADriver::STATUS_REG);
		
		printf("STATUS: %x\n", statusReg);		
*/	
		return(false);
	}
	
// 	DEBUG("READING DATA\n");
	
	// it is 256 words (ushort) or 512 bytes (uchar)
	insw(controller | ATADriver::DATA_REG, tmpBuf, 256);
	
	// read the primary status register once
	inb(controller | ATADriver::STATUS_REG);
	
	// fill in the info for the drive
	devInfo.ATAPI_dev = tmpBuf[0] & 0x8000;
	devInfo.numLogCylinders = tmpBuf[1];
	devInfo.numLogHeads = tmpBuf[3];
	devInfo.numSecPreTrack = tmpBuf[6];
	
	MemCopy(devInfo.serialNumber, &tmpBuf[10], sizeof(devInfo.serialNumber));
	MemCopy(devInfo.firmwareVersion, &tmpBuf[23], sizeof(devInfo.firmwareVersion));
	MemCopy(devInfo.modelNumber, &tmpBuf[27], sizeof(devInfo.modelNumber));

	// need to byte swap the model number
	ByteSwap(devInfo.modelNumber, sizeof(devInfo.modelNumber));
	
	devInfo.maxSectorsForMultiple = tmpBuf[47] & 0x00FF;
	devInfo.numCurLogCylinders = tmpBuf[54];
	devInfo.numCurLogHeads = tmpBuf[55];
	devInfo.numCurLogSectorsPerTrack = tmpBuf[56];
	
	MemCopy(&devInfo.curCapacityInSectors, &tmpBuf[57], sizeof(devInfo.curCapacityInSectors));
	
	devInfo.curNumSectorsForMultiple = tmpBuf[59] & 0x00FF;
	
	MemCopy(&devInfo.totalAddressableSectors, &tmpBuf[60], sizeof(devInfo.totalAddressableSectors));

	devInfo.ATAVersion = tmpBuf[80];
	
	return(true);	
}
Example #20
0
static void
el2_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
{
    int boguscount = 0;
    void __iomem *base = ei_status.mem;
    unsigned short int *buf;
    unsigned short word;

    /* Maybe enable shared memory just be to be safe... nahh.*/
    if (base) {	/* Use the shared memory. */
	ring_offset -= (EL2_MB1_START_PG<<8);
	if (ring_offset + count > EL2_MEMSIZE) {
	    /* We must wrap the input move. */
	    int semi_count = EL2_MEMSIZE - ring_offset;
	    memcpy_fromio(skb->data, base + ring_offset, semi_count);
	    count -= semi_count;
	    memcpy_fromio(skb->data + semi_count, base + ei_status.priv, count);
	} else {
		memcpy_fromio(skb->data, base + ring_offset, count);
	}
	return;
    }

/*
 *  No shared memory, use programmed I/O.
 */
    word = (unsigned short) ring_offset;
    outb(word>>8, E33G_DMAAH);
    outb(word&0xFF, E33G_DMAAL);

    outb_p((ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI) | ECNTRL_INPUT
	   | ECNTRL_START, E33G_CNTRL);

/*
 *  Here I also try to get data as fast as possible. I am betting that I
 *  can read one extra byte without clobbering anything in the kernel because
 *  this would only occur on an odd byte-count and allocation of skb->data
 *  is word-aligned. Variable 'count' is NOT checked. Caller must check
 *  for a valid count.
 *  [This is currently quite safe.... but if one day the 3c503 explodes
 *   you know where to come looking ;)]
 */

    buf =  (unsigned short int *) skb->data;
    count =  (count + 1) >> 1;
    for(;;)
    {
        boguscount = 0x1000;
        while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0)
        {
            if(!boguscount--)
            {
                printk("%s: FIFO blocked in el2_block_input.\n", dev->name);
                el2_reset_8390(dev);
                goto blocked;
            }
        }
        if(count > WRD_COUNT)
        {
            insw(E33G_FIFOH, buf, WRD_COUNT);
            buf   += WRD_COUNT;
            count -= WRD_COUNT;
        }
        else
        {
            insw(E33G_FIFOH, buf, count);
            break;
        }
    }
    blocked:;
    outb_p(ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
    return;
}
Example #21
0
/**************************************************************************
ETH_POLL - Wait for a frame
***************************************************************************/
static int t595_poll(struct nic *nic, int retrieve)
{
	/* common variables */
	/* variables for 3C595 */
	short status, cst;
	register short rx_fifo;

	cst=inw(BASE + VX_STATUS);

#ifdef EDEBUG
	if(cst & 0x1FFF)
		printf("-%hX-",cst);
#endif

	if( (cst & S_RX_COMPLETE)==0 ) {
		/* acknowledge  everything */
		outw(ACK_INTR | cst, BASE + VX_COMMAND);
		outw(C_INTR_LATCH, BASE + VX_COMMAND);

		return 0;
	}

	status = inw(BASE + VX_W1_RX_STATUS);
#ifdef EDEBUG
	printf("*%hX*",status);
#endif

	if (status & ERR_RX) {
		outw(RX_DISCARD_TOP_PACK, BASE + VX_COMMAND);
		return 0;
	}

	rx_fifo = status & RX_BYTES_MASK;
	if (rx_fifo==0)
		return 0;

	if ( ! retrieve ) return 1;

		/* read packet */
#ifdef EDEBUG
	printf("[l=%d",rx_fifo);
#endif
	insw(BASE + VX_W1_RX_PIO_RD_1, nic->packet, rx_fifo / 2);
	if(rx_fifo & 1)
		nic->packet[rx_fifo-1]=inb(BASE + VX_W1_RX_PIO_RD_1);
	nic->packetlen=rx_fifo;

	while(1) {
		status = inw(BASE + VX_W1_RX_STATUS);
#ifdef EDEBUG
		printf("*%hX*",status);
#endif
		rx_fifo = status & RX_BYTES_MASK;

		if(rx_fifo>0) {
			insw(BASE + VX_W1_RX_PIO_RD_1, nic->packet+nic->packetlen, rx_fifo / 2);
			if(rx_fifo & 1)
				nic->packet[nic->packetlen+rx_fifo-1]=inb(BASE + VX_W1_RX_PIO_RD_1);
			nic->packetlen+=rx_fifo;
#ifdef EDEBUG
			printf("+%d",rx_fifo);
#endif
		}
		if(( status & RX_INCOMPLETE )==0) {
#ifdef EDEBUG
			printf("=%d",nic->packetlen);
#endif
			break;
		}
		udelay(1000);
	}

	/* acknowledge reception of packet */
	outw(RX_DISCARD_TOP_PACK, BASE + VX_COMMAND);
	while (inw(BASE + VX_STATUS) & S_COMMAND_IN_PROGRESS);
#ifdef EDEBUG
{
	unsigned short type = 0;	/* used by EDEBUG */
	type = (nic->packet[12]<<8) | nic->packet[13];
	if(nic->packet[0]+nic->packet[1]+nic->packet[2]+nic->packet[3]+nic->packet[4]+
	    nic->packet[5] == 0xFF*ETH_ALEN)
		printf(",t=%hX,b]",type);
	else
		printf(",t=%hX]",type);
}
#endif
	return 1;
}
Example #22
0
wstdcall void WRAP_EXPORT(READ_PORT_BUFFER_USHORT)
	(ULONG_PTR port, USHORT *buf, ULONG count)
{
	insw(port, buf, count);
}
Example #23
0
__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts)
{
	insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts);
}
Example #24
0
static void
epread(struct ep_softc *sc)
{
    struct mbuf *top, *mcur, *m;
    struct ifnet *ifp;
    int lenthisone;

    short rx_fifo2, status;
    short rx_fifo;

    ifp = &sc->arpcom.ac_if;
    status = inw(BASE + EP_W1_RX_STATUS);

read_again:

    if (status & ERR_RX) {
	IFNET_STAT_INC(ifp, ierrors, 1);
	if (status & ERR_RX_OVERRUN) {
	    /*
	     * we can think the rx latency is actually greather than we
	     * expect
	     */
#ifdef EP_LOCAL_STATS
	    if (EP_FTST(sc, F_RX_FIRST))
		sc->rx_overrunf++;
	    else
		sc->rx_overrunl++;
#endif
	}
	goto out;
    }
    rx_fifo = rx_fifo2 = status & RX_BYTES_MASK;

    if (EP_FTST(sc, F_RX_FIRST)) {
	m = m_getl(rx_fifo, MB_DONTWAIT, MT_DATA, M_PKTHDR, NULL);
	if (!m)
	    goto out;
	sc->top = sc->mcur = top = m;
#define EROUND  ((sizeof(struct ether_header) + 3) & ~3)
#define EOFF    (EROUND - sizeof(struct ether_header))
	top->m_data += EOFF;

	/* Read what should be the header. */
	insw(BASE + EP_W1_RX_PIO_RD_1,
	     mtod(top, caddr_t), sizeof(struct ether_header) / 2);
	top->m_len = sizeof(struct ether_header);
	rx_fifo -= sizeof(struct ether_header);
	sc->cur_len = rx_fifo2;
    } else {
	/* come here if we didn't have a complete packet last time */
	top = sc->top;
	m = sc->mcur;
	sc->cur_len += rx_fifo2;
    }

    /* Reads what is left in the RX FIFO */
    while (rx_fifo > 0) {
	lenthisone = min(rx_fifo, M_TRAILINGSPACE(m));
	if (lenthisone == 0) {	/* no room in this one */
	    mcur = m;
	    m = m_getl(rx_fifo, MB_DONTWAIT, MT_DATA, 0, NULL);
	    if (!m)
		goto out;
	    m->m_len = 0;
	    mcur->m_next = m;
	    lenthisone = min(rx_fifo, M_TRAILINGSPACE(m));
	}
	if (EP_FTST(sc, F_ACCESS_32_BITS)) { /* default for EISA configured cards*/
	    insl(BASE + EP_W1_RX_PIO_RD_1, mtod(m, caddr_t) + m->m_len,
		 lenthisone / 4);
	    m->m_len += (lenthisone & ~3);
	    if (lenthisone & 3)
		insb(BASE + EP_W1_RX_PIO_RD_1,
		     mtod(m, caddr_t) + m->m_len,
		     lenthisone & 3);
	    m->m_len += (lenthisone & 3);
	} else {
	    insw(BASE + EP_W1_RX_PIO_RD_1, mtod(m, caddr_t) + m->m_len,
		 lenthisone / 2);
	    m->m_len += lenthisone;
	    if (lenthisone & 1)
		*(mtod(m, caddr_t) + m->m_len - 1) = inb(BASE + EP_W1_RX_PIO_RD_1);
	}
	rx_fifo -= lenthisone;
    }

    if (status & ERR_RX_INCOMPLETE) {	/* we haven't received the complete
					 * packet */
	sc->mcur = m;
#ifdef EP_LOCAL_STATS
	sc->rx_no_first++;	/* to know how often we come here */
#endif
	EP_FRST(sc, F_RX_FIRST);
	if (!((status = inw(BASE + EP_W1_RX_STATUS)) & ERR_RX_INCOMPLETE)) {
	    /* we see if by now, the packet has completly arrived */
	    goto read_again;
	}
	outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH | RX_NEXT_EARLY_THRESH);
	return;
    }
    outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
    IFNET_STAT_INC(ifp, ipackets, 1);
    EP_FSET(sc, F_RX_FIRST);
    top->m_pkthdr.rcvif = &sc->arpcom.ac_if;
    top->m_pkthdr.len = sc->cur_len;

    ifp->if_input(ifp, top);
    sc->top = 0;
    while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
    outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH | RX_INIT_EARLY_THRESH);
    return;

out:
    outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
    if (sc->top) {
	m_freem(sc->top);
	sc->top = 0;
#ifdef EP_LOCAL_STATS
	sc->rx_no_mbuf++;
#endif
    }
    EP_FSET(sc, F_RX_FIRST);
    while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
    outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH | RX_INIT_EARLY_THRESH);
}
Example #25
0
void os_insw (void *port, HPT_U16 *buffer, HPT_U32 count)
{ insw((unsigned)(HPT_UPTR)port, (void *)buffer, count); }
Example #26
0
void eata_pio_int_handler(int irq, void *dev_id, struct pt_regs * regs)
{
    uint eata_stat = 0xfffff;
    Scsi_Cmnd *cmd;
    hostdata *hd;
    struct eata_ccb *cp;
    uint base;
    ulong flags;
    uint x,z;
    struct Scsi_Host *sh;
    ushort zwickel=0;
    unchar stat,odd;
    
    save_flags(flags);
    cli();
    
    for (x = 1, sh = first_HBA; x <= registered_HBAs; x++, sh = SD(sh)->prev) {
	if (sh->irq != irq)
	    continue;
	if (inb((uint)sh->base + HA_RSTATUS) & HA_SBUSY)
	    continue;
	
	int_counter++;
	
	hd=SD(sh);
	
	cp = &hd->ccb[0];
	cmd = cp->cmd;
	base = (uint) cmd->host->base;
	
	do
	{
	    stat=inb(base+HA_RSTATUS);
	    if (stat&HA_SDRQ) {
		if (cp->DataIn)
		{
		    z=256; odd=FALSE;
		    while ((cmd->SCp.Status)&&((z>0)||(odd)))
		    {
			if (odd) 
			{ 
			    *(cmd->SCp.ptr)=zwickel>>8; 
			    IncStat(&cmd->SCp,1);
			    odd=FALSE;
			}
			x=min(z,cmd->SCp.this_residual/2);
			insw(base+HA_RDATA,cmd->SCp.ptr,x);
			z-=x; 
			IncStat(&cmd->SCp,2*x);
			if ((z>0)&&(cmd->SCp.this_residual==1))
			{
			    zwickel=inw(base+HA_RDATA); 
			    *(cmd->SCp.ptr)=zwickel&0xff;
			    IncStat(&cmd->SCp,1); z--; 
			    odd=TRUE;
			}
		    }
		    while (z>0) {
			zwickel=inw(base+HA_RDATA); 
			z--;
		    } 
		}
		else /* cp->DataOut */
		{
		    odd=FALSE; z=256;
		    while ((cmd->SCp.Status)&&((z>0)||(odd)))
		    {
			if (odd)
			{
			    zwickel+=*(cmd->SCp.ptr)<<8; 
			    IncStat(&cmd->SCp,1);
			    outw(zwickel,base+HA_RDATA); 
			    z--; 
			    odd=FALSE; 
			}
			x=min(z,cmd->SCp.this_residual/2);
			outsw(base+HA_RDATA,cmd->SCp.ptr,x);
			z-=x; 
			IncStat(&cmd->SCp,2*x);
			if ((z>0)&&(cmd->SCp.this_residual==1))
			{
			    zwickel=*(cmd->SCp.ptr); 
			    zwickel&=0xff;
			    IncStat(&cmd->SCp,1); 
			    odd=TRUE;
			}  
		    }
		    while (z>0||odd) {
			outw(zwickel,base+HA_RDATA); 
			z--; 
			odd=FALSE;
		    }
		}
	    }
	}
Example #27
0
static void ide_insw (unsigned long port, void *addr, u32 count)
{
	return insw(port, addr, count);
}
Example #28
0
static inline void cirrus_frame_read (struct net_device *dev,struct sk_buff *skb,u16 length)
{
	insw (dev->base_addr,skb_put (skb,length),(length + 1) / 2);
}
Example #29
0
static irqreturn_t eata_pio_int_handler(int irq, void *dev_id)
{
	unsigned int eata_stat = 0xfffff;
	struct scsi_cmnd *cmd;
	hostdata *hd;
	struct eata_ccb *cp;
	unsigned long base;
	unsigned int x, z;
	struct Scsi_Host *sh;
	unsigned short zwickel = 0;
	unsigned char stat, odd;
	irqreturn_t ret = IRQ_NONE;

	for (x = 1, sh = first_HBA; x <= registered_HBAs; x++, sh = SD(sh)->prev) 
	{
		if (sh->irq != irq)
			continue;
		if (inb(sh->base + HA_RSTATUS) & HA_SBUSY)
			continue;

		int_counter++;
		ret = IRQ_HANDLED;

		hd = SD(sh);

		cp = &hd->ccb[0];
		cmd = cp->cmd;
		base = cmd->device->host->base;

		do {
			stat = inb(base + HA_RSTATUS);
			if (stat & HA_SDRQ) {
				if (cp->DataIn) {
					z = 256;
					odd = 0;
					while ((cmd->SCp.Status) && ((z > 0) || (odd))) {
						if (odd) {
							*(cmd->SCp.ptr) = zwickel >> 8;
							IncStat(&cmd->SCp, 1);
							odd = 0;
						}
						x = min_t(unsigned int, z, cmd->SCp.this_residual / 2);
						insw(base + HA_RDATA, cmd->SCp.ptr, x);
						z -= x;
						IncStat(&cmd->SCp, 2 * x);
						if ((z > 0) && (cmd->SCp.this_residual == 1)) {
							zwickel = inw(base + HA_RDATA);
							*(cmd->SCp.ptr) = zwickel & 0xff;
							IncStat(&cmd->SCp, 1);
							z--;
							odd = 1;
						}
					}
					while (z > 0) {
						zwickel = inw(base + HA_RDATA);
						z--;
					}
				} else {	/* cp->DataOut */

					odd = 0;
					z = 256;
					while ((cmd->SCp.Status) && ((z > 0) || (odd))) {
						if (odd) {
							zwickel += *(cmd->SCp.ptr) << 8;
							IncStat(&cmd->SCp, 1);
							outw(zwickel, base + HA_RDATA);
							z--;
							odd = 0;
						}
						x = min_t(unsigned int, z, cmd->SCp.this_residual / 2);
						outsw(base + HA_RDATA, cmd->SCp.ptr, x);
						z -= x;
						IncStat(&cmd->SCp, 2 * x);
						if ((z > 0) && (cmd->SCp.this_residual == 1)) {
							zwickel = *(cmd->SCp.ptr);
							zwickel &= 0xff;
							IncStat(&cmd->SCp, 1);
							odd = 1;
						}
					}
					while (z > 0 || odd) {
						outw(zwickel, base + HA_RDATA);
						z--;
						odd = 0;
					}
				}
			}
		}
Example #30
0
uint8_t identify() {
    inb(ATA_PRIMARY_COMM_REGSTAT);
    outb(ATA_PRIMARY_DRIVE_HEAD, 0xA0);
    inb(ATA_PRIMARY_COMM_REGSTAT);
    outb(ATA_PRIMARY_SECCOUNT, 0);
    inb(ATA_PRIMARY_COMM_REGSTAT);
    outb(ATA_PRIMARY_LBA_LO, 0);
    inb(ATA_PRIMARY_COMM_REGSTAT);
    outb(ATA_PRIMARY_LBA_MID, 0);
    inb(ATA_PRIMARY_COMM_REGSTAT);
    outb(ATA_PRIMARY_LBA_HI, 0);
    inb(ATA_PRIMARY_COMM_REGSTAT);
    outb(ATA_PRIMARY_COMM_REGSTAT, 0xEC);
    outb(ATA_PRIMARY_COMM_REGSTAT, 0xE7);

    // Read the status port. If it's zero, the drive does not exist.
    uint8_t status = inb(ATA_PRIMARY_COMM_REGSTAT);

    printf("Waiting for status.\n");
    while(status & STAT_BSY) {
        uint32_t i = 0;
        while(1) {
            printf("Printing stuff %d\n", i);
            i++;
        }
        for(i = 0; i < 0x0FFFFFFF; i++) {}
        printf("Checking regstat.\n");
        status = inb(ATA_PRIMARY_COMM_REGSTAT);
    }
    
    if(status == 0) return 0;

    printf("Status indicates presence of a drive. Polling while STAT_BSY... ");
    while(status & STAT_BSY) {
      printf("\ninb(ATA_PRIMARY_COMM_REGSTAT);... ");
      status = inb(ATA_PRIMARY_COMM_REGSTAT);
    }
    printf("Done.\n");

    uint8_t mid = inb(ATA_PRIMARY_LBA_MID);
    uint8_t hi = inb(ATA_PRIMARY_LBA_HI);
    if(mid || hi) {
        // The drive is not ATA. (Who knows what it is.)
        return 0;
    }

    printf("Waiting for ERR or DRQ.\n");
    // Wait for ERR or DRQ
    while(!(status & (STAT_ERR | STAT_DRQ))) {
        status = inb(ATA_PRIMARY_COMM_REGSTAT);
    }

    if(status & STAT_ERR) {
        // There was an error on the drive. Forget about it.
        return 0;
    }

    printf("Reading IDENTIFY structure.\n");
    //uint8_t *buff = kmalloc(40960, 0, NULL);
    uint8_t buff[256 * 2];
    insw(ATA_PRIMARY_DATA, buff, 256);
    printf("Success. Disk is ready to go.\n");
    // We read it!
    return 1;
}