kern

diff src/ata.c @ 87:178d5a95e6de

implementing ata read
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 07 Dec 2011 17:10:37 +0200
parents 379332fc1667
children a398bf73fe93
line diff
     1.1 --- a/src/ata.c	Wed Dec 07 14:03:11 2011 +0200
     1.2 +++ b/src/ata.c	Wed Dec 07 17:10:37 2011 +0200
     1.3 @@ -7,6 +7,7 @@
     1.4  #include "ata.h"
     1.5  #include "intr.h"
     1.6  #include "asmops.h"
     1.7 +#include "sched.h"
     1.8  #include "mutex.h"
     1.9  
    1.10  /* registers */
    1.11 @@ -64,6 +65,7 @@
    1.12  static void ata_intr(int inum);
    1.13  static void *atastr(void *res, void *src, int n);
    1.14  static char *size_str(uint64_t nsect, char *buf);
    1.15 +static void print_error(int devid, int wr, uint32_t high, uint32_t low, unsigned char err);
    1.16  
    1.17  /* last drive selected on each bus */
    1.18  static int drvsel[2] = {-1, -1};
    1.19 @@ -107,8 +109,8 @@
    1.20  int ata_read_pio(int devno, uint64_t sect, void *buf)
    1.21  {
    1.22  	int cmd, st, res = -1;
    1.23 -	uint32_t sect_low;
    1.24 -	struct device *dev = device + devno;
    1.25 +	uint32_t sect_low, sect_high;
    1.26 +	struct device *dev = devices + devno;
    1.27  
    1.28  	if(dev->id == -1) {
    1.29  		return -1;
    1.30 @@ -123,7 +125,7 @@
    1.31  
    1.32  	/* LBA48 requires the high-order bits first */
    1.33  	if(sect >= dev->nsect_lba) {
    1.34 -		uint32_t sect_high = (uint32_t)(sect >> 24);
    1.35 +		sect_high = (uint32_t)(sect >> 24);
    1.36  		sect_low = (uint32_t)sect & 0xffffff;
    1.37  
    1.38  		if(sect >= dev->nsect_lba48) {
    1.39 @@ -137,14 +139,15 @@
    1.40  		write_reg8(dev, REG_LBA2, (sect_high >> 16) & 0xff);
    1.41  	} else {
    1.42  		cmd = CMD_READ;
    1.43 -		sect_low = (uint32_t)sect & 0xffffff;
    1.44 +		sect_high = 0;
    1.45 +		sect_low = (uint32_t)sect & 0xfffffff;
    1.46  	}
    1.47  
    1.48  	write_reg8(dev, REG_COUNT, 1);
    1.49  	write_reg8(dev, REG_LBA0, sect_low & 0xff);
    1.50  	write_reg8(dev, REG_LBA1, (sect_low >> 8) & 0xff);
    1.51  	write_reg8(dev, REG_LBA2, (sect_low >> 16) & 0xff);
    1.52 -	write_reg8(dev, REG_DEVICE, ((sect_low >> 24) & 0xf) | DEV_LBA | DEV_SEL(dev->id))
    1.53 +	write_reg8(dev, REG_DEVICE, ((sect_low >> 24) & 0xf) | DEV_LBA | DEV_SEL(dev->id));
    1.54  	/* execute */
    1.55  	write_reg8(dev, REG_CMD, cmd);
    1.56  
    1.57 @@ -154,10 +157,14 @@
    1.58  			/* also sleep on the mutex if we're called from userspace */
    1.59  			wait(&pending);
    1.60  		}
    1.61 -	} while((st = read_reg8(dev, REG_ALTSTAT)) & (ST_DRQ | ST_ERR) == 0);
    1.62 +	} while(((st = read_reg8(dev, REG_ALTSTAT)) & (ST_DRQ | ST_ERR)) == 0);
    1.63  
    1.64  	if(st & ST_ERR) {
    1.65 -		print_error();
    1.66 +		//print_error(int devid, int wr, uint32_t high, uint32_t low, unsigned char err);
    1.67 +		unsigned char err;
    1.68 +
    1.69 +		err = read_reg8(dev, REG_ERROR);
    1.70 +		print_error(devno, 0, sect_high, sect_low, err);
    1.71  		goto end;
    1.72  	}
    1.73  
    1.74 @@ -173,9 +180,10 @@
    1.75  
    1.76  int ata_write_pio(int devno, uint64_t sect, void *buf)
    1.77  {
    1.78 -	if(dev[devno].id == -1) {
    1.79 +	if(devices[devno].id == -1) {
    1.80  		return -1;
    1.81  	}
    1.82 +	return -1;
    1.83  }
    1.84  
    1.85  static int identify(struct device *dev, int iface, int id)
    1.86 @@ -352,3 +360,24 @@
    1.87  	return buf;
    1.88  }
    1.89  
    1.90 +#define ERR_NM		(1 << 1)
    1.91 +#define ERR_ABRT	(1 << 2)
    1.92 +#define ERR_MCR		(1 << 3)
    1.93 +#define ERR_IDNF	(1 << 4)
    1.94 +#define ERR_MC		(1 << 5)
    1.95 +#define ERR_UNC		(1 << 6)
    1.96 +
    1.97 +static void print_error(int devid, int wr, uint32_t high, uint32_t low, unsigned char err)
    1.98 +{
    1.99 +	printf("ata%d %s %serror ", devid, wr ? "write" : "read", err & ERR_UNC ? "uncorrectable " : "");
   1.100 +	printf("at sector %x%x: ", high, low);
   1.101 +
   1.102 +	if(err & ERR_ABRT)
   1.103 +		printf("abort ");
   1.104 +	if(err & ERR_IDNF)
   1.105 +		printf("invalid address ");
   1.106 +	if(err & ERR_NM)
   1.107 +		printf("no media ");
   1.108 +
   1.109 +	printf("(%x)\n", (unsigned int)err);
   1.110 +}