Updated PCI IDs to latest snapshot.
[tangerine.git] / arch / common / boot / grub2 / disk / ieee1275 / nand.c
blobba79faa544d95223543d0988118a7a867fc004fa
1 /* nand.c - NAND flash disk access. */
2 /*
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2008 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/misc.h>
21 #include <grub/disk.h>
22 #include <grub/mm.h>
23 #include <grub/dl.h>
24 #include <grub/ieee1275/ieee1275.h>
26 struct grub_nand_data
28 grub_ieee1275_ihandle_t handle;
29 grub_uint32_t block_size;
32 static int
33 grub_nand_iterate (int (*hook) (const char *name))
35 auto int dev_iterate (struct grub_ieee1275_devalias *alias);
36 int dev_iterate (struct grub_ieee1275_devalias *alias)
38 if (! grub_strcmp (alias->name, "nand"))
40 hook (alias->name);
41 return 1;
44 return 0;
47 grub_devalias_iterate (dev_iterate);
48 return 0;
51 static grub_err_t
52 grub_nand_read (grub_disk_t disk, grub_disk_addr_t sector,
53 grub_size_t size, char *buf);
55 static grub_err_t
56 grub_nand_open (const char *name, grub_disk_t disk)
58 grub_ieee1275_ihandle_t dev_ihandle = 0;
59 struct grub_nand_data *data = 0;
60 struct size_args
62 struct grub_ieee1275_common_hdr common;
63 char *method;
64 grub_ieee1275_ihandle_t ihandle;
65 grub_ieee1275_cell_t result;
66 grub_ieee1275_cell_t size1;
67 grub_ieee1275_cell_t size2;
68 } args;
70 if (! grub_strstr (name, "nand"))
71 return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Not a nand device");
73 data = grub_malloc (sizeof (*data));
74 if (! data)
75 goto fail;
77 grub_ieee1275_open (name, &dev_ihandle);
78 if (! dev_ihandle)
80 grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Can't open device");
81 goto fail;
84 data->handle = dev_ihandle;
86 INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 2);
87 args.method = "block-size";
88 args.ihandle = dev_ihandle;
89 args.result = 1;
91 if ((IEEE1275_CALL_ENTRY_FN (&args) == -1) || (args.result))
93 grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Can't get block size");
94 goto fail;
97 data->block_size = (args.size1 >> GRUB_DISK_SECTOR_BITS);
99 INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 3);
100 args.method = "size";
101 args.ihandle = dev_ihandle;
102 args.result = 1;
104 if ((IEEE1275_CALL_ENTRY_FN (&args) == -1) || (args.result))
106 grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Can't get disk size");
107 goto fail;
110 disk->total_sectors = args.size1;
111 disk->total_sectors <<= 32;
112 disk->total_sectors += args.size2;
113 disk->total_sectors >>= GRUB_DISK_SECTOR_BITS;
115 disk->id = dev_ihandle;
117 disk->has_partitions = 0;
118 disk->data = data;
120 return 0;
122 fail:
123 if (dev_ihandle)
124 grub_ieee1275_close (dev_ihandle);
125 grub_free (data);
126 return grub_errno;
129 static void
130 grub_nand_close (grub_disk_t disk)
132 grub_ieee1275_close (((struct grub_nand_data *) disk->data)->handle);
133 grub_free (disk->data);
136 static grub_err_t
137 grub_nand_read (grub_disk_t disk, grub_disk_addr_t sector,
138 grub_size_t size, char *buf)
140 struct grub_nand_data *data = disk->data;
141 grub_size_t bsize, ofs;
143 struct read_args
145 struct grub_ieee1275_common_hdr common;
146 char *method;
147 grub_ieee1275_ihandle_t ihandle;
148 grub_ieee1275_cell_t ofs;
149 grub_ieee1275_cell_t page;
150 grub_ieee1275_cell_t len;
151 grub_ieee1275_cell_t buf;
152 grub_ieee1275_cell_t result;
153 } args;
155 INIT_IEEE1275_COMMON (&args.common, "call-method", 6, 1);
156 args.method = "pio-read";
157 args.ihandle = data->handle;
158 args.buf = (grub_ieee1275_cell_t) buf;
159 args.page = (grub_ieee1275_cell_t) ((grub_size_t) sector / data->block_size);
161 ofs = ((grub_size_t) sector % data->block_size) << GRUB_DISK_SECTOR_BITS;
162 size <<= GRUB_DISK_SECTOR_BITS;
163 bsize = (data->block_size << GRUB_DISK_SECTOR_BITS);
167 grub_size_t len;
169 len = (ofs + size > bsize) ? (bsize - ofs) : size;
171 args.len = (grub_ieee1275_cell_t) len;
172 args.ofs = (grub_ieee1275_cell_t) ofs;
173 args.result = 1;
175 if ((IEEE1275_CALL_ENTRY_FN (&args) == -1) || (args.result))
176 return grub_error (GRUB_ERR_READ_ERROR, "Read error");
178 ofs = 0;
179 size -= len;
180 args.buf += len;
181 args.page++;
182 } while (size);
184 return GRUB_ERR_NONE;
187 static grub_err_t
188 grub_nand_write (grub_disk_t disk __attribute ((unused)),
189 grub_disk_addr_t sector __attribute ((unused)),
190 grub_size_t size __attribute ((unused)),
191 const char *buf __attribute ((unused)))
193 return GRUB_ERR_NOT_IMPLEMENTED_YET;
196 static struct grub_disk_dev grub_nand_dev =
198 .name = "nand",
199 .id = GRUB_DISK_DEVICE_NAND_ID,
200 .iterate = grub_nand_iterate,
201 .open = grub_nand_open,
202 .close = grub_nand_close,
203 .read = grub_nand_read,
204 .write = grub_nand_write,
205 .next = 0
208 GRUB_MOD_INIT(nand)
210 grub_disk_dev_register (&grub_nand_dev);
213 GRUB_MOD_FINI(nand)
215 grub_disk_dev_unregister (&grub_nand_dev);