patch-2.1.66 linux/drivers/char/ftape/ftape-bsm.c
Next file: linux/drivers/char/ftape/ftape-bsm.h
Previous file: linux/drivers/char/ftape/fdc-isr.h
Back to the patch index
Back to the overall index
- Lines: 429
- Date:
Wed Dec 31 16:00:00 1969
- Orig file:
v2.1.65/linux/drivers/char/ftape/ftape-bsm.c
- Orig date:
Thu Mar 14 01:53:44 1996
diff -u --recursive --new-file v2.1.65/linux/drivers/char/ftape/ftape-bsm.c linux/drivers/char/ftape/ftape-bsm.c
@@ -1,428 +0,0 @@
-/*
- * Copyright (C) 1994-1995 Bas Laarhoven.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- $Source: /home/bas/distr/ftape-2.03b/RCS/ftape-bsm.c,v $
- $Author: bas $
- *
- $Revision: 1.7 $
- $Date: 1995/04/30 13:15:14 $
- $State: Beta $
- *
- * This file contains the bad-sector map handling code for
- * the QIC-117 floppy tape driver for Linux.
- * QIC-40, QIC-80, QIC-3010 and QIC-3020 maps are implemented.
- */
-
-#include <linux/ftape.h>
-#include <linux/string.h>
-
-#include "tracing.h"
-#include "ftape-bsm.h"
-#include "ftape-ctl.h"
-#include "ftape-rw.h"
-
-
-/* Global vars.
- */
-int bad_sector_map_changed = 0;
-
-/* Local vars.
- */
-static byte bad_sector_map[BAD_SECTOR_MAP_SIZE];
-typedef enum {
- forward, backward
-} mode_type;
-
-#if 0
-/* fix_tape converts a normal QIC-80 tape into a 'wide' tape.
- * For testing purposes only !
- */
-void fix_tape(byte * buffer)
-{
- static byte list[BAD_SECTOR_MAP_SIZE];
- unsigned long *src_ptr = (unsigned long *) list;
- byte *dst_ptr = bad_sector_map;
- unsigned long map;
- unsigned sector = 1;
- int i;
-
- memcpy(list, bad_sector_map, sizeof(list));
- memset(bad_sector_map, 0, sizeof(bad_sector_map));
- while ((byte *) src_ptr - list < sizeof(list)) {
- map = *src_ptr++;
- if (map == EMPTY_SEGMENT) {
- *(unsigned long *) dst_ptr = 0x800000 + sector;
- dst_ptr += 3;
- sector += SECTORS_PER_SEGMENT;
- } else {
- for (i = 0; i < SECTORS_PER_SEGMENT; ++i) {
- if (map & 1) {
- *(unsigned long *) dst_ptr = sector;
- dst_ptr += 3;
- }
- map >>= 1;
- ++sector;
- }
- }
- }
- bad_sector_map_changed = 1;
- *(buffer + 4) = 4; /* put new format code */
- format_code = 4;
-}
-
-#endif
-
-byte *
- find_end_of_bsm_list(byte * ptr, byte * limit)
-{
- while (ptr + 2 < limit) {
- if (ptr[0] || ptr[1] || ptr[2]) {
- ptr += 3;
- } else {
- return ptr;
- }
- }
- return NULL;
-}
-
-void store_bad_sector_map(byte * buffer)
-{
- TRACE_FUN(8, "store_bad_sector_map");
- size_t count;
- size_t offset;
-
- /* Store the bad sector map in buffer.
- */
- if (format_code == 4) {
- offset = 256;
- count = sizeof(bad_sector_map);
- } else {
- offset = 2 * SECTOR_SIZE; /* skip failed sector log */
- count = sizeof(bad_sector_map) - (offset - 256);
- }
- memcpy(buffer + offset, bad_sector_map, count);
- TRACE_EXIT;
-}
-
-void put_sector(byte ** ptr, unsigned long sector)
-{
- *(*ptr)++ = sector & 0xff;
- sector >>= 8;
- *(*ptr)++ = sector & 0xff;
- sector >>= 8;
- *(*ptr)++ = sector & 0xff;
-}
-
-unsigned long get_sector(byte ** ptr, mode_type mode)
-{
- unsigned long sector;
-
- if (mode == forward) {
- sector = *(*ptr)++;
- sector += *(*ptr)++ << 8;
- sector += *(*ptr)++ << 16;
- } else {
- sector = *--(*ptr) << 16;
- sector += *--(*ptr) << 8;
- sector += *--(*ptr);
- }
- return sector;
-}
-
-void extract_bad_sector_map(byte * buffer)
-{
- TRACE_FUN(8, "extract_bad_sector_map");
-
- /* Fill the bad sector map with the contents of buffer.
- */
- if (format_code == 4) {
- /* QIC-3010/3020 and wide QIC-80 tapes no longer have a failed
- * sector log but use this area to extend the bad sector map.
- */
- memcpy(bad_sector_map, buffer + 256, sizeof(bad_sector_map));
- } else {
- /* non-wide QIC-80 tapes have a failed sector log area that
- * mustn't be included in the bad sector map.
- */
- memcpy(bad_sector_map, buffer + 256 + FAILED_SECTOR_LOG_SIZE,
- sizeof(bad_sector_map) - FAILED_SECTOR_LOG_SIZE);
- }
-#if 0
- /* for testing of bad sector handling at end of tape
- */
- ((unsigned long *) bad_sector_map)[segments_per_track * tracks_per_tape - 3] = 0x000003e0;
- ((unsigned long *) bad_sector_map)[segments_per_track * tracks_per_tape - 2] = 0xff3fffff;
- ((unsigned long *) bad_sector_map)[segments_per_track * tracks_per_tape - 1] = 0xffffe000;
-#endif
-#if 0
- /* Enable to test bad sector handling
- */
- ((unsigned long *) bad_sector_map)[30] = 0xfffffffe;
- ((unsigned long *) bad_sector_map)[32] = 0x7fffffff;
- ((unsigned long *) bad_sector_map)[34] = 0xfffeffff;
- ((unsigned long *) bad_sector_map)[36] = 0x55555555;
- ((unsigned long *) bad_sector_map)[38] = 0xffffffff;
- ((unsigned long *) bad_sector_map)[50] = 0xffff0000;
- ((unsigned long *) bad_sector_map)[51] = 0xffffffff;
- ((unsigned long *) bad_sector_map)[52] = 0xffffffff;
- ((unsigned long *) bad_sector_map)[53] = 0x0000ffff;
-#endif
-#if 0
- /* Enable when testing multiple volume tar dumps.
- */
- for (i = first_data_segment; i <= ftape_last_segment.id - 7; ++i) {
- ((unsigned long *) bad_sector_map)[i] = EMPTY_SEGMENT;
- }
-#endif
-#if 0
- /* Enable when testing bit positions in *_error_map
- */
- for (i = first_data_segment; i <= ftape_last_segment.id; ++i) {
- ((unsigned long *) bad_sector_map)[i] |= 0x00ff00ff;
- }
-#endif
- if (tracing > 2) {
- unsigned int map;
- int good_sectors = 0;
- int bad_sectors;
- unsigned int total_bad = 0;
- int i;
-
- if (format_code == 4 || format_code == 3) {
- byte *ptr = bad_sector_map;
- unsigned sector;
-
- do {
- sector = get_sector(&ptr, forward);
- if (sector != 0) {
- if (format_code == 4 && sector & 0x800000) {
- total_bad += SECTORS_PER_SEGMENT - 3;
- TRACEx1(6, "bad segment at sector: %6d", sector & 0x7fffff);
- } else {
- ++total_bad;
- TRACEx1(6, "bad sector: %6d", sector);
- }
- }
- } while (sector != 0);
- /* Display end-of-file marks
- */
- do {
- sector = *((unsigned short *) ptr)++;
- if (sector) {
- TRACEx2(4, "eof mark: %4d/%2d", sector,
- *((unsigned short *) ptr)++);
- }
- } while (sector);
- } else {
- for (i = first_data_segment;
- i < segments_per_track * tracks_per_tape; ++i) {
- map = ((unsigned long *) bad_sector_map)[i];
- bad_sectors = count_ones(map);
- if (bad_sectors > 0) {
- TRACEx2(6, "bsm for segment %4d: 0x%08x", i, map);
- if (bad_sectors > SECTORS_PER_SEGMENT - 3) {
- bad_sectors = SECTORS_PER_SEGMENT - 3;
- }
- total_bad += bad_sectors;
- }
- }
- }
- good_sectors = ((segments_per_track * tracks_per_tape - first_data_segment)
- * (SECTORS_PER_SEGMENT - 3)) - total_bad;
- TRACEx1(3, "%d Kb usable on this tape",
- good_sectors - ftape_last_segment.free);
- if (total_bad == 0) {
- TRACE(1, "WARNING: this tape has no bad blocks registered !");
- } else {
- TRACEx1(2, "%d bad sectors", total_bad);
- }
- }
- TRACE_EXIT;
-}
-
-unsigned long cvt2map(int sector)
-{
- return 1 << (((sector & 0x7fffff) - 1) % SECTORS_PER_SEGMENT);
-}
-
-int cvt2segment(int sector)
-{
- return ((sector & 0x7fffff) - 1) / SECTORS_PER_SEGMENT;
-}
-
-int forward_seek_entry(int segment_id, byte ** ptr, unsigned long *map)
-{
- byte *tmp_ptr;
- unsigned long sector;
- int segment;
- int count;
-
- do {
- sector = get_sector(ptr, forward);
- segment = cvt2segment(sector);
- } while (sector != 0 && segment < segment_id);
- tmp_ptr = *ptr - 3; /* point to first sector >= segment_id */
- /* Get all sectors in segment_id
- */
- if (format_code == 4 && (sector & 0x800000) && segment == segment_id) {
- *map = EMPTY_SEGMENT;
- count = 32;
- } else {
- *map = 0;
- count = 0;
- while (sector != 0 && segment == segment_id) {
- *map |= cvt2map(sector);
- sector = get_sector(ptr, forward);
- segment = cvt2segment(sector);
- ++count;
- }
- }
- *ptr = tmp_ptr;
- return count;
-}
-
-int backwards_seek_entry(int segment_id, byte ** ptr, unsigned long *map)
-{
- unsigned long sector;
- int segment;
- int count;
-
- *map = 0;
- if (*ptr > bad_sector_map) {
- do {
- sector = get_sector(ptr, backward);
- segment = cvt2segment(sector);
- } while (*ptr > bad_sector_map && segment > segment_id);
- count = 0;
- if (segment > segment_id) {
- /* at start of list, no entry found */
- } else if (segment < segment_id) {
- /* before smaller entry, adjust for overshoot */
- *ptr += 3;
- } else {
- /* get all sectors in segment_id */
- if (format_code == 4 && (sector & 0x800000)) {
- *map = EMPTY_SEGMENT;
- count = 32;
- } else {
- do {
- *map |= cvt2map(sector);
- ++count;
- if (*ptr <= bad_sector_map) {
- break;
- }
- sector = get_sector(ptr, backward);
- segment = cvt2segment(sector);
- } while (segment == segment_id);
- if (segment < segment_id) {
- *ptr += 3;
- }
- }
- }
- } else {
- count = 0;
- }
- return count;
-}
-
-void put_bad_sector_entry(int segment_id, unsigned long new_map)
-{
- byte *ptr = bad_sector_map;
- int count;
- int new_count;
- unsigned long map;
-
- if (format_code == 3 || format_code == 4) {
- count = forward_seek_entry(segment_id, &ptr, &map);
- new_count = count_ones(new_map);
- /* If format code == 4 put empty segment instead of 32 bad sectors.
- */
- if (new_count == 32 && format_code == 4) {
- new_count = 1;
- }
- if (count != new_count) {
- /* insert (or delete if < 0) new_count - count entries.
- * Move trailing part of list including terminating 0.
- */
- byte *hi_ptr = ptr;
-
- do {
- } while (get_sector(&hi_ptr, forward) != 0);
- memmove(ptr + new_count, ptr + count, hi_ptr - (ptr + count));
- }
- if (new_count == 1 && new_map == EMPTY_SEGMENT) {
- put_sector(&ptr, 0x800001 + segment_id * SECTORS_PER_SEGMENT);
- } else {
- int i = 0;
-
- while (new_map) {
- if (new_map & 1) {
- put_sector(&ptr, 1 + segment_id * SECTORS_PER_SEGMENT + i);
- }
- ++i;
- new_map >>= 1;
- }
- }
- } else {
- ((unsigned long *) bad_sector_map)[segment_id] = new_map;
- }
- bad_sector_map_changed = 1;
-}
-
-unsigned long get_bad_sector_entry(int segment_id)
-{
- TRACE_FUN(8, "get_bad_sector_entry");
- static unsigned long map = 0;
-
- if (used_header_segment == -1) {
- /* When reading header segment we'll need a blank map.
- */
- map = 0;
- } else if (format_code == 3 || format_code == 4) {
- /* Invariants:
- * map - mask value returned on last call.
- * ptr - points to first sector greater or equal to
- * first sector in last_referenced segment.
- * last_referenced - segment id used in the last call,
- * sector and map belong to this id.
- * This code is designed for sequential access and retries.
- * For true random access it may have to be redesigned.
- */
- static int last_reference = -1;
- static byte *ptr = bad_sector_map;
-
- if (segment_id > last_reference) {
- /* Skip all sectors before segment_id
- */
- forward_seek_entry(segment_id, &ptr, &map);
- } else if (segment_id < last_reference) {
- /* Skip backwards until begin of buffer or first sector in segment_id
- */
- backwards_seek_entry(segment_id, &ptr, &map);
- } /* segment_id == last_reference : keep map */
- last_reference = segment_id;
- } else {
- map = ((unsigned long *) bad_sector_map)[segment_id];
- }
- TRACE_EXIT;
- return map;
-}
-
-void ftape_init_bsm(void)
-{
- memset(bad_sector_map, 0, sizeof(bad_sector_map));
-}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov