fdc.c 60 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937
  1. /*
  2. * QEMU Floppy disk emulator (Intel 82078)
  3. *
  4. * Copyright (c) 2003, 2007 Jocelyn Mayer
  5. * Copyright (c) 2008 Hervé Poussineau
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy
  8. * of this software and associated documentation files (the "Software"), to deal
  9. * in the Software without restriction, including without limitation the rights
  10. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. * copies of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. * THE SOFTWARE.
  24. */
  25. /*
  26. * The controller is used in Sun4m systems in a slightly different
  27. * way. There are changes in DOR register and DMA is not available.
  28. */
  29. #include "hw.h"
  30. #include "fdc.h"
  31. #include "block.h"
  32. #include "qemu-timer.h"
  33. #include "isa.h"
  34. /********************************************************/
  35. /* debug Floppy devices */
  36. //#define DEBUG_FLOPPY
  37. #ifdef DEBUG_FLOPPY
  38. #define FLOPPY_DPRINTF(fmt, args...) \
  39. do { printf("FLOPPY: " fmt , ##args); } while (0)
  40. #else
  41. #define FLOPPY_DPRINTF(fmt, args...)
  42. #endif
  43. #define FLOPPY_ERROR(fmt, args...) \
  44. do { printf("FLOPPY ERROR: %s: " fmt, __func__ , ##args); } while (0)
  45. /********************************************************/
  46. /* Floppy drive emulation */
  47. #define GET_CUR_DRV(fdctrl) ((fdctrl)->cur_drv)
  48. #define SET_CUR_DRV(fdctrl, drive) ((fdctrl)->cur_drv = (drive))
  49. /* Will always be a fixed parameter for us */
  50. #define FD_SECTOR_LEN 512
  51. #define FD_SECTOR_SC 2 /* Sector size code */
  52. #define FD_RESET_SENSEI_COUNT 4 /* Number of sense interrupts on RESET */
  53. /* Floppy disk drive emulation */
  54. typedef enum fdisk_type_t {
  55. FDRIVE_DISK_288 = 0x01, /* 2.88 MB disk */
  56. FDRIVE_DISK_144 = 0x02, /* 1.44 MB disk */
  57. FDRIVE_DISK_720 = 0x03, /* 720 kB disk */
  58. FDRIVE_DISK_USER = 0x04, /* User defined geometry */
  59. FDRIVE_DISK_NONE = 0x05, /* No disk */
  60. } fdisk_type_t;
  61. typedef enum fdrive_type_t {
  62. FDRIVE_DRV_144 = 0x00, /* 1.44 MB 3"5 drive */
  63. FDRIVE_DRV_288 = 0x01, /* 2.88 MB 3"5 drive */
  64. FDRIVE_DRV_120 = 0x02, /* 1.2 MB 5"25 drive */
  65. FDRIVE_DRV_NONE = 0x03, /* No drive connected */
  66. } fdrive_type_t;
  67. typedef enum fdisk_flags_t {
  68. FDISK_DBL_SIDES = 0x01,
  69. } fdisk_flags_t;
  70. typedef struct fdrive_t {
  71. BlockDriverState *bs;
  72. /* Drive status */
  73. fdrive_type_t drive;
  74. uint8_t perpendicular; /* 2.88 MB access mode */
  75. /* Position */
  76. uint8_t head;
  77. uint8_t track;
  78. uint8_t sect;
  79. /* Media */
  80. fdisk_flags_t flags;
  81. uint8_t last_sect; /* Nb sector per track */
  82. uint8_t max_track; /* Nb of tracks */
  83. uint16_t bps; /* Bytes per sector */
  84. uint8_t ro; /* Is read-only */
  85. } fdrive_t;
  86. static void fd_init (fdrive_t *drv, BlockDriverState *bs)
  87. {
  88. /* Drive */
  89. drv->bs = bs;
  90. drv->drive = FDRIVE_DRV_NONE;
  91. drv->perpendicular = 0;
  92. /* Disk */
  93. drv->last_sect = 0;
  94. drv->max_track = 0;
  95. }
  96. static int _fd_sector (uint8_t head, uint8_t track,
  97. uint8_t sect, uint8_t last_sect)
  98. {
  99. return (((track * 2) + head) * last_sect) + sect - 1;
  100. }
  101. /* Returns current position, in sectors, for given drive */
  102. static int fd_sector (fdrive_t *drv)
  103. {
  104. return _fd_sector(drv->head, drv->track, drv->sect, drv->last_sect);
  105. }
  106. /* Seek to a new position:
  107. * returns 0 if already on right track
  108. * returns 1 if track changed
  109. * returns 2 if track is invalid
  110. * returns 3 if sector is invalid
  111. * returns 4 if seek is disabled
  112. */
  113. static int fd_seek (fdrive_t *drv, uint8_t head, uint8_t track, uint8_t sect,
  114. int enable_seek)
  115. {
  116. uint32_t sector;
  117. int ret;
  118. if (track > drv->max_track ||
  119. (head != 0 && (drv->flags & FDISK_DBL_SIDES) == 0)) {
  120. FLOPPY_DPRINTF("try to read %d %02x %02x (max=%d %d %02x %02x)\n",
  121. head, track, sect, 1,
  122. (drv->flags & FDISK_DBL_SIDES) == 0 ? 0 : 1,
  123. drv->max_track, drv->last_sect);
  124. return 2;
  125. }
  126. if (sect > drv->last_sect) {
  127. FLOPPY_DPRINTF("try to read %d %02x %02x (max=%d %d %02x %02x)\n",
  128. head, track, sect, 1,
  129. (drv->flags & FDISK_DBL_SIDES) == 0 ? 0 : 1,
  130. drv->max_track, drv->last_sect);
  131. return 3;
  132. }
  133. sector = _fd_sector(head, track, sect, drv->last_sect);
  134. ret = 0;
  135. if (sector != fd_sector(drv)) {
  136. #if 0
  137. if (!enable_seek) {
  138. FLOPPY_ERROR("no implicit seek %d %02x %02x (max=%d %02x %02x)\n",
  139. head, track, sect, 1, drv->max_track, drv->last_sect);
  140. return 4;
  141. }
  142. #endif
  143. drv->head = head;
  144. if (drv->track != track)
  145. ret = 1;
  146. drv->track = track;
  147. drv->sect = sect;
  148. }
  149. return ret;
  150. }
  151. /* Set drive back to track 0 */
  152. static void fd_recalibrate (fdrive_t *drv)
  153. {
  154. FLOPPY_DPRINTF("recalibrate\n");
  155. drv->head = 0;
  156. drv->track = 0;
  157. drv->sect = 1;
  158. }
  159. /* Recognize floppy formats */
  160. typedef struct fd_format_t {
  161. fdrive_type_t drive;
  162. fdisk_type_t disk;
  163. uint8_t last_sect;
  164. uint8_t max_track;
  165. uint8_t max_head;
  166. const char *str;
  167. } fd_format_t;
  168. static const fd_format_t fd_formats[] = {
  169. /* First entry is default format */
  170. /* 1.44 MB 3"1/2 floppy disks */
  171. { FDRIVE_DRV_144, FDRIVE_DISK_144, 18, 80, 1, "1.44 MB 3\"1/2", },
  172. { FDRIVE_DRV_144, FDRIVE_DISK_144, 20, 80, 1, "1.6 MB 3\"1/2", },
  173. { FDRIVE_DRV_144, FDRIVE_DISK_144, 21, 80, 1, "1.68 MB 3\"1/2", },
  174. { FDRIVE_DRV_144, FDRIVE_DISK_144, 21, 82, 1, "1.72 MB 3\"1/2", },
  175. { FDRIVE_DRV_144, FDRIVE_DISK_144, 21, 83, 1, "1.74 MB 3\"1/2", },
  176. { FDRIVE_DRV_144, FDRIVE_DISK_144, 22, 80, 1, "1.76 MB 3\"1/2", },
  177. { FDRIVE_DRV_144, FDRIVE_DISK_144, 23, 80, 1, "1.84 MB 3\"1/2", },
  178. { FDRIVE_DRV_144, FDRIVE_DISK_144, 24, 80, 1, "1.92 MB 3\"1/2", },
  179. /* 2.88 MB 3"1/2 floppy disks */
  180. { FDRIVE_DRV_288, FDRIVE_DISK_288, 36, 80, 1, "2.88 MB 3\"1/2", },
  181. { FDRIVE_DRV_288, FDRIVE_DISK_288, 39, 80, 1, "3.12 MB 3\"1/2", },
  182. { FDRIVE_DRV_288, FDRIVE_DISK_288, 40, 80, 1, "3.2 MB 3\"1/2", },
  183. { FDRIVE_DRV_288, FDRIVE_DISK_288, 44, 80, 1, "3.52 MB 3\"1/2", },
  184. { FDRIVE_DRV_288, FDRIVE_DISK_288, 48, 80, 1, "3.84 MB 3\"1/2", },
  185. /* 720 kB 3"1/2 floppy disks */
  186. { FDRIVE_DRV_144, FDRIVE_DISK_720, 9, 80, 1, "720 kB 3\"1/2", },
  187. { FDRIVE_DRV_144, FDRIVE_DISK_720, 10, 80, 1, "800 kB 3\"1/2", },
  188. { FDRIVE_DRV_144, FDRIVE_DISK_720, 10, 82, 1, "820 kB 3\"1/2", },
  189. { FDRIVE_DRV_144, FDRIVE_DISK_720, 10, 83, 1, "830 kB 3\"1/2", },
  190. { FDRIVE_DRV_144, FDRIVE_DISK_720, 13, 80, 1, "1.04 MB 3\"1/2", },
  191. { FDRIVE_DRV_144, FDRIVE_DISK_720, 14, 80, 1, "1.12 MB 3\"1/2", },
  192. /* 1.2 MB 5"1/4 floppy disks */
  193. { FDRIVE_DRV_120, FDRIVE_DISK_288, 15, 80, 1, "1.2 kB 5\"1/4", },
  194. { FDRIVE_DRV_120, FDRIVE_DISK_288, 18, 80, 1, "1.44 MB 5\"1/4", },
  195. { FDRIVE_DRV_120, FDRIVE_DISK_288, 18, 82, 1, "1.48 MB 5\"1/4", },
  196. { FDRIVE_DRV_120, FDRIVE_DISK_288, 18, 83, 1, "1.49 MB 5\"1/4", },
  197. { FDRIVE_DRV_120, FDRIVE_DISK_288, 20, 80, 1, "1.6 MB 5\"1/4", },
  198. /* 720 kB 5"1/4 floppy disks */
  199. { FDRIVE_DRV_120, FDRIVE_DISK_288, 9, 80, 1, "720 kB 5\"1/4", },
  200. { FDRIVE_DRV_120, FDRIVE_DISK_288, 11, 80, 1, "880 kB 5\"1/4", },
  201. /* 360 kB 5"1/4 floppy disks */
  202. { FDRIVE_DRV_120, FDRIVE_DISK_288, 9, 40, 1, "360 kB 5\"1/4", },
  203. { FDRIVE_DRV_120, FDRIVE_DISK_288, 9, 40, 0, "180 kB 5\"1/4", },
  204. { FDRIVE_DRV_120, FDRIVE_DISK_288, 10, 41, 1, "410 kB 5\"1/4", },
  205. { FDRIVE_DRV_120, FDRIVE_DISK_288, 10, 42, 1, "420 kB 5\"1/4", },
  206. /* 320 kB 5"1/4 floppy disks */
  207. { FDRIVE_DRV_120, FDRIVE_DISK_288, 8, 40, 1, "320 kB 5\"1/4", },
  208. { FDRIVE_DRV_120, FDRIVE_DISK_288, 8, 40, 0, "160 kB 5\"1/4", },
  209. /* 360 kB must match 5"1/4 better than 3"1/2... */
  210. { FDRIVE_DRV_144, FDRIVE_DISK_720, 9, 80, 0, "360 kB 3\"1/2", },
  211. /* end */
  212. { FDRIVE_DRV_NONE, FDRIVE_DISK_NONE, -1, -1, 0, NULL, },
  213. };
  214. /* Revalidate a disk drive after a disk change */
  215. static void fd_revalidate (fdrive_t *drv)
  216. {
  217. const fd_format_t *parse;
  218. uint64_t nb_sectors, size;
  219. int i, first_match, match;
  220. int nb_heads, max_track, last_sect, ro;
  221. FLOPPY_DPRINTF("revalidate\n");
  222. if (drv->bs != NULL && bdrv_is_inserted(drv->bs)) {
  223. ro = bdrv_is_read_only(drv->bs);
  224. bdrv_get_geometry_hint(drv->bs, &nb_heads, &max_track, &last_sect);
  225. if (nb_heads != 0 && max_track != 0 && last_sect != 0) {
  226. FLOPPY_DPRINTF("User defined disk (%d %d %d)",
  227. nb_heads - 1, max_track, last_sect);
  228. } else {
  229. bdrv_get_geometry(drv->bs, &nb_sectors);
  230. match = -1;
  231. first_match = -1;
  232. for (i = 0;; i++) {
  233. parse = &fd_formats[i];
  234. if (parse->drive == FDRIVE_DRV_NONE)
  235. break;
  236. if (drv->drive == parse->drive ||
  237. drv->drive == FDRIVE_DRV_NONE) {
  238. size = (parse->max_head + 1) * parse->max_track *
  239. parse->last_sect;
  240. if (nb_sectors == size) {
  241. match = i;
  242. break;
  243. }
  244. if (first_match == -1)
  245. first_match = i;
  246. }
  247. }
  248. if (match == -1) {
  249. if (first_match == -1)
  250. match = 1;
  251. else
  252. match = first_match;
  253. parse = &fd_formats[match];
  254. }
  255. nb_heads = parse->max_head + 1;
  256. max_track = parse->max_track;
  257. last_sect = parse->last_sect;
  258. drv->drive = parse->drive;
  259. FLOPPY_DPRINTF("%s floppy disk (%d h %d t %d s) %s\n", parse->str,
  260. nb_heads, max_track, last_sect, ro ? "ro" : "rw");
  261. }
  262. if (nb_heads == 1) {
  263. drv->flags &= ~FDISK_DBL_SIDES;
  264. } else {
  265. drv->flags |= FDISK_DBL_SIDES;
  266. }
  267. drv->max_track = max_track;
  268. drv->last_sect = last_sect;
  269. drv->ro = ro;
  270. } else {
  271. FLOPPY_DPRINTF("No disk in drive\n");
  272. drv->last_sect = 0;
  273. drv->max_track = 0;
  274. drv->flags &= ~FDISK_DBL_SIDES;
  275. }
  276. }
  277. /********************************************************/
  278. /* Intel 82078 floppy disk controller emulation */
  279. static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq);
  280. static void fdctrl_reset_fifo (fdctrl_t *fdctrl);
  281. static int fdctrl_transfer_handler (void *opaque, int nchan,
  282. int dma_pos, int dma_len);
  283. static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status0);
  284. static uint32_t fdctrl_read_statusA (fdctrl_t *fdctrl);
  285. static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl);
  286. static uint32_t fdctrl_read_dor (fdctrl_t *fdctrl);
  287. static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value);
  288. static uint32_t fdctrl_read_tape (fdctrl_t *fdctrl);
  289. static void fdctrl_write_tape (fdctrl_t *fdctrl, uint32_t value);
  290. static uint32_t fdctrl_read_main_status (fdctrl_t *fdctrl);
  291. static void fdctrl_write_rate (fdctrl_t *fdctrl, uint32_t value);
  292. static uint32_t fdctrl_read_data (fdctrl_t *fdctrl);
  293. static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value);
  294. static uint32_t fdctrl_read_dir (fdctrl_t *fdctrl);
  295. enum {
  296. FD_DIR_WRITE = 0,
  297. FD_DIR_READ = 1,
  298. FD_DIR_SCANE = 2,
  299. FD_DIR_SCANL = 3,
  300. FD_DIR_SCANH = 4,
  301. };
  302. enum {
  303. FD_STATE_MULTI = 0x01, /* multi track flag */
  304. FD_STATE_FORMAT = 0x02, /* format flag */
  305. FD_STATE_SEEK = 0x04, /* seek flag */
  306. };
  307. enum {
  308. FD_REG_SRA = 0x00,
  309. FD_REG_SRB = 0x01,
  310. FD_REG_DOR = 0x02,
  311. FD_REG_TDR = 0x03,
  312. FD_REG_MSR = 0x04,
  313. FD_REG_DSR = 0x04,
  314. FD_REG_FIFO = 0x05,
  315. FD_REG_DIR = 0x07,
  316. };
  317. enum {
  318. FD_CMD_READ_TRACK = 0x02,
  319. FD_CMD_SPECIFY = 0x03,
  320. FD_CMD_SENSE_DRIVE_STATUS = 0x04,
  321. FD_CMD_WRITE = 0x05,
  322. FD_CMD_READ = 0x06,
  323. FD_CMD_RECALIBRATE = 0x07,
  324. FD_CMD_SENSE_INTERRUPT_STATUS = 0x08,
  325. FD_CMD_WRITE_DELETED = 0x09,
  326. FD_CMD_READ_ID = 0x0a,
  327. FD_CMD_READ_DELETED = 0x0c,
  328. FD_CMD_FORMAT_TRACK = 0x0d,
  329. FD_CMD_DUMPREG = 0x0e,
  330. FD_CMD_SEEK = 0x0f,
  331. FD_CMD_VERSION = 0x10,
  332. FD_CMD_SCAN_EQUAL = 0x11,
  333. FD_CMD_PERPENDICULAR_MODE = 0x12,
  334. FD_CMD_CONFIGURE = 0x13,
  335. FD_CMD_LOCK = 0x14,
  336. FD_CMD_VERIFY = 0x16,
  337. FD_CMD_POWERDOWN_MODE = 0x17,
  338. FD_CMD_PART_ID = 0x18,
  339. FD_CMD_SCAN_LOW_OR_EQUAL = 0x19,
  340. FD_CMD_SCAN_HIGH_OR_EQUAL = 0x1d,
  341. FD_CMD_SAVE = 0x2c,
  342. FD_CMD_OPTION = 0x33,
  343. FD_CMD_RESTORE = 0x4c,
  344. FD_CMD_DRIVE_SPECIFICATION_COMMAND = 0x8e,
  345. FD_CMD_RELATIVE_SEEK_OUT = 0x8f,
  346. FD_CMD_FORMAT_AND_WRITE = 0xcd,
  347. FD_CMD_RELATIVE_SEEK_IN = 0xcf,
  348. };
  349. enum {
  350. FD_CONFIG_PRETRK = 0xff, /* Pre-compensation set to track 0 */
  351. FD_CONFIG_FIFOTHR = 0x0f, /* FIFO threshold set to 1 byte */
  352. FD_CONFIG_POLL = 0x10, /* Poll enabled */
  353. FD_CONFIG_EFIFO = 0x20, /* FIFO disabled */
  354. FD_CONFIG_EIS = 0x40, /* No implied seeks */
  355. };
  356. enum {
  357. FD_SR0_EQPMT = 0x10,
  358. FD_SR0_SEEK = 0x20,
  359. FD_SR0_ABNTERM = 0x40,
  360. FD_SR0_INVCMD = 0x80,
  361. FD_SR0_RDYCHG = 0xc0,
  362. };
  363. enum {
  364. FD_SR1_EC = 0x80, /* End of cylinder */
  365. };
  366. enum {
  367. FD_SR2_SNS = 0x04, /* Scan not satisfied */
  368. FD_SR2_SEH = 0x08, /* Scan equal hit */
  369. };
  370. enum {
  371. FD_SRA_DIR = 0x01,
  372. FD_SRA_nWP = 0x02,
  373. FD_SRA_nINDX = 0x04,
  374. FD_SRA_HDSEL = 0x08,
  375. FD_SRA_nTRK0 = 0x10,
  376. FD_SRA_STEP = 0x20,
  377. FD_SRA_nDRV2 = 0x40,
  378. FD_SRA_INTPEND = 0x80,
  379. };
  380. enum {
  381. FD_SRB_MTR0 = 0x01,
  382. FD_SRB_MTR1 = 0x02,
  383. FD_SRB_WGATE = 0x04,
  384. FD_SRB_RDATA = 0x08,
  385. FD_SRB_WDATA = 0x10,
  386. FD_SRB_DR0 = 0x20,
  387. };
  388. enum {
  389. #if MAX_FD == 4
  390. FD_DOR_SELMASK = 0x03,
  391. #else
  392. FD_DOR_SELMASK = 0x01,
  393. #endif
  394. FD_DOR_nRESET = 0x04,
  395. FD_DOR_DMAEN = 0x08,
  396. FD_DOR_MOTEN0 = 0x10,
  397. FD_DOR_MOTEN1 = 0x20,
  398. FD_DOR_MOTEN2 = 0x40,
  399. FD_DOR_MOTEN3 = 0x80,
  400. };
  401. enum {
  402. #if MAX_FD == 4
  403. FD_TDR_BOOTSEL = 0x0c,
  404. #else
  405. FD_TDR_BOOTSEL = 0x04,
  406. #endif
  407. };
  408. enum {
  409. FD_DSR_DRATEMASK= 0x03,
  410. FD_DSR_PWRDOWN = 0x40,
  411. FD_DSR_SWRESET = 0x80,
  412. };
  413. enum {
  414. FD_MSR_DRV0BUSY = 0x01,
  415. FD_MSR_DRV1BUSY = 0x02,
  416. FD_MSR_DRV2BUSY = 0x04,
  417. FD_MSR_DRV3BUSY = 0x08,
  418. FD_MSR_CMDBUSY = 0x10,
  419. FD_MSR_NONDMA = 0x20,
  420. FD_MSR_DIO = 0x40,
  421. FD_MSR_RQM = 0x80,
  422. };
  423. enum {
  424. FD_DIR_DSKCHG = 0x80,
  425. };
  426. #define FD_MULTI_TRACK(state) ((state) & FD_STATE_MULTI)
  427. #define FD_DID_SEEK(state) ((state) & FD_STATE_SEEK)
  428. #define FD_FORMAT_CMD(state) ((state) & FD_STATE_FORMAT)
  429. struct fdctrl_t {
  430. /* Controller's identification */
  431. uint8_t version;
  432. /* HW */
  433. qemu_irq irq;
  434. int dma_chann;
  435. target_phys_addr_t io_base;
  436. /* Controller state */
  437. QEMUTimer *result_timer;
  438. uint8_t sra;
  439. uint8_t srb;
  440. uint8_t dor;
  441. uint8_t tdr;
  442. uint8_t dsr;
  443. uint8_t msr;
  444. uint8_t cur_drv;
  445. uint8_t status0;
  446. uint8_t status1;
  447. uint8_t status2;
  448. /* Command FIFO */
  449. uint8_t *fifo;
  450. uint32_t data_pos;
  451. uint32_t data_len;
  452. uint8_t data_state;
  453. uint8_t data_dir;
  454. uint8_t eot; /* last wanted sector */
  455. /* States kept only to be returned back */
  456. /* Timers state */
  457. uint8_t timer0;
  458. uint8_t timer1;
  459. /* precompensation */
  460. uint8_t precomp_trk;
  461. uint8_t config;
  462. uint8_t lock;
  463. /* Power down config (also with status regB access mode */
  464. uint8_t pwrd;
  465. /* Sun4m quirks? */
  466. int sun4m;
  467. /* Floppy drives */
  468. fdrive_t drives[MAX_FD];
  469. int reset_sensei;
  470. };
  471. static uint32_t fdctrl_read (void *opaque, uint32_t reg)
  472. {
  473. fdctrl_t *fdctrl = opaque;
  474. uint32_t retval;
  475. switch (reg) {
  476. case FD_REG_SRA:
  477. retval = fdctrl_read_statusA(fdctrl);
  478. break;
  479. case FD_REG_SRB:
  480. retval = fdctrl_read_statusB(fdctrl);
  481. break;
  482. case FD_REG_DOR:
  483. retval = fdctrl_read_dor(fdctrl);
  484. break;
  485. case FD_REG_TDR:
  486. retval = fdctrl_read_tape(fdctrl);
  487. break;
  488. case FD_REG_MSR:
  489. retval = fdctrl_read_main_status(fdctrl);
  490. break;
  491. case FD_REG_FIFO:
  492. retval = fdctrl_read_data(fdctrl);
  493. break;
  494. case FD_REG_DIR:
  495. retval = fdctrl_read_dir(fdctrl);
  496. break;
  497. default:
  498. retval = (uint32_t)(-1);
  499. break;
  500. }
  501. FLOPPY_DPRINTF("read reg%d: 0x%02x\n", reg & 7, retval);
  502. return retval;
  503. }
  504. static void fdctrl_write (void *opaque, uint32_t reg, uint32_t value)
  505. {
  506. fdctrl_t *fdctrl = opaque;
  507. FLOPPY_DPRINTF("write reg%d: 0x%02x\n", reg & 7, value);
  508. switch (reg) {
  509. case FD_REG_DOR:
  510. fdctrl_write_dor(fdctrl, value);
  511. break;
  512. case FD_REG_TDR:
  513. fdctrl_write_tape(fdctrl, value);
  514. break;
  515. case FD_REG_DSR:
  516. fdctrl_write_rate(fdctrl, value);
  517. break;
  518. case FD_REG_FIFO:
  519. fdctrl_write_data(fdctrl, value);
  520. break;
  521. default:
  522. break;
  523. }
  524. }
  525. static uint32_t fdctrl_read_port (void *opaque, uint32_t reg)
  526. {
  527. return fdctrl_read(opaque, reg & 7);
  528. }
  529. static void fdctrl_write_port (void *opaque, uint32_t reg, uint32_t value)
  530. {
  531. fdctrl_write(opaque, reg & 7, value);
  532. }
  533. static uint32_t fdctrl_read_mem (void *opaque, target_phys_addr_t reg)
  534. {
  535. return fdctrl_read(opaque, (uint32_t)reg);
  536. }
  537. static void fdctrl_write_mem (void *opaque,
  538. target_phys_addr_t reg, uint32_t value)
  539. {
  540. fdctrl_write(opaque, (uint32_t)reg, value);
  541. }
  542. static CPUReadMemoryFunc *fdctrl_mem_read[3] = {
  543. fdctrl_read_mem,
  544. fdctrl_read_mem,
  545. fdctrl_read_mem,
  546. };
  547. static CPUWriteMemoryFunc *fdctrl_mem_write[3] = {
  548. fdctrl_write_mem,
  549. fdctrl_write_mem,
  550. fdctrl_write_mem,
  551. };
  552. static CPUReadMemoryFunc *fdctrl_mem_read_strict[3] = {
  553. fdctrl_read_mem,
  554. NULL,
  555. NULL,
  556. };
  557. static CPUWriteMemoryFunc *fdctrl_mem_write_strict[3] = {
  558. fdctrl_write_mem,
  559. NULL,
  560. NULL,
  561. };
  562. static void fd_save (QEMUFile *f, fdrive_t *fd)
  563. {
  564. qemu_put_8s(f, &fd->head);
  565. qemu_put_8s(f, &fd->track);
  566. qemu_put_8s(f, &fd->sect);
  567. }
  568. static void fdc_save (QEMUFile *f, void *opaque)
  569. {
  570. fdctrl_t *s = opaque;
  571. uint8_t tmp;
  572. int i;
  573. uint8_t dor = s->dor | GET_CUR_DRV(s);
  574. /* Controller state */
  575. qemu_put_8s(f, &s->sra);
  576. qemu_put_8s(f, &s->srb);
  577. qemu_put_8s(f, &dor);
  578. qemu_put_8s(f, &s->tdr);
  579. qemu_put_8s(f, &s->dsr);
  580. qemu_put_8s(f, &s->msr);
  581. qemu_put_8s(f, &s->status0);
  582. qemu_put_8s(f, &s->status1);
  583. qemu_put_8s(f, &s->status2);
  584. /* Command FIFO */
  585. qemu_put_buffer(f, s->fifo, FD_SECTOR_LEN);
  586. qemu_put_be32s(f, &s->data_pos);
  587. qemu_put_be32s(f, &s->data_len);
  588. qemu_put_8s(f, &s->data_state);
  589. qemu_put_8s(f, &s->data_dir);
  590. qemu_put_8s(f, &s->eot);
  591. /* States kept only to be returned back */
  592. qemu_put_8s(f, &s->timer0);
  593. qemu_put_8s(f, &s->timer1);
  594. qemu_put_8s(f, &s->precomp_trk);
  595. qemu_put_8s(f, &s->config);
  596. qemu_put_8s(f, &s->lock);
  597. qemu_put_8s(f, &s->pwrd);
  598. tmp = MAX_FD;
  599. qemu_put_8s(f, &tmp);
  600. for (i = 0; i < MAX_FD; i++)
  601. fd_save(f, &s->drives[i]);
  602. }
  603. static int fd_load (QEMUFile *f, fdrive_t *fd)
  604. {
  605. qemu_get_8s(f, &fd->head);
  606. qemu_get_8s(f, &fd->track);
  607. qemu_get_8s(f, &fd->sect);
  608. return 0;
  609. }
  610. static int fdc_load (QEMUFile *f, void *opaque, int version_id)
  611. {
  612. fdctrl_t *s = opaque;
  613. int i, ret = 0;
  614. uint8_t n;
  615. if (version_id != 2)
  616. return -EINVAL;
  617. /* Controller state */
  618. qemu_get_8s(f, &s->sra);
  619. qemu_get_8s(f, &s->srb);
  620. qemu_get_8s(f, &s->dor);
  621. SET_CUR_DRV(s, s->dor & FD_DOR_SELMASK);
  622. s->dor &= ~FD_DOR_SELMASK;
  623. qemu_get_8s(f, &s->tdr);
  624. qemu_get_8s(f, &s->dsr);
  625. qemu_get_8s(f, &s->msr);
  626. qemu_get_8s(f, &s->status0);
  627. qemu_get_8s(f, &s->status1);
  628. qemu_get_8s(f, &s->status2);
  629. /* Command FIFO */
  630. qemu_get_buffer(f, s->fifo, FD_SECTOR_LEN);
  631. qemu_get_be32s(f, &s->data_pos);
  632. qemu_get_be32s(f, &s->data_len);
  633. qemu_get_8s(f, &s->data_state);
  634. qemu_get_8s(f, &s->data_dir);
  635. qemu_get_8s(f, &s->eot);
  636. /* States kept only to be returned back */
  637. qemu_get_8s(f, &s->timer0);
  638. qemu_get_8s(f, &s->timer1);
  639. qemu_get_8s(f, &s->precomp_trk);
  640. qemu_get_8s(f, &s->config);
  641. qemu_get_8s(f, &s->lock);
  642. qemu_get_8s(f, &s->pwrd);
  643. qemu_get_8s(f, &n);
  644. if (n > MAX_FD)
  645. return -EINVAL;
  646. for (i = 0; i < n; i++) {
  647. ret = fd_load(f, &s->drives[i]);
  648. if (ret != 0)
  649. break;
  650. }
  651. return ret;
  652. }
  653. static void fdctrl_external_reset(void *opaque)
  654. {
  655. fdctrl_t *s = opaque;
  656. fdctrl_reset(s, 0);
  657. }
  658. static void fdctrl_handle_tc(void *opaque, int irq, int level)
  659. {
  660. //fdctrl_t *s = opaque;
  661. if (level) {
  662. // XXX
  663. FLOPPY_DPRINTF("TC pulsed\n");
  664. }
  665. }
  666. /* XXX: may change if moved to bdrv */
  667. int fdctrl_get_drive_type(fdctrl_t *fdctrl, int drive_num)
  668. {
  669. return fdctrl->drives[drive_num].drive;
  670. }
  671. /* Change IRQ state */
  672. static void fdctrl_reset_irq (fdctrl_t *fdctrl)
  673. {
  674. if (!(fdctrl->sra & FD_SRA_INTPEND))
  675. return;
  676. FLOPPY_DPRINTF("Reset interrupt\n");
  677. qemu_set_irq(fdctrl->irq, 0);
  678. fdctrl->sra &= ~FD_SRA_INTPEND;
  679. }
  680. static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status0)
  681. {
  682. /* Sparc mutation */
  683. if (fdctrl->sun4m && (fdctrl->msr & FD_MSR_CMDBUSY)) {
  684. /* XXX: not sure */
  685. fdctrl->msr &= ~FD_MSR_CMDBUSY;
  686. fdctrl->msr |= FD_MSR_RQM | FD_MSR_DIO;
  687. fdctrl->status0 = status0;
  688. return;
  689. }
  690. if (!(fdctrl->sra & FD_SRA_INTPEND)) {
  691. qemu_set_irq(fdctrl->irq, 1);
  692. fdctrl->sra |= FD_SRA_INTPEND;
  693. }
  694. fdctrl->reset_sensei = 0;
  695. fdctrl->status0 = status0;
  696. FLOPPY_DPRINTF("Set interrupt status to 0x%02x\n", fdctrl->status0);
  697. }
  698. /* Reset controller */
  699. static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq)
  700. {
  701. int i;
  702. FLOPPY_DPRINTF("reset controller\n");
  703. fdctrl_reset_irq(fdctrl);
  704. /* Initialise controller */
  705. fdctrl->sra = 0;
  706. fdctrl->srb = 0xc0;
  707. if (!fdctrl->drives[1].bs)
  708. fdctrl->sra |= FD_SRA_nDRV2;
  709. fdctrl->cur_drv = 0;
  710. fdctrl->dor = FD_DOR_nRESET;
  711. fdctrl->dor |= (fdctrl->dma_chann != -1) ? FD_DOR_DMAEN : 0;
  712. fdctrl->msr = FD_MSR_RQM;
  713. /* FIFO state */
  714. fdctrl->data_pos = 0;
  715. fdctrl->data_len = 0;
  716. fdctrl->data_state = 0;
  717. fdctrl->data_dir = FD_DIR_WRITE;
  718. for (i = 0; i < MAX_FD; i++)
  719. fd_recalibrate(&fdctrl->drives[i]);
  720. fdctrl_reset_fifo(fdctrl);
  721. if (do_irq) {
  722. fdctrl_raise_irq(fdctrl, FD_SR0_RDYCHG);
  723. fdctrl->reset_sensei = FD_RESET_SENSEI_COUNT;
  724. }
  725. }
  726. static inline fdrive_t *drv0 (fdctrl_t *fdctrl)
  727. {
  728. return &fdctrl->drives[(fdctrl->tdr & FD_TDR_BOOTSEL) >> 2];
  729. }
  730. static inline fdrive_t *drv1 (fdctrl_t *fdctrl)
  731. {
  732. if ((fdctrl->tdr & FD_TDR_BOOTSEL) < (1 << 2))
  733. return &fdctrl->drives[1];
  734. else
  735. return &fdctrl->drives[0];
  736. }
  737. #if MAX_FD == 4
  738. static inline fdrive_t *drv2 (fdctrl_t *fdctrl)
  739. {
  740. if ((fdctrl->tdr & FD_TDR_BOOTSEL) < (2 << 2))
  741. return &fdctrl->drives[2];
  742. else
  743. return &fdctrl->drives[1];
  744. }
  745. static inline fdrive_t *drv3 (fdctrl_t *fdctrl)
  746. {
  747. if ((fdctrl->tdr & FD_TDR_BOOTSEL) < (3 << 2))
  748. return &fdctrl->drives[3];
  749. else
  750. return &fdctrl->drives[2];
  751. }
  752. #endif
  753. static fdrive_t *get_cur_drv (fdctrl_t *fdctrl)
  754. {
  755. switch (fdctrl->cur_drv) {
  756. case 0: return drv0(fdctrl);
  757. case 1: return drv1(fdctrl);
  758. #if MAX_FD == 4
  759. case 2: return drv2(fdctrl);
  760. case 3: return drv3(fdctrl);
  761. #endif
  762. default: return NULL;
  763. }
  764. }
  765. /* Status A register : 0x00 (read-only) */
  766. static uint32_t fdctrl_read_statusA (fdctrl_t *fdctrl)
  767. {
  768. uint32_t retval = fdctrl->sra;
  769. FLOPPY_DPRINTF("status register A: 0x%02x\n", retval);
  770. return retval;
  771. }
  772. /* Status B register : 0x01 (read-only) */
  773. static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl)
  774. {
  775. uint32_t retval = fdctrl->srb;
  776. FLOPPY_DPRINTF("status register B: 0x%02x\n", retval);
  777. return retval;
  778. }
  779. /* Digital output register : 0x02 */
  780. static uint32_t fdctrl_read_dor (fdctrl_t *fdctrl)
  781. {
  782. uint32_t retval = fdctrl->dor;
  783. /* Selected drive */
  784. retval |= fdctrl->cur_drv;
  785. FLOPPY_DPRINTF("digital output register: 0x%02x\n", retval);
  786. return retval;
  787. }
  788. static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value)
  789. {
  790. FLOPPY_DPRINTF("digital output register set to 0x%02x\n", value);
  791. /* Motors */
  792. if (value & FD_DOR_MOTEN0)
  793. fdctrl->srb |= FD_SRB_MTR0;
  794. else
  795. fdctrl->srb &= ~FD_SRB_MTR0;
  796. if (value & FD_DOR_MOTEN1)
  797. fdctrl->srb |= FD_SRB_MTR1;
  798. else
  799. fdctrl->srb &= ~FD_SRB_MTR1;
  800. /* Drive */
  801. if (value & 1)
  802. fdctrl->srb |= FD_SRB_DR0;
  803. else
  804. fdctrl->srb &= ~FD_SRB_DR0;
  805. /* Reset */
  806. if (!(value & FD_DOR_nRESET)) {
  807. if (fdctrl->dor & FD_DOR_nRESET) {
  808. FLOPPY_DPRINTF("controller enter RESET state\n");
  809. }
  810. } else {
  811. if (!(fdctrl->dor & FD_DOR_nRESET)) {
  812. FLOPPY_DPRINTF("controller out of RESET state\n");
  813. fdctrl_reset(fdctrl, 1);
  814. fdctrl->dsr &= ~FD_DSR_PWRDOWN;
  815. }
  816. }
  817. /* Selected drive */
  818. fdctrl->cur_drv = value & FD_DOR_SELMASK;
  819. fdctrl->dor = value;
  820. }
  821. /* Tape drive register : 0x03 */
  822. static uint32_t fdctrl_read_tape (fdctrl_t *fdctrl)
  823. {
  824. uint32_t retval = fdctrl->tdr;
  825. FLOPPY_DPRINTF("tape drive register: 0x%02x\n", retval);
  826. return retval;
  827. }
  828. static void fdctrl_write_tape (fdctrl_t *fdctrl, uint32_t value)
  829. {
  830. /* Reset mode */
  831. if (!(fdctrl->dor & FD_DOR_nRESET)) {
  832. FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
  833. return;
  834. }
  835. FLOPPY_DPRINTF("tape drive register set to 0x%02x\n", value);
  836. /* Disk boot selection indicator */
  837. fdctrl->tdr = value & FD_TDR_BOOTSEL;
  838. /* Tape indicators: never allow */
  839. }
  840. /* Main status register : 0x04 (read) */
  841. static uint32_t fdctrl_read_main_status (fdctrl_t *fdctrl)
  842. {
  843. uint32_t retval = fdctrl->msr;
  844. fdctrl->dsr &= ~FD_DSR_PWRDOWN;
  845. fdctrl->dor |= FD_DOR_nRESET;
  846. FLOPPY_DPRINTF("main status register: 0x%02x\n", retval);
  847. return retval;
  848. }
  849. /* Data select rate register : 0x04 (write) */
  850. static void fdctrl_write_rate (fdctrl_t *fdctrl, uint32_t value)
  851. {
  852. /* Reset mode */
  853. if (!(fdctrl->dor & FD_DOR_nRESET)) {
  854. FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
  855. return;
  856. }
  857. FLOPPY_DPRINTF("select rate register set to 0x%02x\n", value);
  858. /* Reset: autoclear */
  859. if (value & FD_DSR_SWRESET) {
  860. fdctrl->dor &= ~FD_DOR_nRESET;
  861. fdctrl_reset(fdctrl, 1);
  862. fdctrl->dor |= FD_DOR_nRESET;
  863. }
  864. if (value & FD_DSR_PWRDOWN) {
  865. fdctrl_reset(fdctrl, 1);
  866. }
  867. fdctrl->dsr = value;
  868. }
  869. static int fdctrl_media_changed(fdrive_t *drv)
  870. {
  871. int ret;
  872. if (!drv->bs)
  873. return 0;
  874. ret = bdrv_media_changed(drv->bs);
  875. if (ret) {
  876. fd_revalidate(drv);
  877. }
  878. return ret;
  879. }
  880. /* Digital input register : 0x07 (read-only) */
  881. static uint32_t fdctrl_read_dir (fdctrl_t *fdctrl)
  882. {
  883. uint32_t retval = 0;
  884. if (fdctrl_media_changed(drv0(fdctrl))
  885. || fdctrl_media_changed(drv1(fdctrl))
  886. #if MAX_FD == 4
  887. || fdctrl_media_changed(drv2(fdctrl))
  888. || fdctrl_media_changed(drv3(fdctrl))
  889. #endif
  890. )
  891. retval |= FD_DIR_DSKCHG;
  892. if (retval != 0)
  893. FLOPPY_DPRINTF("Floppy digital input register: 0x%02x\n", retval);
  894. return retval;
  895. }
  896. /* FIFO state control */
  897. static void fdctrl_reset_fifo (fdctrl_t *fdctrl)
  898. {
  899. fdctrl->data_dir = FD_DIR_WRITE;
  900. fdctrl->data_pos = 0;
  901. fdctrl->msr &= ~(FD_MSR_CMDBUSY | FD_MSR_DIO);
  902. }
  903. /* Set FIFO status for the host to read */
  904. static void fdctrl_set_fifo (fdctrl_t *fdctrl, int fifo_len, int do_irq)
  905. {
  906. fdctrl->data_dir = FD_DIR_READ;
  907. fdctrl->data_len = fifo_len;
  908. fdctrl->data_pos = 0;
  909. fdctrl->msr |= FD_MSR_CMDBUSY | FD_MSR_RQM | FD_MSR_DIO;
  910. if (do_irq)
  911. fdctrl_raise_irq(fdctrl, 0x00);
  912. }
  913. /* Set an error: unimplemented/unknown command */
  914. static void fdctrl_unimplemented (fdctrl_t *fdctrl, int direction)
  915. {
  916. FLOPPY_ERROR("unimplemented command 0x%02x\n", fdctrl->fifo[0]);
  917. fdctrl->fifo[0] = FD_SR0_INVCMD;
  918. fdctrl_set_fifo(fdctrl, 1, 0);
  919. }
  920. /* Seek to next sector */
  921. static int fdctrl_seek_to_next_sect (fdctrl_t *fdctrl, fdrive_t *cur_drv)
  922. {
  923. FLOPPY_DPRINTF("seek to next sector (%d %02x %02x => %d)\n",
  924. cur_drv->head, cur_drv->track, cur_drv->sect,
  925. fd_sector(cur_drv));
  926. /* XXX: cur_drv->sect >= cur_drv->last_sect should be an
  927. error in fact */
  928. if (cur_drv->sect >= cur_drv->last_sect ||
  929. cur_drv->sect == fdctrl->eot) {
  930. cur_drv->sect = 1;
  931. if (FD_MULTI_TRACK(fdctrl->data_state)) {
  932. if (cur_drv->head == 0 &&
  933. (cur_drv->flags & FDISK_DBL_SIDES) != 0) {
  934. cur_drv->head = 1;
  935. } else {
  936. cur_drv->head = 0;
  937. cur_drv->track++;
  938. if ((cur_drv->flags & FDISK_DBL_SIDES) == 0)
  939. return 0;
  940. }
  941. } else {
  942. cur_drv->track++;
  943. return 0;
  944. }
  945. FLOPPY_DPRINTF("seek to next track (%d %02x %02x => %d)\n",
  946. cur_drv->head, cur_drv->track,
  947. cur_drv->sect, fd_sector(cur_drv));
  948. } else {
  949. cur_drv->sect++;
  950. }
  951. return 1;
  952. }
  953. /* Callback for transfer end (stop or abort) */
  954. static void fdctrl_stop_transfer (fdctrl_t *fdctrl, uint8_t status0,
  955. uint8_t status1, uint8_t status2)
  956. {
  957. fdrive_t *cur_drv;
  958. cur_drv = get_cur_drv(fdctrl);
  959. FLOPPY_DPRINTF("transfer status: %02x %02x %02x (%02x)\n",
  960. status0, status1, status2,
  961. status0 | (cur_drv->head << 2) | GET_CUR_DRV(fdctrl));
  962. fdctrl->fifo[0] = status0 | (cur_drv->head << 2) | GET_CUR_DRV(fdctrl);
  963. fdctrl->fifo[1] = status1;
  964. fdctrl->fifo[2] = status2;
  965. fdctrl->fifo[3] = cur_drv->track;
  966. fdctrl->fifo[4] = cur_drv->head;
  967. fdctrl->fifo[5] = cur_drv->sect;
  968. fdctrl->fifo[6] = FD_SECTOR_SC;
  969. fdctrl->data_dir = FD_DIR_READ;
  970. if (!(fdctrl->msr & FD_MSR_NONDMA)) {
  971. DMA_release_DREQ(fdctrl->dma_chann);
  972. }
  973. fdctrl->msr |= FD_MSR_RQM | FD_MSR_DIO;
  974. fdctrl->msr &= ~FD_MSR_NONDMA;
  975. fdctrl_set_fifo(fdctrl, 7, 1);
  976. }
  977. /* Prepare a data transfer (either DMA or FIFO) */
  978. static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction)
  979. {
  980. fdrive_t *cur_drv;
  981. uint8_t kh, kt, ks;
  982. int did_seek = 0;
  983. SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
  984. cur_drv = get_cur_drv(fdctrl);
  985. kt = fdctrl->fifo[2];
  986. kh = fdctrl->fifo[3];
  987. ks = fdctrl->fifo[4];
  988. FLOPPY_DPRINTF("Start transfer at %d %d %02x %02x (%d)\n",
  989. GET_CUR_DRV(fdctrl), kh, kt, ks,
  990. _fd_sector(kh, kt, ks, cur_drv->last_sect));
  991. switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & FD_CONFIG_EIS)) {
  992. case 2:
  993. /* sect too big */
  994. fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00);
  995. fdctrl->fifo[3] = kt;
  996. fdctrl->fifo[4] = kh;
  997. fdctrl->fifo[5] = ks;
  998. return;
  999. case 3:
  1000. /* track too big */
  1001. fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_EC, 0x00);
  1002. fdctrl->fifo[3] = kt;
  1003. fdctrl->fifo[4] = kh;
  1004. fdctrl->fifo[5] = ks;
  1005. return;
  1006. case 4:
  1007. /* No seek enabled */
  1008. fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00);
  1009. fdctrl->fifo[3] = kt;
  1010. fdctrl->fifo[4] = kh;
  1011. fdctrl->fifo[5] = ks;
  1012. return;
  1013. case 1:
  1014. did_seek = 1;
  1015. break;
  1016. default:
  1017. break;
  1018. }
  1019. /* Set the FIFO state */
  1020. fdctrl->data_dir = direction;
  1021. fdctrl->data_pos = 0;
  1022. fdctrl->msr |= FD_MSR_CMDBUSY;
  1023. if (fdctrl->fifo[0] & 0x80)
  1024. fdctrl->data_state |= FD_STATE_MULTI;
  1025. else
  1026. fdctrl->data_state &= ~FD_STATE_MULTI;
  1027. if (did_seek)
  1028. fdctrl->data_state |= FD_STATE_SEEK;
  1029. else
  1030. fdctrl->data_state &= ~FD_STATE_SEEK;
  1031. if (fdctrl->fifo[5] == 00) {
  1032. fdctrl->data_len = fdctrl->fifo[8];
  1033. } else {
  1034. int tmp;
  1035. fdctrl->data_len = 128 << (fdctrl->fifo[5] > 7 ? 7 : fdctrl->fifo[5]);
  1036. tmp = (fdctrl->fifo[6] - ks + 1);
  1037. if (fdctrl->fifo[0] & 0x80)
  1038. tmp += fdctrl->fifo[6];
  1039. fdctrl->data_len *= tmp;
  1040. }
  1041. fdctrl->eot = fdctrl->fifo[6];
  1042. if (fdctrl->dor & FD_DOR_DMAEN) {
  1043. int dma_mode;
  1044. /* DMA transfer are enabled. Check if DMA channel is well programmed */
  1045. dma_mode = DMA_get_channel_mode(fdctrl->dma_chann);
  1046. dma_mode = (dma_mode >> 2) & 3;
  1047. FLOPPY_DPRINTF("dma_mode=%d direction=%d (%d - %d)\n",
  1048. dma_mode, direction,
  1049. (128 << fdctrl->fifo[5]) *
  1050. (cur_drv->last_sect - ks + 1), fdctrl->data_len);
  1051. if (((direction == FD_DIR_SCANE || direction == FD_DIR_SCANL ||
  1052. direction == FD_DIR_SCANH) && dma_mode == 0) ||
  1053. (direction == FD_DIR_WRITE && dma_mode == 2) ||
  1054. (direction == FD_DIR_READ && dma_mode == 1)) {
  1055. /* No access is allowed until DMA transfer has completed */
  1056. fdctrl->msr &= ~FD_MSR_RQM;
  1057. /* Now, we just have to wait for the DMA controller to
  1058. * recall us...
  1059. */
  1060. DMA_hold_DREQ(fdctrl->dma_chann);
  1061. DMA_schedule(fdctrl->dma_chann);
  1062. return;
  1063. } else {
  1064. FLOPPY_ERROR("dma_mode=%d direction=%d\n", dma_mode, direction);
  1065. }
  1066. }
  1067. FLOPPY_DPRINTF("start non-DMA transfer\n");
  1068. fdctrl->msr |= FD_MSR_NONDMA;
  1069. if (direction != FD_DIR_WRITE)
  1070. fdctrl->msr |= FD_MSR_DIO;
  1071. /* IO based transfer: calculate len */
  1072. fdctrl_raise_irq(fdctrl, 0x00);
  1073. return;
  1074. }
  1075. /* Prepare a transfer of deleted data */
  1076. static void fdctrl_start_transfer_del (fdctrl_t *fdctrl, int direction)
  1077. {
  1078. FLOPPY_ERROR("fdctrl_start_transfer_del() unimplemented\n");
  1079. /* We don't handle deleted data,
  1080. * so we don't return *ANYTHING*
  1081. */
  1082. fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00);
  1083. }
  1084. /* handlers for DMA transfers */
  1085. static int fdctrl_transfer_handler (void *opaque, int nchan,
  1086. int dma_pos, int dma_len)
  1087. {
  1088. fdctrl_t *fdctrl;
  1089. fdrive_t *cur_drv;
  1090. int len, start_pos, rel_pos;
  1091. uint8_t status0 = 0x00, status1 = 0x00, status2 = 0x00;
  1092. fdctrl = opaque;
  1093. if (fdctrl->msr & FD_MSR_RQM) {
  1094. FLOPPY_DPRINTF("Not in DMA transfer mode !\n");
  1095. return 0;
  1096. }
  1097. cur_drv = get_cur_drv(fdctrl);
  1098. if (fdctrl->data_dir == FD_DIR_SCANE || fdctrl->data_dir == FD_DIR_SCANL ||
  1099. fdctrl->data_dir == FD_DIR_SCANH)
  1100. status2 = FD_SR2_SNS;
  1101. if (dma_len > fdctrl->data_len)
  1102. dma_len = fdctrl->data_len;
  1103. if (cur_drv->bs == NULL) {
  1104. if (fdctrl->data_dir == FD_DIR_WRITE)
  1105. fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00);
  1106. else
  1107. fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00);
  1108. len = 0;
  1109. goto transfer_error;
  1110. }
  1111. rel_pos = fdctrl->data_pos % FD_SECTOR_LEN;
  1112. for (start_pos = fdctrl->data_pos; fdctrl->data_pos < dma_len;) {
  1113. len = dma_len - fdctrl->data_pos;
  1114. if (len + rel_pos > FD_SECTOR_LEN)
  1115. len = FD_SECTOR_LEN - rel_pos;
  1116. FLOPPY_DPRINTF("copy %d bytes (%d %d %d) %d pos %d %02x "
  1117. "(%d-0x%08x 0x%08x)\n", len, dma_len, fdctrl->data_pos,
  1118. fdctrl->data_len, GET_CUR_DRV(fdctrl), cur_drv->head,
  1119. cur_drv->track, cur_drv->sect, fd_sector(cur_drv),
  1120. fd_sector(cur_drv) * FD_SECTOR_LEN);
  1121. if (fdctrl->data_dir != FD_DIR_WRITE ||
  1122. len < FD_SECTOR_LEN || rel_pos != 0) {
  1123. /* READ & SCAN commands and realign to a sector for WRITE */
  1124. if (bdrv_read(cur_drv->bs, fd_sector(cur_drv),
  1125. fdctrl->fifo, 1) < 0) {
  1126. FLOPPY_DPRINTF("Floppy: error getting sector %d\n",
  1127. fd_sector(cur_drv));
  1128. /* Sure, image size is too small... */
  1129. memset(fdctrl->fifo, 0, FD_SECTOR_LEN);
  1130. }
  1131. }
  1132. switch (fdctrl->data_dir) {
  1133. case FD_DIR_READ:
  1134. /* READ commands */
  1135. DMA_write_memory (nchan, fdctrl->fifo + rel_pos,
  1136. fdctrl->data_pos, len);
  1137. break;
  1138. case FD_DIR_WRITE:
  1139. /* WRITE commands */
  1140. DMA_read_memory (nchan, fdctrl->fifo + rel_pos,
  1141. fdctrl->data_pos, len);
  1142. if (bdrv_write(cur_drv->bs, fd_sector(cur_drv),
  1143. fdctrl->fifo, 1) < 0) {
  1144. FLOPPY_ERROR("writing sector %d\n", fd_sector(cur_drv));
  1145. fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00);
  1146. goto transfer_error;
  1147. }
  1148. break;
  1149. default:
  1150. /* SCAN commands */
  1151. {
  1152. uint8_t tmpbuf[FD_SECTOR_LEN];
  1153. int ret;
  1154. DMA_read_memory (nchan, tmpbuf, fdctrl->data_pos, len);
  1155. ret = memcmp(tmpbuf, fdctrl->fifo + rel_pos, len);
  1156. if (ret == 0) {
  1157. status2 = FD_SR2_SEH;
  1158. goto end_transfer;
  1159. }
  1160. if ((ret < 0 && fdctrl->data_dir == FD_DIR_SCANL) ||
  1161. (ret > 0 && fdctrl->data_dir == FD_DIR_SCANH)) {
  1162. status2 = 0x00;
  1163. goto end_transfer;
  1164. }
  1165. }
  1166. break;
  1167. }
  1168. fdctrl->data_pos += len;
  1169. rel_pos = fdctrl->data_pos % FD_SECTOR_LEN;
  1170. if (rel_pos == 0) {
  1171. /* Seek to next sector */
  1172. if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv))
  1173. break;
  1174. }
  1175. }
  1176. end_transfer:
  1177. len = fdctrl->data_pos - start_pos;
  1178. FLOPPY_DPRINTF("end transfer %d %d %d\n",
  1179. fdctrl->data_pos, len, fdctrl->data_len);
  1180. if (fdctrl->data_dir == FD_DIR_SCANE ||
  1181. fdctrl->data_dir == FD_DIR_SCANL ||
  1182. fdctrl->data_dir == FD_DIR_SCANH)
  1183. status2 = FD_SR2_SEH;
  1184. if (FD_DID_SEEK(fdctrl->data_state))
  1185. status0 |= FD_SR0_SEEK;
  1186. fdctrl->data_len -= len;
  1187. fdctrl_stop_transfer(fdctrl, status0, status1, status2);
  1188. transfer_error:
  1189. return len;
  1190. }
  1191. /* Data register : 0x05 */
  1192. static uint32_t fdctrl_read_data (fdctrl_t *fdctrl)
  1193. {
  1194. fdrive_t *cur_drv;
  1195. uint32_t retval = 0;
  1196. int pos;
  1197. cur_drv = get_cur_drv(fdctrl);
  1198. fdctrl->dsr &= ~FD_DSR_PWRDOWN;
  1199. if (!(fdctrl->msr & FD_MSR_RQM) || !(fdctrl->msr & FD_MSR_DIO)) {
  1200. FLOPPY_ERROR("controller not ready for reading\n");
  1201. return 0;
  1202. }
  1203. pos = fdctrl->data_pos;
  1204. if (fdctrl->msr & FD_MSR_NONDMA) {
  1205. pos %= FD_SECTOR_LEN;
  1206. if (pos == 0) {
  1207. if (fdctrl->data_pos != 0)
  1208. if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv)) {
  1209. FLOPPY_DPRINTF("error seeking to next sector %d\n",
  1210. fd_sector(cur_drv));
  1211. return 0;
  1212. }
  1213. if (bdrv_read(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1) < 0) {
  1214. FLOPPY_DPRINTF("error getting sector %d\n",
  1215. fd_sector(cur_drv));
  1216. /* Sure, image size is too small... */
  1217. memset(fdctrl->fifo, 0, FD_SECTOR_LEN);
  1218. }
  1219. }
  1220. }
  1221. retval = fdctrl->fifo[pos];
  1222. if (++fdctrl->data_pos == fdctrl->data_len) {
  1223. fdctrl->data_pos = 0;
  1224. /* Switch from transfer mode to status mode
  1225. * then from status mode to command mode
  1226. */
  1227. if (fdctrl->msr & FD_MSR_NONDMA) {
  1228. fdctrl_stop_transfer(fdctrl, FD_SR0_SEEK, 0x00, 0x00);
  1229. } else {
  1230. fdctrl_reset_fifo(fdctrl);
  1231. fdctrl_reset_irq(fdctrl);
  1232. }
  1233. }
  1234. FLOPPY_DPRINTF("data register: 0x%02x\n", retval);
  1235. return retval;
  1236. }
  1237. static void fdctrl_format_sector (fdctrl_t *fdctrl)
  1238. {
  1239. fdrive_t *cur_drv;
  1240. uint8_t kh, kt, ks;
  1241. SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
  1242. cur_drv = get_cur_drv(fdctrl);
  1243. kt = fdctrl->fifo[6];
  1244. kh = fdctrl->fifo[7];
  1245. ks = fdctrl->fifo[8];
  1246. FLOPPY_DPRINTF("format sector at %d %d %02x %02x (%d)\n",
  1247. GET_CUR_DRV(fdctrl), kh, kt, ks,
  1248. _fd_sector(kh, kt, ks, cur_drv->last_sect));
  1249. switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & FD_CONFIG_EIS)) {
  1250. case 2:
  1251. /* sect too big */
  1252. fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00);
  1253. fdctrl->fifo[3] = kt;
  1254. fdctrl->fifo[4] = kh;
  1255. fdctrl->fifo[5] = ks;
  1256. return;
  1257. case 3:
  1258. /* track too big */
  1259. fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_EC, 0x00);
  1260. fdctrl->fifo[3] = kt;
  1261. fdctrl->fifo[4] = kh;
  1262. fdctrl->fifo[5] = ks;
  1263. return;
  1264. case 4:
  1265. /* No seek enabled */
  1266. fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00);
  1267. fdctrl->fifo[3] = kt;
  1268. fdctrl->fifo[4] = kh;
  1269. fdctrl->fifo[5] = ks;
  1270. return;
  1271. case 1:
  1272. fdctrl->data_state |= FD_STATE_SEEK;
  1273. break;
  1274. default:
  1275. break;
  1276. }
  1277. memset(fdctrl->fifo, 0, FD_SECTOR_LEN);
  1278. if (cur_drv->bs == NULL ||
  1279. bdrv_write(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1) < 0) {
  1280. FLOPPY_ERROR("formatting sector %d\n", fd_sector(cur_drv));
  1281. fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00);
  1282. } else {
  1283. if (cur_drv->sect == cur_drv->last_sect) {
  1284. fdctrl->data_state &= ~FD_STATE_FORMAT;
  1285. /* Last sector done */
  1286. if (FD_DID_SEEK(fdctrl->data_state))
  1287. fdctrl_stop_transfer(fdctrl, FD_SR0_SEEK, 0x00, 0x00);
  1288. else
  1289. fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
  1290. } else {
  1291. /* More to do */
  1292. fdctrl->data_pos = 0;
  1293. fdctrl->data_len = 4;
  1294. }
  1295. }
  1296. }
  1297. static void fdctrl_handle_lock (fdctrl_t *fdctrl, int direction)
  1298. {
  1299. fdctrl->lock = (fdctrl->fifo[0] & 0x80) ? 1 : 0;
  1300. fdctrl->fifo[0] = fdctrl->lock << 4;
  1301. fdctrl_set_fifo(fdctrl, 1, fdctrl->lock);
  1302. }
  1303. static void fdctrl_handle_dumpreg (fdctrl_t *fdctrl, int direction)
  1304. {
  1305. fdrive_t *cur_drv = get_cur_drv(fdctrl);
  1306. /* Drives position */
  1307. fdctrl->fifo[0] = drv0(fdctrl)->track;
  1308. fdctrl->fifo[1] = drv1(fdctrl)->track;
  1309. #if MAX_FD == 4
  1310. fdctrl->fifo[2] = drv2(fdctrl)->track;
  1311. fdctrl->fifo[3] = drv3(fdctrl)->track;
  1312. #else
  1313. fdctrl->fifo[2] = 0;
  1314. fdctrl->fifo[3] = 0;
  1315. #endif
  1316. /* timers */
  1317. fdctrl->fifo[4] = fdctrl->timer0;
  1318. fdctrl->fifo[5] = (fdctrl->timer1 << 1) | (fdctrl->dor & FD_DOR_DMAEN ? 1 : 0);
  1319. fdctrl->fifo[6] = cur_drv->last_sect;
  1320. fdctrl->fifo[7] = (fdctrl->lock << 7) |
  1321. (cur_drv->perpendicular << 2);
  1322. fdctrl->fifo[8] = fdctrl->config;
  1323. fdctrl->fifo[9] = fdctrl->precomp_trk;
  1324. fdctrl_set_fifo(fdctrl, 10, 0);
  1325. }
  1326. static void fdctrl_handle_version (fdctrl_t *fdctrl, int direction)
  1327. {
  1328. /* Controller's version */
  1329. fdctrl->fifo[0] = fdctrl->version;
  1330. fdctrl_set_fifo(fdctrl, 1, 1);
  1331. }
  1332. static void fdctrl_handle_partid (fdctrl_t *fdctrl, int direction)
  1333. {
  1334. fdctrl->fifo[0] = 0x41; /* Stepping 1 */
  1335. fdctrl_set_fifo(fdctrl, 1, 0);
  1336. }
  1337. static void fdctrl_handle_restore (fdctrl_t *fdctrl, int direction)
  1338. {
  1339. fdrive_t *cur_drv = get_cur_drv(fdctrl);
  1340. /* Drives position */
  1341. drv0(fdctrl)->track = fdctrl->fifo[3];
  1342. drv1(fdctrl)->track = fdctrl->fifo[4];
  1343. #if MAX_FD == 4
  1344. drv2(fdctrl)->track = fdctrl->fifo[5];
  1345. drv3(fdctrl)->track = fdctrl->fifo[6];
  1346. #endif
  1347. /* timers */
  1348. fdctrl->timer0 = fdctrl->fifo[7];
  1349. fdctrl->timer1 = fdctrl->fifo[8];
  1350. cur_drv->last_sect = fdctrl->fifo[9];
  1351. fdctrl->lock = fdctrl->fifo[10] >> 7;
  1352. cur_drv->perpendicular = (fdctrl->fifo[10] >> 2) & 0xF;
  1353. fdctrl->config = fdctrl->fifo[11];
  1354. fdctrl->precomp_trk = fdctrl->fifo[12];
  1355. fdctrl->pwrd = fdctrl->fifo[13];
  1356. fdctrl_reset_fifo(fdctrl);
  1357. }
  1358. static void fdctrl_handle_save (fdctrl_t *fdctrl, int direction)
  1359. {
  1360. fdrive_t *cur_drv = get_cur_drv(fdctrl);
  1361. fdctrl->fifo[0] = 0;
  1362. fdctrl->fifo[1] = 0;
  1363. /* Drives position */
  1364. fdctrl->fifo[2] = drv0(fdctrl)->track;
  1365. fdctrl->fifo[3] = drv1(fdctrl)->track;
  1366. #if MAX_FD == 4
  1367. fdctrl->fifo[4] = drv2(fdctrl)->track;
  1368. fdctrl->fifo[5] = drv3(fdctrl)->track;
  1369. #else
  1370. fdctrl->fifo[4] = 0;
  1371. fdctrl->fifo[5] = 0;
  1372. #endif
  1373. /* timers */
  1374. fdctrl->fifo[6] = fdctrl->timer0;
  1375. fdctrl->fifo[7] = fdctrl->timer1;
  1376. fdctrl->fifo[8] = cur_drv->last_sect;
  1377. fdctrl->fifo[9] = (fdctrl->lock << 7) |
  1378. (cur_drv->perpendicular << 2);
  1379. fdctrl->fifo[10] = fdctrl->config;
  1380. fdctrl->fifo[11] = fdctrl->precomp_trk;
  1381. fdctrl->fifo[12] = fdctrl->pwrd;
  1382. fdctrl->fifo[13] = 0;
  1383. fdctrl->fifo[14] = 0;
  1384. fdctrl_set_fifo(fdctrl, 15, 1);
  1385. }
  1386. static void fdctrl_handle_readid (fdctrl_t *fdctrl, int direction)
  1387. {
  1388. fdrive_t *cur_drv = get_cur_drv(fdctrl);
  1389. /* XXX: should set main status register to busy */
  1390. cur_drv->head = (fdctrl->fifo[1] >> 2) & 1;
  1391. qemu_mod_timer(fdctrl->result_timer,
  1392. qemu_get_clock(vm_clock) + (ticks_per_sec / 50));
  1393. }
  1394. static void fdctrl_handle_format_track (fdctrl_t *fdctrl, int direction)
  1395. {
  1396. fdrive_t *cur_drv;
  1397. SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
  1398. cur_drv = get_cur_drv(fdctrl);
  1399. fdctrl->data_state |= FD_STATE_FORMAT;
  1400. if (fdctrl->fifo[0] & 0x80)
  1401. fdctrl->data_state |= FD_STATE_MULTI;
  1402. else
  1403. fdctrl->data_state &= ~FD_STATE_MULTI;
  1404. fdctrl->data_state &= ~FD_STATE_SEEK;
  1405. cur_drv->bps =
  1406. fdctrl->fifo[2] > 7 ? 16384 : 128 << fdctrl->fifo[2];
  1407. #if 0
  1408. cur_drv->last_sect =
  1409. cur_drv->flags & FDISK_DBL_SIDES ? fdctrl->fifo[3] :
  1410. fdctrl->fifo[3] / 2;
  1411. #else
  1412. cur_drv->last_sect = fdctrl->fifo[3];
  1413. #endif
  1414. /* TODO: implement format using DMA expected by the Bochs BIOS
  1415. * and Linux fdformat (read 3 bytes per sector via DMA and fill
  1416. * the sector with the specified fill byte
  1417. */
  1418. fdctrl->data_state &= ~FD_STATE_FORMAT;
  1419. fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
  1420. }
  1421. static void fdctrl_handle_specify (fdctrl_t *fdctrl, int direction)
  1422. {
  1423. fdctrl->timer0 = (fdctrl->fifo[1] >> 4) & 0xF;
  1424. fdctrl->timer1 = fdctrl->fifo[2] >> 1;
  1425. if (fdctrl->fifo[2] & 1)
  1426. fdctrl->dor &= ~FD_DOR_DMAEN;
  1427. else
  1428. fdctrl->dor |= FD_DOR_DMAEN;
  1429. /* No result back */
  1430. fdctrl_reset_fifo(fdctrl);
  1431. }
  1432. static void fdctrl_handle_sense_drive_status (fdctrl_t *fdctrl, int direction)
  1433. {
  1434. fdrive_t *cur_drv;
  1435. SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
  1436. cur_drv = get_cur_drv(fdctrl);
  1437. cur_drv->head = (fdctrl->fifo[1] >> 2) & 1;
  1438. /* 1 Byte status back */
  1439. fdctrl->fifo[0] = (cur_drv->ro << 6) |
  1440. (cur_drv->track == 0 ? 0x10 : 0x00) |
  1441. (cur_drv->head << 2) |
  1442. GET_CUR_DRV(fdctrl) |
  1443. 0x28;
  1444. fdctrl_set_fifo(fdctrl, 1, 0);
  1445. }
  1446. static void fdctrl_handle_recalibrate (fdctrl_t *fdctrl, int direction)
  1447. {
  1448. fdrive_t *cur_drv;
  1449. SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
  1450. cur_drv = get_cur_drv(fdctrl);
  1451. fd_recalibrate(cur_drv);
  1452. fdctrl_reset_fifo(fdctrl);
  1453. /* Raise Interrupt */
  1454. fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
  1455. }
  1456. static void fdctrl_handle_sense_interrupt_status (fdctrl_t *fdctrl, int direction)
  1457. {
  1458. fdrive_t *cur_drv = get_cur_drv(fdctrl);
  1459. if(fdctrl->reset_sensei > 0) {
  1460. fdctrl->fifo[0] =
  1461. FD_SR0_RDYCHG + FD_RESET_SENSEI_COUNT - fdctrl->reset_sensei;
  1462. fdctrl->reset_sensei--;
  1463. } else {
  1464. /* XXX: status0 handling is broken for read/write
  1465. commands, so we do this hack. It should be suppressed
  1466. ASAP */
  1467. fdctrl->fifo[0] =
  1468. FD_SR0_SEEK | (cur_drv->head << 2) | GET_CUR_DRV(fdctrl);
  1469. }
  1470. fdctrl->fifo[1] = cur_drv->track;
  1471. fdctrl_set_fifo(fdctrl, 2, 0);
  1472. fdctrl_reset_irq(fdctrl);
  1473. fdctrl->status0 = FD_SR0_RDYCHG;
  1474. }
  1475. static void fdctrl_handle_seek (fdctrl_t *fdctrl, int direction)
  1476. {
  1477. fdrive_t *cur_drv;
  1478. SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
  1479. cur_drv = get_cur_drv(fdctrl);
  1480. fdctrl_reset_fifo(fdctrl);
  1481. if (fdctrl->fifo[2] > cur_drv->max_track) {
  1482. fdctrl_raise_irq(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK);
  1483. } else {
  1484. cur_drv->track = fdctrl->fifo[2];
  1485. /* Raise Interrupt */
  1486. fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
  1487. }
  1488. }
  1489. static void fdctrl_handle_perpendicular_mode (fdctrl_t *fdctrl, int direction)
  1490. {
  1491. fdrive_t *cur_drv = get_cur_drv(fdctrl);
  1492. if (fdctrl->fifo[1] & 0x80)
  1493. cur_drv->perpendicular = fdctrl->fifo[1] & 0x7;
  1494. /* No result back */
  1495. fdctrl_reset_fifo(fdctrl);
  1496. }
  1497. static void fdctrl_handle_configure (fdctrl_t *fdctrl, int direction)
  1498. {
  1499. fdctrl->config = fdctrl->fifo[2];
  1500. fdctrl->precomp_trk = fdctrl->fifo[3];
  1501. /* No result back */
  1502. fdctrl_reset_fifo(fdctrl);
  1503. }
  1504. static void fdctrl_handle_powerdown_mode (fdctrl_t *fdctrl, int direction)
  1505. {
  1506. fdctrl->pwrd = fdctrl->fifo[1];
  1507. fdctrl->fifo[0] = fdctrl->fifo[1];
  1508. fdctrl_set_fifo(fdctrl, 1, 1);
  1509. }
  1510. static void fdctrl_handle_option (fdctrl_t *fdctrl, int direction)
  1511. {
  1512. /* No result back */
  1513. fdctrl_reset_fifo(fdctrl);
  1514. }
  1515. static void fdctrl_handle_drive_specification_command (fdctrl_t *fdctrl, int direction)
  1516. {
  1517. fdrive_t *cur_drv = get_cur_drv(fdctrl);
  1518. if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x80) {
  1519. /* Command parameters done */
  1520. if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x40) {
  1521. fdctrl->fifo[0] = fdctrl->fifo[1];
  1522. fdctrl->fifo[2] = 0;
  1523. fdctrl->fifo[3] = 0;
  1524. fdctrl_set_fifo(fdctrl, 4, 1);
  1525. } else {
  1526. fdctrl_reset_fifo(fdctrl);
  1527. }
  1528. } else if (fdctrl->data_len > 7) {
  1529. /* ERROR */
  1530. fdctrl->fifo[0] = 0x80 |
  1531. (cur_drv->head << 2) | GET_CUR_DRV(fdctrl);
  1532. fdctrl_set_fifo(fdctrl, 1, 1);
  1533. }
  1534. }
  1535. static void fdctrl_handle_relative_seek_out (fdctrl_t *fdctrl, int direction)
  1536. {
  1537. fdrive_t *cur_drv;
  1538. SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
  1539. cur_drv = get_cur_drv(fdctrl);
  1540. if (fdctrl->fifo[2] + cur_drv->track >= cur_drv->max_track) {
  1541. cur_drv->track = cur_drv->max_track - 1;
  1542. } else {
  1543. cur_drv->track += fdctrl->fifo[2];
  1544. }
  1545. fdctrl_reset_fifo(fdctrl);
  1546. /* Raise Interrupt */
  1547. fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
  1548. }
  1549. static void fdctrl_handle_relative_seek_in (fdctrl_t *fdctrl, int direction)
  1550. {
  1551. fdrive_t *cur_drv;
  1552. SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
  1553. cur_drv = get_cur_drv(fdctrl);
  1554. if (fdctrl->fifo[2] > cur_drv->track) {
  1555. cur_drv->track = 0;
  1556. } else {
  1557. cur_drv->track -= fdctrl->fifo[2];
  1558. }
  1559. fdctrl_reset_fifo(fdctrl);
  1560. /* Raise Interrupt */
  1561. fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
  1562. }
  1563. static const struct {
  1564. uint8_t value;
  1565. uint8_t mask;
  1566. const char* name;
  1567. int parameters;
  1568. void (*handler)(fdctrl_t *fdctrl, int direction);
  1569. int direction;
  1570. } handlers[] = {
  1571. { FD_CMD_READ, 0x1f, "READ", 8, fdctrl_start_transfer, FD_DIR_READ },
  1572. { FD_CMD_WRITE, 0x3f, "WRITE", 8, fdctrl_start_transfer, FD_DIR_WRITE },
  1573. { FD_CMD_SEEK, 0xff, "SEEK", 2, fdctrl_handle_seek },
  1574. { FD_CMD_SENSE_INTERRUPT_STATUS, 0xff, "SENSE INTERRUPT STATUS", 0, fdctrl_handle_sense_interrupt_status },
  1575. { FD_CMD_RECALIBRATE, 0xff, "RECALIBRATE", 1, fdctrl_handle_recalibrate },
  1576. { FD_CMD_FORMAT_TRACK, 0xbf, "FORMAT TRACK", 5, fdctrl_handle_format_track },
  1577. { FD_CMD_READ_TRACK, 0xbf, "READ TRACK", 8, fdctrl_start_transfer, FD_DIR_READ },
  1578. { FD_CMD_RESTORE, 0xff, "RESTORE", 17, fdctrl_handle_restore }, /* part of READ DELETED DATA */
  1579. { FD_CMD_SAVE, 0xff, "SAVE", 0, fdctrl_handle_save }, /* part of READ DELETED DATA */
  1580. { FD_CMD_READ_DELETED, 0x1f, "READ DELETED DATA", 8, fdctrl_start_transfer_del, FD_DIR_READ },
  1581. { FD_CMD_SCAN_EQUAL, 0x1f, "SCAN EQUAL", 8, fdctrl_start_transfer, FD_DIR_SCANE },
  1582. { FD_CMD_VERIFY, 0x1f, "VERIFY", 8, fdctrl_unimplemented },
  1583. { FD_CMD_SCAN_LOW_OR_EQUAL, 0x1f, "SCAN LOW OR EQUAL", 8, fdctrl_start_transfer, FD_DIR_SCANL },
  1584. { FD_CMD_SCAN_HIGH_OR_EQUAL, 0x1f, "SCAN HIGH OR EQUAL", 8, fdctrl_start_transfer, FD_DIR_SCANH },
  1585. { FD_CMD_WRITE_DELETED, 0x3f, "WRITE DELETED DATA", 8, fdctrl_start_transfer_del, FD_DIR_WRITE },
  1586. { FD_CMD_READ_ID, 0xbf, "READ ID", 1, fdctrl_handle_readid },
  1587. { FD_CMD_SPECIFY, 0xff, "SPECIFY", 2, fdctrl_handle_specify },
  1588. { FD_CMD_SENSE_DRIVE_STATUS, 0xff, "SENSE DRIVE STATUS", 1, fdctrl_handle_sense_drive_status },
  1589. { FD_CMD_PERPENDICULAR_MODE, 0xff, "PERPENDICULAR MODE", 1, fdctrl_handle_perpendicular_mode },
  1590. { FD_CMD_CONFIGURE, 0xff, "CONFIGURE", 3, fdctrl_handle_configure },
  1591. { FD_CMD_POWERDOWN_MODE, 0xff, "POWERDOWN MODE", 2, fdctrl_handle_powerdown_mode },
  1592. { FD_CMD_OPTION, 0xff, "OPTION", 1, fdctrl_handle_option },
  1593. { FD_CMD_DRIVE_SPECIFICATION_COMMAND, 0xff, "DRIVE SPECIFICATION COMMAND", 5, fdctrl_handle_drive_specification_command },
  1594. { FD_CMD_RELATIVE_SEEK_OUT, 0xff, "RELATIVE SEEK OUT", 2, fdctrl_handle_relative_seek_out },
  1595. { FD_CMD_FORMAT_AND_WRITE, 0xff, "FORMAT AND WRITE", 10, fdctrl_unimplemented },
  1596. { FD_CMD_RELATIVE_SEEK_IN, 0xff, "RELATIVE SEEK IN", 2, fdctrl_handle_relative_seek_in },
  1597. { FD_CMD_LOCK, 0x7f, "LOCK", 0, fdctrl_handle_lock },
  1598. { FD_CMD_DUMPREG, 0xff, "DUMPREG", 0, fdctrl_handle_dumpreg },
  1599. { FD_CMD_VERSION, 0xff, "VERSION", 0, fdctrl_handle_version },
  1600. { FD_CMD_PART_ID, 0xff, "PART ID", 0, fdctrl_handle_partid },
  1601. { FD_CMD_WRITE, 0x1f, "WRITE (BeOS)", 8, fdctrl_start_transfer, FD_DIR_WRITE }, /* not in specification ; BeOS 4.5 bug */
  1602. { 0, 0, "unknown", 0, fdctrl_unimplemented }, /* default handler */
  1603. };
  1604. /* Associate command to an index in the 'handlers' array */
  1605. static uint8_t command_to_handler[256];
  1606. static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value)
  1607. {
  1608. fdrive_t *cur_drv;
  1609. int pos;
  1610. /* Reset mode */
  1611. if (!(fdctrl->dor & FD_DOR_nRESET)) {
  1612. FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
  1613. return;
  1614. }
  1615. if (!(fdctrl->msr & FD_MSR_RQM) || (fdctrl->msr & FD_MSR_DIO)) {
  1616. FLOPPY_ERROR("controller not ready for writing\n");
  1617. return;
  1618. }
  1619. fdctrl->dsr &= ~FD_DSR_PWRDOWN;
  1620. /* Is it write command time ? */
  1621. if (fdctrl->msr & FD_MSR_NONDMA) {
  1622. /* FIFO data write */
  1623. pos = fdctrl->data_pos++;
  1624. pos %= FD_SECTOR_LEN;
  1625. fdctrl->fifo[pos] = value;
  1626. if (pos == FD_SECTOR_LEN - 1 ||
  1627. fdctrl->data_pos == fdctrl->data_len) {
  1628. cur_drv = get_cur_drv(fdctrl);
  1629. if (bdrv_write(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1) < 0) {
  1630. FLOPPY_ERROR("writing sector %d\n", fd_sector(cur_drv));
  1631. return;
  1632. }
  1633. if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv)) {
  1634. FLOPPY_DPRINTF("error seeking to next sector %d\n",
  1635. fd_sector(cur_drv));
  1636. return;
  1637. }
  1638. }
  1639. /* Switch from transfer mode to status mode
  1640. * then from status mode to command mode
  1641. */
  1642. if (fdctrl->data_pos == fdctrl->data_len)
  1643. fdctrl_stop_transfer(fdctrl, FD_SR0_SEEK, 0x00, 0x00);
  1644. return;
  1645. }
  1646. if (fdctrl->data_pos == 0) {
  1647. /* Command */
  1648. pos = command_to_handler[value & 0xff];
  1649. FLOPPY_DPRINTF("%s command\n", handlers[pos].name);
  1650. fdctrl->data_len = handlers[pos].parameters + 1;
  1651. }
  1652. FLOPPY_DPRINTF("%s: %02x\n", __func__, value);
  1653. fdctrl->fifo[fdctrl->data_pos++] = value;
  1654. if (fdctrl->data_pos == fdctrl->data_len) {
  1655. /* We now have all parameters
  1656. * and will be able to treat the command
  1657. */
  1658. if (fdctrl->data_state & FD_STATE_FORMAT) {
  1659. fdctrl_format_sector(fdctrl);
  1660. return;
  1661. }
  1662. pos = command_to_handler[fdctrl->fifo[0] & 0xff];
  1663. FLOPPY_DPRINTF("treat %s command\n", handlers[pos].name);
  1664. (*handlers[pos].handler)(fdctrl, handlers[pos].direction);
  1665. }
  1666. }
  1667. static void fdctrl_result_timer(void *opaque)
  1668. {
  1669. fdctrl_t *fdctrl = opaque;
  1670. fdrive_t *cur_drv = get_cur_drv(fdctrl);
  1671. /* Pretend we are spinning.
  1672. * This is needed for Coherent, which uses READ ID to check for
  1673. * sector interleaving.
  1674. */
  1675. if (cur_drv->last_sect != 0) {
  1676. cur_drv->sect = (cur_drv->sect % cur_drv->last_sect) + 1;
  1677. }
  1678. fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
  1679. }
  1680. /* Init functions */
  1681. static fdctrl_t *fdctrl_init_common (qemu_irq irq, int dma_chann,
  1682. target_phys_addr_t io_base,
  1683. BlockDriverState **fds)
  1684. {
  1685. fdctrl_t *fdctrl;
  1686. int i, j;
  1687. /* Fill 'command_to_handler' lookup table */
  1688. for (i = ARRAY_SIZE(handlers) - 1; i >= 0; i--) {
  1689. for (j = 0; j < sizeof(command_to_handler); j++) {
  1690. if ((j & handlers[i].mask) == handlers[i].value)
  1691. command_to_handler[j] = i;
  1692. }
  1693. }
  1694. FLOPPY_DPRINTF("init controller\n");
  1695. fdctrl = qemu_mallocz(sizeof(fdctrl_t));
  1696. fdctrl->fifo = qemu_memalign(512, FD_SECTOR_LEN);
  1697. fdctrl->result_timer = qemu_new_timer(vm_clock,
  1698. fdctrl_result_timer, fdctrl);
  1699. fdctrl->version = 0x90; /* Intel 82078 controller */
  1700. fdctrl->irq = irq;
  1701. fdctrl->dma_chann = dma_chann;
  1702. fdctrl->io_base = io_base;
  1703. fdctrl->config = FD_CONFIG_EIS | FD_CONFIG_EFIFO; /* Implicit seek, polling & FIFO enabled */
  1704. if (fdctrl->dma_chann != -1) {
  1705. DMA_register_channel(dma_chann, &fdctrl_transfer_handler, fdctrl);
  1706. }
  1707. for (i = 0; i < MAX_FD; i++) {
  1708. fd_init(&fdctrl->drives[i], fds[i]);
  1709. }
  1710. fdctrl_external_reset(fdctrl);
  1711. register_savevm("fdc", io_base, 2, fdc_save, fdc_load, fdctrl);
  1712. qemu_register_reset(fdctrl_external_reset, fdctrl);
  1713. for (i = 0; i < MAX_FD; i++) {
  1714. fd_revalidate(&fdctrl->drives[i]);
  1715. }
  1716. return fdctrl;
  1717. }
  1718. fdctrl_t *fdctrl_init (qemu_irq irq, int dma_chann, int mem_mapped,
  1719. target_phys_addr_t io_base,
  1720. BlockDriverState **fds)
  1721. {
  1722. fdctrl_t *fdctrl;
  1723. int io_mem;
  1724. fdctrl = fdctrl_init_common(irq, dma_chann, io_base, fds);
  1725. fdctrl->sun4m = 0;
  1726. if (mem_mapped) {
  1727. io_mem = cpu_register_io_memory(0, fdctrl_mem_read, fdctrl_mem_write,
  1728. fdctrl);
  1729. cpu_register_physical_memory(io_base, 0x08, io_mem);
  1730. } else {
  1731. register_ioport_read((uint32_t)io_base + 0x01, 5, 1,
  1732. &fdctrl_read_port, fdctrl);
  1733. register_ioport_read((uint32_t)io_base + 0x07, 1, 1,
  1734. &fdctrl_read_port, fdctrl);
  1735. register_ioport_write((uint32_t)io_base + 0x01, 5, 1,
  1736. &fdctrl_write_port, fdctrl);
  1737. register_ioport_write((uint32_t)io_base + 0x07, 1, 1,
  1738. &fdctrl_write_port, fdctrl);
  1739. }
  1740. return fdctrl;
  1741. }
  1742. fdctrl_t *sun4m_fdctrl_init (qemu_irq irq, target_phys_addr_t io_base,
  1743. BlockDriverState **fds, qemu_irq *fdc_tc)
  1744. {
  1745. fdctrl_t *fdctrl;
  1746. int io_mem;
  1747. fdctrl = fdctrl_init_common(irq, -1, io_base, fds);
  1748. fdctrl->sun4m = 1;
  1749. io_mem = cpu_register_io_memory(0, fdctrl_mem_read_strict,
  1750. fdctrl_mem_write_strict,
  1751. fdctrl);
  1752. cpu_register_physical_memory(io_base, 0x08, io_mem);
  1753. *fdc_tc = *qemu_allocate_irqs(fdctrl_handle_tc, fdctrl, 1);
  1754. return fdctrl;
  1755. }