Subversion Repositories freemyipod

Rev

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