1/*
2 * Copyright 2003-2008, Haiku.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Fran��ois Revol <revol@free.fr>
7 */
8
9#ifndef _FLOPPY_H
10#define _FLOPPY_H
11
12#include <Drivers.h>
13#include <ISA.h>
14#include <KernelExport.h>
15
16// TODO: switch to native lock.
17#ifdef __HAIKU__
18#include <lock.h>
19typedef recursive_lock lock;
20#define new_lock recursive_lock_init
21#define free_lock recursive_lock_destroy
22#define	LOCK(l)		recursive_lock_lock(&l);
23#define	UNLOCK(l)	recursive_lock_unlock(&l);
24#else
25#ifndef _IMPEXP_KERNEL
26#define _IMPEXP_KERNEL
27#endif
28#include "lock.h"
29#endif
30
31#define FLO "floppy: "
32#if defined(DEBUG) && DEBUG > 0
33#	define TRACE(x...) dprintf(FLO x)
34#else
35#	define TRACE(x...)
36#endif
37
38#define MOTOR_TIMEOUT 5000000		// 5 seconds
39#define MOTOR_SPINUP_DELAY 500000	// 500 msecs
40#define FLOPPY_CMD_TIMEOUT 500000 // .5s
41#define MAX_DRIVES_PER_CTRL 2
42#define CYL_BUFFER_SIZE (5*B_PAGE_SIZE)
43
44/*** those belong to ISA.h ***/
45#define B_DMA_MODE_DEMAND 0x00     // modeByte bits for various dma modes
46#define B_DMA_MODE_BLOCK  0x80
47#define B_DMA_MODE_SINGLE 0x40
48
49#define B_DMA_MODE_MEMR 0x08       // modeByte memory read or write
50#define B_DMA_MODE_MEMW 0x04
51/*** !ISA.h ***/
52
53typedef enum {
54	FLOP_NO_MEDIA,
55	FLOP_MEDIA_CHANGED,
56	FLOP_MEDIA_UNREADABLE,
57	FLOP_MEDIA_FORMAT_FOUND,
58	FLOP_WORKING
59} floppy_status;
60
61#define CMD_MODE	0x01
62#define CMD_SETTRK	0x21	//21
63#define CMD_READTRK	0x02
64#define CMD_SPECIFY	0x03
65#define CMD_SENSED	0x04
66#define CMD_WRITED	0x05
67#define CMD_READD	0x06
68#define CMD_RECAL	0x07
69#define CMD_SENSEI	0x08
70#define CMD_WRITEDD	0x09
71#define CMD_READID	0x0A
72#define CMD_READDD	0x0C
73#define CMD_FORMAT	0x0D
74#define CMD_DUMPREG	0x0E
75#define CMD_SEEK	0x0F
76#define CMD_RELSEEK	0x8F	//8F
77#define CMD_VERSION	0x10
78#define CMD_SCANE	0x11
79#define CMD_PERPEND	0x12
80#define CMD_CONFIG	0x13
81#define CMD_LOCK	0x14
82#define CMD_VERIFY	0x16
83#define CMD_SCANLE	0x19
84#define CMD_SCANHE	0x1D
85
86#define CMD_RESET	0xF0
87#define CMD_SWITCH_MASK	0x1F
88
89typedef struct floppy_geometry {
90	int gap;
91	int numsectors;
92	int data_rate;
93	int format_gap;
94	int side2_offset;
95	device_geometry g;
96	int flags;
97	const char *name;
98} floppy_geometry;
99
100extern const floppy_geometry supported_geometries[];
101
102#define FL_MFM		0x0001	/* MFM recording */
103#define FL_2STEP	0x0002	/* 2 steps between cylinders */
104#define FL_PERP		0x0004	/* perpendicular recording */
105
106#define FDC_500KBPS	0x00	/* 500KBPS MFM drive transfer rate */
107#define FDC_300KBPS	0x01	/* 300KBPS MFM drive transfer rate */
108#define FDC_250KBPS	0x02	/* 250KBPS MFM drive transfer rate */
109#define FDC_1MBPS	0x03	/* 1MPBS MFM drive transfer rate */
110
111#define FDC_MAX_CYLINDER 85
112
113typedef struct floppy {
114	const floppy_geometry *geometry;
115	device_geometry bgeom;
116	uint32 iobase;	/* controller address */
117	uint32 irq;
118	int32 dma;
119	int drive_num;	/* number of this drive */
120	int current;	/* currently selected drive */
121	floppy_status status;
122	sem_id completion;
123	uint16 pending_cmd;
124	uint8 result[8]; /* status of the last finished command */
125
126	lock ben;
127	spinlock slock;
128	isa_module_info *isa;
129
130	uint8 data_rate; /* FDC_*BPS */
131	uint32 motor_timeout;
132
133	area_id buffer_area;
134	uint8 *buffer;
135	long buffer_index; /* index at which to put/get the next byte in the buffer */
136	long avail;	/* valid bytes in the buffer */
137	int track;	/* the track currently in the cylinder buffer */
138
139	struct floppy *master; /* the 'controller' */
140	struct floppy *next; /* next floppy for same controller */
141} floppy_t;
142
143typedef struct {
144	uint8 id;
145	uint8 drive;
146	uint8 cylinder;
147	uint8 head;
148	uint8 sector;
149	uint8 sector_size;
150	uint8 track_length;
151	uint8 gap3_length;
152	uint8 data_length;
153} floppy_command;
154
155typedef struct {
156	uint8 st0;
157	uint8 st1;
158	uint8 st2;
159	uint8 cylinder;
160	uint8 head;
161	uint8 sector;
162	uint8 sector_size;
163} floppy_result;
164
165typedef enum {
166	STATUS_A = 0,
167	STATUS_B = 1,
168	DIGITAL_OUT = 2,
169	TAPE_DRIVE = 3,
170	MAIN_STATUS = 4,
171	DATA_RATE_SELECT = 4,
172	DATA = 5,
173	/* RESERVED = 6, */
174	DIGITAL_IN = 7,
175	CONFIG_CONTROL = 7
176} floppy_reg_selector;
177
178#define FDC_SR0_IC 0xc0
179#define FDC_SR0_SE 0x20
180#define FDC_SR0_EC 0x10
181#define FDC_SR0_HS 0x04
182#define FDC_SR0_DS 0x03
183
184/* low level */
185extern void write_reg(floppy_t *flp, floppy_reg_selector selector, uint8 data);
186extern uint8 read_reg(floppy_t *flp, floppy_reg_selector selector);
187
188/* init */
189	/* initialize the controller */
190extern void reset_controller(floppy_t *master);
191	/* returns a bitmap of the present drives */
192extern int count_floppies(floppy_t *master);
193	/* seek to track 0 and detect drive presence */
194extern int recalibrate_drive(floppy_t *flp);
195/* debug */
196	/* issue dumpreg command */
197extern void floppy_dump_reg(floppy_t *flp);
198
199/* drive handling */
200extern void drive_select(floppy_t *flp);
201extern void drive_deselect(floppy_t *flp);
202extern void turn_on_motor(floppy_t *flp);
203extern void turn_off_motor(floppy_t *flp);
204
205/* transactions */
206extern void wait_for_rqm(floppy_t *flp);
207extern bool can_read_result(floppy_t *flp);
208	/* send a command and schedule for irq */
209extern int send_command(floppy_t *flp, const uint8 *data, int len);
210extern int wait_til_ready(floppy_t *flp);
211	/* called by irq handler */
212extern int read_result(floppy_t *flp, uint8 *data, int len);
213	/* wait for the irq to occur */
214extern int wait_result(floppy_t *flp);
215
216extern int32 flo_intr(void *arg);
217
218	/* read sectors to internal flp->master->buffer */
219extern ssize_t pio_read_sectors(floppy_t *flp, int lba, int num_sectors);
220	/* write sectors from internal flp->master->buffer */
221extern ssize_t pio_write_sectors(floppy_t *flp, int lba, int num_sectors);
222	/* read a track to internal flp->master->buffer */
223extern ssize_t pio_read_track(floppy_t *flp, int lba);
224
225/* high level */
226	/* query the media type and fill the geometry information */
227extern status_t query_media(floppy_t *flp, bool forceupdate);
228
229extern ssize_t read_sectors(floppy_t *flp, int lba, int num_sectors);
230
231#endif	/* _FLOPPY_H */
232