SimpleOS

LXR

Navigation



Site hébergé par : enix

The LXR Cross Referencer for SOS

source navigation ]
diff markup ]
identifier search ]
general search ]
 
 
Article:1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 6.5 ] [ 7 ] [ 7.5 ] [ 8 ] [ 9 ] [ 9.5 ]

001 /* Copyright (C) 2005  Thomas Petazzoni, David Decotigny
002 
003    This program is free software; you can redistribute it and/or
004    modify it under the terms of the GNU General Public License
005    as published by the Free Software Foundation; either version 2
006    of the License, or (at your option) any later version.
007 
008    This program is distributed in the hope that it will be useful,
009    but WITHOUT ANY WARRANTY; without even the implied warranty of
010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
011    GNU General Public License for more details.
012 
013    You should have received a copy of the GNU General Public License
014    along with this program; if not, write to the Free Software
015    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
016    USA.
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  * @file ide.c
032  *
033  * Basic PIO IDE implementation based on the ATA standards
034  * http://www.t13.org/
035  */
036 
037 
038 /**
039  * Busy-wait for a given time
040  *
041  * @param delay Delay to wait
042  *
043  * @todo Implement a calibration routine
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  * Each IDE controller is controlled through a set of 9 I/O ports,
057  * starting from a base address, which is different for each IDE
058  * controller. On a standard PC with two onboard IDE controllers, the
059  * I/O registers of the first controller start at 0x1F0
060  * (IDE_CONTROLLER_0_BASE), the I/O registers of the second controller
061  * start at 0x170 (IDE_CONTROLLER_1_BASE). These I/O registers are
062  * 8-bits wide, and can be read using the inb() macro, and written
063  * using the outb() macro.
064  *
065  * The first controller is generally known as "primary" controller,
066  * and the second one is know as "secondary" controller. Each of them
067  * can handle at most two devices : the "master" device and the
068  * "slave" device.
069  *
070  * The registers can be used to issue commands and send data to the
071  * IDE controller, for example to identify a device, to read or write
072  * a device. Then are different ways of transmitting data to the IDE
073  * controller :
074  *
075  * - program the IDE controller, send the data, and wait for the
076  *   completion of the request. This method is called "polling".
077  *
078  * - program the IDE controller, send the data, block the current
079  *   process and do something else. The completion of the request will
080  *   be signaled asynchronously by an interrupt (IRQ), which will
081  *   allow to restart the sleeping process.
082  *
083  * - program the IDE controller and the DMA controller. There's no
084  *   need to transfer the data to the IDE controller : the DMA
085  *   controller will do it. This allows to use the CPU to do something
086  *   useful during the transfer of data between the main memory and
087  *   the IDE controller.
088  *
089  * In this driver, we use the two first methods. The polling method is
090  * used to fetch the identification of the devices, while the IRQ
091  * method is used to read and write to devices.
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  * All defines below are relative to the base address of the I/O
102  * registers (IDE_CONTROLLER_0_BASE and IDE_CONTROLLER_1_BASE)
103  */
104 
105 /**
106  * Read/write register that allows to transfer the data to be written
107  * or to fetch the read data from the IDE controller.
108  */
109 #define ATA_DATA                        0x00
110 
111 /**
112  * Read only register that gives information about errors that occured
113  * during operation
114  */
115 #define ATA_ERROR                       0x01
116 
117 /**
118  * Write only register to set precompensation. It is in fact the same
119  * register as the ATA_ERROR register. It simply has a different
120  * behaviour when reading and writing it.
121  */
122 #define ATA_PRECOMP                     0x01
123 
124 /**
125  * Write only register used to set the count of sectors on which the
126  * request applies.
127  */
128 #define ATA_SECTOR_COUNT                0x02
129 
130 /**
131  * Write only register used to set the number of the starting sector
132  * of the request.
133  */
134 #define ATA_SECTOR_NUMBER               0x03
135 
136 /**
137  * Write only register used to set the 8 lower bits of the starting
138  * cylinder number of the request
139  */
140 #define ATA_CYL_LSB                     0x04
141 
142 /**
143  * Write only register used to set the 8 higher bits of the starting
144  * cylinder number of the request
145  */
146 #define ATA_CYL_MSB                     0x05
147 
148 /**
149  * Write only register that allows to select whether the LBA mode
150  * should be used, and to select whether the request concerns the
151  * slave or master device.
152  */
153 #define ATA_DRIVE                       0x06
154 #define         ATA_D_IBM               0xa0    /* bits that must be set */
155 #define         ATA_D_LBA               0x40    /* use LBA ? */
156 #define         ATA_D_MASTER            0x00    /* select master */
157 #define         ATA_D_SLAVE             0x10    /* select slave */
158 
159 /**
160  * Read only register that contains the status of the controller. Each
161  * bit of this register as a different signification.
162  */
163 #define ATA_STATUS                      0x07
164 #define         ATA_S_ERROR             0x01    /* error */
165 #define         ATA_S_INDEX             0x02    /* index */
166 #define         ATA_S_CORR              0x04    /* data corrected */
167 #define         ATA_S_DRQ               0x08    /* data request */
168 #define         ATA_S_DSC               0x10    /* drive Seek Completed */
169 #define         ATA_S_DWF               0x20    /* drive write fault */
170 #define         ATA_S_DRDY              0x40    /* drive ready */
171 #define         ATA_S_BSY               0x80    /* busy */
172 
173 /**
174  * Write only register used to set the command that the IDE controller
175  * should process. In our driver, only ATA_C_ATA_IDENTIFY, ATA_C_READ
176  * and ATA_C_WRITE are used.
177  */
178 #define ATA_CMD                         0x07
179 #define         ATA_C_ATA_IDENTIFY      0xec    /* get ATA params */
180 #define         ATA_C_ATAPI_IDENTIFY    0xa1    /* get ATAPI params*/
181 #define         ATA_C_READ              0x20    /* read command */
182 #define         ATA_C_WRITE             0x30    /* write command */
183 #define         ATA_C_READ_MULTI        0xc4    /* read multi command */
184 #define         ATA_C_WRITE_MULTI       0xc5    /* write multi command */
185 #define         ATA_C_SET_MULTI         0xc6    /* set multi size command */
186 #define         ATA_C_PACKET_CMD        0xa0    /* set multi size command */
187 
188 /**
189  * Read register that contains more information about the status of
190  * the controller
191  */
192 #define ATA_ALTPORT                     0x206   /* (R) alternate
193                                                    Status register */
194 
195 /**
196  * Write only register that allows to control the controller
197  */
198 #define ATA_DEVICE_CONTROL              0x206   /* (W) device control
199                                                    register */
200 #define         ATA_A_nIEN              0x02    /* disable interrupts */
201 #define         ATA_A_RESET             0x04    /* RESET controller */
202 #define         ATA_A_4BIT              0x08    /* 4 head bits */
203 
204 /** Magic numbers used to detect ATAPI devices */
205 #define ATAPI_MAGIC_LSB                 0x14
206 #define ATAPI_MAGIC_MSB                 0xeb
207 
208 /* This structure describe the informations returned by the Identify
209    Device command (imposed by the ATA standard) */
210 struct ide_device_info
211 {
212   sos_ui16_t general_config_info;      /* 0 */
213   sos_ui16_t nb_logical_cylinders;     /* 1 */
214   sos_ui16_t reserved1;                /* 2 */
215   sos_ui16_t nb_logical_heads;         /* 3 */
216   sos_ui16_t unformatted_bytes_track;  /* 4 */
217   sos_ui16_t unformatted_bytes_sector; /* 5 */
218   sos_ui16_t nb_logical_sectors;       /* 6 */
219   sos_ui16_t vendor1[3];               /* 7-9 */
220   sos_ui8_t  serial_number[20];        /* 10-19 */
221   sos_ui16_t buffer_type;              /* 20 */
222   sos_ui16_t buffer_size;              /* 21 */
223   sos_ui16_t ecc_bytes;                /* 22 */
224   sos_ui8_t  firmware_revision[8];     /* 23-26 */
225   sos_ui8_t  model_number[40];         /* 27-46 */
226   sos_ui8_t  max_multisect;            /* 47 */
227   sos_ui8_t  vendor2;
228   sos_ui16_t dword_io;                 /* 48 */
229   sos_ui8_t  vendor3;                  /* 49 */
230   sos_ui8_t  capabilities;
231   sos_ui16_t reserved2;                /* 50 */
232   sos_ui8_t  vendor4;                  /* 51 */
233   sos_ui8_t  pio_trans_mode;
234   sos_ui8_t  vendor5;                  /* 52 */
235   sos_ui8_t  dma_trans_mode;
236   sos_ui16_t fields_valid;             /* 53 */
237   sos_ui16_t cur_logical_cylinders;    /* 54 */
238   sos_ui16_t cur_logical_heads;        /* 55 */
239   sos_ui16_t cur_logical_sectors;      /* 56 */
240   sos_ui16_t capacity1;                /* 57 */
241   sos_ui16_t capacity0;                /* 58 */
242   sos_ui8_t  multsect;                 /* 59 */
243   sos_ui8_t  multsect_valid;
244   sos_ui32_t lba_capacity;             /* 60-61 */
245   sos_ui16_t dma_1word;                /* 62 */
246   sos_ui16_t dma_multiword;            /* 63 */
247   sos_ui16_t pio_modes;                /* 64 */
248   sos_ui16_t min_mword_dma;            /* 65 */
249   sos_ui16_t recommended_mword_dma;    /* 66 */
250   sos_ui16_t min_pio_cycle_time;       /* 67 */
251   sos_ui16_t min_pio_cycle_time_iordy; /* 68 */
252   sos_ui16_t reserved3[11];            /* 69-79 */
253   sos_ui16_t major_version;            /* 80 */
254   sos_ui16_t minor_version;            /* 81 */
255   sos_ui16_t command_sets1;            /* 82 */
256   sos_ui16_t command_sets2;            /* 83 dixit lk : b14 (smart enabled) */
257   sos_ui16_t reserved4[4];             /* 84-87 */
258   sos_ui16_t dma_ultra;                /* 88 dixit lk */
259   sos_ui16_t reserved5[37];            /* 89-125 */
260   sos_ui16_t last_lun;                 /* 126 */
261   sos_ui16_t reserved6;                /* 127 */
262   sos_ui16_t security;                 /* 128 */
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   /* Ask the controller to NOT send interrupts to acknowledge
352      commands */
353   outb(ATA_A_nIEN | ATA_A_4BIT, dev->ctrl->ioaddr + ATA_DEVICE_CONTROL);
354   udelay(1);
355 
356   /* Select the device (master or slave) */
357   outb(ATA_D_IBM | devselect, dev->ctrl->ioaddr + ATA_DRIVE);
358 
359   /* Send the IDENTIFY command */
360   outb(ATA_C_ATA_IDENTIFY, dev->ctrl->ioaddr + ATA_CMD);
361 
362   /* Wait for command completion (wait while busy bit is set) */
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   /* DRQ bit indicates that data is ready to be read. If it is not set
373      after an IDENTIFY command, there is a problem */
374   if(! (status & ATA_S_DRQ))
375     {
376       return SOS_EFATAL;
377     }
378 
379   /* Read data from the controller buffer to a temporary buffer */
380   for(i = 0; i < 256; i++)
381     buffer[i] = inw(dev->ctrl->ioaddr + ATA_DATA);
382 
383   /* The buffer contains an information structure, defined by ATA
384      specification. To ease its access, we use the previously defined
385      ide_device_info structure. */
386   info = (struct ide_device_info *) buffer;
387 
388   /* Fetch intersting informations from the structure */
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   /* Determines if device supports LBA. The method is a bit ugly, but
396      there's no other way */
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   /* Determines the capacity of the device */
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   /* Select the given device */
430   outb (ATA_D_IBM | devselect, dev->ctrl->ioaddr + ATA_DRIVE);
431 
432   /* Read the status of the device */
433   status = inb(dev->ctrl->ioaddr + ATA_STATUS);
434 
435   /* If status indicates a busy device, it means that there's no
436      device */
437   if (status & ATA_S_BSY)
438     return IDE_DEVICE_NONE;
439 
440   /* If status indicates that drive is ready and drive has complete
441      seeking, then we've got an hard drive */
442   if (status & (ATA_S_DRDY | ATA_S_DSC))
443     return IDE_DEVICE_HARDDISK;
444 
445   /* Detect CD-ROM drives by reading the cylinder low byte and
446      cylinder high byte, and check if they match magic values */
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   /* Master */
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   /* Slave */
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   /* Compute the position of the block in the device in terms of
510      cylinders, sectors and heads. As cylinders must be sent in two
511      separate parts, we compute it that way. */
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   /* Make sure nobody is using the same controller at the same time */
532   sos_kmutex_lock (& dev->ctrl->mutex, NULL);
533 
534   /* Select device */
535   outb(ATA_D_IBM | devselect, dev->ctrl->ioaddr + ATA_DRIVE);
536   udelay(100);
537 
538   /* Write to registers */
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   /* Send the command, either read or write */
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   /* Wait for the device ready to transfer */
556   do { udelay(1); } while (inb(dev->ctrl->ioaddr + ATA_STATUS) & ATA_S_BSY);
557 
558   /* If an error was detected, stop here */
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   /* If it's a write I/O, transfer the contents of the buffer provided
566      by the user to the controller internal buffer, so that the
567      controller can write the data to the disk */
568   if (iswrite)
569     {
570       /* Wait for the DRQ bit to be set */
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       /* Do the transfer to the device's buffer */
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       /* Wait for the device to have received all the data */
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   /* Sleep until the IRQ wakes us up */
605   sos_ksema_down (& dev->ctrl->ack_io_sem, NULL);
606 
607   /* ATA specs tell to read the alternate status reg and ignore its
608      result */
609   inb(dev->ctrl->ioaddr + ATA_ALTPORT);
610 
611   if (! iswrite)
612     {
613       /* Wait for the DRQ bit to be set */
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       /* copy data from the controller internal buffer to the buffer
628          provided by the user */
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       /* ATA specs tell to read the alternate status reg and ignore its
634          result */
635       inb(dev->ctrl->ioaddr + ATA_ALTPORT);
636     }
637 
638   /* If an error was detected, stop here */
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   /* Someone else can safely use devices on this controller for other
646      requests */
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               /* Finalize output */
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 

source navigation ] diff markup ] identifier search ] general search ]