1*4882a593Smuzhiyun /**************************************************************************
2*4882a593Smuzhiyun *
3*4882a593Smuzhiyun * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA.
4*4882a593Smuzhiyun * All Rights Reserved.
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Permission is hereby granted, free of charge, to any person obtaining a
7*4882a593Smuzhiyun * copy of this software and associated documentation files (the
8*4882a593Smuzhiyun * "Software"), to deal in the Software without restriction, including
9*4882a593Smuzhiyun * without limitation the rights to use, copy, modify, merge, publish,
10*4882a593Smuzhiyun * distribute, sub license, and/or sell copies of the Software, and to
11*4882a593Smuzhiyun * permit persons to whom the Software is furnished to do so, subject to
12*4882a593Smuzhiyun * the following conditions:
13*4882a593Smuzhiyun *
14*4882a593Smuzhiyun * The above copyright notice and this permission notice (including the
15*4882a593Smuzhiyun * next paragraph) shall be included in all copies or substantial portions
16*4882a593Smuzhiyun * of the Software.
17*4882a593Smuzhiyun *
18*4882a593Smuzhiyun * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19*4882a593Smuzhiyun * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20*4882a593Smuzhiyun * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21*4882a593Smuzhiyun * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
22*4882a593Smuzhiyun * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23*4882a593Smuzhiyun * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24*4882a593Smuzhiyun * USE OR OTHER DEALINGS IN THE SOFTWARE.
25*4882a593Smuzhiyun *
26*4882a593Smuzhiyun *
27*4882a593Smuzhiyun **************************************************************************/
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun /*
30*4882a593Smuzhiyun * Authors:
31*4882a593Smuzhiyun * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
32*4882a593Smuzhiyun */
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun #include <video/sisfb.h>
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun #include <drm/drm_device.h>
37*4882a593Smuzhiyun #include <drm/drm_file.h>
38*4882a593Smuzhiyun #include <drm/sis_drm.h>
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun #include "sis_drv.h"
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun #define VIDEO_TYPE 0
44*4882a593Smuzhiyun #define AGP_TYPE 1
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun struct sis_memblock {
48*4882a593Smuzhiyun struct drm_mm_node mm_node;
49*4882a593Smuzhiyun struct sis_memreq req;
50*4882a593Smuzhiyun struct list_head owner_list;
51*4882a593Smuzhiyun };
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun #if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE)
54*4882a593Smuzhiyun /* fb management via fb device */
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun #define SIS_MM_ALIGN_SHIFT 0
57*4882a593Smuzhiyun #define SIS_MM_ALIGN_MASK 0
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun #else /* CONFIG_FB_SIS[_MODULE] */
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun #define SIS_MM_ALIGN_SHIFT 4
62*4882a593Smuzhiyun #define SIS_MM_ALIGN_MASK ((1 << SIS_MM_ALIGN_SHIFT) - 1)
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun #endif /* CONFIG_FB_SIS[_MODULE] */
65*4882a593Smuzhiyun
sis_fb_init(struct drm_device * dev,void * data,struct drm_file * file_priv)66*4882a593Smuzhiyun static int sis_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
67*4882a593Smuzhiyun {
68*4882a593Smuzhiyun drm_sis_private_t *dev_priv = dev->dev_private;
69*4882a593Smuzhiyun drm_sis_fb_t *fb = data;
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun mutex_lock(&dev->struct_mutex);
72*4882a593Smuzhiyun /* Unconditionally init the drm_mm, even though we don't use it when the
73*4882a593Smuzhiyun * fb sis driver is available - make cleanup easier. */
74*4882a593Smuzhiyun drm_mm_init(&dev_priv->vram_mm, 0, fb->size >> SIS_MM_ALIGN_SHIFT);
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun dev_priv->vram_initialized = 1;
77*4882a593Smuzhiyun dev_priv->vram_offset = fb->offset;
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun mutex_unlock(&dev->struct_mutex);
80*4882a593Smuzhiyun DRM_DEBUG("offset = %lu, size = %lu\n", fb->offset, fb->size);
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun return 0;
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun
sis_drm_alloc(struct drm_device * dev,struct drm_file * file,void * data,int pool)85*4882a593Smuzhiyun static int sis_drm_alloc(struct drm_device *dev, struct drm_file *file,
86*4882a593Smuzhiyun void *data, int pool)
87*4882a593Smuzhiyun {
88*4882a593Smuzhiyun drm_sis_private_t *dev_priv = dev->dev_private;
89*4882a593Smuzhiyun drm_sis_mem_t *mem = data;
90*4882a593Smuzhiyun int retval = 0, user_key;
91*4882a593Smuzhiyun struct sis_memblock *item;
92*4882a593Smuzhiyun struct sis_file_private *file_priv = file->driver_priv;
93*4882a593Smuzhiyun unsigned long offset;
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun mutex_lock(&dev->struct_mutex);
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun if (0 == ((pool == 0) ? dev_priv->vram_initialized :
98*4882a593Smuzhiyun dev_priv->agp_initialized)) {
99*4882a593Smuzhiyun DRM_ERROR
100*4882a593Smuzhiyun ("Attempt to allocate from uninitialized memory manager.\n");
101*4882a593Smuzhiyun mutex_unlock(&dev->struct_mutex);
102*4882a593Smuzhiyun return -EINVAL;
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun item = kzalloc(sizeof(*item), GFP_KERNEL);
106*4882a593Smuzhiyun if (!item) {
107*4882a593Smuzhiyun retval = -ENOMEM;
108*4882a593Smuzhiyun goto fail_alloc;
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun mem->size = (mem->size + SIS_MM_ALIGN_MASK) >> SIS_MM_ALIGN_SHIFT;
112*4882a593Smuzhiyun if (pool == AGP_TYPE) {
113*4882a593Smuzhiyun retval = drm_mm_insert_node(&dev_priv->agp_mm,
114*4882a593Smuzhiyun &item->mm_node,
115*4882a593Smuzhiyun mem->size);
116*4882a593Smuzhiyun offset = item->mm_node.start;
117*4882a593Smuzhiyun } else {
118*4882a593Smuzhiyun #if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE)
119*4882a593Smuzhiyun item->req.size = mem->size;
120*4882a593Smuzhiyun sis_malloc(&item->req);
121*4882a593Smuzhiyun if (item->req.size == 0)
122*4882a593Smuzhiyun retval = -ENOMEM;
123*4882a593Smuzhiyun offset = item->req.offset;
124*4882a593Smuzhiyun #else
125*4882a593Smuzhiyun retval = drm_mm_insert_node(&dev_priv->vram_mm,
126*4882a593Smuzhiyun &item->mm_node,
127*4882a593Smuzhiyun mem->size);
128*4882a593Smuzhiyun offset = item->mm_node.start;
129*4882a593Smuzhiyun #endif
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun if (retval)
132*4882a593Smuzhiyun goto fail_alloc;
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun retval = idr_alloc(&dev_priv->object_idr, item, 1, 0, GFP_KERNEL);
135*4882a593Smuzhiyun if (retval < 0)
136*4882a593Smuzhiyun goto fail_idr;
137*4882a593Smuzhiyun user_key = retval;
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun list_add(&item->owner_list, &file_priv->obj_list);
140*4882a593Smuzhiyun mutex_unlock(&dev->struct_mutex);
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun mem->offset = ((pool == 0) ?
143*4882a593Smuzhiyun dev_priv->vram_offset : dev_priv->agp_offset) +
144*4882a593Smuzhiyun (offset << SIS_MM_ALIGN_SHIFT);
145*4882a593Smuzhiyun mem->free = user_key;
146*4882a593Smuzhiyun mem->size = mem->size << SIS_MM_ALIGN_SHIFT;
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun return 0;
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun fail_idr:
151*4882a593Smuzhiyun drm_mm_remove_node(&item->mm_node);
152*4882a593Smuzhiyun fail_alloc:
153*4882a593Smuzhiyun kfree(item);
154*4882a593Smuzhiyun mutex_unlock(&dev->struct_mutex);
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun mem->offset = 0;
157*4882a593Smuzhiyun mem->size = 0;
158*4882a593Smuzhiyun mem->free = 0;
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun DRM_DEBUG("alloc %d, size = %ld, offset = %ld\n", pool, mem->size,
161*4882a593Smuzhiyun mem->offset);
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun return retval;
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun
sis_drm_free(struct drm_device * dev,void * data,struct drm_file * file_priv)166*4882a593Smuzhiyun static int sis_drm_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
167*4882a593Smuzhiyun {
168*4882a593Smuzhiyun drm_sis_private_t *dev_priv = dev->dev_private;
169*4882a593Smuzhiyun drm_sis_mem_t *mem = data;
170*4882a593Smuzhiyun struct sis_memblock *obj;
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun mutex_lock(&dev->struct_mutex);
173*4882a593Smuzhiyun obj = idr_find(&dev_priv->object_idr, mem->free);
174*4882a593Smuzhiyun if (obj == NULL) {
175*4882a593Smuzhiyun mutex_unlock(&dev->struct_mutex);
176*4882a593Smuzhiyun return -EINVAL;
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun idr_remove(&dev_priv->object_idr, mem->free);
180*4882a593Smuzhiyun list_del(&obj->owner_list);
181*4882a593Smuzhiyun if (drm_mm_node_allocated(&obj->mm_node))
182*4882a593Smuzhiyun drm_mm_remove_node(&obj->mm_node);
183*4882a593Smuzhiyun #if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE)
184*4882a593Smuzhiyun else
185*4882a593Smuzhiyun sis_free(obj->req.offset);
186*4882a593Smuzhiyun #endif
187*4882a593Smuzhiyun kfree(obj);
188*4882a593Smuzhiyun mutex_unlock(&dev->struct_mutex);
189*4882a593Smuzhiyun DRM_DEBUG("free = 0x%lx\n", mem->free);
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun return 0;
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun
sis_fb_alloc(struct drm_device * dev,void * data,struct drm_file * file_priv)194*4882a593Smuzhiyun static int sis_fb_alloc(struct drm_device *dev, void *data,
195*4882a593Smuzhiyun struct drm_file *file_priv)
196*4882a593Smuzhiyun {
197*4882a593Smuzhiyun return sis_drm_alloc(dev, file_priv, data, VIDEO_TYPE);
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun
sis_ioctl_agp_init(struct drm_device * dev,void * data,struct drm_file * file_priv)200*4882a593Smuzhiyun static int sis_ioctl_agp_init(struct drm_device *dev, void *data,
201*4882a593Smuzhiyun struct drm_file *file_priv)
202*4882a593Smuzhiyun {
203*4882a593Smuzhiyun drm_sis_private_t *dev_priv = dev->dev_private;
204*4882a593Smuzhiyun drm_sis_agp_t *agp = data;
205*4882a593Smuzhiyun dev_priv = dev->dev_private;
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun mutex_lock(&dev->struct_mutex);
208*4882a593Smuzhiyun drm_mm_init(&dev_priv->agp_mm, 0, agp->size >> SIS_MM_ALIGN_SHIFT);
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun dev_priv->agp_initialized = 1;
211*4882a593Smuzhiyun dev_priv->agp_offset = agp->offset;
212*4882a593Smuzhiyun mutex_unlock(&dev->struct_mutex);
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun DRM_DEBUG("offset = %lu, size = %lu\n", agp->offset, agp->size);
215*4882a593Smuzhiyun return 0;
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun
sis_ioctl_agp_alloc(struct drm_device * dev,void * data,struct drm_file * file_priv)218*4882a593Smuzhiyun static int sis_ioctl_agp_alloc(struct drm_device *dev, void *data,
219*4882a593Smuzhiyun struct drm_file *file_priv)
220*4882a593Smuzhiyun {
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun return sis_drm_alloc(dev, file_priv, data, AGP_TYPE);
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun
sis_reg_init(struct drm_device * dev)225*4882a593Smuzhiyun static drm_local_map_t *sis_reg_init(struct drm_device *dev)
226*4882a593Smuzhiyun {
227*4882a593Smuzhiyun struct drm_map_list *entry;
228*4882a593Smuzhiyun drm_local_map_t *map;
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun list_for_each_entry(entry, &dev->maplist, head) {
231*4882a593Smuzhiyun map = entry->map;
232*4882a593Smuzhiyun if (!map)
233*4882a593Smuzhiyun continue;
234*4882a593Smuzhiyun if (map->type == _DRM_REGISTERS)
235*4882a593Smuzhiyun return map;
236*4882a593Smuzhiyun }
237*4882a593Smuzhiyun return NULL;
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun
sis_idle(struct drm_device * dev)240*4882a593Smuzhiyun int sis_idle(struct drm_device *dev)
241*4882a593Smuzhiyun {
242*4882a593Smuzhiyun drm_sis_private_t *dev_priv = dev->dev_private;
243*4882a593Smuzhiyun uint32_t idle_reg;
244*4882a593Smuzhiyun unsigned long end;
245*4882a593Smuzhiyun int i;
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun if (dev_priv->idle_fault)
248*4882a593Smuzhiyun return 0;
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun if (dev_priv->mmio == NULL) {
251*4882a593Smuzhiyun dev_priv->mmio = sis_reg_init(dev);
252*4882a593Smuzhiyun if (dev_priv->mmio == NULL) {
253*4882a593Smuzhiyun DRM_ERROR("Could not find register map.\n");
254*4882a593Smuzhiyun return 0;
255*4882a593Smuzhiyun }
256*4882a593Smuzhiyun }
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun /*
259*4882a593Smuzhiyun * Implement a device switch here if needed
260*4882a593Smuzhiyun */
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun if (dev_priv->chipset != SIS_CHIP_315)
263*4882a593Smuzhiyun return 0;
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun /*
266*4882a593Smuzhiyun * Timeout after 3 seconds. We cannot use DRM_WAIT_ON here
267*4882a593Smuzhiyun * because its polling frequency is too low.
268*4882a593Smuzhiyun */
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun end = jiffies + (HZ * 3);
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun for (i = 0; i < 4; ++i) {
273*4882a593Smuzhiyun do {
274*4882a593Smuzhiyun idle_reg = SIS_READ(0x85cc);
275*4882a593Smuzhiyun } while (!time_after_eq(jiffies, end) &&
276*4882a593Smuzhiyun ((idle_reg & 0x80000000) != 0x80000000));
277*4882a593Smuzhiyun }
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun if (time_after_eq(jiffies, end)) {
280*4882a593Smuzhiyun DRM_ERROR("Graphics engine idle timeout. "
281*4882a593Smuzhiyun "Disabling idle check\n");
282*4882a593Smuzhiyun dev_priv->idle_fault = 1;
283*4882a593Smuzhiyun }
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun /*
286*4882a593Smuzhiyun * The caller never sees an error code. It gets trapped
287*4882a593Smuzhiyun * in libdrm.
288*4882a593Smuzhiyun */
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun return 0;
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun
sis_lastclose(struct drm_device * dev)294*4882a593Smuzhiyun void sis_lastclose(struct drm_device *dev)
295*4882a593Smuzhiyun {
296*4882a593Smuzhiyun drm_sis_private_t *dev_priv = dev->dev_private;
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun if (!dev_priv)
299*4882a593Smuzhiyun return;
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun mutex_lock(&dev->struct_mutex);
302*4882a593Smuzhiyun if (dev_priv->vram_initialized) {
303*4882a593Smuzhiyun drm_mm_takedown(&dev_priv->vram_mm);
304*4882a593Smuzhiyun dev_priv->vram_initialized = 0;
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun if (dev_priv->agp_initialized) {
307*4882a593Smuzhiyun drm_mm_takedown(&dev_priv->agp_mm);
308*4882a593Smuzhiyun dev_priv->agp_initialized = 0;
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun dev_priv->mmio = NULL;
311*4882a593Smuzhiyun mutex_unlock(&dev->struct_mutex);
312*4882a593Smuzhiyun }
313*4882a593Smuzhiyun
sis_reclaim_buffers_locked(struct drm_device * dev,struct drm_file * file)314*4882a593Smuzhiyun void sis_reclaim_buffers_locked(struct drm_device *dev,
315*4882a593Smuzhiyun struct drm_file *file)
316*4882a593Smuzhiyun {
317*4882a593Smuzhiyun struct sis_file_private *file_priv = file->driver_priv;
318*4882a593Smuzhiyun struct sis_memblock *entry, *next;
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun if (!(dev->master && file->master->lock.hw_lock))
321*4882a593Smuzhiyun return;
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun drm_legacy_idlelock_take(&file->master->lock);
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun mutex_lock(&dev->struct_mutex);
326*4882a593Smuzhiyun if (list_empty(&file_priv->obj_list)) {
327*4882a593Smuzhiyun mutex_unlock(&dev->struct_mutex);
328*4882a593Smuzhiyun drm_legacy_idlelock_release(&file->master->lock);
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun return;
331*4882a593Smuzhiyun }
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun sis_idle(dev);
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun list_for_each_entry_safe(entry, next, &file_priv->obj_list,
337*4882a593Smuzhiyun owner_list) {
338*4882a593Smuzhiyun list_del(&entry->owner_list);
339*4882a593Smuzhiyun if (drm_mm_node_allocated(&entry->mm_node))
340*4882a593Smuzhiyun drm_mm_remove_node(&entry->mm_node);
341*4882a593Smuzhiyun #if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE)
342*4882a593Smuzhiyun else
343*4882a593Smuzhiyun sis_free(entry->req.offset);
344*4882a593Smuzhiyun #endif
345*4882a593Smuzhiyun kfree(entry);
346*4882a593Smuzhiyun }
347*4882a593Smuzhiyun mutex_unlock(&dev->struct_mutex);
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun drm_legacy_idlelock_release(&file->master->lock);
350*4882a593Smuzhiyun
351*4882a593Smuzhiyun return;
352*4882a593Smuzhiyun }
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun const struct drm_ioctl_desc sis_ioctls[] = {
355*4882a593Smuzhiyun DRM_IOCTL_DEF_DRV(SIS_FB_ALLOC, sis_fb_alloc, DRM_AUTH),
356*4882a593Smuzhiyun DRM_IOCTL_DEF_DRV(SIS_FB_FREE, sis_drm_free, DRM_AUTH),
357*4882a593Smuzhiyun DRM_IOCTL_DEF_DRV(SIS_AGP_INIT, sis_ioctl_agp_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY),
358*4882a593Smuzhiyun DRM_IOCTL_DEF_DRV(SIS_AGP_ALLOC, sis_ioctl_agp_alloc, DRM_AUTH),
359*4882a593Smuzhiyun DRM_IOCTL_DEF_DRV(SIS_AGP_FREE, sis_drm_free, DRM_AUTH),
360*4882a593Smuzhiyun DRM_IOCTL_DEF_DRV(SIS_FB_INIT, sis_fb_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY),
361*4882a593Smuzhiyun };
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun int sis_max_ioctl = ARRAY_SIZE(sis_ioctls);
364