Hotswap code shuffling: Fix yellow. Simplify some target function access. Keep fat...
[kugel-rb.git] / firmware / common / disk.c
blobd4cfbc1a05170c92e348b6507defc96b9f1ef7f7
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 by Björn Stenberg
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
19 #include <stdio.h>
20 #include "ata.h"
21 #include "debug.h"
22 #include "fat.h"
23 #ifdef HAVE_HOTSWAP
24 #include "hotswap.h"
25 #include "dir.h" /* for release_dirs() */
26 #include "file.h" /* for release_files() */
27 #endif
28 #include "disk.h"
30 /* Partition table entry layout:
31 -----------------------
32 0: 0x80 - active
33 1: starting head
34 2: starting sector
35 3: starting cylinder
36 4: partition type
37 5: end head
38 6: end sector
39 7: end cylinder
40 8-11: starting sector (LBA)
41 12-15: nr of sectors in partition
44 #define BYTES2INT32(array,pos) \
45 ((long)array[pos] | ((long)array[pos+1] << 8 ) | \
46 ((long)array[pos+2] << 16 ) | ((long)array[pos+3] << 24 ))
48 static struct partinfo part[8]; /* space for 4 partitions on 2 drives */
49 static int vol_drive[NUM_VOLUMES]; /* mounted to which drive (-1 if none) */
51 #ifdef MAX_LOG_SECTOR_SIZE
52 int disk_sector_multiplier = 1;
53 #endif
54 struct partinfo* disk_init(IF_MV_NONVOID(int drive))
56 int i;
57 unsigned char sector[512];
58 #ifdef HAVE_MULTIVOLUME
59 /* For each drive, start at a different position, in order not to destroy
60 the first entry of drive 0.
61 That one is needed to calculate config sector position. */
62 struct partinfo* pinfo = &part[drive*4];
63 if ((size_t)drive >= sizeof(part)/sizeof(*part)/4)
64 return NULL; /* out of space in table */
65 #else
66 struct partinfo* pinfo = part;
67 #endif
69 ata_read_sectors(IF_MV2(drive,) 0,1,&sector);
71 /* check that the boot sector is initialized */
72 if ( (sector[510] != 0x55) ||
73 (sector[511] != 0xaa)) {
74 DEBUGF("Bad boot sector signature\n");
75 return NULL;
78 /* parse partitions */
79 for ( i=0; i<4; i++ ) {
80 unsigned char* ptr = sector + 0x1be + 16*i;
81 pinfo[i].type = ptr[4];
82 pinfo[i].start = BYTES2INT32(ptr, 8);
83 pinfo[i].size = BYTES2INT32(ptr, 12);
85 DEBUGF("Part%d: Type %02x, start: %08lx size: %08lx\n",
86 i,pinfo[i].type,pinfo[i].start,pinfo[i].size);
88 /* extended? */
89 if ( pinfo[i].type == 5 ) {
90 /* not handled yet */
94 return pinfo;
97 struct partinfo* disk_partinfo(int partition)
99 return &part[partition];
102 int disk_mount_all(void)
104 int mounted;
105 int i;
107 #ifdef HAVE_HOTSWAP
108 card_enable_monitoring(false);
109 #endif
111 fat_init(); /* reset all mounted partitions */
112 for (i=0; i<NUM_VOLUMES; i++)
113 vol_drive[i] = -1; /* mark all as unassigned */
115 mounted = disk_mount(0);
116 #ifdef HAVE_HOTSWAP
117 if (card_detect())
119 mounted += disk_mount(1); /* try 2nd "drive", too */
122 card_enable_monitoring(true);
123 #endif
125 return mounted;
128 static int get_free_volume(void)
130 int i;
131 for (i=0; i<NUM_VOLUMES; i++)
133 if (vol_drive[i] == -1) /* unassigned? */
134 return i;
137 return -1; /* none found */
140 int disk_mount(int drive)
142 int mounted = 0; /* reset partition-on-drive flag */
143 int volume = get_free_volume();
144 struct partinfo* pinfo = disk_init(IF_MV(drive));
146 if (pinfo == NULL)
148 return 0;
150 #ifdef TOSHIBA_GIGABEAT_S
151 int i = 1; /* For the Gigabeat S, we mount the second partition */
152 #else
153 int i = 0;
154 #endif
155 for (; volume != -1 && i<4; i++)
157 #ifdef MAX_LOG_SECTOR_SIZE
158 int j;
160 for (j = 1; j <= (MAX_LOG_SECTOR_SIZE/SECTOR_SIZE); j <<= 1)
162 if (!fat_mount(IF_MV2(volume,) IF_MV2(drive,) pinfo[i].start * j))
164 pinfo[i].start *= j;
165 pinfo[i].size *= j;
166 mounted++;
167 vol_drive[volume] = drive; /* remember the drive for this volume */
168 volume = get_free_volume(); /* prepare next entry */
169 if (drive == 0)
170 disk_sector_multiplier = j;
171 break;
174 #else
175 if (!fat_mount(IF_MV2(volume,) IF_MV2(drive,) pinfo[i].start))
177 mounted++;
178 vol_drive[volume] = drive; /* remember the drive for this volume */
179 volume = get_free_volume(); /* prepare next entry */
181 #endif
184 if (mounted == 0 && volume != -1) /* none of the 4 entries worked? */
185 { /* try "superfloppy" mode */
186 DEBUGF("No partition found, trying to mount sector 0.\n");
187 if (!fat_mount(IF_MV2(volume,) IF_MV2(drive,) 0))
189 mounted = 1;
190 vol_drive[volume] = drive; /* remember the drive for this volume */
193 return mounted;
196 #ifdef HAVE_HOTSWAP
197 int disk_unmount(int drive)
199 int unmounted = 0;
200 int i;
201 for (i=0; i<NUM_VOLUMES; i++)
203 if (vol_drive[i] == drive)
204 { /* force releasing resources */
205 vol_drive[i] = -1; /* mark unused */
206 unmounted++;
207 release_files(i);
208 release_dirs(i);
209 fat_unmount(i, false);
213 return unmounted;
215 #endif /* #ifdef HAVE_HOTSWAP */