1 /* ata_pthru.c - ATA pass through for ata.mod. */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2009 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
21 #include <grub/scsi.h>
22 #include <grub/disk.h>
25 #ifndef GRUB_MACHINE_MIPS_QEMU_MIPS
27 #include <grub/cs5536.h>
29 #define GRUB_MACHINE_PCI_IO_BASE 0xb4000000
31 #include <grub/time.h>
33 GRUB_MOD_LICENSE ("GPLv3+");
35 /* At the moment, only two IDE ports are supported. */
36 static const grub_port_t grub_pata_ioaddress
[] = { GRUB_ATA_CH0_PORT1
,
39 struct grub_pata_device
41 /* IDE port to use. */
44 /* IO addresses on which the registers for this device can be
46 grub_port_t ioaddress
;
48 /* Two devices can be connected to a single cable. Use this field
49 to select device 0 (commonly known as "master") or device 1
50 (commonly known as "slave"). */
55 struct grub_pata_device
*next
;
58 static struct grub_pata_device
*grub_pata_devices
;
61 grub_pata_regset (struct grub_pata_device
*dev
, int reg
, int val
)
63 grub_outb (val
, dev
->ioaddress
+ reg
);
66 static inline grub_uint8_t
67 grub_pata_regget (struct grub_pata_device
*dev
, int reg
)
69 return grub_inb (dev
->ioaddress
+ reg
);
74 grub_pata_wait_not_busy (struct grub_pata_device
*dev
, int milliseconds
)
76 /* ATA requires 400ns (after a write to CMD register) or
77 1 PIO cycle (after a DRQ block transfer) before
78 first check of BSY. */
83 while ((sts
= grub_pata_regget (dev
, GRUB_ATA_REG_STATUS
))
84 & GRUB_ATA_STATUS_BUSY
)
86 if (i
>= milliseconds
)
88 grub_dprintf ("pata", "timeout: %dms, status=0x%x\n",
90 return grub_error (GRUB_ERR_TIMEOUT
, "PATA timeout");
100 static inline grub_err_t
101 grub_pata_check_ready (struct grub_pata_device
*dev
, int spinup
)
103 if (grub_pata_regget (dev
, GRUB_ATA_REG_STATUS
) & GRUB_ATA_STATUS_BUSY
)
104 return grub_pata_wait_not_busy (dev
, spinup
? GRUB_ATA_TOUT_SPINUP
105 : GRUB_ATA_TOUT_STD
);
107 return GRUB_ERR_NONE
;
111 grub_pata_wait (void)
113 grub_millisleep (50);
116 #ifdef GRUB_MACHINE_MIPS_QEMU_MIPS
117 #define grub_ata_to_cpu16(x) ((grub_uint16_t) (x))
118 #define grub_cpu_to_ata16(x) ((grub_uint16_t) (x))
120 #define grub_ata_to_cpu16 grub_le_to_cpu16
121 #define grub_cpu_to_ata16 grub_cpu_to_le16
125 grub_pata_pio_read (struct grub_pata_device
*dev
, char *buf
, grub_size_t size
)
129 /* Read in the data, word by word. */
130 for (i
= 0; i
< size
/ 2; i
++)
131 grub_set_unaligned16 (buf
+ 2 * i
,
132 grub_ata_to_cpu16 (grub_inw(dev
->ioaddress
133 + GRUB_ATA_REG_DATA
)));
135 buf
[size
- 1] = (char) grub_ata_to_cpu16 (grub_inw (dev
->ioaddress
136 + GRUB_ATA_REG_DATA
));
140 grub_pata_pio_write (struct grub_pata_device
*dev
, char *buf
, grub_size_t size
)
144 /* Write the data, word by word. */
145 for (i
= 0; i
< size
/ 2; i
++)
146 grub_outw(grub_cpu_to_ata16 (grub_get_unaligned16 (buf
+ 2 * i
)), dev
->ioaddress
+ GRUB_ATA_REG_DATA
);
149 /* ATA pass through support, used by hdparm.mod. */
151 grub_pata_readwrite (struct grub_ata
*disk
,
152 struct grub_disk_ata_pass_through_parms
*parms
,
155 struct grub_pata_device
*dev
= (struct grub_pata_device
*) disk
->data
;
156 grub_size_t nread
= 0;
159 if (! (parms
->cmdsize
== 0 || parms
->cmdsize
== 12))
160 return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET
,
161 "ATAPI non-12 byte commands not supported");
163 grub_dprintf ("pata", "pata_pass_through: cmd=0x%x, features=0x%x, sectors=0x%x\n",
165 parms
->taskfile
.features
,
166 parms
->taskfile
.sectors
);
167 grub_dprintf ("pata", "lba_high=0x%x, lba_mid=0x%x, lba_low=0x%x, size=%"
169 parms
->taskfile
.lba_high
,
170 parms
->taskfile
.lba_mid
,
171 parms
->taskfile
.lba_low
, parms
->size
);
174 grub_pata_regset (dev
, GRUB_ATA_REG_DISK
, (dev
->device
<< 4)
175 | (parms
->taskfile
.disk
& 0xef));
176 if (grub_pata_check_ready (dev
, spinup
))
179 for (i
= GRUB_ATA_REG_SECTORS
; i
<= GRUB_ATA_REG_LBAHIGH
; i
++)
180 grub_pata_regset (dev
, i
,
181 parms
->taskfile
.raw
[7 + (i
- GRUB_ATA_REG_SECTORS
)]);
182 for (i
= GRUB_ATA_REG_FEATURES
; i
<= GRUB_ATA_REG_LBAHIGH
; i
++)
183 grub_pata_regset (dev
, i
, parms
->taskfile
.raw
[i
- GRUB_ATA_REG_FEATURES
]);
186 grub_pata_regset (dev
, GRUB_ATA_REG_CMD
, parms
->taskfile
.cmd
);
189 if (grub_pata_wait_not_busy (dev
, GRUB_ATA_TOUT_DATA
))
193 grub_int8_t sts
= grub_pata_regget (dev
, GRUB_ATA_REG_STATUS
);
194 grub_dprintf ("pata", "status=0x%x\n", sts
);
200 if (grub_pata_wait_not_busy (dev
, GRUB_ATA_TOUT_DATA
))
203 irs
= grub_pata_regget (dev
, GRUB_ATAPI_REG_IREASON
);
204 /* OK if DRQ is asserted and interrupt reason is as expected. */
205 if (!((sts
& GRUB_ATA_STATUS_DRQ
)
206 && (irs
& GRUB_ATAPI_IREASON_MASK
) == GRUB_ATAPI_IREASON_CMD_OUT
))
207 return grub_error (GRUB_ERR_READ_ERROR
, "ATAPI protocol error");
208 /* Write the packet. */
209 grub_pata_pio_write (dev
, parms
->cmd
, parms
->cmdsize
);
213 while (nread
< parms
->size
214 && (sts
& (GRUB_ATA_STATUS_DRQ
| GRUB_ATA_STATUS_ERR
))
215 == GRUB_ATA_STATUS_DRQ
)
220 if (grub_pata_wait_not_busy (dev
, GRUB_ATA_TOUT_DATA
))
225 if ((grub_pata_regget (dev
, GRUB_ATAPI_REG_IREASON
)
226 & GRUB_ATAPI_IREASON_MASK
) != GRUB_ATAPI_IREASON_DATA_IN
)
227 return grub_error (GRUB_ERR_READ_ERROR
, "ATAPI protocol error");
229 cnt
= grub_pata_regget (dev
, GRUB_ATAPI_REG_CNTHIGH
) << 8
230 | grub_pata_regget (dev
, GRUB_ATAPI_REG_CNTLOW
);
231 grub_dprintf("pata", "DRQ count=%u\n", cnt
);
233 /* Count of last transfer may be uneven. */
234 if (! (0 < cnt
&& cnt
<= parms
->size
- nread
235 && (! (cnt
& 1) || cnt
== parms
->size
- nread
)))
236 return grub_error (GRUB_ERR_READ_ERROR
,
237 "invalid ATAPI transfer count");
240 cnt
= GRUB_DISK_SECTOR_SIZE
;
241 if (cnt
> parms
->size
- nread
)
242 cnt
= parms
->size
- nread
;
245 grub_pata_pio_write (dev
, (char *) parms
->buffer
+ nread
, cnt
);
247 grub_pata_pio_read (dev
, (char *) parms
->buffer
+ nread
, cnt
);
253 /* Check for write error. */
254 if (grub_pata_wait_not_busy (dev
, GRUB_ATA_TOUT_DATA
))
257 if (grub_pata_regget (dev
, GRUB_ATA_REG_STATUS
)
258 & (GRUB_ATA_STATUS_DRQ
| GRUB_ATA_STATUS_ERR
))
259 return grub_error (GRUB_ERR_WRITE_ERROR
, "ATA write error");
264 if (grub_pata_wait_not_busy (dev
, GRUB_ATA_TOUT_DATA
))
267 /* Return registers. */
268 for (i
= GRUB_ATA_REG_ERROR
; i
<= GRUB_ATA_REG_STATUS
; i
++)
269 parms
->taskfile
.raw
[i
- GRUB_ATA_REG_FEATURES
] = grub_pata_regget (dev
, i
);
271 grub_dprintf ("pata", "status=0x%x, error=0x%x, sectors=0x%x\n",
272 parms
->taskfile
.status
,
273 parms
->taskfile
.error
,
274 parms
->taskfile
.sectors
);
276 if (parms
->taskfile
.status
277 & (GRUB_ATA_STATUS_DRQ
| GRUB_ATA_STATUS_ERR
))
278 return grub_error (GRUB_ERR_READ_ERROR
, "PATA passthrough failed");
280 return GRUB_ERR_NONE
;
284 check_device (struct grub_pata_device
*dev
)
286 grub_pata_regset (dev
, GRUB_ATA_REG_DISK
, dev
->device
<< 4);
289 /* Try to detect if the port is in use by writing to it,
290 waiting for a while and reading it again. If the value
291 was preserved, there is a device connected. */
292 grub_pata_regset (dev
, GRUB_ATA_REG_SECTORS
, 0x5A);
294 grub_uint8_t sec
= grub_pata_regget (dev
, GRUB_ATA_REG_SECTORS
);
295 grub_dprintf ("ata", "sectors=0x%x\n", sec
);
297 return grub_error (GRUB_ERR_UNKNOWN_DEVICE
, "no device connected");
299 /* The above test may detect a second (slave) device
300 connected to a SATA controller which supports only one
301 (master) device. It is not safe to use the status register
302 READY bit to check for controller channel existence. Some
303 ATAPI commands (RESET, DIAGNOSTIC) may clear this bit. */
305 return GRUB_ERR_NONE
;
309 grub_pata_device_initialize (int port
, int device
, int addr
)
311 struct grub_pata_device
*dev
;
312 struct grub_pata_device
**devp
;
315 grub_dprintf ("pata", "detecting device %d,%d (0x%x)\n",
318 dev
= grub_malloc (sizeof(*dev
));
322 /* Setup the device information. */
324 dev
->device
= device
;
325 dev
->ioaddress
= addr
+ GRUB_MACHINE_PCI_IO_BASE
;
329 /* Register the device. */
330 for (devp
= &grub_pata_devices
; *devp
; devp
= &(*devp
)->next
);
333 err
= check_device (dev
);
340 #ifndef GRUB_MACHINE_MIPS_QEMU_MIPS
342 grub_pata_pciinit (grub_pci_device_t dev
,
344 void *data
__attribute__ ((unused
)))
346 static int compat_use
[2] = { 0 };
347 grub_pci_address_t addr
;
353 static int controller
= 0;
358 addr
= grub_pci_make_address (dev
, GRUB_PCI_REG_CLASS
);
359 class = grub_pci_read (addr
);
361 /* AMD CS5536 Southbridge. */
362 if (pciid
== GRUB_CS5536_PCIID
)
368 /* Check if this class ID matches that of a PCI IDE Controller. */
369 if (!cs5536
&& (class >> 16 != 0x0101))
372 for (i
= 0; i
< nports
; i
++)
374 /* Set to 0 when the channel operated in compatibility mode. */
377 /* We don't support non-compatibility mode for CS5536. */
381 compat
= (class >> (8 + 2 * i
)) & 1;
385 /* If the channel is in compatibility mode, just assign the
386 default registers. */
387 if (compat
== 0 && !compat_use
[i
])
389 rega
= grub_pata_ioaddress
[i
];
394 /* Read the BARs, which either contain a mmapped IO address
395 or the IO port address. */
396 addr
= grub_pci_make_address (dev
, GRUB_PCI_REG_ADDRESSES
397 + sizeof (grub_uint64_t
) * i
);
398 bar1
= grub_pci_read (addr
);
399 addr
= grub_pci_make_address (dev
, GRUB_PCI_REG_ADDRESSES
400 + sizeof (grub_uint64_t
) * i
401 + sizeof (grub_uint32_t
));
402 bar2
= grub_pci_read (addr
);
404 /* Check if the BARs describe an IO region. */
405 if ((bar1
& 1) && (bar2
& 1) && (bar1
& ~3))
408 addr
= grub_pci_make_address (dev
, GRUB_PCI_REG_COMMAND
);
409 grub_pci_write_word (addr
, grub_pci_read_word (addr
)
410 | GRUB_PCI_COMMAND_IO_ENABLED
411 | GRUB_PCI_COMMAND_MEM_ENABLED
412 | GRUB_PCI_COMMAND_BUS_MASTER
);
417 grub_dprintf ("pata",
418 "PCI dev (%d,%d,%d) compat=%d rega=0x%x\n",
419 grub_pci_get_bus (dev
), grub_pci_get_device (dev
),
420 grub_pci_get_function (dev
), compat
, rega
);
424 grub_errno
= GRUB_ERR_NONE
;
425 grub_pata_device_initialize (controller
* 2 + i
, 0, rega
);
427 /* Most errors raised by grub_ata_device_initialize() are harmless.
428 They just indicate this particular drive is not responding, most
429 likely because it doesn't exist. We might want to ignore specific
430 error types here, instead of printing them. */
434 grub_errno
= GRUB_ERR_NONE
;
437 grub_pata_device_initialize (controller
* 2 + i
, 1, rega
);
443 grub_errno
= GRUB_ERR_NONE
;
454 grub_pata_initialize (void)
456 grub_pci_iterate (grub_pata_pciinit
, NULL
);
461 grub_pata_initialize (void)
464 for (i
= 0; i
< 2; i
++)
466 grub_pata_device_initialize (i
, 0, grub_pata_ioaddress
[i
]);
467 grub_pata_device_initialize (i
, 1, grub_pata_ioaddress
[i
]);
474 grub_pata_open (int id
, int devnum
, struct grub_ata
*ata
)
476 struct grub_pata_device
*dev
;
477 struct grub_pata_device
*devfnd
= 0;
480 if (id
!= GRUB_SCSI_SUBSYSTEM_PATA
)
481 return grub_error (GRUB_ERR_UNKNOWN_DEVICE
, "not a PATA device");
483 for (dev
= grub_pata_devices
; dev
; dev
= dev
->next
)
485 if (dev
->port
* 2 + dev
->device
== devnum
)
492 grub_dprintf ("pata", "opening PATA dev `ata%d'\n", devnum
);
495 return grub_error (GRUB_ERR_UNKNOWN_DEVICE
, "no such PATA device");
497 err
= check_device (devfnd
);
503 ata
->maxbuffer
= 256 * 512;
504 ata
->present
= &devfnd
->present
;
506 return GRUB_ERR_NONE
;
510 grub_pata_iterate (grub_ata_dev_iterate_hook_t hook
, void *hook_data
,
511 grub_disk_pull_t pull
)
513 struct grub_pata_device
*dev
;
515 if (pull
!= GRUB_DISK_PULL_NONE
)
518 for (dev
= grub_pata_devices
; dev
; dev
= dev
->next
)
519 if (hook (GRUB_SCSI_SUBSYSTEM_PATA
, dev
->port
* 2 + dev
->device
,
527 static struct grub_ata_dev grub_pata_dev
=
529 .iterate
= grub_pata_iterate
,
530 .open
= grub_pata_open
,
531 .readwrite
= grub_pata_readwrite
,
537 GRUB_MOD_INIT(ata_pthru
)
539 grub_stop_disk_firmware ();
541 /* ATA initialization. */
542 grub_pata_initialize ();
544 grub_ata_dev_register (&grub_pata_dev
);
547 GRUB_MOD_FINI(ata_pthru
)
549 grub_ata_dev_unregister (&grub_pata_dev
);