Loading [MathJax]/extensions/tex2jax.js
CS350 COS
COS
All Data Structures Files Functions Variables Typedefs Macros
ide.c File Reference
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <sys/kassert.h>
#include <sys/kmem.h>
#include <sys/spinlock.h>
#include <sys/disk.h>
#include "ioport.h"
#include "../ata.h"
Include dependency graph for ide.c:

Go to the source code of this file.

Data Structures

struct  IDE
 
struct  IDEDrive
 

Macros

#define IDE_PRIMARY_BASE   0x1F0
 
#define IDE_PRIMARY_DEVCTL   0x3F6
 
#define IDE_PRIMARY_IRQ   14
 
#define IDE_SECONDARY_BASE   0x170
 
#define IDE_SECONDARY_DEVCTL   0x376
 
#define IDE_SECONDARY_IRQ   15
 
#define IDE_DATAPORT   0
 
#define IDE_FEATURES   1
 
#define IDE_SECTORCOUNT   2
 
#define IDE_LBALOW   3
 
#define IDE_LBAMID   4
 
#define IDE_LBAHIGH   5
 
#define IDE_DRIVE   6
 
#define IDE_COMMAND   7 /* Write */
 
#define IDE_STATUS   7 /* Read */
 
#define IDE_CMD_READ   0x20
 
#define IDE_CMD_READ_EXT   0x24
 
#define IDE_CMD_WRITE   0x30
 
#define IDE_CMD_WRITE_EXT   0x34
 
#define IDE_CMD_FLUSH   0xE7
 
#define IDE_CMD_IDENTIFY   0xEC
 
#define IDE_STATUS_ERR   0x01 /* Error */
 
#define IDE_STATUS_DRQ   0x08 /* Data Ready */
 
#define IDE_STATUS_SRV   0x10 /* Overlapped-mode Service Request */
 
#define IDE_STATUS_DF   0x20 /* Drive Fault Error */
 
#define IDE_STATUS_RDY   0x40 /* Ready */
 
#define IDE_STATUS_BSY   0x80 /* Busy */
 
#define IDE_CONTROL_SRST   0x04 /* Software Reset */
 
#define IDE_SECTOR_SIZE   512
 

Typedefs

typedef struct IDE IDE
 
typedef struct IDEDrive IDEDrive
 

Functions

bool IDE_HasController (IDE *ide)
 
void IDE_Reset (IDE *ide)
 
void IDE_Identify (IDE *ide, int drive)
 
int IDE_Read (Disk *disk, void *buf, SGArray *sga, DiskCB, void *arg)
 
int IDE_Write (Disk *disk, void *buf, SGArray *sga, DiskCB, void *arg)
 
int IDE_Flush (Disk *disk, void *buf, SGArray *sga, DiskCB, void *arg)
 
int IDE_ReadOne (IDEDrive *drive, void *buf, uint64_t off, uint64_t len)
 
int IDE_WriteOne (IDEDrive *drive, void *buf, uint64_t off, uint64_t len)
 
void IDE_Init ()
 
int IDEWaitForBusy (IDE *ide, bool wait)
 
void IDE_SwapAndTruncateString (char *str, int len)
 

Variables

IDE primary
 
IDEDrive primaryDrives [2]
 

Data Structure Documentation

◆ IDE

struct IDE

Definition at line 57 of file ide.c.

Collaboration diagram for IDE:
[legend]
Data Fields
uint16_t base
uint16_t devctl
uint8_t lastDriveCode
Spinlock lock

◆ IDEDrive

struct IDEDrive

Definition at line 65 of file ide.c.

Collaboration diagram for IDEDrive:
[legend]
Data Fields
int drive
IDE * ide
bool lba48
uint64_t size

Macro Definition Documentation

◆ IDE_CMD_FLUSH

#define IDE_CMD_FLUSH   0xE7

Definition at line 42 of file ide.c.

◆ IDE_CMD_IDENTIFY

#define IDE_CMD_IDENTIFY   0xEC

Definition at line 43 of file ide.c.

◆ IDE_CMD_READ

#define IDE_CMD_READ   0x20

Definition at line 38 of file ide.c.

◆ IDE_CMD_READ_EXT

#define IDE_CMD_READ_EXT   0x24

Definition at line 39 of file ide.c.

◆ IDE_CMD_WRITE

#define IDE_CMD_WRITE   0x30

Definition at line 40 of file ide.c.

◆ IDE_CMD_WRITE_EXT

#define IDE_CMD_WRITE_EXT   0x34

Definition at line 41 of file ide.c.

◆ IDE_COMMAND

#define IDE_COMMAND   7 /* Write */

Definition at line 34 of file ide.c.

◆ IDE_CONTROL_SRST

#define IDE_CONTROL_SRST   0x04 /* Software Reset */

Definition at line 53 of file ide.c.

◆ IDE_DATAPORT

#define IDE_DATAPORT   0

Definition at line 27 of file ide.c.

◆ IDE_DRIVE

#define IDE_DRIVE   6

Definition at line 33 of file ide.c.

◆ IDE_FEATURES

#define IDE_FEATURES   1

Definition at line 28 of file ide.c.

◆ IDE_LBAHIGH

#define IDE_LBAHIGH   5

Definition at line 32 of file ide.c.

◆ IDE_LBALOW

#define IDE_LBALOW   3

Definition at line 30 of file ide.c.

◆ IDE_LBAMID

#define IDE_LBAMID   4

Definition at line 31 of file ide.c.

◆ IDE_PRIMARY_BASE

#define IDE_PRIMARY_BASE   0x1F0

Definition at line 18 of file ide.c.

◆ IDE_PRIMARY_DEVCTL

#define IDE_PRIMARY_DEVCTL   0x3F6

Definition at line 19 of file ide.c.

◆ IDE_PRIMARY_IRQ

#define IDE_PRIMARY_IRQ   14

Definition at line 20 of file ide.c.

◆ IDE_SECONDARY_BASE

#define IDE_SECONDARY_BASE   0x170

Definition at line 22 of file ide.c.

◆ IDE_SECONDARY_DEVCTL

#define IDE_SECONDARY_DEVCTL   0x376

Definition at line 23 of file ide.c.

◆ IDE_SECONDARY_IRQ

#define IDE_SECONDARY_IRQ   15

Definition at line 24 of file ide.c.

◆ IDE_SECTOR_SIZE

#define IDE_SECTOR_SIZE   512

Definition at line 55 of file ide.c.

◆ IDE_SECTORCOUNT

#define IDE_SECTORCOUNT   2

Definition at line 29 of file ide.c.

◆ IDE_STATUS

#define IDE_STATUS   7 /* Read */

Definition at line 35 of file ide.c.

◆ IDE_STATUS_BSY

#define IDE_STATUS_BSY   0x80 /* Busy */

Definition at line 51 of file ide.c.

◆ IDE_STATUS_DF

#define IDE_STATUS_DF   0x20 /* Drive Fault Error */

Definition at line 49 of file ide.c.

◆ IDE_STATUS_DRQ

#define IDE_STATUS_DRQ   0x08 /* Data Ready */

Definition at line 47 of file ide.c.

◆ IDE_STATUS_ERR

#define IDE_STATUS_ERR   0x01 /* Error */

Definition at line 46 of file ide.c.

◆ IDE_STATUS_RDY

#define IDE_STATUS_RDY   0x40 /* Ready */

Definition at line 50 of file ide.c.

◆ IDE_STATUS_SRV

#define IDE_STATUS_SRV   0x10 /* Overlapped-mode Service Request */

Definition at line 48 of file ide.c.

Typedef Documentation

◆ IDE

typedef struct IDE IDE

◆ IDEDrive

typedef struct IDEDrive IDEDrive

Function Documentation

◆ IDE_Flush()

int IDE_Flush ( Disk disk,
void *  buf,
SGArray sga,
DiskCB  cb,
void *  arg 
)

Definition at line 315 of file ide.c.

316{
317 uint8_t driveCode;
318 IDE *ide;
319 IDEDrive *idedrive;
320
321 idedrive = disk->handle;
322 ide = idedrive->ide;
323
324 if (idedrive->drive == 0)
325 driveCode = 0xA0;
326 else
327 driveCode = 0xB0;
328
329 Spinlock_Lock(&ide->lock);
330 outb(ide->base + IDE_DRIVE, driveCode);
332
333 IDEWaitForBusy(ide, false);
334 Spinlock_Unlock(&ide->lock);
335
336 return 0;
337}
static INLINE void outb(uint16_t port, uint8_t data)
Definition: amd64op.h:431
Spinlock lock
Definition: ide.c:62
int drive
Definition: ide.c:68
IDE * ide
Definition: ide.c:67
int IDEWaitForBusy(IDE *ide, bool wait)
Definition: ide.c:108
#define IDE_COMMAND
Definition: ide.c:34
#define IDE_CMD_FLUSH
Definition: ide.c:42
#define IDE_DRIVE
Definition: ide.c:33
uint16_t base
Definition: ide.c:59
Definition: ide.c:58
Definition: ide.c:66
void Spinlock_Unlock(Spinlock *lock) __UNLOCK_EX(*lock)
Definition: spinlock.c:109
void Spinlock_Lock(Spinlock *lock) __LOCK_EX(*lock)
Definition: spinlock.c:75
void * handle
Definition: disk.h:12
unsigned char uint8_t
Definition: types.h:10
Here is the call graph for this function:
Here is the caller graph for this function:

◆ IDE_HasController()

bool IDE_HasController ( IDE ide)

Definition at line 131 of file ide.c.

132{
133 outb(ide->base + IDE_LBALOW, 0x41);
134 outb(ide->base + IDE_LBAMID, 0x4D);
135
136 if (inb(ide->base + IDE_LBALOW) != 0x41)
137 return false;
138 if (inb(ide->base + IDE_LBAMID) != 0x4D)
139 return false;
140
141 return true;
142}
static INLINE uint8_t inb(uint16_t port)
Definition: amd64op.h:452
#define IDE_LBAMID
Definition: ide.c:31
#define IDE_LBALOW
Definition: ide.c:30
Here is the call graph for this function:
Here is the caller graph for this function:

◆ IDE_Identify()

void IDE_Identify ( IDE ide,
int  drive 
)

Definition at line 182 of file ide.c.

183{
184 uint8_t driveCode;
185 uint8_t status;
186 ATAIdentifyDevice ident;
187
188 ASSERT(drive == 0 || drive == 1);
189
190 if (drive == 0)
191 driveCode = 0xA0;
192 else
193 driveCode = 0xB0;
194
195 outb(ide->base + IDE_DRIVE, driveCode);
196
197 status = IDEWaitForBusy(ide, true);
198 if ((status & IDE_STATUS_ERR) != 0) {
199 Log(ide, "Error selecting drive %d\n", drive);
200 return;
201 }
202 ide->lastDriveCode = driveCode;
203
204 outb(ide->base + IDE_SECTORCOUNT, 0x00);
205 outb(ide->base + IDE_LBALOW, 0x00);
206 outb(ide->base + IDE_LBAMID, 0x00);
207 outb(ide->base + IDE_LBAHIGH, 0x00);
209
210 status = inb(ide->base + IDE_STATUS);
211 if (status == 0) {
212 Log(ide, "Drive %d not present\n", drive);
213 return;
214 }
215
216 // XXX: Need timeout
217 while (1) {
218 if ((status & IDE_STATUS_BSY) == 0)
219 break;
220 status = inb(ide->base + IDE_STATUS);
221 }
222
223 if ((status & IDE_STATUS_ERR) != 0) {
224 Log(ide, "Error trying to identify drive %d\n", drive);
225 return;
226 }
227
228 insw(ide->base, (void *)&ident, 256);
229
230 // Cleanup model and serial for printing
231 char model[41];
232 char serial[21];
233
234 memcpy(&model[0], &ident.model[0], 40);
235 model[40] = '\0';
236 IDE_SwapAndTruncateString(&model[0], 40);
237
238 memcpy(&serial[0], &ident.serial[0], 20);
239 serial[20] = '\0';
240 IDE_SwapAndTruncateString(&serial[0], 20);
241
242 Log(ide, "Drive %d Model: %s Serial: %s\n", drive, model, serial);
243 Log(ide, "Drive %d %llu Sectors (%llu MBs)\n",
244 drive, ident.lbaSectors, ident.lbaSectors / 2048ULL);
245
246 primaryDrives[drive].ide = &primary;
247 primaryDrives[drive].drive = drive;
248 primaryDrives[drive].lba48 = (ident.lbaSectors > (1 << 24));
249 primaryDrives[drive].size = ident.lbaSectors;
250
251 // Register Disk
252 Disk *disk = PAlloc_AllocPage();
253 if (!disk) {
254 Panic("IDE: No memory!\n");
255 }
256
257 disk->handle = &primaryDrives[drive];
258 disk->ctrlNo = 0;
259 disk->diskNo = drive;
261 disk->sectorCount = ident.lbaSectors;
262 disk->diskSize = IDE_SECTOR_SIZE * ident.lbaSectors;
263 disk->read = IDE_Read;
264 disk->write = IDE_Write;
265 disk->flush = IDE_Flush;
266
267 Disk_AddDisk(disk);
268}
uint64_t lbaSectors
Definition: ata.h:26
uint8_t model[40]
Definition: ata.h:14
uint8_t serial[20]
Definition: ata.h:11
void Disk_AddDisk(Disk *disk)
int IDE_Write(Disk *disk, void *buf, SGArray *sga, DiskCB, void *arg)
Definition: ide.c:293
#define IDE_STATUS
Definition: ide.c:35
#define IDE_STATUS_ERR
Definition: ide.c:46
#define IDE_SECTORCOUNT
Definition: ide.c:29
bool lba48
Definition: ide.c:69
#define IDE_STATUS_BSY
Definition: ide.c:51
#define IDE_CMD_IDENTIFY
Definition: ide.c:43
IDEDrive primaryDrives[2]
Definition: ide.c:83
#define IDE_LBAHIGH
Definition: ide.c:32
IDE primary
Definition: ide.c:82
int IDE_Flush(Disk *disk, void *buf, SGArray *sga, DiskCB, void *arg)
Definition: ide.c:315
uint64_t size
Definition: ide.c:70
int IDE_Read(Disk *disk, void *buf, SGArray *sga, DiskCB, void *arg)
Definition: ide.c:271
void IDE_SwapAndTruncateString(char *str, int len)
Definition: ide.c:160
#define IDE_SECTOR_SIZE
Definition: ide.c:55
uint8_t lastDriveCode
Definition: ide.c:61
static __inline__ void insw(int port, void *buf, int cnt)
Definition: ioport.h:66
#define Log(_module, _format,...)
Definition: kassert.h:32
#define ASSERT(_x)
Definition: kassert.h:8
void * PAlloc_AllocPage()
Definition: palloc.c:188
void * memcpy(void *dst, const void *src, size_t len)
Definition: string.c:177
Definition: disk.h:11
uint64_t ctrlNo
Definition: disk.h:13
uint64_t sectorCount
Definition: disk.h:16
uint64_t diskNo
Definition: disk.h:14
int(* write)(Disk *, void *, SGArray *, DiskCB, void *)
Definition: disk.h:19
int(* flush)(Disk *, void *, SGArray *, DiskCB, void *)
Definition: disk.h:20
uint64_t diskSize
Definition: disk.h:17
uint64_t sectorSize
Definition: disk.h:15
int(* read)(Disk *, void *, SGArray *, DiskCB, void *)
Definition: disk.h:18
void Panic(const char *str)
Definition: vgacons.c:164
Here is the call graph for this function:
Here is the caller graph for this function:

◆ IDE_Init()

void IDE_Init ( )

Definition at line 86 of file ide.c.

87{
88 ASSERT(sizeof(ATAIdentifyDevice) == 512);
89
92 Spinlock_Init(&primary.lock, "IDE Primary Controller Lock",
94
96 kprintf("IDE: No controller detected\n");
97 return;
98 }
99
105}
uint16_t devctl
Definition: ide.c:60
void IDE_Identify(IDE *ide, int drive)
Definition: ide.c:182
bool IDE_HasController(IDE *ide)
Definition: ide.c:131
void IDE_Reset(IDE *ide)
Definition: ide.c:145
#define IDE_PRIMARY_BASE
Definition: ide.c:18
#define IDE_PRIMARY_DEVCTL
Definition: ide.c:19
int kprintf(const char *fmt,...)
Definition: printf.c:210
#define SPINLOCK_TYPE_NORMAL
Definition: spinlock.h:12
void Spinlock_Init(Spinlock *lock, const char *name, uint64_t type)
Definition: spinlock.c:43
Here is the call graph for this function:
Here is the caller graph for this function:

◆ IDE_Read()

int IDE_Read ( Disk disk,
void *  buf,
SGArray sga,
DiskCB  cb,
void *  arg 
)

Definition at line 271 of file ide.c.

272{
273 int i;
274 int status;
275 IDEDrive *idedrive;
276
277 idedrive = disk->handle;
278
279 for (i = 0; i < sga->len; i++) {
280 status = IDE_ReadOne(idedrive,
281 buf,
282 sga->entries[i].offset / 512,
283 sga->entries[i].length / 512);
284 buf += sga->entries[i].length;
285 if (status < 0)
286 return status;
287 }
288
289 return 0;
290}
static char buf[4096]
Definition: ethdump.c:10
int IDE_ReadOne(IDEDrive *drive, void *buf, uint64_t off, uint64_t len)
Definition: ide.c:340
uint64_t length
Definition: sga.h:10
SGEntry entries[SGARRAY_MAX_ENTRIES]
Definition: sga.h:16
uint32_t len
Definition: sga.h:15
uint64_t offset
Definition: sga.h:9
Here is the call graph for this function:
Here is the caller graph for this function:

◆ IDE_ReadOne()

int IDE_ReadOne ( IDEDrive drive,
void *  buf,
uint64_t  off,
uint64_t  len 
)

Definition at line 340 of file ide.c.

341{
342 bool lba48 = false;
343 uint8_t driveCode;
344 uint8_t status;
345 IDE *ide = drive->ide;
346
347 DLOG(ide, "read %llx %llx\n", off, len);
348
349 ASSERT(drive->drive == 0 || drive->drive == 1);
350
351 if (drive->drive == 0)
352 driveCode = lba48 ? 0x40 : 0xE0;
353 else
354 driveCode = lba48 ? 0x50 : 0xF0;
355
356 ASSERT(len < 0x10000);
357
358 Spinlock_Lock(&ide->lock);
359 if (driveCode != ide->lastDriveCode) {
360 outb(ide->base + IDE_DRIVE, driveCode);
361
362 // Need to wait for select to complete
363 status = IDEWaitForBusy(ide, true);
364 if ((status & IDE_STATUS_ERR) != 0) {
365 Spinlock_Unlock(&ide->lock);
366 Log(ide, "Error selecting drive %d\n", drive->drive);
367 return -1;
368 }
369 ide->lastDriveCode = driveCode;
370 }
371
372 if (lba48) {
373 outb(ide->base + IDE_SECTORCOUNT, len >> 8);
374 outb(ide->base + IDE_LBALOW, off >> 24);
375 outb(ide->base + IDE_LBAMID, off >> 32);
376 outb(ide->base + IDE_LBAHIGH, off >> 40);
377 }
378 outb(ide->base + IDE_SECTORCOUNT, len);
379 outb(ide->base + IDE_LBALOW, off & 0xff);
380 outb(ide->base + IDE_LBAMID, (off >> 8) & 0xff);
381 outb(ide->base + IDE_LBAHIGH, (off >> 16) & 0xff);
382
383 if (lba48)
385 else
387
388 status = IDEWaitForBusy(ide, false);
389 if ((status & IDE_STATUS_ERR) != 0) {
390 Spinlock_Unlock(&ide->lock);
391 Log(ide, "Error trying read from drive %d\n", drive->drive);
392 return -1;
393 }
394
395 int sectors;
396 for (sectors = 0; sectors < len; sectors++)
397 {
398 uint8_t *b = buf + sectors * IDE_SECTOR_SIZE;
399 insw(ide->base + IDE_DATAPORT, b, 256);
400
401 status = IDEWaitForBusy(ide, true);
402 if ((status & IDE_STATUS_ERR) != 0) {
403 Spinlock_Unlock(&ide->lock);
404 Log(ide, "Error reading from drive %d\n", drive->drive);
405 return -1;
406 }
407 }
408 Spinlock_Unlock(&ide->lock);
409
410 return 0;
411}
#define IDE_DATAPORT
Definition: ide.c:27
#define IDE_CMD_READ
Definition: ide.c:38
#define IDE_CMD_READ_EXT
Definition: ide.c:39
#define DLOG(_module, _format,...)
Definition: kassert.h:37
uint64_t len
Definition: multiboot.h:2
Here is the call graph for this function:
Here is the caller graph for this function:

◆ IDE_Reset()

void IDE_Reset ( IDE ide)

Definition at line 145 of file ide.c.

146{
147 uint8_t status;
148
150 outb(ide->devctl, 0);
151
152 status = IDEWaitForBusy(ide, true);
153 if ((status & IDE_STATUS_RDY) != IDE_STATUS_RDY) {
154 Log(ide, "Controller not ready!\n");
155 return;
156 }
157}
#define IDE_STATUS_RDY
Definition: ide.c:50
#define IDE_CONTROL_SRST
Definition: ide.c:53
Here is the call graph for this function:
Here is the caller graph for this function:

◆ IDE_SwapAndTruncateString()

void IDE_SwapAndTruncateString ( char *  str,
int  len 
)

Definition at line 160 of file ide.c.

161{
162 int i;
163
164 ASSERT(len % 2 == 0);
165
166 for (i = 0; i < len/2; i++)
167 {
168 char tmp = str[2*i];
169 str[2*i] = str[2*i+1];
170 str[2*i+1] = tmp;
171 }
172
173 for (i = len - 1; i > 0; i--) {
174 if (str[i] == ' ' || str[i] == '\0')
175 str[i] = '\0';
176 else
177 break;
178 }
179}
Here is the caller graph for this function:

◆ IDE_Write()

int IDE_Write ( Disk disk,
void *  buf,
SGArray sga,
DiskCB  cb,
void *  arg 
)

Definition at line 293 of file ide.c.

294{
295 int i;
296 int status;
297 IDEDrive *idedrive;
298
299 idedrive = disk->handle;
300
301 for (i = 0; i < sga->len; i++) {
302 status = IDE_WriteOne(idedrive,
303 buf,
304 sga->entries[i].offset / 512,
305 sga->entries[i].length / 512);
306 buf += sga->entries[i].length;
307 if (status < 0)
308 return status;
309 }
310
311 return 0;
312}
int IDE_WriteOne(IDEDrive *drive, void *buf, uint64_t off, uint64_t len)
Definition: ide.c:414
Here is the call graph for this function:
Here is the caller graph for this function:

◆ IDE_WriteOne()

int IDE_WriteOne ( IDEDrive drive,
void *  buf,
uint64_t  off,
uint64_t  len 
)

Definition at line 414 of file ide.c.

415{
416 bool lba48 = false;
417 uint8_t driveCode;
418 uint8_t status;
419 IDE *ide = drive->ide;
420
421 DLOG(ide, "read %llx %llx\n", off, len);
422
423 ASSERT(drive->drive == 0 || drive->drive == 1);
424
425 if (drive->drive == 0)
426 driveCode = lba48 ? 0x40 : 0xE0;
427 else
428 driveCode = lba48 ? 0x50 : 0xF0;
429
430 ASSERT(len < 0x10000);
431
432 Spinlock_Lock(&ide->lock);
433 if (driveCode != ide->lastDriveCode) {
434 outb(ide->base + IDE_DRIVE, driveCode);
435
436 // Need to wait for select to complete
437 status = IDEWaitForBusy(ide, true);
438 if ((status & IDE_STATUS_ERR) != 0) {
439 Spinlock_Unlock(&ide->lock);
440 Log(ide, "Error selecting drive %d\n", drive->drive);
441 return -1;
442 }
443 ide->lastDriveCode = driveCode;
444 }
445
446 if (lba48) {
447 outb(ide->base + IDE_SECTORCOUNT, len >> 8);
448 outb(ide->base + IDE_LBALOW, off >> 24);
449 outb(ide->base + IDE_LBAMID, off >> 32);
450 outb(ide->base + IDE_LBAHIGH, off >> 40);
451 }
452 outb(ide->base + IDE_SECTORCOUNT, len);
453 outb(ide->base + IDE_LBALOW, off & 0xff);
454 outb(ide->base + IDE_LBAMID, (off >> 8) & 0xff);
455 outb(ide->base + IDE_LBAHIGH, (off >> 16) & 0xff);
456
457 if (lba48)
459 else
461
462 status = IDEWaitForBusy(ide, false);
463 if ((status & IDE_STATUS_ERR) != 0) {
464 Spinlock_Unlock(&ide->lock);
465 Log(ide, "Error trying read from drive %d\n", drive->drive);
466 return -1;
467 }
468
469 int sectors;
470 for (sectors = 0; sectors < len; sectors++)
471 {
472 uint8_t *b = buf + sectors * IDE_SECTOR_SIZE;
473 outsw(ide->base + IDE_DATAPORT, b, 256);
474
475 status = IDEWaitForBusy(ide, true);
476 if ((status & IDE_STATUS_ERR) != 0) {
477 Spinlock_Unlock(&ide->lock);
478 Log(ide, "Error reading from drive %d\n", drive->drive);
479 return -1;
480 }
481 }
482 Spinlock_Unlock(&ide->lock);
483
484 // XXX: Flush cache ...
485
486 return 0;
487}
#define IDE_CMD_WRITE_EXT
Definition: ide.c:41
#define IDE_CMD_WRITE
Definition: ide.c:40
static __inline__ void outsw(int port, const void *buf, int cnt)
Definition: ioport.h:87
Here is the call graph for this function:
Here is the caller graph for this function:

◆ IDEWaitForBusy()

int IDEWaitForBusy ( IDE ide,
bool  wait 
)

Definition at line 108 of file ide.c.

109{
110 uint8_t status;
111
113
114 if (wait) {
115 inb(ide->base + IDE_STATUS);
116 inb(ide->base + IDE_STATUS);
117 inb(ide->base + IDE_STATUS);
118 inb(ide->base + IDE_STATUS);
119 }
120
121 while (1) {
122 status = inb(ide->base + IDE_STATUS);
123 if ((status & IDE_STATUS_BSY) == 0)
124 return status;
125 }
126
127 return 0xFF;
128}
pid_t wait(int *status)
Definition: process.c:49
bool Spinlock_IsHeld(Spinlock *lock) __LOCK_EX_ASSERT(*lock)
Definition: spinlock.c:126
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ primary

IDE primary

Definition at line 82 of file ide.c.

◆ primaryDrives

IDEDrive primaryDrives[2]

Definition at line 83 of file ide.c.