4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * This file contains the routines for the IDE drive interface
31 #include <sys/types.h>
32 #include <sys/param.h>
33 #include <sys/ioctl.h>
35 #include <sys/fcntl.h>
41 #include <sys/byteorder.h>
44 #include <sys/dktp/altsctr.h>
46 #include <sys/dktp/dadkio.h>
57 #include "menu_fdisk.h"
64 static int ata_ck_format(void);
66 static int ata_ex_cur(struct defect_list
*);
67 static int ata_wr_cur(struct defect_list
*);
68 static int ata_repair(diskaddr_t
, int);
71 static int ata_ck_format();
73 static int ata_ex_cur();
74 static int ata_wr_cur();
75 static int ata_repair();
79 struct ctlr_ops ataops
= {
98 #endif /* defined(sparc) */
101 struct ctlr_ops pcmcia_ataops
= {
114 static struct dkl_partition
*dpart
= NULL
;
115 #endif /* defined(i386) */
116 extern struct badsec_lst
*badsl_chain
;
117 extern int badsl_chain_cnt
;
118 extern struct badsec_lst
*gbadsl_chain
;
119 extern int gbadsl_chain_cnt
;
120 extern struct alts_mempart
*ap
;
122 static char *dadkrawioerrs
[] = {
123 "cmd was successful", /* DADKIO_STAT_NO_ERROR */
124 "device not ready", /* DADKIO_STAT_NOT_READY */
125 "error on medium blkno: %d", /* DADKIO_STAT_MEDIUM_ERROR */
126 "other hardware error", /* DADKIO_STAT_HARDWARE_ERROR */
127 "illegal request", /* DADKIO_STAT_ILLEGAL_REQUEST */
128 "illegal block address: %d", /* DADKIO_STAT_ILLEGAL_ADDRESS */
129 "device write-protected", /* DADKIO_STAT_WRITE_PROTECTED */
130 "no response from device", /* DADKIO_STAT_TIMED_OUT */
131 "parity error in data", /* DADKIO_STAT_PARITY */
132 "error on bus", /* DADKIO_STAT_BUS_ERROR */
133 "data recovered via ECC", /* DADKIO_STAT_SOFT_ERROR */
134 "no resources for cmd", /* DADKIO_STAT_NO_RESOURCES */
135 "device is not formatted", /* DADKIO_STAT_NOT_FORMATTED */
136 "device is reserved", /* DADKIO_STAT_RESERVED */
137 "feature not supported", /* DADKIO_STAT_NOT_SUPPORTED */
143 ata_rdwr(int dir
, int fd
, diskaddr_t blk64
, int secnt
, caddr_t bufaddr
,
144 int flags
, int *xfercntp
)
145 #else /* defined(i386) */
147 ata_rdwr(int dir
, int fd
, diskaddr_t blk64
, int secnt
, caddr_t bufaddr
,
148 int flags
, int *xfercntp
)
149 #endif /* defined(i386) */
152 struct dadkio_rwcmd dadkio_rwcmd
;
155 blkno
= (blkaddr_t
)blk64
;
156 bzero((caddr_t
)&dadkio_rwcmd
, sizeof (struct dadkio_rwcmd
));
158 tmpsec
= secnt
* cur_blksz
;
161 dadkio_rwcmd
.cmd
= (dir
== DIR_READ
) ? DADKIO_RWCMD_READ
:
163 dadkio_rwcmd
.blkaddr
= blkno
;
164 dadkio_rwcmd
.buflen
= tmpsec
;
165 dadkio_rwcmd
.flags
= flags
;
166 dadkio_rwcmd
.bufaddr
= bufaddr
;
169 if (cur_ctype
->ctype_ctype
== DKC_PCMCIA_ATA
) {
171 * PCATA requires to use "p0" when calling
172 * DIOCTL_RWCMD ioctl() to read/write the label
175 (void) open_cur_file(FD_USE_P0_PATH
);
179 if (ioctl(fd
, DIOCTL_RWCMD
, &dadkio_rwcmd
) == -1) {
180 err_print("DIOCTL_RWCMD: %s\n", strerror(errno
));
184 if (cur_ctype
->ctype_ctype
== DKC_PCMCIA_ATA
) {
185 /* Restore cur_file with cur_disk->disk_path */
186 (void) open_cur_file(FD_USE_CUR_DISK_PATH
);
189 switch (dadkio_rwcmd
.status
.status
) {
190 case DADKIO_STAT_NOT_READY
:
191 disk_error
= DISK_STAT_NOTREADY
;
193 case DADKIO_STAT_RESERVED
:
194 disk_error
= DISK_STAT_RESERVED
;
196 case DADKIO_STAT_WRITE_PROTECTED
:
197 disk_error
= DISK_STAT_DATA_PROTECT
;
199 case DADKIO_STAT_MEDIUM_ERROR
:
204 if (dadkio_rwcmd
.status
.status
) {
205 if ((flags
& F_SILENT
) == 0)
206 err_print(dadkrawioerrs
[dadkio_rwcmd
.status
.status
],
207 dadkio_rwcmd
.status
.failed_blk
);
219 bufaddr
= (char *)zalloc(4 * cur_blksz
);
220 status
= ata_rdwr(DIR_READ
, cur_file
, (diskaddr_t
)1, 4,
221 (caddr_t
)bufaddr
, 0, NULL
);
238 if (cur_parts
== NULL
) {
239 (void) fprintf(stderr
, "No current partition list\n");
243 for (i
= 0; i
< V_NUMPAR
&& alts_slice
== -1; i
++) {
244 if (cur_parts
->vtoc
.v_part
[i
].p_tag
== V_ALTSCTR
) {
246 dpart
= &cur_parts
->vtoc
.v_part
[i
];
250 if (alts_slice
== -1) {
251 (void) fprintf(stderr
, "NO Alt slice\n");
255 if (copy_solaris_part(&cur_disk
->fdisk_part
))
258 altsec_offset
= dpart
->p_start
+ solaris_offset
;
269 status
= wr_altsctr();
274 if (ioctl(cur_file
, DKIOCADDBAD
, NULL
) == -1) {
275 (void) fprintf(stderr
, "Warning: DKIOCADDBAD ioctl failed\n");
284 ata_convert_list(struct defect_list
*list
, int list_format
)
288 struct defect_entry
*new_defect
;
290 switch (list_format
) {
293 if (ap
->ap_tblp
->alts_ent_used
) {
294 new_defect
= calloc(ap
->ap_tblp
->alts_ent_used
,
295 sizeof (struct defect_entry
));
296 if (new_defect
== NULL
) {
298 "ata_convert_list: calloc failed\n");
301 list
->header
.count
= ap
->ap_tblp
->alts_ent_used
;
302 list
->header
.magicno
= (uint_t
)DEFECT_MAGIC
;
303 list
->list
= new_defect
;
304 for (i
= 0; i
< ap
->ap_tblp
->alts_ent_used
;
307 bn2c((ap
->ap_entp
)[i
].bad_start
);
309 bn2h((ap
->ap_entp
)[i
].bad_start
);
310 new_defect
->bfi
= UNKNOWN
;
312 bn2s((ap
->ap_entp
)[i
].bad_start
);
313 new_defect
->nbits
= UNKNOWN
;
319 list
->header
.count
= 0;
320 list
->header
.magicno
= (uint_t
)DEFECT_MAGIC
;
321 new_defect
= calloc(1,
322 sizeof (struct defect_entry
));
323 if (new_defect
== NULL
) {
325 "ata_convert_list: calloc failed\n");
328 list
->list
= new_defect
;
333 err_print("ata_convert_list: can't deal with it\n");
336 (void) checkdefsum(list
, CK_MAKESUM
);
342 * NB - there used to be a ata_ex_man() which was identical to
343 * ata_ex_cur; since it's really not a "manufacturer's list",
344 * it's gone; if we ever want that exact functionality back,
345 * we can add ata_ex_cur() to the ctlr_ops above. Otherwise,
346 * if this is ever modified to support formatting of IDE drives,
347 * we should probably add something that issues the
348 * drive Read Defect list rather than getting the s9 info
349 * as ata_ex_cur() does.
353 ata_ex_cur(struct defect_list
*list
)
357 status
= get_alts_slice();
360 status
= read_altsctr(dpart
);
364 (void) ata_convert_list(list
, BFI_FORMAT
);
369 ata_repair(diskaddr_t bn
, int flag
)
373 struct badsec_lst
*blc_p
;
374 struct badsec_lst
*blc_p_nxt
;
377 (void) get_alts_slice();
379 blc_p
= (struct badsec_lst
*)calloc(1, BADSLSZ
);
381 (void) fprintf(stderr
,
382 "Unable to allocate memory for additional bad sectors\n");
385 gbadsl_chain
= blc_p
;
387 for (blc_p
= gbadsl_chain
; blc_p
->bl_nxt
; )
388 blc_p
= blc_p
->bl_nxt
;
390 if (blc_p
->bl_cnt
== MAXBLENT
) {
391 blc_p
->bl_nxt
= (struct badsec_lst
*)calloc(1, BADSLSZ
);
392 if (!blc_p
->bl_nxt
) {
393 (void) fprintf(stderr
,
394 "Unable to allocate memory for additional bad sectors\n");
397 blc_p
= blc_p
->bl_nxt
;
399 blc_p
->bl_sec
[blc_p
->bl_cnt
++] = (uint_t
)bn
;
402 (void) updatebadsec(dpart
, 0);
403 status
= put_alts_slice();
405 /* clear out the bad sector list chains that were generated */
408 if (badsl_chain
->bl_nxt
== NULL
) {
411 for (blc_p
= badsl_chain
; blc_p
; ) {
412 blc_p_nxt
= blc_p
->bl_nxt
;
422 if (gbadsl_chain
->bl_nxt
== NULL
) {
425 for (blc_p
= gbadsl_chain
; blc_p
; ) {
426 blc_p_nxt
= blc_p
->bl_nxt
;
432 gbadsl_chain_cnt
= 0;
440 ata_wr_cur(struct defect_list
*list
)
445 struct badsec_lst
*blc_p
;
446 struct badsec_lst
*blc_p_nxt
;
447 struct defect_entry
*dlist
;
449 if (list
->header
.magicno
!= (uint_t
)DEFECT_MAGIC
)
452 sec_count
= list
->header
.count
;
455 (void) get_alts_slice();
456 for (x
= 0; x
< sec_count
; x
++) {
458 /* test for unsupported list format */
459 if ((dlist
->bfi
!= UNKNOWN
) || (dlist
->nbits
!= UNKNOWN
)) {
460 (void) fprintf(stderr
,
461 "BFI unsuported format for bad sectors\n");
466 blc_p
= (struct badsec_lst
*)calloc(1, BADSLSZ
);
468 (void) fprintf(stderr
,
469 "Unable to allocate memory for additional bad sectors\n");
472 gbadsl_chain
= blc_p
;
475 for (blc_p
= gbadsl_chain
; blc_p
->bl_nxt
; )
476 blc_p
= blc_p
->bl_nxt
;
478 if (blc_p
->bl_cnt
== MAXBLENT
) {
479 blc_p
->bl_nxt
= (struct badsec_lst
*)calloc(1, BADSLSZ
);
480 if (!blc_p
->bl_nxt
) {
481 (void) fprintf(stderr
,
482 "Unable to allocate memory for additional bad sectors\n");
485 blc_p
= blc_p
->bl_nxt
;
487 blc_p
->bl_sec
[blc_p
->bl_cnt
++] =
488 (uint_t
)chs2bn(dlist
->cyl
, dlist
->head
, dlist
->sect
);
494 (void) updatebadsec(dpart
, 0);
495 status
= put_alts_slice();
497 /* clear out the bad sector list chains that were generated */
500 if (badsl_chain
->bl_nxt
== NULL
) {
503 for (blc_p
= badsl_chain
; blc_p
; ) {
504 blc_p_nxt
= blc_p
->bl_nxt
;
514 if (gbadsl_chain
->bl_nxt
== NULL
) {
517 for (blc_p
= gbadsl_chain
; blc_p
; ) {
518 blc_p_nxt
= blc_p
->bl_nxt
;
524 gbadsl_chain_cnt
= 0;
530 #endif /* defined(i386) */