Changeset 194
- Timestamp:
- Jul 13, 2017, 12:27:52 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/hal/x86_64/drivers/soclib_bdv.c
r76 r194 28 28 #include <spinlock.h> 29 29 30 #include <hal_internal.h> 31 32 #define PIO_ATA_CBR_BASE 0x1F0 33 # define ATA_DATA 0x000 34 # define ATA_ERRFEAT 0x001 /* two regs */ 35 # define ATA_SCR 0x002 36 # define ATA_SNR 0x003 /* lba0 */ 37 # define ATA_CLR 0x004 /* lba1 */ 38 # define ATA_CHR 0x005 /* lba2 */ 39 # define ATA_DHR 0x006 /* drive | lba3 */ 40 # define ATA_SR 0x007 41 # define ATA_SR_ERR 0x01 42 # define ATA_SR_IDX 0x02 43 # define ATA_SR_CORR 0x04 44 # define ATA_SR_DRQ 0x08 45 # define ATA_SR_DSC 0x10 46 # define ATA_SR_DF 0x20 47 # define ATA_SR_DRDY 0x40 48 # define ATA_SR_BSY 0x80 49 # define ATA_CR 0x007 /* two regs */ 50 51 #define ATA_CMD_READ_SECTORS_RETRY 0x20 52 #define ATA_CMD_READ_SECTORS_NORETRY 0x21 53 #define ATA_CMD_WRITE_SECTORS_RETRY 0x30 54 #define ATA_CMD_WRITE_SECTORS_NORETRY 0x31 55 #define ATA_CMD_IDENTIFY 0xEC 56 57 static inline uint16_t ata_data_read() 58 { 59 return in16(PIO_ATA_CBR_BASE + ATA_DATA); 60 } 61 62 static inline void ata_data_write(uint16_t val) 63 { 64 out16(PIO_ATA_CBR_BASE + ATA_DATA, val); 65 } 66 67 static inline uint8_t ata_cbr_read(uint32_t reg) 68 { 69 return in8(PIO_ATA_CBR_BASE + reg); 70 } 71 72 static inline void ata_cbr_write(uint32_t reg, uint8_t val) 73 { 74 out8(PIO_ATA_CBR_BASE + reg, val); 75 } 76 77 static inline int ata_wait() 78 { 79 uint8_t status; 80 81 while (!(ata_cbr_read(ATA_SR) & ATA_SR_DRQ)); 82 status = ata_cbr_read(ATA_SR); 83 return ((status & ATA_SR_ERR) ? -1 : 0); 84 } 85 86 static void ata_prepare(uint8_t slave, uint32_t lba, uint8_t count) 87 { 88 ata_cbr_write(ATA_ERRFEAT, 0x00); /* NULL byte to port 0x1F1 */ 89 ata_cbr_write(ATA_SCR, count); /* sector count */ 90 91 /* set the lba */ 92 ata_cbr_write(ATA_SNR, (lba >> 0) & 0xFF); 93 ata_cbr_write(ATA_CLR, (lba >> 8) & 0xFF); 94 ata_cbr_write(ATA_CHR, (lba >> 16)& 0xFF); 95 96 /* set the drive and lba3 */ 97 ata_cbr_write(ATA_DHR, 0xE0 | (slave << 4) | ((lba >> 24) & 0x0F)); 98 } 99 100 static int ata_read(uint8_t count, char *buf) 101 { 102 uint16_t tmpword; 103 int idx; 104 105 /* wait for the drive to signal that it's ready */ 106 if (ata_wait() == -1) 107 return -1; 108 109 for (idx = 0; idx < 256 * count; idx++) { 110 tmpword = ata_data_read(); 111 buf[idx * 2] = (uint8_t)(tmpword & 0xFF); 112 buf[idx * 2 + 1] = (uint8_t)(tmpword >> 8); 113 } 114 115 return 0; 116 } 117 118 static int ata_write(uint8_t count, char *buf) 119 { 120 uint16_t tmpword; 121 int idx; 122 123 /* wait for the drive to signal that it's ready */ 124 if (ata_wait() == -1) 125 return -1; 126 127 for (idx = 0; idx < 256 * count; idx++) { 128 tmpword = (buf[idx * 2 + 1] << 8) | buf[idx * 2]; 129 ata_data_write(tmpword); 130 } 131 132 return 0; 133 } 134 135 static uint16_t bswap16(uint16_t x) 136 { 137 return ((x << 8) & 0xFF00) | ((x >> 8) & 0x00FF); 138 } 139 140 static void ata_init() 141 { 142 uint8_t id[512]; 143 uint16_t tmpw, *p; 144 size_t idx; 145 char *model; 146 uint8_t ncyl; 147 int ret; 148 149 ata_prepare(0, 0, 0); 150 ata_cbr_write(ATA_CR, ATA_CMD_IDENTIFY); 151 152 /* wait for the drive to signal that it's ready */ 153 ret = ata_wait(); 154 if (ret == -1) 155 x86_printf("-> unable to identify ATA\n"); 156 157 for (idx = 0; idx < 256; idx++) { 158 tmpw = ata_data_read(); 159 id[idx * 2] = (uint8_t)((tmpw >> 0) & 0xFF); 160 id[idx * 2 + 1] = (uint8_t)((tmpw >> 8) & 0xFF); 161 } 162 163 ncyl = id[0] & 0x1; 164 x86_printf("-> cyl: %z\n", (uint64_t)ncyl); 165 166 for (idx = 27*2; idx < 46*2; idx += 2) { 167 p = (uint16_t *)(&id[idx]); 168 *p = bswap16(*p); 169 } 170 171 model = &id[27*2]; 172 id[46*2] = '\0'; 173 x86_printf("-> ATA model: '%s'\n", model); 174 } 175 176 /* -------------------------------------------------------------------------- */ 177 178 30 179 void soclib_bdv_init( chdev_t * chdev ) 31 180 { 32 181 ata_init(); 33 182 } 34 183 … … 36 185 { 37 186 187 x86_panic("myshit!\n"); 188 189 uint32_t cmd_type; // IOC_READ / IOC_WRITE / IOC_SYNC_READ 190 uint32_t lba; // command argument 191 uint32_t count; // command argument 192 xptr_t buf_xp; // command argument 193 194 // get client thread cluster and local pointer 195 cxy_t th_cxy = GET_CXY( th_xp ); 196 thread_t * th_ptr = (thread_t *)GET_PTR( th_xp ); 197 198 // get command arguments and extended pointer on IOC device 199 cmd_type = hal_remote_lw ( XPTR( th_cxy , &th_ptr->command.ioc.type ) ); 200 lba = hal_remote_lw ( XPTR( th_cxy , &th_ptr->command.ioc.lba ) ); 201 count = hal_remote_lw ( XPTR( th_cxy , &th_ptr->command.ioc.count ) ); 202 buf_xp = (xptr_t)hal_remote_lwd( XPTR( th_cxy , &th_ptr->command.ioc.buf_xp ) ); 203 204 /* execute operation */ 205 ata_prepare(0, lba, count); 206 if (cmd_type == IOC_WRITE) { 207 ata_cbr_write(ATA_CR, ATA_CMD_WRITE_SECTORS_RETRY); 208 } else { 209 ata_cbr_write(ATA_CR, ATA_CMD_READ_SECTORS_RETRY); 210 } 211 212 /* waiting policy depends on the command type */ 213 if (cmd_type == IOC_SYNC_READ) { 214 ata_read(count, (char *)buf_xp); 215 } else { 216 x86_panic("!IOC_SYNC_READ not supported"); 217 } 38 218 } 39 219
Note: See TracChangeset
for help on using the changeset viewer.