]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/ia64/ia64/sscdisk.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / ia64 / ia64 / sscdisk.c
1 /*-
2  * ----------------------------------------------------------------------------
3  * "THE BEER-WARE LICENSE" (Revision 42):
4  * <phk@FreeBSD.ORG> wrote this file.  As long as you retain this notice you
5  * can do whatever you want with this stuff. If we meet some day, and you think
6  * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
7  * ----------------------------------------------------------------------------
8  *
9  * $FreeBSD$
10  *
11  */
12
13 #include "opt_md.h"
14 #include "opt_ski.h"
15
16 #include <sys/param.h>
17 #include <sys/systm.h>
18 #include <sys/bio.h>
19 #include <sys/conf.h>
20 #include <sys/kernel.h>
21 #include <sys/linker.h>
22 #include <sys/lock.h>
23 #include <sys/malloc.h>
24 #include <sys/mutex.h>
25 #include <sys/queue.h>
26 #include <sys/sysctl.h>
27 #include <sys/proc.h>
28 #include <vm/vm.h>
29 #include <vm/vm_kern.h>
30 #include <vm/vm_page.h>
31 #include <vm/vm_map.h>
32 #include <vm/vm_extern.h>
33 #include <vm/vm_object.h>
34 #include <vm/vm_pager.h>
35 #include <machine/md_var.h>
36 #include <geom/geom_disk.h>
37
38 #ifndef SKI_ROOT_FILESYSTEM
39 #define SKI_ROOT_FILESYSTEM     "ia64-root.fs"
40 #endif
41
42 #define SSC_OPEN                        50
43 #define SSC_CLOSE                       51
44 #define SSC_READ                        52
45 #define SSC_WRITE                       53
46 #define SSC_GET_COMPLETION              54
47 #define SSC_WAIT_COMPLETION             55
48
49 struct disk_req {
50         unsigned long addr;
51         unsigned len;
52 };
53
54 struct disk_stat {
55         int fd;
56         unsigned count;
57 };
58
59 static u_int64_t
60 ssc(u_int64_t in0, u_int64_t in1, u_int64_t in2, u_int64_t in3, int which)
61 {
62         register u_int64_t ret0 __asm("r8");
63
64         __asm __volatile("mov r15=%1\n\t"
65                          "break 0x80001"
66                          : "=r"(ret0)
67                          : "r"(which), "r"(in0), "r"(in1), "r"(in2), "r"(in3));
68         return ret0;
69 }
70
71 #ifndef SSC_NSECT
72 #define SSC_NSECT 409600
73 #endif
74
75 MALLOC_DEFINE(M_SSC, "ssc_disk", "Simulator Disk");
76
77 static int sscrootready;
78
79 static d_strategy_t sscstrategy;
80
81 static LIST_HEAD(, ssc_s) ssc_softc_list = LIST_HEAD_INITIALIZER(&ssc_softc_list);
82
83 struct ssc_s {
84         int unit;
85         LIST_ENTRY(ssc_s) list;
86         struct bio_queue_head bio_queue;
87         struct disk *disk;
88         struct cdev *dev;
89         int busy;
90         int fd;
91 };
92
93 static int sscunits;
94
95 static void
96 sscstrategy(struct bio *bp)
97 {
98         struct ssc_s *sc;
99         int s;
100         struct disk_req req;
101         struct disk_stat stat;
102         u_long len, va, off;
103
104         sc = bp->bio_disk->d_drv1;
105
106         s = splbio();
107
108         bioq_disksort(&sc->bio_queue, bp);
109
110         if (sc->busy) {
111                 splx(s);
112                 return;
113         }
114
115         sc->busy++;
116         
117         while (1) {
118                 bp = bioq_takefirst(&sc->bio_queue);
119                 splx(s);
120                 if (!bp)
121                         break;
122
123                 va = (u_long) bp->bio_data;
124                 len = bp->bio_bcount;
125                 off = bp->bio_pblkno << DEV_BSHIFT;
126                 while (len > 0) {
127                         u_int t;
128                         if ((va & PAGE_MASK) + len > PAGE_SIZE)
129                                 t = PAGE_SIZE - (va & PAGE_MASK);
130                         else
131                                 t = len;
132                         req.len = t;
133                         req.addr = ia64_tpa(va);
134                         ssc(sc->fd, 1, ia64_tpa((long) &req), off,
135                             (bp->bio_cmd == BIO_READ) ? SSC_READ : SSC_WRITE);
136                         stat.fd = sc->fd;
137                         ssc(ia64_tpa((long)&stat), 0, 0, 0,
138                             SSC_WAIT_COMPLETION);
139                         va += t;
140                         len -= t;
141                         off += t;
142                 }
143                 bp->bio_resid = 0;
144                 biodone(bp);
145                 s = splbio();
146         }
147
148         sc->busy = 0;
149         return;
150 }
151
152 static struct ssc_s *
153 ssccreate(int unit)
154 {
155         struct ssc_s *sc;
156         int fd;
157
158         fd = ssc(ia64_tpa((u_int64_t) SKI_ROOT_FILESYSTEM),
159                  1, 0, 0, SSC_OPEN);
160         if (fd == -1)
161                 return (NULL);
162
163         if (unit == -1)
164                 unit = sscunits++;
165         /* Make sure this unit isn't already in action */
166         LIST_FOREACH(sc, &ssc_softc_list, list) {
167                 if (sc->unit == unit)
168                         return (NULL);
169         }
170         MALLOC(sc, struct ssc_s *,sizeof(*sc), M_SSC, M_WAITOK | M_ZERO);
171         LIST_INSERT_HEAD(&ssc_softc_list, sc, list);
172         sc->unit = unit;
173         bioq_init(&sc->bio_queue);
174
175         sc->disk = disk_alloc();
176         sc->disk->d_drv1 = sc;
177         sc->disk->d_fwheads = 0;
178         sc->disk->d_fwsectors = 0;
179         sc->disk->d_maxsize = DFLTPHYS;
180         sc->disk->d_mediasize = (off_t)SSC_NSECT * DEV_BSIZE;
181         sc->disk->d_name = "sscdisk";
182         sc->disk->d_sectorsize = DEV_BSIZE;
183         sc->disk->d_strategy = sscstrategy;
184         sc->disk->d_unit = sc->unit;
185         sc->disk->d_flags = DISKFLAG_NEEDSGIANT;
186         disk_create(sc->disk, DISK_VERSION);
187         sc->fd = fd;
188         if (sc->unit == 0) 
189                 sscrootready = 1;
190         return (sc);
191 }
192
193 static void
194 ssc_drvinit(void *unused)
195 {
196         ssccreate(-1);
197 }
198
199 SYSINIT(sscdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE, ssc_drvinit,NULL);
200
201 static void
202 ssc_takeroot(void *junk)
203 {
204         if (sscrootready)
205                 rootdevnames[0] = "ufs:/dev/sscdisk0";
206 }
207
208 SYSINIT(ssc_root, SI_SUB_MOUNT_ROOT, SI_ORDER_FIRST, ssc_takeroot, NULL);