Move /var/svc/log to /var/log/svc
[unleashed/lotheac.git] / usr / src / cmd / format / ctlr_ata.c
blobc36672875c2a0d429707d42feb2abe48ed860870
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
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
29 #include "global.h"
31 #include <sys/types.h>
32 #include <sys/param.h>
33 #include <sys/ioctl.h>
34 #include <sys/uio.h>
35 #include <sys/fcntl.h>
36 #include <memory.h>
37 #include <malloc.h>
38 #include <unistd.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <sys/byteorder.h>
42 #include <errno.h>
43 #if defined(i386)
44 #include <sys/dktp/altsctr.h>
45 #endif
46 #include <sys/dktp/dadkio.h>
49 #include "startup.h"
50 #include "misc.h"
51 #include "ctlr_ata.h"
52 #include "analyze.h"
53 #include "param.h"
54 #include "io.h"
55 #include "badsec.h"
57 #include "menu_fdisk.h"
59 int wr_altsctr();
60 int read_altsctr();
61 int updatebadsec();
63 #ifdef __STDC__
64 static int ata_ck_format(void);
65 #ifdef i386
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);
69 #endif /* i386 */
70 #else /* __STDC__ */
71 static int ata_ck_format();
72 #ifdef i386
73 static int ata_ex_cur();
74 static int ata_wr_cur();
75 static int ata_repair();
76 #endif /* i386 */
77 #endif
79 struct ctlr_ops ataops = {
80 #if defined(sparc)
81 ata_rdwr,
82 ata_ck_format,
89 #else
90 ata_rdwr,
91 ata_ck_format,
94 ata_ex_cur,
95 ata_repair,
97 ata_wr_cur,
98 #endif /* defined(sparc) */
101 struct ctlr_ops pcmcia_ataops = {
102 ata_rdwr,
103 ata_ck_format,
113 #if defined(i386)
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 */
140 /*ARGSUSED6*/
141 #if defined(i386)
143 ata_rdwr(int dir, int fd, diskaddr_t blk64, int secnt, caddr_t bufaddr,
144 int flags, int *xfercntp)
145 #else /* defined(i386) */
146 static int
147 ata_rdwr(int dir, int fd, diskaddr_t blk64, int secnt, caddr_t bufaddr,
148 int flags, int *xfercntp)
149 #endif /* defined(i386) */
151 int tmpsec;
152 struct dadkio_rwcmd dadkio_rwcmd;
153 blkaddr_t blkno;
155 blkno = (blkaddr_t)blk64;
156 bzero((caddr_t)&dadkio_rwcmd, sizeof (struct dadkio_rwcmd));
158 tmpsec = secnt * cur_blksz;
160 /* Doing raw read */
161 dadkio_rwcmd.cmd = (dir == DIR_READ) ? DADKIO_RWCMD_READ :
162 DADKIO_RWCMD_WRITE;
163 dadkio_rwcmd.blkaddr = blkno;
164 dadkio_rwcmd.buflen = tmpsec;
165 dadkio_rwcmd.flags = flags;
166 dadkio_rwcmd.bufaddr = bufaddr;
168 media_error = 0;
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
174 (void) close(fd);
175 (void) open_cur_file(FD_USE_P0_PATH);
176 fd = cur_file;
179 if (ioctl(fd, DIOCTL_RWCMD, &dadkio_rwcmd) == -1) {
180 err_print("DIOCTL_RWCMD: %s\n", strerror(errno));
181 return (1);
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;
192 break;
193 case DADKIO_STAT_RESERVED:
194 disk_error = DISK_STAT_RESERVED;
195 break;
196 case DADKIO_STAT_WRITE_PROTECTED:
197 disk_error = DISK_STAT_DATA_PROTECT;
198 break;
199 case DADKIO_STAT_MEDIUM_ERROR:
200 media_error = 1;
201 break;
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);
208 return (1);
210 return (0);
214 ata_ck_format()
216 char *bufaddr;
217 int status;
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);
223 free(bufaddr);
225 return (!status);
229 #if defined(i386)
231 static int
232 get_alts_slice()
235 int i;
236 int alts_slice = -1;
238 if (cur_parts == NULL) {
239 (void) fprintf(stderr, "No current partition list\n");
240 return (-1);
243 for (i = 0; i < V_NUMPAR && alts_slice == -1; i++) {
244 if (cur_parts->vtoc.v_part[i].p_tag == V_ALTSCTR) {
245 alts_slice = i;
246 dpart = &cur_parts->vtoc.v_part[i];
250 if (alts_slice == -1) {
251 (void) fprintf(stderr, "NO Alt slice\n");
252 return (-1);
254 if (!solaris_offset)
255 if (copy_solaris_part(&cur_disk->fdisk_part))
256 return (-1);
258 altsec_offset = dpart->p_start + solaris_offset;
260 return (SUCCESS);
264 static int
265 put_alts_slice()
267 int status;
269 status = wr_altsctr();
270 if (status) {
271 return (status);
274 if (ioctl(cur_file, DKIOCADDBAD, NULL) == -1) {
275 (void) fprintf(stderr, "Warning: DKIOCADDBAD ioctl failed\n");
276 sync();
277 return (-1);
279 sync();
280 return (0);
283 static int
284 ata_convert_list(struct defect_list *list, int list_format)
287 int i;
288 struct defect_entry *new_defect;
290 switch (list_format) {
292 case BFI_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) {
297 err_print(
298 "ata_convert_list: calloc failed\n");
299 fullabort();
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;
305 i++, new_defect++) {
306 new_defect->cyl =
307 bn2c((ap->ap_entp)[i].bad_start);
308 new_defect->head =
309 bn2h((ap->ap_entp)[i].bad_start);
310 new_defect->bfi = UNKNOWN;
311 new_defect->sect =
312 bn2s((ap->ap_entp)[i].bad_start);
313 new_defect->nbits = UNKNOWN;
317 } else {
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) {
324 err_print(
325 "ata_convert_list: calloc failed\n");
326 fullabort();
328 list->list = new_defect;
330 break;
332 default:
333 err_print("ata_convert_list: can't deal with it\n");
334 exit(0);
336 (void) checkdefsum(list, CK_MAKESUM);
337 return (0);
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.
352 static int
353 ata_ex_cur(struct defect_list *list)
355 int status;
357 status = get_alts_slice();
358 if (status)
359 return (status);
360 status = read_altsctr(dpart);
361 if (status) {
362 return (status);
364 (void) ata_convert_list(list, BFI_FORMAT);
365 return (status);
369 ata_repair(diskaddr_t bn, int flag)
372 int status;
373 struct badsec_lst *blc_p;
374 struct badsec_lst *blc_p_nxt;
377 (void) get_alts_slice();
378 if (!gbadsl_chain) {
379 blc_p = (struct badsec_lst *)calloc(1, BADSLSZ);
380 if (!blc_p) {
381 (void) fprintf(stderr,
382 "Unable to allocate memory for additional bad sectors\n");
383 return (-1);
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");
395 return (-1);
397 blc_p = blc_p->bl_nxt;
399 blc_p->bl_sec[blc_p->bl_cnt++] = (uint_t)bn;
400 gbadsl_chain_cnt++;
402 (void) updatebadsec(dpart, 0);
403 status = put_alts_slice();
405 /* clear out the bad sector list chains that were generated */
407 if (badsl_chain) {
408 if (badsl_chain->bl_nxt == NULL) {
409 free(badsl_chain);
410 } else {
411 for (blc_p = badsl_chain; blc_p; ) {
412 blc_p_nxt = blc_p->bl_nxt;
413 free(blc_p);
414 blc_p = blc_p_nxt;
417 badsl_chain = NULL;
418 badsl_chain_cnt = 0;
421 if (gbadsl_chain) {
422 if (gbadsl_chain->bl_nxt == NULL) {
423 free(gbadsl_chain);
424 } else {
425 for (blc_p = gbadsl_chain; blc_p; ) {
426 blc_p_nxt = blc_p->bl_nxt;
427 free(blc_p);
428 blc_p = blc_p_nxt;
431 gbadsl_chain = NULL;
432 gbadsl_chain_cnt = 0;
435 return (status);
440 ata_wr_cur(struct defect_list *list)
442 int status;
443 int sec_count;
444 int x;
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)
450 return (-1);
452 sec_count = list->header.count;
453 dlist = list->list;
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");
462 return (-1);
465 if (!gbadsl_chain) {
466 blc_p = (struct badsec_lst *)calloc(1, BADSLSZ);
467 if (!blc_p) {
468 (void) fprintf(stderr,
469 "Unable to allocate memory for additional bad sectors\n");
470 return (-1);
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");
483 return (-1);
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);
489 gbadsl_chain_cnt++;
490 dlist++;
494 (void) updatebadsec(dpart, 0);
495 status = put_alts_slice();
497 /* clear out the bad sector list chains that were generated */
499 if (badsl_chain) {
500 if (badsl_chain->bl_nxt == NULL) {
501 free(badsl_chain);
502 } else {
503 for (blc_p = badsl_chain; blc_p; ) {
504 blc_p_nxt = blc_p->bl_nxt;
505 free(blc_p);
506 blc_p = blc_p_nxt;
509 badsl_chain = NULL;
510 badsl_chain_cnt = 0;
513 if (gbadsl_chain) {
514 if (gbadsl_chain->bl_nxt == NULL) {
515 free(gbadsl_chain);
516 } else {
517 for (blc_p = gbadsl_chain; blc_p; ) {
518 blc_p_nxt = blc_p->bl_nxt;
519 free(blc_p);
520 blc_p = blc_p_nxt;
523 gbadsl_chain = NULL;
524 gbadsl_chain_cnt = 0;
527 return (status);
530 #endif /* defined(i386) */