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 routines that manipulate the defect list.
30 #include <sys/types.h>
31 #include <sys/param.h>
35 #endif /* defined(sparc) */
38 #include <sys/ioctl.h>
40 #include <sys/fcntl.h>
46 #include <sys/dkbad.h>
47 #endif /* defined(sparc) */
55 * This structure is the bad block table for the current disk if
56 * the disk uses bad-144 defect mapping.
59 #endif /* defined(sparc) */
62 * This routine reads the defect list off the disk. It also reads in the
63 * bad block table if the disk is a BAD144 type. The defect list is
64 * located on the first 2 tracks of the 2nd alternate cylinder of all
65 * disks. The bad block map is located on the first 5 even sectors of
66 * the last track of the last cylinder.
69 read_list(struct defect_list
*list
)
76 #endif /* defined(sparc) */
78 assert(!EMBEDDED_SCSI
);
81 * This flags has been introduced only for Sparc ATA IDE.
82 * This indicates that no list manipulation is done in this controller
83 * and hence return without any other checking.
85 if (cur_ctype
->ctype_flags
& CF_NOWLIST
) {
90 * Panther's working list is maintained by the controller
92 if (cur_ctype
->ctype_flags
& CF_WLIST
) {
93 if (*cur_ops
->op_ex_cur
!= NULL
&&
94 ((*cur_ops
->op_ex_cur
)(list
)) == 0) {
95 if (list
->header
.magicno
!= DEFECT_MAGIC
) {
96 fmt_print("Defect list BAD\n");
98 fmt_print("Controller working list found\n");
103 if (*cur_ops
->op_ex_man
!= NULL
&&
104 ((*cur_ops
->op_ex_man
)(list
)) == 0) {
105 if (list
->header
.magicno
!= DEFECT_MAGIC
) {
106 fmt_print("Defect list BAD\n");
108 fmt_print("MANUFACTURER's list found\n");
112 fmt_print("No defect list found\n");
117 * Loop for each copy of the defect list until we get a good one.
119 for (head
= 0; head
< LISTCOUNT
; head
++) {
121 * Try to read the list header.
123 if ((*cur_ops
->op_rdwr
)(DIR_READ
, cur_file
,
124 (diskaddr_t
)chs2bn(ncyl
+ 1, head
, 0), 1,
125 (char *)&list
->header
, NULL
), F_NORMAL
)
128 * If the magic number is wrong, this copy is corrupt.
130 if (list
->header
.magicno
!= DEFECT_MAGIC
)
133 * Allocate space for the rest of the list.
135 size
= deflist_size(cur_blksz
, list
->header
.count
);
136 list
->list
= (struct defect_entry
*)zalloc(size
* cur_blksz
);
138 * Try to read in the rest of the list. If there is an
139 * error, or the checksum is wrong, this copy is corrupt.
141 if ((*cur_ops
->op_rdwr
)(DIR_READ
, cur_file
,
142 (diskaddr_t
)chs2bn(ncyl
+ 1, head
, 1), size
,
143 (char *)list
->list
, F_NORMAL
, NULL
) ||
144 checkdefsum(list
, CK_CHECKSUM
)) {
146 * Destroy the list and go on.
152 * Got a good copy, stop searching.
157 if (!(cur_ctlr
->ctlr_flags
& DKI_BAD144
))
160 * The disk uses BAD144, read in the bad-block table.
162 for (sec
= 0; ((sec
< BAD_LISTCNT
* 2) && (sec
< nsect
)); sec
+= 2) {
163 status
= (*cur_ops
->op_rdwr
)(DIR_READ
, cur_file
,
164 (diskaddr_t
)chs2bn(ncyl
+ acyl
- 1, nhead
- 1, sec
), 1,
165 &badmap
, F_NORMAL
, NULL
);
169 * Do a sanity check on the list read in. If it passes,
172 if (badmap
.bt_mbz
!= 0)
174 for (bt
= badmap
.bt_bad
; bt
- badmap
.bt_bad
< NDKBAD
; bt
++) {
177 if (bt
->bt_trksec
< 0)
179 head
= bt
->bt_trksec
>> 8;
180 if ((bt
->bt_cyl
>= pcyl
) || (head
>= nhead
) ||
181 ((bt
->bt_trksec
& 0xff) >= sectors(head
))) {
191 * If we couldn't find the bad block table, initialize it to
194 for (bt
= badmap
.bt_bad
; bt
- badmap
.bt_bad
< NDKBAD
; bt
++)
195 bt
->bt_cyl
= bt
->bt_trksec
= -1;
196 badmap
.bt_mbz
= badmap
.bt_csn
= badmap
.bt_flag
= 0;
197 #endif /* defined(sparc) */
201 * This routine either checks or calculates the checksum for a defect
202 * list, depending on the mode parameter. In check mode, it returns
203 * whether or not the checksum is correct.
206 checkdefsum(struct defect_list
*list
, int mode
)
208 register int *lp
, i
, sum
= 0;
211 * Perform the rolling xor to get what the checksum should be.
213 lp
= (int *)list
->list
;
214 for (i
= 0; i
< (list
->header
.count
*
215 sizeof (struct defect_entry
) / sizeof (int)); i
++)
218 * If in check mode, return whether header checksum was correct.
220 if (mode
== CK_CHECKSUM
)
221 return (sum
!= list
->header
.cksum
);
223 * If in create mode, set the header checksum.
226 list
->header
.cksum
= sum
;
232 * This routine prints a single defect to stdout in a readable format.
235 pr_defect(struct defect_entry
*def
, int num
)
239 * Make defect numbering look 1 relative.
243 * Print out common values.
245 fmt_print("%4d%8d%7d", num
, def
->cyl
, def
->head
);
247 * The rest of the values may be unknown. If they are, just
248 * print blanks instead. Also, only print length only if bfi is
249 * known, and assume that a known bfi implies an unknown sect.
251 if (def
->bfi
!= UNKNOWN
) {
252 fmt_print("%8d", def
->bfi
);
253 if (def
->nbits
!= UNKNOWN
)
254 fmt_print("%8d", def
->nbits
);
257 fmt_print("%8d", def
->sect
);
258 fmt_print("%8llu", chs2bn(def
->cyl
, def
->head
, def
->sect
));
264 * This routine calculates where in a defect list a given defect should
265 * be sorted. It returns the index that the defect should become. The
266 * algorithm used sorts all bfi based defects by cylinder/head/bfi, and
267 * adds all logical sector defects to the end of the list. This is
268 * necessary because the ordering of logical sector defects is significant
269 * when sector slipping is employed.
272 sort_defect(struct defect_entry
*def
, struct defect_list
*list
)
274 struct defect_entry
*ptr
;
277 * If it's a logical sector defect, return the entry at the end
280 if (def
->bfi
== UNKNOWN
)
281 return (list
->header
.count
);
283 * It's a bfi defect. Loop through the defect list.
285 for (ptr
= list
->list
; ptr
- list
->list
< list
->header
.count
; ptr
++) {
287 * If we get to a logical sector defect, put this defect
290 if (ptr
->bfi
== UNKNOWN
)
293 * If we get to a defect that is past this one in
294 * cylinder/head/bfi, put this defect right before it.
296 if (def
->cyl
< ptr
->cyl
)
298 if (def
->cyl
!= ptr
->cyl
)
300 if (def
->head
< ptr
->head
)
302 if (def
->head
!= ptr
->head
)
304 if (def
->bfi
< ptr
->bfi
)
309 * Return the index to put the defect at.
311 return (ptr
- list
->list
);
315 * This routine writes the defect list on the back on the disk. It also
316 * writes the bad block table to disk if bad-144 mapping applies to the
320 write_deflist(struct defect_list
*list
)
322 int size
, head
, status
;
326 caddr_t bad_ptr
= (caddr_t
)&badmap
;
327 #endif /* defined(sparc) */
329 assert(!EMBEDDED_SCSI
);
333 * This indicates that no list manipulation is done in this controller
334 * and hence return without any other checking.
336 if (cur_ctype
->ctype_flags
& CF_NOWLIST
) {
341 * Panther's working list is maintained by the controller
343 if (cur_ctype
->ctype_flags
& CF_WLIST
) {
344 (*cur_ops
->op_wr_cur
)(list
);
349 * If the list is null, there is nothing to write.
351 if (list
->list
!= NULL
) {
353 * calculate how many sectors the defect list will occupy.
355 size
= deflist_size(cur_blksz
, list
->header
.count
);
357 * Loop for each copy of the list to be written. Write
358 * out the header of the list followed by the data.
360 for (head
= 0; head
< LISTCOUNT
; head
++) {
361 status
= (*cur_ops
->op_rdwr
)(DIR_WRITE
, cur_file
,
362 (diskaddr_t
)chs2bn(ncyl
+ 1, head
, 0), 1,
363 (char *)&list
->header
, F_NORMAL
, NULL
);
366 "Warning: error saving defect list.\n");
369 status
= (*cur_ops
->op_rdwr
)(DIR_WRITE
, cur_file
,
370 (diskaddr_t
)chs2bn(ncyl
+ 1, head
, 1), size
,
371 (char *)list
->list
, F_NORMAL
, NULL
);
374 "Warning: error saving defect list.\n");
377 if (!(cur_ctlr
->ctlr_flags
& DKI_BAD144
))
381 * Current disk uses bad-144 mapping. Loop for each copy of the
382 * bad block table to be written and write it out.
384 for (sec
= 0; ((sec
< BAD_LISTCNT
* 2) && (sec
< nsect
)); sec
+= 2) {
385 status
= (*cur_ops
->op_rdwr
)(DIR_WRITE
, cur_file
,
386 (diskaddr_t
)chs2bn(ncyl
+ acyl
- 1, nhead
- 1, sec
), 1,
387 &badmap
, F_NORMAL
, NULL
);
390 "Warning: error saving bad block map table.\n");
395 * Execute an ioctl to tell unix about the new bad block table.
397 if (ioctl(cur_file
, HDKIOCSBAD
, &bad_ptr
))
399 "Warning: error telling SunOS bad block map table.\n");
400 #endif /* defined(sparc) */
404 * This routine adds a logical sector to the given defect list.
407 add_ldef(diskaddr_t blkno
, struct defect_list
*list
)
409 struct defect_entry def
;
414 * Calculate the fields for the defect struct.
416 def
.cyl
= bn2c(blkno
);
417 def
.head
= bn2h(blkno
);
418 def
.sect
= bn2s(blkno
);
420 * Initialize the unknown fields.
422 def
.bfi
= def
.nbits
= UNKNOWN
;
424 * Calculate the index into the list that the defect belongs at.
426 index
= sort_defect(&def
, list
);
428 * Add the defect to the list.
430 add_def(&def
, list
, index
);
434 * This routine adds the given defect struct to the defect list at
435 * a precalculated index.
438 add_def(struct defect_entry
*def
, struct defect_list
*list
, int index
)
443 * If adding this defect makes the list overflow into another
444 * sector, allocate the necessary space.
446 count
= list
->header
.count
;
447 if (deflist_size(cur_blksz
, count
+ 1) > deflist_size(cur_blksz
, count
))
448 list
->list
= (struct defect_entry
*)rezalloc((void *)list
->list
,
449 deflist_size(cur_blksz
, count
+ 1) * cur_blksz
);
451 * Slip all the defects after this one down one slot in the list.
453 for (i
= count
; i
> index
; i
--)
454 *(list
->list
+ i
) = *(list
->list
+ i
- 1);
456 * Fill in the created hole with this defect.
458 *(list
->list
+ i
) = *def
;
460 * Increment the count and calculate a new checksum.
462 list
->header
.count
++;
463 (void) checkdefsum(list
, CK_MAKESUM
);
467 * This routine sets the given defect list back to null.
470 kill_deflist(struct defect_list
*list
)
474 * If it's already null, we're done.
476 if (list
->list
== NULL
)
479 * Free the malloc'd space it's using.
481 destroy_data((char *)list
->list
);
483 * Mark it as null, and clear any flags.
490 * This routine returns the defect list size
491 * according to the sector size.
494 deflist_size(int secsz
, int sz
)
502 rval
= sz
? ((sz
* sizeof (struct defect_entry
) +
503 secsz
- 1) / secsz
) : 1;