blob: 29eeaee1fc791d42d02bc6009d52f61c217fc7f6 [file] [log] [blame]
Sundarajan Srinivasan15516f22013-12-04 17:11:36 -08001/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -07002 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <stdlib.h>
30#include <stdint.h>
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -070031#include <mmc_wrapper.h>
Channagoud Kadabia17fc422013-09-11 12:25:34 -070032#include <mmc_sdhci.h>
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -070033#include <sdhci.h>
Channagoud Kadabia17fc422013-09-11 12:25:34 -070034#include <ufs.h>
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -070035#include <target.h>
Oliver Wangcee448d2013-10-22 18:40:13 +080036#include <string.h>
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -070037
38/*
Channagoud Kadabia17fc422013-09-11 12:25:34 -070039 * Weak function for UFS.
40 * These are needed to avoid link errors for platforms which
41 * do not support UFS. Its better to keep this inside the
42 * mmc wrapper.
43 */
44__WEAK int ufs_write(struct ufs_dev *dev, uint64_t data_addr, addr_t in, uint32_t len)
45{
46 return 0;
47}
48
49__WEAK int ufs_read(struct ufs_dev *dev, uint64_t data_addr, addr_t in, uint32_t len)
50{
51 return 0;
52}
53
54__WEAK uint32_t ufs_get_page_size(struct ufs_dev *dev)
55{
56 return 0;
57}
58
59__WEAK uint32_t ufs_get_serial_num(struct ufs_dev *dev)
60{
61 return 0;
62}
63
64__WEAK uint64_t ufs_get_dev_capacity(struct ufs_dev *dev)
65{
66 return 0;
67}
68
Sundarajan Srinivasan7b74ed22013-11-01 16:01:06 -070069__WEAK uint32_t ufs_get_erase_blk_size(struct ufs_dev *dev)
70{
71 return 0;
72}
73
74__WEAK int ufs_erase(struct ufs_dev* dev, uint64_t start_lba, uint32_t num_blocks)
75{
76 return 0;
77}
Sundarajan Srinivasan15516f22013-12-04 17:11:36 -080078
79__WEAK uint8_t ufs_get_num_of_luns(struct ufs_dev* dev)
80{
81 return 0;
82}
83
Channagoud Kadabia17fc422013-09-11 12:25:34 -070084/*
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -070085 * Function: get mmc card
86 * Arg : None
87 * Return : Pointer to mmc card structure
88 * Flow : Get the card pointer from the device structure
89 */
90static struct mmc_card *get_mmc_card()
91{
Channagoud Kadabia17fc422013-09-11 12:25:34 -070092 void *dev;
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -070093 struct mmc_card *card;
94
95 dev = target_mmc_device();
Channagoud Kadabia17fc422013-09-11 12:25:34 -070096 card = &((struct mmc_device*)dev)->card;
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -070097
98 return card;
99}
100
101/*
102 * Function: mmc_write
103 * Arg : Data address on card, data length, i/p buffer
104 * Return : 0 on Success, non zero on failure
105 * Flow : Write the data from in to the card
106 */
107uint32_t mmc_write(uint64_t data_addr, uint32_t data_len, void *in)
108{
Channagoud Kadabi53f1be72013-06-05 17:56:11 -0700109 uint32_t val = 0;
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700110 int ret = 0;
111 uint32_t block_size = 0;
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700112 uint32_t write_size = SDHCI_ADMA_MAX_TRANS_SZ;
Channagoud Kadabi53f1be72013-06-05 17:56:11 -0700113 uint8_t *sptr = (uint8_t *)in;
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700114 void *dev;
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700115
116 dev = target_mmc_device();
117
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700118 block_size = mmc_get_device_blocksize();
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700119
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700120 ASSERT(!(data_addr % block_size));
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700121
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700122 if (data_len % block_size)
123 data_len = ROUNDUP(data_len, block_size);
124
125 if (target_boot_device_emmc())
126 {
127 /* TODO: This function is aware of max data that can be
128 * tranferred using sdhci adma mode, need to have a cleaner
129 * implementation to keep this function independent of sdhci
130 * limitations
131 */
132 while (data_len > write_size) {
133 val = mmc_sdhci_write((struct mmc_device *)dev, (void *)sptr, (data_addr / block_size), (write_size / block_size));
134 if (val)
135 {
136 dprintf(CRITICAL, "Failed Writing block @ %x\n", (data_addr / block_size));
137 return val;
138 }
139 sptr += write_size;
140 data_addr += write_size;
141 data_len -= write_size;
Channagoud Kadabi53f1be72013-06-05 17:56:11 -0700142 }
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700143
144 if (data_len)
145 val = mmc_sdhci_write((struct mmc_device *)dev, (void *)sptr, (data_addr / block_size), (data_len / block_size));
146
147 if (val)
148 dprintf(CRITICAL, "Failed Writing block @ %x\n", (data_addr / block_size));
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700149 }
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700150 else
151 {
152 arch_clean_invalidate_cache_range((addr_t)in, data_len);
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700153
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700154 ret = ufs_write((struct ufs_dev *)dev, data_addr, (addr_t)in, (data_len / block_size));
Channagoud Kadabi53f1be72013-06-05 17:56:11 -0700155
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700156 if (ret)
157 {
158 dprintf(CRITICAL, "Error: UFS write failed writing to block: %llu\n", data_addr);
159 val = 1;
160 }
161 }
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700162
163 return val;
164}
165
166/*
167 * Function: mmc_read
168 * Arg : Data address on card, o/p buffer & data length
169 * Return : 0 on Success, non zero on failure
170 * Flow : Read data from the card to out
171 */
172uint32_t mmc_read(uint64_t data_addr, uint32_t *out, uint32_t data_len)
173{
174 uint32_t ret = 0;
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700175 uint32_t block_size;
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700176 uint32_t read_size = SDHCI_ADMA_MAX_TRANS_SZ;
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700177 void *dev;
Channagoud Kadabi53f1be72013-06-05 17:56:11 -0700178 uint8_t *sptr = (uint8_t *)out;
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700179
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700180 dev = target_mmc_device();
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700181 block_size = mmc_get_device_blocksize();
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700182
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700183 ASSERT(!(data_addr % block_size));
184 ASSERT(!(data_len % block_size));
185
186
187 if (target_boot_device_emmc())
188 {
189 /* TODO: This function is aware of max data that can be
190 * tranferred using sdhci adma mode, need to have a cleaner
191 * implementation to keep this function independent of sdhci
192 * limitations
193 */
194 while (data_len > read_size) {
195 ret = mmc_sdhci_read((struct mmc_device *)dev, (void *)sptr, (data_addr / block_size), (read_size / block_size));
196 if (ret)
197 {
198 dprintf(CRITICAL, "Failed Reading block @ %x\n", (data_addr / block_size));
199 return ret;
200 }
201 sptr += read_size;
202 data_addr += read_size;
203 data_len -= read_size;
204 }
205
206 if (data_len)
207 ret = mmc_sdhci_read((struct mmc_device *)dev, (void *)sptr, (data_addr / block_size), (data_len / block_size));
208
209 if (ret)
210 dprintf(CRITICAL, "Failed Reading block @ %x\n", (data_addr / block_size));
211 }
212 else
213 {
214 ret = ufs_read((struct ufs_dev *) dev, data_addr, (addr_t)out, (data_len / block_size));
Channagoud Kadabi53f1be72013-06-05 17:56:11 -0700215 if (ret)
216 {
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700217 dprintf(CRITICAL, "Error: UFS read failed writing to block: %llu\n", data_addr);
Channagoud Kadabi53f1be72013-06-05 17:56:11 -0700218 }
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700219
220 arch_invalidate_cache_range((addr_t)out, data_len);
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700221 }
222
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700223 return ret;
224}
225
Sundarajan Srinivasan7b74ed22013-11-01 16:01:06 -0700226
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700227/*
Oliver Wangcee448d2013-10-22 18:40:13 +0800228 * Function: mmc get erase unit size
229 * Arg : None
230 * Return : Returns the erase unit size of the storage
231 * Flow : Get the erase unit size from the card
232 */
233
234uint32_t mmc_get_eraseunit_size()
235{
236 uint32_t erase_unit_sz = 0;
237
238 if (target_boot_device_emmc()) {
239 struct mmc_device *dev;
240 struct mmc_card *card;
241
242 dev = target_mmc_device();
243 card = &dev->card;
244 /*
245 * Calculate the erase unit size,
246 * 1. Based on emmc 4.5 spec for emmc card
247 * 2. Use SD Card Status info for SD cards
248 */
249 if (MMC_CARD_MMC(card))
250 {
251 /*
252 * Calculate the erase unit size as per the emmc specification v4.5
253 */
254 if (dev->card.ext_csd[MMC_ERASE_GRP_DEF])
255 erase_unit_sz = (MMC_HC_ERASE_MULT * dev->card.ext_csd[MMC_HC_ERASE_GRP_SIZE]) / MMC_BLK_SZ;
256 else
257 erase_unit_sz = (dev->card.csd.erase_grp_size + 1) * (dev->card.csd.erase_grp_mult + 1);
258 }
259 else
260 erase_unit_sz = dev->card.ssr.au_size * dev->card.ssr.num_aus;
261 }
262
263 return erase_unit_sz;
264}
265
266/*
267 * Function: Zero out blk_len blocks at the blk_addr by writing zeros. The
268 * function can be used when we want to erase the blocks not
269 * aligned with the mmc erase group.
270 * Arg : Block address & length
271 * Return : Returns 0
272 * Flow : Erase the card from specified addr
273 */
274
275static uint32_t mmc_zero_out(struct mmc_device* dev, uint32_t blk_addr, uint32_t num_blks)
276{
277 uint32_t *out;
278 uint32_t block_size;
279 int i;
280
281 dprintf(INFO, "erasing 0x%x:0x%x\n", blk_addr, num_blks);
282 block_size = mmc_get_device_blocksize();
283
284 /* Assume there are at least block_size bytes available in the heap */
285 out = memalign(CACHE_LINE, ROUNDUP(block_size, CACHE_LINE));
286
287 if (!out)
288 {
289 dprintf(CRITICAL, "Error allocating memory\n");
290 return 1;
291 }
292 memset((void *)out, 0, ROUNDUP(block_size, CACHE_LINE));
293
294 for (i = 0; i < num_blks; i++)
295 {
296 if (mmc_sdhci_write(dev, out, blk_addr + i, 1))
297 {
298 dprintf(CRITICAL, "failed to erase the partition: %x\n", blk_addr);
299 free(out);
300 return 1;
301 }
302 }
303 free(out);
304 return 0;
305}
306
307/*
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700308 * Function: mmc erase card
309 * Arg : Block address & length
310 * Return : Returns 0
Channagoud Kadabid87c6b12013-05-29 15:22:03 -0700311 * Flow : Erase the card from specified addr
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700312 */
313uint32_t mmc_erase_card(uint64_t addr, uint64_t len)
314{
Oliver Wangcee448d2013-10-22 18:40:13 +0800315 struct mmc_device *dev;
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700316 uint32_t block_size;
Oliver Wangcee448d2013-10-22 18:40:13 +0800317 uint32_t unaligned_blks;
318 uint32_t head_unit;
319 uint32_t tail_unit;
320 uint32_t erase_unit_sz;
321 uint32_t blk_addr;
322 uint32_t blk_count;
323 uint64_t blks_to_erase;
Channagoud Kadabid87c6b12013-05-29 15:22:03 -0700324
Sundarajan Srinivasan7b74ed22013-11-01 16:01:06 -0700325 block_size = mmc_get_device_blocksize();
326
327 dev = target_mmc_device();
328
329 ASSERT(!(addr % block_size));
330 ASSERT(!(len % block_size));
331
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700332 if (target_boot_device_emmc())
Channagoud Kadabid87c6b12013-05-29 15:22:03 -0700333 {
Oliver Wangcee448d2013-10-22 18:40:13 +0800334 erase_unit_sz = mmc_get_eraseunit_size();
335 dprintf(SPEW, "erase_unit_sz:0x%x\n", erase_unit_sz);
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700336
Oliver Wangcee448d2013-10-22 18:40:13 +0800337 blk_addr = addr / block_size;
338 blk_count = len / block_size;
339
Oliver Wangcee448d2013-10-22 18:40:13 +0800340 dprintf(INFO, "Erasing card: 0x%x:0x%x\n", blk_addr, blk_count);
341
342 head_unit = blk_addr / erase_unit_sz;
343 tail_unit = (blk_addr + blk_count - 1) / erase_unit_sz;
344
345 if (tail_unit - head_unit <= 1)
346 {
347 dprintf(INFO, "SDHCI unit erase not required\n");
348 return mmc_zero_out(dev, blk_addr, blk_count);
349 }
350
351 unaligned_blks = erase_unit_sz - (blk_addr % erase_unit_sz);
352
353 if (unaligned_blks < erase_unit_sz)
354 {
355 dprintf(SPEW, "Handling unaligned head blocks\n");
356 if (mmc_zero_out(dev, blk_addr, unaligned_blks))
357 return 1;
358
359 blk_addr += unaligned_blks;
360 blk_count -= unaligned_blks;
361 }
362
363 unaligned_blks = blk_count % erase_unit_sz;
364 blks_to_erase = blk_count - unaligned_blks;
365
366 dprintf(SPEW, "Performing SDHCI erase: 0x%x:0x%x\n", blk_addr, blks_to_erase);
367 if (mmc_sdhci_erase((struct mmc_device *)dev, blk_addr, blks_to_erase * block_size))
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700368 {
369 dprintf(CRITICAL, "MMC erase failed\n");
370 return 1;
371 }
Oliver Wangcee448d2013-10-22 18:40:13 +0800372
373 blk_addr += blks_to_erase;
374
375 if (unaligned_blks)
376 {
377 dprintf(SPEW, "Handling unaligned tail blocks\n");
378 if (mmc_zero_out(dev, blk_addr, unaligned_blks))
379 return 1;
380 }
381
Channagoud Kadabid87c6b12013-05-29 15:22:03 -0700382 }
Sundarajan Srinivasan7b74ed22013-11-01 16:01:06 -0700383 else
384 {
385 if(ufs_erase((struct ufs_dev *)dev, addr, (len / block_size)))
386 {
387 dprintf(CRITICAL, "mmc_erase_card: UFS erase failed\n");
388 return 1;
389 }
390 }
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700391
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700392 return 0;
393}
394
395/*
396 * Function: mmc get psn
397 * Arg : None
398 * Return : Returns the product serial number
399 * Flow : Get the PSN from card
400 */
401uint32_t mmc_get_psn(void)
402{
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700403 if (target_boot_device_emmc())
404 {
405 struct mmc_card *card;
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700406
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700407 card = get_mmc_card();
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700408
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700409 return card->cid.psn;
410 }
411 else
412 {
413 void *dev;
414
415 dev = target_mmc_device();
416
417 return ufs_get_serial_num((struct ufs_dev *)dev);
418 }
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700419}
420
421/*
422 * Function: mmc get capacity
423 * Arg : None
424 * Return : Returns the density of the emmc card
425 * Flow : Get the density from card
426 */
427uint64_t mmc_get_device_capacity()
428{
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700429 if (target_boot_device_emmc())
430 {
431 struct mmc_card *card;
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700432
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700433 card = get_mmc_card();
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700434
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700435 return card->capacity;
436 }
437 else
438 {
439 void *dev;
440
441 dev = target_mmc_device();
442
443 return ufs_get_dev_capacity((struct ufs_dev *)dev);
444 }
Channagoud Kadabi4ed511f2013-03-11 16:10:18 -0700445}
446
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700447/*
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700448 * Function: mmc get blocksize
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700449 * Arg : None
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700450 * Return : Returns the block size of the storage
451 * Flow : Get the block size form the card
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700452 */
453uint32_t mmc_get_device_blocksize()
454{
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700455 if (target_boot_device_emmc())
456 {
457 struct mmc_card *card;
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700458
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700459 card = get_mmc_card();
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700460
Channagoud Kadabia17fc422013-09-11 12:25:34 -0700461 return card->block_size;
462 }
463 else
464 {
465 void *dev;
466
467 dev = target_mmc_device();
468
469 return ufs_get_page_size((struct ufs_dev *)dev);
470 }
471}
472
473/*
474 * Function: storage page size
475 * Arg : None
476 * Return : Returns the page size for the card
477 * Flow : Get the page size for storage
478 */
479uint32_t mmc_page_size()
480{
481 if (target_boot_device_emmc())
482 {
483 return BOARD_KERNEL_PAGESIZE;
484 }
485 else
486 {
487 void *dev;
488
489 dev = target_mmc_device();
490
491 return ufs_get_page_size((struct ufs_dev *)dev);
492 }
493}
494
495/*
496 * Function: mmc device sleep
497 * Arg : None
498 * Return : Clean up function for storage
499 * Flow : Put the mmc card to sleep
500 */
501void mmc_device_sleep()
502{
503 void *dev;
504 dev = target_mmc_device();
505
506 if (target_boot_device_emmc())
507 {
508 mmc_put_card_to_sleep((struct mmc_device *)dev);
509 }
Channagoud Kadabi96c629e2013-09-10 14:21:30 -0700510}
Sundarajan Srinivasan15516f22013-12-04 17:11:36 -0800511
512/*
513 * Function : mmc set LUN for ufs
514 * Arg : LUN number
515 * Return type : void
516 */
517void mmc_set_lun(uint8_t lun)
518{
519 void *dev;
520 dev = target_mmc_device();
521
522 if (!target_boot_device_emmc())
523 {
524 ((struct ufs_dev*)dev)->current_lun = lun;
525 }
526}
527
528/*
529 * Function : mmc get LUN from ufs
530 * Arg : LUN number
531 * Return type : lun number for UFS and 0 for emmc
532 */
533uint8_t mmc_get_lun(void)
534{
535 void *dev;
536 uint8_t lun=0;
537
538 dev = target_mmc_device();
539
540 if (!target_boot_device_emmc())
541 {
542 lun = ((struct ufs_dev*)dev)->current_lun;
543 }
544
545 return lun;
546}
547
548void mmc_read_partition_table(uint8_t arg)
549{
550 void *dev;
551 uint8_t lun = 0;
552 uint8_t max_luns;
553
554 dev = target_mmc_device();
555
556 if(!target_boot_device_emmc())
557 {
558 max_luns = ufs_get_num_of_luns((struct ufs_dev*)dev);
559
560 ASSERT(max_luns);
561
562 for(lun = arg; lun < max_luns; lun++)
563 {
564 mmc_set_lun(lun);
565
566 if(partition_read_table())
567 {
568 dprintf(CRITICAL, "Error reading the partition table info for lun %d\n", lun);
569 }
570 }
571 }
572 else
573 {
574 if(partition_read_table())
575 {
576 dprintf(CRITICAL, "Error reading the partition table info\n");
577 }
578 }
579}