Blame view
drivers/mtd/st_smi.c
13.6 KB
a6e34f76c SPEAr : smi drive... |
1 2 |
/* * (C) Copyright 2009 |
f3fcf92d5 st_smi: Add suppo... |
3 |
* Vipin Kumar, ST Microelectronics, vipin.kumar@st.com. |
a6e34f76c SPEAr : smi drive... |
4 |
* |
1a4596601 Add GPL-2.0+ SPDX... |
5 |
* SPDX-License-Identifier: GPL-2.0+ |
a6e34f76c SPEAr : smi drive... |
6 7 8 9 10 |
*/ #include <common.h> #include <flash.h> #include <linux/err.h> |
f3fcf92d5 st_smi: Add suppo... |
11 |
#include <linux/mtd/st_smi.h> |
a6e34f76c SPEAr : smi drive... |
12 13 14 |
#include <asm/io.h> #include <asm/arch/hardware.h> |
a6e34f76c SPEAr : smi drive... |
15 16 17 18 19 20 21 22 |
#if !defined(CONFIG_SYS_NO_FLASH) static struct smi_regs *const smicntl = (struct smi_regs * const)CONFIG_SYS_SMI_BASE; static ulong bank_base[CONFIG_SYS_MAX_FLASH_BANKS] = CONFIG_SYS_FLASH_ADDR_BASE; flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; |
6d6d23c14 st_smi: Change th... |
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
/* data structure to maintain flash ids from different vendors */ struct flash_device { char *name; u8 erase_cmd; u32 device_id; u32 pagesize; unsigned long sectorsize; unsigned long size_in_bytes; }; #define FLASH_ID(n, es, id, psize, ssize, size) \ { \ .name = n, \ .erase_cmd = es, \ .device_id = id, \ .pagesize = psize, \ .sectorsize = ssize, \ .size_in_bytes = size \ } /* * List of supported flash devices. * Currently the erase_cmd field is not used in this driver. */ static struct flash_device flash_devices[] = { FLASH_ID("st m25p16" , 0xd8, 0x00152020, 0x100, 0x10000, 0x200000), FLASH_ID("st m25p32" , 0xd8, 0x00162020, 0x100, 0x10000, 0x400000), FLASH_ID("st m25p64" , 0xd8, 0x00172020, 0x100, 0x10000, 0x800000), FLASH_ID("st m25p128" , 0xd8, 0x00182020, 0x100, 0x40000, 0x1000000), FLASH_ID("st m25p05" , 0xd8, 0x00102020, 0x80 , 0x8000 , 0x10000), FLASH_ID("st m25p10" , 0xd8, 0x00112020, 0x80 , 0x8000 , 0x20000), FLASH_ID("st m25p20" , 0xd8, 0x00122020, 0x100, 0x10000, 0x40000), FLASH_ID("st m25p40" , 0xd8, 0x00132020, 0x100, 0x10000, 0x80000), FLASH_ID("st m25p80" , 0xd8, 0x00142020, 0x100, 0x10000, 0x100000), FLASH_ID("st m45pe10" , 0xd8, 0x00114020, 0x100, 0x10000, 0x20000), FLASH_ID("st m45pe20" , 0xd8, 0x00124020, 0x100, 0x10000, 0x40000), FLASH_ID("st m45pe40" , 0xd8, 0x00134020, 0x100, 0x10000, 0x80000), FLASH_ID("st m45pe80" , 0xd8, 0x00144020, 0x100, 0x10000, 0x100000), FLASH_ID("sp s25fl004" , 0xd8, 0x00120201, 0x100, 0x10000, 0x80000), FLASH_ID("sp s25fl008" , 0xd8, 0x00130201, 0x100, 0x10000, 0x100000), FLASH_ID("sp s25fl016" , 0xd8, 0x00140201, 0x100, 0x10000, 0x200000), FLASH_ID("sp s25fl032" , 0xd8, 0x00150201, 0x100, 0x10000, 0x400000), FLASH_ID("sp s25fl064" , 0xd8, 0x00160201, 0x100, 0x10000, 0x800000), FLASH_ID("mac 25l512" , 0xd8, 0x001020C2, 0x010, 0x10000, 0x10000), FLASH_ID("mac 25l1005" , 0xd8, 0x001120C2, 0x010, 0x10000, 0x20000), FLASH_ID("mac 25l2005" , 0xd8, 0x001220C2, 0x010, 0x10000, 0x40000), FLASH_ID("mac 25l4005" , 0xd8, 0x001320C2, 0x010, 0x10000, 0x80000), FLASH_ID("mac 25l4005a" , 0xd8, 0x001320C2, 0x010, 0x10000, 0x80000), FLASH_ID("mac 25l8005" , 0xd8, 0x001420C2, 0x010, 0x10000, 0x100000), FLASH_ID("mac 25l1605" , 0xd8, 0x001520C2, 0x100, 0x10000, 0x200000), FLASH_ID("mac 25l1605a" , 0xd8, 0x001520C2, 0x010, 0x10000, 0x200000), FLASH_ID("mac 25l3205" , 0xd8, 0x001620C2, 0x100, 0x10000, 0x400000), FLASH_ID("mac 25l3205a" , 0xd8, 0x001620C2, 0x100, 0x10000, 0x400000), FLASH_ID("mac 25l6405" , 0xd8, 0x001720C2, 0x100, 0x10000, 0x800000), |
926407763 st_smi: Fixed pag... |
77 |
FLASH_ID("wbd w25q128" , 0xd8, 0x001840EF, 0x100, 0x10000, 0x1000000), |
a6e34f76c SPEAr : smi drive... |
78 79 80 81 82 83 84 85 |
}; /* * smi_wait_xfer_finish - Wait until TFF is set in status register * @timeout: timeout in milliseconds * * Wait until TFF is set in status register */ |
5c16c5412 st_smi: Return er... |
86 |
static int smi_wait_xfer_finish(int timeout) |
a6e34f76c SPEAr : smi drive... |
87 |
{ |
b5992fac8 st_smi: Change ti... |
88 89 90 |
ulong start = get_timer(0); while (get_timer(start) < timeout) { |
a6e34f76c SPEAr : smi drive... |
91 |
if (readl(&smicntl->smi_sr) & TFF) |
5c16c5412 st_smi: Return er... |
92 |
return 0; |
b5992fac8 st_smi: Change ti... |
93 94 95 96 |
/* Try after 10 ms */ udelay(10); }; |
5c16c5412 st_smi: Return er... |
97 98 |
return -1; |
a6e34f76c SPEAr : smi drive... |
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
} /* * smi_read_id - Read flash id * @info: flash_info structure pointer * @banknum: bank number * * Read the flash id present at bank #banknum */ static unsigned int smi_read_id(flash_info_t *info, int banknum) { unsigned int value; writel(readl(&smicntl->smi_cr1) | SW_MODE, &smicntl->smi_cr1); writel(READ_ID, &smicntl->smi_tr); writel((banknum << BANKSEL_SHIFT) | SEND | TX_LEN_1 | RX_LEN_3, &smicntl->smi_cr2); |
f3fcf92d5 st_smi: Add suppo... |
116 |
|
5c16c5412 st_smi: Return er... |
117 118 |
if (smi_wait_xfer_finish(XFER_FINISH_TOUT)) return -EIO; |
a6e34f76c SPEAr : smi drive... |
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
value = (readl(&smicntl->smi_rr) & 0x00FFFFFF); writel(readl(&smicntl->smi_sr) & ~TFF, &smicntl->smi_sr); writel(readl(&smicntl->smi_cr1) & ~SW_MODE, &smicntl->smi_cr1); return value; } /* * flash_get_size - Detect the SMI flash by reading the ID. * @base: Base address of the flash area bank #banknum * @banknum: Bank number * * Detect the SMI flash by reading the ID. Initializes the flash_info structure * with size, sector count etc. */ static ulong flash_get_size(ulong base, int banknum) { flash_info_t *info = &flash_info[banknum]; |
69fcb55f7 st_smi: Enhance t... |
139 |
int value; |
a6e34f76c SPEAr : smi drive... |
140 141 142 |
int i; value = smi_read_id(info, banknum); |
69fcb55f7 st_smi: Enhance t... |
143 144 145 146 147 148 |
if (value < 0) { printf("Flash id could not be read "); return 0; } |
6d6d23c14 st_smi: Change th... |
149 150 151 152 153 154 155 156 |
/* Matches chip-id to entire list of 'serial-nor flash' ids */ for (i = 0; i < ARRAY_SIZE(flash_devices); i++) { if (flash_devices[i].device_id == value) { info->size = flash_devices[i].size_in_bytes; info->flash_id = value; info->start[0] = base; info->sector_count = info->size/flash_devices[i].sectorsize; |
a6e34f76c SPEAr : smi drive... |
157 |
|
6d6d23c14 st_smi: Change th... |
158 |
return info->size; |
a6e34f76c SPEAr : smi drive... |
159 160 |
} } |
6d6d23c14 st_smi: Change th... |
161 |
return 0; |
a6e34f76c SPEAr : smi drive... |
162 163 164 165 166 167 168 169 170 |
} /* * smi_read_sr - Read status register of SMI * @bank: bank number * * This routine will get the status register of the flash chip present at the * given bank */ |
69fcb55f7 st_smi: Enhance t... |
171 |
static int smi_read_sr(int bank) |
a6e34f76c SPEAr : smi drive... |
172 |
{ |
a59c7b37b st_smi: Move stat... |
173 |
u32 ctrlreg1, val; |
a6e34f76c SPEAr : smi drive... |
174 175 176 177 178 179 180 181 182 183 |
/* store the CTRL REG1 state */ ctrlreg1 = readl(&smicntl->smi_cr1); /* Program SMI in HW Mode */ writel(readl(&smicntl->smi_cr1) & ~(SW_MODE | WB_MODE), &smicntl->smi_cr1); /* Performing a RSR instruction in HW mode */ writel((bank << BANKSEL_SHIFT) | RD_STATUS_REG, &smicntl->smi_cr2); |
5c16c5412 st_smi: Return er... |
184 185 |
if (smi_wait_xfer_finish(XFER_FINISH_TOUT)) return -1; |
a6e34f76c SPEAr : smi drive... |
186 |
|
a59c7b37b st_smi: Move stat... |
187 |
val = readl(&smicntl->smi_sr); |
a6e34f76c SPEAr : smi drive... |
188 189 |
/* Restore the CTRL REG1 state */ writel(ctrlreg1, &smicntl->smi_cr1); |
a59c7b37b st_smi: Move stat... |
190 |
return val; |
a6e34f76c SPEAr : smi drive... |
191 192 193 194 195 196 197 198 199 200 201 202 203 |
} /* * smi_wait_till_ready - Wait till last operation is over. * @bank: bank number shifted. * @timeout: timeout in milliseconds. * * This routine checks for WIP(write in progress)bit in Status register(SMSR-b0) * The routine checks for #timeout loops, each at interval of 1 milli-second. * If successful the routine returns 0. */ static int smi_wait_till_ready(int bank, int timeout) { |
69fcb55f7 st_smi: Enhance t... |
204 |
int sr; |
b5992fac8 st_smi: Change ti... |
205 |
ulong start = get_timer(0); |
a6e34f76c SPEAr : smi drive... |
206 207 208 |
/* One chip guarantees max 5 msec wait here after page writes, but potentially three seconds (!) after page erase. */ |
b5992fac8 st_smi: Change ti... |
209 |
while (get_timer(start) < timeout) { |
a6e34f76c SPEAr : smi drive... |
210 |
sr = smi_read_sr(bank); |
a5ad7ccd7 st_smi: Fix smi r... |
211 |
if ((sr >= 0) && (!(sr & WIP_BIT))) |
a6e34f76c SPEAr : smi drive... |
212 |
return 0; |
b5992fac8 st_smi: Change ti... |
213 214 |
/* Try again after 10 usec */ udelay(10); |
69fcb55f7 st_smi: Enhance t... |
215 |
} while (timeout--); |
a6e34f76c SPEAr : smi drive... |
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
printf("SMI controller is still in wait, timeout=%d ", timeout); return -EIO; } /* * smi_write_enable - Enable the flash to do write operation * @bank: bank number * * Set write enable latch with Write Enable command. * Returns negative if error occurred. */ static int smi_write_enable(int bank) { u32 ctrlreg1; |
b5992fac8 st_smi: Change ti... |
231 |
u32 start; |
a6e34f76c SPEAr : smi drive... |
232 |
int timeout = WMODE_TOUT; |
69fcb55f7 st_smi: Enhance t... |
233 |
int sr; |
a6e34f76c SPEAr : smi drive... |
234 235 236 237 238 239 240 241 242 |
/* Store the CTRL REG1 state */ ctrlreg1 = readl(&smicntl->smi_cr1); /* Program SMI in H/W Mode */ writel(readl(&smicntl->smi_cr1) & ~SW_MODE, &smicntl->smi_cr1); /* Give the Flash, Write Enable command */ writel((bank << BANKSEL_SHIFT) | WE, &smicntl->smi_cr2); |
5c16c5412 st_smi: Return er... |
243 244 |
if (smi_wait_xfer_finish(XFER_FINISH_TOUT)) return -1; |
a6e34f76c SPEAr : smi drive... |
245 246 247 |
/* Restore the CTRL REG1 state */ writel(ctrlreg1, &smicntl->smi_cr1); |
b5992fac8 st_smi: Change ti... |
248 249 |
start = get_timer(0); while (get_timer(start) < timeout) { |
69fcb55f7 st_smi: Enhance t... |
250 |
sr = smi_read_sr(bank); |
a5ad7ccd7 st_smi: Fix smi r... |
251 |
if ((sr >= 0) && (sr & (1 << (bank + WM_SHIFT)))) |
69fcb55f7 st_smi: Enhance t... |
252 |
return 0; |
a6e34f76c SPEAr : smi drive... |
253 |
|
b5992fac8 st_smi: Change ti... |
254 255 256 |
/* Try again after 10 usec */ udelay(10); }; |
a6e34f76c SPEAr : smi drive... |
257 258 259 260 261 262 263 264 265 |
return -1; } /* * smi_init - SMI initialization routine * * SMI initialization routine. Sets SMI control register1. */ |
f3fcf92d5 st_smi: Add suppo... |
266 |
void smi_init(void) |
a6e34f76c SPEAr : smi drive... |
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 |
{ /* Setting the fast mode values. SMI working at 166/4 = 41.5 MHz */ writel(HOLD1 | FAST_MODE | BANK_EN | DSEL_TIME | PRESCAL4, &smicntl->smi_cr1); } /* * smi_sector_erase - Erase flash sector * @info: flash_info structure pointer * @sector: sector number * * Set write enable latch with Write Enable command. * Returns negative if error occurred. */ static int smi_sector_erase(flash_info_t *info, unsigned int sector) { int bank; unsigned int sect_add; unsigned int instruction; switch (info->start[0]) { case SMIBANK0_BASE: bank = BANK0; break; case SMIBANK1_BASE: bank = BANK1; break; case SMIBANK2_BASE: bank = BANK2; break; case SMIBANK3_BASE: bank = BANK3; break; default: return -1; } sect_add = sector * (info->size / info->sector_count); instruction = ((sect_add >> 8) & 0x0000FF00) | SECTOR_ERASE; writel(readl(&smicntl->smi_sr) & ~(ERF1 | ERF2), &smicntl->smi_sr); |
ae3e0cc92 st_smi: Removed n... |
308 309 310 |
/* Wait until finished previous write command. */ if (smi_wait_till_ready(bank, CONFIG_SYS_FLASH_ERASE_TOUT)) return -EBUSY; |
a6e34f76c SPEAr : smi drive... |
311 |
|
ae3e0cc92 st_smi: Removed n... |
312 313 314 |
/* Send write enable, before erase commands. */ if (smi_write_enable(bank)) return -EIO; |
a6e34f76c SPEAr : smi drive... |
315 |
|
ae3e0cc92 st_smi: Removed n... |
316 317 |
/* Put SMI in SW mode */ writel(readl(&smicntl->smi_cr1) | SW_MODE, &smicntl->smi_cr1); |
a6e34f76c SPEAr : smi drive... |
318 |
|
ae3e0cc92 st_smi: Removed n... |
319 320 321 |
/* Send Sector Erase command in SW Mode */ writel(instruction, &smicntl->smi_tr); writel((bank << BANKSEL_SHIFT) | SEND | TX_LEN_4, |
a6e34f76c SPEAr : smi drive... |
322 |
&smicntl->smi_cr2); |
ae3e0cc92 st_smi: Removed n... |
323 324 |
if (smi_wait_xfer_finish(XFER_FINISH_TOUT)) return -EIO; |
a6e34f76c SPEAr : smi drive... |
325 |
|
ae3e0cc92 st_smi: Removed n... |
326 327 |
if (smi_wait_till_ready(bank, CONFIG_SYS_FLASH_ERASE_TOUT)) return -EBUSY; |
a6e34f76c SPEAr : smi drive... |
328 |
|
ae3e0cc92 st_smi: Removed n... |
329 330 |
/* Put SMI in HW mode */ writel(readl(&smicntl->smi_cr1) & ~SW_MODE, |
a6e34f76c SPEAr : smi drive... |
331 |
&smicntl->smi_cr1); |
ae3e0cc92 st_smi: Removed n... |
332 |
return 0; |
a6e34f76c SPEAr : smi drive... |
333 334 335 336 337 338 |
} /* * smi_write - Write to SMI flash * @src_addr: source buffer * @dst_addr: destination buffer |
185b3b76a MTD: SPEAr SMI: A... |
339 |
* @length: length to write in bytes |
a6e34f76c SPEAr : smi drive... |
340 341 342 343 344 345 346 |
* @bank: bank base address * * Write to SMI flash */ static int smi_write(unsigned int *src_addr, unsigned int *dst_addr, unsigned int length, ulong bank_addr) { |
185b3b76a MTD: SPEAr SMI: A... |
347 348 |
u8 *src_addr8 = (u8 *)src_addr; u8 *dst_addr8 = (u8 *)dst_addr; |
a6e34f76c SPEAr : smi drive... |
349 |
int banknum; |
185b3b76a MTD: SPEAr SMI: A... |
350 |
int i; |
a6e34f76c SPEAr : smi drive... |
351 352 353 354 |
switch (bank_addr) { case SMIBANK0_BASE: banknum = BANK0; |
a6e34f76c SPEAr : smi drive... |
355 356 357 |
break; case SMIBANK1_BASE: banknum = BANK1; |
a6e34f76c SPEAr : smi drive... |
358 359 360 |
break; case SMIBANK2_BASE: banknum = BANK2; |
a6e34f76c SPEAr : smi drive... |
361 362 363 |
break; case SMIBANK3_BASE: banknum = BANK3; |
a6e34f76c SPEAr : smi drive... |
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 |
break; default: return -1; } if (smi_wait_till_ready(banknum, CONFIG_SYS_FLASH_WRITE_TOUT)) return -EBUSY; /* Set SMI in Hardware Mode */ writel(readl(&smicntl->smi_cr1) & ~SW_MODE, &smicntl->smi_cr1); if (smi_write_enable(banknum)) return -EIO; /* Perform the write command */ |
185b3b76a MTD: SPEAr SMI: A... |
379 |
for (i = 0; i < length; i += 4) { |
a6e34f76c SPEAr : smi drive... |
380 381 382 383 384 385 386 387 |
if (((ulong) (dst_addr) % SFLASH_PAGE_SIZE) == 0) { if (smi_wait_till_ready(banknum, CONFIG_SYS_FLASH_WRITE_TOUT)) return -EBUSY; if (smi_write_enable(banknum)) return -EIO; } |
185b3b76a MTD: SPEAr SMI: A... |
388 389 390 391 392 393 394 395 396 397 398 399 |
if (length < 4) { int k; /* * Handle special case, where length < 4 (redundant env) */ for (k = 0; k < length; k++) *dst_addr8++ = *src_addr8++; } else { /* Normal 32bit write */ *dst_addr++ = *src_addr++; } |
a6e34f76c SPEAr : smi drive... |
400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 |
if ((readl(&smicntl->smi_sr) & (ERF1 | ERF2))) return -EIO; } if (smi_wait_till_ready(banknum, CONFIG_SYS_FLASH_WRITE_TOUT)) return -EBUSY; writel(readl(&smicntl->smi_sr) & ~(WCF), &smicntl->smi_sr); return 0; } /* * write_buff - Write to SMI flash * @info: flash info structure * @src: source buffer * @dest_addr: destination buffer * @length: length to write in words * * Write to SMI flash */ int write_buff(flash_info_t *info, uchar *src, ulong dest_addr, ulong length) { return smi_write((unsigned int *)src, (unsigned int *)dest_addr, |
185b3b76a MTD: SPEAr SMI: A... |
425 |
length, info->start[0]); |
a6e34f76c SPEAr : smi drive... |
426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 |
} /* * flash_init - SMI flash initialization * * SMI flash initialization */ unsigned long flash_init(void) { unsigned long size = 0; int i, j; smi_init(); for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) { flash_info[i].flash_id = FLASH_UNKNOWN; size += flash_info[i].size = flash_get_size(bank_base[i], i); } for (j = 0; j < CONFIG_SYS_MAX_FLASH_BANKS; j++) { for (i = 1; i < flash_info[j].sector_count; i++) flash_info[j].start[i] = flash_info[j].start[i - 1] + flash_info->size / flash_info->sector_count; } return size; } /* * flash_print_info - Print SMI flash information * * Print SMI flash information */ void flash_print_info(flash_info_t *info) { int i; if (info->flash_id == FLASH_UNKNOWN) { puts("missing or unknown FLASH type "); return; } |
cf9026deb st_smi: Fix bug i... |
469 470 471 472 473 474 475 476 477 |
if (info->size >= 0x100000) printf(" Size: %ld MB in %d Sectors ", info->size >> 20, info->sector_count); else printf(" Size: %ld KB in %d Sectors ", info->size >> 10, info->sector_count); |
a6e34f76c SPEAr : smi drive... |
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 |
puts(" Sector Start Addresses:"); for (i = 0; i < info->sector_count; ++i) { #ifdef CONFIG_SYS_FLASH_EMPTY_INFO int size; int erased; u32 *flash; /* * Check if whole sector is erased */ size = (info->size) / (info->sector_count); flash = (u32 *) info->start[i]; size = size / sizeof(int); while ((size--) && (*flash++ == ~0)) ; size++; if (size) erased = 0; else erased = 1; if ((i % 5) == 0) printf(" "); printf(" %08lX%s%s", info->start[i], erased ? " E" : " ", info->protect[i] ? "RO " : " "); #else if ((i % 5) == 0) printf(" "); printf(" %08lX%s", info->start[i], info->protect[i] ? " (RO) " : " "); #endif } putc(' '); return; } /* * flash_erase - Erase SMI flash * * Erase SMI flash */ int flash_erase(flash_info_t *info, int s_first, int s_last) { int rcode = 0; int prot = 0; flash_sect_t sect; |
a6e34f76c SPEAr : smi drive... |
532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 |
if ((s_first < 0) || (s_first > s_last)) { puts("- no sectors to erase "); return 1; } for (sect = s_first; sect <= s_last; ++sect) { if (info->protect[sect]) prot++; } if (prot) { printf("- Warning: %d protected sectors will not be erased! ", prot); } else { putc(' '); } for (sect = s_first; sect <= s_last; sect++) { if (info->protect[sect] == 0) { if (smi_sector_erase(info, sect)) rcode = 1; else putc('.'); } } puts(" done "); return rcode; } #endif |