Subversion Repositories freemyipod

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
46 theseven 1
/***************************************************************************
2
 *             __________               __   ___.
3
 *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
4
 *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
5
 *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
6
 *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
7
 *                     \/            \/     \/    \/            \/
8
 * $Id: disk.c 26629 2010-06-06 13:28:13Z gevaerts $
9
 *
10
 * Copyright (C) 2002 by Björn Stenberg
11
 *
12
 * This program is free software; you can redistribute it and/or
13
 * modify it under the terms of the GNU General Public License
14
 * as published by the Free Software Foundation; either version 2
15
 * of the License, or (at your option) any later version.
16
 *
17
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18
 * KIND, either express or implied.
19
 *
20
 ****************************************************************************/
49 theseven 21
#include "global.h"
22
#include "thread.h"
46 theseven 23
#include "storage.h"
24
#include "debug.h"
25
#include "fat.h"
26
#ifdef HAVE_HOTSWAP
27
#include "dir.h" /* for release_dirs() */
28
#include "file.h" /* for release_files() */
29
#endif
30
#include "disk.h"
58 theseven 31
#include "util.h"
115 theseven 32
#include "libc/include/string.h"
46 theseven 33
 
34
/* Partition table entry layout:
35
   -----------------------
36
   0: 0x80 - active
37
   1: starting head
38
   2: starting sector
39
   3: starting cylinder
40
   4: partition type
41
   5: end head
42
   6: end sector
43
   7: end cylinder
44
   8-11: starting sector (LBA)
45
   12-15: nr of sectors in partition
46
*/
47
 
48
#define BYTES2INT32(array,pos)                  \
49
    ((long)array[pos] | ((long)array[pos+1] << 8 ) |        \
50
     ((long)array[pos+2] << 16 ) | ((long)array[pos+3] << 24 ))
51
 
52
static const unsigned char fat_partition_types[] = {
53
    0x0b, 0x1b, /* FAT32 + hidden variant */
54
    0x0c, 0x1c, /* FAT32 (LBA) + hidden variant */
55
#ifdef HAVE_FAT16SUPPORT
56
    0x04, 0x14, /* FAT16 <= 32MB + hidden variant */
57
    0x06, 0x16, /* FAT16  > 32MB + hidden variant */
58
    0x0e, 0x1e, /* FAT16 (LBA) + hidden variant */
59
#endif
60
};
61
 
62
static struct partinfo part[NUM_DRIVES*4]; /* space for 4 partitions on 2 drives */
63
static int vol_drive[NUM_VOLUMES]; /* mounted to which drive (-1 if none) */
64
static struct mutex disk_mutex;
65
 
66
struct partinfo* disk_init(IF_MD_NONVOID(int drive))
67
{
68
    int i;
69
#ifdef HAVE_MULTIDRIVE
47 farthen 70
    /* For each drive, start at a different position, in order not to destroy
71
       the first entry of drive 0.
46 theseven 72
       That one is needed to calculate config sector position. */
73
    struct partinfo* pinfo = &part[drive*4];
74
    if ((size_t)drive >= sizeof(part)/sizeof(*part)/4)
75
        return NULL; /* out of space in table */
76
#else
77
    struct partinfo* pinfo = part;
78
    const int drive = 0;
79
    (void)drive;
80
#endif
81
 
58 theseven 82
    unsigned char* sector = fat_get_sector_buffer();
46 theseven 83
    storage_read_sectors(IF_MD2(drive,) 0,1, sector);
84
    /* check that the boot sector is initialized */
85
    if ( (sector[510] != 0x55) ||
86
         (sector[511] != 0xaa)) {
58 theseven 87
        fat_release_sector_buffer();
50 theseven 88
        DEBUGF("Bad boot sector signature");
46 theseven 89
        return NULL;
90
    }
91
 
92
    /* parse partitions */
93
    for ( i=0; i<4; i++ ) {
94
        unsigned char* ptr = sector + 0x1be + 16*i;
95
        pinfo[i].type  = ptr[4];
96
        pinfo[i].start = BYTES2INT32(ptr, 8);
97
        pinfo[i].size  = BYTES2INT32(ptr, 12);
98
 
50 theseven 99
        DEBUGF("Part%d: Type %02x, start: %08lx size: %08lx",
46 theseven 100
               i,pinfo[i].type,pinfo[i].start,pinfo[i].size);
101
 
102
        /* extended? */
103
        if ( pinfo[i].type == 5 ) {
104
            /* not handled yet */
105
        }
106
    }
58 theseven 107
    fat_release_sector_buffer();
46 theseven 108
    return pinfo;
109
}
110
 
111
struct partinfo* disk_partinfo(int partition)
112
{
113
    return &part[partition];
114
}
115
 
116
void disk_init_subsystem(void)
117
{
118
   mutex_init(&disk_mutex);
119
}
120
 
121
int disk_mount_all(void)
122
{
123
    int mounted=0;
124
    int i;
125
 
126
#ifdef HAVE_HOTSWAP
143 theseven 127
    mutex_lock(&disk_mutex, TIMEOUT_BLOCK);
46 theseven 128
#endif
129
 
130
    fat_init(); /* reset all mounted partitions */
131
    for (i=0; i<NUM_VOLUMES; i++)
132
        vol_drive[i] = -1; /* mark all as unassigned */
133
 
134
#ifndef HAVE_MULTIDRIVE
135
    mounted = disk_mount(0);
136
#else
137
    for(i=0;i<NUM_DRIVES;i++)
138
    {
139
#ifdef HAVE_HOTSWAP
140
        if (storage_present(i))
141
#endif
142
            mounted += disk_mount(i); 
143
    }
144
#endif
145
 
146
#ifdef HAVE_HOTSWAP
147
    mutex_unlock(&disk_mutex);
148
#endif
149
    return mounted;
150
}
151
 
152
static int get_free_volume(void)
153
{
154
    int i;
155
    for (i=0; i<NUM_VOLUMES; i++)
156
    {
157
        if (vol_drive[i] == -1) /* unassigned? */
158
            return i;
159
    }
160
 
161
    return -1; /* none found */
162
}
163
 
164
int disk_mount(int drive)
165
{
166
    int i;
167
    int mounted = 0; /* reset partition-on-drive flag */
168
    int volume;
169
    struct partinfo* pinfo;
170
 
171
#ifdef HAVE_HOTSWAP
143 theseven 172
    mutex_lock(&disk_mutex, TIMEOUT_BLOCK);
46 theseven 173
#endif
174
 
175
    volume = get_free_volume();
176
    pinfo = disk_init(IF_MD(drive));
177
 
178
    if (pinfo == NULL)
179
    {
180
#ifdef HAVE_HOTSWAP
181
        mutex_unlock(&disk_mutex);
182
#endif
183
        return 0;
184
    }
185
    for (i = 0; volume != -1 && i<4 && mounted<NUM_VOLUMES_PER_DRIVE; i++)
186
    {
187
        if (memchr(fat_partition_types, pinfo[i].type,
188
                   sizeof(fat_partition_types)) == NULL)
189
            continue;  /* not an accepted partition type */
190
 
191
        if (!fat_mount(IF_MV2(volume,) IF_MD2(drive,) pinfo[i].start))
192
        {
193
            mounted++;
194
            vol_drive[volume] = drive; /* remember the drive for this volume */
195
            volume = get_free_volume(); /* prepare next entry */
196
        }
197
    }
198
 
199
    if (mounted == 0 && volume != -1) /* none of the 4 entries worked? */
200
    {   /* try "superfloppy" mode */
50 theseven 201
        DEBUGF("No partition found, trying to mount sector 0.");
46 theseven 202
        if (!fat_mount(IF_MV2(volume,) IF_MD2(drive,) 0))
203
        {
204
            mounted = 1;
205
            vol_drive[volume] = drive; /* remember the drive for this volume */
206
        }
207
    }
208
#ifdef HAVE_HOTSWAP
209
    mutex_unlock(&disk_mutex);
210
#endif
211
    return mounted;
212
}
213
 
214
#ifdef HAVE_HOTSWAP
215
int disk_unmount(int drive)
216
{
217
    int unmounted = 0;
218
    int i;
143 theseven 219
    mutex_lock(&disk_mutex, TIMEOUT_BLOCK);
46 theseven 220
    for (i=0; i<NUM_VOLUMES; i++)
221
    {
222
        if (vol_drive[i] == drive)
223
        {   /* force releasing resources */
224
            vol_drive[i] = -1; /* mark unused */
225
            unmounted++;
226
            release_files(i);
227
            release_dirs(i);
228
            fat_unmount(i, false);
229
        }
230
    }
231
    mutex_unlock(&disk_mutex);
232
 
233
    return unmounted;
234
}
235
#endif /* #ifdef HAVE_HOTSWAP */