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 +}