001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019 #include <sos/types.h>
020 #include <sos/errno.h>
021 #include <sos/assert.h>
022 #include <sos/ksynch.h>
023 #include <drivers/devices.h>
024 #include <drivers/bochs.h>
025 #include <drivers/part.h>
026 #include <hwcore/irq.h>
027 #include <hwcore/ioports.h>
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045 static void udelay(int delay)
046 {
047 int i;
048
049 for (i = 0; i < (delay * 1000) ; i++)
050 {
051 i++; i--;
052 }
053 }
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094 #define IDE_CONTROLLER_0_BASE 0x1F0
095 #define IDE_CONTROLLER_1_BASE 0x170
096
097 #define IDE_CONTROLLER_0_IRQ 14
098 #define IDE_CONTROLLER_1_IRQ 15
099
100
101
102
103
104
105
106
107
108
109 #define ATA_DATA 0x00
110
111
112
113
114
115 #define ATA_ERROR 0x01
116
117
118
119
120
121
122 #define ATA_PRECOMP 0x01
123
124
125
126
127
128 #define ATA_SECTOR_COUNT 0x02
129
130
131
132
133
134 #define ATA_SECTOR_NUMBER 0x03
135
136
137
138
139
140 #define ATA_CYL_LSB 0x04
141
142
143
144
145
146 #define ATA_CYL_MSB 0x05
147
148
149
150
151
152
153 #define ATA_DRIVE 0x06
154 #define ATA_D_IBM 0xa0
155 #define ATA_D_LBA 0x40
156 #define ATA_D_MASTER 0x00
157 #define ATA_D_SLAVE 0x10
158
159
160
161
162
163 #define ATA_STATUS 0x07
164 #define ATA_S_ERROR 0x01
165 #define ATA_S_INDEX 0x02
166 #define ATA_S_CORR 0x04
167 #define ATA_S_DRQ 0x08
168 #define ATA_S_DSC 0x10
169 #define ATA_S_DWF 0x20
170 #define ATA_S_DRDY 0x40
171 #define ATA_S_BSY 0x80
172
173
174
175
176
177
178 #define ATA_CMD 0x07
179 #define ATA_C_ATA_IDENTIFY 0xec
180 #define ATA_C_ATAPI_IDENTIFY 0xa1
181 #define ATA_C_READ 0x20
182 #define ATA_C_WRITE 0x30
183 #define ATA_C_READ_MULTI 0xc4
184 #define ATA_C_WRITE_MULTI 0xc5
185 #define ATA_C_SET_MULTI 0xc6
186 #define ATA_C_PACKET_CMD 0xa0
187
188
189
190
191
192 #define ATA_ALTPORT 0x206
193
194
195
196
197
198 #define ATA_DEVICE_CONTROL 0x206
199
200 #define ATA_A_nIEN 0x02
201 #define ATA_A_RESET 0x04
202 #define ATA_A_4BIT 0x08
203
204
205 #define ATAPI_MAGIC_LSB 0x14
206 #define ATAPI_MAGIC_MSB 0xeb
207
208
209
210 struct ide_device_info
211 {
212 sos_ui16_t general_config_info;
213 sos_ui16_t nb_logical_cylinders;
214 sos_ui16_t reserved1;
215 sos_ui16_t nb_logical_heads;
216 sos_ui16_t unformatted_bytes_track;
217 sos_ui16_t unformatted_bytes_sector;
218 sos_ui16_t nb_logical_sectors;
219 sos_ui16_t vendor1[3];
220 sos_ui8_t serial_number[20];
221 sos_ui16_t buffer_type;
222 sos_ui16_t buffer_size;
223 sos_ui16_t ecc_bytes;
224 sos_ui8_t firmware_revision[8];
225 sos_ui8_t model_number[40];
226 sos_ui8_t max_multisect;
227 sos_ui8_t vendor2;
228 sos_ui16_t dword_io;
229 sos_ui8_t vendor3;
230 sos_ui8_t capabilities;
231 sos_ui16_t reserved2;
232 sos_ui8_t vendor4;
233 sos_ui8_t pio_trans_mode;
234 sos_ui8_t vendor5;
235 sos_ui8_t dma_trans_mode;
236 sos_ui16_t fields_valid;
237 sos_ui16_t cur_logical_cylinders;
238 sos_ui16_t cur_logical_heads;
239 sos_ui16_t cur_logical_sectors;
240 sos_ui16_t capacity1;
241 sos_ui16_t capacity0;
242 sos_ui8_t multsect;
243 sos_ui8_t multsect_valid;
244 sos_ui32_t lba_capacity;
245 sos_ui16_t dma_1word;
246 sos_ui16_t dma_multiword;
247 sos_ui16_t pio_modes;
248 sos_ui16_t min_mword_dma;
249 sos_ui16_t recommended_mword_dma;
250 sos_ui16_t min_pio_cycle_time;
251 sos_ui16_t min_pio_cycle_time_iordy;
252 sos_ui16_t reserved3[11];
253 sos_ui16_t major_version;
254 sos_ui16_t minor_version;
255 sos_ui16_t command_sets1;
256 sos_ui16_t command_sets2;
257 sos_ui16_t reserved4[4];
258 sos_ui16_t dma_ultra;
259 sos_ui16_t reserved5[37];
260 sos_ui16_t last_lun;
261 sos_ui16_t reserved6;
262 sos_ui16_t security;
263 sos_ui16_t reserved7[127];
264 } __attribute__((packed));
265
266 #define MAX_IDE_CONTROLLERS 2
267 #define MAX_IDE_DEVICES 2
268
269 #define IDE_BLK_SIZE 512
270
271 #define IDE_DEVICE(ctrl,device) (((ctrl) * 2) + (device))
272 #define IDE_MINOR(ctrl,device) (IDE_DEVICE(ctrl,device)*16)
273
274 typedef enum { IDE_DEVICE_NONE,
275 IDE_DEVICE_HARDDISK,
276 IDE_DEVICE_CDROM } ide_device_type_t;
277
278 struct ide_controller;
279 struct ide_device {
280 int id;
281 ide_device_type_t type;
282 enum { IDE_DEVICE_MASTER, IDE_DEVICE_SLAVE } position;
283 int cyls;
284 int heads;
285 int sectors;
286 int blocks;
287 sos_bool_t support_lba;
288 struct ide_controller *ctrl;
289 };
290
291 struct ide_controller {
292 int id;
293 int ioaddr;
294 int irq;
295 enum { IDE_CTRL_NOT_PRESENT, IDE_CTRL_PRESENT } state;
296 struct ide_device devices[MAX_IDE_DEVICES];
297 struct sos_kmutex mutex;
298
299 struct sos_ksema ack_io_sem;
300 };
301
302 struct ide_controller ide_controllers[MAX_IDE_CONTROLLERS] = {
303 {
304 .id = 0,
305 .ioaddr = IDE_CONTROLLER_0_BASE,
306 .irq = IDE_CONTROLLER_0_IRQ,
307 .state = IDE_CTRL_NOT_PRESENT,
308 },
309 {
310 .id = 1,
311 .ioaddr = IDE_CONTROLLER_1_BASE,
312 .irq = IDE_CONTROLLER_1_IRQ,
313 .state = IDE_CTRL_NOT_PRESENT
314 }
315 };
316
317 void ide_irq_handler (int irq_level)
318 {
319 int i;
320 struct ide_controller *ctrl = NULL;
321
322 for (i = 0; i < MAX_IDE_CONTROLLERS ; i++)
323 {
324 if (ide_controllers[i].irq == irq_level)
325 {
326 ctrl = & ide_controllers[i];
327 break;
328 }
329 }
330
331 SOS_ASSERT_FATAL (ctrl != NULL);
332
333 sos_ksema_up (& ctrl->ack_io_sem);
334 }
335
336 static int ide_get_device_info (struct ide_device *dev)
337 {
338 int devselect;
339 sos_ui16_t buffer[256];
340 struct ide_device_info *info;
341 int timeout, i;
342 int status;
343
344 SOS_ASSERT_FATAL (dev->type == IDE_DEVICE_HARDDISK);
345
346 if (dev->position == IDE_DEVICE_MASTER)
347 devselect = ATA_D_MASTER;
348 else
349 devselect = ATA_D_SLAVE;
350
351
352
353 outb(ATA_A_nIEN | ATA_A_4BIT, dev->ctrl->ioaddr + ATA_DEVICE_CONTROL);
354 udelay(1);
355
356
357 outb(ATA_D_IBM | devselect, dev->ctrl->ioaddr + ATA_DRIVE);
358
359
360 outb(ATA_C_ATA_IDENTIFY, dev->ctrl->ioaddr + ATA_CMD);
361
362
363 for(timeout = 0; timeout < 30000; timeout++)
364 {
365 status = inb(dev->ctrl->ioaddr + ATA_STATUS);
366 if(!(status & ATA_S_BSY))
367 break;
368
369 udelay(1);
370 }
371
372
373
374 if(! (status & ATA_S_DRQ))
375 {
376 return SOS_EFATAL;
377 }
378
379
380 for(i = 0; i < 256; i++)
381 buffer[i] = inw(dev->ctrl->ioaddr + ATA_DATA);
382
383
384
385
386 info = (struct ide_device_info *) buffer;
387
388
389 dev->heads = info->nb_logical_heads;
390 dev->cyls = info->nb_logical_cylinders;
391 dev->sectors = info->nb_logical_sectors;
392
393 dev->support_lba = FALSE;
394
395
396
397 if (info->capabilities & (1 << 1)
398 && info->major_version
399 && (info->fields_valid & 1)
400 && (info->lba_capacity & 1))
401 dev->support_lba = TRUE;
402
403
404 if (dev->heads == 16 &&
405 dev->sectors == 63 &&
406 dev->cyls == 16383)
407 {
408 if (dev->support_lba)
409 dev->blocks = info->lba_capacity;
410 else
411 return SOS_EFATAL;
412 }
413 else
414 dev->blocks = dev->cyls * dev->sectors * dev->heads;
415
416 return SOS_OK;
417 }
418
419 static ide_device_type_t ide_probe_device (struct ide_device *dev)
420 {
421 int status;
422 int devselect;
423
424 if (dev->position == IDE_DEVICE_MASTER)
425 devselect = ATA_D_MASTER;
426 else
427 devselect = ATA_D_SLAVE;
428
429
430 outb (ATA_D_IBM | devselect, dev->ctrl->ioaddr + ATA_DRIVE);
431
432
433 status = inb(dev->ctrl->ioaddr + ATA_STATUS);
434
435
436
437 if (status & ATA_S_BSY)
438 return IDE_DEVICE_NONE;
439
440
441
442 if (status & (ATA_S_DRDY | ATA_S_DSC))
443 return IDE_DEVICE_HARDDISK;
444
445
446
447 if(inb(dev->ctrl->ioaddr + ATA_CYL_LSB) == ATAPI_MAGIC_LSB &&
448 inb(dev->ctrl->ioaddr + ATA_CYL_MSB) == ATAPI_MAGIC_MSB)
449 return IDE_DEVICE_CDROM;
450
451 return IDE_DEVICE_NONE;
452 }
453
454 static sos_ret_t ide_probe_controller(struct ide_controller *ctrl)
455 {
456 sos_bool_t hasdevice = FALSE;
457
458 sos_kmutex_init (& ctrl->mutex, "ide-mutex", SOS_KWQ_ORDER_FIFO);
459 sos_ksema_init (& ctrl->ack_io_sem, "ide-sem", 0, SOS_KWQ_ORDER_FIFO);
460
461
462 ctrl->devices[0].id = 0;
463 ctrl->devices[0].position = IDE_DEVICE_MASTER;
464 ctrl->devices[0].ctrl = ctrl;
465 ctrl->devices[0].type = ide_probe_device (& ctrl->devices[0]);
466
467 if (ctrl->devices[0].type == IDE_DEVICE_HARDDISK)
468 {
469 ide_get_device_info (& ctrl->devices[0]);
470 hasdevice = TRUE;
471 }
472
473
474 ctrl->devices[1].id = 1;
475 ctrl->devices[1].position = IDE_DEVICE_SLAVE;
476 ctrl->devices[1].ctrl = ctrl;
477 ctrl->devices[1].type = ide_probe_device (& ctrl->devices[1]);
478
479 if (ctrl->devices[1].type == IDE_DEVICE_HARDDISK)
480 {
481 ide_get_device_info (& ctrl->devices[1]);
482 hasdevice = TRUE;
483 }
484
485 if (hasdevice)
486 sos_irq_set_routine (ctrl->irq, ide_irq_handler);
487
488 return SOS_OK;
489 }
490
491
492 static sos_ret_t ide_io_operation (struct ide_device *dev,
493 sos_vaddr_t buf, int block,
494 sos_bool_t iswrite)
495 {
496 sos_ui8_t cyl_lo, cyl_hi, sect, head, status;
497 int devselect, i;
498
499 SOS_ASSERT_FATAL (dev->type == IDE_DEVICE_HARDDISK);
500
501 if (block > dev->blocks)
502 return -SOS_EFATAL;
503
504 if (dev->position == IDE_DEVICE_MASTER)
505 devselect = ATA_D_MASTER;
506 else
507 devselect = ATA_D_SLAVE;
508
509
510
511
512 if (dev->support_lba)
513 {
514 sect = (block & 0xff);
515 cyl_lo = (block >> 8) & 0xff;
516 cyl_hi = (block >> 16) & 0xff;
517 head = ((block >> 24) & 0x7) | 0x40;
518 }
519 else
520 {
521 int cylinder = block /
522 (dev->heads * dev->sectors);
523 int temp = block %
524 (dev->heads * dev->sectors);
525 cyl_lo = cylinder & 0xff;
526 cyl_hi = (cylinder >> 8) & 0xff;
527 head = temp / dev->sectors;
528 sect = (temp % dev->sectors) + 1;
529 }
530
531
532 sos_kmutex_lock (& dev->ctrl->mutex, NULL);
533
534
535 outb(ATA_D_IBM | devselect, dev->ctrl->ioaddr + ATA_DRIVE);
536 udelay(100);
537
538
539 outb(ATA_A_4BIT, dev->ctrl->ioaddr + ATA_DEVICE_CONTROL);
540 outb(1, dev->ctrl->ioaddr + ATA_ERROR);
541 outb(0, dev->ctrl->ioaddr + ATA_PRECOMP);
542 outb(1, dev->ctrl->ioaddr + ATA_SECTOR_COUNT);
543 outb(sect, dev->ctrl->ioaddr + ATA_SECTOR_NUMBER);
544 outb(cyl_lo, dev->ctrl->ioaddr + ATA_CYL_LSB);
545 outb(cyl_hi, dev->ctrl->ioaddr + ATA_CYL_MSB);
546 outb((ATA_D_IBM | devselect | head),
547 dev->ctrl->ioaddr + ATA_DRIVE);
548
549
550 if (iswrite)
551 outb(ATA_C_WRITE, dev->ctrl->ioaddr + ATA_CMD);
552 else
553 outb(ATA_C_READ, dev->ctrl->ioaddr + ATA_CMD);
554
555
556 do { udelay(1); } while (inb(dev->ctrl->ioaddr + ATA_STATUS) & ATA_S_BSY);
557
558
559 if (inb(dev->ctrl->ioaddr + ATA_STATUS) & ATA_S_ERROR)
560 {
561 sos_kmutex_unlock (& dev->ctrl->mutex);
562 return -SOS_EFATAL;
563 }
564
565
566
567
568 if (iswrite)
569 {
570
571 while (1)
572 {
573 status = inb(dev->ctrl->ioaddr + ATA_STATUS);
574 if (status & ATA_S_ERROR)
575 {
576 sos_kmutex_unlock (& dev->ctrl->mutex);
577 return -SOS_EFATAL;
578 }
579
580 if (!(status & ATA_S_BSY) && (status & ATA_S_DRQ))
581 break;
582 }
583
584
585 sos_ui16_t *buffer = (sos_ui16_t *) buf;
586 for (i = 0 ; i < 256 ; i++)
587 outw (buffer[i], dev->ctrl->ioaddr + ATA_DATA);
588
589
590 while (1)
591 {
592 status = inb(dev->ctrl->ioaddr + ATA_STATUS);
593 if (status & ATA_S_ERROR)
594 {
595 sos_kmutex_unlock (& dev->ctrl->mutex);
596 return -SOS_EFATAL;
597 }
598
599 if (!(status & ATA_S_BSY) && !(status & ATA_S_DRQ))
600 break;
601 }
602 }
603
604
605 sos_ksema_down (& dev->ctrl->ack_io_sem, NULL);
606
607
608
609 inb(dev->ctrl->ioaddr + ATA_ALTPORT);
610
611 if (! iswrite)
612 {
613
614 while (1)
615 {
616 status = inb(dev->ctrl->ioaddr + ATA_STATUS);
617 if (status & ATA_S_ERROR)
618 {
619 sos_kmutex_unlock (& dev->ctrl->mutex);
620 return -SOS_EFATAL;
621 }
622
623 if (!(status & ATA_S_BSY) && (status & ATA_S_DRQ))
624 break;
625 }
626
627
628
629 sos_ui16_t *buffer = (sos_ui16_t *) buf;
630 for (i = 0 ; i < 256 ; i++)
631 buffer [i] = inw (dev->ctrl->ioaddr + ATA_DATA);
632
633
634
635 inb(dev->ctrl->ioaddr + ATA_ALTPORT);
636 }
637
638
639 if (inb(dev->ctrl->ioaddr + ATA_STATUS) & ATA_S_ERROR)
640 {
641 sos_kmutex_unlock (& dev->ctrl->mutex);
642 return -SOS_EFATAL;
643 }
644
645
646
647 sos_kmutex_unlock (& dev->ctrl->mutex);
648 return SOS_OK;
649 }
650
651 static sos_ret_t
652 ide_read_device (void *blkdev_instance, sos_vaddr_t dest_buf,
653 sos_luoffset_t block_offset)
654 {
655 struct ide_device *dev;
656
657 dev = (struct ide_device *) blkdev_instance;
658
659 return ide_io_operation (dev, dest_buf, block_offset, FALSE);
660 }
661
662 static sos_ret_t
663 ide_write_device (void *blkdev_instance, sos_vaddr_t src_buf,
664 sos_luoffset_t block_offset)
665 {
666 struct ide_device *dev;
667
668 dev = (struct ide_device *) blkdev_instance;
669
670 return ide_io_operation (dev, src_buf, block_offset, TRUE);
671 }
672
673 static struct sos_blockdev_operations ide_ops = {
674 .read_block = ide_read_device,
675 .write_block = ide_write_device,
676 .ioctl = NULL
677 };
678
679
680 static sos_ret_t
681 ide_register_devices (void)
682 {
683 int ctrl, dev;
684 sos_ret_t ret;
685
686 for (ctrl = 0; ctrl < MAX_IDE_CONTROLLERS ; ctrl++)
687 {
688 for (dev = 0; dev < MAX_IDE_DEVICES ; dev++)
689 {
690 char name[16];
691 struct ide_device *device;
692
693 device = & ide_controllers[ctrl].devices[dev];
694
695 snprintf (name, sizeof(name), "hd%c", ('a' + IDE_DEVICE(ctrl, dev)));
696
697 if (device->type == IDE_DEVICE_HARDDISK)
698 {
699 sos_bochs_printf("%s: harddisk %d Mb <", name,
700 (device->blocks * IDE_BLK_SIZE >> 20));
701 ret = sos_blockdev_register_disk (SOS_BLOCKDEV_IDE_MAJOR,
702 IDE_MINOR(ctrl, dev),
703 IDE_BLK_SIZE, device->blocks,
704 128, & ide_ops, device);
705 if (ret != SOS_OK)
706 {
707 sos_bochs_printf ("Warning: could not register disk>\n");
708 continue;
709 }
710
711 ret = sos_part_detect (SOS_BLOCKDEV_IDE_MAJOR,
712 IDE_MINOR(ctrl, dev), IDE_BLK_SIZE,
713 name);
714 if (ret != SOS_OK)
715 {
716 sos_bochs_printf ("Warning could not detect partitions (%d)>\n",
717 ret);
718 continue;
719 }
720
721
722 sos_bochs_printf (">\n");
723 }
724
725 else if (device->type == IDE_DEVICE_CDROM)
726 sos_bochs_printf("%s: CDROM\n", name);
727 }
728 }
729
730 return SOS_OK;
731 }
732
733 static sos_ret_t
734 ide_unregister_devices (void)
735 {
736 int ctrl, dev;
737 sos_ret_t ret;
738
739 for (ctrl = 0; ctrl < MAX_IDE_CONTROLLERS ; ctrl++)
740 {
741 for (dev = 0; dev < MAX_IDE_DEVICES ; dev++)
742 {
743 struct ide_device *device;
744
745 device = & ide_controllers[ctrl].devices[dev];
746
747 if (device->type != IDE_DEVICE_HARDDISK)
748 continue;
749
750 sos_part_undetect (SOS_BLOCKDEV_IDE_MAJOR, IDE_MINOR(ctrl,dev));
751
752 ret = sos_blockdev_unregister_device (SOS_BLOCKDEV_IDE_MAJOR,
753 IDE_MINOR(ctrl,dev));
754 if (ret != SOS_OK)
755 sos_bochs_printf ("Error while unregistering device %d:%d\n",
756 SOS_BLOCKDEV_IDE_MAJOR, IDE_MINOR(ctrl,dev));
757 }
758 }
759
760 return SOS_OK;
761 }
762
763
764 sos_ret_t sos_ide_subsystem_setup (void)
765 {
766 sos_ret_t ret;
767
768 ret = ide_probe_controller(& ide_controllers[0]);
769 if (ret != SOS_OK)
770 sos_bochs_printf ("Error while probing IDE controller 0\n");
771
772 ret =ide_probe_controller(& ide_controllers[1]);
773 if (ret != SOS_OK)
774 sos_bochs_printf ("Error while probing IDE controller 1\n");
775
776 ide_register_devices ();
777
778 return SOS_OK;
779 }
780
781 sos_ret_t ide_driver_cleanup (void)
782 {
783 return ide_unregister_devices ();
784 }
785