BOOK.TXT
上传用户:datang2001
上传日期:2007-02-01
资源大小:53269k
文件大小:999k
源码类别:

操作系统开发

开发平台:

C/C++

  1. 07893 int privilege;
  2. 07894 {
  3. 07895 /* Build descriptor for a code segment. */
  4. 07896
  5. 07897   sdesc(segdp, base, size);
  6. 07898   segdp->access = (privilege << DPL_SHIFT)
  7. 07899                 | (PRESENT | SEGMENT | EXECUTABLE | READABLE);
  8. 07900                 /* CONFORMING = 0, ACCESSED = 0 */
  9. 07901 }
  10. 07903 /*=========================================================================*
  11. 07904  *                              init_dataseg                               *
  12. 07905  *=========================================================================*/
  13. 07906 PUBLIC void init_dataseg(segdp, base, size, privilege)
  14. 07907 register struct segdesc_s *segdp;
  15. 07908 phys_bytes base;
  16. 07909 phys_bytes size;
  17. 07910 int privilege;
  18. 07911 {
  19. 07912 /* Build descriptor for a data segment. */
  20. 07913
  21. 07914   sdesc(segdp, base, size);
  22. 07915   segdp->access = (privilege << DPL_SHIFT) | (PRESENT | SEGMENT | WRITEABLE);
  23. 07916                 /* EXECUTABLE = 0, EXPAND_DOWN = 0, ACCESSED = 0 */
  24. 07917 }
  25. 07919 /*=========================================================================*
  26. 07920  *                              sdesc                                      *
  27. 07921  *=========================================================================*/
  28. 07922 PRIVATE void sdesc(segdp, base, size)
  29. 07923 register struct segdesc_s *segdp;
  30. 07924 phys_bytes base;
  31. 07925 phys_bytes size;
  32. 07926 {
  33. 07927 /* Fill in the size fields (base, limit and granularity) of a descriptor. */
  34. 07928
  35. 07929   segdp->base_low = base;
  36. 07930   segdp->base_middle = base >> BASE_MIDDLE_SHIFT;
  37. 07931   segdp->base_high = base >> BASE_HIGH_SHIFT;
  38. 07932   --size;                       /* convert to a limit, 0 size means 4G */
  39. 07933   if (size > BYTE_GRAN_MAX) {
  40. 07934         segdp->limit_low = size >> PAGE_GRAN_SHIFT;
  41. 07935         segdp->granularity = GRANULAR | (size >>
  42. 07936                                      (PAGE_GRAN_SHIFT + GRANULARITY_SHIFT));
  43. 07937   } else {
  44. 07938         segdp->limit_low = size;
  45. 07939         segdp->granularity = size >> GRANULARITY_SHIFT;
  46. 07940   }
  47. 07941   segdp->granularity |= DEFAULT;        /* means BIG for data seg */
  48. 07942 }
  49. 07944 /*=========================================================================*
  50. 07945  *                              seg2phys                                   *
  51. 07946  *=========================================================================*/
  52. 07947 PUBLIC phys_bytes seg2phys(seg)
  53. 07948 U16_t seg;
  54. 07949 {
  55. 07950 /* Return the base address of a segment, with seg being either a 8086 segment
  56. 07951  * register, or a 286/386 segment selector.
  57. 07952  */
  58. 07953   phys_bytes base;
  59. 07954   struct segdesc_s *segdp;
  60. 07955
  61. 07956   if (!protected_mode) {
  62. 07957         base = hclick_to_physb(seg);
  63. 07958   } else {
  64. 07959         segdp = &gdt[seg >> 3];
  65. 07960         base = segdp->base_low | ((u32_t) segdp->base_middle << 16);
  66. 07961         base |= ((u32_t) segdp->base_high << 24);
  67. 07962   }
  68. 07963   return base;
  69. 07964 }
  70. 07966 /*=========================================================================*
  71. 07967  *                              int_gate                                   *
  72. 07968  *=========================================================================*/
  73. 07969 PRIVATE void int_gate(vec_nr, base, dpl_type)
  74. 07970 unsigned vec_nr;
  75. 07971 phys_bytes base;
  76. 07972 unsigned dpl_type;
  77. 07973 {
  78. 07974 /* Build descriptor for an interrupt gate. */
  79. 07975
  80. 07976   register struct gatedesc_s *idp;
  81. 07977
  82. 07978   idp = &idt[vec_nr];
  83. 07979   idp->offset_low = base;
  84. 07980   idp->selector = CS_SELECTOR;
  85. 07981   idp->p_dpl_type = dpl_type;
  86. 07982   idp->offset_high = base >> OFFSET_HIGH_SHIFT;
  87. 07983 }
  88. 07985 /*=========================================================================*
  89. 07986  *                              enable_iop                                 *
  90. 07987  *=========================================================================*/
  91. 07988 PUBLIC void enable_iop(pp)
  92. 07989 struct proc *pp;
  93. 07990 {
  94. 07991 /* Allow a user process to use I/O instructions.  Change the I/O Permission
  95. 07992  * Level bits in the psw. These specify least-privileged Current Permission
  96. 07993  * Level allowed to execute I/O instructions. Users and servers have CPL 3. 
  97. 07994  * You can't have less privilege than that. Kernel has CPL 0, tasks CPL 1.
  98. 07995  */
  99. 07996   pp->p_reg.psw |= 0x3000;
  100. 07997 }
  101. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  102. src/kernel/klib.s    
  103. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  104. 08000 #
  105. 08001 ! Chooses between the 8086 and 386 versions of the low level kernel code.
  106. 08002
  107. 08003 #include <minix/config.h>
  108. 08004 #if _WORD_SIZE == 2
  109. 08005 #include "klib88.s"
  110. 08006 #else
  111. 08007 #include "klib386.s"
  112. 08008 #endif
  113. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  114. src/kernel/klib386.s    
  115. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  116. 08100 #
  117. 08101 ! sections
  118. 08102
  119. 08103 .sect .text; .sect .rom; .sect .data; .sect .bss
  120. 08104
  121. 08105 #include <minix/config.h>
  122. 08106 #include <minix/const.h>
  123. 08107 #include "const.h"
  124. 08108 #include "sconst.h"
  125. 08109 #include "protect.h"
  126. 08110
  127. 08111 ! This file contains a number of assembly code utility routines needed by the
  128. 08112 ! kernel.  They are:
  129. 08113
  130. 08114 .define _monitor        ! exit Minix and return to the monitor
  131. 08115 .define _check_mem      ! check a block of memory, return the valid size
  132. 08116 .define _cp_mess        ! copies messages from source to destination
  133. 08117 .define _exit           ! dummy for library routines
  134. 08118 .define __exit          ! dummy for library routines
  135. 08119 .define ___exit         ! dummy for library routines
  136. 08120 .define ___main         ! dummy for GCC
  137. 08121 .define _in_byte        ! read a byte from a port and return it
  138. 08122 .define _in_word        ! read a word from a port and return it
  139. 08123 .define _out_byte       ! write a byte to a port
  140. 08124 .define _out_word       ! write a word to a port
  141. 08125 .define _port_read      ! transfer data from (disk controller) port to memory
  142. 08126 .define _port_read_byte ! likewise byte by byte
  143. 08127 .define _port_write     ! transfer data from memory to (disk controller) port
  144. 08128 .define _port_write_byte ! likewise byte by byte
  145. 08129 .define _lock           ! disable interrupts
  146. 08130 .define _unlock         ! enable interrupts
  147. 08131 .define _enable_irq     ! enable an irq at the 8259 controller
  148. 08132 .define _disable_irq    ! disable an irq
  149. 08133 .define _phys_copy      ! copy data from anywhere to anywhere in memory
  150. 08134 .define _mem_rdw        ! copy one word from [segment:offset]
  151. 08135 .define _reset          ! reset the system
  152. 08136 .define _mem_vid_copy   ! copy data to video ram
  153. 08137 .define _vid_vid_copy   ! move data in video ram
  154. 08138 .define _level0         ! call a function at level 0
  155. 08139
  156. 08140 ! The routines only guarantee to preserve the registers the C compiler
  157. 08141 ! expects to be preserved (ebx, esi, edi, ebp, esp, segment registers, and
  158. 08142 ! direction bit in the flags).
  159. 08143
  160. 08144 ! imported variables
  161. 08145
  162. 08146 .sect .bss
  163. 08147 .extern _mon_return, _mon_sp
  164. 08148 .extern _irq_use
  165. 08149 .extern _blank_color
  166. 08150 .extern _ext_memsize
  167. 08151 .extern _gdt
  168. 08152 .extern _low_memsize
  169. 08153 .extern _sizes
  170. 08154 .extern _vid_seg
  171. 08155 .extern _vid_size
  172. 08156 .extern _vid_mask
  173. 08157 .extern _level0_func
  174. 08158
  175. 08159 .sect .text
  176. 08160 !*===========================================================================*
  177. 08161 !*                              monitor                                      *
  178. 08162 !*===========================================================================*
  179. 08163 ! PUBLIC void monitor();
  180. 08164 ! Return to the monitor.
  181. 08165
  182. 08166 _monitor:
  183. 08167         mov     eax, (_reboot_code)     ! address of new parameters
  184. 08168         mov     esp, (_mon_sp)          ! restore monitor stack pointer
  185. 08169     o16 mov     dx, SS_SELECTOR         ! monitor data segment
  186. 08170         mov     ds, dx
  187. 08171         mov     es, dx
  188. 08172         mov     fs, dx
  189. 08173         mov     gs, dx
  190. 08174         mov     ss, dx
  191. 08175         pop     edi
  192. 08176         pop     esi
  193. 08177         pop     ebp
  194. 08178     o16 retf                            ! return to the monitor
  195. 08179
  196. 08180
  197. 08181 !*===========================================================================*
  198. 08182 !*                              check_mem                                    *
  199. 08183 !*===========================================================================*
  200. 08184 ! PUBLIC phys_bytes check_mem(phys_bytes base, phys_bytes size);
  201. 08185 ! Check a block of memory, return the amount valid.
  202. 08186 ! Only every 16th byte is checked.
  203. 08187 ! An initial size of 0 means everything.
  204. 08188 ! This really should do some alias checks.
  205. 08189
  206. 08190 CM_DENSITY      =       16
  207. 08191 CM_LOG_DENSITY  =       4
  208. 08192 TEST1PATTERN    =       0x55            ! memory test pattern 1
  209. 08193 TEST2PATTERN    =       0xAA            ! memory test pattern 2
  210. 08194
  211. 08195 CHKM_ARGS       =       4 + 4 + 4       ! 4 + 4
  212. 08196 !                       ds ebx eip      base size
  213. 08197
  214. 08198 _check_mem:
  215. 08199         push    ebx
  216. 08200         push    ds
  217. 08201     o16 mov     ax, FLAT_DS_SELECTOR
  218. 08202         mov     ds, ax
  219. 08203         mov     eax, CHKM_ARGS(esp)
  220. 08204         mov     ebx, eax
  221. 08205         mov     ecx, CHKM_ARGS+4(esp)
  222. 08206         shr     ecx, CM_LOG_DENSITY
  223. 08207 cm_loop:
  224. 08208         movb    dl, TEST1PATTERN
  225. 08209         xchgb   dl, (eax)               ! write test pattern, remember original
  226. 08210         xchgb   dl, (eax)               ! restore original, read test pattern
  227. 08211         cmpb    dl, TEST1PATTERN        ! must agree if good real memory
  228. 08212         jnz     cm_exit                 ! if different, memory is unusable
  229. 08213         movb    dl, TEST2PATTERN
  230. 08214         xchgb   dl, (eax)
  231. 08215         xchgb   dl, (eax)
  232. 08216         add     eax, CM_DENSITY
  233. 08217         cmpb    dl, TEST2PATTERN
  234. 08218         loopz   cm_loop
  235. 08219 cm_exit:
  236. 08220         sub     eax, ebx
  237. 08221         pop     ds
  238. 08222         pop     ebx
  239. 08223         ret
  240. 08224
  241. 08225
  242. 08226 !*===========================================================================*
  243. 08227 !*                              cp_mess                                      *
  244. 08228 !*===========================================================================*
  245. 08229 ! PUBLIC void cp_mess(int src, phys_clicks src_clicks, vir_bytes src_offset,
  246. 08230 !                     phys_clicks dst_clicks, vir_bytes dst_offset);
  247. 08231 ! This routine makes a fast copy of a message from anywhere in the address
  248. 08232 ! space to anywhere else.  It also copies the source address provided as a
  249. 08233 ! parameter to the call into the first word of the destination message.
  250. 08234 !
  251. 08235 ! Note that the message size, "Msize" is in DWORDS (not bytes) and must be set
  252. 08236 ! correctly.  Changing the definition of message in the type file and not
  253. 08237 ! changing it here will lead to total disaster.
  254. 08238
  255. 08239 CM_ARGS =       4 + 4 + 4 + 4 + 4       ! 4 + 4 + 4 + 4 + 4
  256. 08240 !               es  ds edi esi eip      proc scl sof dcl dof
  257. 08241
  258. 08242         .align  16
  259. 08243 _cp_mess:
  260. 08244         cld
  261. 08245         push    esi
  262. 08246         push    edi
  263. 08247         push    ds
  264. 08248         push    es
  265. 08249
  266. 08250         mov     eax, FLAT_DS_SELECTOR
  267. 08251         mov     ds, ax
  268. 08252         mov     es, ax
  269. 08253
  270. 08254         mov     esi, CM_ARGS+4(esp)             ! src clicks
  271. 08255         shl     esi, CLICK_SHIFT
  272. 08256         add     esi, CM_ARGS+4+4(esp)           ! src offset
  273. 08257         mov     edi, CM_ARGS+4+4+4(esp)         ! dst clicks
  274. 08258         shl     edi, CLICK_SHIFT
  275. 08259         add     edi, CM_ARGS+4+4+4+4(esp)       ! dst offset
  276. 08260
  277. 08261         mov     eax, CM_ARGS(esp)       ! process number of sender
  278. 08262         stos                            ! copy number of sender to dest message
  279. 08263         add     esi, 4                  ! do not copy first word
  280. 08264         mov     ecx, Msize - 1          ! remember, first word does not count
  281. 08265         rep
  282. 08266         movs                            ! copy the message
  283. 08267
  284. 08268         pop     es
  285. 08269         pop     ds
  286. 08270         pop     edi
  287. 08271         pop     esi
  288. 08272         ret                             ! that is all folks!
  289. 08273
  290. 08274
  291. 08275 !*===========================================================================*
  292. 08276 !*                              exit                                         *
  293. 08277 !*===========================================================================*
  294. 08278 ! PUBLIC void exit();
  295. 08279 ! Some library routines use exit, so provide a dummy version.
  296. 08280 ! Actual calls to exit cannot occur in the kernel.
  297. 08281 ! GNU CC likes to call ___main from main() for nonobvious reasons.
  298. 08282
  299. 08283 _exit:
  300. 08284 __exit:
  301. 08285 ___exit:
  302. 08286         sti
  303. 08287         jmp     ___exit
  304. 08288
  305. 08289 ___main:
  306. 08290         ret
  307. 08291
  308. 08292
  309. 08293 !*===========================================================================*
  310. 08294 !*                              in_byte                                      *
  311. 08295 !*===========================================================================*
  312. 08296 ! PUBLIC unsigned in_byte(port_t port);
  313. 08297 ! Read an (unsigned) byte from the i/o port  port  and return it.
  314. 08298
  315. 08299         .align  16
  316. 08300 _in_byte:
  317. 08301         mov     edx, 4(esp)             ! port
  318. 08302         sub     eax, eax
  319. 08303         inb     dx                      ! read 1 byte
  320. 08304         ret
  321. 08305
  322. 08306
  323. 08307 !*===========================================================================*
  324. 08308 !*                              in_word                                      *
  325. 08309 !*===========================================================================*
  326. 08310 ! PUBLIC unsigned in_word(port_t port);
  327. 08311 ! Read an (unsigned) word from the i/o port  port  and return it.
  328. 08312
  329. 08313         .align  16
  330. 08314 _in_word:
  331. 08315         mov     edx, 4(esp)             ! port
  332. 08316         sub     eax, eax
  333. 08317     o16 in      dx                      ! read 1 word
  334. 08318         ret
  335. 08319
  336. 08320
  337. 08321 !*===========================================================================*
  338. 08322 !*                              out_byte                                     *
  339. 08323 !*===========================================================================*
  340. 08324 ! PUBLIC void out_byte(port_t port, u8_t value);
  341. 08325 ! Write  value  (cast to a byte)  to the I/O port  port.
  342. 08326
  343. 08327         .align  16
  344. 08328 _out_byte:
  345. 08329         mov     edx, 4(esp)             ! port
  346. 08330         movb    al, 4+4(esp)            ! value
  347. 08331         outb    dx                      ! output 1 byte
  348. 08332         ret
  349. 08333
  350. 08334
  351. 08335 !*===========================================================================*
  352. 08336 !*                              out_word                                     *
  353. 08337 !*===========================================================================*
  354. 08338 ! PUBLIC void out_word(Port_t port, U16_t value);
  355. 08339 ! Write  value  (cast to a word)  to the I/O port  port.
  356. 08340
  357. 08341         .align  16
  358. 08342 _out_word:
  359. 08343         mov     edx, 4(esp)             ! port
  360. 08344         mov     eax, 4+4(esp)           ! value
  361. 08345     o16 out     dx                      ! output 1 word
  362. 08346         ret
  363. 08347
  364. 08348
  365. 08349 !*===========================================================================*
  366. 08350 !*                              port_read                                    *
  367. 08351 !*===========================================================================*
  368. 08352 ! PUBLIC void port_read(port_t port, phys_bytes destination, unsigned bytcount);
  369. 08353 ! Transfer data from (hard disk controller) port to memory.
  370. 08354
  371. 08355 PR_ARGS =       4 + 4 + 4               ! 4 + 4 + 4
  372. 08356 !               es edi eip              port dst len
  373. 08357
  374. 08358         .align  16
  375. 08359 _port_read:
  376. 08360         cld
  377. 08361         push    edi
  378. 08362         push    es
  379. 08363         mov     ecx, FLAT_DS_SELECTOR
  380. 08364         mov     es, cx
  381. 08365         mov     edx, PR_ARGS(esp)       ! port to read from
  382. 08366         mov     edi, PR_ARGS+4(esp)     ! destination addr
  383. 08367         mov     ecx, PR_ARGS+4+4(esp)   ! byte count
  384. 08368         shr     ecx, 1                  ! word count
  385. 08369         rep                             ! (hardware cannot handle dwords)
  386. 08370     o16 ins                             ! read everything
  387. 08371         pop     es
  388. 08372         pop     edi
  389. 08373         ret
  390. 08374
  391. 08375
  392. 08376 !*===========================================================================*
  393. 08377 !*                              port_read_byte                               *
  394. 08378 !*===========================================================================*
  395. 08379 ! PUBLIC void port_read_byte(port_t port, phys_bytes destination,
  396. 08380 !                                               unsigned bytcount);
  397. 08381 ! Transfer data from port to memory.
  398. 08382
  399. 08383 PR_ARGS_B =     4 + 4 + 4               ! 4 + 4 + 4
  400. 08384 !               es edi eip              port dst len
  401. 08385
  402. 08386 _port_read_byte:
  403. 08387         cld
  404. 08388         push    edi
  405. 08389         push    es
  406. 08390         mov     ecx, FLAT_DS_SELECTOR
  407. 08391         mov     es, cx
  408. 08392         mov     edx, PR_ARGS_B(esp)
  409. 08393         mov     edi, PR_ARGS_B+4(esp)
  410. 08394         mov     ecx, PR_ARGS_B+4+4(esp)
  411. 08395         rep
  412. 08396         insb
  413. 08397         pop     es
  414. 08398         pop     edi
  415. 08399         ret
  416. 08400
  417. 08401
  418. 08402 !*===========================================================================*
  419. 08403 !*                              port_write                                   *
  420. 08404 !*===========================================================================*
  421. 08405 ! PUBLIC void port_write(port_t port, phys_bytes source, unsigned bytcount);
  422. 08406 ! Transfer data from memory to (hard disk controller) port.
  423. 08407
  424. 08408 PW_ARGS =       4 + 4 + 4               ! 4 + 4 + 4
  425. 08409 !               es edi eip              port src len
  426. 08410
  427. 08411         .align  16
  428. 08412 _port_write:
  429. 08413         cld
  430. 08414         push    esi
  431. 08415         push    ds
  432. 08416         mov     ecx, FLAT_DS_SELECTOR
  433. 08417         mov     ds, cx
  434. 08418         mov     edx, PW_ARGS(esp)       ! port to write to
  435. 08419         mov     esi, PW_ARGS+4(esp)     ! source addr
  436. 08420         mov     ecx, PW_ARGS+4+4(esp)   ! byte count
  437. 08421         shr     ecx, 1                  ! word count
  438. 08422         rep                             ! (hardware cannot handle dwords)
  439. 08423     o16 outs                            ! write everything
  440. 08424         pop     ds
  441. 08425         pop     esi
  442. 08426         ret
  443. 08427
  444. 08428
  445. 08429 !*===========================================================================*
  446. 08430 !*                              port_write_byte                              *
  447. 08431 !*===========================================================================*
  448. 08432 ! PUBLIC void port_write_byte(port_t port, phys_bytes source,
  449. 08433 !                                               unsigned bytcount);
  450. 08434 ! Transfer data from memory to port.
  451. 08435
  452. 08436 PW_ARGS_B =     4 + 4 + 4               ! 4 + 4 + 4
  453. 08437 !               es edi eip              port src len
  454. 08438
  455. 08439 _port_write_byte:
  456. 08440         cld
  457. 08441         push    esi
  458. 08442         push    ds
  459. 08443         mov     ecx, FLAT_DS_SELECTOR
  460. 08444         mov     ds, cx
  461. 08445         mov     edx, PW_ARGS_B(esp)
  462. 08446         mov     esi, PW_ARGS_B+4(esp)
  463. 08447         mov     ecx, PW_ARGS_B+4+4(esp)
  464. 08448         rep
  465. 08449         outsb
  466. 08450         pop     ds
  467. 08451         pop     esi
  468. 08452         ret
  469. 08453
  470. 08454
  471. 08455 !*===========================================================================*
  472. 08456 !*                              lock                                         *
  473. 08457 !*===========================================================================*
  474. 08458 ! PUBLIC void lock();
  475. 08459 ! Disable CPU interrupts.
  476. 08460
  477. 08461         .align  16
  478. 08462 _lock:
  479. 08463         cli                             ! disable interrupts
  480. 08464         ret
  481. 08465
  482. 08466
  483. 08467 !*===========================================================================*
  484. 08468 !*                              unlock                                       *
  485. 08469 !*===========================================================================*
  486. 08470 ! PUBLIC void unlock();
  487. 08471 ! Enable CPU interrupts.
  488. 08472
  489. 08473         .align  16
  490. 08474 _unlock:
  491. 08475         sti
  492. 08476         ret
  493. 08477
  494. 08478
  495. 08479 !*==========================================================================*
  496. 08480 !*                              enable_irq                                  *
  497. 08481 !*==========================================================================*/
  498. 08482 ! PUBLIC void enable_irq(unsigned irq)
  499. 08483 ! Enable an interrupt request line by clearing an 8259 bit.
  500. 08484 ! Equivalent code for irq < 8:
  501. 08485 !       out_byte(INT_CTLMASK, in_byte(INT_CTLMASK) & ~(1 << irq));
  502. 08486
  503. 08487         .align  16
  504. 08488 _enable_irq:
  505. 08489         mov     ecx, 4(esp)             ! irq
  506. 08490         pushf
  507. 08491         cli
  508. 08492         movb    ah, ~1
  509. 08493         rolb    ah, cl                  ! ah = ~(1 << (irq % 8))
  510. 08494         cmpb    cl, 8
  511. 08495         jae     enable_8                ! enable irq >= 8 at the slave 8259
  512. 08496 enable_0:
  513. 08497         inb     INT_CTLMASK
  514. 08498         andb    al, ah
  515. 08499         outb    INT_CTLMASK             ! clear bit at master 8259
  516. 08500         popf
  517. 08501         ret
  518. 08502         .align  4
  519. 08503 enable_8:
  520. 08504         inb     INT2_CTLMASK
  521. 08505         andb    al, ah
  522. 08506         outb    INT2_CTLMASK            ! clear bit at slave 8259
  523. 08507         popf
  524. 08508         ret
  525. 08509
  526. 08510
  527. 08511 !*==========================================================================*
  528. 08512 !*                              disable_irq                                 *
  529. 08513 !*==========================================================================*/
  530. 08514 ! PUBLIC int disable_irq(unsigned irq)
  531. 08515 ! Disable an interrupt request line by setting an 8259 bit.
  532. 08516 ! Equivalent code for irq < 8:
  533. 08517 !       out_byte(INT_CTLMASK, in_byte(INT_CTLMASK) | (1 << irq));
  534. 08518 ! Returns true iff the interrupt was not already disabled.
  535. 08519
  536. 08520         .align  16
  537. 08521 _disable_irq:
  538. 08522         mov     ecx, 4(esp)             ! irq
  539. 08523         pushf
  540. 08524         cli
  541. 08525         movb    ah, 1
  542. 08526         rolb    ah, cl                  ! ah = (1 << (irq % 8))
  543. 08527         cmpb    cl, 8
  544. 08528         jae     disable_8               ! disable irq >= 8 at the slave 8259
  545. 08529 disable_0:
  546. 08530         inb     INT_CTLMASK
  547. 08531         testb   al, ah
  548. 08532         jnz     dis_already             ! already disabled?
  549. 08533         orb     al, ah
  550. 08534         outb    INT_CTLMASK             ! set bit at master 8259
  551. 08535         popf
  552. 08536         mov     eax, 1                  ! disabled by this function
  553. 08537         ret
  554. 08538 disable_8:
  555. 08539         inb     INT2_CTLMASK
  556. 08540         testb   al, ah
  557. 08541         jnz     dis_already             ! already disabled?
  558. 08542         orb     al, ah
  559. 08543         outb    INT2_CTLMASK            ! set bit at slave 8259
  560. 08544         popf
  561. 08545         mov     eax, 1                  ! disabled by this function
  562. 08546         ret
  563. 08547 dis_already:
  564. 08548         popf
  565. 08549         xor     eax, eax                ! already disabled
  566. 08550         ret
  567. 08551
  568. 08552
  569. 08553 !*===========================================================================*
  570. 08554 !*                              phys_copy                                    *
  571. 08555 !*===========================================================================*
  572. 08556 ! PUBLIC void phys_copy(phys_bytes source, phys_bytes destination,
  573. 08557 !                       phys_bytes bytecount);
  574. 08558 ! Copy a block of physical memory.
  575. 08559
  576. 08560 PC_ARGS =       4 + 4 + 4 + 4   ! 4 + 4 + 4
  577. 08561 !               es edi esi eip   src dst len
  578. 08562
  579. 08563         .align  16
  580. 08564 _phys_copy:
  581. 08565         cld
  582. 08566         push    esi
  583. 08567         push    edi
  584. 08568         push    es
  585. 08569
  586. 08570         mov     eax, FLAT_DS_SELECTOR
  587. 08571         mov     es, ax
  588. 08572
  589. 08573         mov     esi, PC_ARGS(esp)
  590. 08574         mov     edi, PC_ARGS+4(esp)
  591. 08575         mov     eax, PC_ARGS+4+4(esp)
  592. 08576
  593. 08577         cmp     eax, 10                 ! avoid align overhead for small counts
  594. 08578         jb      pc_small
  595. 08579         mov     ecx, esi                ! align source, hope target is too
  596. 08580         neg     ecx
  597. 08581         and     ecx, 3                  ! count for alignment
  598. 08582         sub     eax, ecx
  599. 08583         rep
  600. 08584    eseg movsb
  601. 08585         mov     ecx, eax
  602. 08586         shr     ecx, 2                  ! count of dwords
  603. 08587         rep
  604. 08588    eseg movs
  605. 08589         and     eax, 3
  606. 08590 pc_small:
  607. 08591         xchg    ecx, eax                ! remainder
  608. 08592         rep
  609. 08593    eseg movsb
  610. 08594
  611. 08595         pop     es
  612. 08596         pop     edi
  613. 08597         pop     esi
  614. 08598         ret
  615. 08599
  616. 08600
  617. 08601 !*===========================================================================*
  618. 08602 !*                              mem_rdw                                      *
  619. 08603 !*===========================================================================*
  620. 08604 ! PUBLIC u16_t mem_rdw(U16_t segment, u16_t *offset);
  621. 08605 ! Load and return word at far pointer segment:offset.
  622. 08606
  623. 08607         .align  16
  624. 08608 _mem_rdw:
  625. 08609         mov     cx, ds
  626. 08610         mov     ds, 4(esp)              ! segment
  627. 08611         mov     eax, 4+4(esp)           ! offset
  628. 08612         movzx   eax, (eax)              ! word to return
  629. 08613         mov     ds, cx
  630. 08614         ret
  631. 08615
  632. 08616
  633. 08617 !*===========================================================================*
  634. 08618 !*                              reset                                        *
  635. 08619 !*===========================================================================*
  636. 08620 ! PUBLIC void reset();
  637. 08621 ! Reset the system by loading IDT with offset 0 and interrupting.
  638. 08622
  639. 08623 _reset:
  640. 08624         lidt    (idt_zero)
  641. 08625         int     3               ! anything goes, the 386 will not like it
  642. 08626 .sect .data
  643. 08627 idt_zero:       .data4  0, 0
  644. 08628 .sect .text
  645. 08629
  646. 08630
  647. 08631 !*===========================================================================*
  648. 08632 !*                              mem_vid_copy                                 *
  649. 08633 !*===========================================================================*
  650. 08634 ! PUBLIC void mem_vid_copy(u16 *src, unsigned dst, unsigned count);
  651. 08635 !
  652. 08636 ! Copy count characters from kernel memory to video memory.  Src, dst and
  653. 08637 ! count are character (word) based video offsets and counts.  If src is null
  654. 08638 ! then screen memory is blanked by filling it with blank_color.
  655. 08639
  656. 08640 MVC_ARGS        =       4 + 4 + 4 + 4   ! 4 + 4 + 4
  657. 08641 !                       es edi esi eip   src dst ct
  658. 08642
  659. 08643 _mem_vid_copy:
  660. 08644         push    esi
  661. 08645         push    edi
  662. 08646         push    es
  663. 08647         mov     esi, MVC_ARGS(esp)      ! source
  664. 08648         mov     edi, MVC_ARGS+4(esp)    ! destination
  665. 08649         mov     edx, MVC_ARGS+4+4(esp)  ! count
  666. 08650         mov     es, (_vid_seg)          ! destination is video segment
  667. 08651         cld                             ! make sure direction is up
  668. 08652 mvc_loop:
  669. 08653         and     edi, (_vid_mask)        ! wrap address
  670. 08654         mov     ecx, edx                ! one chunk to copy
  671. 08655         mov     eax, (_vid_size)
  672. 08656         sub     eax, edi
  673. 08657         cmp     ecx, eax
  674. 08658         jbe     0f
  675. 08659         mov     ecx, eax                ! ecx = min(ecx, vid_size - edi)
  676. 08660 0:      sub     edx, ecx                ! count -= ecx
  677. 08661         shl     edi, 1                  ! byte address
  678. 08662         test    esi, esi                ! source == 0 means blank the screen
  679. 08663         jz      mvc_blank
  680. 08664 mvc_copy:
  681. 08665         rep                             ! copy words to video memory
  682. 08666     o16 movs
  683. 08667         jmp     mvc_test
  684. 08668 mvc_blank:
  685. 08669         mov     eax, (_blank_color)     ! ax = blanking character
  686. 08670         rep
  687. 08671     o16 stos                            ! copy blanks to video memory
  688. 08672         !jmp    mvc_test
  689. 08673 mvc_test:
  690. 08674         shr     edi, 1                  ! word addresses
  691. 08675         test    edx, edx
  692. 08676         jnz     mvc_loop
  693. 08677 mvc_done:
  694. 08678         pop     es
  695. 08679         pop     edi
  696. 08680         pop     esi
  697. 08681         ret
  698. 08682
  699. 08683
  700. 08684 !*===========================================================================*
  701. 08685 !*                              vid_vid_copy                                 *
  702. 08686 !*===========================================================================*
  703. 08687 ! PUBLIC void vid_vid_copy(unsigned src, unsigned dst, unsigned count);
  704. 08688 !
  705. 08689 ! Copy count characters from video memory to video memory.  Handle overlap.
  706. 08690 ! Used for scrolling, line or character insertion and deletion.  Src, dst
  707. 08691 ! and count are character (word) based video offsets and counts.
  708. 08692
  709. 08693 VVC_ARGS        =       4 + 4 + 4 + 4   ! 4 + 4 + 4
  710. 08694 !                       es edi esi eip   src dst ct
  711. 08695
  712. 08696 _vid_vid_copy:
  713. 08697         push    esi
  714. 08698         push    edi
  715. 08699         push    es
  716. 08700         mov     esi, VVC_ARGS(esp)      ! source
  717. 08701         mov     edi, VVC_ARGS+4(esp)    ! destination
  718. 08702         mov     edx, VVC_ARGS+4+4(esp)  ! count
  719. 08703         mov     es, (_vid_seg)          ! use video segment
  720. 08704         cmp     esi, edi                ! copy up or down?
  721. 08705         jb      vvc_down
  722. 08706 vvc_up:
  723. 08707         cld                             ! direction is up
  724. 08708 vvc_uploop:
  725. 08709         and     esi, (_vid_mask)        ! wrap addresses
  726. 08710         and     edi, (_vid_mask)
  727. 08711         mov     ecx, edx                ! one chunk to copy
  728. 08712         mov     eax, (_vid_size)
  729. 08713         sub     eax, esi
  730. 08714         cmp     ecx, eax
  731. 08715         jbe     0f
  732. 08716         mov     ecx, eax                ! ecx = min(ecx, vid_size - esi)
  733. 08717 0:      mov     eax, (_vid_size)
  734. 08718         sub     eax, edi
  735. 08719         cmp     ecx, eax
  736. 08720         jbe     0f
  737. 08721         mov     ecx, eax                ! ecx = min(ecx, vid_size - edi)
  738. 08722 0:      sub     edx, ecx                ! count -= ecx
  739. 08723         shl     esi, 1
  740. 08724         shl     edi, 1                  ! byte addresses
  741. 08725         rep
  742. 08726 eseg o16 movs                           ! copy video words
  743. 08727         shr     esi, 1
  744. 08728         shr     edi, 1                  ! word addresses
  745. 08729         test    edx, edx
  746. 08730         jnz     vvc_uploop              ! again?
  747. 08731         jmp     vvc_done
  748. 08732 vvc_down:
  749. 08733         std                             ! direction is down
  750. 08734         lea     esi, -1(esi)(edx*1)     ! start copying at the top
  751. 08735         lea     edi, -1(edi)(edx*1)
  752. 08736 vvc_downloop:
  753. 08737         and     esi, (_vid_mask)        ! wrap addresses
  754. 08738         and     edi, (_vid_mask)
  755. 08739         mov     ecx, edx                ! one chunk to copy
  756. 08740         lea     eax, 1(esi)
  757. 08741         cmp     ecx, eax
  758. 08742         jbe     0f
  759. 08743         mov     ecx, eax                ! ecx = min(ecx, esi + 1)
  760. 08744 0:      lea     eax, 1(edi)
  761. 08745         cmp     ecx, eax
  762. 08746         jbe     0f
  763. 08747         mov     ecx, eax                ! ecx = min(ecx, edi + 1)
  764. 08748 0:      sub     edx, ecx                ! count -= ecx
  765. 08749         shl     esi, 1
  766. 08750         shl     edi, 1                  ! byte addresses
  767. 08751         rep
  768. 08752 eseg o16 movs                           ! copy video words
  769. 08753         shr     esi, 1
  770. 08754         shr     edi, 1                  ! word addresses
  771. 08755         test    edx, edx
  772. 08756         jnz     vvc_downloop            ! again?
  773. 08757         cld                             ! C compiler expect up
  774. 08758         !jmp    vvc_done
  775. 08759 vvc_done:
  776. 08760         pop     es
  777. 08761         pop     edi
  778. 08762         pop     esi
  779. 08763         ret
  780. 08764
  781. 08765
  782. 08766 !*===========================================================================*
  783. 08767 !*                            level0                                         *
  784. 08768 !*===========================================================================*
  785. 08769 ! PUBLIC void level0(void (*func)(void))
  786. 08770 ! Call a function at permission level 0.  This allows kernel tasks to do
  787. 08771 ! things that are only possible at the most privileged CPU level.
  788. 08772 !
  789. 08773 _level0:
  790. 08774         mov     eax, 4(esp)
  791. 08775         mov     (_level0_func), eax
  792. 08776         int     LEVEL0_VECTOR
  793. 08777         ret
  794. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  795. src/kernel/misc.c    
  796. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  797. 08800 /* This file contains a collection of miscellaneous procedures:
  798. 08801  *      mem_init:       initialize memory tables.  Some memory is reported
  799. 08802  *                      by the BIOS, some is guesstimated and checked later
  800. 08803  *      env_parse       parse environment variable.
  801. 08804  *      bad_assertion   for debugging
  802. 08805  *      bad_compare     for debugging
  803. 08806  */
  804. 08807
  805. 08808 #include "kernel.h"
  806. 08809 #include "assert.h"
  807. 08810 #include <stdlib.h>
  808. 08811 #include <minix/com.h>
  809. 08812
  810. 08813 #define EM_BASE     0x100000L   /* base of extended memory on AT's */
  811. 08814 #define SHADOW_BASE 0xFA0000L   /* base of RAM shadowing ROM on some AT's */
  812. 08815 #define SHADOW_MAX  0x060000L   /* maximum usable shadow memory (16M limit) */
  813. 08816
  814. 08817 /*=========================================================================*
  815. 08818  *                              mem_init                                   *
  816. 08819  *=========================================================================*/
  817. 08820 PUBLIC void mem_init()
  818. 08821 {
  819. 08822 /* Initialize the memory size tables.  This is complicated by fragmentation
  820. 08823  * and different access strategies for protected mode.  There must be a
  821. 08824  * chunk at 0 big enough to hold Minix proper.  For 286 and 386 processors,
  822. 08825  * there can be extended memory (memory above 1MB).  This usually starts at
  823. 08826  * 1MB, but there may be another chunk just below 16MB, reserved under DOS
  824. 08827  * for shadowing ROM, but available to Minix if the hardware can be re-mapped.
  825. 08828  * In protected mode, extended memory is accessible assuming CLICK_SIZE is
  826. 08829  * large enough, and is treated as ordinary memory.
  827. 08830  */
  828. 08831
  829. 08832   u32_t ext_clicks;
  830. 08833   phys_clicks max_clicks;
  831. 08834
  832. 08835   /* Get the size of ordinary memory from the BIOS. */
  833. 08836   mem[0].size = k_to_click(low_memsize);        /* base = 0 */
  834. 08837
  835. 08838   if (pc_at && protected_mode) {
  836. 08839         /* Get the size of extended memory from the BIOS.  This is special
  837. 08840          * except in protected mode, but protected mode is now normal.
  838. 08841          * Note that no more than 16M can be addressed in 286 mode, so make
  839. 08842          * sure that the highest memory address fits in a short when counted
  840. 08843          * in clicks.
  841. 08844          */
  842. 08845         ext_clicks = k_to_click((u32_t) ext_memsize);
  843. 08846         max_clicks = USHRT_MAX - (EM_BASE >> CLICK_SHIFT);
  844. 08847         mem[1].size = MIN(ext_clicks, max_clicks);
  845. 08848         mem[1].base = EM_BASE >> CLICK_SHIFT;
  846. 08849
  847. 08850         if (ext_memsize <= (unsigned) ((SHADOW_BASE - EM_BASE) / 1024)
  848. 08851                         && check_mem(SHADOW_BASE, SHADOW_MAX) == SHADOW_MAX) {
  849. 08852                 /* Shadow ROM memory. */
  850. 08853                 mem[2].size = SHADOW_MAX >> CLICK_SHIFT;
  851. 08854                 mem[2].base = SHADOW_BASE >> CLICK_SHIFT;
  852. 08855         }
  853. 08856   }
  854. 08857
  855. 08858   /* Total system memory. */
  856. 08859   tot_mem_size = mem[0].size + mem[1].size + mem[2].size;
  857. 08860 }
  858. 08862 /*=========================================================================*
  859. 08863  *                              env_parse                                  *
  860. 08864  *=========================================================================*/
  861. 08865 PUBLIC int env_parse(env, fmt, field, param, min, max)
  862. 08866 char *env;              /* environment variable to inspect */
  863. 08867 char *fmt;              /* template to parse it with */
  864. 08868 int field;              /* field number of value to return */
  865. 08869 long *param;            /* address of parameter to get */
  866. 08870 long min, max;          /* minimum and maximum values for the parameter */
  867. 08871 {
  868. 08872 /* Parse an environment variable setting, something like "DPETH0=300:3".
  869. 08873  * Panic if the parsing fails.  Return EP_UNSET if the environment variable
  870. 08874  * is not set, EP_OFF if it is set to "off", EP_ON if set to "on" or a
  871. 08875  * field is left blank, or EP_SET if a field is given (return value through
  872. 08876  * *param).  Commas and colons may be used in the environment and format
  873. 08877  * string, fields in the environment string may be empty, and punctuation
  874. 08878  * may be missing to skip fields.  The format string contains characters
  875. 08879  * 'd', 'o', 'x' and 'c' to indicate that 10, 8, 16, or 0 is used as the
  876. 08880  * last argument to strtol.
  877. 08881  */
  878. 08882
  879. 08883   char *val, *end;
  880. 08884   long newpar;
  881. 08885   int i = 0, radix, r;
  882. 08886
  883. 08887   if ((val = k_getenv(env)) == NIL_PTR) return(EP_UNSET);
  884. 08888   if (strcmp(val, "off") == 0) return(EP_OFF);
  885. 08889   if (strcmp(val, "on") == 0) return(EP_ON);
  886. 08890
  887. 08891   r = EP_ON;
  888. 08892   for (;;) {
  889. 08893         while (*val == ' ') val++;
  890. 08894
  891. 08895         if (*val == 0) return(r);       /* the proper exit point */
  892. 08896
  893. 08897         if (*fmt == 0) break;           /* too many values */
  894. 08898
  895. 08899         if (*val == ',' || *val == ':') {
  896. 08900                 /* Time to go to the next field. */
  897. 08901                 if (*fmt == ',' || *fmt == ':') i++;
  898. 08902                 if (*fmt++ == *val) val++;
  899. 08903         } else {
  900. 08904                 /* Environment contains a value, get it. */
  901. 08905                 switch (*fmt) {
  902. 08906                 case 'd':       radix =   10;   break;
  903. 08907                 case 'o':       radix =  010;   break;
  904. 08908                 case 'x':       radix = 0x10;   break;
  905. 08909                 case 'c':       radix =    0;   break;
  906. 08910                 default:        goto badenv;
  907. 08911                 }
  908. 08912                 newpar = strtol(val, &end, radix);
  909. 08913
  910. 08914                 if (end == val) break;  /* not a number */
  911. 08915                 val = end;
  912. 08916
  913. 08917                 if (i == field) {
  914. 08918                         /* The field requested. */
  915. 08919                         if (newpar < min || newpar > max) break;
  916. 08920                         *param = newpar;
  917. 08921                         r = EP_SET;
  918. 08922                 }
  919. 08923         }
  920. 08924   }
  921. 08925 badenv:
  922. 08926   printf("Bad environment setting: '%s = %s'n", env, k_getenv(env));
  923. 08927   panic("", NO_NUM);
  924. 08928   /*NOTREACHED*/
  925. 08929 }
  926. 08931 #if DEBUG
  927. 08932 /*=========================================================================*
  928. 08933  *                              bad_assertion                              *
  929. 08934  *=========================================================================*/
  930. 08935 PUBLIC void bad_assertion(file, line, what)
  931. 08936 char *file;
  932. 08937 int line;
  933. 08938 char *what;
  934. 08939 {
  935. 08940   printf("panic at %s(%d): assertion "%s" failedn", file, line, what);
  936. 08941   panic(NULL, NO_NUM);
  937. 08942 }
  938. 08944 /*=========================================================================*
  939. 08945  *                              bad_compare                                *
  940. 08946  *=========================================================================*/
  941. 08947 PUBLIC void bad_compare(file, line, lhs, what, rhs)
  942. 08948 char *file;
  943. 08949 int line;
  944. 08950 int lhs;
  945. 08951 char *what;
  946. 08952 int rhs;
  947. 08953 {
  948. 08954   printf("panic at %s(%d): compare (%d) %s (%d) failedn",
  949. 08955         file, line, lhs, what, rhs);
  950. 08956   panic(NULL, NO_NUM);
  951. 08957 }
  952. 08958 #endif /* DEBUG */
  953. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  954. src/kernel/driver.h    
  955. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  956. 09000 /* Types and constants shared between the generic and device dependent
  957. 09001  * device driver code.
  958. 09002  */
  959. 09003
  960. 09004 #include <minix/callnr.h>
  961. 09005 #include <minix/com.h>
  962. 09006 #include "proc.h"
  963. 09007 #include <minix/partition.h>
  964. 09008
  965. 09009 /* Info about and entry points into the device dependent code. */
  966. 09010 struct driver {
  967. 09011   _PROTOTYPE( char *(*dr_name), (void) );
  968. 09012   _PROTOTYPE( int (*dr_open), (struct driver *dp, message *m_ptr) );
  969. 09013   _PROTOTYPE( int (*dr_close), (struct driver *dp, message *m_ptr) );
  970. 09014   _PROTOTYPE( int (*dr_ioctl), (struct driver *dp, message *m_ptr) );
  971. 09015   _PROTOTYPE( struct device *(*dr_prepare), (int device) );
  972. 09016   _PROTOTYPE( int (*dr_schedule), (int proc_nr, struct iorequest_s *request) );
  973. 09017   _PROTOTYPE( int (*dr_finish), (void) );
  974. 09018   _PROTOTYPE( void (*dr_cleanup), (void) );
  975. 09019   _PROTOTYPE( void (*dr_geometry), (struct partition *entry) );
  976. 09020 };
  977. 09021
  978. 09022 #if (CHIP == INTEL)
  979. 09023
  980. 09024 /* Number of bytes you can DMA before hitting a 64K boundary: */
  981. 09025 #define dma_bytes_left(phys)    
  982. 09026    ((unsigned) (sizeof(int) == 2 ? 0 : 0x10000) - (unsigned) ((phys) & 0xFFFF))
  983. 09027
  984. 09028 #endif /* CHIP == INTEL */
  985. 09029
  986. 09030 /* Base and size of a partition in bytes. */
  987. 09031 struct device {
  988. 09032   unsigned long dv_base;
  989. 09033   unsigned long dv_size;
  990. 09034 };
  991. 09035
  992. 09036 #define NIL_DEV         ((struct device *) 0)
  993. 09037
  994. 09038 /* Functions defined by driver.c: */
  995. 09039 _PROTOTYPE( void driver_task, (struct driver *dr) );
  996. 09040 _PROTOTYPE( int do_rdwt, (struct driver *dr, message *m_ptr) );
  997. 09041 _PROTOTYPE( int do_vrdwt, (struct driver *dr, message *m_ptr) );
  998. 09042 _PROTOTYPE( char *no_name, (void) );
  999. 09043 _PROTOTYPE( int do_nop, (struct driver *dp, message *m_ptr) );
  1000. 09044 _PROTOTYPE( int nop_finish, (void) );
  1001. 09045 _PROTOTYPE( void nop_cleanup, (void) );
  1002. 09046 _PROTOTYPE( void clock_mess, (int ticks, watchdog_t func) );
  1003. 09047 _PROTOTYPE( int do_diocntl, (struct driver *dr, message *m_ptr) );
  1004. 09048
  1005. 09049 /* Parameters for the disk drive. */
  1006. 09050 #define SECTOR_SIZE      512    /* physical sector size in bytes */
  1007. 09051 #define SECTOR_SHIFT       9    /* for division */
  1008. 09052 #define SECTOR_MASK      511    /* and remainder */
  1009. 09053
  1010. 09054 /* Size of the DMA buffer buffer in bytes. */
  1011. 09055 #define DMA_BUF_SIZE    (DMA_SECTORS * SECTOR_SIZE)
  1012. 09056
  1013. 09057 #if (CHIP == INTEL)
  1014. 09058 extern u8_t *tmp_buf;                   /* the DMA buffer */
  1015. 09059 #else
  1016. 09060 extern u8_t tmp_buf[];                  /* the DMA buffer */
  1017. 09061 #endif
  1018. 09062 extern phys_bytes tmp_phys;             /* phys address of DMA buffer */
  1019. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1020. src/kernel/driver.c    
  1021. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1022. 09100 /* This file contains device independent device driver interface.
  1023. 09101  *                                                      Author: Kees J. Bot.
  1024. 09102  *
  1025. 09103  * The drivers support the following operations (using message format m2):
  1026. 09104  *
  1027. 09105  *    m_type      DEVICE    PROC_NR     COUNT    POSITION  ADRRESS
  1028. 09106  * ----------------------------------------------------------------
  1029. 09107  * |  DEV_OPEN  | device  | proc nr |         |         |         |
  1030. 09108  * |------------+---------+---------+---------+---------+---------|
  1031. 09109  * |  DEV_CLOSE | device  | proc nr |         |         |         |
  1032. 09110  * |------------+---------+---------+---------+---------+---------|
  1033. 09111  * |  DEV_READ  | device  | proc nr |  bytes  |  offset | buf ptr |
  1034. 09112  * |------------+---------+---------+---------+---------+---------|
  1035. 09113  * |  DEV_WRITE | device  | proc nr |  bytes  |  offset | buf ptr |
  1036. 09114  * |------------+---------+---------+---------+---------+---------|
  1037. 09115  * |SCATTERED_IO| device  | proc nr | requests|         | iov ptr |
  1038. 09116  * ----------------------------------------------------------------
  1039. 09117  * |  DEV_IOCTL | device  | proc nr |func code|         | buf ptr |
  1040. 09118  * ----------------------------------------------------------------
  1041. 09119  *
  1042. 09120  * The file contains one entry point:
  1043. 09121  *
  1044. 09122  *   driver_task:       called by the device dependent task entry
  1045. 09123  *
  1046. 09124  *
  1047. 09125  * Constructed 92/04/02 by Kees J. Bot from the old AT wini and floppy driver.
  1048. 09126  */
  1049. 09127
  1050. 09128 #include "kernel.h"
  1051. 09129 #include <sys/ioctl.h>
  1052. 09130 #include "driver.h"
  1053. 09131
  1054. 09132 #define BUF_EXTRA       0
  1055. 09133
  1056. 09134 /* Claim space for variables. */
  1057. 09135 PRIVATE u8_t buffer[(unsigned) 2 * DMA_BUF_SIZE + BUF_EXTRA];
  1058. 09136 u8_t *tmp_buf;                  /* the DMA buffer eventually */
  1059. 09137 phys_bytes tmp_phys;            /* phys address of DMA buffer */
  1060. 09138
  1061. 09139 FORWARD _PROTOTYPE( void init_buffer, (void) );
  1062. 09140
  1063. 09141 /*===========================================================================*
  1064. 09142  *                              driver_task                                  *
  1065. 09143  *===========================================================================*/
  1066. 09144 PUBLIC void driver_task(dp)
  1067. 09145 struct driver *dp;      /* Device dependent entry points. */
  1068. 09146 {
  1069. 09147 /* Main program of any device driver task. */
  1070. 09148
  1071. 09149   int r, caller, proc_nr;
  1072. 09150   message mess;
  1073. 09151
  1074. 09152   init_buffer();        /* Get a DMA buffer. */
  1075. 09153
  1076. 09154   /* Here is the main loop of the disk task.  It waits for a message, carries
  1077. 09155    * it out, and sends a reply.
  1078. 09156    */
  1079. 09157
  1080. 09158   while (TRUE) {
  1081. 09159         /* First wait for a request to read or write a disk block. */
  1082. 09160         receive(ANY, &mess);
  1083. 09161
  1084. 09162         caller = mess.m_source;
  1085. 09163         proc_nr = mess.PROC_NR;
  1086. 09164
  1087. 09165         switch (caller) {
  1088. 09166         case HARDWARE:
  1089. 09167                 /* Leftover interrupt. */
  1090. 09168                 continue;
  1091. 09169         case FS_PROC_NR:
  1092. 09170                 /* The only legitimate caller. */
  1093. 09171                 break;
  1094. 09172         default:
  1095. 09173                 printf("%s: got message from %dn", (*dp->dr_name)(), caller);
  1096. 09174                 continue;
  1097. 09175         }
  1098. 09176
  1099. 09177         /* Now carry out the work. */
  1100. 09178         switch(mess.m_type) {
  1101. 09179             case DEV_OPEN:      r = (*dp->dr_open)(dp, &mess);  break;
  1102. 09180             case DEV_CLOSE:     r = (*dp->dr_close)(dp, &mess); break;
  1103. 09181             case DEV_IOCTL:     r = (*dp->dr_ioctl)(dp, &mess); break;
  1104. 09182
  1105. 09183             case DEV_READ:
  1106. 09184             case DEV_WRITE:     r = do_rdwt(dp, &mess);         break;
  1107. 09185
  1108. 09186             case SCATTERED_IO:  r = do_vrdwt(dp, &mess);        break;
  1109. 09187             default:            r = EINVAL;                     break;
  1110. 09188         }
  1111. 09189
  1112. 09190         /* Clean up leftover state. */
  1113. 09191         (*dp->dr_cleanup)();
  1114. 09192
  1115. 09193         /* Finally, prepare and send the reply message. */
  1116. 09194         mess.m_type = TASK_REPLY;
  1117. 09195         mess.REP_PROC_NR = proc_nr;
  1118. 09196
  1119. 09197         mess.REP_STATUS = r;    /* # of bytes transferred or error code */
  1120. 09198         send(caller, &mess);    /* send reply to caller */
  1121. 09199   }
  1122. 09200 }
  1123. 09202 /*===========================================================================*
  1124. 09203  *                              init_buffer                                  *
  1125. 09204  *===========================================================================*/
  1126. 09205 PRIVATE void init_buffer()
  1127. 09206 {
  1128. 09207 /* Select a buffer that can safely be used for dma transfers.  It may also
  1129. 09208  * be used to read partition tables and such.  Its absolute address is
  1130. 09209  * 'tmp_phys', the normal address is 'tmp_buf'.
  1131. 09210  */
  1132. 09211
  1133. 09212   tmp_buf = buffer;
  1134. 09213   tmp_phys = vir2phys(buffer);
  1135. 09214
  1136. 09215   if (tmp_phys == 0) panic("no DMA buffer", NO_NUM);
  1137. 09216
  1138. 09217   if (dma_bytes_left(tmp_phys) < DMA_BUF_SIZE) {
  1139. 09218         /* First half of buffer crosses a 64K boundary, can't DMA into that */
  1140. 09219         tmp_buf += DMA_BUF_SIZE;
  1141. 09220         tmp_phys += DMA_BUF_SIZE;
  1142. 09221   }
  1143. 09222 }
  1144. 09224 /*===========================================================================*
  1145. 09225  *                              do_rdwt                                      *
  1146. 09226  *===========================================================================*/
  1147. 09227 PUBLIC int do_rdwt(dp, m_ptr)
  1148. 09228 struct driver *dp;              /* device dependent entry points */
  1149. 09229 message *m_ptr;                 /* pointer to read or write message */
  1150. 09230 {
  1151. 09231 /* Carry out a single read or write request. */
  1152. 09232   struct iorequest_s ioreq;
  1153. 09233   int r;
  1154. 09234
  1155. 09235   if (m_ptr->COUNT <= 0) return(EINVAL);
  1156. 09236
  1157. 09237   if ((*dp->dr_prepare)(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
  1158. 09238
  1159. 09239   ioreq.io_request = m_ptr->m_type;
  1160. 09240   ioreq.io_buf = m_ptr->ADDRESS;
  1161. 09241   ioreq.io_position = m_ptr->POSITION;
  1162. 09242   ioreq.io_nbytes = m_ptr->COUNT;
  1163. 09243
  1164. 09244   r = (*dp->dr_schedule)(m_ptr->PROC_NR, &ioreq);
  1165. 09245
  1166. 09246   if (r == OK) (void) (*dp->dr_finish)();
  1167. 09247
  1168. 09248   r = ioreq.io_nbytes;
  1169. 09249   return(r < 0 ? r : m_ptr->COUNT - r);
  1170. 09250 }
  1171. 09252 /*==========================================================================*
  1172. 09253  *                              do_vrdwt                                    *
  1173. 09254  *==========================================================================*/
  1174. 09255 PUBLIC int do_vrdwt(dp, m_ptr)
  1175. 09256 struct driver *dp;      /* device dependent entry points */
  1176. 09257 message *m_ptr;         /* pointer to read or write message */
  1177. 09258 {
  1178. 09259 /* Fetch a vector of i/o requests.  Handle requests one at a time.  Return
  1179. 09260  * status in the vector.
  1180. 09261  */
  1181. 09262
  1182. 09263   struct iorequest_s *iop;
  1183. 09264   static struct iorequest_s iovec[NR_IOREQS];
  1184. 09265   phys_bytes iovec_phys;
  1185. 09266   unsigned nr_requests;
  1186. 09267   int request;
  1187. 09268   int r;
  1188. 09269   phys_bytes user_iovec_phys;
  1189. 09270
  1190. 09271   nr_requests = m_ptr->COUNT;
  1191. 09272
  1192. 09273   if (nr_requests > sizeof iovec / sizeof iovec[0])
  1193. 09274         panic("FS passed too big an I/O vector", nr_requests);
  1194. 09275
  1195. 09276   iovec_phys = vir2phys(iovec);
  1196. 09277   user_iovec_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS,
  1197. 09278                          (vir_bytes) (nr_requests * sizeof iovec[0]));
  1198. 09279
  1199. 09280   if (user_iovec_phys == 0)
  1200. 09281         panic("FS passed a bad I/O vector", (int) m_ptr->ADDRESS);
  1201. 09282
  1202. 09283   phys_copy(user_iovec_phys, iovec_phys,
  1203. 09284                             (phys_bytes) nr_requests * sizeof iovec[0]);
  1204. 09285
  1205. 09286   if ((*dp->dr_prepare)(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
  1206. 09287
  1207. 09288   for (request = 0, iop = iovec; request < nr_requests; request++, iop++) {
  1208. 09289         if ((r = (*dp->dr_schedule)(m_ptr->PROC_NR, iop)) != OK) break;
  1209. 09290   }
  1210. 09291
  1211. 09292   if (r == OK) (void) (*dp->dr_finish)();
  1212. 09293
  1213. 09294   phys_copy(iovec_phys, user_iovec_phys,
  1214. 09295                             (phys_bytes) nr_requests * sizeof iovec[0]);
  1215. 09296   return(OK);
  1216. 09297 }
  1217. 09299 /*===========================================================================*
  1218. 09300  *                              no_name                                      *
  1219. 09301  *===========================================================================*/
  1220. 09302 PUBLIC char *no_name()
  1221. 09303 {
  1222. 09304 /* If no specific name for the device. */
  1223. 09305
  1224. 09306   return(tasktab[proc_number(proc_ptr) + NR_TASKS].name);
  1225. 09307 }
  1226. 09309 /*============================================================================*
  1227. 09310  *                              do_nop                                        *
  1228. 09311  *============================================================================*/
  1229. 09312 PUBLIC int do_nop(dp, m_ptr)
  1230. 09313 struct driver *dp;
  1231. 09314 message *m_ptr;
  1232. 09315 {
  1233. 09316 /* Nothing there, or nothing to do. */
  1234. 09317
  1235. 09318   switch (m_ptr->m_type) {
  1236. 09319   case DEV_OPEN:        return(ENODEV);
  1237. 09320   case DEV_CLOSE:       return(OK);
  1238. 09321   case DEV_IOCTL:       return(ENOTTY);
  1239. 09322   default:              return(EIO);
  1240. 09323   }
  1241. 09324 }
  1242. 09326 /*===========================================================================*
  1243. 09327  *                              nop_finish                                   *
  1244. 09328  *===========================================================================*/
  1245. 09329 PUBLIC int nop_finish()
  1246. 09330 {
  1247. 09331 /* Nothing to finish, all the work has been done by dp->dr_schedule. */
  1248. 09332   return(OK);
  1249. 09333 }
  1250. 09335 /*===========================================================================*
  1251. 09336  *                              nop_cleanup                                  *
  1252. 09337  *===========================================================================*/
  1253. 09338 PUBLIC void nop_cleanup()
  1254. 09339 {
  1255. 09340 /* Nothing to clean up. */
  1256. 09341 }
  1257. 09343 /*===========================================================================*
  1258. 09344  *                              clock_mess                                   *
  1259. 09345  *===========================================================================*/
  1260. 09346 PUBLIC void clock_mess(ticks, func)
  1261. 09347 int ticks;                      /* how many clock ticks to wait */
  1262. 09348 watchdog_t func;                /* function to call upon time out */
  1263. 09349 {
  1264. 09350 /* Send the clock task a message. */
  1265. 09351
  1266. 09352   message mess;
  1267. 09353
  1268. 09354   mess.m_type = SET_ALARM;
  1269. 09355   mess.CLOCK_PROC_NR = proc_number(proc_ptr);
  1270. 09356   mess.DELTA_TICKS = (long) ticks;
  1271. 09357   mess.FUNC_TO_CALL = (sighandler_t) func;
  1272. 09358   sendrec(CLOCK, &mess);
  1273. 09359 }
  1274. 09361 /*============================================================================*
  1275. 09362  *                              do_diocntl                                    *
  1276. 09363  *============================================================================*/
  1277. 09364 PUBLIC int do_diocntl(dp, m_ptr)
  1278. 09365 struct driver *dp;
  1279. 09366 message *m_ptr;                 /* pointer to ioctl request */
  1280. 09367 {
  1281. 09368 /* Carry out a partition setting/getting request. */
  1282. 09369   struct device *dv;
  1283. 09370   phys_bytes user_phys, entry_phys;
  1284. 09371   struct partition entry;
  1285. 09372
  1286. 09373   if (m_ptr->REQUEST != DIOCSETP && m_ptr->REQUEST != DIOCGETP) return(ENOTTY);
  1287. 09374
  1288. 09375   /* Decode the message parameters. */
  1289. 09376   if ((dv = (*dp->dr_prepare)(m_ptr->DEVICE)) == NIL_DEV) return(ENXIO);
  1290. 09377
  1291. 09378   user_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS, sizeof(entry));
  1292. 09379   if (user_phys == 0) return(EFAULT);
  1293. 09380
  1294. 09381   entry_phys = vir2phys(&entry);
  1295. 09382
  1296. 09383   if (m_ptr->REQUEST == DIOCSETP) {
  1297. 09384         /* Copy just this one partition table entry. */
  1298. 09385         phys_copy(user_phys, entry_phys, (phys_bytes) sizeof(entry));
  1299. 09386         dv->dv_base = entry.base;
  1300. 09387         dv->dv_size = entry.size;
  1301. 09388   } else {
  1302. 09389         /* Return a partition table entry and the geometry of the drive. */
  1303. 09390         entry.base = dv->dv_base;
  1304. 09391         entry.size = dv->dv_size;
  1305. 09392         (*dp->dr_geometry)(&entry);
  1306. 09393         phys_copy(entry_phys, user_phys, (phys_bytes) sizeof(entry));
  1307. 09394   }
  1308. 09395   return(OK);
  1309. 09396 }
  1310. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1311. src/kernel/drvlib.h    
  1312. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1313. 09400 /* IBM device driver definitions                        Author: Kees J. Bot
  1314. 09401  *                                                              7 Dec 1995
  1315. 09402  */
  1316. 09403
  1317. 09404 #include <ibm/partition.h>
  1318. 09405
  1319. 09406 _PROTOTYPE( void partition, (struct driver *dr, int device, int style) );
  1320. 09407
  1321. 09408 /* BIOS parameter table layout. */
  1322. 09409 #define bp_cylinders(t)         (* (u16_t *) (&(t)[0]))
  1323. 09410 #define bp_heads(t)             (* (u8_t *)  (&(t)[2]))
  1324. 09411 #define bp_reduced_wr(t)        (* (u16_t *) (&(t)[3]))
  1325. 09412 #define bp_precomp(t)           (* (u16_t *) (&(t)[5]))
  1326. 09413 #define bp_max_ecc(t)           (* (u8_t *)  (&(t)[7]))
  1327. 09414 #define bp_ctlbyte(t)           (* (u8_t *)  (&(t)[8]))
  1328. 09415 #define bp_landingzone(t)       (* (u16_t *) (&(t)[12]))
  1329. 09416 #define bp_sectors(t)           (* (u8_t *)  (&(t)[14]))
  1330. 09417
  1331. 09418 /* Miscellaneous. */
  1332. 09419 #define DEV_PER_DRIVE   (1 + NR_PARTITIONS)
  1333. 09420 #define MINOR_hd1a      128
  1334. 09421 #define MINOR_fd0a      (28<<2)
  1335. 09422 #define P_FLOPPY        0
  1336. 09423 #define P_PRIMARY       1
  1337. 09424 #define P_SUB           2
  1338. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1339. src/kernel/drvlib.c    
  1340. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1341. 09500 /* IBM device driver utility functions.                 Author: Kees J. Bot
  1342. 09501  *                                                              7 Dec 1995
  1343. 09502  * Entry point:
  1344. 09503  *   partition: partition a disk to the partition table(s) on it.
  1345. 09504  */
  1346. 09505
  1347. 09506 #include "kernel.h"
  1348. 09507 #include "driver.h"
  1349. 09508 #include "drvlib.h"
  1350. 09509
  1351. 09510
  1352. 09511 FORWARD _PROTOTYPE( void extpartition, (struct driver *dp, int extdev,
  1353. 09512                                                 unsigned long extbase) );
  1354. 09513 FORWARD _PROTOTYPE( int get_part_table, (struct driver *dp, int device,
  1355. 09514                         unsigned long offset, struct part_entry *table) );
  1356. 09515 FORWARD _PROTOTYPE( void sort, (struct part_entry *table) );
  1357. 09516
  1358. 09517
  1359. 09518 /*============================================================================*
  1360. 09519  *                              partition                                     *
  1361. 09520  *============================================================================*/
  1362. 09521 PUBLIC void partition(dp, device, style)
  1363. 09522 struct driver *dp;      /* device dependent entry points */
  1364. 09523 int device;             /* device to partition */
  1365. 09524 int style;              /* partitioning style: floppy, primary, sub. */
  1366. 09525 {
  1367. 09526 /* This routine is called on first open to initialize the partition tables
  1368. 09527  * of a device.  It makes sure that each partition falls safely within the
  1369. 09528  * device's limits.  Depending on the partition style we are either making
  1370. 09529  * floppy partitions, primary partitions or subpartitions.  Only primary
  1371. 09530  * partitions are sorted, because they are shared with other operating
  1372. 09531  * systems that expect this.
  1373. 09532  */
  1374. 09533   struct part_entry table[NR_PARTITIONS], *pe;
  1375. 09534   int disk, par;
  1376. 09535   struct device *dv;
  1377. 09536   unsigned long base, limit, part_limit;
  1378. 09537
  1379. 09538   /* Get the geometry of the device to partition */
  1380. 09539   if ((dv = (*dp->dr_prepare)(device)) == NIL_DEV || dv->dv_size == 0) return;
  1381. 09540   base = dv->dv_base >> SECTOR_SHIFT;
  1382. 09541   limit = base + (dv->dv_size >> SECTOR_SHIFT);
  1383. 09542
  1384. 09543   /* Read the partition table for the device. */
  1385. 09544   if (!get_part_table(dp, device, 0L, table)) return;
  1386. 09545
  1387. 09546   /* Compute the device number of the first partition. */
  1388. 09547   switch (style) {
  1389. 09548   case P_FLOPPY:
  1390. 09549         device += MINOR_fd0a;
  1391. 09550         break;
  1392. 09551   case P_PRIMARY:
  1393. 09552         sort(table);            /* sort a primary partition table */
  1394. 09553         device += 1;
  1395. 09554         break;
  1396. 09555   case P_SUB:
  1397. 09556         disk = device / DEV_PER_DRIVE;
  1398. 09557         par = device % DEV_PER_DRIVE - 1;
  1399. 09558         device = MINOR_hd1a + (disk * NR_PARTITIONS + par) * NR_PARTITIONS;
  1400. 09559   }
  1401. 09560
  1402. 09561   /* Find an array of devices. */
  1403. 09562   if ((dv = (*dp->dr_prepare)(device)) == NIL_DEV) return;
  1404. 09563
  1405. 09564   /* Set the geometry of the partitions from the partition table. */
  1406. 09565   for (par = 0; par < NR_PARTITIONS; par++, dv++) {
  1407. 09566         /* Shrink the partition to fit within the device. */
  1408. 09567         pe = &table[par];
  1409. 09568         part_limit = pe->lowsec + pe->size;
  1410. 09569         if (part_limit < pe->lowsec) part_limit = limit;
  1411. 09570         if (part_limit > limit) part_limit = limit;
  1412. 09571         if (pe->lowsec < base) pe->lowsec = base;
  1413. 09572         if (part_limit < pe->lowsec) part_limit = pe->lowsec;
  1414. 09573
  1415. 09574         dv->dv_base = pe->lowsec << SECTOR_SHIFT;
  1416. 09575         dv->dv_size = (part_limit - pe->lowsec) << SECTOR_SHIFT;
  1417. 09576
  1418. 09577         if (style == P_PRIMARY) {
  1419. 09578                 /* Each Minix primary partition can be subpartitioned. */
  1420. 09579                 if (pe->sysind == MINIX_PART)
  1421. 09580                         partition(dp, device + par, P_SUB);
  1422. 09581
  1423. 09582                 /* An extended partition has logical partitions. */
  1424. 09583                 if (pe->sysind == EXT_PART)
  1425. 09584                         extpartition(dp, device + par, pe->lowsec);
  1426. 09585         }
  1427. 09586   }
  1428. 09587 }
  1429. 09590 /*============================================================================*
  1430. 09591  *                              extpartition                                  *
  1431. 09592  *============================================================================*/
  1432. 09593 PRIVATE void extpartition(dp, extdev, extbase)
  1433. 09594 struct driver *dp;      /* device dependent entry points */
  1434. 09595 int extdev;             /* extended partition to scan */
  1435. 09596 unsigned long extbase;  /* sector offset of the base extended partition */
  1436. 09597 {
  1437. 09598 /* Extended partitions cannot be ignored alas, because people like to move
  1438. 09599  * files to and from DOS partitions.  Avoid reading this code, it's no fun.
  1439. 09600  */
  1440. 09601   struct part_entry table[NR_PARTITIONS], *pe;
  1441. 09602   int subdev, disk, par;
  1442. 09603   struct device *dv;
  1443. 09604   unsigned long offset, nextoffset;
  1444. 09605
  1445. 09606   disk = extdev / DEV_PER_DRIVE;
  1446. 09607   par = extdev % DEV_PER_DRIVE - 1;
  1447. 09608   subdev = MINOR_hd1a + (disk * NR_PARTITIONS + par) * NR_PARTITIONS;
  1448. 09609
  1449. 09610   offset = 0;
  1450. 09611   do {
  1451. 09612         if (!get_part_table(dp, extdev, offset, table)) return;
  1452. 09613         sort(table);
  1453. 09614
  1454. 09615         /* The table should contain one logical partition and optionally
  1455. 09616          * another extended partition.  (It's a linked list.)
  1456. 09617          */
  1457. 09618         nextoffset = 0;
  1458. 09619         for (par = 0; par < NR_PARTITIONS; par++) {
  1459. 09620                 pe = &table[par];
  1460. 09621                 if (pe->sysind == EXT_PART) {
  1461. 09622                         nextoffset = pe->lowsec;
  1462. 09623                 } else
  1463. 09624                 if (pe->sysind != NO_PART) {
  1464. 09625                         if ((dv = (*dp->dr_prepare)(subdev)) == NIL_DEV) return;
  1465. 09626
  1466. 09627                         dv->dv_base = (extbase + offset
  1467. 09628                                         + pe->lowsec) << SECTOR_SHIFT;
  1468. 09629                         dv->dv_size = pe->size << SECTOR_SHIFT;
  1469. 09630
  1470. 09631                         /* Out of devices? */
  1471. 09632                         if (++subdev % NR_PARTITIONS == 0) return;
  1472. 09633                 }
  1473. 09634         }
  1474. 09635   } while ((offset = nextoffset) != 0);
  1475. 09636 }
  1476. 09639 /*============================================================================*
  1477. 09640  *                              get_part_table                                *
  1478. 09641  *============================================================================*/
  1479. 09642 PRIVATE int get_part_table(dp, device, offset, table)
  1480. 09643 struct driver *dp;
  1481. 09644 int device;
  1482. 09645 unsigned long offset;           /* sector offset to the table */
  1483. 09646 struct part_entry *table;       /* four entries */
  1484. 09647 {
  1485. 09648 /* Read the partition table for the device, return true iff there were no
  1486. 09649  * errors.
  1487. 09650  */
  1488. 09651   message mess;
  1489. 09652
  1490. 09653   mess.DEVICE = device;
  1491. 09654   mess.POSITION = offset << SECTOR_SHIFT;
  1492. 09655   mess.COUNT = SECTOR_SIZE;
  1493. 09656   mess.ADDRESS = (char *) tmp_buf;
  1494. 09657   mess.PROC_NR = proc_number(proc_ptr);
  1495. 09658   mess.m_type = DEV_READ;
  1496. 09659
  1497. 09660   if (do_rdwt(dp, &mess) != SECTOR_SIZE) {
  1498. 09661         printf("%s: can't read partition tablen", (*dp->dr_name)());
  1499. 09662         return 0;
  1500. 09663   }
  1501. 09664   if (tmp_buf[510] != 0x55 || tmp_buf[511] != 0xAA) {
  1502. 09665         /* Invalid partition table. */
  1503. 09666         return 0;
  1504. 09667   }
  1505. 09668   memcpy(table, (tmp_buf + PART_TABLE_OFF), NR_PARTITIONS * sizeof(table[0]));
  1506. 09669   return 1;
  1507. 09670 }
  1508. 09673 /*===========================================================================*
  1509. 09674  *                              sort                                         *
  1510. 09675  *===========================================================================*/
  1511. 09676 PRIVATE void sort(table)
  1512. 09677 struct part_entry *table;
  1513. 09678 {
  1514. 09679 /* Sort a partition table. */
  1515. 09680   struct part_entry *pe, tmp;
  1516. 09681   int n = NR_PARTITIONS;
  1517. 09682
  1518. 09683   do {
  1519. 09684         for (pe = table; pe < table + NR_PARTITIONS-1; pe++) {
  1520. 09685                 if (pe[0].sysind == NO_PART
  1521. 09686                         || (pe[0].lowsec > pe[1].lowsec
  1522. 09687                                         && pe[1].sysind != NO_PART)) {
  1523. 09688                         tmp = pe[0]; pe[0] = pe[1]; pe[1] = tmp;
  1524. 09689                 }
  1525. 09690         }
  1526. 09691   } while (--n > 0);
  1527. 09692 }
  1528. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1529. src/kernel/memory.c    
  1530. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1531. 09700 /* This file contains the device dependent part of the drivers for the
  1532. 09701  * following special files:
  1533. 09702  *     /dev/null        - null device (data sink)
  1534. 09703  *     /dev/mem         - absolute memory
  1535. 09704  *     /dev/kmem        - kernel virtual memory
  1536. 09705  *     /dev/ram         - RAM disk
  1537. 09706  *
  1538. 09707  * The file contains one entry point:
  1539. 09708  *
  1540. 09709  *   mem_task:  main entry when system is brought up
  1541. 09710  *
  1542. 09711  *  Changes:
  1543. 09712  *      20 Apr  1992 by Kees J. Bot: device dependent/independent split
  1544. 09713  */
  1545. 09714
  1546. 09715 #include "kernel.h"
  1547. 09716 #include "driver.h"
  1548. 09717 #include <sys/ioctl.h>
  1549. 09718
  1550. 09719 #define NR_RAMS            4    /* number of RAM-type devices */
  1551. 09720
  1552. 09721 PRIVATE struct device m_geom[NR_RAMS];  /* Base and size of each RAM disk */
  1553. 09722 PRIVATE int m_device;           /* current device */
  1554. 09723
  1555. 09724 FORWARD _PROTOTYPE( struct device *m_prepare, (int device) );
  1556. 09725 FORWARD _PROTOTYPE( int m_schedule, (int proc_nr, struct iorequest_s *iop) );
  1557. 09726 FORWARD _PROTOTYPE( int m_do_open, (struct driver *dp, message *m_ptr) );
  1558. 09727 FORWARD _PROTOTYPE( void m_init, (void) );
  1559. 09728 FORWARD _PROTOTYPE( int m_ioctl, (struct driver *dp, message *m_ptr) );
  1560. 09729 FORWARD _PROTOTYPE( void m_geometry, (struct partition *entry) );
  1561. 09730
  1562. 09731
  1563. 09732 /* Entry points to this driver. */
  1564. 09733 PRIVATE struct driver m_dtab = {
  1565. 09734   no_name,      /* current device's name */
  1566. 09735   m_do_open,    /* open or mount */
  1567. 09736   do_nop,       /* nothing on a close */
  1568. 09737   m_ioctl,      /* specify ram disk geometry */
  1569. 09738   m_prepare,    /* prepare for I/O on a given minor device */
  1570. 09739   m_schedule,   /* do the I/O */
  1571. 09740   nop_finish,   /* schedule does the work, no need to be smart */
  1572. 09741   nop_cleanup,  /* nothing's dirty */
  1573. 09742   m_geometry,   /* memory device "geometry" */
  1574. 09743 };
  1575. 09744
  1576. 09745
  1577. 09746 /*===========================================================================*
  1578. 09747  *                              mem_task                                     *
  1579. 09748  *===========================================================================*/
  1580. 09749 PUBLIC void mem_task()
  1581. 09750 {
  1582. 09751   m_init();
  1583. 09752   driver_task(&m_dtab);
  1584. 09753 }
  1585. 09756 /*===========================================================================*
  1586. 09757  *                              m_prepare                                    *
  1587. 09758  *===========================================================================*/
  1588. 09759 PRIVATE struct device *m_prepare(device)
  1589. 09760 int device;
  1590. 09761 {
  1591. 09762 /* Prepare for I/O on a device. */
  1592. 09763
  1593. 09764   if (device < 0 || device >= NR_RAMS) return(NIL_DEV);
  1594. 09765   m_device = device;
  1595. 09766
  1596. 09767   return(&m_geom[device]);
  1597. 09768 }
  1598. 09771 /*===========================================================================*
  1599. 09772  *                              m_schedule                                   *
  1600. 09773  *===========================================================================*/
  1601. 09774 PRIVATE int m_schedule(proc_nr, iop)
  1602. 09775 int proc_nr;                    /* process doing the request */
  1603. 09776 struct iorequest_s *iop;        /* pointer to read or write request */
  1604. 09777 {
  1605. 09778 /* Read or write /dev/null, /dev/mem, /dev/kmem, or /dev/ram. */
  1606. 09779
  1607. 09780   int device, count, opcode;
  1608. 09781   phys_bytes mem_phys, user_phys;
  1609. 09782   struct device *dv;
  1610. 09783
  1611. 09784   /* Type of request */
  1612. 09785   opcode = iop->io_request & ~OPTIONAL_IO;
  1613. 09786
  1614. 09787   /* Get minor device number and check for /dev/null. */
  1615. 09788   device = m_device;
  1616. 09789   dv = &m_geom[device];
  1617. 09790
  1618. 09791   /* Determine address where data is to go or to come from. */
  1619. 09792   user_phys = numap(proc_nr, (vir_bytes) iop->io_buf,
  1620. 09793                                                 (vir_bytes) iop->io_nbytes);
  1621. 09794   if (user_phys == 0) return(iop->io_nbytes = EINVAL);
  1622. 09795
  1623. 09796   if (device == NULL_DEV) {
  1624. 09797         /* /dev/null: Black hole. */
  1625. 09798         if (opcode == DEV_WRITE) iop->io_nbytes = 0;
  1626. 09799         count = 0;
  1627. 09800   } else {
  1628. 09801         /* /dev/mem, /dev/kmem, or /dev/ram: Check for EOF */
  1629. 09802         if (iop->io_position >= dv->dv_size) return(OK);
  1630. 09803         count = iop->io_nbytes;
  1631. 09804         if (iop->io_position + count > dv->dv_size)
  1632. 09805                 count = dv->dv_size - iop->io_position;
  1633. 09806   }
  1634. 09807
  1635. 09808   /* Set up 'mem_phys' for /dev/mem, /dev/kmem, or /dev/ram */
  1636. 09809   mem_phys = dv->dv_base + iop->io_position;
  1637. 09810
  1638. 09811   /* Book the number of bytes to be transferred in advance. */
  1639. 09812   iop->io_nbytes -= count;
  1640. 09813
  1641. 09814   if (count == 0) return(OK);
  1642. 09815
  1643. 09816   /* Copy the data. */
  1644. 09817   if (opcode == DEV_READ)
  1645. 09818         phys_copy(mem_phys, user_phys, (phys_bytes) count);
  1646. 09819   else
  1647. 09820         phys_copy(user_phys, mem_phys, (phys_bytes) count);
  1648. 09821
  1649. 09822   return(OK);
  1650. 09823 }
  1651. 09826 /*============================================================================*
  1652. 09827  *                              m_do_open                                     *
  1653. 09828  *============================================================================*/
  1654. 09829 PRIVATE int m_do_open(dp, m_ptr)
  1655. 09830 struct driver *dp;
  1656. 09831 message *m_ptr;
  1657. 09832 {
  1658. 09833 /* Check device number on open.  Give I/O privileges to a process opening
  1659. 09834  * /dev/mem or /dev/kmem.
  1660. 09835  */
  1661. 09836
  1662. 09837   if (m_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
  1663. 09838
  1664. 09839   if (m_device == MEM_DEV || m_device == KMEM_DEV)
  1665. 09840         enable_iop(proc_addr(m_ptr->PROC_NR));
  1666. 09841
  1667. 09842   return(OK);
  1668. 09843 }
  1669. 09846 /*===========================================================================*
  1670. 09847  *                              m_init                                       *
  1671. 09848  *===========================================================================*/
  1672. 09849 PRIVATE void m_init()
  1673. 09850 {
  1674. 09851   /* Initialize this task. */
  1675. 09852   extern int _end;
  1676. 09853
  1677. 09854   m_geom[KMEM_DEV].dv_base = vir2phys(0);
  1678. 09855   m_geom[KMEM_DEV].dv_size = vir2phys(&_end);
  1679. 09856
  1680. 09857 #if (CHIP == INTEL)
  1681. 09858   if (!protected_mode) {
  1682. 09859         m_geom[MEM_DEV].dv_size =   0x100000;   /* 1M for 8086 systems */
  1683. 09860   } else {
  1684. 09861 #if _WORD_SIZE == 2
  1685. 09862         m_geom[MEM_DEV].dv_size =  0x1000000;   /* 16M for 286 systems */
  1686. 09863 #else
  1687. 09864         m_geom[MEM_DEV].dv_size = 0xFFFFFFFF;   /* 4G-1 for 386 systems */
  1688. 09865 #endif
  1689. 09866   }
  1690. 09867 #endif
  1691. 09868 }
  1692. 09871 /*===========================================================================*
  1693. 09872  *                              m_ioctl                                      *
  1694. 09873  *===========================================================================*/
  1695. 09874 PRIVATE int m_ioctl(dp, m_ptr)
  1696. 09875 struct driver *dp;
  1697. 09876 message *m_ptr;                 /* pointer to read or write message */
  1698. 09877 {
  1699. 09878 /* Set parameters for one of the RAM disks. */
  1700. 09879
  1701. 09880   unsigned long bytesize;
  1702. 09881   unsigned base, size;
  1703. 09882   struct memory *memp;
  1704. 09883   static struct psinfo psinfo = { NR_TASKS, NR_PROCS, (vir_bytes) proc, 0, 0 };
  1705. 09884   phys_bytes psinfo_phys;
  1706. 09885
  1707. 09886   switch (m_ptr->REQUEST) {
  1708. 09887   case MIOCRAMSIZE:
  1709. 09888         /* FS sets the RAM disk size. */
  1710. 09889         if (m_ptr->PROC_NR != FS_PROC_NR) return(EPERM);
  1711. 09890
  1712. 09891         bytesize = m_ptr->POSITION * BLOCK_SIZE;
  1713. 09892         size = (bytesize + CLICK_SHIFT-1) >> CLICK_SHIFT;
  1714. 09893
  1715. 09894         /* Find a memory chunk big enough for the RAM disk. */
  1716. 09895         memp= &mem[NR_MEMS];
  1717. 09896         while ((--memp)->size < size) {
  1718. 09897                 if (memp == mem) panic("RAM disk is too big", NO_NUM);
  1719. 09898         }
  1720. 09899         base = memp->base;
  1721. 09900         memp->base += size;
  1722. 09901         memp->size -= size;
  1723. 09902
  1724. 09903         m_geom[RAM_DEV].dv_base = (unsigned long) base << CLICK_SHIFT;
  1725. 09904         m_geom[RAM_DEV].dv_size = bytesize;
  1726. 09905         break;
  1727. 09906   case MIOCSPSINFO:
  1728. 09907         /* MM or FS set the address of their process table. */
  1729. 09908         if (m_ptr->PROC_NR == MM_PROC_NR) {
  1730. 09909                 psinfo.mproc = (vir_bytes) m_ptr->ADDRESS;
  1731. 09910         } else
  1732. 09911         if (m_ptr->PROC_NR == FS_PROC_NR) {
  1733. 09912                 psinfo.fproc = (vir_bytes) m_ptr->ADDRESS;
  1734. 09913         } else {
  1735. 09914                 return(EPERM);
  1736. 09915         }
  1737. 09916         break;
  1738. 09917   case MIOCGPSINFO:
  1739. 09918         /* The ps program wants the process table addresses. */
  1740. 09919         psinfo_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS,
  1741. 09920                                                         sizeof(psinfo));
  1742. 09921         if (psinfo_phys == 0) return(EFAULT);
  1743. 09922         phys_copy(vir2phys(&psinfo), psinfo_phys, (phys_bytes) sizeof(psinfo));
  1744. 09923         break;
  1745. 09924   default:
  1746. 09925         return(do_diocntl(&m_dtab, m_ptr));
  1747. 09926   }
  1748. 09927   return(OK);
  1749. 09928 }
  1750. 09931 /*============================================================================*
  1751. 09932  *                              m_geometry                                    *
  1752. 09933  *============================================================================*/
  1753. 09934 PRIVATE void m_geometry(entry)
  1754. 09935 struct partition *entry;
  1755. 09936 {
  1756. 09937   /* Memory devices don't have a geometry, but the outside world insists. */
  1757. 09938   entry->cylinders = (m_geom[m_device].dv_size >> SECTOR_SHIFT) / (64 * 32);
  1758. 09939   entry->heads = 64;
  1759. 09940   entry->sectors = 32;
  1760. 09941 }
  1761. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1762. src/kernel/wini.c    
  1763. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1764. 10000 /*      wini.c - choose a winchester driver.            Author: Kees J. Bot
  1765. 10001  *                                                              28 May 1994
  1766. 10002  * Several different winchester drivers may be compiled
  1767. 10003  * into the kernel, but only one may run.  That one is chosen here using
  1768. 10004  * the boot variable 'hd'.
  1769. 10005  */
  1770. 10006
  1771. 10007 #include "kernel.h"
  1772. 10008 #include "driver.h"
  1773. 10009
  1774. 10010 #if ENABLE_WINI
  1775. 10011
  1776. 10012 /* Map driver name to task function. */
  1777. 10013 struct hdmap {
  1778. 10014   char          *name;
  1779. 10015   task_t        *task;
  1780. 10016 } hdmap[] = {
  1781. 10017
  1782. 10018 #if ENABLE_AT_WINI
  1783. 10019   { "at",       at_winchester_task      },
  1784. 10020 #endif
  1785. 10021
  1786. 10022 #if ENABLE_BIOS_WINI
  1787. 10023   { "bios",     bios_winchester_task    },
  1788. 10024 #endif
  1789. 10025
  1790. 10026 #if ENABLE_ESDI_WINI
  1791. 10027   { "esdi",     esdi_winchester_task    },
  1792. 10028 #endif
  1793. 10029
  1794. 10030 #if ENABLE_XT_WINI
  1795. 10031   { "xt",       xt_winchester_task      },
  1796. 10032 #endif
  1797. 10033
  1798. 10034 };
  1799. 10035
  1800. 10036
  1801. 10037 /*===========================================================================*
  1802. 10038  *                              winchester_task                              *
  1803. 10039  *===========================================================================*/
  1804. 10040 PUBLIC void winchester_task()
  1805. 10041 {
  1806. 10042   /* Call the default or selected winchester task. */
  1807. 10043   char *hd;
  1808. 10044   struct hdmap *map;
  1809. 10045
  1810. 10046   hd = k_getenv("hd");
  1811. 10047
  1812. 10048   for (map = hdmap; map < hdmap + sizeof(hdmap)/sizeof(hdmap[0]); map++) {
  1813. 10049         if (hd == NULL || strcmp(hd, map->name) == 0) {
  1814. 10050                 /* Run the selected winchester task. */
  1815. 10051                 (*map->task)();
  1816. 10052         }
  1817. 10053   }
  1818. 10054   panic("no hd driver", NO_NUM);
  1819. 10055 }
  1820. 10056 #endif /* ENABLE_WINI */
  1821. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1822. src/kernel/at_wini.c    
  1823. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1824. 10100 /* This file contains the device dependent part of a driver for the IBM-AT
  1825. 10101  * winchester controller.
  1826. 10102  * It was written by Adri Koppes.
  1827. 10103  *
  1828. 10104  * The file contains one entry point:
  1829. 10105  *
  1830. 10106  *   at_winchester_task:        main entry when system is brought up
  1831. 10107  *
  1832. 10108  *
  1833. 10109  * Changes:
  1834. 10110  *      13 Apr 1992 by Kees J. Bot: device dependent/independent split.
  1835. 10111  */
  1836. 10112
  1837. 10113 #include "kernel.h"
  1838. 10114 #include "driver.h"
  1839. 10115 #include "drvlib.h"
  1840. 10116
  1841. 10117 #if ENABLE_AT_WINI
  1842. 10118
  1843. 10119 /* I/O Ports used by winchester disk controllers. */
  1844. 10120
  1845. 10121 /* Read and write registers */
  1846. 10122 #define REG_BASE0       0x1F0   /* base register of controller 0 */
  1847. 10123 #define REG_BASE1       0x170   /* base register of controller 1 */
  1848. 10124 #define REG_DATA            0   /* data register (offset from the base reg.) */
  1849. 10125 #define REG_PRECOMP         1   /* start of write precompensation */
  1850. 10126 #define REG_COUNT           2   /* sectors to transfer */
  1851. 10127 #define REG_SECTOR          3   /* sector number */
  1852. 10128 #define REG_CYL_LO          4   /* low byte of cylinder number */
  1853. 10129 #define REG_CYL_HI          5   /* high byte of cylinder number */
  1854. 10130 #define REG_LDH             6   /* lba, drive and head */
  1855. 10131 #define   LDH_DEFAULT           0xA0    /* ECC enable, 512 bytes per sector */
  1856. 10132 #define   LDH_LBA               0x40    /* Use LBA addressing */
  1857. 10133 #define   ldh_init(drive)       (LDH_DEFAULT | ((drive) << 4))
  1858. 10134
  1859. 10135 /* Read only registers */
  1860. 10136 #define REG_STATUS          7   /* status */
  1861. 10137 #define   STATUS_BSY            0x80    /* controller busy */
  1862. 10138 #define   STATUS_RDY            0x40    /* drive ready */
  1863. 10139 #define   STATUS_WF             0x20    /* write fault */
  1864. 10140 #define   STATUS_SC             0x10    /* seek complete (obsolete) */
  1865. 10141 #define   STATUS_DRQ            0x08    /* data transfer request */
  1866. 10142 #define   STATUS_CRD            0x04    /* corrected data */
  1867. 10143 #define   STATUS_IDX            0x02    /* index pulse */
  1868. 10144 #define   STATUS_ERR            0x01    /* error */
  1869. 10145 #define REG_ERROR           1   /* error code */
  1870. 10146 #define   ERROR_BB              0x80    /* bad block */
  1871. 10147 #define   ERROR_ECC             0x40    /* bad ecc bytes */
  1872. 10148 #define   ERROR_ID              0x10    /* id not found */
  1873. 10149 #define   ERROR_AC              0x04    /* aborted command */
  1874. 10150 #define   ERROR_TK              0x02    /* track zero error */
  1875. 10151 #define   ERROR_DM              0x01    /* no data address mark */
  1876. 10152
  1877. 10153 /* Write only registers */
  1878. 10154 #define REG_COMMAND         7   /* command */
  1879. 10155 #define   CMD_IDLE              0x00    /* for w_command: drive idle */
  1880. 10156 #define   CMD_RECALIBRATE       0x10    /* recalibrate drive */
  1881. 10157 #define   CMD_READ              0x20    /* read data */
  1882. 10158 #define   CMD_WRITE             0x30    /* write data */
  1883. 10159 #define   CMD_READVERIFY        0x40    /* read verify */
  1884. 10160 #define   CMD_FORMAT            0x50    /* format track */
  1885. 10161 #define   CMD_SEEK              0x70    /* seek cylinder */
  1886. 10162 #define   CMD_DIAG              0x90    /* execute device diagnostics */
  1887. 10163 #define   CMD_SPECIFY           0x91    /* specify parameters */
  1888. 10164 #define   ATA_IDENTIFY          0xEC    /* identify drive */
  1889. 10165 #define REG_CTL         0x206   /* control register */
  1890. 10166 #define   CTL_NORETRY           0x80    /* disable access retry */
  1891. 10167 #define   CTL_NOECC             0x40    /* disable ecc retry */
  1892. 10168 #define   CTL_EIGHTHEADS        0x08    /* more than eight heads */
  1893. 10169 #define   CTL_RESET             0x04    /* reset controller */
  1894. 10170 #define   CTL_INTDISABLE        0x02    /* disable interrupts */
  1895. 10171
  1896. 10172 /* Interrupt request lines. */
  1897. 10173 #define AT_IRQ0         14      /* interrupt number for controller 0 */
  1898. 10174 #define AT_IRQ1         15      /* interrupt number for controller 1 */
  1899. 10175
  1900. 10176 /* Common command block */
  1901. 10177 struct command {
  1902. 10178   u8_t  precomp;        /* REG_PRECOMP, etc. */
  1903. 10179   u8_t  count;
  1904. 10180   u8_t  sector;
  1905. 10181   u8_t  cyl_lo;
  1906. 10182   u8_t  cyl_hi;
  1907. 10183   u8_t  ldh;
  1908. 10184   u8_t  command;
  1909. 10185 };
  1910. 10186
  1911. 10187
  1912. 10188 /* Error codes */
  1913. 10189 #define ERR              (-1)   /* general error */
  1914. 10190 #define ERR_BAD_SECTOR   (-2)   /* block marked bad detected */
  1915. 10191
  1916. 10192 /* Some controllers don't interrupt, the clock will wake us up. */
  1917. 10193 #define WAKEUP          (32*HZ) /* drive may be out for 31 seconds max */
  1918. 10194
  1919. 10195 /* Miscellaneous. */
  1920. 10196 #define MAX_DRIVES         4    /* this driver supports 4 drives (hd0 - hd19) */
  1921. 10197 #if _WORD_SIZE > 2
  1922. 10198 #define MAX_SECS         256    /* controller can transfer this many sectors */
  1923. 10199 #else
  1924. 10200 #define MAX_SECS         127    /* but not to a 16 bit process */
  1925. 10201 #endif
  1926. 10202 #define MAX_ERRORS         4    /* how often to try rd/wt before quitting */
  1927. 10203 #define NR_DEVICES      (MAX_DRIVES * DEV_PER_DRIVE)
  1928. 10204 #define SUB_PER_DRIVE   (NR_PARTITIONS * NR_PARTITIONS)
  1929. 10205 #define NR_SUBDEVS      (MAX_DRIVES * SUB_PER_DRIVE)
  1930. 10206 #define TIMEOUT        32000    /* controller timeout in ms */
  1931. 10207 #define RECOVERYTIME     500    /* controller recovery time in ms */
  1932. 10208 #define INITIALIZED     0x01    /* drive is initialized */
  1933. 10209 #define DEAF            0x02    /* controller must be reset */
  1934. 10210 #define SMART           0x04    /* drive supports ATA commands */
  1935. 10211
  1936. 10212
  1937. 10213 /* Variables. */
  1938. 10214 PRIVATE struct wini {           /* main drive struct, one entry per drive */
  1939. 10215   unsigned state;               /* drive state: deaf, initialized, dead */
  1940. 10216   unsigned base;                /* base register of the register file */
  1941. 10217   unsigned irq;                 /* interrupt request line */
  1942. 10218   unsigned lcylinders;          /* logical number of cylinders (BIOS) */
  1943. 10219   unsigned lheads;              /* logical number of heads */
  1944. 10220   unsigned lsectors;            /* logical number of sectors per track */
  1945. 10221   unsigned pcylinders;          /* physical number of cylinders (translated) */
  1946. 10222   unsigned pheads;              /* physical number of heads */
  1947. 10223   unsigned psectors;            /* physical number of sectors per track */
  1948. 10224   unsigned ldhpref;             /* top four bytes of the LDH (head) register */
  1949. 10225   unsigned precomp;             /* write precompensation cylinder / 4 */
  1950. 10226   unsigned max_count;           /* max request for this drive */
  1951. 10227   unsigned open_ct;             /* in-use count */
  1952. 10228   struct device part[DEV_PER_DRIVE];    /* primary partitions: hd[0-4] */
  1953. 10229   struct device subpart[SUB_PER_DRIVE]; /* subpartitions: hd[1-4][a-d] */
  1954. 10230 } wini[MAX_DRIVES], *w_wn;
  1955. 10231
  1956. 10232 PRIVATE struct trans {
  1957. 10233   struct iorequest_s *iop;      /* belongs to this I/O request */
  1958. 10234   unsigned long block;          /* first sector to transfer */
  1959. 10235   unsigned count;               /* byte count */
  1960. 10236   phys_bytes phys;              /* user physical address */
  1961. 10237 } wtrans[NR_IOREQS];
  1962. 10238
  1963. 10239 PRIVATE struct trans *w_tp;             /* to add transfer requests */
  1964. 10240 PRIVATE unsigned w_count;               /* number of bytes to transfer */
  1965. 10241 PRIVATE unsigned long w_nextblock;      /* next block on disk to transfer */
  1966. 10242 PRIVATE int w_opcode;                   /* DEV_READ or DEV_WRITE */
  1967. 10243 PRIVATE int w_command;                  /* current command in execution */
  1968. 10244 PRIVATE int w_status;                   /* status after interrupt */
  1969. 10245 PRIVATE int w_drive;                    /* selected drive */
  1970. 10246 PRIVATE struct device *w_dv;            /* device's base and size */
  1971. 10247
  1972. 10248 FORWARD _PROTOTYPE( void init_params, (void) );
  1973. 10249 FORWARD _PROTOTYPE( int w_do_open, (struct driver *dp, message *m_ptr) );
  1974. 10250 FORWARD _PROTOTYPE( struct device *w_prepare, (int device) );
  1975. 10251 FORWARD _PROTOTYPE( int w_identify, (void) );
  1976. 10252 FORWARD _PROTOTYPE( char *w_name, (void) );
  1977. 10253 FORWARD _PROTOTYPE( int w_specify, (void) );
  1978. 10254 FORWARD _PROTOTYPE( int w_schedule, (int proc_nr, struct iorequest_s *iop) );
  1979. 10255 FORWARD _PROTOTYPE( int w_finish, (void) );
  1980. 10256 FORWARD _PROTOTYPE( int com_out, (struct command *cmd) );
  1981. 10257 FORWARD _PROTOTYPE( void w_need_reset, (void) );
  1982. 10258 FORWARD _PROTOTYPE( int w_do_close, (struct driver *dp, message *m_ptr) );
  1983. 10259 FORWARD _PROTOTYPE( int com_simple, (struct command *cmd) );
  1984. 10260 FORWARD _PROTOTYPE( void w_timeout, (void) );
  1985. 10261 FORWARD _PROTOTYPE( int w_reset, (void) );
  1986. 10262 FORWARD _PROTOTYPE( int w_intr_wait, (void) );
  1987. 10263 FORWARD _PROTOTYPE( int w_waitfor, (int mask, int value) );
  1988. 10264 FORWARD _PROTOTYPE( int w_handler, (int irq) );
  1989. 10265 FORWARD _PROTOTYPE( void w_geometry, (struct partition *entry) );
  1990. 10266
  1991. 10267 /* w_waitfor loop unrolled once for speed. */
  1992. 10268 #define waitfor(mask, value)    
  1993. 10269         ((in_byte(w_wn->base + REG_STATUS) & mask) == value 
  1994. 10270                 || w_waitfor(mask, value))
  1995. 10271
  1996. 10272
  1997. 10273 /* Entry points to this driver. */
  1998. 10274 PRIVATE struct driver w_dtab = {
  1999. 10275   w_name,               /* current device's name */
  2000. 10276   w_do_open,            /* open or mount request, initialize device */
  2001. 10277   w_do_close,           /* release device */
  2002. 10278   do_diocntl,           /* get or set a partition's geometry */
  2003. 10279   w_prepare,            /* prepare for I/O on a given minor device */
  2004. 10280   w_schedule,           /* precompute cylinder, head, sector, etc. */
  2005. 10281   w_finish,             /* do the I/O */
  2006. 10282   nop_cleanup,          /* nothing to clean up */
  2007. 10283   w_geometry,           /* tell the geometry of the disk */
  2008. 10284 };
  2009. 10285
  2010. 10286 #if ENABLE_ATAPI
  2011. 10287 #include "atapi.c"      /* extra code for ATAPI CD-ROM */
  2012. 10288 #endif
  2013. 10289
  2014. 10290
  2015. 10291 /*===========================================================================*
  2016. 10292  *                              at_winchester_task                           *
  2017. 10293  *===========================================================================*/
  2018. 10294 PUBLIC void at_winchester_task()
  2019. 10295 {
  2020. 10296 /* Set special disk parameters then call the generic main loop. */
  2021. 10297
  2022. 10298   init_params();
  2023. 10299
  2024. 10300   driver_task(&w_dtab);
  2025. 10301 }
  2026. 10304 /*============================================================================*
  2027. 10305  *                              init_params                                   *
  2028. 10306  *============================================================================*/
  2029. 10307 PRIVATE void init_params()
  2030. 10308 {
  2031. 10309 /* This routine is called at startup to initialize the drive parameters. */
  2032. 10310
  2033. 10311   u16_t parv[2];
  2034. 10312   unsigned int vector;
  2035. 10313   int drive, nr_drives, i;
  2036. 10314   struct wini *wn;
  2037. 10315   u8_t params[16];
  2038. 10316   phys_bytes param_phys = vir2phys(params);
  2039. 10317
  2040. 10318   /* Get the number of drives from the BIOS data area */
  2041. 10319   phys_copy(0x475L, param_phys, 1L);
  2042. 10320   if ((nr_drives = params[0]) > 2) nr_drives = 2;
  2043. 10321
  2044. 10322   for (drive = 0, wn = wini; drive < MAX_DRIVES; drive++, wn++) {
  2045. 10323         if (drive < nr_drives) {
  2046. 10324                 /* Copy the BIOS parameter vector */
  2047. 10325                 vector = drive == 0 ? WINI_0_PARM_VEC : WINI_1_PARM_VEC;
  2048. 10326                 phys_copy(vector * 4L, vir2phys(parv), 4L);
  2049. 10327
  2050. 10328                 /* Calculate the address of the parameters and copy them */
  2051. 10329                 phys_copy(hclick_to_physb(parv[1]) + parv[0], param_phys, 16L);
  2052. 10330
  2053. 10331                 /* Copy the parameters to the structures of the drive */
  2054. 10332                 wn->lcylinders = bp_cylinders(params);
  2055. 10333                 wn->lheads = bp_heads(params);
  2056. 10334                 wn->lsectors = bp_sectors(params);
  2057. 10335                 wn->precomp = bp_precomp(params) >> 2;
  2058. 10336         }
  2059. 10337         wn->ldhpref = ldh_init(drive);
  2060. 10338         wn->max_count = MAX_SECS << SECTOR_SHIFT;
  2061. 10339         if (drive < 2) {
  2062. 10340                 /* Controller 0. */
  2063. 10341                 wn->base = REG_BASE0;
  2064. 10342                 wn->irq = AT_IRQ0;
  2065. 10343         } else {
  2066. 10344                 /* Controller 1. */
  2067. 10345                 wn->base = REG_BASE1;
  2068. 10346                 wn->irq = AT_IRQ1;
  2069. 10347         }
  2070. 10348   }
  2071. 10349 }
  2072. 10352 /*============================================================================*
  2073. 10353  *                              w_do_open                                     *
  2074. 10354  *============================================================================*/
  2075. 10355 PRIVATE int w_do_open(dp, m_ptr)
  2076. 10356 struct driver *dp;
  2077. 10357 message *m_ptr;
  2078. 10358 {
  2079. 10359 /* Device open: Initialize the controller and read the partition table. */
  2080. 10360
  2081. 10361   int r;
  2082. 10362   struct wini *wn;
  2083. 10363   struct command cmd;
  2084. 10364
  2085. 10365   if (w_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
  2086. 10366   wn = w_wn;
  2087. 10367
  2088. 10368   if (wn->state == 0) {
  2089. 10369         /* Try to identify the device. */
  2090. 10370         if (w_identify() != OK) {
  2091. 10371                 printf("%s: probe failedn", w_name());
  2092. 10372                 if (wn->state & DEAF) w_reset();
  2093. 10373                 wn->state = 0;
  2094. 10374                 return(ENXIO);
  2095. 10375         }
  2096. 10376   }
  2097. 10377   if (wn->open_ct++ == 0) {
  2098. 10378         /* Partition the disk. */
  2099. 10379         partition(&w_dtab, w_drive * DEV_PER_DRIVE, P_PRIMARY);
  2100. 10380   }
  2101. 10381   return(OK);
  2102. 10382 }
  2103. 10385 /*===========================================================================*
  2104. 10386  *                              w_prepare                                    *
  2105. 10387  *===========================================================================*/
  2106. 10388 PRIVATE struct device *w_prepare(device)
  2107. 10389 int device;
  2108. 10390 {
  2109. 10391 /* Prepare for I/O on a device. */
  2110. 10392
  2111. 10393   /* Nothing to transfer as yet. */
  2112. 10394   w_count = 0;
  2113. 10395
  2114. 10396   if (device < NR_DEVICES) {                    /* hd0, hd1, ... */
  2115. 10397         w_drive = device / DEV_PER_DRIVE;       /* save drive number */
  2116. 10398         w_wn = &wini[w_drive];
  2117. 10399         w_dv = &w_wn->part[device % DEV_PER_DRIVE];
  2118. 10400   } else
  2119. 10401   if ((unsigned) (device -= MINOR_hd1a) < NR_SUBDEVS) { /* hd1a, hd1b, ... */
  2120. 10402         w_drive = device / SUB_PER_DRIVE;
  2121. 10403         w_wn = &wini[w_drive];
  2122. 10404         w_dv = &w_wn->subpart[device % SUB_PER_DRIVE];
  2123. 10405   } else {
  2124. 10406         return(NIL_DEV);
  2125. 10407   }
  2126. 10408   return(w_dv);
  2127. 10409 }
  2128. 10412 /*===========================================================================*
  2129. 10413  *                              w_identify                                   *
  2130. 10414  *===========================================================================*/
  2131. 10415 PRIVATE int w_identify()
  2132. 10416 {
  2133. 10417 /* Find out if a device exists, if it is an old AT disk, or a newer ATA
  2134. 10418  * drive, a removable media device, etc.
  2135. 10419  */
  2136. 10420
  2137. 10421   struct wini *wn = w_wn;
  2138. 10422   struct command cmd;
  2139. 10423   char id_string[40];
  2140. 10424   int i, r;
  2141. 10425   unsigned long size;
  2142. 10426 #define id_byte(n)      (&tmp_buf[2 * (n)])
  2143. 10427 #define id_word(n)      (((u16_t) id_byte(n)[0] <<  0) 
  2144. 10428                         |((u16_t) id_byte(n)[1] <<  8))
  2145. 10429 #define id_longword(n)  (((u32_t) id_byte(n)[0] <<  0) 
  2146. 10430                         |((u32_t) id_byte(n)[1] <<  8) 
  2147. 10431                         |((u32_t) id_byte(n)[2] << 16) 
  2148. 10432                         |((u32_t) id_byte(n)[3] << 24))
  2149. 10433
  2150. 10434   /* Check if the one of the registers exists. */
  2151. 10435   r = in_byte(wn->base + REG_CYL_LO);
  2152. 10436   out_byte(wn->base + REG_CYL_LO, ~r);
  2153. 10437   if (in_byte(wn->base + REG_CYL_LO) == r) return(ERR);
  2154. 10438
  2155. 10439   /* Looks OK; register IRQ and try an ATA identify command. */
  2156. 10440   put_irq_handler(wn->irq, w_handler);
  2157. 10441   enable_irq(wn->irq);
  2158. 10442
  2159. 10443   cmd.ldh     = wn->ldhpref;
  2160. 10444   cmd.command = ATA_IDENTIFY;
  2161. 10445   if (com_simple(&cmd) == OK) {
  2162. 10446         /* This is an ATA device. */
  2163. 10447         wn->state |= SMART;
  2164. 10448
  2165. 10449         /* Device information. */
  2166. 10450         port_read(wn->base + REG_DATA, tmp_phys, SECTOR_SIZE);
  2167. 10451
  2168. 10452         /* Why are the strings byte swapped??? */
  2169. 10453         for (i = 0; i < 40; i++) id_string[i] = id_byte(27)[i^1];
  2170. 10454
  2171. 10455         /* Preferred CHS translation mode. */
  2172. 10456         wn->pcylinders = id_word(1);
  2173. 10457         wn->pheads = id_word(3);
  2174. 10458         wn->psectors = id_word(6);
  2175. 10459         size = (u32_t) wn->pcylinders * wn->pheads * wn->psectors;
  2176. 10460
  2177. 10461         if ((id_byte(49)[1] & 0x02) && size > 512L*1024*2) {
  2178. 10462                 /* Drive is LBA capable and is big enough to trust it to
  2179. 10463                  * not make a mess of it.
  2180. 10464                  */
  2181. 10465                 wn->ldhpref |= LDH_LBA;
  2182. 10466                 size = id_longword(60);
  2183. 10467         }
  2184. 10468
  2185. 10469         if (wn->lcylinders == 0) {
  2186. 10470                 /* No BIOS parameters?  Then make some up. */
  2187. 10471                 wn->lcylinders = wn->pcylinders;
  2188. 10472                 wn->lheads = wn->pheads;
  2189. 10473                 wn->lsectors = wn->psectors;
  2190. 10474                 while (wn->lcylinders > 1024) {
  2191. 10475                         wn->lheads *= 2;
  2192. 10476                         wn->lcylinders /= 2;
  2193. 10477                 }
  2194. 10478         }
  2195. 10479   } else {
  2196. 10480         /* Not an ATA device; no translations, no special features.  Don't
  2197. 10481          * touch it unless the BIOS knows about it.
  2198. 10482          */
  2199. 10483         if (wn->lcylinders == 0) return(ERR);   /* no BIOS parameters */
  2200. 10484         wn->pcylinders = wn->lcylinders;
  2201. 10485         wn->pheads = wn->lheads;
  2202. 10486         wn->psectors = wn->lsectors;
  2203. 10487         size = (u32_t) wn->pcylinders * wn->pheads * wn->psectors;
  2204. 10488   }
  2205. 10489   /* The fun ends at 4 GB. */
  2206. 10490   if (size > ((u32_t) -1) / SECTOR_SIZE) size = ((u32_t) -1) / SECTOR_SIZE;
  2207. 10491
  2208. 10492   /* Base and size of the whole drive */
  2209. 10493   wn->part[0].dv_base = 0;
  2210. 10494   wn->part[0].dv_size = size << SECTOR_SHIFT;
  2211. 10495
  2212. 10496   if (w_specify() != OK && w_specify() != OK) return(ERR);
  2213. 10497
  2214. 10498   printf("%s: ", w_name());
  2215. 10499   if (wn->state & SMART) {
  2216. 10500         printf("%.40sn", id_string);
  2217. 10501   } else {
  2218. 10502         printf("%ux%ux%un", wn->pcylinders, wn->pheads, wn->psectors);
  2219. 10503   }
  2220. 10504   return(OK);
  2221. 10505 }
  2222. 10508 /*===========================================================================*
  2223. 10509  *                              w_name                                       *
  2224. 10510  *===========================================================================*/
  2225. 10511 PRIVATE char *w_name()
  2226. 10512 {
  2227. 10513 /* Return a name for the current device. */
  2228. 10514   static char name[] = "at-hd15";
  2229. 10515   unsigned device = w_drive * DEV_PER_DRIVE;
  2230. 10516
  2231. 10517   if (device < 10) {
  2232. 10518         name[5] = '0' + device;
  2233. 10519         name[6] = 0;
  2234. 10520   } else {
  2235. 10521         name[5] = '0' + device / 10;
  2236. 10522         name[6] = '0' + device % 10;
  2237. 10523   }
  2238. 10524   return name;
  2239. 10525 }
  2240. 10528 /*===========================================================================*
  2241. 10529  *                              w_specify                                    *
  2242. 10530  *===========================================================================*/
  2243. 10531 PRIVATE int w_specify()
  2244. 10532 {
  2245. 10533 /* Routine to initialize the drive after boot or when a reset is needed. */
  2246. 10534
  2247. 10535   struct wini *wn = w_wn;
  2248. 10536   struct command cmd;
  2249. 10537
  2250. 10538   if ((wn->state & DEAF) && w_reset() != OK) return(ERR);
  2251. 10539
  2252. 10540   /* Specify parameters: precompensation, number of heads and sectors. */
  2253. 10541   cmd.precomp = wn->precomp;
  2254. 10542   cmd.count   = wn->psectors;
  2255. 10543   cmd.ldh     = w_wn->ldhpref | (wn->pheads - 1);
  2256. 10544   cmd.command = CMD_SPECIFY;            /* Specify some parameters */
  2257. 10545
  2258. 10546   if (com_simple(&cmd) != OK) return(ERR);
  2259. 10547
  2260. 10548   if (!(wn->state & SMART)) {
  2261. 10549         /* Calibrate an old disk. */
  2262. 10550         cmd.sector  = 0;
  2263. 10551         cmd.cyl_lo  = 0;
  2264. 10552         cmd.cyl_hi  = 0;
  2265. 10553         cmd.ldh     = w_wn->ldhpref;
  2266. 10554         cmd.command = CMD_RECALIBRATE;
  2267. 10555
  2268. 10556         if (com_simple(&cmd) != OK) return(ERR);
  2269. 10557   }
  2270. 10558
  2271. 10559   wn->state |= INITIALIZED;
  2272. 10560   return(OK);
  2273. 10561 }
  2274. 10564 /*===========================================================================*
  2275. 10565  *                              w_schedule                                   *
  2276. 10566  *===========================================================================*/
  2277. 10567 PRIVATE int w_schedule(proc_nr, iop)
  2278. 10568 int proc_nr;                    /* process doing the request */
  2279. 10569 struct iorequest_s *iop;        /* pointer to read or write request */
  2280. 10570 {
  2281. 10571 /* Gather I/O requests on consecutive blocks so they may be read/written
  2282. 10572  * in one controller command.  (There is enough time to compute the next
  2283. 10573  * consecutive request while an unwanted block passes by.)
  2284. 10574  */
  2285. 10575   struct wini *wn = w_wn;
  2286. 10576   int r, opcode;
  2287. 10577   unsigned long pos;
  2288. 10578   unsigned nbytes, count;
  2289. 10579   unsigned long block;
  2290. 10580   phys_bytes user_phys;
  2291. 10581
  2292. 10582   /* This many bytes to read/write */
  2293. 10583   nbytes = iop->io_nbytes;
  2294. 10584   if ((nbytes & SECTOR_MASK) != 0) return(iop->io_nbytes = EINVAL);
  2295. 10585
  2296. 10586   /* From/to this position on the device */
  2297. 10587   pos = iop->io_position;
  2298. 10588   if ((pos & SECTOR_MASK) != 0) return(iop->io_nbytes = EINVAL);
  2299. 10589
  2300. 10590   /* To/from this user address */
  2301. 10591   user_phys = numap(proc_nr, (vir_bytes) iop->io_buf, nbytes);
  2302. 10592   if (user_phys == 0) return(iop->io_nbytes = EINVAL);
  2303. 10593
  2304. 10594   /* Read or write? */
  2305. 10595   opcode = iop->io_request & ~OPTIONAL_IO;
  2306. 10596
  2307. 10597   /* Which block on disk and how close to EOF? */
  2308. 10598   if (pos >= w_dv->dv_size) return(OK);         /* At EOF */
  2309. 10599   if (pos + nbytes > w_dv->dv_size) nbytes = w_dv->dv_size - pos;
  2310. 10600   block = (w_dv->dv_base + pos) >> SECTOR_SHIFT;
  2311. 10601
  2312. 10602   if (w_count > 0 && block != w_nextblock) {
  2313. 10603         /* This new request can't be chained to the job being built */
  2314. 10604         if ((r = w_finish()) != OK) return(r);
  2315. 10605   }
  2316. 10606
  2317. 10607   /* The next consecutive block */
  2318. 10608   w_nextblock = block + (nbytes >> SECTOR_SHIFT);
  2319. 10609
  2320. 10610   /* While there are "unscheduled" bytes in the request: */
  2321. 10611   do {
  2322. 10612         count = nbytes;
  2323. 10613
  2324. 10614         if (w_count == wn->max_count) {
  2325. 10615                 /* The drive can't do more then max_count at once */
  2326. 10616                 if ((r = w_finish()) != OK) return(r);
  2327. 10617         }
  2328. 10618
  2329. 10619         if (w_count + count > wn->max_count)
  2330. 10620                 count = wn->max_count - w_count;
  2331. 10621
  2332. 10622         if (w_count == 0) {
  2333. 10623                 /* The first request in a row, initialize. */
  2334. 10624                 w_opcode = opcode;
  2335. 10625                 w_tp = wtrans;
  2336. 10626         }
  2337. 10627
  2338. 10628         /* Store I/O parameters */
  2339. 10629         w_tp->iop = iop;
  2340. 10630         w_tp->block = block;
  2341. 10631         w_tp->count = count;
  2342. 10632         w_tp->phys = user_phys;
  2343. 10633
  2344. 10634         /* Update counters */
  2345. 10635         w_tp++;
  2346. 10636         w_count += count;
  2347. 10637         block += count >> SECTOR_SHIFT;
  2348. 10638         user_phys += count;
  2349. 10639         nbytes -= count;
  2350. 10640   } while (nbytes > 0);
  2351. 10641
  2352. 10642   return(OK);
  2353. 10643 }
  2354. 10646 /*===========================================================================*
  2355. 10647  *                              w_finish                                     *
  2356. 10648  *===========================================================================*/
  2357. 10649 PRIVATE int w_finish()
  2358. 10650 {
  2359. 10651 /* Carry out the I/O requests gathered in wtrans[]. */
  2360. 10652
  2361. 10653   struct trans *tp = wtrans;
  2362. 10654   struct wini *wn = w_wn;
  2363. 10655   int r, errors;
  2364. 10656   struct command cmd;
  2365. 10657   unsigned cylinder, head, sector, secspcyl;
  2366. 10658
  2367. 10659   if (w_count == 0) return(OK); /* Spurious finish. */
  2368. 10660
  2369. 10661   r = ERR;      /* Trigger the first com_out */
  2370. 10662   errors = 0;
  2371. 10663
  2372. 10664   do {
  2373. 10665         if (r != OK) {
  2374. 10666                 /* The controller must be (re)programmed. */
  2375. 10667
  2376. 10668                 /* First check to see if a reinitialization is needed. */
  2377. 10669                 if (!(wn->state & INITIALIZED) && w_specify() != OK)
  2378. 10670                         return(tp->iop->io_nbytes = EIO);
  2379. 10671
  2380. 10672                 /* Tell the controller to transfer w_count bytes */
  2381. 10673                 cmd.precomp = wn->precomp;
  2382. 10674                 cmd.count   = (w_count >> SECTOR_SHIFT) & BYTE;
  2383. 10675                 if (wn->ldhpref & LDH_LBA) {
  2384. 10676                         cmd.sector  = (tp->block >>  0) & 0xFF;
  2385. 10677                         cmd.cyl_lo  = (tp->block >>  8) & 0xFF;
  2386. 10678                         cmd.cyl_hi  = (tp->block >> 16) & 0xFF;
  2387. 10679                         cmd.ldh     = wn->ldhpref | ((tp->block >> 24) & 0xF);
  2388. 10680                 } else {
  2389. 10681                         secspcyl = wn->pheads * wn->psectors;
  2390. 10682                         cylinder = tp->block / secspcyl;
  2391. 10683                         head = (tp->block % secspcyl) / wn->psectors;
  2392. 10684                         sector = tp->block % wn->psectors;
  2393. 10685                         cmd.sector  = sector + 1;
  2394. 10686                         cmd.cyl_lo  = cylinder & BYTE;
  2395. 10687                         cmd.cyl_hi  = (cylinder >> 8) & BYTE;
  2396. 10688                         cmd.ldh     = wn->ldhpref | head;
  2397. 10689                 }
  2398. 10690                 cmd.command = w_opcode == DEV_WRITE ? CMD_WRITE : CMD_READ;
  2399. 10691
  2400. 10692                 if ((r = com_out(&cmd)) != OK) {
  2401. 10693                         if (++errors == MAX_ERRORS) {
  2402. 10694                                 w_command = CMD_IDLE;
  2403. 10695                                 return(tp->iop->io_nbytes = EIO);
  2404. 10696                         }
  2405. 10697                         continue;       /* Retry */
  2406. 10698                 }
  2407. 10699         }
  2408. 10700
  2409. 10701         /* For each sector, wait for an interrupt and fetch the data (read),
  2410. 10702          * or supply data to the controller and wait for an interrupt (write).
  2411. 10703          */
  2412. 10704
  2413. 10705         if (w_opcode == DEV_READ) {
  2414. 10706                 if ((r = w_intr_wait()) == OK) {
  2415. 10707                         /* Copy data from the device's buffer to user space. */
  2416. 10708
  2417. 10709                         port_read(wn->base + REG_DATA, tp->phys, SECTOR_SIZE);
  2418. 10710
  2419. 10711                         tp->phys += SECTOR_SIZE;
  2420. 10712                         tp->iop->io_nbytes -= SECTOR_SIZE;
  2421. 10713                         w_count -= SECTOR_SIZE;
  2422. 10714                         if ((tp->count -= SECTOR_SIZE) == 0) tp++;
  2423. 10715                 } else {
  2424. 10716                         /* Any faulty data? */
  2425. 10717                         if (w_status & STATUS_DRQ) {
  2426. 10718                                 port_read(wn->base + REG_DATA, tmp_phys,
  2427. 10719                                                                 SECTOR_SIZE);
  2428. 10720                         }
  2429. 10721                 }
  2430. 10722         } else {
  2431. 10723                 /* Wait for data requested. */
  2432. 10724                 if (!waitfor(STATUS_DRQ, STATUS_DRQ)) {
  2433. 10725                         r = ERR;
  2434. 10726                 } else {
  2435. 10727                         /* Fill the buffer of the drive. */
  2436. 10728
  2437. 10729                         port_write(wn->base + REG_DATA, tp->phys, SECTOR_SIZE);
  2438. 10730                         r = w_intr_wait();
  2439. 10731                 }
  2440. 10732
  2441. 10733                 if (r == OK) {
  2442. 10734                         /* Book the bytes successfully written. */
  2443. 10735
  2444. 10736                         tp->phys += SECTOR_SIZE;
  2445. 10737                         tp->iop->io_nbytes -= SECTOR_SIZE;
  2446. 10738                         w_count -= SECTOR_SIZE;
  2447. 10739                         if ((tp->count -= SECTOR_SIZE) == 0) tp++;
  2448. 10740                 }
  2449. 10741         }
  2450. 10742
  2451. 10743         if (r != OK) {
  2452. 10744                 /* Don't retry if sector marked bad or too many errors */
  2453. 10745                 if (r == ERR_BAD_SECTOR || ++errors == MAX_ERRORS) {
  2454. 10746                         w_command = CMD_IDLE;
  2455. 10747                         return(tp->iop->io_nbytes = EIO);
  2456. 10748                 }
  2457. 10749
  2458. 10750                 /* Reset if halfway, but bail out if optional I/O. */
  2459. 10751                 if (errors == MAX_ERRORS / 2) {
  2460. 10752                         w_need_reset();
  2461. 10753                         if (tp->iop->io_request & OPTIONAL_IO) {
  2462. 10754                                 w_command = CMD_IDLE;
  2463. 10755                                 return(tp->iop->io_nbytes = EIO);
  2464. 10756                         }
  2465. 10757                 }
  2466. 10758                 continue;       /* Retry */
  2467. 10759         }
  2468. 10760         errors = 0;
  2469. 10761   } while (w_count > 0);
  2470. 10762
  2471. 10763   w_command = CMD_IDLE;
  2472. 10764   return(OK);
  2473. 10765 }
  2474. 10768 /*============================================================================*
  2475. 10769  *                              com_out                                       *
  2476. 10770  *============================================================================*/
  2477. 10771 PRIVATE int com_out(cmd)
  2478. 10772 struct command *cmd;            /* Command block */
  2479. 10773 {
  2480. 10774 /* Output the command block to the winchester controller and return status */
  2481. 10775
  2482. 10776   struct wini *wn = w_wn;
  2483. 10777   unsigned base = wn->base;
  2484. 10778
  2485. 10779   if (!waitfor(STATUS_BSY, 0)) {
  2486. 10780         printf("%s: controller not readyn", w_name());
  2487. 10781         return(ERR);
  2488. 10782   }
  2489. 10783
  2490. 10784   /* Select drive. */
  2491. 10785   out_byte(base + REG_LDH, cmd->ldh);
  2492. 10786
  2493. 10787   if (!waitfor(STATUS_BSY, 0)) {
  2494. 10788         printf("%s: drive not readyn", w_name());
  2495. 10789         return(ERR);
  2496. 10790   }
  2497. 10791
  2498. 10792   /* Schedule a wakeup call, some controllers are flaky. */
  2499. 10793   clock_mess(WAKEUP, w_timeout);
  2500. 10794
  2501. 10795   out_byte(base + REG_CTL, wn->pheads >= 8 ? CTL_EIGHTHEADS : 0);
  2502. 10796   out_byte(base + REG_PRECOMP, cmd->precomp);
  2503. 10797   out_byte(base + REG_COUNT, cmd->count);
  2504. 10798   out_byte(base + REG_SECTOR, cmd->sector);
  2505. 10799   out_byte(base + REG_CYL_LO, cmd->cyl_lo);
  2506. 10800   out_byte(base + REG_CYL_HI, cmd->cyl_hi);
  2507. 10801   lock();
  2508. 10802   out_byte(base + REG_COMMAND, cmd->command);
  2509. 10803   w_command = cmd->command;
  2510. 10804   w_status = STATUS_BSY;
  2511. 10805   unlock();
  2512. 10806   return(OK);
  2513. 10807 }
  2514. 10810 /*===========================================================================*
  2515. 10811  *                              w_need_reset                                 *
  2516. 10812  *===========================================================================*/
  2517. 10813 PRIVATE void w_need_reset()
  2518. 10814 {
  2519. 10815 /* The controller needs to be reset. */
  2520. 10816   struct wini *wn;
  2521. 10817
  2522. 10818   for (wn = wini; wn < &wini[MAX_DRIVES]; wn++) {
  2523. 10819         wn->state |= DEAF;
  2524. 10820         wn->state &= ~INITIALIZED;
  2525. 10821   }
  2526. 10822 }
  2527. 10825 /*============================================================================*
  2528. 10826  *                              w_do_close                                    *
  2529. 10827  *============================================================================*/
  2530. 10828 PRIVATE int w_do_close(dp, m_ptr)
  2531. 10829 struct driver *dp;
  2532. 10830 message *m_ptr;
  2533. 10831 {
  2534. 10832 /* Device close: Release a device. */
  2535. 10833
  2536. 10834   if (w_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
  2537. 10835   w_wn->open_ct--;
  2538. 10836   return(OK);
  2539. 10837 }
  2540. 10840 /*============================================================================*
  2541. 10841  *                              com_simple                                    *
  2542. 10842  *============================================================================*/
  2543. 10843 PRIVATE int com_simple(cmd)
  2544. 10844 struct command *cmd;            /* Command block */
  2545. 10845 {
  2546. 10846 /* A simple controller command, only one interrupt and no data-out phase. */
  2547. 10847   int r;
  2548. 10848
  2549. 10849   if ((r = com_out(cmd)) == OK) r = w_intr_wait();
  2550. 10850   w_command = CMD_IDLE;
  2551. 10851   return(r);
  2552. 10852 }
  2553. 10855 /*===========================================================================*
  2554. 10856  *                              w_timeout                                    *
  2555. 10857  *===========================================================================*/
  2556. 10858 PRIVATE void w_timeout()
  2557. 10859 {
  2558. 10860   struct wini *wn = w_wn;
  2559. 10861
  2560. 10862   switch (w_command) {
  2561. 10863   case CMD_IDLE:
  2562. 10864         break;          /* fine */
  2563. 10865   case CMD_READ:
  2564. 10866   case CMD_WRITE:
  2565. 10867         /* Impossible, but not on PC's:  The controller does not respond. */
  2566. 10868
  2567. 10869         /* Limiting multisector I/O seems to help. */
  2568. 10870         if (wn->max_count > 8 * SECTOR_SIZE) {
  2569. 10871                 wn->max_count = 8 * SECTOR_SIZE;
  2570. 10872         } else {
  2571. 10873                 wn->max_count = SECTOR_SIZE;
  2572. 10874         }
  2573. 10875         /*FALL THROUGH*/
  2574. 10876   default:
  2575. 10877         /* Some other command. */
  2576. 10878         printf("%s: timeout on command %02xn", w_name(), w_command);
  2577. 10879         w_need_reset();
  2578. 10880         w_status = 0;
  2579. 10881         interrupt(WINCHESTER);
  2580. 10882   }
  2581. 10883 }
  2582. 10886 /*===========================================================================*
  2583. 10887  *                              w_reset                                      *
  2584. 10888  *===========================================================================*/
  2585. 10889 PRIVATE int w_reset()
  2586. 10890 {
  2587. 10891 /* Issue a reset to the controller.  This is done after any catastrophe,
  2588. 10892  * like the controller refusing to respond.
  2589. 10893  */
  2590. 10894
  2591. 10895   struct wini *wn;
  2592. 10896   int err;
  2593. 10897
  2594. 10898   /* Wait for any internal drive recovery. */
  2595. 10899   milli_delay(RECOVERYTIME);
  2596. 10900
  2597. 10901   /* Strobe reset bit */
  2598. 10902   out_byte(w_wn->base + REG_CTL, CTL_RESET);
  2599. 10903   milli_delay(1);
  2600. 10904   out_byte(w_wn->base + REG_CTL, 0);
  2601. 10905   milli_delay(1);
  2602. 10906
  2603. 10907   /* Wait for controller ready */
  2604. 10908   if (!w_waitfor(STATUS_BSY | STATUS_RDY, STATUS_RDY)) {
  2605. 10909         printf("%s: reset failed, drive busyn", w_name());
  2606. 10910         return(ERR);
  2607. 10911   }
  2608. 10912
  2609. 10913   /* The error register should be checked now, but some drives mess it up. */
  2610. 10914
  2611. 10915   for (wn = wini; wn < &wini[MAX_DRIVES]; wn++) {
  2612. 10916         if (wn->base == w_wn->base) wn->state &= ~DEAF;
  2613. 10917   }
  2614. 10918   return(OK);
  2615. 10919 }
  2616. 10922 /*============================================================================*
  2617. 10923  *                              w_intr_wait                                   *
  2618. 10924  *============================================================================*/
  2619. 10925 PRIVATE int w_intr_wait()
  2620. 10926 {
  2621. 10927 /* Wait for a task completion interrupt and return results. */
  2622. 10928
  2623. 10929   message mess;
  2624. 10930   int r;
  2625. 10931
  2626. 10932   /* Wait for an interrupt that sets w_status to "not busy". */
  2627. 10933   while (w_status & STATUS_BSY) receive(HARDWARE, &mess);
  2628. 10934
  2629. 10935   /* Check status. */
  2630. 10936   lock();
  2631. 10937   if ((w_status & (STATUS_BSY | STATUS_RDY | STATUS_WF | STATUS_ERR))
  2632. 10938                                                         == STATUS_RDY) {
  2633. 10939         r = OK;
  2634. 10940         w_status |= STATUS_BSY; /* assume still busy with I/O */
  2635. 10941   } else
  2636. 10942   if ((w_status & STATUS_ERR) && (in_byte(w_wn->base + REG_ERROR) & ERROR_BB)) {
  2637. 10943         r = ERR_BAD_SECTOR;     /* sector marked bad, retries won't help */
  2638. 10944   } else {
  2639. 10945         r = ERR;                /* any other error */
  2640. 10946   }
  2641. 10947   unlock();
  2642. 10948   return(r);
  2643. 10949 }
  2644. 10952 /*==========================================================================*
  2645. 10953  *                              w_waitfor                                   *
  2646. 10954  *==========================================================================*/
  2647. 10955 PRIVATE int w_waitfor(mask, value)
  2648. 10956 int mask;                       /* status mask */
  2649. 10957 int value;                      /* required status */
  2650. 10958 {
  2651. 10959 /* Wait until controller is in the required state.  Return zero on timeout. */
  2652. 10960
  2653. 10961   struct milli_state ms;
  2654. 10962
  2655. 10963   milli_start(&ms);
  2656. 10964   do {
  2657. 10965        if ((in_byte(w_wn->base + REG_STATUS) & mask) == value) return 1;
  2658. 10966   } while (milli_elapsed(&ms) < TIMEOUT);
  2659. 10967
  2660. 10968   w_need_reset();       /* Controller gone deaf. */
  2661. 10969   return(0);
  2662. 10970 }
  2663. 10973 /*==========================================================================*
  2664. 10974  *                              w_handler                                   *
  2665. 10975  *==========================================================================*/
  2666. 10976 PRIVATE int w_handler(irq)
  2667. 10977 int irq;
  2668. 10978 {
  2669. 10979 /* Disk interrupt, send message to winchester task and reenable interrupts. */
  2670. 10980
  2671. 10981   w_status = in_byte(w_wn->base + REG_STATUS);  /* acknowledge interrupt */
  2672. 10982   interrupt(WINCHESTER);
  2673. 10983   return 1;
  2674. 10984 }
  2675. 10987 /*============================================================================*
  2676. 10988  *                              w_geometry                                    *
  2677. 10989  *============================================================================*/
  2678. 10990 PRIVATE void w_geometry(entry)
  2679. 10991 struct partition *entry;
  2680. 10992 {
  2681. 10993   entry->cylinders = w_wn->lcylinders;
  2682. 10994   entry->heads = w_wn->lheads;
  2683. 10995   entry->sectors = w_wn->lsectors;
  2684. 10996 }
  2685. 10997 #endif /* ENABLE_AT_WINI */
  2686. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2687. src/kernel/clock.c    
  2688. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2689. 11000 /* This file contains the code and data for the clock task.  The clock task
  2690. 11001  * accepts six message types:
  2691. 11002  *
  2692. 11003  *   HARD_INT:    a clock interrupt has occurred
  2693. 11004  *   GET_UPTIME:  get the time since boot in ticks
  2694. 11005  *   GET_TIME:    a process wants the real time in seconds
  2695. 11006  *   SET_TIME:    a process wants to set the real time in seconds
  2696. 11007  *   SET_ALARM:   a process wants to be alerted after a specified interval
  2697. 11008  *   SET_SYN_AL:  set the sync alarm
  2698. 11009  *
  2699. 11010  *
  2700. 11011  * The input message is format m6.  The parameters are as follows:
  2701. 11012  *
  2702. 11013  *     m_type    CLOCK_PROC   FUNC    NEW_TIME
  2703. 11014  * ---------------------------------------------
  2704. 11015  * | HARD_INT   |          |         |         |
  2705. 11016  * |------------+----------+---------+---------|
  2706. 11017  * | GET_UPTIME |          |         |         |
  2707. 11018  * |------------+----------+---------+---------|