3 * - By John Hodge (thePowersGang)
12 #include <api_drv_disk.h>
15 #define FDD_VERSION VER2(1,10)
20 int FDD_Install(char **Arguments);
21 int FDD_RegisterFS(void);
23 char *FDD_ReadDir(tVFS_Node *Node, int pos);
24 tVFS_Node *FDD_FindDir(tVFS_Node *dirNode, const char *Name);
25 int FDD_IOCtl(tVFS_Node *Node, int ID, void *Data);
26 Uint64 FDD_ReadFS(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer);
29 MODULE_DEFINE(0, FDD_VERSION, Storage_FDDv2, FDD_Install, NULL, "x86_ISADMA", NULL);
30 tDrive gaFDD_Disks[MAX_DISKS];
31 tVFS_Node gaFDD_DiskNodes[MAX_DISKS];
32 tDevFS_Driver gFDD_DriverInfo = {
37 .ACLs = &gVFS_ACL_EveryoneRX,
38 .Flags = VFS_FFLAG_DIRECTORY,
39 .ReadDir = FDD_ReadDir,
40 .FindDir = FDD_FindDir,
46 int FDD_Install(char **Arguments)
54 // NOTE: CMOS only reports 2 disks
55 if( (data & 0xF0) == 0x40 )
56 gaFDD_Disks[0].bValid = gaFDD_Disks[0].bInserted = 1;
57 if( (data & 0x0F) == 0x04 )
58 gaFDD_Disks[1].bValid = gaFDD_Disks[1].bInserted = 1;
60 if( gaFDD_Disks[0].bValid == 0 && gaFDD_Disks[1].bValid == 0 )
61 return MODULE_ERR_NOTNEEDED;
64 // Initialise controller
73 * \brief Register the FDD driver with DevFS
75 int FDD_RegisterFS(void)
77 gFDD_DriverInfo.RootNode.CTime = gFDD_DriverInfo.RootNode.MTime
78 = gFDD_DriverInfo.RootNode.ATime = now();
80 for( int i = 0; i < MAX_DISKS; i ++ )
82 if( !gaFDD_Disks[i].bValid ) continue ;
84 // Initialise Child Nodes
85 gaFDD_DiskNodes[i].Inode = i;
86 gaFDD_DiskNodes[i].Flags = 0;
87 gaFDD_DiskNodes[i].NumACLs = 0;
88 gaFDD_DiskNodes[i].Read = FDD_ReadFS;
89 gaFDD_DiskNodes[i].Write = NULL;//FDD_WriteFS;
90 gaFDD_DiskNodes[i].Size = 1440*1024; // TODO: Non 1.44 disks
93 DevFS_AddDevice( &gFDD_DriverInfo );
97 * \brief Get the name of the \a Pos th item in the driver root
98 * \param Node Root node (unused)
100 * \return Heap string of node name
102 char *FDD_ReadDir(tVFS_Node *Node, int Pos)
105 if(Pos < 0 || Pos > MAX_DISKS )
107 if(gaFDD_Disks[Pos].bValid)
110 ret_tpl[0] = '0' + Pos;
112 return strdup(ret_tpl);
116 * \brief Get a node by name
117 * \param Node Root node (unused)
118 * \param Name Drive name
119 * \return Pointer to node structure
121 tVFS_Node *FDD_FindDir(tVFS_Node *Node, const char *Name)
124 if( '0' > Name[0] || Name[0] > '9' ) return NULL;
125 if( Name[1] != '\0' ) return NULL;
129 return &gaFDD_DiskNodes[pos];
132 static const char *casIOCTLS[] = {DRV_IOCTLNAMES,DRV_DISK_IOCTLNAMES,NULL};
134 * \brief Driver root IOCtl Handler
135 * \param Node Root node (unused)
137 * \param Data IOCtl specific data pointer
139 int FDD_IOCtl(tVFS_Node *Node, int ID, void *Data)
143 BASE_IOCTLS(DRV_TYPE_DISK, "FDDv2", FDD_VERSION, casIOCTLS);
145 case DISK_IOCTL_GETBLOCKSIZE: return 512;
153 * \brief Read from a disk
154 * \param Node Disk node
155 * \param Offset Byte offset in disk
156 * \param Length Number of bytes to read
157 * \param Buffer Destination buffer
158 * \return Number of bytes read
160 Uint64 FDD_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
162 int disk = Node->Inode;
165 track = Offset / BYTES_PER_TRACK;
167 if( Offset % BYTES_PER_TRACK )
174 * \brief Read from a track
176 int FDD_int_ReadWriteWithinTrack(int Disk, int Track, int bWrite, size_t Offset, size_t Length, void *Buffer)
178 if( Offset > BYTES_PER_TRACK || Length > BYTES_PER_TRACK )
180 if( Offset + Length > BYTES_PER_TRACK )
183 Mutex_Acquire( &gaFDD_Disks[Disk].Mutex );
185 // If the cache doesn't exist, create it
186 if( !gaFDD_Disks[Disk].TrackData[Track] )
188 gaFDD_Disks[Disk].TrackData[Track] = malloc( BYTES_PER_TRACK );
189 // Don't bother reading if this is a whole track write
190 if( !(bWrite && Offset == 0 && Length == BYTES_PER_TRACK) )
192 FDD_int_ReadWriteTrack(Disk, Track, 0, gaFDD_Disks[Disk].TrackData[Track]);
199 // Write to cache then commit cache to disk
200 char *dest = gaFDD_Disks[Disk].TrackData[Track];
201 memcpy( dest + Offset, Buffer, Length );
202 FDD_int_ReadWriteTrack(Disk, Track, 1, gaFDD_Disks[Disk].TrackData[Track]);
207 char *src = gaFDD_Disks[Disk].TrackData[Track];
208 memcpy(Buffer, src + Offset, Length);
211 Mutex_Release( &gaFDD_Disks[Disk].Mutex );