Indentation fix, cleanup.
[AROS.git] / arch / all-pc / boot / grub2-aros / grub-core / disk / pata.c
blob23eef2be18c2dc1b88fc4edfe4d9e480a549eadf
1 /* ata_pthru.c - ATA pass through for ata.mod. */
2 /*
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/>.
20 #include <grub/ata.h>
21 #include <grub/scsi.h>
22 #include <grub/disk.h>
23 #include <grub/dl.h>
24 #include <grub/mm.h>
25 #ifndef GRUB_MACHINE_MIPS_QEMU_MIPS
26 #include <grub/pci.h>
27 #include <grub/cs5536.h>
28 #else
29 #define GRUB_MACHINE_PCI_IO_BASE 0xb4000000
30 #endif
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,
37 GRUB_ATA_CH1_PORT1 };
39 struct grub_pata_device
41 /* IDE port to use. */
42 int port;
44 /* IO addresses on which the registers for this device can be
45 found. */
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"). */
51 int device;
53 int present;
55 struct grub_pata_device *next;
58 static struct grub_pata_device *grub_pata_devices;
60 static inline void
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);
72 /* Wait for !BSY. */
73 static grub_err_t
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. */
79 grub_millisleep (1);
81 int i = 1;
82 grub_uint8_t sts;
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",
89 milliseconds, sts);
90 return grub_error (GRUB_ERR_TIMEOUT, "PATA timeout");
93 grub_millisleep (1);
94 i++;
97 return GRUB_ERR_NONE;
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;
110 static inline void
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))
119 #else
120 #define grub_ata_to_cpu16 grub_le_to_cpu16
121 #define grub_cpu_to_ata16 grub_cpu_to_le16
122 #endif
124 static void
125 grub_pata_pio_read (struct grub_pata_device *dev, char *buf, grub_size_t size)
127 unsigned int i;
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)));
134 if (size & 1)
135 buf[size - 1] = (char) grub_ata_to_cpu16 (grub_inw (dev->ioaddress
136 + GRUB_ATA_REG_DATA));
139 static void
140 grub_pata_pio_write (struct grub_pata_device *dev, char *buf, grub_size_t size)
142 unsigned int i;
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. */
150 static grub_err_t
151 grub_pata_readwrite (struct grub_ata *disk,
152 struct grub_disk_ata_pass_through_parms *parms,
153 int spinup)
155 struct grub_pata_device *dev = (struct grub_pata_device *) disk->data;
156 grub_size_t nread = 0;
157 int i;
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",
164 parms->taskfile.cmd,
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=%"
168 PRIuGRUB_SIZE "\n",
169 parms->taskfile.lba_high,
170 parms->taskfile.lba_mid,
171 parms->taskfile.lba_low, parms->size);
173 /* Set registers. */
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))
177 return grub_errno;
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]);
185 /* Start command. */
186 grub_pata_regset (dev, GRUB_ATA_REG_CMD, parms->taskfile.cmd);
188 /* Wait for !BSY. */
189 if (grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA))
190 return grub_errno;
192 /* Check status. */
193 grub_int8_t sts = grub_pata_regget (dev, GRUB_ATA_REG_STATUS);
194 grub_dprintf ("pata", "status=0x%x\n", sts);
196 if (parms->cmdsize)
198 grub_uint8_t irs;
199 /* Wait for !BSY. */
200 if (grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA))
201 return grub_errno;
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);
212 /* Transfer data. */
213 while (nread < parms->size
214 && (sts & (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR))
215 == GRUB_ATA_STATUS_DRQ)
217 unsigned cnt;
219 /* Wait for !BSY. */
220 if (grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA))
221 return grub_errno;
223 if (parms->cmdsize)
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");
239 else
240 cnt = GRUB_DISK_SECTOR_SIZE;
241 if (cnt > parms->size - nread)
242 cnt = parms->size - nread;
244 if (parms->write)
245 grub_pata_pio_write (dev, (char *) parms->buffer + nread, cnt);
246 else
247 grub_pata_pio_read (dev, (char *) parms->buffer + nread, cnt);
249 nread += cnt;
251 if (parms->write)
253 /* Check for write error. */
254 if (grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA))
255 return grub_errno;
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");
261 parms->size = nread;
263 /* Wait for !BSY. */
264 if (grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA))
265 return grub_errno;
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;
283 static grub_err_t
284 check_device (struct grub_pata_device *dev)
286 grub_pata_regset (dev, GRUB_ATA_REG_DISK, dev->device << 4);
287 grub_pata_wait ();
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);
293 grub_pata_wait ();
294 grub_uint8_t sec = grub_pata_regget (dev, GRUB_ATA_REG_SECTORS);
295 grub_dprintf ("ata", "sectors=0x%x\n", sec);
296 if (sec != 0x5A)
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;
308 static grub_err_t
309 grub_pata_device_initialize (int port, int device, int addr)
311 struct grub_pata_device *dev;
312 struct grub_pata_device **devp;
313 grub_err_t err;
315 grub_dprintf ("pata", "detecting device %d,%d (0x%x)\n",
316 port, device, addr);
318 dev = grub_malloc (sizeof(*dev));
319 if (! dev)
320 return grub_errno;
322 /* Setup the device information. */
323 dev->port = port;
324 dev->device = device;
325 dev->ioaddress = addr + GRUB_MACHINE_PCI_IO_BASE;
326 dev->present = 1;
327 dev->next = NULL;
329 /* Register the device. */
330 for (devp = &grub_pata_devices; *devp; devp = &(*devp)->next);
331 *devp = dev;
333 err = check_device (dev);
334 if (err)
335 grub_print_error ();
337 return 0;
340 #ifndef GRUB_MACHINE_MIPS_QEMU_MIPS
341 static int
342 grub_pata_pciinit (grub_pci_device_t dev,
343 grub_pci_id_t pciid,
344 void *data __attribute__ ((unused)))
346 static int compat_use[2] = { 0 };
347 grub_pci_address_t addr;
348 grub_uint32_t class;
349 grub_uint32_t bar1;
350 grub_uint32_t bar2;
351 int rega;
352 int i;
353 static int controller = 0;
354 int cs5536 = 0;
355 int nports = 2;
357 /* Read class. */
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)
364 cs5536 = 1;
365 nports = 1;
368 /* Check if this class ID matches that of a PCI IDE Controller. */
369 if (!cs5536 && (class >> 16 != 0x0101))
370 return 0;
372 for (i = 0; i < nports; i++)
374 /* Set to 0 when the channel operated in compatibility mode. */
375 int compat;
377 /* We don't support non-compatibility mode for CS5536. */
378 if (cs5536)
379 compat = 0;
380 else
381 compat = (class >> (8 + 2 * i)) & 1;
383 rega = 0;
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];
390 compat_use[i] = 1;
392 else if (compat)
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))
407 rega = 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);
422 if (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. */
431 if (grub_errno)
433 grub_print_error ();
434 grub_errno = GRUB_ERR_NONE;
437 grub_pata_device_initialize (controller * 2 + i, 1, rega);
439 /* Likewise. */
440 if (grub_errno)
442 grub_print_error ();
443 grub_errno = GRUB_ERR_NONE;
448 controller++;
450 return 0;
453 static grub_err_t
454 grub_pata_initialize (void)
456 grub_pci_iterate (grub_pata_pciinit, NULL);
457 return 0;
459 #else
460 static grub_err_t
461 grub_pata_initialize (void)
463 int i;
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]);
469 return 0;
471 #endif
473 static grub_err_t
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;
478 grub_err_t err;
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)
487 devfnd = dev;
488 break;
492 grub_dprintf ("pata", "opening PATA dev `ata%d'\n", devnum);
494 if (! devfnd)
495 return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such PATA device");
497 err = check_device (devfnd);
498 if (err)
499 return err;
501 ata->data = devfnd;
502 ata->dma = 0;
503 ata->maxbuffer = 256 * 512;
504 ata->present = &devfnd->present;
506 return GRUB_ERR_NONE;
509 static int
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)
516 return 0;
518 for (dev = grub_pata_devices; dev; dev = dev->next)
519 if (hook (GRUB_SCSI_SUBSYSTEM_PATA, dev->port * 2 + dev->device,
520 hook_data))
521 return 1;
523 return 0;
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);